41#include "base/base_uses.f90"
51 PRIVATE :: cite_smearing
53 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'smearing_utils'
54 INTEGER,
PARAMETER,
PRIVATE :: BISECT_MAX_ITER = 400
55 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_ITER = 50
56 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_BACKTRACK = 20
57 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: mpmv_max_newton_step = 2.0_dp
64 SUBROUTINE cite_smearing(method)
65 INTEGER,
INTENT(IN) :: method
81 END SUBROUTINE cite_smearing
107 SUBROUTINE smearocc(f, N, kTS, e, mu, sigma, maxocc, method, estate, festate)
109 REAL(kind=
dp),
INTENT(OUT) :: f(:), n, kts
110 REAL(kind=
dp),
INTENT(IN) :: e(:), mu, sigma, maxocc
111 INTEGER,
INTENT(IN) :: method
112 INTEGER,
INTENT(IN),
OPTIONAL :: estate
113 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
116 REAL(kind=
dp) :: arg, expu2, expx2, occupation, term1, &
117 term2, tmp, tmp2, tmp3, tmp4, tmplog, &
124 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
125 IF (i == estate)
THEN
137 arg = -(e(i) - mu)/sigma
143 term1 = tmp2*(arg + tmplog)
146 arg = (e(i) - mu)/sigma
153 term2 = tmp3*(arg + tmplog)
155 f(i) = occupation*tmp2
156 kts = kts + sigma*occupation*(term1 + term2)
159 x = (e(i) - mu)/sigma
161 f(i) = occupation*0.5_dp*erfc(x)
162 kts = kts - (sigma/(2.0_dp*
rootpi))*occupation*expx2
165 x = (e(i) - mu)/sigma
167 f(i) = occupation*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
168 kts = kts + (sigma/(4.0_dp*
rootpi))*occupation*(2.0_dp*x*x - 1.0_dp)*expx2
171 x = (e(i) - mu)/sigma
174 f(i) = occupation*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
175 kts = kts - (sigma/(
sqrt2*
rootpi))*occupation*u*expu2
178 cpabort(
"SmearOcc: unknown smearing method")
202 SUBROUTINE smear2(f, nel, kTS, e, mu, wk, sigma, maxocc, method)
204 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
205 REAL(kind=
dp),
INTENT(OUT) :: nel, kts
206 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
207 REAL(kind=
dp),
INTENT(IN) :: mu
208 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
209 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
210 INTEGER,
INTENT(IN) :: method
212 INTEGER :: ik, is, nkp, nmo
213 REAL(kind=
dp) :: arg, expu2, expx2, term1, term2, tmp, &
214 tmp2, tmp3, tmp4, tmplog, u, x
220 IF (sigma > 1.0e-14_dp)
THEN
225 IF (e(is, ik) > mu)
THEN
226 arg = -(e(is, ik) - mu)/sigma
232 term1 = tmp2*(arg + tmplog)
235 arg = (e(is, ik) - mu)/sigma
242 term2 = tmp3*(arg + tmplog)
244 f(is, ik) = maxocc*tmp2
245 kts = kts + sigma*maxocc*(term1 + term2)*wk(ik)
248 x = (e(is, ik) - mu)/sigma
250 f(is, ik) = maxocc*0.5_dp*erfc(x)
251 kts = kts - (sigma/(2.0_dp*
rootpi))*maxocc*expx2*wk(ik)
254 x = (e(is, ik) - mu)/sigma
256 f(is, ik) = maxocc*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
257 kts = kts + (sigma/(4.0_dp*
rootpi))*maxocc*(2.0_dp*x*x - 1.0_dp)*expx2*wk(ik)
260 x = (e(is, ik) - mu)/sigma
263 f(is, ik) = maxocc*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
264 kts = kts - (sigma/(
sqrt2*
rootpi))*maxocc*u*expu2*wk(ik)
267 cpabort(
"Smear2: unknown smearing method")
275 IF (e(is, ik) <= mu)
THEN
289 END SUBROUTINE smear2
314 SUBROUTINE smearfixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
316 REAL(kind=
dp),
INTENT(OUT) :: f(:), mu, kts
317 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
318 INTEGER,
INTENT(IN) :: method
319 INTEGER,
INTENT(IN),
OPTIONAL :: estate
320 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
322 INTEGER :: iback, iter, my_estate, nstate
323 REAL(kind=
dp) :: gsum, mu_best, mu_max, mu_min, mu_now, mu_trial, my_festate, n_now, n_tmp, &
324 n_trial, res_best, res_now, res_trial, step, step_try
325 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
327 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
331 my_estate = nint(maxocc)
332 my_festate = my_estate
337 CALL cite_smearing(method)
351 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
353 mu_min = mu_min - sigma
363 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
365 mu_max = mu_max + sigma
369 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
371 mu_now = (mu_max + mu_min)/2.0_dp
378 IF (iter > bisect_max_iter)
EXIT
380 mu = (mu_max + mu_min)/2.0_dp
387 ALLOCATE (gvec(nstate))
388 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
389 res_best = abs(n_now - n)
391 DO iter = 1, newton_max_iter
392 res_now = abs(n_now - n)
393 IF (res_now < n*1.0e-12_dp)
EXIT
395 gvec, f, e, mu, sigma, maxocc, nstate, method, my_estate, my_festate)
397 IF (abs(gsum) < epsilon(gsum))
EXIT
399 step = (n - n_now)/gsum
400 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
402 DO iback = 1, newton_max_backtrack
403 mu_trial = mu + step_try
404 CALL smearocc(f, n_trial, kts, e, mu_trial, sigma, maxocc, method, &
405 my_estate, my_festate)
406 res_trial = abs(n_trial - n)
407 IF (res_trial < res_now)
THEN
410 IF (res_trial < res_best)
THEN
416 step_try = 0.5_dp*step_try
418 IF (iback > newton_max_backtrack)
EXIT
424 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
425 IF (abs(n_now - n) >= n*1.0e-12_dp)
THEN
426 cpwarn(
"SmearFixed: MP/MV smearing did not reach the requested electron count")
435 CALL smearocc(f, n_tmp, kts, e, mu_min, sigma, maxocc, method, my_estate, my_festate)
438 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
440 mu_min = mu_min - sigma
447 CALL smearocc(f, n_tmp, kts, e, mu_max, sigma, maxocc, method, my_estate, my_festate)
450 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
452 mu_max = mu_max + sigma
456 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
458 mu_now = (mu_max + mu_min)/2.0_dp
459 CALL smearocc(f, n_now, kts, e, mu_now, sigma, maxocc, method, my_estate, my_festate)
465 IF (iter > bisect_max_iter)
THEN
466 cpwarn(
"SmearFixed: maximum bisection iterations reached")
471 mu = (mu_max + mu_min)/2.0_dp
472 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
498 SUBROUTINE smearkp(f, mu, kTS, e, nel, wk, sigma, maxocc, method)
500 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
501 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
502 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
503 REAL(kind=
dp),
INTENT(IN) :: nel
504 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
505 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
506 INTEGER,
INTENT(IN) :: method
508 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
510 INTEGER :: bisect_method, iback, ik, is, iter, nkp, &
512 REAL(kind=
dp) :: de, dndmu, expu2, expx2, mu_best, &
513 mu_max, mu_min, n_now, n_trial, &
514 res_best, res_now, res_trial, step, &
520 CALL cite_smearing(method)
527 bisect_method = method
531 SELECT CASE (bisect_method)
533 de = sigma*log((1.0_dp - epsocc)/epsocc)
540 mu_min = minval(e) - de
541 mu_max = maxval(e) + de
543 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
545 mu = (mu_max + mu_min)/2.0_dp
546 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, bisect_method)
548 IF (abs(n_now - nel) < nel*epsocc)
EXIT
550 IF (n_now <= nel)
THEN
556 IF (iter > bisect_max_iter)
THEN
557 cpwarn(
"Smearkp: maximum bisection iterations reached")
561 mu = (mu_max + mu_min)/2.0_dp
568 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
569 res_best = abs(n_now - nel)
571 DO iter = 1, newton_max_iter
572 res_now = abs(n_now - nel)
573 IF (res_now < nel*epsocc)
EXIT
579 x = (e(is, ik) - mu)/sigma
583 dndmu = dndmu + maxocc*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
587 dndmu = dndmu + maxocc*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
592 IF (abs(dndmu) < epsilon(dndmu))
EXIT
593 step = (nel - n_now)/dndmu
594 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
596 DO iback = 1, newton_max_backtrack
597 CALL smear2(f, n_trial, kts, e, mu + step_try, wk, sigma, maxocc, method)
598 res_trial = abs(n_trial - nel)
599 IF (res_trial < res_now)
THEN
602 IF (res_trial < res_best)
THEN
608 step_try = 0.5_dp*step_try
610 IF (iback > newton_max_backtrack)
EXIT
616 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
619 IF (abs(n_now - nel) >= nel*epsocc)
THEN
620 cpwarn(
"Smearkp: MP/MV smearing did not reach the requested electron count")
642 SUBROUTINE smearkp2(f, mu, kTS, e, nel, wk, sigma, method)
644 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(OUT) :: f
645 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
646 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: e
647 REAL(kind=
dp),
INTENT(IN) :: nel
648 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
649 REAL(kind=
dp),
INTENT(IN) :: sigma
650 INTEGER,
INTENT(IN) :: method
652 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
654 INTEGER :: bisect_method, iback, ik, is, ispin, &
656 REAL(kind=
dp) :: de, dndmu, expu2, expx2, ktsa, ktsb, mu_best, mu_max, mu_min, n_now, &
657 n_trial, na, nb, res_best, res_now, res_trial, step, step_try, u, x
659 cpassert(
SIZE(f, 3) == 2 .AND.
SIZE(e, 3) == 2)
664 CALL cite_smearing(method)
670 bisect_method = method
673 SELECT CASE (bisect_method)
675 de = sigma*log((1.0_dp - epsocc)/epsocc)
682 mu_min = minval(e) - de
683 mu_max = maxval(e) + de
685 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
687 mu = (mu_max + mu_min)/2.0_dp
688 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, bisect_method)
689 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, bisect_method)
692 IF (abs(n_now - nel) < nel*epsocc)
EXIT
694 IF (n_now <= nel)
THEN
700 IF (iter > bisect_max_iter)
THEN
701 cpwarn(
"Smearkp2: maximum bisection iterations reached")
705 mu = (mu_max + mu_min)/2.0_dp
712 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
713 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
715 res_best = abs(n_now - nel)
717 DO iter = 1, newton_max_iter
718 res_now = abs(n_now - nel)
719 IF (res_now < nel*epsocc)
EXIT
726 x = (e(is, ik, ispin) - mu)/sigma
730 dndmu = dndmu + (3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
734 dndmu = dndmu + (2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
740 IF (abs(dndmu) < epsilon(dndmu))
EXIT
741 step = (nel - n_now)/dndmu
742 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
744 DO iback = 1, newton_max_backtrack
745 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu + step_try, wk, sigma, 1.0_dp, method)
746 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu + step_try, wk, sigma, 1.0_dp, method)
748 res_trial = abs(n_trial - nel)
749 IF (res_trial < res_now)
THEN
752 IF (res_trial < res_best)
THEN
758 step_try = 0.5_dp*step_try
760 IF (iback > newton_max_backtrack)
EXIT
766 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
767 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
772 IF (abs(n_now - nel) >= nel*epsocc)
THEN
773 cpwarn(
"Smearkp2: MP/MV smearing did not reach the requested electron count")
807 gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
809 REAL(kind=
dp),
INTENT(OUT) :: gvec(:)
810 REAL(kind=
dp),
INTENT(IN) :: f(:), e(:), mu, sigma, maxocc
811 INTEGER,
INTENT(IN) :: nstate, method
812 INTEGER,
INTENT(IN),
OPTIONAL :: estate
813 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
816 REAL(kind=
dp) :: expu2, expx2, fi_norm, occ_i, u, x
819 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
820 IF (i == estate)
THEN
829 IF (occ_i < epsilon(occ_i))
THEN
834 x = (e(i) - mu)/sigma
839 gvec(i) = occ_i*fi_norm*(1.0_dp - fi_norm)/sigma
843 gvec(i) = occ_i/(sigma*
rootpi)*expx2
847 gvec(i) = occ_i*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2
852 gvec(i) = occ_i*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2
888 SUBROUTINE smearfixedderiv(dfde, f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
890 REAL(kind=
dp),
INTENT(OUT) :: dfde(:, :), f(:), mu, kts
891 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
892 INTEGER,
INTENT(IN) :: method
893 INTEGER,
INTENT(IN),
OPTIONAL :: estate
894 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
896 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDeriv'
898 INTEGER :: handle, i, j, nstate
899 REAL(kind=
dp) :: gsum
900 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
902 CALL timeset(routinen, handle)
905 CALL smearfixed(f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
909 ALLOCATE (gvec(nstate))
914 IF (abs(gsum) > epsilon(gsum))
THEN
917 dfde(i, j) = gvec(i)*gvec(j)/gsum
919 dfde(j, j) = dfde(j, j) - gvec(j)
926 CALL timestop(handle)
961 SUBROUTINE smearfixedderivmv(RESULT, f, mu, kTS, e, N_el, sigma, maxocc, method, v, estate, festate)
963 REAL(kind=
dp),
INTENT(OUT) :: result(:), f(:), mu, kts
964 REAL(kind=
dp),
INTENT(IN) :: e(:), n_el, sigma, maxocc
965 INTEGER,
INTENT(IN) :: method
966 REAL(kind=
dp),
INTENT(IN) :: v(:)
967 INTEGER,
INTENT(IN),
OPTIONAL :: estate
968 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
970 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDerivMV'
972 INTEGER :: handle, i, nstate
973 REAL(kind=
dp) :: gdotv, gsum
974 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
976 CALL timeset(routinen, handle)
979 CALL smearfixed(f, mu, kts, e, n_el, sigma, maxocc, method, estate, festate)
983 ALLOCATE (gvec(nstate))
988 IF (abs(gsum) > epsilon(gsum))
THEN
991 gdotv = gdotv + gvec(i)*v(i)
994 result(i) = gvec(i)*(gdotv/gsum - v(i))
1001 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,...
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...