Octopus
smear.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19! Some pieces glued from PW/w(0,1)gauss.f90 from PWSCF
20
21#include "global.h"
22
23module smear_oct_m
24 use debug_oct_m
25 use global_oct_m
26 use, intrinsic :: iso_fortran_env
31 use parser_oct_m
34 use sort_oct_m
35 use unit_oct_m
38
39 implicit none
40
41 private
42 public :: &
43 smear_t, &
44 smear_init, &
45 smear_copy, &
54
55 type smear_t
56 private
57 integer, public :: method
58 real(real64), public :: dsmear
59 real(real64) :: dsmear_cond
60 real(real64), public :: e_fermi
61 real(real64) :: e_fermi_cond
62
63 integer, public :: el_per_state
64 real(real64), public :: ef_occ
65 real(real64) :: ef_occ_cond
66 logical, public :: integral_occs
67 integer, public :: MP_n
68 integer :: fermi_count
69 integer :: nik_factor
70 integer :: nspins
71
72 type(simplex_t), pointer :: tetra_simplex => null()
73
74 ! PhotonDoping
75 logical, public:: photodop
76 real(real64) :: nephotodop
77 integer :: photodop_bandmin
78
79 end type smear_t
80
81 integer, parameter, public :: &
82 SMEAR_SEMICONDUCTOR = 1, &
84 smear_cold = 3, &
86 smear_spline = 5, &
87 smear_fixed_occ = 6, &
88 smear_gaussian = option__smearingfunction__gaussian_smearing, &
89 smear_lorentzian = option__smearingfunction__lorentzian_smearing, &
90 smear_tetrahedra = option__smearingfunction__tetrahedra, &
91 smear_tetrahedra_opt = option__smearingfunction__tetrahedra_opt
92
93 real(real64), parameter :: TOL_SMEAR = 1e-6_real64
94
95contains
96
97 !--------------------------------------------------
98 subroutine smear_init(this, namespace, ispin, fixed_occ, integral_occs, kpoints)
99 type(smear_t), intent(out) :: this
100 type(namespace_t), intent(in) :: namespace
101 integer, intent(in) :: ispin
102 logical, intent(in) :: fixed_occ
103 logical, intent(in) :: integral_occs
104 type(kpoints_t), intent(in) :: kpoints
105
106 push_sub(smear_init)
107
108 this%integral_occs = integral_occs
109
110 !%Variable SmearingFunction
111 !%Type integer
112 !%Default semiconducting
113 !%Section States
114 !%Description
115 !% This is the function used to smear the electronic occupations.
116 !% It is ignored if the <tt>Occupations</tt> block is set.
117 !%Option semiconducting 1
118 !% Semiconducting occupations, <i>i.e.</i> the lowest lying states are occupied
119 !% until no more electrons are left.
120 !%Option fermi_dirac 2
121 !% Simple Fermi-Dirac distribution. In this case, <tt>Smearing</tt> has
122 !% the meaning of an electronic temperature. DN Mermin, <i>Phys. Rev.</i> <b>137</b>, A1441 (1965).
123 !%Option cold_smearing 3
124 !% N Marzari, D Vanderbilt, A De Vita, and MC Payne, <i>Phys. Rev. Lett.</i> <b>82</b>, 3296 (1999).
125 !%Option methfessel_paxton 4
126 !% M Methfessel and AT Paxton, <i>Phys. Rev. B</i> <b>40</b>, 3616 (1989).
127 !% In this case, the variable <tt>SmearingMPOrder</tt> sets the order of the smearing.
128 !% Occupations may be negative.
129 !%Option spline_smearing 5
130 !% Nearly identical to Gaussian smearing.
131 !% JM Holender, MJ Gillan, MC Payne, and AD Simpson, <i>Phys. Rev. B</i> <b>52</b>, 967 (1995).
132 !%Option gaussian_smearing
133 !% Gaussian smearing.
134 !%Option lorentzian_smearing
135 !% Lorentzian smearing.
136 !%Option tetrahedra
137 !% Linear tetrahedron method as in P. E. Bloechl, et al., <i>Phys. Rev. B</i> <b>49</b>, 16223 (1994).
138 !% Requires a regular Monkhorst-Pack generated by Octopus.
139 !%Option tetrahedra_opt
140 !% Improved tetrahedron method as in M. Kawamura, et al., <i>Phys. Rev. B</i> <b>89</b>, 094515 (2014).
141 !% Requires a regular Monkhorst-Pack generated by Octopus.
142 !%End
143 if (fixed_occ) then
144 this%method = smear_fixed_occ
145 else
146 call parse_variable(namespace, 'SmearingFunction', smear_semiconductor, this%method)
147 if (.not. varinfo_valid_option('SmearingFunction', this%method)) call messages_input_error(namespace, 'SmearingFunction')
148 call messages_print_var_option('SmearingFunction', this%method, namespace=namespace)
149 end if
151 !%Variable Smearing
152 !%Type float
153 !%Default 0.1 eV
154 !%Section States
155 !%Description
156 !% If <tt>Occupations</tt> is not set, <tt>Smearing</tt> is the
157 !% smearing width used in the <tt>SmearingFunction</tt> to distribute the electrons
158 !% among the existing states.
159 !%End
160 this%dsmear = 1e-14_real64
161 if (this%method /= smear_semiconductor .and. this%method /= smear_fixed_occ) then
162 call parse_variable(namespace, 'Smearing', 0.1_real64 / (m_two * p_ry), this%dsmear, units_inp%energy)
163 end if
165 !%Variable PhotoDopingSmearing
166 !%Type float
167 !%Default 0.1 eV
168 !%Section States
169 !%Description
170 !% If <tt>Occupations</tt> is not set, <tt>PhotoDopingSmearing</tt> is the
171 !% smearing width used in the <tt>SmearingFunction</tt> to distribute the electrons in conduction bands
172 !% among the existing states.
173 !%End
174 this%dsmear_cond = this%dsmear
175 if (this%method /= smear_semiconductor .and. this%method /= smear_fixed_occ) then
176 call parse_variable(namespace, 'PhotoDopingSmearing', 0.1_real64 / (m_two * p_ry), this%dsmear_cond, units_inp%energy)
177 end if
178
179 !%Variable PhotoDopingNumElectrons
180 !%Type float
181 !%Default 0
182 !%Section States
183 !%Description
184 !% This variable allows to set the number of valence electrons taken out to put
185 !% into the conduction bands. The method follows Marini and Calandra, PRB 104, 144103 (2021).
186 !%End
187 call parse_variable(namespace, 'PhotoDopingNumElectrons', m_zero, this%nephotodop)
189 if (this%nephotodop > m_min_occ) then
190 this%photodop=.true.
191 else
192 this%photodop=.false.
193 endif
194
195
196 !%Variable PhotoDopingBand
197 !%Type integer
198 !%Default 1
199 !%Section States
200 !%Description
201 !% This variable specifies where the minium (starting) conduction band index for the photodoping electrons.
202 !%End
203 call parse_variable(namespace, 'PhotoDopingBand', 1, this%photodop_bandmin)
204
205
206 call messages_obsolete_variable(namespace, 'ElectronicTemperature', 'Smearing')
207
208 if (ispin == 1) then ! unpolarized
209 this%el_per_state = 2
210 else
211 this%el_per_state = 1
212 end if
213
214 if (ispin == 2) then
215 this%nspins = 2
216 else
217 this%nspins = 1
218 end if
219
220 if (this%method == smear_semiconductor) then
221 this%nik_factor = kpoints_kweight_denominator(kpoints)
222
223 if (this%nik_factor == 0) then
224 message(1) = "k-point weights in KPoints or KPointsReduced blocks must be rational numbers for semiconducting smearing."
225 call messages_fatal(1, namespace=namespace)
226 end if
227 else if (this%method == smear_tetrahedra .or. this%method == smear_tetrahedra_opt) then
228 if (.not. associated(kpoints%reduced%simplex)) then
229 message(1) = "Tetrahedron smearing requires a simplex mesh for the k-point grid."
230 call messages_fatal(1, namespace=namespace)
231 end if
232
233 this%tetra_simplex => kpoints%reduced%simplex
234 end if
235
236 this%MP_n = 0
237 if (this%method == smear_methfessel_paxton) then
238 !%Variable SmearingMPOrder
239 !%Type integer
240 !%Default 1
241 !%Section States
242 !%Description
243 !% Sets the order of the Methfessel-Paxton smearing function.
244 !%End
245 call parse_variable(namespace, 'SmearingMPOrder', 1, this%MP_n)
246 end if
247
248 pop_sub(smear_init)
249 end subroutine smear_init
250
251
252 !--------------------------------------------------
253 subroutine smear_copy(to, from)
254 type(smear_t), intent(out) :: to
255 type(smear_t), intent(in) :: from
256
257 push_sub(smear_copy)
258
259 to%method = from%method
260 to%dsmear = from%dsmear
261 to%e_fermi = from%e_fermi
262 to%el_per_state = from%el_per_state
263 to%ef_occ = from%ef_occ
264 to%MP_n = from%MP_n
265 to%fermi_count = from%fermi_count
266 to%nik_factor = from%nik_factor
267 to%tetra_simplex => from%tetra_simplex
268
269 to%dsmear_cond = from%dsmear_cond
270 to%e_fermi_cond = from%e_fermi_cond
271 to%ef_occ_cond = from%ef_occ_cond
272 to%integral_occs = from%integral_occs
273 to%nspins = from%nspins
274 to%photodop = from%photodop
275 to%nephotodop = from%nephotodop
276 to%photodop_bandmin = from%photodop_bandmin
277
278 pop_sub(smear_copy)
279 end subroutine smear_copy
280
281
282 !--------------------------------------------------
283 subroutine smear_find_fermi_energy(this, namespace, eigenvalues, occupations, &
284 qtot, nik, nst, kweights)
285 type(smear_t), intent(inout) :: this
286 type(namespace_t), intent(in) :: namespace
287 real(real64), contiguous, intent(in) :: eigenvalues(:,:), occupations(:,:)
288 real(real64), intent(in) :: qtot
289 real(real64), contiguous, intent(in) :: kweights(:)
290 integer, intent(in) :: nik, nst
291
292 real(real64), parameter :: tol = 1.0e-10_real64
293 integer :: ist, ik, iter, maxq, weight, sumq_int, sum_weight
294 real(real64) :: sumq_frac
295 logical :: conv
296 real(real64), allocatable :: eigenval_list(:)
297 integer, allocatable :: k_list(:), reorder(:)
298 integer :: fermi_count_up, fermi_count_down
299
301
302 maxq = this%el_per_state * nst * this%nspins
303 if (maxq - qtot <= -tol) then ! not enough states
304 message(1) = 'Not enough states'
305 write(message(2),'(6x,a,f12.6,a,i10)')'(total charge = ', qtot, &
306 ' max charge = ', maxq
307 call messages_fatal(2, namespace=namespace)
308 end if
309
310 conv = .true.
311 if (this%method == smear_fixed_occ) then ! Fermi energy: last of occupied states
312 ist_cycle: do ist = nst, 1, -1
313 if (any(occupations(ist, :) > m_min_occ)) then
314 this%e_fermi = eigenvalues(ist, 1)
315 this%ef_occ = occupations(ist, 1) / this%el_per_state
316 do ik = 2, nik
317 if (eigenvalues(ist, ik) > this%e_fermi .and. occupations(ist, ik) > m_min_occ) then
318 this%e_fermi = eigenvalues(ist, ik)
319 this%ef_occ = occupations(ist, ik) / this%el_per_state
320 end if
321 end do
322 exit ist_cycle
323 end if
324 end do ist_cycle
325
326 else if (this%method == smear_semiconductor) then
327 ! first we sort the eigenvalues
328 safe_allocate(eigenval_list(1:nst * nik))
329 safe_allocate( k_list(1:nst * nik))
330 safe_allocate( reorder(1:nst * nik))
331
332 iter = 1
333 do ist = 1, nst
334 do ik = 1, nik
335 eigenval_list(iter) = eigenvalues(ist, ik)
336 k_list(iter) = ik
337 reorder(iter) = iter
338 iter = iter + 1
339 end do
340 end do
341
342 call sort(eigenval_list, reorder)
343
344 sumq_int = floor(qtot) * this%nik_factor
345 sumq_frac = qtot * this%nik_factor - sumq_int
346 if ( sumq_frac + tol > this%nik_factor ) then
347 sumq_int = sumq_int + this%nik_factor
348 sumq_frac = sumq_frac - this%nik_factor
349 end if
350 if (sumq_frac < tol) sumq_frac = m_zero
351
352 do iter = 1, nst * nik
353 weight = int(kweights(k_list(reorder(iter))) * this%nik_factor + m_half)
354 if (weight <= 0) cycle
355 this%e_fermi = eigenval_list(iter)
356 this%ef_occ = (sumq_int + sumq_frac) / (weight * this%el_per_state)
357
358 if (sumq_int - weight * this%el_per_state <= 0) then
359 ! count how many occupied states are at the fermi level,
360 ! this is required later to fill the states
361 this%fermi_count = 1
362 fermi_count_up = 1
363 fermi_count_down = 1
364 sum_weight = weight
365 do
366 if (iter - fermi_count_down < 1) exit
367 if (abs(this%e_fermi - eigenval_list(iter - fermi_count_down)) > tol_smear) exit
368 weight = int(kweights(k_list(reorder(iter - fermi_count_down))) * this%nik_factor + m_half)
369 if (weight > 0) then
370 sumq_int = sumq_int + weight * this%el_per_state
371 sum_weight = sum_weight + weight
372 end if
373 fermi_count_down = fermi_count_down + 1
374 end do
375 do
376 if (iter + fermi_count_up > nst*nik) exit
377 if (abs(this%e_fermi - eigenval_list(iter + fermi_count_up)) > tol_smear) exit
378 weight = int(kweights(k_list(reorder(iter + fermi_count_up))) * this%nik_factor + m_half)
379 if (weight > 0) then
380 sum_weight = sum_weight + weight
381 end if
382 fermi_count_up = fermi_count_up + 1
383 end do
384 this%fermi_count = fermi_count_up + fermi_count_down - 1
385 this%ef_occ = (sumq_int + sumq_frac) / (sum_weight * this%el_per_state)
386 exit
387 end if
388
389 sumq_int = sumq_int - weight * this%el_per_state
390 end do
391 assert(this%ef_occ < m_one + 10.0_real64*m_epsilon)
392
393 safe_deallocate_a(eigenval_list)
394 safe_deallocate_a(k_list)
395 safe_deallocate_a(reorder)
396
397 else if (this%method == smear_tetrahedra .or. this%method == smear_tetrahedra_opt) then
398 if (this%photodop) then
399 call messages_not_implemented('Photodoping for SmearingFunction = tetrahedra/tetrahedra_opt')
400 end if
401 call bisection_find_fermi_energy_tetra(this, namespace, tol, eigenvalues, nik, nst, qtot, this%e_fermi)
402 else ! bisection
403 if (this%photodop) then
404 ! find fermi energy for valence electrons
405 call bisection_find_fermi_energy(this, namespace, this%dsmear, tol, &
406 eigenvalues, kweights, nik, qtot-this%nephotodop, 1, this%photodop_bandmin-1, &
407 this%e_fermi, this%ef_occ)
408
409 ! find fermi energy for conduction electrons
410 call bisection_find_fermi_energy(this, namespace, this%dsmear_cond, tol, &
411 eigenvalues, kweights, nik, this%nephotodop, this%photodop_bandmin, nst, &
412 this%e_fermi_cond, this%ef_occ_cond)
413 else
414 call bisection_find_fermi_energy(this, namespace, this%dsmear, tol, &
415 eigenvalues, kweights, nik, qtot, 1, nst, this%e_fermi, this%ef_occ)
416 end if
417 end if
418
420 end subroutine smear_find_fermi_energy
421
422 ! ---------------------------------------------------------
423 subroutine bisection_find_fermi_energy(this, namespace, dsmear_in, tol, &
424 eigenvalues, kweights, nik, q_in, start_band, end_band, e_fermi, ef_occ)
425 type(smear_t), intent(inout) :: this
426 type(namespace_t), intent(in) :: namespace
427 real(real64), intent(in) :: dsmear_in
428 real(real64), intent(in) :: tol
429 integer, intent(in) :: nik
430 real(real64), contiguous, intent(in) :: eigenvalues(:,:)
431 real(real64), intent(in) :: q_in
432 real(real64), contiguous, intent(in) :: kweights(:)
433 integer, intent(in) :: start_band, end_band
434 real(real64), intent(out) :: e_fermi, ef_occ
435
436 integer, parameter :: nitmax = 200
437 integer :: ist, ik, iter
438 real(real64) :: drange, dsmear, emin, emax, xx, sumq
439 logical :: conv
440
442
443 dsmear = max(1e-14_real64, dsmear_in)
444 drange = dsmear * sqrt(-log(tol * 0.01_real64))
445
446 emin = minval(eigenvalues) - drange
447 emax = maxval(eigenvalues) + drange
448
449 do iter = 1, nitmax
450 e_fermi = m_half * (emin + emax)
451 sumq = m_zero
452
453 do ik = 1, nik
454 do ist = start_band, end_band
455 xx = (e_fermi - eigenvalues(ist, ik))/dsmear
456 sumq = sumq + kweights(ik) * this%el_per_state * &
457 smear_step_function(this, xx)
458 end do
459 end do
460
461 conv = (abs(sumq - q_in) <= tol)
462 if (conv) exit
463
464 if (sumq <= q_in) emin = e_fermi
465 if (sumq >= q_in) emax = e_fermi
466
467 ef_occ = smear_step_function(this, m_zero)
468 end do
469
470 if (.not. conv) then
471 message(1) = 'Fermi: did not converge.'
472 call messages_fatal(1, namespace=namespace)
473 end if
474
476 end subroutine bisection_find_fermi_energy
477
478 ! ---------------------------------------------------------
498 subroutine bisection_find_fermi_energy_tetra(this, namespace, tol, eigenvalues, nik, nst, q_in, e_fermi)
499 type(smear_t), intent(inout) :: this
500 type(namespace_t), intent(in) :: namespace
501 real(real64), intent(in) :: tol
502 integer, intent(in) :: nik, nst
503 real(real64), contiguous, intent(in) :: eigenvalues(:,:)
504 real(real64), intent(in) :: q_in
505 real(real64), intent(out) :: e_fermi
506
507 integer, parameter :: nitmax = 200
508 integer :: iter
509 real(real64) :: emin, emax, sumq
510 logical :: conv
511
512 integer :: ist, ii, ll, is, ik, ns, nik_red, nvertices
513 real(real64) :: e_simplex(20), w_simplex(4), dos_simplex(4)
514
515 push_sub_with_profile(bisection_find_fermi_energy_tetra)
516
517 assert(associated(this%tetra_simplex))
518 assert(this%tetra_simplex%n_simplices > 0)
519 assert(this%tetra_simplex%sdim > 0)
520
521 ns = this%nspins
522 assert(ns > 0)
523 assert(mod(nik, ns) == 0)
524
525 nik_red = nik / ns
526 assert(maxval(this%tetra_simplex%simplices) <= nik_red)
527
528 nvertices = this%tetra_simplex%rdim + 1
529 assert(nvertices > 0)
530 assert(nvertices <= this%tetra_simplex%sdim)
531
532 emin = minval(eigenvalues)
533 emax = maxval(eigenvalues)
534 if (.not. (emin < emax)) then
535 write(message(1), '(a)') 'Tetra bisection: invalid energy bracket from eigenvalues.'
536 call messages_fatal(1, namespace=namespace)
537 end if
538
539 do iter = 1, nitmax
540 e_fermi = m_half * (emin + emax)
541 sumq = m_zero
542 !$omp parallel do collapse(2) private(ist, ii, is, ll, ik, e_simplex, w_simplex, dos_simplex) reduction(+:sumq)
543 do ist = 1, nst
544 do ii = 1, this%tetra_simplex%n_simplices
545 do is = 0, ns - 1
546 do ll = 1, this%tetra_simplex%sdim
547 ik = ns * (this%tetra_simplex%simplices(ii, ll) - 1) + 1
548 e_simplex(ll) = eigenvalues(ist, ik + is)
549 end do
550 w_simplex(:) = m_zero
551
552 call simplex_weights(this%tetra_simplex%rdim, e_simplex(1:this%tetra_simplex%sdim), e_fermi, &
553 w_simplex(1:nvertices), dos_simplex(1:nvertices))
554
555 do ll = 1, nvertices
556 sumq = sumq + this%el_per_state * w_simplex(ll) / this%tetra_simplex%n_points
557 end do
558 end do
559 end do
560 end do
561 !$omp end parallel do
562
563 conv = (abs(sumq - q_in) <= tol)
564 if (conv) exit
565
566 if (sumq <= q_in) emin = e_fermi
567 if (sumq >= q_in) emax = e_fermi
568 end do
569
570 if (.not. conv) then
571 message(1) = 'Fermi (tetrahedra): did not converge.'
572 call messages_fatal(1, namespace=namespace)
573 end if
574
575 pop_sub_with_profile(bisection_find_fermi_energy_tetra)
577
578 ! ---------------------------------------------------------
579 subroutine smear_fill_occupations(this, eigenvalues, occupations, kweights, nik, nst)
580 type(smear_t), intent(in) :: this
581 real(real64), contiguous, intent(in) :: eigenvalues(:,:)
582 real(real64), contiguous, intent(inout) :: occupations(:,:)
583 real(real64), contiguous, intent(in) :: kweights(:)
584 integer, intent(in) :: nik, nst
585
586 integer :: ik, ist, ifermi
587 real(real64) :: dsmear, xx, dsmear_cond
588
589 push_sub(smear_fill_occupations)
590
591 if (this%method == smear_fixed_occ) then
592 ! do nothing
593 else if (this%method == smear_semiconductor) then
594 assert(this%fermi_count > 0 .and. this%fermi_count <= nik*nst)
595
596 ifermi = 0
597 do ik = 1, nik
598 do ist = 1, nst
599 xx = eigenvalues(ist, ik) - this%e_fermi
600 if (xx < -tol_smear) then
601 occupations(ist, ik) = this%el_per_state
602 else if (abs(xx) <= tol_smear .and. ifermi < this%fermi_count) then
603 occupations(ist, ik) = this%ef_occ * this%el_per_state
604 ifermi = ifermi + 1
605 else
606 occupations(ist, ik) = m_zero
607 end if
608
609 end do
610 end do
611 else if (this%method == smear_tetrahedra .or. this%method == smear_tetrahedra_opt) then
612 if (this%photodop) then
613 call messages_not_implemented('Photodoping for SmearingFunction = tetrahedra/tetrahedra_opt')
614 end if
615 block
616 integer :: ii, ll, is, ns, nik_red, nvertices
617 real(real64) :: e_simplex(20), w_simplex(4), dos_simplex(4)
618
619 assert(associated(this%tetra_simplex))
620 assert(this%tetra_simplex%n_simplices > 0)
621 assert(this%tetra_simplex%sdim > 0)
622
623 ns = this%nspins
624 assert(ns > 0)
625 assert(mod(nik, ns) == 0)
626
627 nik_red = nik / ns
628 assert(maxval(this%tetra_simplex%simplices) <= nik_red)
629
630 nvertices = this%tetra_simplex%rdim + 1
631 assert(nvertices > 0)
632 assert(nvertices <= this%tetra_simplex%sdim)
633
634 occupations(:, :) = m_zero
635 !$omp parallel do collapse(2) private(ist, ii, is, ll, ik, e_simplex, w_simplex, dos_simplex) reduction(+:occupations)
636 do ist = 1, nst
637 do ii = 1, this%tetra_simplex%n_simplices
638 do is = 0, ns - 1
639 do ll = 1, this%tetra_simplex%sdim
640 ik = ns * (this%tetra_simplex%simplices(ii, ll) - 1) + 1
641 e_simplex(ll) = eigenvalues(ist, ik + is)
642 end do
643 w_simplex(:) = m_zero
644
645 call simplex_weights(this%tetra_simplex%rdim, e_simplex(1:this%tetra_simplex%sdim), this%e_fermi, &
646 w_simplex(1:nvertices), dos_simplex(1:nvertices))
647
648 do ll = 1, nvertices
649 ik = ns * (this%tetra_simplex%simplices(ii, ll) - 1) + 1
650 assert(kweights(ik + is) > m_epsilon)
651 occupations(ist, ik + is) = occupations(ist, ik + is) + this%el_per_state * &
652 w_simplex(ll) / (this%tetra_simplex%n_points * kweights(ik + is))
653 end do
654 end do
655 end do
656 end do
657 !$omp end parallel do
658 end block
659 else
660 dsmear = max(1e-14_real64, this%dsmear)
661 if (this%photodop) then
662 dsmear_cond = max(1e-14_real64, this%dsmear_cond)
663 do ik = 1, nik
664 do ist = 1, nst
665 if (ist < this%photodop_bandmin) then
666 ! valence electrons
667 xx = (this%e_fermi - eigenvalues(ist, ik))/dsmear
668 else
669 ! conduction electrons
670 xx = (this%e_fermi_cond - eigenvalues(ist, ik))/dsmear_cond
671 end if
672 occupations(ist, ik) = smear_step_function(this, xx) * this%el_per_state
673 end do
674 end do
675 else
676 do ik = 1, nik
677 do ist = 1, nst
678 xx = (this%e_fermi - eigenvalues(ist, ik))/dsmear
679 occupations(ist, ik) = smear_step_function(this, xx) * this%el_per_state
680 end do
681 end do
682 end if
683 end if
684
686 end subroutine smear_fill_occupations
687
688 !--------------------------------------------------
689 real(real64) function smear_calc_entropy(this, eigenvalues, &
690 nik, nst, kweights, occ) result(entropy)
691 type(smear_t), intent(in) :: this
692 real(real64), contiguous, intent(in) :: eigenvalues(:,:)
693 real(real64), contiguous, intent(in) :: kweights(:)
694 integer, intent(in) :: nik, nst
695 real(real64), contiguous, intent(in) :: occ(:, :)
696
697 integer :: ist, ik
698 real(real64) :: dsmear, xx, term, ff
699
700 push_sub(smear_calc_entropy)
701
702 entropy = m_zero
703
704 if (this%method == smear_fixed_occ .or. this%method == smear_semiconductor) then
705 ! Fermi-Dirac entropy, not quite the same as will be obtained with true smearing
706 ! RM Wentzcovitch, JL Martins, and PB Allen, Phys. Rev. B 45, 11372 (1992) eqn (5)
707 ! also N Marzari PhD thesis p 117, http://quasiamore.mit.edu/phd/Marzari_PhD.pdf
708 do ik = 1, nik
709 do ist = 1, nst
710 ff = occ(ist, ik) / this%el_per_state
711 if (ff > m_zero .and. ff < m_one) then
712 term = ff * log(ff) + (1 - ff) * log(1 - ff)
713 else ! we have semiconducting smearing, or perverse occupations as in Methfessel-Paxton
714 term = m_zero
715 end if
716 entropy = entropy - kweights(ik) * this%el_per_state * term
717 end do
718 end do
719 else
720 dsmear = max(1e-14_real64, this%dsmear)
721
722 do ik = 1, nik
723 do ist = 1, nst
724 if (eigenvalues(ist, ik) < huge(m_one)) then
725 xx = (this%e_fermi - eigenvalues(ist, ik)) / dsmear
726 entropy = entropy - kweights(ik) * this%el_per_state * &
727 smear_entropy_function(this, xx)
728 end if
729 end do
730 end do
731 end if
732
733 pop_sub(smear_calc_entropy)
734 end function smear_calc_entropy
735
736
737 ! ---------------------------------------------------------
738 real(real64) function smear_delta_function(this, xx) result(deltaf)
739 type(smear_t), intent(in) :: this
740 real(real64), intent(in) :: xx
741
742 real(real64), parameter :: maxarg = 200.0_real64
743 real(real64) :: xp, arg, hd, hp, aa
744 integer :: ii, ni
745
746 ! no PUSH_SUB, called too often
747
748 ! smear_delta_function is not defined for SMEAR_FIXED_OCC
749 assert(this%method /= smear_fixed_occ)
750
751 deltaf = m_zero
752 select case (this%method)
754 if (abs(xx) <= m_epsilon) then
755 deltaf = this%ef_occ
756 end if
757
758 case (smear_fermi_dirac)
759 if (abs(xx) <= 36.0_real64) then
760 deltaf = m_one / (m_two + exp(-xx) + exp(xx))
761 end if
762
763 case (smear_cold)
764 xp = xx - m_one / sqrt(m_two)
765 arg = min(maxarg, xp**2)
766
767 deltaf = exp(-arg) / sqrt(m_pi) * (m_two - sqrt(m_two) * xx)
768
770 arg = min(maxarg, xx**2)
771 deltaf = exp(-arg) / sqrt(m_pi)
772
773 if (this%MP_n > 0) then ! recursion
774 hd = m_zero
775 hp = exp(-arg)
776 ni = 0
777 aa = m_one / sqrt(m_pi)
778 do ii = 1, this%MP_n
779 hd = m_two * xx * hp - m_two * ni * hd
780 ni = ni + 1
781 aa = -aa / (m_four * ii)
782 hp = m_two * xx * hd - m_two * ni * hp
783 ni = ni + 1
784 deltaf = deltaf + aa * hp
785 end do
786 end if
787
788 case (smear_spline)
789 xp = abs(xx) + m_one / sqrt(m_two)
790 deltaf = sqrt(m_e) * xp * exp(-xp * xp)
791
792 case (smear_gaussian)
793 deltaf = exp(-xx * xx) / sqrt(m_pi)
794
795 case (smear_lorentzian)
796 deltaf = m_one / (m_pi * (xx * xx + m_one))
797
798 end select
799
800 end function smear_delta_function
801
802
803 ! ---------------------------------------------------------
804 real(real64) function smear_step_function(this, xx) result(stepf)
805 type(smear_t), intent(in) :: this
806 real(real64), intent(in) :: xx
807
808 real(real64), parameter :: maxarg = 200.0_real64
809 real(real64) :: xp, arg, hd, hp, aa
810 integer :: ii, ni
811
812 push_sub(smear_step_function)
813
814 ! smear_step_function is not defined for SMEAR_FIXED_OCC
815 assert(this%method /= smear_fixed_occ)
816
817 stepf = m_zero
818 select case (this%method)
820 if (xx > m_zero) then
821 stepf = m_one
822 else if (abs(xx) <= m_epsilon) then
823 stepf = this%ef_occ
824 end if
825
826 case (smear_fermi_dirac)
827 if (xx > maxarg) then
828 stepf = m_one
829 else if (xx > -maxarg) then
830 stepf = m_one / (m_one + exp(-xx))
831 end if
832
834 xp = xx - m_one / sqrt(m_two)
835 arg = min(maxarg, xp**2)
836
837 stepf = m_half * erf(xp) + &
838 m_one / sqrt(m_two * m_pi) * exp(-arg) + m_half
839
841 stepf = m_half * erfc(-xx)
842
843 if (this%MP_n > 0) then ! recursion
844 hd = m_zero
845 arg = min(maxarg, xx**2)
846 hp = exp(-arg)
847 ni = 0
848 aa = m_one / sqrt(m_pi)
849 do ii = 1, this%MP_n
850 hd = m_two * xx * hp - m_two * ni * hd
851 ni = ni + 1
852 aa = -aa / (m_four * ii)
853 stepf = stepf - aa * hd
854 hp = m_two * xx * hd - m_two * ni * hp
855 ni = ni + 1
856 end do
857 end if
858
859 case (smear_spline)
860 if (xx <= m_zero) then
861 xp = xx - m_one / sqrt(m_two)
862 stepf = m_half * sqrt(m_e) * exp(-xp * xp)
863 else
864 xp = xx + m_one / sqrt(m_two)
865 stepf = m_one - m_half * sqrt(m_e) * exp(-xp * xp)
866 end if
867
868 case (smear_gaussian)
869 stepf = m_half * erfc(-xx)
870
871 case (smear_lorentzian)
872 stepf = atan(xx) / m_pi + m_half
873
874 end select
875
876 pop_sub(smear_step_function)
877 end function smear_step_function
878
879
880 ! ---------------------------------------------------------
882 real(real64) function smear_entropy_function(this, xx) result(entropyf)
883 type(smear_t), intent(in) :: this
884 real(real64), intent(in) :: xx
885
886 real(real64), parameter :: maxarg = 200.0_real64
887 real(real64) :: xp, arg, hd, hp, hpm1, aa
888 integer :: ii, ni
889
890 push_sub(smear_entropy_function)
891
892 ! smear_entropy_function is not defined for SMEAR_FIXED_OCC
893 assert(this%method /= smear_fixed_occ)
894
895 entropyf = m_zero
896 select case (this%method)
898
900 if (abs(xx) <= 36.0_real64) then
901 xp = m_one / (m_one + exp(-xx))
902 entropyf = xp * log(xp) + (m_one - xp) * log(m_one - xp)
903 end if
904
905 case (smear_cold)
906 xp = xx - m_one / sqrt(m_two)
907 arg = min(maxarg, xp**2)
908
909 entropyf = m_one / sqrt(m_two * m_pi) * xp * exp(-arg)
910
912 arg = min(maxarg, xx**2)
913 entropyf = -m_half * exp(-arg) / sqrt(m_pi)
914
915 if (this%MP_n > 0) then ! recursion
916 hd = m_zero
917 hp = exp(-arg)
918 ni = 0
919 aa = m_one / sqrt(m_pi)
920 do ii = 1, this%MP_n
921 hd = m_two * xx * hp - m_two * ni * hd
922 ni = ni + 1
923 hpm1 = hp
924 hp = m_two * xx * hd - m_two * ni * hp
925 ni = ni + 1
926 aa = -aa / (m_four * ii)
927 entropyf = entropyf - aa * (m_half * hp + hpm1 * ni)
928 end do
929 end if
930
931 case (smear_spline)
932 xp = abs(xx) + m_one / sqrt(m_two)
933 entropyf = -sqrt(m_e) * (abs(xx) * exp(-xp * xp) / m_two + sqrt(m_pi) / m_four * erfc(xp))
934
935 case (smear_gaussian)
936 entropyf = -exp(-xx * xx) / m_two / sqrt(m_pi)
937
938 case (smear_lorentzian)
939 entropyf = m_ninf
940
941 end select
942
944 end function smear_entropy_function
945
946
947 ! ---------------------------------------------------------
948 logical pure function smear_is_semiconducting(this) result(answer)
949 type(smear_t), intent(in) :: this
950
951 answer = this%method == smear_semiconductor
952
953 end function smear_is_semiconducting
954
955 subroutine smear_write_info(this, namespace, iunit)
956 type(smear_t), intent(in) :: this
957 type(namespace_t), intent(in) :: namespace
958 integer, optional, intent(in) :: iunit
959
960
961 if (this%method /= smear_semiconductor .and. this%method /= smear_fixed_occ) then
962 if (this%photodop) then
963 write(message(1), '(a,f12.6,1x,a)') "Fermi energy (valence ) = ", &
964 units_from_atomic(units_out%energy, this%e_fermi), units_abbrev(units_out%energy)
965 write(message(2), '(a,f12.6,1x,a)') "Fermi energy (conduction) = ", &
966 units_from_atomic(units_out%energy, this%e_fermi_cond), units_abbrev(units_out%energy)
967 call messages_info(2, iunit=iunit, namespace=namespace)
968 else
969 write(message(1), '(a,f12.6,1x,a)') "Fermi energy = ", &
970 units_from_atomic(units_out%energy, this%e_fermi), units_abbrev(units_out%energy)
971 call messages_info(1, iunit=iunit, namespace=namespace)
972 end if
973 end if
974
975 end subroutine smear_write_info
976
978end module smear_oct_m
979
980!! Local Variables:
981!! mode: f90
982!! coding: utf-8
983!! End:
This is the common interface to a sorting routine. It performs the shell algorithm,...
Definition: sort.F90:156
double log(double __x) __attribute__((__nothrow__
double exp(double __x) __attribute__((__nothrow__
double atan(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double floor(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public p_ry
Definition: global.F90:239
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
real(real64), parameter, public m_min_occ
Minimal occupation that is considered to be non-zero.
Definition: global.F90:227
integer function, public kpoints_kweight_denominator(this)
Definition: kpoints.F90:1815
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
integer, parameter, public smear_tetrahedra_opt
Definition: smear.F90:176
real(real64) function, public smear_calc_entropy(this, eigenvalues, nik, nst, kweights, occ)
Definition: smear.F90:786
integer, parameter, public smear_tetrahedra
Definition: smear.F90:176
subroutine, public smear_find_fermi_energy(this, namespace, eigenvalues, occupations, qtot, nik, nst, kweights)
Definition: smear.F90:380
real(real64) function, public smear_entropy_function(this, xx)
This function is defined as .
Definition: smear.F90:978
real(real64) function, public smear_delta_function(this, xx)
Definition: smear.F90:834
integer, parameter, public smear_fermi_dirac
Definition: smear.F90:176
subroutine bisection_find_fermi_energy_tetra(this, namespace, tol, eigenvalues, nik, nst, q_in, e_fermi)
Finds the Fermi energy using the tetrahedron method via bisection.
Definition: smear.F90:594
integer, parameter, public smear_methfessel_paxton
Definition: smear.F90:176
subroutine, public smear_write_info(this, namespace, iunit)
Definition: smear.F90:1051
real(real64) function, public smear_step_function(this, xx)
Definition: smear.F90:900
integer, parameter, public smear_semiconductor
Definition: smear.F90:176
subroutine, public smear_fill_occupations(this, eigenvalues, occupations, kweights, nik, nst)
Definition: smear.F90:675
integer, parameter, public smear_lorentzian
Definition: smear.F90:176
subroutine, public smear_copy(to, from)
Definition: smear.F90:349
integer, parameter, public smear_fixed_occ
Definition: smear.F90:176
integer, parameter, public smear_spline
Definition: smear.F90:176
subroutine bisection_find_fermi_energy(this, namespace, dsmear_in, tol, eigenvalues, kweights, nik, q_in, start_band, end_band, e_fermi, ef_occ)
Definition: smear.F90:520
subroutine, public smear_init(this, namespace, ispin, fixed_occ, integral_occs, kpoints)
Definition: smear.F90:194
integer, parameter, public smear_cold
Definition: smear.F90:176
logical pure function, public smear_is_semiconducting(this)
Definition: smear.F90:1044
integer, parameter, public smear_gaussian
Definition: smear.F90:176
This module is intended to contain "only mathematical" functions and procedures.
Definition: sort.F90:119
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
type(unit_system_t), public units_inp
the units systems for reading and writing
int true(void)