41#include "base/base_uses.f90"
50 PRIVATE :: cite_smearing
52 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'smearing_utils'
53 INTEGER,
PARAMETER,
PRIVATE :: BISECT_MAX_ITER = 400
54 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_ITER = 50
55 INTEGER,
PARAMETER,
PRIVATE :: NEWTON_MAX_BACKTRACK = 20
56 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: mpmv_max_newton_step = 2.0_dp
63 SUBROUTINE cite_smearing(method)
64 INTEGER,
INTENT(IN) :: method
80 END SUBROUTINE cite_smearing
106 SUBROUTINE smearocc(f, N, kTS, e, mu, sigma, maxocc, method, estate, festate)
108 REAL(kind=
dp),
INTENT(OUT) :: f(:), n, kts
109 REAL(kind=
dp),
INTENT(IN) :: e(:), mu, sigma, maxocc
110 INTEGER,
INTENT(IN) :: method
111 INTEGER,
INTENT(IN),
OPTIONAL :: estate
112 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
115 REAL(kind=
dp) :: arg, expu2, expx2, occupation, term1, &
116 term2, tmp, tmp2, tmp3, tmp4, tmplog, &
123 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
124 IF (i == estate)
THEN
136 arg = -(e(i) - mu)/sigma
142 term1 = tmp2*(arg + tmplog)
145 arg = (e(i) - mu)/sigma
152 term2 = tmp3*(arg + tmplog)
154 f(i) = occupation*tmp2
155 kts = kts + sigma*occupation*(term1 + term2)
158 x = (e(i) - mu)/sigma
160 f(i) = occupation*0.5_dp*erfc(x)
161 kts = kts - (sigma/(2.0_dp*
rootpi))*occupation*expx2
164 x = (e(i) - mu)/sigma
166 f(i) = occupation*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
167 kts = kts + (sigma/(4.0_dp*
rootpi))*occupation*(2.0_dp*x*x - 1.0_dp)*expx2
170 x = (e(i) - mu)/sigma
173 f(i) = occupation*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
174 kts = kts - (sigma/(
sqrt2*
rootpi))*occupation*u*expu2
177 cpabort(
"SmearOcc: unknown smearing method")
201 SUBROUTINE smear2(f, nel, kTS, e, mu, wk, sigma, maxocc, method)
203 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
204 REAL(kind=
dp),
INTENT(OUT) :: nel, kts
205 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
206 REAL(kind=
dp),
INTENT(IN) :: mu
207 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
208 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
209 INTEGER,
INTENT(IN) :: method
211 INTEGER :: ik, is, nkp, nmo
212 REAL(kind=
dp) :: arg, expu2, expx2, term1, term2, tmp, &
213 tmp2, tmp3, tmp4, tmplog, u, x
219 IF (sigma > 1.0e-14_dp)
THEN
224 IF (e(is, ik) > mu)
THEN
225 arg = -(e(is, ik) - mu)/sigma
231 term1 = tmp2*(arg + tmplog)
234 arg = (e(is, ik) - mu)/sigma
241 term2 = tmp3*(arg + tmplog)
243 f(is, ik) = maxocc*tmp2
244 kts = kts + sigma*maxocc*(term1 + term2)*wk(ik)
247 x = (e(is, ik) - mu)/sigma
249 f(is, ik) = maxocc*0.5_dp*erfc(x)
250 kts = kts - (sigma/(2.0_dp*
rootpi))*maxocc*expx2*wk(ik)
253 x = (e(is, ik) - mu)/sigma
255 f(is, ik) = maxocc*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
256 kts = kts + (sigma/(4.0_dp*
rootpi))*maxocc*(2.0_dp*x*x - 1.0_dp)*expx2*wk(ik)
259 x = (e(is, ik) - mu)/sigma
262 f(is, ik) = maxocc*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
263 kts = kts - (sigma/(
sqrt2*
rootpi))*maxocc*u*expu2*wk(ik)
266 cpabort(
"Smear2: unknown smearing method")
274 IF (e(is, ik) <= mu)
THEN
288 END SUBROUTINE smear2
313 SUBROUTINE smearfixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
315 REAL(kind=
dp),
INTENT(OUT) :: f(:), mu, kts
316 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
317 INTEGER,
INTENT(IN) :: method
318 INTEGER,
INTENT(IN),
OPTIONAL :: estate
319 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
321 INTEGER :: iback, iter, my_estate, nstate
322 REAL(kind=
dp) :: gsum, mu_best, mu_max, mu_min, mu_now, mu_trial, my_festate, n_now, n_tmp, &
323 n_trial, res_best, res_now, res_trial, step, step_try
324 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
326 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
330 my_estate = nint(maxocc)
331 my_festate = my_estate
336 CALL cite_smearing(method)
350 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
352 mu_min = mu_min - sigma
362 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
364 mu_max = mu_max + sigma
368 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
370 mu_now = (mu_max + mu_min)/2.0_dp
377 IF (iter > bisect_max_iter)
EXIT
379 mu = (mu_max + mu_min)/2.0_dp
386 ALLOCATE (gvec(nstate))
387 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
388 res_best = abs(n_now - n)
390 DO iter = 1, newton_max_iter
391 res_now = abs(n_now - n)
392 IF (res_now < n*1.0e-12_dp)
EXIT
393 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, my_estate, my_festate)
395 IF (abs(gsum) < epsilon(gsum))
EXIT
397 step = (n - n_now)/gsum
398 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
400 DO iback = 1, newton_max_backtrack
401 mu_trial = mu + step_try
402 CALL smearocc(f, n_trial, kts, e, mu_trial, sigma, maxocc, method, &
403 my_estate, my_festate)
404 res_trial = abs(n_trial - n)
405 IF (res_trial < res_now)
THEN
408 IF (res_trial < res_best)
THEN
414 step_try = 0.5_dp*step_try
416 IF (iback > newton_max_backtrack)
EXIT
422 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
423 IF (abs(n_now - n) >= n*1.0e-12_dp)
THEN
424 cpwarn(
"SmearFixed: MP/MV smearing did not reach the requested electron count")
433 CALL smearocc(f, n_tmp, kts, e, mu_min, sigma, maxocc, method, my_estate, my_festate)
436 cpabort(
"SmearFixed: failed to bracket lower chemical potential")
438 mu_min = mu_min - sigma
445 CALL smearocc(f, n_tmp, kts, e, mu_max, sigma, maxocc, method, my_estate, my_festate)
448 cpabort(
"SmearFixed: failed to bracket upper chemical potential")
450 mu_max = mu_max + sigma
454 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
456 mu_now = (mu_max + mu_min)/2.0_dp
457 CALL smearocc(f, n_now, kts, e, mu_now, sigma, maxocc, method, my_estate, my_festate)
463 IF (iter > bisect_max_iter)
THEN
464 cpwarn(
"SmearFixed: maximum bisection iterations reached")
469 mu = (mu_max + mu_min)/2.0_dp
470 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
496 SUBROUTINE smearkp(f, mu, kTS, e, nel, wk, sigma, maxocc, method)
498 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
499 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
500 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
501 REAL(kind=
dp),
INTENT(IN) :: nel
502 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
503 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
504 INTEGER,
INTENT(IN) :: method
506 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
508 INTEGER :: bisect_method, iback, ik, is, iter, nkp, &
510 REAL(kind=
dp) :: de, dndmu, expu2, expx2, mu_best, &
511 mu_max, mu_min, n_now, n_trial, &
512 res_best, res_now, res_trial, step, &
518 CALL cite_smearing(method)
525 bisect_method = method
529 SELECT CASE (bisect_method)
531 de = sigma*log((1.0_dp - epsocc)/epsocc)
538 mu_min = minval(e) - de
539 mu_max = maxval(e) + de
541 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
543 mu = (mu_max + mu_min)/2.0_dp
544 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, bisect_method)
546 IF (abs(n_now - nel) < nel*epsocc)
EXIT
548 IF (n_now <= nel)
THEN
554 IF (iter > bisect_max_iter)
THEN
555 cpwarn(
"Smearkp: maximum bisection iterations reached")
559 mu = (mu_max + mu_min)/2.0_dp
566 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
567 res_best = abs(n_now - nel)
569 DO iter = 1, newton_max_iter
570 res_now = abs(n_now - nel)
571 IF (res_now < nel*epsocc)
EXIT
577 x = (e(is, ik) - mu)/sigma
581 dndmu = dndmu + maxocc*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
585 dndmu = dndmu + maxocc*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
590 IF (abs(dndmu) < epsilon(dndmu))
EXIT
591 step = (nel - n_now)/dndmu
592 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
594 DO iback = 1, newton_max_backtrack
595 CALL smear2(f, n_trial, kts, e, mu + step_try, wk, sigma, maxocc, method)
596 res_trial = abs(n_trial - nel)
597 IF (res_trial < res_now)
THEN
600 IF (res_trial < res_best)
THEN
606 step_try = 0.5_dp*step_try
608 IF (iback > newton_max_backtrack)
EXIT
614 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
617 IF (abs(n_now - nel) >= nel*epsocc)
THEN
618 cpwarn(
"Smearkp: MP/MV smearing did not reach the requested electron count")
640 SUBROUTINE smearkp2(f, mu, kTS, e, nel, wk, sigma, method)
642 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(OUT) :: f
643 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
644 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: e
645 REAL(kind=
dp),
INTENT(IN) :: nel
646 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
647 REAL(kind=
dp),
INTENT(IN) :: sigma
648 INTEGER,
INTENT(IN) :: method
650 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
652 INTEGER :: bisect_method, iback, ik, is, ispin, &
654 REAL(kind=
dp) :: de, dndmu, expu2, expx2, ktsa, ktsb, mu_best, mu_max, mu_min, n_now, &
655 n_trial, na, nb, res_best, res_now, res_trial, step, step_try, u, x
657 cpassert(
SIZE(f, 3) == 2 .AND.
SIZE(e, 3) == 2)
662 CALL cite_smearing(method)
668 bisect_method = method
671 SELECT CASE (bisect_method)
673 de = sigma*log((1.0_dp - epsocc)/epsocc)
680 mu_min = minval(e) - de
681 mu_max = maxval(e) + de
683 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
685 mu = (mu_max + mu_min)/2.0_dp
686 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, bisect_method)
687 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, bisect_method)
690 IF (abs(n_now - nel) < nel*epsocc)
EXIT
692 IF (n_now <= nel)
THEN
698 IF (iter > bisect_max_iter)
THEN
699 cpwarn(
"Smearkp2: maximum bisection iterations reached")
703 mu = (mu_max + mu_min)/2.0_dp
710 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
711 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
713 res_best = abs(n_now - nel)
715 DO iter = 1, newton_max_iter
716 res_now = abs(n_now - nel)
717 IF (res_now < nel*epsocc)
EXIT
724 x = (e(is, ik, ispin) - mu)/sigma
728 dndmu = dndmu + (3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
732 dndmu = dndmu + (2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
738 IF (abs(dndmu) < epsilon(dndmu))
EXIT
739 step = (nel - n_now)/dndmu
740 step = sign(min(abs(step), mpmv_max_newton_step*sigma), step)
742 DO iback = 1, newton_max_backtrack
743 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu + step_try, wk, sigma, 1.0_dp, method)
744 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu + step_try, wk, sigma, 1.0_dp, method)
746 res_trial = abs(n_trial - nel)
747 IF (res_trial < res_now)
THEN
750 IF (res_trial < res_best)
THEN
756 step_try = 0.5_dp*step_try
758 IF (iback > newton_max_backtrack)
EXIT
764 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
765 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
770 IF (abs(n_now - nel) >= nel*epsocc)
THEN
771 cpwarn(
"Smearkp2: MP/MV smearing did not reach the requested electron count")
804 SUBROUTINE compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
806 REAL(kind=
dp),
INTENT(OUT) :: gvec(:)
807 REAL(kind=
dp),
INTENT(IN) :: f(:), e(:), mu, sigma, maxocc
808 INTEGER,
INTENT(IN) :: nstate, method
809 INTEGER,
INTENT(IN),
OPTIONAL :: estate
810 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
813 REAL(kind=
dp) :: expu2, expx2, fi_norm, occ_i, u, x
816 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
817 IF (i == estate)
THEN
826 IF (occ_i < epsilon(occ_i))
THEN
831 x = (e(i) - mu)/sigma
836 gvec(i) = occ_i*fi_norm*(1.0_dp - fi_norm)/sigma
840 gvec(i) = occ_i/(sigma*
rootpi)*expx2
844 gvec(i) = occ_i*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2
849 gvec(i) = occ_i*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2
854 END SUBROUTINE compute_gvec
885 SUBROUTINE smearfixedderiv(dfde, f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
887 REAL(kind=
dp),
INTENT(OUT) :: dfde(:, :), f(:), mu, kts
888 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
889 INTEGER,
INTENT(IN) :: method
890 INTEGER,
INTENT(IN),
OPTIONAL :: estate
891 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
893 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDeriv'
895 INTEGER :: handle, i, j, nstate
896 REAL(kind=
dp) :: gsum
897 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
899 CALL timeset(routinen, handle)
902 CALL smearfixed(f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
906 ALLOCATE (gvec(nstate))
907 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
911 IF (abs(gsum) > epsilon(gsum))
THEN
914 dfde(i, j) = gvec(i)*gvec(j)/gsum
916 dfde(j, j) = dfde(j, j) - gvec(j)
923 CALL timestop(handle)
958 SUBROUTINE smearfixedderivmv(RESULT, f, mu, kTS, e, N_el, sigma, maxocc, method, v, estate, festate)
960 REAL(kind=
dp),
INTENT(OUT) :: result(:), f(:), mu, kts
961 REAL(kind=
dp),
INTENT(IN) :: e(:), n_el, sigma, maxocc
962 INTEGER,
INTENT(IN) :: method
963 REAL(kind=
dp),
INTENT(IN) :: v(:)
964 INTEGER,
INTENT(IN),
OPTIONAL :: estate
965 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
967 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDerivMV'
969 INTEGER :: handle, i, nstate
970 REAL(kind=
dp) :: gdotv, gsum
971 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
973 CALL timeset(routinen, handle)
976 CALL smearfixed(f, mu, kts, e, n_el, sigma, maxocc, method, estate, festate)
980 ALLOCATE (gvec(nstate))
981 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
985 IF (abs(gsum) > epsilon(gsum))
THEN
988 gdotv = gdotv + gvec(i)*v(i)
991 result(i) = gvec(i)*(gdotv/gsum - v(i))
998 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 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...