24 LOGICAL :: first_fractional, has_weight, last_occupied
25 LOGICAL,
DIMENSION(2) :: last_occupied_spin
26 REAL(kind=
dp),
DIMENSION(2) :: weight
27 REAL(kind=
dp),
DIMENSION(3, 2, 2) :: occupation
31 smear%do_smear = .true.
32 smear%eps_fermi_dirac = 1.0e-5_dp
34 occupation(1, :, :) = 1.0_dp
35 weight = [1.0_dp, 0.0_dp]
37 occupation(1, 2, 1) = 0.5_dp
38 occupation(3, 2, 2) = 0.5_dp
40 first_fractional, last_occupied, last_occupied_spin)
41 IF (.NOT. has_weight) error stop
"Positive K-point weight was not detected"
42 IF (first_fractional) error stop
"Zero-weight first-band occupation was included"
43 IF (last_occupied) error stop
"Zero-weight last-band occupation was included"
44 IF (any(last_occupied_spin)) error stop
"Zero-weight spin edge was included"
48 first_fractional, last_occupied, last_occupied_spin)
49 IF (.NOT. first_fractional) error stop
"Fractional first band was not detected"
50 IF (.NOT. last_occupied) error stop
"Occupied last band was not detected"
51 IF (last_occupied_spin(1)) error stop
"Wrong occupied spin edge was reported"
52 IF (.NOT. last_occupied_spin(2)) error stop
"Occupied spin edge was not reported"
55 occupation(1, :, 1) = 2.0_dp
57 first_fractional, last_occupied)
58 IF (first_fractional) error stop
"Restricted full occupation was classified as fractional"
62 first_fractional, last_occupied, last_occupied_spin)
63 IF (has_weight .OR. first_fractional .OR. last_occupied)
THEN
64 error stop
"Zero-weight K-point set produced an edge status"
67 smear%do_smear = .false.
70 first_fractional, last_occupied, last_occupied_spin)
71 IF (has_weight .OR. first_fractional .OR. last_occupied)
THEN
72 error stop
"Disabled smearing produced an edge status"
84 INTEGER,
PARAMETER :: nkpoint = 2, nstate = 5
85 REAL(kind=
dp),
PARAMETER :: fd_step = 1.0e-6_dp, maxocc = 2.0_dp, &
86 sigma = 0.15_dp,
TARGET = 4.3_dp
88 INTEGER :: ikpoint, imethod
89 INTEGER,
DIMENSION(4) :: methods
90 REAL(kind=
dp) :: error, kts, mu, response_sum
91 REAL(kind=
dp),
DIMENSION(nkpoint) :: kpoint_weight
92 REAL(kind=
dp),
DIMENSION(nstate*nkpoint) :: fd_response, flat_direction, &
95 DIMENSION(nstate*nkpoint, nstate*nkpoint) :: hessian
96 REAL(kind=
dp),
DIMENSION(nstate, nkpoint) :: direction, eigenvalue, eigenvalue_minus, &
97 eigenvalue_plus, occupation, occupation_minus, occupation_plus, response
100 kpoint_weight(:) = [0.4_dp, 0.6_dp]
101 eigenvalue(:, 1) = [-0.38_dp, -0.14_dp, 0.02_dp, 0.23_dp, 0.52_dp]
102 eigenvalue(:, 2) = [-0.31_dp, -0.08_dp, 0.07_dp, 0.28_dp, 0.61_dp]
103 direction(:, 1) = [0.13_dp, -0.07_dp, 0.11_dp, -0.04_dp, 0.09_dp]
104 direction(:, 2) = [-0.08_dp, 0.05_dp, -0.12_dp, 0.06_dp, -0.03_dp]
105 flat_direction(:) = reshape(direction, [nstate*nkpoint])
107 DO imethod = 1,
SIZE(methods)
108 CALL smearkp(occupation, mu, kts, eigenvalue,
TARGET, kpoint_weight, sigma, maxocc, &
110 DO ikpoint = 1, nkpoint
112 response(:, ikpoint), occupation(:, ikpoint), eigenvalue(:, ikpoint), mu, sigma, &
113 maxocc, nstate, methods(imethod))
114 response(:, ikpoint) = kpoint_weight(ikpoint)*response(:, ikpoint)
116 response_sum = sum(response)
117 IF (abs(response_sum) <= epsilon(response_sum))
THEN
118 error stop
"Singular fixed-N smearing response in unit test"
120 IF ((methods(imethod) ==
smear_mp .OR. methods(imethod) ==
smear_mv) .AND. &
121 .NOT. any(response < 0.0_dp))
THEN
122 error stop
"Signed smearing-response branch was not exercised"
125 reshape(response, [nstate*nkpoint]), response_sum, hessian)
127 eigenvalue_plus(:, :) = eigenvalue + fd_step*direction
128 eigenvalue_minus(:, :) = eigenvalue - fd_step*direction
129 CALL smearkp(occupation_plus, mu, kts, eigenvalue_plus,
TARGET, kpoint_weight, sigma, &
130 maxocc, methods(imethod))
131 CALL smearkp(occupation_minus, mu, kts, eigenvalue_minus,
TARGET, kpoint_weight, sigma, &
132 maxocc, methods(imethod))
133 DO ikpoint = 1, nkpoint
134 fd_response((ikpoint - 1)*nstate + 1:ikpoint*nstate) = &
135 kpoint_weight(ikpoint)*(occupation_plus(:, ikpoint) - &
136 occupation_minus(:, ikpoint))/(2.0_dp*fd_step)
138 predicted_response(:) = -matmul(hessian, flat_direction)
139 error = maxval(abs(fd_response - predicted_response))
140 error = max(error, abs(sum(fd_response)))
141 error = max(error, maxval(abs(matmul(hessian, spread(1.0_dp, 1, nstate*nkpoint)))))
142 IF (error > 2.0e-6_dp) error stop
"Fixed-N smearing response finite difference failed"
subroutine test_fixed_n_smearing_response()
Check the fixed-N occupation response for every supported K-point smearing method.
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
pure subroutine, public qs_ot_fixed_n_energy_hessian(response_weight, fixed_n_weight_sum, hessian)
dense fixed-N occupation Hessian in auxiliary-energy coordinates
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...
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