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
61 SUBROUTINE cite_smearing(method)
62 INTEGER,
INTENT(IN) :: method
78 END SUBROUTINE cite_smearing
104 SUBROUTINE smearocc(f, N, kTS, e, mu, sigma, maxocc, method, estate, festate)
106 REAL(kind=
dp),
INTENT(OUT) :: f(:), n, kts
107 REAL(kind=
dp),
INTENT(IN) :: e(:), mu, sigma, maxocc
108 INTEGER,
INTENT(IN) :: method
109 INTEGER,
INTENT(IN),
OPTIONAL :: estate
110 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
113 REAL(kind=
dp) :: arg, expu2, expx2, occupation, term1, &
114 term2, tmp, tmp2, tmp3, tmp4, tmplog, &
121 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
122 IF (i == estate)
THEN
134 arg = -(e(i) - mu)/sigma
140 term1 = tmp2*(arg + tmplog)
143 arg = (e(i) - mu)/sigma
150 term2 = tmp3*(arg + tmplog)
152 f(i) = occupation*tmp2
153 kts = kts + sigma*occupation*(term1 + term2)
156 x = (e(i) - mu)/sigma
158 f(i) = occupation*0.5_dp*erfc(x)
159 kts = kts - (sigma/(2.0_dp*
rootpi))*occupation*expx2
162 x = (e(i) - mu)/sigma
164 f(i) = occupation*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
165 kts = kts + (sigma/(4.0_dp*
rootpi))*occupation*(2.0_dp*x*x - 1.0_dp)*expx2
168 x = (e(i) - mu)/sigma
171 f(i) = occupation*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
172 kts = kts - (sigma/(
sqrt2*
rootpi))*occupation*u*expu2
175 cpabort(
"SmearOcc: unknown smearing method")
199 SUBROUTINE smear2(f, nel, kTS, e, mu, wk, sigma, maxocc, method)
201 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
202 REAL(kind=
dp),
INTENT(OUT) :: nel, kts
203 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
204 REAL(kind=
dp),
INTENT(IN) :: mu
205 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
206 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
207 INTEGER,
INTENT(IN) :: method
209 INTEGER :: ik, is, nkp, nmo
210 REAL(kind=
dp) :: arg, expu2, expx2, term1, term2, tmp, &
211 tmp2, tmp3, tmp4, tmplog, u, x
217 IF (sigma > 1.0e-14_dp)
THEN
222 IF (e(is, ik) > mu)
THEN
223 arg = -(e(is, ik) - mu)/sigma
229 term1 = tmp2*(arg + tmplog)
232 arg = (e(is, ik) - mu)/sigma
239 term2 = tmp3*(arg + tmplog)
241 f(is, ik) = maxocc*tmp2
242 kts = kts + sigma*maxocc*(term1 + term2)*wk(ik)
245 x = (e(is, ik) - mu)/sigma
247 f(is, ik) = maxocc*0.5_dp*erfc(x)
248 kts = kts - (sigma/(2.0_dp*
rootpi))*maxocc*expx2*wk(ik)
251 x = (e(is, ik) - mu)/sigma
253 f(is, ik) = maxocc*(0.5_dp*erfc(x) - x/(2.0_dp*
rootpi)*expx2)
254 kts = kts + (sigma/(4.0_dp*
rootpi))*maxocc*(2.0_dp*x*x - 1.0_dp)*expx2*wk(ik)
257 x = (e(is, ik) - mu)/sigma
260 f(is, ik) = maxocc*(0.5_dp*erfc(u) + expu2/(
sqrt2*
rootpi))
261 kts = kts - (sigma/(
sqrt2*
rootpi))*maxocc*u*expu2*wk(ik)
264 cpabort(
"Smear2: unknown smearing method")
272 IF (e(is, ik) <= mu)
THEN
286 END SUBROUTINE smear2
311 SUBROUTINE smearfixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
313 REAL(kind=
dp),
INTENT(OUT) :: f(:), mu, kts
314 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
315 INTEGER,
INTENT(IN) :: method
316 INTEGER,
INTENT(IN),
OPTIONAL :: estate
317 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
319 INTEGER :: iter, my_estate, nstate
320 REAL(kind=
dp) :: gsum, mu_max, mu_min, mu_now, &
321 my_festate, n_now, n_tmp
322 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
324 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
328 my_estate = nint(maxocc)
329 my_festate = my_estate
334 CALL cite_smearing(method)
346 IF (n_tmp > n .OR. iter > 20)
THEN
347 mu_min = mu_min - sigma
358 IF (n_tmp < n .OR. iter > 20)
THEN
359 mu_max = mu_max + sigma
366 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
368 mu_now = (mu_max + mu_min)/2.0_dp
375 IF (iter > bisect_max_iter)
EXIT
377 mu = (mu_max + mu_min)/2.0_dp
380 ALLOCATE (gvec(nstate))
381 DO iter = 1, newton_max_iter
382 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
383 IF (abs(n_now - n) < n*1.0e-12_dp)
EXIT
384 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, my_estate, my_festate)
386 IF (abs(gsum) < epsilon(gsum))
EXIT
387 mu = mu + (n - n_now)/gsum
392 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
400 CALL smearocc(f, n_tmp, kts, e, mu_min, sigma, maxocc, method, my_estate, my_festate)
401 IF (n_tmp > n .OR. iter > 20)
THEN
402 mu_min = mu_min - sigma
412 CALL smearocc(f, n_tmp, kts, e, mu_max, sigma, maxocc, method, my_estate, my_festate)
413 IF (n_tmp < n .OR. iter > 20)
THEN
414 mu_max = mu_max + sigma
421 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
423 mu_now = (mu_max + mu_min)/2.0_dp
424 CALL smearocc(f, n_now, kts, e, mu_now, sigma, maxocc, method, my_estate, my_festate)
430 IF (iter > bisect_max_iter)
THEN
431 cpwarn(
"SmearFixed: maximum bisection iterations reached")
436 mu = (mu_max + mu_min)/2.0_dp
437 CALL smearocc(f, n_now, kts, e, mu, sigma, maxocc, method, my_estate, my_festate)
463 SUBROUTINE smearkp(f, mu, kTS, e, nel, wk, sigma, maxocc, method)
465 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: f
466 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
467 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: e
468 REAL(kind=
dp),
INTENT(IN) :: nel
469 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
470 REAL(kind=
dp),
INTENT(IN) :: sigma, maxocc
471 INTEGER,
INTENT(IN) :: method
473 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
475 INTEGER :: bisect_method, ik, is, iter, nkp, nmo
476 REAL(kind=
dp) :: de, dndmu, expu2, expx2, mu_max, mu_min, &
482 CALL cite_smearing(method)
489 bisect_method = method
493 SELECT CASE (bisect_method)
495 de = sigma*log((1.0_dp - epsocc)/epsocc)
502 mu_min = minval(e) - de
503 mu_max = maxval(e) + de
505 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
507 mu = (mu_max + mu_min)/2.0_dp
508 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, bisect_method)
510 IF (abs(n_now - nel) < nel*epsocc)
EXIT
512 IF (n_now <= nel)
THEN
518 IF (iter > bisect_max_iter)
THEN
519 cpwarn(
"Smearkp: maximum bisection iterations reached")
523 mu = (mu_max + mu_min)/2.0_dp
528 DO iter = 1, newton_max_iter
529 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
530 IF (abs(n_now - nel) < nel*epsocc)
EXIT
536 x = (e(is, ik) - mu)/sigma
540 dndmu = dndmu + maxocc*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
544 dndmu = dndmu + maxocc*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
549 IF (abs(dndmu) < epsilon(dndmu))
EXIT
550 mu = mu + (nel - n_now)/dndmu
555 CALL smear2(f, n_now, kts, e, mu, wk, sigma, maxocc, method)
575 SUBROUTINE smearkp2(f, mu, kTS, e, nel, wk, sigma, method)
577 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(OUT) :: f
578 REAL(kind=
dp),
INTENT(OUT) :: mu, kts
579 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: e
580 REAL(kind=
dp),
INTENT(IN) :: nel
581 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wk
582 REAL(kind=
dp),
INTENT(IN) :: sigma
583 INTEGER,
INTENT(IN) :: method
585 REAL(kind=
dp),
PARAMETER :: epsocc = 1.0e-12_dp
587 INTEGER :: bisect_method, ik, is, ispin, iter, nkp, &
589 REAL(kind=
dp) :: de, dndmu, expu2, expx2, ktsa, ktsb, &
590 mu_max, mu_min, n_now, na, nb, u, x
592 cpassert(
SIZE(f, 3) == 2 .AND.
SIZE(e, 3) == 2)
597 CALL cite_smearing(method)
603 bisect_method = method
606 SELECT CASE (bisect_method)
608 de = sigma*log((1.0_dp - epsocc)/epsocc)
615 mu_min = minval(e) - de
616 mu_max = maxval(e) + de
618 DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
620 mu = (mu_max + mu_min)/2.0_dp
621 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, bisect_method)
622 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, bisect_method)
625 IF (abs(n_now - nel) < nel*epsocc)
EXIT
627 IF (n_now <= nel)
THEN
633 IF (iter > bisect_max_iter)
THEN
634 cpwarn(
"Smearkp2: maximum bisection iterations reached")
638 mu = (mu_max + mu_min)/2.0_dp
643 DO iter = 1, newton_max_iter
644 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
645 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
647 IF (abs(n_now - nel) < nel*epsocc)
EXIT
654 x = (e(is, ik, ispin) - mu)/sigma
658 dndmu = dndmu + (3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2*wk(ik)
662 dndmu = dndmu + (2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2*wk(ik)
668 IF (abs(dndmu) < epsilon(dndmu))
EXIT
669 mu = mu + (nel - n_now)/dndmu
674 CALL smear2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
675 CALL smear2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
707 SUBROUTINE compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
709 REAL(kind=
dp),
INTENT(OUT) :: gvec(:)
710 REAL(kind=
dp),
INTENT(IN) :: f(:), e(:), mu, sigma, maxocc
711 INTEGER,
INTENT(IN) :: nstate, method
712 INTEGER,
INTENT(IN),
OPTIONAL :: estate
713 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
716 REAL(kind=
dp) :: expu2, expx2, fi_norm, occ_i, u, x
719 IF (
PRESENT(estate) .AND.
PRESENT(festate))
THEN
720 IF (i == estate)
THEN
729 IF (occ_i < epsilon(occ_i))
THEN
734 x = (e(i) - mu)/sigma
739 gvec(i) = occ_i*fi_norm*(1.0_dp - fi_norm)/sigma
743 gvec(i) = occ_i/(sigma*
rootpi)*expx2
747 gvec(i) = occ_i*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*
rootpi)*expx2
752 gvec(i) = occ_i*(2.0_dp +
sqrt2*x)/(sigma*
rootpi)*expu2
757 END SUBROUTINE compute_gvec
788 SUBROUTINE smearfixedderiv(dfde, f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
790 REAL(kind=
dp),
INTENT(OUT) :: dfde(:, :), f(:), mu, kts
791 REAL(kind=
dp),
INTENT(IN) :: e(:), n, sigma, maxocc
792 INTEGER,
INTENT(IN) :: method
793 INTEGER,
INTENT(IN),
OPTIONAL :: estate
794 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
796 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDeriv'
798 INTEGER :: handle, i, j, nstate
799 REAL(kind=
dp) :: gsum
800 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
802 CALL timeset(routinen, handle)
805 CALL smearfixed(f, mu, kts, e, n, sigma, maxocc, method, estate, festate)
809 ALLOCATE (gvec(nstate))
810 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
814 IF (abs(gsum) > epsilon(gsum))
THEN
817 dfde(i, j) = gvec(i)*gvec(j)/gsum
819 dfde(j, j) = dfde(j, j) - gvec(j)
826 CALL timestop(handle)
861 SUBROUTINE smearfixedderivmv(RESULT, f, mu, kTS, e, N_el, sigma, maxocc, method, v, estate, festate)
863 REAL(kind=
dp),
INTENT(OUT) :: result(:), f(:), mu, kts
864 REAL(kind=
dp),
INTENT(IN) :: e(:), n_el, sigma, maxocc
865 INTEGER,
INTENT(IN) :: method
866 REAL(kind=
dp),
INTENT(IN) :: v(:)
867 INTEGER,
INTENT(IN),
OPTIONAL :: estate
868 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: festate
870 CHARACTER(len=*),
PARAMETER :: routinen =
'SmearFixedDerivMV'
872 INTEGER :: handle, i, nstate
873 REAL(kind=
dp) :: gdotv, gsum
874 REAL(kind=
dp),
ALLOCATABLE :: gvec(:)
876 CALL timeset(routinen, handle)
879 CALL smearfixed(f, mu, kts, e, n_el, sigma, maxocc, method, estate, festate)
883 ALLOCATE (gvec(nstate))
884 CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
888 IF (abs(gsum) > epsilon(gsum))
THEN
891 gdotv = gdotv + gvec(i)*v(i)
894 result(i) = gvec(i)*(gdotv/gsum - v(i))
901 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...