(git:5e7fe52)
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
19 USE smearing_utils, ONLY: smearkp,&
21
22 IMPLICIT NONE
23
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
28 TYPE(smear_type) :: smear
29
31 smear%do_smear = .true.
32 smear%eps_fermi_dirac = 1.0e-5_dp
33 occupation = 0.0_dp
34 occupation(1, :, :) = 1.0_dp
35 weight = [1.0_dp, 0.0_dp]
36
37 occupation(1, 2, 1) = 0.5_dp
38 occupation(3, 2, 2) = 0.5_dp
39 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
45
46 weight(2) = 0.25_dp
47 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
53
54 occupation = 0.0_dp
55 occupation(1, :, 1) = 2.0_dp
56 CALL kpoint_smearing_edge_status(occupation(:, :, 1:1), weight, smear, 1, has_weight, &
57 first_fractional, last_occupied)
58 IF (first_fractional) error stop "Restricted full occupation was classified as fractional"
59
60 weight = 0.0_dp
61 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
65 END IF
66
67 smear%do_smear = .false.
68 weight = 1.0_dp
69 CALL kpoint_smearing_edge_status(occupation, weight, smear, 2, has_weight, &
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"
73 END IF
74
77
78CONTAINS
79
80! **************************************************************************************************
81!> \brief Check the fixed-N occupation response for every supported K-point smearing method.
82! **************************************************************************************************
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
87
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, &
93 predicted_response
94 REAL(kind=dp), &
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
98
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])
106
107 DO imethod = 1, SIZE(methods)
108 CALL smearkp(occupation, mu, kts, eigenvalue, TARGET, kpoint_weight, sigma, maxocc, &
109 methods(imethod))
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)
115 END DO
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"
119 END IF
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"
123 END IF
125 reshape(response, [nstate*nkpoint]), response_sum, hessian)
126
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)
137 END DO
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"
143 END DO
144
145 END SUBROUTINE test_fixed_n_smearing_response
146
147END PROGRAM kpoint_smearing_unittest
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
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
orbital transformations
Definition qs_ot.F:15
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
Definition qs_ot.F:183
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