Line data Source code
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 :
8 : ! **************************************************************************************************
9 : !> \brief module that contains the algorithms to perform an iterative
10 : !> diagonalization by the block-Davidson approach
11 : !> P. Blaha, et al J. Comp. Physics, 229, (2010), 453-460
12 : !> Iterative diagonalization in augmented plane wave based
13 : !> methods in electronic structure calculations
14 : !> \par History
15 : !> 05.2011 created [MI]
16 : !> \author MI
17 : ! **************************************************************************************************
18 : MODULE qs_block_davidson_types
19 :
20 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
21 : cp_fm_struct_release,&
22 : cp_fm_struct_type
23 : USE cp_fm_types, ONLY: cp_fm_create,&
24 : cp_fm_release,&
25 : cp_fm_type
26 : USE input_section_types, ONLY: section_vals_type,&
27 : section_vals_val_get
28 : USE kinds, ONLY: dp
29 : #include "./base/base_uses.f90"
30 :
31 : IMPLICIT NONE
32 : PRIVATE
33 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_block_davidson_types'
34 :
35 : PUBLIC :: block_davidson_allocate, block_davidson_deallocate, block_davidson_release, &
36 : block_davidson_env_create, davidson_type
37 :
38 : TYPE davidson_type
39 : INTEGER :: max_iter = -1, prec_type = -1, solver_type = -1, niter_new_prec = -1, first_prec = -1
40 : LOGICAL :: use_sparse_mos = .FALSE.
41 : REAL(KIND=dp) :: conv_percent = -1.0_dp, energy_gap = -1.0_dp, eps_iter = -1.0_dp, &
42 : noise_scale = 100.0_dp
43 : ! adaptive-tolerance ratchet state: the inner threshold of the previous
44 : ! SCF step, carried across steps so that it may only tighten, and the
45 : ! threshold the latest solve actually used (zero: EPS_ADAPT inactive)
46 : REAL(KIND=dp) :: eps_iter_prev = HUGE(1.0_dp), eps_iter_used = 0.0_dp
47 : TYPE(cp_fm_type), POINTER :: H_block_mat => NULL(), H_block_vec => NULL(), &
48 : matrix_z => NULL(), matrix_pz => NULL(), S_block_mat => NULL(), W_block_mat => NULL()
49 : END TYPE davidson_type
50 :
51 : CONTAINS
52 :
53 : ! **************************************************************************************************
54 :
55 : ! **************************************************************************************************
56 : !> \brief creates one Davidson environment per solver channel: for Gamma-point
57 : !> runs a channel is a spin, for K-point runs it is (ikpoint,ispin)
58 : !> following the layout of qs_ot_channel_index.
59 : !> \param bdav_env ...
60 : !> \param nchannels number of channels (spins at Gamma, local kpoints*spins with K points)
61 : !> \param scf_section ...
62 : ! **************************************************************************************************
63 38 : SUBROUTINE block_davidson_env_create(bdav_env, nchannels, scf_section)
64 :
65 : TYPE(davidson_type), DIMENSION(:), POINTER :: bdav_env
66 : INTEGER, INTENT(IN) :: nchannels
67 : TYPE(section_vals_type), POINTER :: scf_section
68 :
69 : INTEGER :: ichannel
70 : TYPE(davidson_type) :: settings
71 :
72 0 : CPASSERT(.NOT. ASSOCIATED(bdav_env))
73 : ! the solver settings are channel independent, so they are read once and
74 : ! then copied into every channel
75 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%PRECONDITIONER", &
76 38 : i_val=settings%prec_type)
77 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%PRECOND_SOLVER", &
78 38 : i_val=settings%solver_type)
79 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%ENERGY_GAP", &
80 38 : r_val=settings%energy_gap)
81 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%NEW_PREC_EACH", &
82 38 : i_val=settings%niter_new_prec)
83 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%MAX_ITER", &
84 38 : i_val=settings%max_iter)
85 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%EPS_ITER", &
86 38 : r_val=settings%eps_iter)
87 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%FIRST_PREC", &
88 38 : i_val=settings%first_prec)
89 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%CONV_MOS_PERCENT", &
90 38 : r_val=settings%conv_percent)
91 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%NOISE_SCALE", &
92 38 : r_val=settings%noise_scale)
93 : CALL section_vals_val_get(scf_section, "DIAGONALIZATION%DAVIDSON%SPARSE_MOS", &
94 38 : l_val=settings%use_sparse_mos)
95 :
96 184 : ALLOCATE (bdav_env(nchannels))
97 108 : DO ichannel = 1, nchannels
98 : ! davidson_type has default initializers, so allocation leaves the
99 : ! matrix pointers disassociated
100 108 : bdav_env(ichannel) = settings
101 :
102 : END DO
103 :
104 38 : END SUBROUTINE block_davidson_env_create
105 :
106 : ! **************************************************************************************************
107 : !> \brief ...
108 : !> \param bdav_env ...
109 : !> \param mo_coeff ...
110 : !> \param nao ...
111 : !> \param nmo ...
112 : ! **************************************************************************************************
113 20 : SUBROUTINE block_davidson_allocate(bdav_env, mo_coeff, nao, nmo)
114 :
115 : TYPE(davidson_type) :: bdav_env
116 : TYPE(cp_fm_type), INTENT(IN) :: mo_coeff
117 : INTEGER, INTENT(IN) :: nao, nmo
118 :
119 : CHARACTER(len=*), PARAMETER :: routineN = 'block_davidson_allocate'
120 :
121 : INTEGER :: handle, nmox2
122 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
123 :
124 20 : CALL timeset(routineN, handle)
125 20 : NULLIFY (fm_struct_tmp)
126 :
127 20 : nmox2 = 2*nmo
128 :
129 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nao, ncol_global=nmo, &
130 : para_env=mo_coeff%matrix_struct%para_env, &
131 20 : context=mo_coeff%matrix_struct%context)
132 20 : NULLIFY (bdav_env%matrix_z, bdav_env%matrix_pz)
133 20 : ALLOCATE (bdav_env%matrix_z, bdav_env%matrix_pz)
134 20 : CALL cp_fm_create(bdav_env%matrix_z, fm_struct_tmp, name="Z_mat")
135 20 : CALL cp_fm_create(bdav_env%matrix_pz, fm_struct_tmp, name="Z_mat")
136 20 : CALL cp_fm_struct_release(fm_struct_tmp)
137 :
138 20 : CALL timestop(handle)
139 :
140 20 : END SUBROUTINE block_davidson_allocate
141 :
142 : ! **************************************************************************************************
143 : !> \brief ...
144 : !> \param bdav_env ...
145 : ! **************************************************************************************************
146 50 : SUBROUTINE block_davidson_deallocate(bdav_env)
147 :
148 : TYPE(davidson_type), DIMENSION(:), POINTER :: bdav_env
149 :
150 : INTEGER :: ichannel, nchannels
151 :
152 50 : IF (ASSOCIATED(bdav_env)) THEN
153 :
154 50 : nchannels = SIZE(bdav_env)
155 140 : DO ichannel = 1, nchannels
156 :
157 : ! K-point channels carry settings only (the complex scratch is local
158 : ! to generate_extended_space_c), so the pointers may stay disassociated
159 90 : IF (ASSOCIATED(bdav_env(ichannel)%matrix_z)) THEN
160 20 : CALL cp_fm_release(bdav_env(ichannel)%matrix_z)
161 20 : DEALLOCATE (bdav_env(ichannel)%matrix_z)
162 : END IF
163 90 : IF (ASSOCIATED(bdav_env(ichannel)%matrix_pz)) THEN
164 20 : CALL cp_fm_release(bdav_env(ichannel)%matrix_pz)
165 20 : DEALLOCATE (bdav_env(ichannel)%matrix_pz)
166 : END IF
167 140 : NULLIFY (bdav_env(ichannel)%matrix_z, bdav_env(ichannel)%matrix_pz)
168 :
169 : END DO
170 :
171 : END IF
172 :
173 50 : END SUBROUTINE block_davidson_deallocate
174 :
175 : ! **************************************************************************************************
176 : !> \brief ...
177 : !> \param bdav_env ...
178 : ! **************************************************************************************************
179 38 : SUBROUTINE block_davidson_release(bdav_env)
180 :
181 : TYPE(davidson_type), DIMENSION(:), POINTER :: bdav_env
182 :
183 : INTEGER :: ispin, nspins
184 :
185 38 : IF (ASSOCIATED(bdav_env)) THEN
186 :
187 38 : nspins = SIZE(bdav_env)
188 108 : DO ispin = 1, nspins
189 :
190 108 : IF (ASSOCIATED(bdav_env(ispin)%matrix_z)) THEN
191 0 : CALL cp_fm_release(bdav_env(ispin)%matrix_z)
192 0 : CALL cp_fm_release(bdav_env(ispin)%matrix_pz)
193 0 : DEALLOCATE (bdav_env(ispin)%matrix_z, bdav_env(ispin)%matrix_pz)
194 0 : NULLIFY (bdav_env(ispin)%matrix_z, bdav_env(ispin)%matrix_pz)
195 : END IF
196 :
197 : END DO
198 38 : DEALLOCATE (bdav_env)
199 :
200 : END IF
201 :
202 38 : END SUBROUTINE block_davidson_release
203 :
204 0 : END MODULE qs_block_davidson_types
|