(git:374b731)
Loading...
Searching...
No Matches
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
28CONTAINS
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
463END MODULE fermi_utils
deal with the Fermi distribution, compute it, fix mu, get derivs
Definition fermi_utils.F:13
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,...
subroutine, public fermikp2(f, mu, kts, e, nel, wk, t)
Bisection search to find mu for a given nel (kpoint case)
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...
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 fermikp(f, mu, kts, e, nel, wk, t, maxocc)
Bisection search to find mu for a given nel (kpoint case)
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