25 LOGICAL :: first_fractional, has_weight, last_occupied
26 LOGICAL,
DIMENSION(2) :: last_occupied_spin
27 REAL(kind=
dp),
DIMENSION(2) :: weight
28 REAL(kind=
dp),
DIMENSION(3, 2, 2) :: occupation
32 smear%do_smear = .true.
33 smear%eps_fermi_dirac = 1.0e-5_dp
35 occupation(1, :, :) = 1.0_dp
36 weight = [1.0_dp, 0.0_dp]
38 occupation(1, 2, 1) = 0.5_dp
39 occupation(3, 2, 2) = 0.5_dp
41 first_fractional, last_occupied, last_occupied_spin)
42 IF (.NOT. has_weight) error stop
"Positive K-point weight was not detected"
43 IF (first_fractional) error stop
"Zero-weight first-band occupation was included"
44 IF (last_occupied) error stop
"Zero-weight last-band occupation was included"
45 IF (any(last_occupied_spin)) error stop
"Zero-weight spin edge was included"
49 first_fractional, last_occupied, last_occupied_spin)
50 IF (.NOT. first_fractional) error stop
"Fractional first band was not detected"
51 IF (.NOT. last_occupied) error stop
"Occupied last band was not detected"
52 IF (last_occupied_spin(1)) error stop
"Wrong occupied spin edge was reported"
53 IF (.NOT. last_occupied_spin(2)) error stop
"Occupied spin edge was not reported"
56 occupation(1, :, 1) = 2.0_dp
58 first_fractional, last_occupied)
59 IF (first_fractional) error stop
"Restricted full occupation was classified as fractional"
63 first_fractional, last_occupied, last_occupied_spin)
64 IF (has_weight .OR. first_fractional .OR. last_occupied)
THEN
65 error stop
"Zero-weight K-point set produced an edge status"
68 smear%do_smear = .false.
71 first_fractional, last_occupied, last_occupied_spin)
72 IF (has_weight .OR. first_fractional .OR. last_occupied)
THEN
73 error stop
"Disabled smearing produced an edge status"
76 CALL test_fixed_n_smearing_response()
86 REAL(kind=
dp),
DIMENSION(2) :: targets
93 IF (maxval(abs(targets - [3.0_dp, 1.0_dp])) > 1.0e-14_dp)
THEN
94 error stop
"Integer spin targets changed"
97 IF (maxval(abs(targets - 2.0_dp)) > 1.0e-14_dp) error stop
"Zero-moment targets are wrong"
99 IF (maxval(abs(targets - [2.25_dp, 1.75_dp])) > 1.0e-14_dp)
THEN
100 error stop
"Fractional spin targets were rounded"
107 SUBROUTINE test_fixed_n_smearing_response()
108 INTEGER,
PARAMETER :: nkpoint = 2, nstate = 5
109 REAL(kind=
dp),
PARAMETER :: fd_step = 1.0e-6_dp, maxocc = 2.0_dp, &
110 sigma = 0.15_dp,
TARGET = 4.3_dp
112 INTEGER :: ikpoint, imethod
113 INTEGER,
DIMENSION(4) :: methods
114 REAL(kind=
dp) :: error, kts, mu, response_sum
115 REAL(kind=
dp),
DIMENSION(nkpoint) :: kpoint_weight
116 REAL(kind=
dp),
DIMENSION(nstate*nkpoint) :: fd_response, flat_direction, &
117 flat_response, predicted_response
118 REAL(kind=
dp),
DIMENSION(nstate, nkpoint) :: direction, eigenvalue, eigenvalue_minus, &
119 eigenvalue_plus, occupation, occupation_minus, occupation_plus, response
122 kpoint_weight(:) = [0.4_dp, 0.6_dp]
123 eigenvalue(:, 1) = [-0.38_dp, -0.14_dp, 0.02_dp, 0.23_dp, 0.52_dp]
124 eigenvalue(:, 2) = [-0.31_dp, -0.08_dp, 0.07_dp, 0.28_dp, 0.61_dp]
125 direction(:, 1) = [0.13_dp, -0.07_dp, 0.11_dp, -0.04_dp, 0.09_dp]
126 direction(:, 2) = [-0.08_dp, 0.05_dp, -0.12_dp, 0.06_dp, -0.03_dp]
127 flat_direction(:) = reshape(direction, [nstate*nkpoint])
129 DO imethod = 1,
SIZE(methods)
130 CALL smearkp(occupation, mu, kts, eigenvalue,
TARGET, kpoint_weight, sigma, maxocc, &
132 DO ikpoint = 1, nkpoint
134 response(:, ikpoint), occupation(:, ikpoint), eigenvalue(:, ikpoint), mu, sigma, &
135 maxocc, nstate, methods(imethod))
136 response(:, ikpoint) = kpoint_weight(ikpoint)*response(:, ikpoint)
138 response_sum = sum(response)
139 IF (abs(response_sum) <= epsilon(response_sum))
THEN
140 error stop
"Singular fixed-N smearing response in unit test"
142 IF ((methods(imethod) ==
smear_mp .OR. methods(imethod) ==
smear_mv) .AND. &
143 .NOT. any(response < 0.0_dp))
THEN
144 error stop
"Signed smearing-response branch was not exercised"
146 flat_response = reshape(response, [nstate*nkpoint])
148 eigenvalue_plus(:, :) = eigenvalue + fd_step*direction
149 eigenvalue_minus(:, :) = eigenvalue - fd_step*direction
150 CALL smearkp(occupation_plus, mu, kts, eigenvalue_plus,
TARGET, kpoint_weight, sigma, &
151 maxocc, methods(imethod))
152 CALL smearkp(occupation_minus, mu, kts, eigenvalue_minus,
TARGET, kpoint_weight, sigma, &
153 maxocc, methods(imethod))
154 DO ikpoint = 1, nkpoint
155 fd_response((ikpoint - 1)*nstate + 1:ikpoint*nstate) = &
156 kpoint_weight(ikpoint)*(occupation_plus(:, ikpoint) - &
157 occupation_minus(:, ikpoint))/(2.0_dp*fd_step)
159 predicted_response = -flat_response* &
160 (flat_direction - dot_product(flat_response, flat_direction)/response_sum)
161 error = maxval(abs(fd_response - predicted_response))
162 error = max(error, abs(sum(fd_response)))
164 CALL smearkp(occupation_plus, mu, kts, eigenvalue + 0.37_dp,
TARGET, kpoint_weight, &
165 sigma, maxocc, methods(imethod))
166 error = max(error, maxval(abs(occupation_plus - occupation)))
167 IF (error > 2.0e-6_dp) error stop
"Fixed-N smearing response finite difference failed"
170 END SUBROUTINE test_fixed_n_smearing_response
subroutine test_fixed_spin_populations()
Check fractional, zero, integer-preserving, and unconstrained spin targets.
program kpoint_smearing_unittest
collects all references to literature in CP2K as new algorithms / method are included from literature...
subroutine, public add_all_references()
adds references that can later be cited / printed using the key
Defines the basic variable types.
integer, parameter, public dp
Routines needed for kpoint calculation.
subroutine, public kpoint_smearing_edge_status(wocc, wkp, smear, nspin, has_weight, first_fractional, last_occupied, last_occupied_spin)
summarize whether weighted k-point smearing reaches the available band edges
provides a uniform framework to add references to CP2K cite and output these
subroutine, public remove_all_references()
deallocate the bibliography
parameters that control an scf iteration
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...
pure logical function, public smearing_separate_spin(fixed_mag_mom)
Whether a smearing constraint fixes the separate spin populations.
pure real(kind=dp) function, dimension(2), public smearing_spin_targets(nelectron, fixed_mag_mom)
Resolve real-valued spin targets without rounding a prescribed moment.
subroutine, public smearing_response_weight(gvec, f, e, mu, sigma, maxocc, nstate, method, estate, festate)
Computes the smearing weight vector g_i = -df_i/de_i with mu held fixed.
contains the parameters needed by a scf run