41#include "base/base_uses.f90"
52 PRIVATE :: cite_smearing
54 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'smearing_utils'
55 INTEGER,
PARAMETER,
PRIVATE :: BISECT_MAX_ITER = 400
56 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_ITER = 50
57 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_BACKTRACK = 20
58 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: mpmv_max_newton_step = 2.0_dp
67 REAL(kind=
dp),
INTENT(IN) :: fixed_mag_mom
79 INTEGER,
DIMENSION(2),
INTENT(IN) :: nelectron
80 REAL(kind=
dp),
INTENT(IN) :: fixed_mag_mom
81 REAL(kind=
dp),
DIMENSION(2) :: targets
83 REAL(kind=
dp) :: total
85 targets(:) = real(nelectron,
dp)
86 IF (fixed_mag_mom >= 0.0_dp)
THEN
88 targets(1) = 0.5_dp*(total + fixed_mag_mom)
89 targets(2) = 0.5_dp*(total - fixed_mag_mom)
97 SUBROUTINE cite_smearing(method)
98 INTEGER,
INTENT(IN) :: method
114 END SUBROUTINE cite_smearing
140 SUBROUTINE smearocc(f, N, kTS, e, mu, sigma, maxocc, method, estate, festate)
142 REAL(kind=
dp),
INTENT(OUT) :: f(:), n, kts
143 REAL(kind=
dp),
INTENT(IN) :: e(:), mu, sigma, maxocc
144 INTEGER,
INTENT(IN) :: method
145 INTEGER,
INTENT(IN),
OPTIONAL :: estate
146 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
149 REAL(kind=
dp) :: arg, expu2, expx2, occupation, term1, &
150 term2, tmp, tmp2, tmp3, tmp4, tmplog, &
157 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
158 IF (i == estate)
THEN
170 arg = -(e(i) - mu)/sigma
176 term1 = tmp2*(arg + tmplog)
179 arg = (e(i) - mu)/sigma
186 term2 = tmp3*(arg + tmplog)
188 f(i) = occupation*tmp2
189 kts = kts + sigma*occupation*(term1 + term2)
192 x = (e(i) - mu)/sigma
194 f(i) = occupation*0.5_dp*erfc(x)
195 kts = kts - (sigma/(2.0_dp*
rootpi))*occupation*expx2
198 x = (e(i) - mu)/sigma
200 f(i) = occupation*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
201 kts = kts + (sigma/(4.0_dp*
rootpi))*occupation*(2.0_dp*x*x - 1.0_dp)*expx2
204 x = (e(i) - mu)/sigma
207 f(i) = occupation*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
208 kts = kts - (sigma/(
sqrt2*
rootpi))*occupation*u*expu2
211 cpabort(
"SmearOcc: unknown smearing method")
235 SUBROUTINE smear2(f, nel, kTS, e, mu, wk, sigma, maxocc, method)
237 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
238 REAL(kind=
dp),
INTENT(OUT) :: nel, kts
239 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
240 REAL(kind=
dp),
INTENT(IN) :: mu
241 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
242 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
243 INTEGER,
INTENT(IN) :: method
245 INTEGER :: ik, is, nkp, nmo
246 REAL(kind=
dp) :: arg, expu2, expx2, term1, term2, tmp, &
247 tmp2, tmp3, tmp4, tmplog, u, x
253 IF (sigma > 1.0e-14_dp)
THEN
258 IF (e(is, ik) > mu)
THEN
259 arg = -(e(is, ik) - mu)/sigma
265 term1 = tmp2*(arg + tmplog)
268 arg = (e(is, ik) - mu)/sigma
275 term2 = tmp3*(arg + tmplog)
277 f(is, ik) = maxocc*tmp2
278 kts = kts + sigma*maxocc*(term1 + term2)*wk(ik)
281 x = (e(is, ik) - mu)/sigma
283 f(is, ik) = maxocc*0.5_dp*erfc(x)
284 kts = kts - (sigma/(2.0_dp*
rootpi))*maxocc*expx2*wk(ik)
287 x = (e(is, ik) - mu)/sigma
289 f(is, ik) = maxocc*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
290 kts = kts + (sigma/(4.0_dp*
rootpi))*maxocc*(2.0_dp*x*x - 1.0_dp)*expx2*wk(ik)
293 x = (e(is, ik) - mu)/sigma
296 f(is, ik) = maxocc*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
297 kts = kts - (sigma/(
sqrt2*
rootpi))*maxocc*u*expu2*wk(ik)
300 cpabort(
"Smear2: unknown smearing method")
308 IF (e(is, ik) <= mu)
THEN
322 END SUBROUTINE smear2
347 SUBROUTINE smearfixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
349 REAL(kind=
dp),
INTENT(OUT) :: f(:), mu, kts
350 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
351 INTEGER,
INTENT(IN) :: method
352 INTEGER,
INTENT(IN),
OPTIONAL :: estate
353 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
355 INTEGER :: iback, iter, my_estate, nstate
356 REAL(kind=
dp) :: gsum, mu_best, mu_max, mu_min, mu_now, mu_trial, my_festate, n_now, n_tmp, &
357 n_trial, res_best, res_now, res_trial, step, step_try
358 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
360 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
364 my_estate = nint(maxocc)
365 my_festate = my_estate
370 CALL cite_smearing(method)
384 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
386 mu_min = mu_min - sigma
396 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
398 mu_max = mu_max + sigma
402 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
404 mu_now = (mu_max + mu_min)/2.0_dp
411 IF (iter > bisect_max_iter)
EXIT
413 mu = (mu_max + mu_min)/2.0_dp
420 ALLOCATE (gvec(nstate))
421 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
422 res_best = abs(n_now - n)
424 DO iter = 1, newton_max_iter
425 res_now = abs(n_now - n)
426 IF (res_now < n*1.0e-12_dp)
EXIT
428 gvec, f, e, mu, sigma, maxocc, nstate, method, my_estate, my_festate)
430 IF (abs(gsum) < epsilon(gsum))
EXIT
432 step = (n - n_now)/gsum
433 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
435 DO iback = 1, newton_max_backtrack
436 mu_trial = mu + step_try
437 CALL smearocc(f, n_trial, kts, e, mu_trial, sigma, maxocc, method, &
438 my_estate, my_festate)
439 res_trial = abs(n_trial - n)
440 IF (res_trial < res_now)
THEN
443 IF (res_trial < res_best)
THEN
449 step_try = 0.5_dp*step_try
451 IF (iback > newton_max_backtrack)
EXIT
457 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
458 IF (abs(n_now - n) >= n*1.0e-12_dp)
THEN
459 cpwarn(
"SmearFixed: MP/MV smearing did not reach the requested electron count")
468 CALL smearocc(f, n_tmp, kts, e, mu_min, sigma, maxocc, method, my_estate, my_festate)
471 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
473 mu_min = mu_min - sigma
480 CALL smearocc(f, n_tmp, kts, e, mu_max, sigma, maxocc, method, my_estate, my_festate)
483 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
485 mu_max = mu_max + sigma
489 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
491 mu_now = (mu_max + mu_min)/2.0_dp
492 CALL smearocc(f, n_now, kts, e, mu_now, sigma, maxocc, method, my_estate, my_festate)
498 IF (iter > bisect_max_iter)
THEN
499 cpwarn(
"SmearFixed: maximum bisection iterations reached")
504 mu = (mu_max + mu_min)/2.0_dp
505 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
531 SUBROUTINE smearkp(f, mu, kTS, e, nel, wk, sigma, maxocc, method)
533 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
534 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
535 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
536 REAL(kind=
dp),
INTENT(IN) :: nel
537 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
538 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
539 INTEGER,
INTENT(IN) :: method
541 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
543 INTEGER :: bisect_method, iback, ik, is, iter, nkp, &
545 REAL(kind=
dp) :: de, dndmu, expu2, expx2, mu_best, &
546 mu_max, mu_min, n_now, n_trial, &
547 res_best, res_now, res_trial, step, &
553 CALL cite_smearing(method)
560 bisect_method = method
564 SELECT CASE (bisect_method)
566 de = sigma*log((1.0_dp - epsocc)/epsocc)
573 mu_min = minval(e) - de
574 mu_max = maxval(e) + de
576 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
578 mu = (mu_max + mu_min)/2.0_dp
579 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, bisect_method)
581 IF (abs(n_now - nel) < nel*epsocc)
EXIT
583 IF (n_now <= nel)
THEN
589 IF (iter > bisect_max_iter)
THEN
590 cpwarn(
"Smearkp: maximum bisection iterations reached")
594 mu = (mu_max + mu_min)/2.0_dp
601 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
602 res_best = abs(n_now - nel)
604 DO iter = 1, newton_max_iter
605 res_now = abs(n_now - nel)
606 IF (res_now < nel*epsocc)
EXIT
612 x = (e(is, ik) - mu)/sigma
616 dndmu = dndmu + maxocc*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
620 dndmu = dndmu + maxocc*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
625 IF (abs(dndmu) < epsilon(dndmu))
EXIT
626 step = (nel - n_now)/dndmu
627 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
629 DO iback = 1, newton_max_backtrack
630 CALL smear2(f, n_trial, kts, e, mu + step_try, wk, sigma, maxocc, method)
631 res_trial = abs(n_trial - nel)
632 IF (res_trial < res_now)
THEN
635 IF (res_trial < res_best)
THEN
641 step_try = 0.5_dp*step_try
643 IF (iback > newton_max_backtrack)
EXIT
649 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
652 IF (abs(n_now - nel) >= nel*epsocc)
THEN
653 cpwarn(
"Smearkp: MP/MV smearing did not reach the requested electron count")
675 SUBROUTINE smearkp2(f, mu, kTS, e, nel, wk, sigma, method)
677 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(OUT) :: f
678 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
679 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: e
680 REAL(kind=
dp),
INTENT(IN) :: nel
681 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
682 REAL(kind=
dp),
INTENT(IN) :: sigma
683 INTEGER,
INTENT(IN) :: method
685 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
687 INTEGER :: bisect_method, iback, ik, is, ispin, &
689 REAL(kind=
dp) :: de, dndmu, expu2, expx2, ktsa, ktsb, mu_best, mu_max, mu_min, n_now, &
690 n_trial, na, nb, res_best, res_now, res_trial, step, step_try, u, x
692 cpassert(
SIZE(f, 3) == 2 .AND.
SIZE(e, 3) == 2)
697 CALL cite_smearing(method)
703 bisect_method = method
706 SELECT CASE (bisect_method)
708 de = sigma*log((1.0_dp - epsocc)/epsocc)
715 mu_min = minval(e) - de
716 mu_max = maxval(e) + de
718 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
720 mu = (mu_max + mu_min)/2.0_dp
721 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, bisect_method)
722 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, bisect_method)
725 IF (abs(n_now - nel) < nel*epsocc)
EXIT
727 IF (n_now <= nel)
THEN
733 IF (iter > bisect_max_iter)
THEN
734 cpwarn(
"Smearkp2: maximum bisection iterations reached")
738 mu = (mu_max + mu_min)/2.0_dp
745 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
746 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
748 res_best = abs(n_now - nel)
750 DO iter = 1, newton_max_iter
751 res_now = abs(n_now - nel)
752 IF (res_now < nel*epsocc)
EXIT
759 x = (e(is, ik, ispin) - mu)/sigma
763 dndmu = dndmu + (3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
767 dndmu = dndmu + (2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
773 IF (abs(dndmu) < epsilon(dndmu))
EXIT
774 step = (nel - n_now)/dndmu
775 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
777 DO iback = 1, newton_max_backtrack
778 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu + step_try, wk, sigma, 1.0_dp, method)
779 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu + step_try, wk, sigma, 1.0_dp, method)
781 res_trial = abs(n_trial - nel)
782 IF (res_trial < res_now)
THEN
785 IF (res_trial < res_best)
THEN
791 step_try = 0.5_dp*step_try
793 IF (iback > newton_max_backtrack)
EXIT
799 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
800 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
805 IF (abs(n_now - nel) >= nel*epsocc)
THEN
806 cpwarn(
"Smearkp2: MP/MV smearing did not reach the requested electron count")
840 gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
842 REAL(kind=
dp),
INTENT(OUT) :: gvec(:)
843 REAL(kind=
dp),
INTENT(IN) :: f(:), e(:), mu, sigma, maxocc
844 INTEGER,
INTENT(IN) :: nstate, method
845 INTEGER,
INTENT(IN),
OPTIONAL :: estate
846 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
849 REAL(kind=
dp) :: expu2, expx2, fi_norm, occ_i, u, x
852 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
853 IF (i == estate)
THEN
862 IF (occ_i < epsilon(occ_i))
THEN
867 x = (e(i) - mu)/sigma
872 gvec(i) = occ_i*fi_norm*(1.0_dp - fi_norm)/sigma
876 gvec(i) = occ_i/(sigma*
rootpi)*expx2
880 gvec(i) = occ_i*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2
885 gvec(i) = occ_i*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2
921 SUBROUTINE smearfixedderiv(dfde, f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
923 REAL(kind=
dp),
INTENT(OUT) :: dfde(:, :), f(:), mu, kts
924 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
925 INTEGER,
INTENT(IN) :: method
926 INTEGER,
INTENT(IN),
OPTIONAL :: estate
927 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
929 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDeriv'
931 INTEGER :: handle, i, j, nstate
932 REAL(kind=
dp) :: gsum
933 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
935 CALL timeset(routinen, handle)
938 CALL smearfixed(f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
942 ALLOCATE (gvec(nstate))
947 IF (abs(gsum) > epsilon(gsum))
THEN
950 dfde(i, j) = gvec(i)*gvec(j)/gsum
952 dfde(j, j) = dfde(j, j) - gvec(j)
959 CALL timestop(handle)
994 SUBROUTINE smearfixedderivmv(RESULT, f, mu, kTS, e, N_el, sigma, maxocc, method, v, estate, festate)
996 REAL(kind=
dp),
INTENT(OUT) :: result(:), f(:), mu, kts
997 REAL(kind=
dp),
INTENT(IN) :: e(:), n_el, sigma, maxocc
998 INTEGER,
INTENT(IN) :: method
999 REAL(kind=
dp),
INTENT(IN) :: v(:)
1000 INTEGER,
INTENT(IN),
OPTIONAL :: estate
1001 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
1003 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDerivMV'
1005 INTEGER :: handle, i, nstate
1006 REAL(kind=
dp) :: gdotv, gsum
1007 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
1009 CALL timeset(routinen, handle)
1012 CALL smearfixed(f, mu, kts, e, n_el, sigma, maxocc, method, estate, festate)
1016 ALLOCATE (gvec(nstate))
1021 IF (abs(gsum) > epsilon(gsum))
THEN
1024 gdotv = gdotv + gvec(i)*v(i)
1027 result(i) = gvec(i)*(gdotv/gsum - v(i))
1034 CALL timestop(handle)
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public fuho1983
integer, save, public mermin1965
integer, save, public marzari1999
integer, save, public dossantos2023
integer, save, public methfesselpaxton1989
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public sqrthalf
real(kind=dp), parameter, public rootpi
real(kind=dp), parameter, public sqrt2
Unified smearing module supporting four methods: smear_fermi_dirac — Fermi-Dirac distribution smear_g...
subroutine, public smearkp(f, mu, kts, e, nel, wk, sigma, maxocc, method)
Bisection search for mu given a target electron count (k-point case, single spin channel or spin-dege...
subroutine, public smearkp2(f, mu, kts, e, nel, wk, sigma, method)
Bisection search for mu (k-point, spin-polarised with a shared chemical potential across both spin ch...
subroutine, public smearfixedderiv(dfde, f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
Analytical Jacobian df_i/de_j for any smearing method under the electron-number constraint sum(f) = N...
subroutine, public smearocc(f, n, kts, e, mu, sigma, maxocc, method, estate, festate)
Returns occupations and smearing correction for a given set of energies and chemical potential,...
pure logical function, public smearing_separate_spin(fixed_mag_mom)
Whether a smearing constraint fixes the separate spin populations.
pure real(kind=dp) function, dimension(2), public smearing_spin_targets(nelectron, fixed_mag_mom)
Resolve real-valued spin targets without rounding a prescribed moment.
subroutine, public smearing_response_weight(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
Computes the smearing weight vector g_i = -df_i/de_i with mu held fixed.
subroutine, public smearfixed(f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
Bisection search for the chemical potential mu such that the total electron count equals N,...
subroutine, public smearfixedderivmv(result, f, mu, kts, e, n_el, sigma, maxocc, method, v, estate, festate)
Apply TRANSPOSE(df/de) to a vector WITHOUT forming the full N x N Jacobian. O(N) time and O(N) memory...