(git:b279b6b)
fermi_utils.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief deal with the Fermi distribution, compute it, fix mu, get derivs
10 !> \author Joost VandeVondele
11 !> \date 09.2008
12 ! **************************************************************************************************
14 
15  USE kahan_sum, ONLY: accurate_sum
16  USE kinds, ONLY: dp
17 #include "base/base_uses.f90"
18 
19  IMPLICIT NONE
20 
21  PRIVATE
22 
24 
25  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'fermi_utils'
26  INTEGER, PARAMETER, PRIVATE :: BISECT_MAX_ITER = 400
27 
28 CONTAINS
29 ! **************************************************************************************************
30 !> \brief returns occupations according to Fermi-Dirac statistics
31 !> for a given set of energies and fermi level.
32 !> Note that singly occupied orbitals are assumed
33 !> \param f occupations
34 !> \param N total number of electrons (output)
35 !> \param kTS ...
36 !> \param e eigenvalues
37 !> \param mu Fermi level (input)
38 !> \param T electronic temperature
39 !> \param maxocc maximum occupation of an orbital
40 !> \param estate excited state in core level spectroscopy
41 !> \param festate occupation of the excited state in core level spectroscopy
42 !> \date 09.2008
43 !> \par History
44 !> - Made estate and festate optional (LT, 2014/02/26)
45 !> \author Joost VandeVondele
46 ! **************************************************************************************************
47  SUBROUTINE fermi(f, N, kTS, e, mu, T, maxocc, estate, festate)
48 
49  REAL(kind=dp), INTENT(out) :: f(:), n, kts
50  REAL(kind=dp), INTENT(IN) :: e(:), mu, t, maxocc
51  INTEGER, INTENT(IN), OPTIONAL :: estate
52  REAL(kind=dp), INTENT(IN), OPTIONAL :: festate
53 
54  INTEGER :: i, nstate
55  REAL(kind=dp) :: arg, occupation, term1, term2, tmp, &
56  tmp2, tmp3, tmp4, tmplog
57 
58  nstate = SIZE(e)
59  kts = 0.0_dp
60  ! kTS is the entropic contribution to the energy i.e. -TS
61  ! kTS= kT*[f ln f + (1-f) ln (1-f)]
62 
63  DO i = 1, nstate
64  IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
65  IF (i == estate) THEN
66  occupation = festate
67  ELSE
68  occupation = maxocc
69  END IF
70  ELSE
71  occupation = maxocc
72  END IF
73  ! have the result of exp go to zero instead of overflowing
74  IF (e(i) > mu) THEN
75  arg = -(e(i) - mu)/t
76  ! tmp is smaller than 1
77  tmp = exp(arg)
78  tmp4 = tmp + 1.0_dp
79  tmp2 = tmp/tmp4
80  tmp3 = 1.0_dp/tmp4
81  ! log(1+eps), might need to be written more accurately
82  tmplog = -log(tmp4)
83  term1 = tmp2*(arg + tmplog)
84  term2 = tmp3*tmplog
85  ELSE
86  arg = (e(i) - mu)/t
87  ! tmp is smaller than 1
88  tmp = exp(arg)
89  tmp4 = tmp + 1.0_dp
90  tmp2 = 1.0_dp/tmp4
91  tmp3 = tmp/tmp4
92  tmplog = -log(tmp4)
93  term1 = tmp2*tmplog
94  term2 = tmp3*(arg + tmplog)
95  END IF
96 
97  f(i) = occupation*tmp2
98  kts = kts + t*occupation*(term1 + term2)
99  END DO
100 
101  n = accurate_sum(f)
102 
103  END SUBROUTINE fermi
104 
105 ! **************************************************************************************************
106 !> \brief Fermi function for KP cases
107 !> \param f Occupation numbers
108 !> \param nel Number of electrons (total)
109 !> \param kTS Entropic energy contribution
110 !> \param e orbital (band) energies
111 !> \param mu chemical potential
112 !> \param wk kpoint weights
113 !> \param t Temperature
114 !> \param maxocc Maximum occupation
115 ! **************************************************************************************************
116  SUBROUTINE fermi2(f, nel, kTS, e, mu, wk, t, maxocc)
117 
118  REAL(kind=dp), DIMENSION(:, :), INTENT(OUT) :: f
119  REAL(kind=dp), INTENT(OUT) :: nel, kts
120  REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: e
121  REAL(kind=dp), INTENT(IN) :: mu
122  REAL(kind=dp), DIMENSION(:), INTENT(IN) :: wk
123  REAL(kind=dp), INTENT(IN) :: t, maxocc
124 
125  INTEGER :: ik, is, nkp, nmo
126  REAL(kind=dp) :: arg, beta, term1, term2, tmp, tmp2, &
127  tmp3, tmp4, tmplog
128 
129  nmo = SIZE(e, 1)
130  nkp = SIZE(e, 2)
131  kts = 0.0_dp
132  ! kTS is the entropic contribution to the energy i.e. -TS
133  ! kTS= kT*[f ln f + (1-f) ln (1-f)]
134  IF (t > 1.0e-14_dp) THEN
135  beta = 1.0_dp/t
136  DO ik = 1, nkp
137  DO is = 1, nmo
138  IF (e(is, ik) > mu) THEN
139  arg = -(e(is, ik) - mu)*beta
140  tmp = exp(arg)
141  tmp4 = tmp + 1.0_dp
142  tmp2 = tmp/tmp4
143  tmp3 = 1.0_dp/tmp4
144  tmplog = -log(tmp4)
145  term1 = tmp2*(arg + tmplog)
146  term2 = tmp3*tmplog
147  ELSE
148  arg = (e(is, ik) - mu)*beta
149  tmp = exp(arg)
150  tmp4 = tmp + 1.0_dp
151  tmp2 = 1.0_dp/tmp4
152  tmp3 = tmp/tmp4
153  tmplog = -log(tmp4)
154  term1 = tmp2*tmplog
155  term2 = tmp3*(arg + tmplog)
156  END IF
157 
158  f(is, ik) = maxocc*tmp2
159  kts = kts + t*maxocc*(term1 + term2)*wk(ik)
160  END DO
161  END DO
162  ELSE
163  DO ik = 1, nkp
164  DO is = 1, nmo
165  IF (e(is, ik) <= mu) THEN
166  f(is, ik) = maxocc
167  ELSE
168  f(is, ik) = 0.0_dp
169  END IF
170  END DO
171  END DO
172  END IF
173 
174  nel = 0.0_dp
175  DO ik = 1, nkp
176  nel = nel + accurate_sum(f(1:nmo, ik))*wk(ik)
177  END DO
178 
179  END SUBROUTINE fermi2
180 
181 ! **************************************************************************************************
182 !> \brief returns occupations according to Fermi-Dirac statistics
183 !> for a given set of energies and number of electrons.
184 !> Note that singly occupied orbitals are assumed.
185 !> could fail if the fermi level lies out of the range of eigenvalues
186 !> (to be fixed)
187 !> \param f occupations
188 !> \param mu Fermi level (output)
189 !> \param kTS ...
190 !> \param e eigenvalues
191 !> \param N total number of electrons (input)
192 !> \param T electronic temperature
193 !> \param maxocc maximum occupation of an orbital
194 !> \param estate excited state in core level spectroscopy
195 !> \param festate occupation of the excited state in core level spectroscopy
196 !> \date 09.2008
197 !> \par History
198 !> - Made estate and festate optional (LT, 2014/02/26)
199 !> \author Joost VandeVondele
200 ! **************************************************************************************************
201  SUBROUTINE fermifixed(f, mu, kTS, e, N, T, maxocc, estate, festate)
202  REAL(kind=dp), INTENT(OUT) :: f(:), mu, kts
203  REAL(kind=dp), INTENT(IN) :: e(:), n, t, maxocc
204  INTEGER, INTENT(IN), OPTIONAL :: estate
205  REAL(kind=dp), INTENT(IN), OPTIONAL :: festate
206 
207  INTEGER :: iter, my_estate
208  REAL(kind=dp) :: mu_max, mu_min, mu_now, my_festate, &
209  n_max, n_min, n_now
210 
211  IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
212  my_estate = estate
213  my_festate = festate
214  ELSE
215  my_estate = nint(maxocc)
216  my_festate = my_estate
217  END IF
218 
219 ! bisection search to find N
220 ! first bracket
221 
222  mu_min = minval(e)
223  iter = 0
224  DO
225  iter = iter + 1
226  CALL fermi(f, n_min, kts, e, mu_min, t, maxocc, my_estate, my_festate)
227  IF (n_min > n .OR. iter > 20) THEN
228  mu_min = mu_min - t
229  ELSE
230  EXIT
231  END IF
232  END DO
233 
234  mu_max = maxval(e)
235  iter = 0
236  DO
237  iter = iter + 1
238  CALL fermi(f, n_max, kts, e, mu_max, t, maxocc, my_estate, my_festate)
239  IF (n_max < n .OR. iter > 20) THEN
240  mu_max = mu_max + t
241  ELSE
242  EXIT
243  END IF
244  END DO
245 
246  ! now bisect
247  iter = 0
248  DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
249  iter = iter + 1
250  mu_now = (mu_max + mu_min)/2.0_dp
251  CALL fermi(f, n_now, kts, e, mu_now, t, maxocc, my_estate, my_festate)
252  iter = iter + 1
253 
254  IF (n_now <= n) THEN
255  mu_min = mu_now
256  ELSE
257  mu_max = mu_now
258  END IF
259 
260  IF (iter > bisect_max_iter) THEN
261  cpwarn("Maximum number of iterations reached while finding the Fermi energy")
262  EXIT
263  END IF
264  END DO
265 
266  mu = (mu_max + mu_min)/2.0_dp
267  CALL fermi(f, n_now, kts, e, mu, t, maxocc, my_estate, my_festate)
268 
269  END SUBROUTINE fermifixed
270 
271 ! **************************************************************************************************
272 !> \brief Bisection search to find mu for a given nel (kpoint case)
273 !> \param f Occupation numbers
274 !> \param mu chemical potential
275 !> \param kTS Entropic energy contribution
276 !> \param e orbital (band) energies
277 !> \param nel Number of electrons (total)
278 !> \param wk kpoint weights
279 !> \param t Temperature
280 !> \param maxocc Maximum occupation
281 ! **************************************************************************************************
282  SUBROUTINE fermikp(f, mu, kTS, e, nel, wk, t, maxocc)
283  REAL(kind=dp), DIMENSION(:, :), INTENT(OUT) :: f
284  REAL(kind=dp), INTENT(OUT) :: mu, kts
285  REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: e
286  REAL(kind=dp), INTENT(IN) :: nel
287  REAL(kind=dp), DIMENSION(:), INTENT(IN) :: wk
288  REAL(kind=dp), INTENT(IN) :: t, maxocc
289 
290  REAL(kind=dp), PARAMETER :: epsocc = 1.0e-12_dp
291 
292  INTEGER :: iter
293  REAL(kind=dp) :: de, mu_max, mu_min, n_now
294 
295  ! bisection search to find mu for a given nel
296  de = t*log((1.0_dp - epsocc)/epsocc)
297  de = max(de, 0.5_dp)
298  mu_min = minval(e) - de
299  mu_max = maxval(e) + de
300  iter = 0
301  DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
302  iter = iter + 1
303  mu = (mu_max + mu_min)/2.0_dp
304  CALL fermi2(f, n_now, kts, e, mu, wk, t, maxocc)
305 
306  IF (abs(n_now - nel) < nel*epsocc) EXIT
307 
308  IF (n_now <= nel) THEN
309  mu_min = mu
310  ELSE
311  mu_max = mu
312  END IF
313 
314  IF (iter > bisect_max_iter) THEN
315  cpwarn("Maximum number of iterations reached while finding the Fermi energy")
316  EXIT
317  END IF
318  END DO
319 
320  mu = (mu_max + mu_min)/2.0_dp
321  CALL fermi2(f, n_now, kts, e, mu, wk, t, maxocc)
322 
323  END SUBROUTINE fermikp
324 
325 ! **************************************************************************************************
326 !> \brief Bisection search to find mu for a given nel (kpoint case)
327 !> \param f Occupation numbers
328 !> \param mu chemical potential
329 !> \param kTS Entropic energy contribution
330 !> \param e orbital (band) energies
331 !> \param nel Number of electrons (total)
332 !> \param wk kpoint weights
333 !> \param t Temperature
334 ! **************************************************************************************************
335  SUBROUTINE fermikp2(f, mu, kTS, e, nel, wk, t)
336  REAL(kind=dp), DIMENSION(:, :, :), INTENT(OUT) :: f
337  REAL(kind=dp), INTENT(OUT) :: mu, kts
338  REAL(kind=dp), DIMENSION(:, :, :), INTENT(IN) :: e
339  REAL(kind=dp), INTENT(IN) :: nel
340  REAL(kind=dp), DIMENSION(:), INTENT(IN) :: wk
341  REAL(kind=dp), INTENT(IN) :: t
342 
343  REAL(kind=dp), PARAMETER :: epsocc = 1.0e-12_dp
344 
345  INTEGER :: iter
346  REAL(kind=dp) :: de, ktsa, ktsb, mu_max, mu_min, n_now, &
347  na, nb
348 
349  ! only do spin polarized case
350  cpassert(SIZE(f, 3) == 2 .AND. SIZE(e, 3) == 2)
351 
352  ! bisection search to find mu for a given nel
353  de = t*log((1.0_dp - epsocc)/epsocc)
354  de = max(de, 0.5_dp)
355  mu_min = minval(e) - de
356  mu_max = maxval(e) + de
357  iter = 0
358  DO WHILE (mu_max - mu_min > epsilon(mu)*max(1.0_dp, abs(mu_max), abs(mu_min)))
359  iter = iter + 1
360  mu = (mu_max + mu_min)/2.0_dp
361  CALL fermi2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, t, 1.0_dp)
362  CALL fermi2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, t, 1.0_dp)
363  n_now = na + nb
364 
365  IF (abs(n_now - nel) < nel*epsocc) EXIT
366 
367  IF (n_now <= nel) THEN
368  mu_min = mu
369  ELSE
370  mu_max = mu
371  END IF
372 
373  IF (iter > bisect_max_iter) THEN
374  cpwarn("Maximum number of iterations reached while finding the Fermi energy")
375  EXIT
376  END IF
377  END DO
378 
379  mu = (mu_max + mu_min)/2.0_dp
380  CALL fermi2(f(:, :, 1), na, ktsa, e(:, :, 1), mu, wk, t, 1.0_dp)
381  CALL fermi2(f(:, :, 2), nb, ktsb, e(:, :, 2), mu, wk, t, 1.0_dp)
382  kts = ktsa + ktsb
383 
384  END SUBROUTINE fermikp2
385 
386 ! **************************************************************************************************
387 !> \brief returns f and dfde for a given set of energies and number of electrons
388 !> it is a numerical derivative, trying to use a reasonable step length
389 !> it ought to yield an accuracy of approximately EPSILON()^(2/3) (~10^-11)
390 !> l ~ 10*T yields best accuracy
391 !> Note that singly occupied orbitals are assumed.
392 !> To be fixed: this could be parallellized for better efficiency
393 !> \param dfde derivatives of the occupation numbers with respect to the eigenvalues
394 !> the ith column is the derivative of f wrt to e_i
395 !> \param f occupations
396 !> \param mu Fermi level (input)
397 !> \param kTS ...
398 !> \param e eigenvalues
399 !> \param N total number of electrons (output)
400 !> \param T electronic temperature
401 !> \param maxocc ...
402 !> \param l typical length scale (~ 10 * T)
403 !> \param estate ...
404 !> \param festate ...
405 !> \date 09.2008
406 !> \par History
407 !> - Made estate and festate optional (LT, 2014/02/26)
408 !> - Changed order of input, so l is before the two optional variables
409 !> (LT, 2014/02/26)
410 !> \author Joost VandeVondele
411 ! **************************************************************************************************
412  SUBROUTINE fermifixedderiv(dfde, f, mu, kTS, e, N, T, maxocc, l, estate, festate)
413  REAL(kind=dp), INTENT(OUT) :: dfde(:, :), f(:), mu, kts
414  REAL(kind=dp), INTENT(IN) :: e(:), n, t, maxocc, l
415  INTEGER, INTENT(IN), OPTIONAL :: estate
416  REAL(kind=dp), INTENT(IN), OPTIONAL :: festate
417 
418  CHARACTER(len=*), PARAMETER :: routinen = 'FermiFixedDeriv'
419 
420  INTEGER :: handle, i, my_estate, nstate
421  REAL(kind=dp) :: h, mux, my_festate
422  REAL(kind=dp), ALLOCATABLE :: ex(:), fx(:)
423 
424  CALL timeset(routinen, handle)
425 
426  nstate = SIZE(e)
427  ALLOCATE (ex(nstate), fx(nstate))
428 
429  IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
430  my_estate = estate
431  my_festate = festate
432  ELSE
433  my_estate = nint(maxocc)
434  my_festate = my_estate
435  END IF
436 
437  DO i = 1, nstate
438  ! NR 5.7.8
439  ! the problem here is that each f_i 'seems to have' a different length scale
440  ! and it would be to expensive to compute each single df_i/de_i using a finite difference
441  h = (epsilon(h)**(1.0_dp/3.0_dp))*l
442  ! get an exact machine representable number close to this h
443  h = 2.0_dp**exponent(h)
444  ! this should write three times the same number
445  ! write(*,*) h,(e(i)+h)-e(i),(e(i)-h)-e(i)
446  ! and the symmetric finite difference
447  ex(:) = e
448  ex(i) = e(i) + h
449  CALL fermifixed(fx, mux, kts, ex, n, t, maxocc, my_estate, my_festate)
450  dfde(:, i) = fx
451  ex(i) = e(i) - h
452  CALL fermifixed(fx, mux, kts, ex, n, t, maxocc, my_estate, my_festate)
453  dfde(:, i) = (dfde(:, i) - fx)/(2.0_dp*h)
454  END DO
455  DEALLOCATE (ex, fx)
456 
457  CALL fermifixed(f, mu, kts, e, n, t, maxocc, my_estate, my_festate)
458 
459  CALL timestop(handle)
460 
461  END SUBROUTINE fermifixedderiv
462 
463 END MODULE fermi_utils
deal with the Fermi distribution, compute it, fix mu, get derivs
Definition: fermi_utils.F:13
subroutine, public fermikp2(f, mu, kTS, e, nel, wk, t)
Bisection search to find mu for a given nel (kpoint case)
Definition: fermi_utils.F:336
subroutine, public fermikp(f, mu, kTS, e, nel, wk, t, maxocc)
Bisection search to find mu for a given nel (kpoint case)
Definition: fermi_utils.F:283
subroutine, public fermi(f, N, kTS, e, mu, T, maxocc, estate, festate)
returns occupations according to Fermi-Dirac statistics for a given set of energies and fermi level....
Definition: fermi_utils.F:48
subroutine, public fermifixedderiv(dfde, f, mu, kTS, e, N, T, maxocc, l, estate, festate)
returns f and dfde for a given set of energies and number of electrons it is a numerical derivative,...
Definition: fermi_utils.F:413
subroutine, public fermifixed(f, mu, kTS, e, N, T, maxocc, estate, festate)
returns occupations according to Fermi-Dirac statistics for a given set of energies and number of ele...
Definition: fermi_utils.F:202
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Definition: kahan_sum.F:29
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34