(git:6344619)
Loading...
Searching...
No Matches
kpoint_smearing_unittest.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
12 smear_mp,&
14 USE kinds, ONLY: dp
18 USE smearing_utils, ONLY: smearkp,&
22
23 IMPLICIT NONE
24
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
29 TYPE(smear_type) :: smear
30
32 smear%do_smear = .true.
33 smear%eps_fermi_dirac = 1.0e-5_dp
34 occupation = 0.0_dp
35 occupation(1, :, :) = 1.0_dp
36 weight = [1.0_dp, 0.0_dp]
37
38 occupation(1, 2, 1) = 0.5_dp
39 occupation(3, 2, 2) = 0.5_dp
40 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
46
47 weight(2) = 0.25_dp
48 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
54
55 occupation = 0.0_dp
56 occupation(1, :, 1) = 2.0_dp
57 CALL kpoint_smearing_edge_status(occupation(:, :, 1:1), weight, smear, 1, has_weight, &
58 first_fractional, last_occupied)
59 IF (first_fractional) error stop "Restricted full occupation was classified as fractional"
60
61 weight = 0.0_dp
62 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
66 END IF
67
68 smear%do_smear = .false.
69 weight = 1.0_dp
70 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
74 END IF
75
76 CALL test_fixed_n_smearing_response()
79
80CONTAINS
81
82! **************************************************************************************************
83!> \brief Check fractional, zero, integer-preserving, and unconstrained spin targets.
84! **************************************************************************************************
86 REAL(kind=dp), DIMENSION(2) :: targets
87
88 IF (smearing_separate_spin(-100.0_dp)) error stop "Unconstrained spin was fixed"
89 IF (.NOT. smearing_separate_spin(-1.0_dp)) error stop "Integer spin populations were released"
90 IF (.NOT. smearing_separate_spin(0.0_dp)) error stop "Zero magnetization was not constrained"
91 IF (.NOT. smearing_separate_spin(0.5_dp)) error stop "Fractional magnetization was not constrained"
92 targets(:) = smearing_spin_targets([3, 1], -1.0_dp)
93 IF (maxval(abs(targets - [3.0_dp, 1.0_dp])) > 1.0e-14_dp) THEN
94 error stop "Integer spin targets changed"
95 END IF
96 targets(:) = smearing_spin_targets([3, 1], 0.0_dp)
97 IF (maxval(abs(targets - 2.0_dp)) > 1.0e-14_dp) error stop "Zero-moment targets are wrong"
98 targets(:) = smearing_spin_targets([3, 1], 0.5_dp)
99 IF (maxval(abs(targets - [2.25_dp, 1.75_dp])) > 1.0e-14_dp) THEN
100 error stop "Fractional spin targets were rounded"
101 END IF
102 END SUBROUTINE test_fixed_spin_populations
103
104! **************************************************************************************************
105!> \brief Check the fixed-N occupation response for every supported K-point smearing method.
106! **************************************************************************************************
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
111
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
120
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])
128
129 DO imethod = 1, SIZE(methods)
130 CALL smearkp(occupation, mu, kts, eigenvalue, TARGET, kpoint_weight, sigma, maxocc, &
131 methods(imethod))
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)
137 END DO
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"
141 END IF
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"
145 END IF
146 flat_response = reshape(response, [nstate*nkpoint])
147
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)
158 END DO
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)))
163 ! A common energy shift leaves fixed-N occupations unchanged.
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"
168 END DO
169
170 END SUBROUTINE test_fixed_n_smearing_response
171
172END PROGRAM kpoint_smearing_unittest
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
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public smear_fermi_dirac
integer, parameter, public smear_gaussian
integer, parameter, public smear_mv
integer, parameter, public smear_mp
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
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