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 Different diagonalization schemes that can be used
10 : !> for the iterative solution of the eigenvalue problem
11 : !> \par History
12 : !> started from routines previously located in the qs_scf module
13 : !> 05.2009
14 : ! **************************************************************************************************
15 : MODULE qs_scf_diagonalization
16 : USE cp_array_utils, ONLY: cp_1d_r_p_type
17 : USE cp_blacs_env, ONLY: cp_blacs_env_type
18 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_column_scale,&
19 : cp_cfm_scale_and_add,&
20 : cp_cfm_scale_and_add_fm
21 : USE cp_cfm_diag, ONLY: cp_cfm_diag_workspace_type,&
22 : cp_cfm_geeig,&
23 : cp_cfm_geeig_canon,&
24 : cp_cfm_geeig_canon_local,&
25 : cp_cfm_geeig_local,&
26 : cp_cfm_heevd,&
27 : cp_cfm_local_workspace_prepare
28 : USE cp_cfm_types, ONLY: cp_cfm_create,&
29 : cp_cfm_release,&
30 : cp_cfm_set_all,&
31 : cp_cfm_to_cfm,&
32 : cp_cfm_to_fm,&
33 : cp_cfm_type,&
34 : cp_fm_to_cfm
35 : USE cp_control_types, ONLY: dft_control_type,&
36 : hairy_probes_type
37 : USE cp_dbcsr_api, ONLY: &
38 : dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_init_p, dbcsr_p_type, &
39 : dbcsr_release_p, dbcsr_set, dbcsr_type, dbcsr_type_symmetric
40 : USE cp_dbcsr_cp2k_link, ONLY: cp_dbcsr_alloc_block_from_nbl
41 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
42 : copy_fm_to_dbcsr,&
43 : cp_dbcsr_sm_fm_multiply,&
44 : dbcsr_allocate_matrix_set
45 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale,&
46 : cp_fm_scale_and_add,&
47 : cp_fm_symm,&
48 : cp_fm_uplo_to_full
49 : USE cp_fm_cholesky, ONLY: cp_fm_cholesky_reduce,&
50 : cp_fm_cholesky_restore
51 : USE cp_fm_diag, ONLY: choose_eigv_solver,&
52 : cp_fm_geeig,&
53 : cp_fm_geeig_canon,&
54 : diag_check_requested,&
55 : direct_generalized_diagonalization
56 : USE cp_fm_pool_types, ONLY: cp_fm_pool_p_type,&
57 : fm_pool_create_fm,&
58 : fm_pool_get_el_struct,&
59 : fm_pool_give_back_fm
60 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
61 : cp_fm_struct_release,&
62 : cp_fm_struct_type
63 : USE cp_fm_types, ONLY: cp_fm_add_to_element,&
64 : cp_fm_create,&
65 : cp_fm_get_info,&
66 : cp_fm_release,&
67 : cp_fm_set_all,&
68 : cp_fm_to_fm,&
69 : cp_fm_type
70 : USE cp_log_handling, ONLY: cp_get_default_logger,&
71 : cp_logger_get_default_unit_nr,&
72 : cp_logger_type
73 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
74 : cp_print_key_unit_nr,&
75 : debug_print_level
76 : USE ieee_arithmetic, ONLY: ieee_is_finite
77 : USE input_constants, ONLY: &
78 : cholesky_dbcsr, cholesky_inverse, cholesky_off, cholesky_reduce, cholesky_restore, &
79 : core_guess, diag_update_method_adiis, general_roks, high_spin_roks, ot_precond_full_all, &
80 : ot_precond_full_kinetic, ot_precond_full_single_inverse, ot_precond_none, &
81 : ot_precond_s_inverse, restart_guess
82 : USE input_cp2k_kpoints, ONLY: lattice_fft_auto,&
83 : lattice_fft_off,&
84 : lattice_fft_on
85 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
86 : section_vals_type
87 : USE kinds, ONLY: dp,&
88 : int_8
89 : USE kpoint_methods, ONLY: kpoint_density_matrices,&
90 : kpoint_density_transform,&
91 : kpoint_set_mo_occupation,&
92 : rskp_grid_type,&
93 : rskp_transform_grid_prepare,&
94 : rskp_transform_grid_release
95 : USE kpoint_types, ONLY: get_kpoint_info,&
96 : kpoint_env_type,&
97 : kpoint_type
98 : USE local_gemm_api, ONLY: LOCAL_GEMM_PU_GPU,&
99 : local_gemm_ctxt_type
100 : USE machine, ONLY: m_flush,&
101 : m_walltime
102 : USE mathconstants, ONLY: gaussi,&
103 : z_one,&
104 : z_zero
105 : USE message_passing, ONLY: mp_para_env_type
106 : USE parallel_gemm_api, ONLY: parallel_gemm
107 : USE preconditioner, ONLY: dbcsr_pair_to_cfm,&
108 : make_preconditioner_complex_full_kinetic,&
109 : make_preconditioner_complex_full_s_inverse,&
110 : prepare_preconditioner,&
111 : restart_preconditioner
112 : USE preconditioner_makes, ONLY: make_complex_full_all,&
113 : make_complex_full_single_inverse
114 : USE preconditioner_types, ONLY: destroy_preconditioner,&
115 : init_preconditioner
116 : USE qs_density_matrices, ONLY: calculate_density_matrix
117 : USE qs_density_mixing_types, ONLY: direct_mixing_nr,&
118 : gspace_mixing_nr
119 : USE qs_diis, ONLY: qs_diis_b_calc_err_kp,&
120 : qs_diis_b_check_i_alloc_kp,&
121 : qs_diis_b_clear,&
122 : qs_diis_b_clear_kp,&
123 : qs_diis_b_info_kp,&
124 : qs_diis_b_step,&
125 : qs_diis_b_step_kp
126 : USE qs_energy_types, ONLY: qs_energy_type
127 : USE qs_environment_types, ONLY: get_qs_env,&
128 : qs_environment_type
129 : USE qs_gspace_mixing, ONLY: gspace_mixing
130 : USE qs_kpoint_operators, ONLY: &
131 : kpoint_operator_cfm_to_mo, kpoint_operator_context_create, &
132 : kpoint_operator_context_release, kpoint_operator_context_type, kpoint_operator_evaluate, &
133 : kpoint_operator_finish, kpoint_operator_get, kpoint_operator_get_local, &
134 : kpoint_operator_prepare, kpoint_operator_start, kpoint_operator_store, &
135 : kpoint_operator_work_size, kpoint_slot_ks, kpoint_slot_s, kpoint_slot_t, kpoint_spin_free
136 : USE qs_ks_methods, ONLY: qs_ks_update_qs_env
137 : USE qs_ks_types, ONLY: qs_ks_did_change,&
138 : qs_ks_env_type
139 : USE qs_matrix_pools, ONLY: mpools_get,&
140 : qs_matrix_pools_type
141 : USE qs_mixing_utils, ONLY: charge_mixing_init,&
142 : mixing_allocate,&
143 : mixing_init,&
144 : self_consistency_check
145 : USE qs_mo_methods, ONLY: calculate_subspace_eigenvalues
146 : USE qs_mo_occupation, ONLY: set_mo_occupation
147 : USE qs_mo_types, ONLY: get_mo_set,&
148 : mo_set_type
149 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
150 : USE qs_ot_eigensolver, ONLY: ot_eigensolver,&
151 : ot_eigensolver_complex
152 : USE qs_rho_atom_types, ONLY: rho_atom_type
153 : USE qs_rho_methods, ONLY: qs_rho_update_rho
154 : USE qs_rho_types, ONLY: qs_rho_get,&
155 : qs_rho_type
156 : USE qs_scf_block_davidson, ONLY: generate_extended_space,&
157 : generate_extended_space_c,&
158 : generate_extended_space_sparse
159 : USE qs_scf_lanczos, ONLY: lanczos_refinement,&
160 : lanczos_refinement_2v
161 : USE qs_scf_methods, ONLY: combine_ks_matrices,&
162 : eigensolver,&
163 : eigensolver_dbcsr,&
164 : eigensolver_generalized,&
165 : eigensolver_simple,&
166 : eigensolver_symm,&
167 : scf_env_density_mixing
168 : USE qs_scf_types, ONLY: qs_scf_env_type,&
169 : subspace_env_type
170 : USE scf_control_types, ONLY: scf_control_type
171 :
172 : !$ USE OMP_LIB, ONLY: omp_get_max_threads, &
173 : !$ omp_get_thread_num
174 : #include "./base/base_uses.f90"
175 :
176 : IMPLICIT NONE
177 :
178 : PRIVATE
179 :
180 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_diagonalization'
181 :
182 : TYPE, PRIVATE :: kp_diag_workspace_type
183 : TYPE(cp_cfm_type) :: cksmat, cmos, csmat, csmat_base, cwork
184 : TYPE(cp_cfm_diag_workspace_type) :: solver
185 : TYPE(local_gemm_ctxt_type) :: gemm_ctx
186 : COMPLEX(KIND=dp), ALLOCATABLE :: phase(:, :)
187 : END TYPE kp_diag_workspace_type
188 :
189 : PUBLIC :: do_general_diag, do_general_diag_kp, do_roks_diag, &
190 : do_special_diag, do_ot_diag, do_ot_diag_kp, do_block_davidson_diag, &
191 : do_block_davidson_diag_kp, &
192 : do_block_krylov_diag, do_scf_diag_subspace, diag_subspace_allocate, &
193 : general_eigenproblem, diag_kp_smat, diag_kp_basic
194 :
195 : CONTAINS
196 :
197 : ! **************************************************************************************************
198 : !> \brief Fade candidate regularization through handover; never regularize a raw-map check.
199 : !> \param scf_env Current SCF state.
200 : !> \return ...
201 : ! **************************************************************************************************
202 206 : FUNCTION adiis_candidate_shift(scf_env) RESULT(shift)
203 : TYPE(qs_scf_env_type), INTENT(IN) :: scf_env
204 : REAL(KIND=dp) :: shift
205 :
206 206 : shift = 0.0_dp
207 206 : IF (scf_env%iter_count <= 1 .OR. scf_env%adiis_check_next) RETURN
208 190 : IF (.NOT. ASSOCIATED(scf_env%scf_subspace_buffer)) RETURN
209 190 : shift = scf_env%adiis_shift*(1.0_dp - scf_env%scf_subspace_buffer%diis_weight)
210 190 : END FUNCTION adiis_candidate_shift
211 :
212 : ! **************************************************************************************************
213 : !> \brief Add -shift*S*C*(occupation/maxocc)*C^T*S to a candidate Fock matrix.
214 : !> The occupied projector does not require any stored virtual orbitals.
215 : !> \param fock Candidate matrix; physical F[P] and all history matrices remain unchanged.
216 : !> \param overlap AO overlap.
217 : !> \param mos Previous physical orbitals and occupations.
218 : !> \param shift Nonnegative regularization parameter in hartree.
219 : ! **************************************************************************************************
220 84 : SUBROUTINE shift_candidate_real(fock, overlap, mos, shift)
221 : TYPE(cp_fm_type), INTENT(INOUT) :: fock
222 : TYPE(cp_fm_type), INTENT(IN) :: overlap
223 : TYPE(mo_set_type), INTENT(IN) :: mos
224 : REAL(KIND=dp), INTENT(IN) :: shift
225 :
226 : INTEGER :: nao, nmo
227 : REAL(KIND=dp) :: maxocc
228 28 : REAL(KIND=dp), DIMENSION(:), POINTER :: occupation
229 : TYPE(cp_fm_type) :: sc
230 : TYPE(cp_fm_type), POINTER :: coeff
231 :
232 0 : IF (shift == 0.0_dp) RETURN
233 28 : CALL get_mo_set(mos, nao=nao, nmo=nmo, maxocc=maxocc, occupation_numbers=occupation, mo_coeff=coeff)
234 28 : CALL cp_fm_create(sc, coeff%matrix_struct)
235 28 : CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, overlap, coeff, 0.0_dp, sc)
236 406 : CALL cp_fm_column_scale(sc, SQRT(MAX(0.0_dp, occupation/maxocc)))
237 28 : CALL parallel_gemm("N", "T", nao, nao, nmo, -shift, sc, sc, 1.0_dp, fock)
238 28 : CALL cp_fm_release(sc)
239 28 : END SUBROUTINE shift_candidate_real
240 :
241 : ! **************************************************************************************************
242 : !> \brief Complex occupied-space shift, using conjugate transpose and existing eigensolver workspaces.
243 : !> \param fock Candidate Fock matrix, modified in place.
244 : !> \param overlap AO overlap, unchanged.
245 : !> \param mos Real and imaginary components of the previous physical MOs.
246 : !> \param coeff AO/MO eigensolver workspace.
247 : !> \param work AO/AO eigensolver workspace.
248 : !> \param shift Nonnegative regularization parameter in hartree.
249 : !> \param local Whether the matrices are complete on this rank.
250 : !> \param gemm_ctx Private local GEMM context, unused for distributed groups.
251 : ! **************************************************************************************************
252 138 : SUBROUTINE shift_candidate_complex(fock, overlap, mos, coeff, work, shift, local, gemm_ctx)
253 : TYPE(cp_cfm_type), INTENT(INOUT) :: fock
254 : TYPE(cp_cfm_type), INTENT(IN) :: overlap
255 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
256 : TYPE(cp_cfm_type), INTENT(INOUT) :: coeff, work
257 : REAL(KIND=dp), INTENT(IN) :: shift
258 : LOGICAL, INTENT(IN) :: local
259 : TYPE(local_gemm_ctxt_type), INTENT(INOUT) :: gemm_ctx
260 :
261 : INTEGER :: nao, nmo
262 : REAL(KIND=dp) :: maxocc
263 138 : REAL(KIND=dp), DIMENSION(:), POINTER :: occupation
264 : TYPE(cp_fm_type), POINTER :: imos, rmos
265 :
266 118 : IF (shift == 0.0_dp) RETURN
267 20 : CALL get_mo_set(mos(1), nao=nao, nmo=nmo, maxocc=maxocc, occupation_numbers=occupation, mo_coeff=rmos)
268 20 : CALL get_mo_set(mos(2), mo_coeff=imos)
269 20 : CALL cp_fm_to_cfm(rmos, imos, coeff)
270 320 : CALL cp_cfm_column_scale(coeff, CMPLX(SQRT(MAX(0.0_dp, occupation/maxocc)), KIND=dp))
271 20 : IF (local) THEN
272 60 : CPASSERT(PRODUCT(overlap%matrix_struct%context%num_pe) == 1)
273 60 : CPASSERT(PRODUCT(coeff%matrix_struct%context%num_pe) == 1)
274 60 : CPASSERT(PRODUCT(work%matrix_struct%context%num_pe) == 1)
275 60 : CPASSERT(PRODUCT(fock%matrix_struct%context%num_pe) == 1)
276 : CALL gemm_ctx%gemm("N", "N", nao, nmo, nao, z_one, &
277 : overlap%local_data, SIZE(overlap%local_data, 1), &
278 : coeff%local_data, SIZE(coeff%local_data, 1), z_zero, &
279 20 : work%local_data, SIZE(work%local_data, 1))
280 : CALL gemm_ctx%gemm("N", "C", nao, nao, nmo, CMPLX(-shift, KIND=dp), &
281 : work%local_data, SIZE(work%local_data, 1), &
282 : work%local_data, SIZE(work%local_data, 1), z_one, &
283 20 : fock%local_data, SIZE(fock%local_data, 1))
284 : ELSE
285 0 : CALL parallel_gemm("N", "N", nao, nmo, nao, z_one, overlap, coeff, z_zero, work)
286 0 : CALL parallel_gemm("N", "C", nao, nao, nmo, CMPLX(-shift, KIND=dp), work, work, z_one, fock)
287 : END IF
288 138 : END SUBROUTINE shift_candidate_complex
289 :
290 : ! **************************************************************************************************
291 : !> \brief the inner loop of scf, specific to diagonalization with S matrix
292 : !> basically, in goes the ks matrix out goes a new p matrix
293 : !> \param scf_env ...
294 : !> \param mos ...
295 : !> \param matrix_ks ...
296 : !> \param matrix_s ...
297 : !> \param scf_control ...
298 : !> \param scf_section ...
299 : !> \param diis_step ...
300 : !> \par History
301 : !> 03.2006 created [Joost VandeVondele]
302 : ! **************************************************************************************************
303 :
304 100851 : SUBROUTINE general_eigenproblem(scf_env, mos, matrix_ks, &
305 : matrix_s, scf_control, scf_section, &
306 : diis_step)
307 :
308 : TYPE(qs_scf_env_type), POINTER :: scf_env
309 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
310 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
311 : TYPE(scf_control_type), POINTER :: scf_control
312 : TYPE(section_vals_type), POINTER :: scf_section
313 : LOGICAL, INTENT(INOUT) :: diis_step
314 :
315 : INTEGER :: cdiis_cholesky_method, cdiis_ncall, &
316 : ispin, nspin
317 : LOGICAL :: cdiis_step, do_level_shift, owns_ortho, &
318 : use_adiis, use_cdiis, use_jacobi, &
319 : use_subspace_fock
320 : REAL(KIND=dp) :: candidate_shift, cdiis_error, &
321 : diis_error, diis_weight, eps_diis
322 : TYPE(cp_fm_type), POINTER :: ortho
323 : TYPE(dbcsr_type), POINTER :: effective_ks_dbcsr, ortho_dbcsr
324 :
325 100851 : nspin = SIZE(matrix_ks)
326 100851 : NULLIFY (effective_ks_dbcsr, ortho, ortho_dbcsr)
327 :
328 100851 : use_adiis = scf_control%diagonalization%update_method == diag_update_method_adiis
329 100851 : use_subspace_fock = .FALSE.
330 100851 : IF (use_adiis) THEN
331 68 : IF (.NOT. ASSOCIATED(scf_env%scf_subspace_buffer)) THEN
332 0 : CPABORT("ADIIS is only available in the main Quickstep SCF workflow")
333 : END IF
334 68 : use_subspace_fock = scf_env%scf_subspace_buffer%use_combined_fock
335 : END IF
336 :
337 100851 : eps_diis = scf_control%eps_diis
338 100851 : use_cdiis = .FALSE.
339 100851 : IF (use_adiis .AND. ASSOCIATED(scf_env%scf_diis_buffer)) THEN
340 : IF (.NOT. scf_env%skip_diis .AND. scf_env%iter_count > 1 .AND. &
341 : .NOT. scf_env%adiis_check_next .AND. &
342 68 : .NOT. scf_env%scf_subspace_buffer%last_restart .AND. &
343 : scf_env%scf_subspace_buffer%nstored > 0) THEN
344 62 : use_cdiis = scf_env%iter_delta < eps_diis .OR. scf_env%scf_diis_buffer%ncall > 0
345 : END IF
346 : END IF
347 :
348 219962 : DO ispin = 1, nspin
349 219962 : IF (use_cdiis) THEN
350 92 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin))
351 119019 : ELSE IF (use_subspace_fock) THEN
352 : CALL copy_dbcsr_to_fm(scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix, &
353 20 : scf_env%scf_work1(ispin))
354 : ELSE
355 118999 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin))
356 : END IF
357 : END DO
358 :
359 100851 : IF (use_adiis) THEN
360 68 : diis_step = .FALSE.
361 68 : diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
362 68 : diis_weight = scf_env%scf_subspace_buffer%diis_weight
363 68 : IF (use_cdiis) THEN
364 46 : cdiis_ncall = scf_env%scf_diis_buffer%ncall
365 : CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
366 : scf_env%scf_work2, scf_env%iter_delta, cdiis_error, cdiis_step, &
367 46 : eps_diis, 2, s_matrix=matrix_s, scf_section=scf_section)
368 46 : IF (.NOT. ieee_is_finite(cdiis_error) .OR. cdiis_error >= eps_diis) THEN
369 6 : cdiis_step = .FALSE.
370 6 : IF (cdiis_ncall < scf_env%scf_diis_buffer%nbuffer) THEN
371 : ! The rejected state has not overwritten a full circular buffer.
372 6 : scf_env%scf_diis_buffer%ncall = cdiis_ncall
373 : ELSE
374 0 : CALL qs_diis_b_clear(scf_env%scf_diis_buffer)
375 0 : diis_weight = 0.0_dp
376 : END IF
377 : END IF
378 46 : IF (cdiis_step) THEN
379 : ! Use one half-weight handover step; MAX_DIIS only controls the buffer capacity.
380 34 : diis_weight = MIN(1.0_dp, diis_weight + 0.5_dp)
381 : ELSE
382 : ! A rejected or deferred CDIIS step must not leave a partial raw-Fock blend active.
383 12 : diis_weight = 0.0_dp
384 : END IF
385 46 : IF (diis_weight < 1.0_dp) THEN
386 54 : DO ispin = 1, nspin
387 36 : IF (use_subspace_fock) THEN
388 : CALL copy_dbcsr_to_fm( &
389 32 : scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix, scf_env%scf_work2)
390 : ELSE
391 4 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work2)
392 : END IF
393 : CALL cp_fm_scale_and_add(diis_weight, scf_env%scf_work1(ispin), &
394 54 : 1.0_dp - diis_weight, scf_env%scf_work2)
395 : END DO
396 : END IF
397 46 : diis_step = cdiis_step .AND. diis_weight >= 1.0_dp
398 46 : IF (diis_step) diis_error = cdiis_error
399 22 : ELSE IF (ASSOCIATED(scf_env%scf_diis_buffer)) THEN
400 22 : IF (scf_env%scf_diis_buffer%ncall > 0) CALL qs_diis_b_clear(scf_env%scf_diis_buffer)
401 22 : diis_weight = 0.0_dp
402 : END IF
403 68 : scf_env%scf_subspace_buffer%diis_weight = diis_weight
404 : ELSE
405 100783 : IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
406 : CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
407 : scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
408 : eps_diis, scf_control%nmixing, &
409 : s_matrix=matrix_s, &
410 81859 : scf_section=scf_section)
411 : ELSE
412 18924 : diis_step = .FALSE.
413 : END IF
414 : END IF
415 :
416 100851 : candidate_shift = 0.0_dp
417 100851 : IF (use_adiis) candidate_shift = adiis_candidate_shift(scf_env)
418 100851 : IF (candidate_shift > 0.0_dp) THEN
419 14 : CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, scf_env%scf_work2)
420 42 : DO ispin = 1, nspin
421 42 : CALL shift_candidate_real(scf_env%scf_work1(ispin), scf_env%scf_work2, mos(ispin), candidate_shift)
422 : END DO
423 : END IF
424 :
425 : do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
426 : ((scf_control%density_guess == core_guess) .OR. &
427 100851 : (scf_env%iter_count > 1)))
428 :
429 100851 : IF (.NOT. use_adiis .AND. (scf_env%iter_count > 1) .AND. &
430 : (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
431 0 : use_jacobi = .TRUE.
432 : ELSE
433 100783 : use_jacobi = .FALSE.
434 : END IF
435 :
436 68 : IF (use_adiis .AND. .NOT. diis_step) THEN
437 40 : scf_env%iter_param = diis_error
438 40 : IF (scf_env%scf_subspace_buffer%last_restart) THEN
439 0 : scf_env%iter_method = "ADIIS/Rst."
440 : ELSE
441 40 : scf_env%iter_method = "ADIIS/Diag."
442 : END IF
443 100811 : ELSE IF (diis_step) THEN
444 50247 : scf_env%iter_param = diis_error
445 50247 : IF (use_jacobi) THEN
446 0 : scf_env%iter_method = "DIIS/Jacobi"
447 : ELSE
448 50247 : scf_env%iter_method = "DIIS/Diag."
449 : END IF
450 : ELSE
451 50564 : IF (scf_env%mixing_method == 0) THEN
452 0 : scf_env%iter_method = "NoMix/Diag."
453 50564 : ELSE IF (scf_env%mixing_method == 1) THEN
454 45548 : scf_env%iter_param = scf_env%p_mix_alpha
455 45548 : IF (use_jacobi) THEN
456 0 : scf_env%iter_method = "P_Mix/Jacobi"
457 : ELSE
458 45548 : scf_env%iter_method = "P_Mix/Diag."
459 : END IF
460 5016 : ELSE IF (scf_env%mixing_method > 1) THEN
461 5016 : scf_env%iter_param = scf_env%mixing_store%alpha
462 5016 : IF (use_jacobi) THEN
463 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
464 : ELSE
465 5016 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
466 : END IF
467 : END IF
468 : END IF
469 :
470 100851 : IF (scf_env%cholesky_method == cholesky_dbcsr .AND. .NOT. use_cdiis) THEN
471 1072 : ortho_dbcsr => scf_env%ortho_dbcsr
472 3198 : DO ispin = 1, nspin
473 2126 : effective_ks_dbcsr => matrix_ks(ispin)%matrix
474 2126 : IF (use_subspace_fock) THEN
475 0 : effective_ks_dbcsr => scf_env%scf_subspace_buffer%combined_fock(ispin, 1)%matrix
476 : END IF
477 : CALL eigensolver_dbcsr(matrix_ks=effective_ks_dbcsr, matrix_ks_fm=scf_env%scf_work1(ispin), &
478 : mo_set=mos(ispin), &
479 : ortho_dbcsr=ortho_dbcsr, &
480 3198 : ksbuf1=scf_env%buf1_dbcsr, ksbuf2=scf_env%buf2_dbcsr)
481 : END DO
482 :
483 99779 : ELSE IF (scf_env%cholesky_method > cholesky_off) THEN
484 99345 : cdiis_cholesky_method = scf_env%cholesky_method
485 99345 : IF (cdiis_cholesky_method == cholesky_dbcsr) THEN
486 0 : cdiis_cholesky_method = cholesky_inverse
487 : END IF
488 99345 : IF (scf_env%cholesky_method == cholesky_inverse) THEN
489 264 : ortho => scf_env%ortho_m1
490 : ELSE
491 99081 : ortho => scf_env%ortho
492 : END IF
493 :
494 99345 : owns_ortho = .FALSE.
495 99345 : IF (.NOT. ASSOCIATED(ortho)) THEN
496 0 : ALLOCATE (ortho)
497 0 : owns_ortho = .TRUE.
498 : END IF
499 :
500 215814 : DO ispin = 1, nspin
501 215814 : IF (direct_generalized_diagonalization .AND. .NOT. do_level_shift) THEN
502 : CALL eigensolver_generalized(matrix_ks_fm=scf_env%scf_work1(ispin), &
503 : matrix_s=matrix_s(ispin)%matrix, &
504 : mo_set=mos(ispin), &
505 0 : work=scf_env%scf_work2)
506 : ELSE
507 116469 : IF (do_level_shift) THEN
508 : CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
509 : mo_set=mos(ispin), &
510 : ortho=ortho, &
511 : work=scf_env%scf_work2, &
512 : cholesky_method=cdiis_cholesky_method, &
513 : do_level_shift=do_level_shift, &
514 : level_shift=scf_control%level_shift, &
515 : matrix_u_fm=scf_env%ortho, &
516 128 : use_jacobi=use_jacobi)
517 : ELSE
518 : CALL eigensolver(matrix_ks_fm=scf_env%scf_work1(ispin), &
519 : mo_set=mos(ispin), &
520 : ortho=ortho, &
521 : work=scf_env%scf_work2, &
522 : cholesky_method=cdiis_cholesky_method, &
523 : do_level_shift=do_level_shift, &
524 : level_shift=scf_control%level_shift, &
525 116341 : use_jacobi=use_jacobi)
526 : END IF
527 : END IF
528 : END DO
529 :
530 99345 : IF (scf_env%cholesky_method /= cholesky_dbcsr) THEN
531 99345 : scf_env%cholesky_method = cdiis_cholesky_method
532 : END IF
533 :
534 99345 : IF (owns_ortho) DEALLOCATE (ortho)
535 : ELSE
536 434 : ortho => scf_env%ortho
537 :
538 434 : owns_ortho = .FALSE.
539 434 : IF (.NOT. ASSOCIATED(ortho)) THEN
540 0 : ALLOCATE (ortho)
541 0 : owns_ortho = .TRUE.
542 : END IF
543 :
544 434 : IF (do_level_shift) THEN
545 172 : DO ispin = 1, nspin
546 : IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
547 172 : .AND. ASSOCIATED(scf_env%ortho_red) .AND. ASSOCIATED(scf_env%ortho_m1_red)) THEN
548 : CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
549 : mo_set=mos(ispin), &
550 : ortho=ortho, &
551 : work=scf_env%scf_work2, &
552 : do_level_shift=do_level_shift, &
553 : level_shift=scf_control%level_shift, &
554 : matrix_u_fm=scf_env%ortho_m1, &
555 : use_jacobi=use_jacobi, &
556 : jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
557 : matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
558 : ortho_red=scf_env%ortho_red, &
559 : work_red=scf_env%scf_work2_red, &
560 86 : matrix_u_fm_red=scf_env%ortho_m1_red)
561 : ELSE
562 : CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
563 : mo_set=mos(ispin), &
564 : ortho=ortho, &
565 : work=scf_env%scf_work2, &
566 : do_level_shift=do_level_shift, &
567 : level_shift=scf_control%level_shift, &
568 : matrix_u_fm=scf_env%ortho_m1, &
569 : use_jacobi=use_jacobi, &
570 0 : jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
571 : END IF
572 : END DO
573 : ELSE
574 778 : DO ispin = 1, nspin
575 : IF (ASSOCIATED(scf_env%scf_work1_red) .AND. ASSOCIATED(scf_env%scf_work2_red) &
576 778 : .AND. ASSOCIATED(scf_env%ortho_red)) THEN
577 : CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
578 : mo_set=mos(ispin), &
579 : ortho=ortho, &
580 : work=scf_env%scf_work2, &
581 : do_level_shift=do_level_shift, &
582 : level_shift=scf_control%level_shift, &
583 : use_jacobi=use_jacobi, &
584 : jacobi_threshold=scf_control%diagonalization%jacobi_threshold, &
585 : matrix_ks_fm_red=scf_env%scf_work1_red(ispin), &
586 : ortho_red=scf_env%ortho_red, &
587 430 : work_red=scf_env%scf_work2_red)
588 : ELSE
589 : CALL eigensolver_symm(matrix_ks_fm=scf_env%scf_work1(ispin), &
590 : mo_set=mos(ispin), &
591 : ortho=ortho, &
592 : work=scf_env%scf_work2, &
593 : do_level_shift=do_level_shift, &
594 : level_shift=scf_control%level_shift, &
595 : use_jacobi=use_jacobi, &
596 0 : jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
597 : END IF
598 : END DO
599 : END IF
600 :
601 434 : IF (owns_ortho) DEALLOCATE (ortho)
602 : END IF
603 :
604 100851 : END SUBROUTINE general_eigenproblem
605 :
606 : ! **************************************************************************************************
607 : !> \brief ...
608 : !> \param scf_env ...
609 : !> \param mos ...
610 : !> \param matrix_ks ...
611 : !> \param matrix_s ...
612 : !> \param scf_control ...
613 : !> \param scf_section ...
614 : !> \param diis_step ...
615 : !> \param probe ...
616 : ! **************************************************************************************************
617 99811 : SUBROUTINE do_general_diag(scf_env, mos, matrix_ks, &
618 : matrix_s, scf_control, scf_section, &
619 : diis_step, probe)
620 :
621 : TYPE(qs_scf_env_type), POINTER :: scf_env
622 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
623 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
624 : TYPE(scf_control_type), POINTER :: scf_control
625 : TYPE(section_vals_type), POINTER :: scf_section
626 : LOGICAL, INTENT(INOUT) :: diis_step
627 : TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
628 : POINTER :: probe
629 :
630 : INTEGER :: ispin, nspin
631 : REAL(KIND=dp) :: total_zeff_corr
632 :
633 99811 : nspin = SIZE(matrix_ks)
634 :
635 : CALL general_eigenproblem(scf_env, mos, matrix_ks, &
636 99811 : matrix_s, scf_control, scf_section, diis_step)
637 :
638 : total_zeff_corr = 0.0_dp
639 99811 : total_zeff_corr = scf_env%sum_zeff_corr
640 :
641 99811 : IF (ABS(total_zeff_corr) > 0.0_dp) THEN
642 : CALL set_mo_occupation(mo_array=mos, &
643 40 : smear=scf_control%smear, tot_zeff_corr=total_zeff_corr)
644 : ELSE
645 99771 : IF (PRESENT(probe) .EQV. .TRUE.) THEN
646 14 : scf_control%smear%do_smear = .FALSE.
647 : CALL set_mo_occupation(mo_array=mos, &
648 : smear=scf_control%smear, &
649 14 : probe=probe)
650 : ELSE
651 99757 : IF (.NOT. scf_control%gce%do_gce) THEN
652 : CALL set_mo_occupation(mo_array=mos, &
653 99693 : smear=scf_control%smear)
654 : ELSE
655 : CALL set_mo_occupation(mo_array=mos, &
656 : smear=scf_control%smear, &
657 64 : gce=scf_control%gce)
658 : END IF
659 : END IF
660 : END IF
661 :
662 216842 : DO ispin = 1, nspin
663 : CALL calculate_density_matrix(mos(ispin), &
664 216842 : scf_env%p_mix_new(ispin, 1)%matrix)
665 : END DO
666 :
667 99811 : END SUBROUTINE do_general_diag
668 :
669 : ! **************************************************************************************************
670 : !> \brief Kpoint diagonalization routine
671 : !> Transforms matrices to kpoint, distributes kpoint groups, performs
672 : !> general diagonalization (no storgae of overlap decomposition), stores
673 : !> MOs, calculates occupation numbers, calculates density matrices
674 : !> in kpoint representation, transforms density matrices to real space
675 : !> \param matrix_ks Kohn-sham matrices (RS indices, global)
676 : !> \param matrix_s Overlap matrices (RS indices, global)
677 : !> \param kpoints Kpoint environment
678 : !> \param scf_env SCF environment
679 : !> \param scf_control SCF control variables
680 : !> \param update_p ...
681 : !> \param diis_step ...
682 : !> \param diis_error ...
683 : !> \param qs_env ...
684 : !> \param probe ...
685 : !> \param added_mos_auto_grow true when the adaptive virtual-space buffer must grow
686 : !> \par History
687 : !> 08.2014 created [JGH]
688 : ! **************************************************************************************************
689 33754 : SUBROUTINE do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, update_p, &
690 : diis_step, diis_error, qs_env, probe, added_mos_auto_grow)
691 :
692 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
693 : TYPE(kpoint_type), POINTER :: kpoints
694 : TYPE(qs_scf_env_type), POINTER :: scf_env
695 : TYPE(scf_control_type), POINTER :: scf_control
696 : LOGICAL, INTENT(IN) :: update_p
697 : LOGICAL, INTENT(INOUT) :: diis_step
698 : REAL(dp), INTENT(INOUT), OPTIONAL :: diis_error
699 : TYPE(qs_environment_type), OPTIONAL, POINTER :: qs_env
700 : TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
701 : POINTER :: probe
702 : LOGICAL, INTENT(OUT), OPTIONAL :: added_mos_auto_grow
703 :
704 : CHARACTER(len=*), PARAMETER :: routineN = 'do_general_diag_kp'
705 :
706 33754 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coeffs
707 : INTEGER :: cdiis_ncall, handle, ib, ikp, ispin, kplocal, kpmax, &
708 : lattice_fft, nb, nkp, nspin, omp_threads, nworkers, nentry
709 : INTEGER, DIMENSION(2) :: kp_range
710 : INTEGER, DIMENSION(3) :: nkp_grid
711 33754 : INTEGER, DIMENSION(:, :), POINTER :: kp_dist
712 33754 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
713 : LOGICAL :: adiis_cdiis, cache_smat, cdiis_step, do_diis, my_added_mos_auto_grow, prepared_ops, prepared_part, &
714 : reuse_smat, spin_grid_fft, use_adiis, use_grid_fft, use_local_kpoints, use_real_wfn
715 : REAL(KIND=dp) :: diis_weight
716 33754 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
717 33754 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp
718 : TYPE(cp_cfm_type), POINTER :: cksmat, cmos, csmat, cwork
719 33754 : TYPE(kp_diag_workspace_type), ALLOCATABLE, TARGET :: workspace(:)
720 33754 : TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER :: ao_ao_fm_pools
721 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct, mo_struct
722 : TYPE(cp_fm_type) :: fmlocal, rksmat, rsmat
723 33754 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
724 : TYPE(cp_fm_type), POINTER :: mo_coeff
725 33754 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: adiis_ks, effective_ks
726 : TYPE(dbcsr_type), POINTER :: rmatrix
727 : TYPE(kpoint_env_type), POINTER :: kp
728 33754 : TYPE(kpoint_operator_context_type) :: op_ctx
729 : TYPE(mp_para_env_type), POINTER :: para_env
730 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
731 33754 : POINTER :: sab_nl
732 : TYPE(qs_matrix_pools_type), POINTER :: mpools
733 33754 : TYPE(rskp_grid_type) :: s_grid
734 33754 : TYPE(rskp_grid_type), ALLOCATABLE, DIMENSION(:) :: ks_grid
735 : TYPE(section_vals_type), POINTER :: scf_section
736 :
737 33754 : CALL timeset(routineN, handle)
738 :
739 33754 : my_added_mos_auto_grow = .FALSE.
740 33754 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .FALSE.
741 :
742 33754 : NULLIFY (adiis_ks, effective_ks, sab_nl)
743 : CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
744 : kp_dist=kp_dist, sab_nl=sab_nl, &
745 33754 : cell_to_index=cell_to_index, nkp_grid=nkp_grid, lattice_fft=lattice_fft)
746 33754 : CPASSERT(ASSOCIATED(sab_nl))
747 33754 : kplocal = kp_range(2) - kp_range(1) + 1
748 90934 : kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
749 :
750 : !Whether we use DIIS for k-points
751 33754 : do_diis = .FALSE.
752 33754 : use_adiis = update_p .AND. scf_control%diagonalization%update_method == diag_update_method_adiis
753 33754 : IF (use_adiis) THEN
754 80 : CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
755 : END IF
756 33754 : adiis_cdiis = .FALSE.
757 33754 : IF (use_adiis .AND. ASSOCIATED(kpoints%scf_diis_buffer)) THEN
758 : IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis .AND. &
759 : .NOT. scf_env%adiis_check_next .AND. &
760 : .NOT. scf_env%scf_subspace_buffer%last_restart .AND. &
761 : scf_env%scf_subspace_buffer%nstored > 0 .AND. &
762 80 : PRESENT(diis_error) .AND. PRESENT(qs_env)) THEN
763 : adiis_cdiis = scf_env%iter_delta < scf_control%eps_diis .OR. &
764 74 : kpoints%scf_diis_buffer%ncall > 0
765 : END IF
766 : END IF
767 : IF ((.NOT. use_adiis .AND. scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis .AND. &
768 33754 : .NOT. use_real_wfn .AND. PRESENT(diis_error) .AND. PRESENT(qs_env)) .OR. &
769 27512 : adiis_cdiis) do_diis = .TRUE.
770 :
771 33754 : adiis_ks => matrix_ks
772 33754 : IF (use_adiis) THEN
773 80 : IF (scf_env%scf_subspace_buffer%use_combined_fock) THEN
774 32 : adiis_ks => scf_env%scf_subspace_buffer%combined_fock
775 : END IF
776 : END IF
777 33754 : effective_ks => matrix_ks
778 33754 : IF (use_adiis .AND. .NOT. adiis_cdiis) THEN
779 30 : effective_ks => adiis_ks
780 : END IF
781 33754 : IF (use_adiis .AND. .NOT. do_diis) THEN
782 30 : scf_env%scf_subspace_buffer%diis_weight = 0.0_dp
783 30 : IF (ASSOCIATED(kpoints%scf_diis_buffer)) THEN
784 30 : IF (kpoints%scf_diis_buffer%ncall > 0) CALL qs_diis_b_clear_kp(kpoints%scf_diis_buffer)
785 : END IF
786 : END IF
787 :
788 33754 : para_env => kpoints%blacs_env_all%para_env
789 33754 : nspin = SIZE(matrix_ks, 1)
790 33754 : omp_threads = 1
791 33754 : !$ omp_threads = omp_get_max_threads()
792 : ! One-rank groups use the same worker path for MPI, OpenMP and hybrid jobs.
793 33754 : use_local_kpoints = kpoints%para_env_kp%num_pe == 1 .AND. .NOT. use_real_wfn
794 33754 : IF (diag_check_requested()) use_local_kpoints = .FALSE.
795 33754 : IF (para_env%num_pe == 1 .AND. omp_threads == 1) THEN
796 0 : IF (lattice_fft == lattice_fft_on .OR. (lattice_fft == lattice_fft_auto .AND. nkp >= 27)) THEN
797 0 : use_local_kpoints = .FALSE.
798 : END IF
799 : END IF
800 33754 : ib = 0
801 33754 : nb = 0
802 33754 : NULLIFY (scf_section)
803 :
804 33754 : NULLIFY (rmatrix)
805 :
806 33754 : fmwork => scf_env%scf_work1
807 : ! Both real and complex operators share the same assembly and transfer context.
808 33754 : CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
809 :
810 : ! fm pools to be used within a kpoint group
811 33754 : CALL get_kpoint_info(kpoints, mpools=mpools)
812 33754 : CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
813 :
814 33754 : CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
815 33754 : CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
816 :
817 33754 : IF (use_real_wfn) THEN
818 : CALL cp_fm_create(rksmat, matrix_struct)
819 : CALL cp_fm_create(rsmat, matrix_struct)
820 : END IF
821 : ! Retain the unmodified S(k) for this SCF run, outside the driver-local
822 : ! operator context. Solvers receive work copies because they overwrite S.
823 33754 : cache_smat = para_env%num_pe > 1 .AND. update_p .AND. .NOT. use_real_wfn
824 33754 : reuse_smat = .FALSE.
825 33754 : IF (cache_smat) THEN
826 33448 : reuse_smat = ALLOCATED(kpoints%scf_smat)
827 33448 : IF (.NOT. reuse_smat) THEN
828 17592 : ALLOCATE (kpoints%scf_smat(kplocal))
829 10620 : DO ikp = 1, kplocal
830 10620 : CALL cp_cfm_create(kpoints%scf_smat(ikp), matrix_struct)
831 : END DO
832 : END IF
833 33448 : CPASSERT(SIZE(kpoints%scf_smat) == kplocal)
834 : END IF
835 :
836 : ! Prepare H/S before starting any round. ADIIS can replace only the idle KS slot.
837 33754 : prepared_ops = .FALSE.
838 : ! A single distributed group can also assemble its prepared local tiles.
839 33754 : IF (para_env%num_pe > 1 .OR. use_local_kpoints) THEN
840 33754 : CALL kpoint_operator_prepare(op_ctx, effective_ks, kpoint_slot_ks, prepared_ops)
841 33754 : IF (.NOT. reuse_smat) THEN
842 3792 : CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, prepared_part, matrix_row=kpoint_spin_free)
843 3802 : prepared_ops = prepared_ops .AND. prepared_part
844 : END IF
845 : END IF
846 :
847 33754 : use_local_kpoints = use_local_kpoints .AND. prepared_ops
848 33754 : nworkers = 1
849 33754 : nentry = 0
850 33754 : IF (use_local_kpoints) THEN
851 23426 : nworkers = MIN(omp_threads, kplocal)
852 23426 : CALL kpoint_operator_work_size(op_ctx, nentry)
853 : END IF
854 33754 : IF (.NOT. use_real_wfn .OR. do_diis) THEN
855 33624 : kp => kpoints%kp_env(1)%kpoint_env
856 33624 : CALL get_mo_set(kp%mos(1, 1), mo_coeff=mo_coeff)
857 33624 : CALL cp_fm_get_info(mo_coeff, matrix_struct=mo_struct)
858 : CALL kp_diag_workspaces_create(workspace, nworkers, matrix_struct, mo_struct, nentry, &
859 33624 : use_local_kpoints, scf_env%cholesky_method == cholesky_off)
860 33624 : cksmat => workspace(1)%cksmat
861 33624 : csmat => workspace(1)%csmat
862 33624 : cwork => workspace(1)%cwork
863 33624 : cmos => workspace(1)%cmos
864 : END IF
865 :
866 : ! For a complete Monkhorst-Pack grid, transform every MPI-local DBCSR block over all k points
867 : ! in one lattice FFT. The established per-k phase sum remains the exact memory/irregular-grid
868 : ! fallback. Divide the conservative memory budget between H spins and S.
869 136810 : ALLOCATE (ks_grid(nspin))
870 33746 : SELECT CASE (lattice_fft)
871 : CASE (lattice_fft_auto)
872 33746 : use_grid_fft = nkp >= 27
873 : CASE (lattice_fft_on)
874 8 : use_grid_fft = .TRUE.
875 : CASE (lattice_fft_off)
876 0 : use_grid_fft = .FALSE.
877 : CASE DEFAULT
878 33754 : CPABORT("Unknown lattice FFT selection mode")
879 : END SELECT
880 33754 : IF (prepared_ops) use_grid_fft = .FALSE.
881 : ! The driver needs sparse scratch only for forward lattice-FFT preparation.
882 33754 : IF (use_grid_fft) THEN
883 0 : ALLOCATE (rmatrix)
884 0 : CALL dbcsr_create(rmatrix, template=matrix_ks(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
885 0 : CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
886 : END IF
887 33754 : IF (use_grid_fft .AND. .NOT. reuse_smat) THEN
888 : CALL rskp_transform_grid_prepare(s_grid, rmatrix, matrix_s, 1, xkp, nkp_grid, &
889 : cell_to_index, sab_nl, use_grid_fft, &
890 0 : max_storage_bytes=512_int_8*1024_int_8**2/INT(nspin + 1, int_8))
891 : END IF
892 33754 : IF (use_grid_fft) THEN
893 0 : DO ispin = 1, nspin
894 : CALL rskp_transform_grid_prepare(ks_grid(ispin), rmatrix, effective_ks, ispin, xkp, nkp_grid, &
895 : cell_to_index, sab_nl, spin_grid_fft, &
896 0 : max_storage_bytes=512_int_8*1024_int_8**2/INT(nspin + 1, int_8))
897 0 : use_grid_fft = use_grid_fft .AND. spin_grid_fft
898 : END DO
899 : END IF
900 33754 : IF (.NOT. use_grid_fft) THEN
901 33754 : CALL rskp_transform_grid_release(s_grid)
902 69302 : DO ispin = 1, nspin
903 69302 : CALL rskp_transform_grid_release(ks_grid(ispin))
904 : END DO
905 : END IF
906 :
907 : ! Setup and start all the communication.
908 33754 : IF (.NOT. use_local_kpoints) THEN
909 31194 : DO ikp = 1, kpmax
910 55562 : DO ispin = 1, nspin
911 : CALL kpoint_operator_start(op_ctx, ikp, ispin, effective_ks, kpoint_slot_ks, &
912 24368 : ks_grid(ispin), use_grid_fft, matrix_row=ispin)
913 45234 : IF (.NOT. cache_smat .OR. (.NOT. reuse_smat .AND. ispin == 1)) THEN
914 : CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_s, kpoint_slot_s, s_grid, &
915 3464 : use_grid_fft, matrix_row=kpoint_spin_free)
916 : END IF
917 : END DO
918 : END DO
919 : END IF
920 :
921 : ! Finish communication then diagonalise in each group
922 33754 : diis_weight = 1.0_dp
923 33754 : IF (do_diis) THEN
924 27512 : scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
925 27512 : cdiis_ncall = kpoints%scf_diis_buffer%ncall
926 27512 : CALL qs_diis_b_info_kp(kpoints%scf_diis_buffer, ib, nb)
927 27512 : CALL qs_diis_b_check_i_alloc_kp(kpoints%scf_diis_buffer, matrix_struct, nspin, kplocal, scf_section)
928 27512 : IF (use_local_kpoints) THEN
929 : CALL kp_diag_local_phase(op_ctx, kpoints, workspace, scf_env, scf_control, nspin, &
930 19692 : cache_smat, reuse_smat, use_adiis, ib, .TRUE., 1.0_dp)
931 : ELSE
932 19930 : DO ikp = 1, kpmax
933 35184 : DO ispin = 1, nspin
934 15254 : CALL harvest_operators(ikp, ispin)
935 15254 : IF (ikp > kplocal) CYCLE
936 : CALL qs_diis_b_calc_err_kp(kpoints%scf_diis_buffer, ib, kp%mos, cksmat, csmat, &
937 : ispin, ikp, cmos, real_wfn=use_real_wfn, &
938 27364 : local=.FALSE., gemm_ctx=workspace(1)%gemm_ctx)
939 :
940 : END DO !ispin
941 : END DO !ikp
942 :
943 : END IF
944 :
945 82536 : ALLOCATE (coeffs(nb))
946 : CALL qs_diis_b_step_kp(kpoints%scf_diis_buffer, coeffs, ib, nb, scf_env%iter_delta, diis_error, &
947 : cdiis_step, scf_control%eps_diis, nspin, nkp, kplocal, &
948 : MERGE(2, scf_control%nmixing, use_adiis), &
949 54974 : scf_section, kpoints%para_env_inter_kp)
950 : diis_weight = 1.0_dp
951 27512 : IF (use_adiis) THEN
952 50 : diis_weight = scf_env%scf_subspace_buffer%diis_weight
953 50 : IF (.NOT. ieee_is_finite(diis_error) .OR. diis_error >= scf_control%eps_diis) THEN
954 6 : cdiis_step = .FALSE.
955 6 : IF (cdiis_ncall < kpoints%scf_diis_buffer%nbuffer) THEN
956 : ! The rejected state has not overwritten a full circular buffer.
957 6 : kpoints%scf_diis_buffer%ncall = cdiis_ncall
958 : ELSE
959 0 : CALL qs_diis_b_clear_kp(kpoints%scf_diis_buffer)
960 0 : diis_weight = 0.0_dp
961 : END IF
962 : END IF
963 50 : IF (cdiis_step) THEN
964 : ! Use one half-weight handover step; MAX_DIIS only controls the buffer capacity.
965 38 : diis_weight = MIN(1.0_dp, diis_weight + 0.5_dp)
966 : ELSE
967 : ! A rejected or deferred CDIIS step must not leave a partial raw-Fock blend active.
968 12 : diis_weight = 0.0_dp
969 : END IF
970 50 : scf_env%scf_subspace_buffer%diis_weight = diis_weight
971 50 : diis_step = cdiis_step .AND. diis_weight >= 1.0_dp
972 50 : IF (.NOT. diis_step) diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
973 : ELSE
974 27462 : diis_step = cdiis_step
975 : END IF
976 :
977 : ! All first-pass instances have finished. Capture the selected
978 : ! ADIIS operator once instead of retransferring it in every round.
979 55024 : IF (use_adiis .AND. diis_weight < 1.0_dp) THEN
980 18 : CALL kpoint_operator_prepare(op_ctx, adiis_ks, kpoint_slot_ks, prepared_part)
981 : ! A collective prepare rejection must return all ranks to the transfer path.
982 18 : use_local_kpoints = use_local_kpoints .AND. prepared_part
983 : END IF
984 :
985 : ELSE
986 6242 : IF (.NOT. update_p .OR. use_adiis) diis_step = .FALSE.
987 : END IF
988 :
989 33754 : IF (use_local_kpoints) THEN
990 : ! An unallocated coeffs actual is absent at the optional dummy (Fortran 2008).
991 : CALL kp_diag_local_phase(op_ctx, kpoints, workspace, scf_env, scf_control, nspin, &
992 23426 : cache_smat, reuse_smat, use_adiis, ib, .FALSE., diis_weight, coeffs)
993 : ELSE
994 31194 : DO ikp = 1, kpmax
995 55562 : DO ispin = 1, nspin
996 24368 : IF (do_diis) THEN
997 15254 : IF (use_adiis .AND. diis_weight < 1.0_dp) THEN
998 : CALL kpoint_operator_start(op_ctx, ikp, ispin, adiis_ks, kpoint_slot_ks, &
999 0 : use_grid=.FALSE., matrix_row=ispin)
1000 0 : CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, cwork)
1001 : END IF
1002 15254 : IF (ikp > kplocal) CYCLE
1003 15254 : CALL cp_cfm_to_cfm(kpoints%scf_diis_buffer%smat(ikp), csmat)
1004 15254 : CALL kp_diis_candidate(kpoints, ikp, ispin, coeffs, diis_weight, cksmat, cwork)
1005 15254 : IF (use_real_wfn) THEN
1006 0 : CALL cp_cfm_to_fm(cksmat, rksmat, fmlocal)
1007 0 : CALL cp_cfm_to_fm(csmat, rsmat, fmlocal)
1008 : END IF
1009 : ELSE
1010 9114 : CALL harvest_operators(ikp, ispin)
1011 9114 : IF (ikp > kplocal) CYCLE
1012 : END IF
1013 24368 : kp => kpoints%kp_env(ikp)%kpoint_env
1014 45234 : IF (use_real_wfn) THEN
1015 156 : CALL get_mo_set(kp%mos(1, ispin), mo_coeff=mo_coeff, eigenvalues=eigenvalues)
1016 156 : IF (use_adiis) CALL shift_candidate_real(rksmat, rsmat, kp%mos(1, ispin), &
1017 0 : adiis_candidate_shift(scf_env))
1018 156 : IF (scf_env%cholesky_method == cholesky_off) THEN
1019 40 : CALL cp_fm_geeig_canon(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal, scf_control%eps_eigval)
1020 : ELSE
1021 116 : CALL cp_fm_geeig(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal)
1022 : END IF
1023 : ELSE
1024 24212 : CALL kp_solve_complex(kp%mos(:, ispin), workspace(1), scf_env, scf_control, use_adiis, .FALSE.)
1025 : END IF
1026 : END DO
1027 : END DO
1028 : END IF
1029 33754 : IF (ALLOCATED(coeffs)) DEALLOCATE (coeffs)
1030 :
1031 33754 : CALL kpoint_operator_context_release(op_ctx)
1032 :
1033 33754 : IF (update_p) THEN
1034 : ! MO occupations
1035 33578 : IF (PRESENT(probe) .EQV. .TRUE.) THEN
1036 0 : scf_control%smear%do_smear = .FALSE.
1037 : CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
1038 0 : probe=probe)
1039 : ELSE
1040 : CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
1041 : added_mos_auto=scf_control%added_mos_auto, &
1042 33578 : added_mos_auto_grow=my_added_mos_auto_grow)
1043 : END IF
1044 33578 : IF (my_added_mos_auto_grow) THEN
1045 0 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
1046 : ELSE
1047 : ! density matrices
1048 33578 : CALL kpoint_density_matrices(kpoints)
1049 : ! density matrices in real space
1050 : CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
1051 33578 : matrix_s(1, 1)%matrix, sab_nl, fmwork, overlap_rs=matrix_s)
1052 : END IF
1053 : END IF
1054 :
1055 33754 : IF (ASSOCIATED(rmatrix)) CALL dbcsr_deallocate_matrix(rmatrix)
1056 33754 : CALL rskp_transform_grid_release(s_grid)
1057 69302 : DO ispin = 1, nspin
1058 69302 : CALL rskp_transform_grid_release(ks_grid(ispin))
1059 : END DO
1060 69302 : DEALLOCATE (ks_grid)
1061 :
1062 33754 : IF (use_real_wfn) THEN
1063 130 : CALL cp_fm_release(rksmat)
1064 130 : CALL cp_fm_release(rsmat)
1065 : END IF
1066 33754 : IF (ALLOCATED(workspace)) CALL kp_diag_workspaces_release(workspace)
1067 33754 : CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
1068 :
1069 101262 : CALL timestop(handle)
1070 :
1071 : CONTAINS
1072 :
1073 : ! Serialized harvest only. Inactive tail rounds participate in every transfer,
1074 : ! then return before reading a local matrix or publishing the overlap cache.
1075 : ! **************************************************************************************************
1076 : !> \brief ...
1077 : !> \param round ...
1078 : !> \param spin ...
1079 : ! **************************************************************************************************
1080 24368 : SUBROUTINE harvest_operators(round, spin)
1081 : INTEGER, INTENT(IN) :: round, spin
1082 :
1083 24368 : IF (use_real_wfn) THEN
1084 156 : CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_ks, fm_re=rksmat)
1085 156 : CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_s, fm_re=rsmat)
1086 156 : IF (round <= kplocal .AND. do_diis) THEN
1087 0 : CALL cp_cfm_scale_and_add_fm(z_zero, cksmat, z_one, rksmat)
1088 0 : CALL cp_cfm_scale_and_add_fm(z_zero, csmat, z_one, rsmat)
1089 : END IF
1090 : ELSE
1091 24212 : CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_ks, cksmat)
1092 24212 : IF (.NOT. cache_smat .OR. (.NOT. reuse_smat .AND. spin == 1)) THEN
1093 3308 : CALL kpoint_operator_finish(op_ctx, round, spin, kpoint_slot_s, csmat)
1094 : END IF
1095 : END IF
1096 :
1097 24368 : IF (round > kplocal) RETURN
1098 24368 : kp => kpoints%kp_env(round)%kpoint_env
1099 24368 : IF (cache_smat) THEN
1100 23368 : IF (.NOT. reuse_smat .AND. spin == 1) THEN
1101 2464 : CALL cp_cfm_to_cfm(csmat, kpoints%scf_smat(round))
1102 : ELSE
1103 20904 : CALL cp_cfm_to_cfm(kpoints%scf_smat(round), csmat)
1104 : END IF
1105 : END IF
1106 : END SUBROUTINE harvest_operators
1107 :
1108 : END SUBROUTINE do_general_diag_kp
1109 :
1110 : ! **************************************************************************************************
1111 : !> \brief Execute a local numerical phase. All SCF decisions and collectives belong to the caller.
1112 : !> \param ctx immutable prepared operators
1113 : !> \param kpoints host environment
1114 : !> \param workspace private dense/phase/LAPACK storage per worker
1115 : !> \param scf_env SCF settings (read only during this phase)
1116 : !> \param scf_control SCF control
1117 : !> \param nspin spin count
1118 : !> \param cache_smat retain the unmodified overlap
1119 : !> \param reuse_smat overlap cache is already valid
1120 : !> \param use_adiis shift an ADIIS candidate only
1121 : !> \param ib DIIS insertion index
1122 : !> \param store_error store raw F and its residual instead of solving
1123 : !> \param diis_weight weight of the CDIIS candidate
1124 : !> \param coeffs optional DIIS coefficients for the second phase
1125 : ! **************************************************************************************************
1126 43118 : SUBROUTINE kp_diag_local_phase(ctx, kpoints, workspace, scf_env, scf_control, nspin, &
1127 43118 : cache_smat, reuse_smat, use_adiis, ib, store_error, diis_weight, coeffs)
1128 : TYPE(kpoint_operator_context_type), INTENT(IN) :: ctx
1129 : TYPE(kpoint_type), POINTER :: kpoints
1130 : TYPE(kp_diag_workspace_type), TARGET, INTENT(INOUT) :: workspace(:)
1131 : TYPE(qs_scf_env_type), POINTER :: scf_env
1132 : TYPE(scf_control_type), POINTER :: scf_control
1133 : INTEGER, INTENT(IN) :: nspin, ib
1134 : LOGICAL, INTENT(IN) :: cache_smat, reuse_smat, use_adiis, store_error
1135 : REAL(KIND=dp), INTENT(IN) :: diis_weight
1136 : COMPLEX(KIND=dp), OPTIONAL, INTENT(IN) :: coeffs(:)
1137 :
1138 : INTEGER :: ik, ikp, ispin, kplocal, nworkers, thread
1139 : LOGICAL :: build_h, build_s
1140 : TYPE(kpoint_env_type), POINTER :: kp
1141 : TYPE(kp_diag_workspace_type), POINTER :: work
1142 :
1143 43118 : kplocal = kpoints%kp_range(2) - kpoints%kp_range(1) + 1
1144 43118 : nworkers = SIZE(workspace)
1145 43118 : build_s = .NOT. PRESENT(coeffs) .AND. .NOT. reuse_smat
1146 19692 : build_h = .NOT. PRESENT(coeffs) .OR. diis_weight < 1.0_dp
1147 : ! Each one-rank group owns complete matrices: assemble directly into solver storage.
1148 : ! Keep the workspace binding explicit and thread-private for classic ifort.
1149 : !$OMP PARALLEL DO DEFAULT(NONE) SCHEDULE(DYNAMIC, 1) NUM_THREADS(nworkers) IF(nworkers > 1) &
1150 : !$OMP SHARED(ctx,kpoints,workspace,scf_env,scf_control,nspin,cache_smat,reuse_smat,use_adiis,ib, &
1151 : !$OMP store_error,diis_weight,coeffs,kplocal,nworkers,build_h,build_s) &
1152 43118 : !$OMP PRIVATE(ik,ikp,ispin,thread,kp,work)
1153 : DO ikp = 1, kplocal
1154 : thread = 1
1155 : !$ thread = omp_get_thread_num() + 1
1156 : ik = kpoints%kp_range(1) + ikp - 1
1157 : kp => kpoints%kp_env(ikp)%kpoint_env
1158 : work => workspace(thread)
1159 : IF (build_s) THEN
1160 : CALL kpoint_operator_evaluate(ctx, 1, kpoint_slot_s, ik, work%phase, work%csmat_base)
1161 : END IF
1162 : DO ispin = 1, nspin
1163 : IF (build_h) THEN
1164 : IF (PRESENT(coeffs)) THEN
1165 : CALL kpoint_operator_evaluate(ctx, ispin, kpoint_slot_ks, ik, work%phase, work%csmat_base)
1166 : ELSE
1167 : CALL kpoint_operator_evaluate(ctx, ispin, kpoint_slot_ks, ik, work%phase, work%cksmat)
1168 : END IF
1169 : END IF
1170 : IF (PRESENT(coeffs)) THEN
1171 : CALL cp_cfm_to_cfm(kpoints%scf_diis_buffer%smat(ikp), work%csmat)
1172 : CALL kp_diis_candidate(kpoints, ikp, ispin, coeffs, diis_weight, work%cksmat, work%csmat_base)
1173 : ELSE
1174 : IF (reuse_smat) THEN
1175 : CALL cp_cfm_to_cfm(kpoints%scf_smat(ikp), work%csmat)
1176 : ELSE
1177 : CALL cp_cfm_to_cfm(work%csmat_base, work%csmat)
1178 : END IF
1179 : IF (cache_smat .AND. .NOT. reuse_smat .AND. ispin == 1) THEN
1180 : CALL cp_cfm_to_cfm(work%csmat, kpoints%scf_smat(ikp))
1181 : END IF
1182 : END IF
1183 : IF (store_error) THEN
1184 : CALL qs_diis_b_calc_err_kp(kpoints%scf_diis_buffer, ib, kp%mos, work%cksmat, work%csmat, &
1185 : ispin, ikp, work%cmos, local=.TRUE., gemm_ctx=work%gemm_ctx)
1186 : ELSE
1187 : CALL kp_solve_complex(kp%mos(:, ispin), work, scf_env, scf_control, use_adiis, .TRUE.)
1188 : END IF
1189 : END DO
1190 : END DO
1191 : !$OMP END PARALLEL DO
1192 :
1193 43118 : END SUBROUTINE kp_diag_local_phase
1194 :
1195 : ! **************************************************************************************************
1196 : !> \brief Form the same candidate on local and distributed layouts, preserving raw DIIS history.
1197 : !> \param kpoints host DIIS buffer
1198 : !> \param ikp local k-point index
1199 : !> \param ispin spin index
1200 : !> \param coeffs DIIS coefficients
1201 : !> \param weight CDIIS blend weight
1202 : !> \param fock output candidate
1203 : !> \param adiis_fock ADIIS candidate, read only when weight is less than one
1204 : ! **************************************************************************************************
1205 48874 : SUBROUTINE kp_diis_candidate(kpoints, ikp, ispin, coeffs, weight, fock, adiis_fock)
1206 : TYPE(kpoint_type), POINTER :: kpoints
1207 : INTEGER, INTENT(IN) :: ikp, ispin
1208 : COMPLEX(KIND=dp), INTENT(IN) :: coeffs(:)
1209 : REAL(KIND=dp), INTENT(IN) :: weight
1210 : TYPE(cp_cfm_type), INTENT(INOUT) :: fock
1211 : TYPE(cp_cfm_type), INTENT(IN) :: adiis_fock
1212 :
1213 : INTEGER :: jb
1214 :
1215 48874 : CALL cp_cfm_set_all(fock, z_zero)
1216 212913 : DO jb = 1, SIZE(coeffs)
1217 212913 : CALL cp_cfm_scale_and_add(z_one, fock, coeffs(jb), kpoints%scf_diis_buffer%param(jb, ispin, ikp))
1218 : END DO
1219 48874 : IF (weight < 1.0_dp) CALL cp_cfm_scale_and_add(CMPLX(weight, KIND=dp), fock, &
1220 30 : CMPLX(1.0_dp - weight, KIND=dp), adiis_fock)
1221 48874 : END SUBROUTINE kp_diis_candidate
1222 :
1223 : ! **************************************************************************************************
1224 : !> \brief Shift, solve and publish a complex SCF candidate using private scratch.
1225 : !> \param mos real/imaginary MO sets
1226 : !> \param work private workspace
1227 : !> \param scf_env SCF settings
1228 : !> \param scf_control SCF control
1229 : !> \param use_adiis apply the candidate shift
1230 : !> \param local select the one-rank local solver; otherwise honor the configured backend
1231 : ! **************************************************************************************************
1232 67937 : SUBROUTINE kp_solve_complex(mos, work, scf_env, scf_control, use_adiis, local)
1233 : TYPE(mo_set_type), INTENT(INOUT) :: mos(:)
1234 : TYPE(kp_diag_workspace_type), INTENT(INOUT) :: work
1235 : TYPE(qs_scf_env_type), POINTER :: scf_env
1236 : TYPE(scf_control_type), POINTER :: scf_control
1237 : LOGICAL, INTENT(IN) :: use_adiis, local
1238 :
1239 67937 : REAL(KIND=dp), POINTER :: eigenvalues(:)
1240 :
1241 67937 : CALL get_mo_set(mos(1), eigenvalues=eigenvalues)
1242 67937 : IF (use_adiis) CALL shift_candidate_complex(work%cksmat, work%csmat, mos, work%cmos, work%cwork, &
1243 138 : adiis_candidate_shift(scf_env), local, work%gemm_ctx)
1244 67937 : IF (scf_env%cholesky_method == cholesky_off) THEN
1245 3628 : IF (local) THEN
1246 : CALL cp_cfm_geeig_canon_local(work%cksmat, work%csmat, work%cmos, eigenvalues, work%cwork, &
1247 1400 : scf_control%eps_eigval, ws=work%solver)
1248 : ELSE
1249 2228 : CALL cp_cfm_geeig_canon(work%cksmat, work%csmat, work%cmos, eigenvalues, work%cwork, scf_control%eps_eigval)
1250 : END IF
1251 : ELSE
1252 64309 : IF (local) THEN
1253 42325 : CALL cp_cfm_geeig_local(work%cksmat, work%csmat, work%cmos, eigenvalues, ws=work%solver)
1254 : ELSE
1255 21984 : CALL cp_cfm_geeig(work%cksmat, work%csmat, work%cmos, eigenvalues, work%cwork)
1256 : END IF
1257 : END IF
1258 67937 : CALL kpoint_operator_cfm_to_mo(work%cmos, mos(1), mos(2), eigenvalues)
1259 67937 : END SUBROUTINE kp_solve_complex
1260 :
1261 : ! **************************************************************************************************
1262 : !> \brief Allocate all worker storage before launching numerical phases.
1263 : !> \param workspace returned private workspaces
1264 : !> \param nworkers number of workers
1265 : !> \param matrix_struct AO layout of the k-point group
1266 : !> \param mo_struct MO layout of the k-point group
1267 : !> \param nentry number of phase-sum entries
1268 : !> \param local allocate local phase and solver scratch
1269 : !> \param canonical use the canonical solver
1270 : ! **************************************************************************************************
1271 33624 : SUBROUTINE kp_diag_workspaces_create(workspace, nworkers, matrix_struct, mo_struct, nentry, local, canonical)
1272 : TYPE(kp_diag_workspace_type), ALLOCATABLE, &
1273 : INTENT(OUT) :: workspace(:)
1274 : INTEGER, INTENT(IN) :: nworkers
1275 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct, mo_struct
1276 : INTEGER, INTENT(IN) :: nentry
1277 : LOGICAL, INTENT(IN) :: local, canonical
1278 :
1279 : INTEGER :: i, n
1280 :
1281 134496 : ALLOCATE (workspace(nworkers))
1282 67248 : DO i = 1, nworkers
1283 33624 : CALL cp_cfm_create(workspace(i)%cksmat, matrix_struct)
1284 33624 : CALL cp_cfm_create(workspace(i)%csmat, matrix_struct)
1285 33624 : CALL cp_cfm_create(workspace(i)%cwork, matrix_struct)
1286 33624 : CALL cp_cfm_create(workspace(i)%cmos, mo_struct)
1287 33624 : IF (.NOT. local) CYCLE
1288 23426 : CALL workspace(i)%gemm_ctx%create(LOCAL_GEMM_PU_GPU, timing=.FALSE.)
1289 23426 : CALL cp_cfm_create(workspace(i)%csmat_base, matrix_struct)
1290 70278 : ALLOCATE (workspace(i)%phase(1, nentry))
1291 23426 : n = matrix_struct%nrow_global
1292 57050 : IF (canonical) THEN
1293 596 : CALL cp_cfm_local_workspace_prepare(workspace(i)%solver, n, workspace(i)%cksmat%local_data)
1294 : ELSE
1295 : CALL cp_cfm_local_workspace_prepare(workspace(i)%solver, n, workspace(i)%cksmat%local_data, &
1296 22830 : workspace(i)%csmat%local_data)
1297 : END IF
1298 : END DO
1299 33624 : END SUBROUTINE kp_diag_workspaces_create
1300 :
1301 : ! **************************************************************************************************
1302 : !> \brief Release dense matrices and automatic phase/LAPACK allocations after all workers finish.
1303 : !> \param workspace private workspaces
1304 : ! **************************************************************************************************
1305 33624 : SUBROUTINE kp_diag_workspaces_release(workspace)
1306 : TYPE(kp_diag_workspace_type), ALLOCATABLE, &
1307 : INTENT(INOUT) :: workspace(:)
1308 :
1309 : INTEGER :: i
1310 :
1311 67248 : DO i = 1, SIZE(workspace)
1312 33624 : CALL workspace(i)%gemm_ctx%destroy()
1313 33624 : CALL cp_cfm_release(workspace(i)%cksmat)
1314 33624 : CALL cp_cfm_release(workspace(i)%csmat)
1315 33624 : CALL cp_cfm_release(workspace(i)%csmat_base)
1316 33624 : CALL cp_cfm_release(workspace(i)%cwork)
1317 67248 : CALL cp_cfm_release(workspace(i)%cmos)
1318 : END DO
1319 67248 : DEALLOCATE (workspace)
1320 33624 : END SUBROUTINE kp_diag_workspaces_release
1321 :
1322 : ! **************************************************************************************************
1323 : !> \brief Kpoint diagonalization routine
1324 : !> Transforms matrices to kpoint, distributes kpoint groups, performs
1325 : !> general diagonalization (no storgae of overlap decomposition), stores
1326 : !> MOs, calculates occupation numbers, calculates density matrices
1327 : !> in kpoint representation, transforms density matrices to real space
1328 : !> \param matrix_ks Kohn-sham matrices (RS indices, global)
1329 : !> \param matrix_s Overlap matrices (RS indices, global)
1330 : !> \param kpoints Kpoint environment
1331 : !> \param fmwork global-layout FM template in the first array entry
1332 : !> \par History
1333 : !> 08.2014 created [JGH]
1334 : ! **************************************************************************************************
1335 22 : SUBROUTINE diag_kp_basic(matrix_ks, matrix_s, kpoints, fmwork)
1336 :
1337 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
1338 : TYPE(kpoint_type), POINTER :: kpoints
1339 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
1340 :
1341 : CHARACTER(len=*), PARAMETER :: routineN = 'diag_kp_basic'
1342 :
1343 : INTEGER :: handle, ikp, ispin, kplocal, kpmax, nspin
1344 : INTEGER, DIMENSION(2) :: kp_range
1345 22 : INTEGER, DIMENSION(:, :), POINTER :: kp_dist
1346 : LOGICAL :: use_real_wfn
1347 22 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
1348 : TYPE(cp_cfm_type) :: cksmat, cmos, csmat, cwork
1349 22 : TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER :: ao_ao_fm_pools
1350 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct, mo_struct
1351 : TYPE(cp_fm_type) :: fmlocal, rksmat, rsmat
1352 : TYPE(cp_fm_type), POINTER :: mo_coeff
1353 : TYPE(kpoint_env_type), POINTER :: kp
1354 22 : TYPE(kpoint_operator_context_type) :: op_ctx
1355 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1356 22 : POINTER :: sab_nl
1357 : TYPE(qs_matrix_pools_type), POINTER :: mpools
1358 :
1359 22 : CALL timeset(routineN, handle)
1360 :
1361 22 : NULLIFY (sab_nl)
1362 : CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, kp_range=kp_range, &
1363 22 : kp_dist=kp_dist, sab_nl=sab_nl)
1364 22 : CPASSERT(ASSOCIATED(sab_nl))
1365 22 : kplocal = kp_range(2) - kp_range(1) + 1
1366 46 : kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
1367 :
1368 : ! fm pools to be used within a kpoint group
1369 22 : CALL get_kpoint_info(kpoints, mpools=mpools)
1370 22 : CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
1371 :
1372 22 : CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
1373 22 : CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
1374 :
1375 22 : IF (use_real_wfn) THEN
1376 0 : CALL cp_fm_create(rksmat, matrix_struct)
1377 0 : CALL cp_fm_create(rsmat, matrix_struct)
1378 : ELSE
1379 22 : CALL cp_cfm_create(cksmat, matrix_struct)
1380 22 : CALL cp_cfm_create(csmat, matrix_struct)
1381 22 : CALL cp_cfm_create(cwork, matrix_struct)
1382 22 : kp => kpoints%kp_env(1)%kpoint_env
1383 22 : CALL get_mo_set(kp%mos(1, 1), mo_coeff=mo_coeff)
1384 22 : CALL cp_fm_get_info(mo_coeff, matrix_struct=mo_struct)
1385 22 : CALL cp_cfm_create(cmos, mo_struct)
1386 : END IF
1387 :
1388 22 : nspin = SIZE(matrix_ks, 1)
1389 22 : CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
1390 22 : CALL kpoint_operator_prepare(op_ctx, matrix_ks, kpoint_slot_ks)
1391 22 : CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, matrix_row=kpoint_spin_free)
1392 94 : DO ikp = 1, kpmax
1393 166 : DO ispin = 1, nspin
1394 : CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_ks, kpoint_slot_ks, &
1395 72 : use_grid=.FALSE., matrix_row=ispin)
1396 : CALL kpoint_operator_start(op_ctx, ikp, ispin, matrix_s, kpoint_slot_s, &
1397 144 : use_grid=.FALSE., matrix_row=kpoint_spin_free)
1398 : END DO
1399 : END DO
1400 :
1401 : ! Finish communication then diagonalise in each group
1402 94 : DO ikp = 1, kpmax
1403 166 : DO ispin = 1, nspin
1404 72 : IF (use_real_wfn) THEN
1405 0 : CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, fm_re=rksmat)
1406 0 : CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_s, fm_re=rsmat)
1407 : ELSE
1408 72 : CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_ks, cksmat)
1409 72 : CALL kpoint_operator_finish(op_ctx, ikp, ispin, kpoint_slot_s, csmat)
1410 : END IF
1411 :
1412 : ! Each kpoint group has now information on a kpoint to be diagonalized
1413 : ! General eigensolver Hermite or Symmetric
1414 72 : IF (ikp > kplocal) CYCLE
1415 72 : kp => kpoints%kp_env(ikp)%kpoint_env
1416 144 : IF (use_real_wfn) THEN
1417 0 : CALL get_mo_set(kp%mos(1, ispin), mo_coeff=mo_coeff, eigenvalues=eigenvalues)
1418 0 : CALL cp_fm_geeig(rksmat, rsmat, mo_coeff, eigenvalues, fmlocal)
1419 : ELSE
1420 72 : CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1421 72 : CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
1422 : ! split the real and imaginary parts of the mos and copy the eigenvalues to the imaginary set
1423 72 : CALL kpoint_operator_cfm_to_mo(cmos, kp%mos(1, ispin), kp%mos(2, ispin), eigenvalues)
1424 : END IF
1425 : END DO
1426 : END DO
1427 :
1428 22 : CALL kpoint_operator_context_release(op_ctx)
1429 :
1430 22 : IF (use_real_wfn) THEN
1431 0 : CALL cp_fm_release(rksmat)
1432 0 : CALL cp_fm_release(rsmat)
1433 : ELSE
1434 22 : CALL cp_cfm_release(cksmat)
1435 22 : CALL cp_cfm_release(csmat)
1436 22 : CALL cp_cfm_release(cwork)
1437 22 : CALL cp_cfm_release(cmos)
1438 : END IF
1439 22 : CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
1440 :
1441 22 : CALL timestop(handle)
1442 :
1443 44 : END SUBROUTINE diag_kp_basic
1444 :
1445 : ! **************************************************************************************************
1446 : !> \brief inner loop within MOS subspace, to refine occupation and density,
1447 : !> before next diagonalization of the Hamiltonian
1448 : !> \param qs_env ...
1449 : !> \param scf_env ...
1450 : !> \param subspace_env ...
1451 : !> \param mos ...
1452 : !> \param rho ...
1453 : !> \param ks_env ...
1454 : !> \param scf_section ...
1455 : !> \param scf_control ...
1456 : !> \par History
1457 : !> 09.2009 created [MI]
1458 : !> \note it is assumed that when diagonalization is used, also some mixing procedure is active
1459 : ! **************************************************************************************************
1460 10 : SUBROUTINE do_scf_diag_subspace(qs_env, scf_env, subspace_env, mos, rho, &
1461 : ks_env, scf_section, scf_control)
1462 :
1463 : TYPE(qs_environment_type), POINTER :: qs_env
1464 : TYPE(qs_scf_env_type), POINTER :: scf_env
1465 : TYPE(subspace_env_type), POINTER :: subspace_env
1466 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
1467 : TYPE(qs_rho_type), POINTER :: rho
1468 : TYPE(qs_ks_env_type), POINTER :: ks_env
1469 : TYPE(section_vals_type), POINTER :: scf_section
1470 : TYPE(scf_control_type), POINTER :: scf_control
1471 :
1472 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_scf_diag_subspace'
1473 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
1474 :
1475 : INTEGER :: handle, i, iloop, ispin, nao, nmo, &
1476 : nspin, output_unit
1477 : LOGICAL :: converged
1478 : REAL(dp) :: ene_diff, ene_old, iter_delta, max_val, &
1479 : sum_band, sum_val, t1, t2
1480 10 : REAL(KIND=dp), DIMENSION(:), POINTER :: mo_eigenvalues, mo_occupations
1481 10 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:) :: eval_first, occ_first
1482 : TYPE(cp_fm_type) :: work
1483 : TYPE(cp_fm_type), POINTER :: c0, chc, evec, mo_coeff
1484 : TYPE(cp_logger_type), POINTER :: logger
1485 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s, rho_ao
1486 10 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
1487 : TYPE(dft_control_type), POINTER :: dft_control
1488 : TYPE(mp_para_env_type), POINTER :: para_env
1489 : TYPE(qs_energy_type), POINTER :: energy
1490 10 : TYPE(rho_atom_type), DIMENSION(:), POINTER :: rho_atom
1491 :
1492 10 : CALL timeset(routineN, handle)
1493 10 : NULLIFY (c0, chc, energy, evec, matrix_ks, mo_coeff, mo_eigenvalues, &
1494 10 : mo_occupations, dft_control, rho_ao, rho_ao_kp)
1495 :
1496 10 : logger => cp_get_default_logger()
1497 : output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DIAG_SUB_SCF", &
1498 10 : extension=".scfLog")
1499 :
1500 : !Extra loop keeping mos unchanged and refining the subspace occupation
1501 10 : nspin = SIZE(mos)
1502 10 : CALL qs_rho_get(rho, rho_ao=rho_ao, rho_ao_kp=rho_ao_kp)
1503 :
1504 40 : ALLOCATE (eval_first(nspin))
1505 40 : ALLOCATE (occ_first(nspin))
1506 20 : DO ispin = 1, nspin
1507 : CALL get_mo_set(mo_set=mos(ispin), &
1508 : nmo=nmo, &
1509 : eigenvalues=mo_eigenvalues, &
1510 10 : occupation_numbers=mo_occupations)
1511 30 : ALLOCATE (eval_first(ispin)%array(nmo))
1512 20 : ALLOCATE (occ_first(ispin)%array(nmo))
1513 50 : eval_first(ispin)%array(1:nmo) = mo_eigenvalues(1:nmo)
1514 70 : occ_first(ispin)%array(1:nmo) = mo_occupations(1:nmo)
1515 : END DO
1516 :
1517 20 : DO ispin = 1, nspin
1518 : ! does not yet handle k-points
1519 10 : CALL dbcsr_copy(subspace_env%p_matrix_store(ispin)%matrix, rho_ao(ispin)%matrix)
1520 20 : CALL dbcsr_copy(rho_ao(ispin)%matrix, scf_env%p_mix_new(ispin, 1)%matrix)
1521 : END DO
1522 :
1523 10 : subspace_env%p_matrix_mix => scf_env%p_mix_new
1524 :
1525 10 : NULLIFY (matrix_ks, energy, para_env, matrix_s)
1526 : CALL get_qs_env(qs_env, &
1527 : matrix_ks=matrix_ks, &
1528 : energy=energy, &
1529 : matrix_s=matrix_s, &
1530 : para_env=para_env, &
1531 10 : dft_control=dft_control)
1532 :
1533 : ! mixing storage allocation
1534 10 : IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
1535 : CALL mixing_allocate(qs_env, subspace_env%mixing_method, scf_env%p_mix_new, &
1536 0 : scf_env%p_delta, nspin, subspace_env%mixing_store)
1537 0 : IF (dft_control%qs_control%gapw) THEN
1538 0 : CALL get_qs_env(qs_env=qs_env, rho_atom_set=rho_atom)
1539 : CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, &
1540 0 : para_env, rho_atom=rho_atom)
1541 0 : ELSE IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
1542 0 : CALL charge_mixing_init(subspace_env%mixing_store)
1543 0 : ELSE IF (dft_control%qs_control%semi_empirical) THEN
1544 0 : CPABORT('SE Code not possible')
1545 : ELSE
1546 0 : CALL mixing_init(subspace_env%mixing_method, rho, subspace_env%mixing_store, para_env)
1547 : END IF
1548 : END IF
1549 :
1550 10 : ene_old = 0.0_dp
1551 : ene_diff = 0.0_dp
1552 10 : IF (output_unit > 0) THEN
1553 0 : WRITE (output_unit, "(/T19,A)") '<<<<<<<<< SUBSPACE ROTATION <<<<<<<<<<'
1554 : WRITE (output_unit, "(T4,A,T13,A,T21,A,T38,A,T51,A,T65,A/,T4,A)") &
1555 0 : "In-step", "Time", "Convergence", "Band ene.", "Total ene.", "Energy diff.", REPEAT("-", 74)
1556 : END IF
1557 :
1558 : ! recalculate density matrix here
1559 :
1560 : ! update of density
1561 10 : CALL qs_rho_update_rho(rho, qs_env=qs_env)
1562 :
1563 22 : DO iloop = 1, subspace_env%max_iter
1564 20 : t1 = m_walltime()
1565 20 : converged = .FALSE.
1566 20 : ene_old = energy%total
1567 :
1568 20 : CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
1569 : CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., &
1570 20 : just_energy=.FALSE., print_active=.FALSE.)
1571 :
1572 20 : max_val = 0.0_dp
1573 20 : sum_val = 0.0_dp
1574 20 : sum_band = 0.0_dp
1575 40 : DO ispin = 1, SIZE(matrix_ks)
1576 : CALL get_mo_set(mo_set=mos(ispin), &
1577 : nao=nao, &
1578 : nmo=nmo, &
1579 : eigenvalues=mo_eigenvalues, &
1580 : occupation_numbers=mo_occupations, &
1581 20 : mo_coeff=mo_coeff)
1582 :
1583 : !compute C'HC
1584 20 : chc => subspace_env%chc_mat(ispin)
1585 20 : evec => subspace_env%c_vec(ispin)
1586 20 : c0 => subspace_env%c0(ispin)
1587 20 : CALL cp_fm_to_fm(mo_coeff, c0)
1588 20 : CALL cp_fm_create(work, c0%matrix_struct)
1589 20 : CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, c0, work, nmo)
1590 20 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
1591 20 : CALL cp_fm_release(work)
1592 : !diagonalize C'HC
1593 20 : CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
1594 :
1595 : !rotate the mos by the eigenvectors of C'HC
1596 20 : CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, mo_coeff)
1597 :
1598 20 : IF (.NOT. scf_control%gce%do_gce) THEN
1599 : CALL set_mo_occupation(mo_set=mos(ispin), &
1600 20 : smear=scf_control%smear)
1601 : ELSE
1602 : CALL set_mo_occupation(mo_set=mos(ispin), &
1603 : smear=scf_control%smear, &
1604 0 : gce=scf_control%gce)
1605 : END IF
1606 :
1607 : ! does not yet handle k-points
1608 : CALL calculate_density_matrix(mos(ispin), &
1609 20 : subspace_env%p_matrix_mix(ispin, 1)%matrix)
1610 :
1611 160 : DO i = 1, nmo
1612 100 : sum_band = sum_band + mo_eigenvalues(i)*mo_occupations(i)
1613 : END DO
1614 :
1615 : !check for self consistency
1616 : END DO
1617 :
1618 20 : IF (subspace_env%mixing_method == direct_mixing_nr) THEN
1619 : CALL scf_env_density_mixing(subspace_env%p_matrix_mix, &
1620 20 : scf_env%mixing_store, rho_ao_kp, para_env, iter_delta, iloop)
1621 : ELSE
1622 : CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, &
1623 0 : subspace_env%p_matrix_mix, delta=iter_delta)
1624 : END IF
1625 :
1626 40 : DO ispin = 1, nspin
1627 : ! does not yet handle k-points
1628 40 : CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_mix(ispin, 1)%matrix)
1629 : END DO
1630 : ! update of density
1631 20 : CALL qs_rho_update_rho(rho, qs_env=qs_env)
1632 : ! Mixing in reciprocal space
1633 20 : IF (subspace_env%mixing_method >= gspace_mixing_nr) THEN
1634 : CALL gspace_mixing(qs_env, scf_env%mixing_method, subspace_env%mixing_store, &
1635 0 : rho, para_env, scf_env%iter_count)
1636 : END IF
1637 :
1638 20 : ene_diff = energy%total - ene_old
1639 : converged = (ABS(ene_diff) < subspace_env%eps_ene .AND. &
1640 20 : iter_delta < subspace_env%eps_adapt*scf_env%iter_delta)
1641 20 : t2 = m_walltime()
1642 20 : IF (output_unit > 0) THEN
1643 : WRITE (output_unit, "(T4,I5,T11,F8.3,T18,E14.4,T34,F12.5,T46,F16.8,T62,E14.4)") &
1644 0 : iloop, t2 - t1, iter_delta, sum_band, energy%total, ene_diff
1645 0 : CALL m_flush(output_unit)
1646 : END IF
1647 22 : IF (converged) THEN
1648 8 : IF (output_unit > 0) WRITE (output_unit, "(T10,A,I6,A,/)") &
1649 0 : " Reached convergence in ", iloop, " iterations "
1650 : EXIT
1651 : END IF
1652 :
1653 : END DO ! iloop
1654 :
1655 10 : NULLIFY (subspace_env%p_matrix_mix)
1656 20 : DO ispin = 1, nspin
1657 : ! does not yet handle k-points
1658 10 : CALL dbcsr_copy(scf_env%p_mix_new(ispin, 1)%matrix, rho_ao(ispin)%matrix)
1659 10 : CALL dbcsr_copy(rho_ao(ispin)%matrix, subspace_env%p_matrix_store(ispin)%matrix)
1660 :
1661 20 : DEALLOCATE (eval_first(ispin)%array, occ_first(ispin)%array)
1662 : END DO
1663 10 : DEALLOCATE (eval_first, occ_first)
1664 :
1665 10 : CALL timestop(handle)
1666 :
1667 10 : END SUBROUTINE do_scf_diag_subspace
1668 :
1669 : ! **************************************************************************************************
1670 : !> \brief ...
1671 : !> \param subspace_env ...
1672 : !> \param qs_env ...
1673 : !> \param mos ...
1674 : ! **************************************************************************************************
1675 2 : SUBROUTINE diag_subspace_allocate(subspace_env, qs_env, mos)
1676 :
1677 : TYPE(subspace_env_type), POINTER :: subspace_env
1678 : TYPE(qs_environment_type), POINTER :: qs_env
1679 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
1680 :
1681 : CHARACTER(LEN=*), PARAMETER :: routineN = 'diag_subspace_allocate'
1682 :
1683 : INTEGER :: handle, i, ispin, nmo, nspin
1684 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
1685 : TYPE(cp_fm_type), POINTER :: mo_coeff
1686 2 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1687 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1688 2 : POINTER :: sab_orb
1689 :
1690 2 : CALL timeset(routineN, handle)
1691 :
1692 2 : NULLIFY (sab_orb, matrix_s)
1693 : CALL get_qs_env(qs_env=qs_env, sab_orb=sab_orb, &
1694 2 : matrix_s=matrix_s)
1695 :
1696 2 : nspin = SIZE(mos)
1697 : ! *** allocate p_atrix_store ***
1698 2 : IF (.NOT. ASSOCIATED(subspace_env%p_matrix_store)) THEN
1699 2 : CALL dbcsr_allocate_matrix_set(subspace_env%p_matrix_store, nspin)
1700 :
1701 4 : DO i = 1, nspin
1702 2 : ALLOCATE (subspace_env%p_matrix_store(i)%matrix)
1703 : CALL dbcsr_create(matrix=subspace_env%p_matrix_store(i)%matrix, template=matrix_s(1)%matrix, &
1704 2 : name="DENSITY_STORE", matrix_type=dbcsr_type_symmetric)
1705 : CALL cp_dbcsr_alloc_block_from_nbl(subspace_env%p_matrix_store(i)%matrix, &
1706 2 : sab_orb)
1707 4 : CALL dbcsr_set(subspace_env%p_matrix_store(i)%matrix, 0.0_dp)
1708 : END DO
1709 :
1710 : END IF
1711 :
1712 8 : ALLOCATE (subspace_env%chc_mat(nspin))
1713 6 : ALLOCATE (subspace_env%c_vec(nspin))
1714 6 : ALLOCATE (subspace_env%c0(nspin))
1715 :
1716 4 : DO ispin = 1, nspin
1717 2 : CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo)
1718 2 : CALL cp_fm_create(subspace_env%c0(ispin), mo_coeff%matrix_struct)
1719 2 : NULLIFY (fm_struct_tmp)
1720 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nmo, ncol_global=nmo, &
1721 : para_env=mo_coeff%matrix_struct%para_env, &
1722 2 : context=mo_coeff%matrix_struct%context)
1723 2 : CALL cp_fm_create(subspace_env%chc_mat(ispin), fm_struct_tmp, "chc")
1724 2 : CALL cp_fm_create(subspace_env%c_vec(ispin), fm_struct_tmp, "vec")
1725 6 : CALL cp_fm_struct_release(fm_struct_tmp)
1726 : END DO
1727 :
1728 2 : CALL timestop(handle)
1729 :
1730 2 : END SUBROUTINE diag_subspace_allocate
1731 :
1732 : ! **************************************************************************************************
1733 : !> \brief the inner loop of scf, specific to diagonalization without S matrix
1734 : !> basically, in goes the ks matrix out goes a new p matrix
1735 : !> \param scf_env ...
1736 : !> \param mos ...
1737 : !> \param matrix_ks ...
1738 : !> \param scf_control ...
1739 : !> \param scf_section ...
1740 : !> \param diis_step ...
1741 : !> \par History
1742 : !> 03.2006 created [Joost VandeVondele]
1743 : ! **************************************************************************************************
1744 17876 : SUBROUTINE do_special_diag(scf_env, mos, matrix_ks, scf_control, &
1745 : scf_section, diis_step)
1746 :
1747 : TYPE(qs_scf_env_type), POINTER :: scf_env
1748 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
1749 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1750 : TYPE(scf_control_type), POINTER :: scf_control
1751 : TYPE(section_vals_type), POINTER :: scf_section
1752 : LOGICAL, INTENT(INOUT) :: diis_step
1753 :
1754 : INTEGER :: ispin, nspin
1755 : LOGICAL :: do_level_shift, use_jacobi
1756 : REAL(KIND=dp) :: diis_error
1757 :
1758 17876 : nspin = SIZE(matrix_ks)
1759 :
1760 36518 : DO ispin = 1, nspin
1761 36518 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, scf_env%scf_work1(ispin))
1762 : END DO
1763 17876 : IF (scf_env%iter_count > 1 .AND. .NOT. scf_env%skip_diis) THEN
1764 : CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
1765 : scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
1766 : scf_control%eps_diis, scf_control%nmixing, &
1767 15282 : scf_section=scf_section)
1768 : ELSE
1769 2594 : diis_step = .FALSE.
1770 : END IF
1771 :
1772 17876 : IF ((scf_env%iter_count > 1) .AND. (scf_env%iter_delta < scf_control%diagonalization%eps_jacobi)) THEN
1773 18 : use_jacobi = .TRUE.
1774 : ELSE
1775 17858 : use_jacobi = .FALSE.
1776 : END IF
1777 :
1778 : do_level_shift = ((scf_control%level_shift /= 0.0_dp) .AND. &
1779 17876 : ((scf_control%density_guess == core_guess) .OR. (scf_env%iter_count > 1)))
1780 17876 : IF (diis_step) THEN
1781 11870 : scf_env%iter_param = diis_error
1782 11870 : IF (use_jacobi) THEN
1783 18 : scf_env%iter_method = "DIIS/Jacobi"
1784 : ELSE
1785 11852 : scf_env%iter_method = "DIIS/Diag."
1786 : END IF
1787 : ELSE
1788 6006 : IF (scf_env%mixing_method == 1) THEN
1789 6006 : scf_env%iter_param = scf_env%p_mix_alpha
1790 6006 : IF (use_jacobi) THEN
1791 0 : scf_env%iter_method = "P_Mix/Jacobi"
1792 : ELSE
1793 6006 : scf_env%iter_method = "P_Mix/Diag."
1794 : END IF
1795 0 : ELSE IF (scf_env%mixing_method > 1) THEN
1796 0 : scf_env%iter_param = scf_env%mixing_store%alpha
1797 0 : IF (use_jacobi) THEN
1798 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Jacobi"
1799 : ELSE
1800 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
1801 : END IF
1802 : END IF
1803 : END IF
1804 17876 : scf_env%iter_delta = 0.0_dp
1805 :
1806 36518 : DO ispin = 1, nspin
1807 : CALL eigensolver_simple(matrix_ks=scf_env%scf_work1(ispin), &
1808 : mo_set=mos(ispin), &
1809 : work=scf_env%scf_work2, &
1810 : do_level_shift=do_level_shift, &
1811 : level_shift=scf_control%level_shift, &
1812 : use_jacobi=use_jacobi, &
1813 36518 : jacobi_threshold=scf_control%diagonalization%jacobi_threshold)
1814 : END DO
1815 :
1816 17876 : IF (.NOT. scf_control%gce%do_gce) THEN
1817 : CALL set_mo_occupation(mo_array=mos, &
1818 17876 : smear=scf_control%smear)
1819 : ELSE
1820 : CALL set_mo_occupation(mo_array=mos, &
1821 : smear=scf_control%smear, &
1822 0 : gce=scf_control%gce)
1823 : END IF
1824 :
1825 36518 : DO ispin = 1, nspin
1826 : ! does not yet handle k-points
1827 : CALL calculate_density_matrix(mos(ispin), &
1828 36518 : scf_env%p_mix_new(ispin, 1)%matrix)
1829 : END DO
1830 :
1831 17876 : END SUBROUTINE do_special_diag
1832 :
1833 : ! **************************************************************************************************
1834 : !> \brief the inner loop of scf, specific to iterative diagonalization using OT
1835 : !> with S matrix; basically, in goes the ks matrix out goes a new p matrix
1836 : !> \param scf_env ...
1837 : !> \param mos ...
1838 : !> \param matrix_ks ...
1839 : !> \param matrix_s ...
1840 : !> \param scf_control ...
1841 : !> \param scf_section ...
1842 : !> \param diis_step ...
1843 : !> \par History
1844 : !> 10.2008 created [JGH]
1845 : ! **************************************************************************************************
1846 202 : SUBROUTINE do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
1847 : scf_control, scf_section, diis_step)
1848 :
1849 : TYPE(qs_scf_env_type), POINTER :: scf_env
1850 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
1851 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
1852 : TYPE(scf_control_type), POINTER :: scf_control
1853 : TYPE(section_vals_type), POINTER :: scf_section
1854 : LOGICAL, INTENT(INOUT) :: diis_step
1855 :
1856 : INTEGER :: homo, ispin, nmo, nspin
1857 : REAL(KIND=dp) :: diis_error, eps_iter
1858 202 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
1859 : TYPE(cp_fm_type), POINTER :: mo_coeff
1860 :
1861 202 : NULLIFY (eigenvalues)
1862 :
1863 202 : nspin = SIZE(matrix_ks)
1864 :
1865 448 : DO ispin = 1, nspin
1866 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
1867 448 : scf_env%scf_work1(ispin))
1868 : END DO
1869 :
1870 202 : IF ((scf_env%iter_count > 1) .AND. (.NOT. scf_env%skip_diis)) THEN
1871 : CALL qs_diis_b_step(scf_env%scf_diis_buffer, mos, scf_env%scf_work1, &
1872 : scf_env%scf_work2, scf_env%iter_delta, diis_error, diis_step, &
1873 : scf_control%eps_diis, scf_control%nmixing, &
1874 : s_matrix=matrix_s, &
1875 180 : scf_section=scf_section)
1876 : ELSE
1877 22 : diis_step = .FALSE.
1878 : END IF
1879 :
1880 202 : eps_iter = scf_control%diagonalization%eps_iter
1881 202 : IF (diis_step) THEN
1882 130 : scf_env%iter_param = diis_error
1883 130 : scf_env%iter_method = "DIIS/OTdiag"
1884 274 : DO ispin = 1, nspin
1885 : CALL copy_fm_to_dbcsr(scf_env%scf_work1(ispin), &
1886 274 : matrix_ks(ispin)%matrix, keep_sparsity=.TRUE.)
1887 : END DO
1888 130 : eps_iter = MAX(eps_iter, scf_control%diagonalization%eps_adapt*diis_error)
1889 : ELSE
1890 72 : IF (scf_env%mixing_method == 1) THEN
1891 72 : scf_env%iter_param = scf_env%p_mix_alpha
1892 72 : scf_env%iter_method = "P_Mix/OTdiag."
1893 0 : ELSE IF (scf_env%mixing_method > 1) THEN
1894 0 : scf_env%iter_param = scf_env%mixing_store%alpha
1895 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/OTdiag."
1896 : END IF
1897 : END IF
1898 :
1899 202 : scf_env%iter_delta = 0.0_dp
1900 :
1901 448 : DO ispin = 1, nspin
1902 : CALL get_mo_set(mos(ispin), &
1903 : mo_coeff=mo_coeff, &
1904 : eigenvalues=eigenvalues, &
1905 : nmo=nmo, &
1906 246 : homo=homo)
1907 : CALL ot_eigensolver(matrix_h=matrix_ks(ispin)%matrix, &
1908 : matrix_s=matrix_s(1)%matrix, &
1909 : matrix_c_fm=mo_coeff, &
1910 : preconditioner=scf_env%ot_preconditioner( &
1911 : MIN(ispin, SIZE(scf_env%ot_preconditioner)))%preconditioner, &
1912 : eps_gradient=eps_iter, &
1913 : iter_max=scf_control%diagonalization%max_iter, &
1914 : silent=.TRUE., &
1915 246 : ot_settings=scf_control%diagonalization%ot_settings)
1916 : CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, &
1917 : evals_arg=eigenvalues, &
1918 246 : do_rotation=.TRUE.)
1919 : CALL copy_fm_to_dbcsr(mos(ispin)%mo_coeff, &
1920 694 : mos(ispin)%mo_coeff_b)
1921 : !fm->dbcsr
1922 : END DO
1923 :
1924 : CALL set_mo_occupation(mo_array=mos, &
1925 202 : smear=scf_control%smear)
1926 :
1927 448 : DO ispin = 1, nspin
1928 : ! does not yet handle k-points
1929 : CALL calculate_density_matrix(mos(ispin), &
1930 448 : scf_env%p_mix_new(ispin, 1)%matrix)
1931 : END DO
1932 :
1933 202 : END SUBROUTINE do_ot_diag
1934 :
1935 : ! **************************************************************************************************
1936 : !> \brief fixed-H OT diagonalization for real or complex K-point channels
1937 : !> \param matrix_ks real-space Kohn-Sham matrices
1938 : !> \param matrix_s real-space overlap matrices
1939 : !> \param matrix_t ...
1940 : !> \param kpoints K-point environment
1941 : !> \param scf_env SCF environment
1942 : !> \param scf_control SCF controls
1943 : !> \param diis_step set false; density mixing remains the outer accelerator
1944 : !> \param added_mos_auto_grow request a larger adaptive virtual-space buffer
1945 : ! **************************************************************************************************
1946 98 : SUBROUTINE do_ot_diag_kp(matrix_ks, matrix_s, matrix_t, kpoints, scf_env, scf_control, &
1947 : diis_step, added_mos_auto_grow)
1948 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s, matrix_t
1949 : TYPE(kpoint_type), POINTER :: kpoints
1950 : TYPE(qs_scf_env_type), POINTER :: scf_env
1951 : TYPE(scf_control_type), POINTER :: scf_control
1952 : LOGICAL, INTENT(INOUT) :: diis_step
1953 : LOGICAL, INTENT(OUT) :: added_mos_auto_grow
1954 :
1955 : INTEGER :: ikp, ispin, ks_spin, nspin
1956 : LOGICAL :: store_kinetic, use_real_wfn
1957 : REAL(KIND=dp) :: eps_iter
1958 98 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
1959 : TYPE(cp_fm_type) :: coeff_im_work
1960 98 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
1961 : TYPE(cp_fm_type), POINTER :: coeff_im, coeff_re
1962 : TYPE(dbcsr_type), POINTER :: matrix_h_im, matrix_h_re, matrix_s_im, &
1963 : matrix_s_re, matrix_t_im, matrix_t_re
1964 : TYPE(kpoint_env_type), POINTER :: kp
1965 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1966 98 : POINTER :: sab_nl
1967 :
1968 98 : NULLIFY (coeff_im, coeff_re, eigenvalues, fmwork, kp, matrix_h_im, matrix_h_re, &
1969 98 : matrix_s_im, matrix_s_re, matrix_t_im, matrix_t_re, sab_nl)
1970 98 : added_mos_auto_grow = .FALSE.
1971 98 : diis_step = .FALSE.
1972 98 : eps_iter = scf_control%diagonalization%eps_iter
1973 98 : nspin = SIZE(matrix_ks, 1)
1974 : store_kinetic = scf_control%diagonalization%ot_settings%preconditioner_type == &
1975 98 : ot_precond_full_kinetic
1976 98 : IF (store_kinetic) THEN
1977 0 : CPASSERT(ASSOCIATED(matrix_t))
1978 : END IF
1979 98 : CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, sab_nl=sab_nl)
1980 98 : CPASSERT(ASSOCIATED(sab_nl))
1981 :
1982 : ! A full diagonalization supplies an orthonormal start after initialization or an
1983 : ! ADDED_MOS AUTO resize. Subsequent SCF steps only redistribute H(k) and S(k).
1984 98 : IF (scf_env%iter_count <= 1) THEN
1985 : CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, &
1986 10 : .FALSE., diis_step)
1987 : END IF
1988 98 : IF (store_kinetic) THEN
1989 0 : CALL kpoint_operator_store(kpoints, scf_env%scf_work1(1), matrix_ks, matrix_s, matrix_t)
1990 : ELSE
1991 98 : CALL kpoint_operator_store(kpoints, scf_env%scf_work1(1), matrix_ks, matrix_s)
1992 : END IF
1993 :
1994 98 : scf_env%iter_delta = 0.0_dp
1995 256 : DO ikp = 1, SIZE(kpoints%kp_env)
1996 158 : kp => kpoints%kp_env(ikp)%kpoint_env
1997 158 : CPASSERT(ASSOCIATED(kp%ot_hmat) .AND. ASSOCIATED(kp%ot_smat))
1998 158 : IF (SIZE(kp%ot_smat) >= 2) THEN
1999 : CALL kpoint_operator_get_local(matrix_s, kpoints, kp, 1, &
2000 : kp%ot_smat(1), kp%ot_smat(2), &
2001 158 : matrix_s_re, matrix_s_im)
2002 : ELSE
2003 : CALL kpoint_operator_get_local(matrix_s, kpoints, kp, 1, &
2004 : kp%ot_smat(1), kp%ot_smat(1), &
2005 0 : matrix_s_re, matrix_s_im)
2006 0 : CALL dbcsr_set(matrix_s_im, 0.0_dp)
2007 : END IF
2008 158 : IF (store_kinetic) THEN
2009 0 : CPASSERT(ASSOCIATED(kp%ot_tmat))
2010 0 : IF (SIZE(kp%ot_tmat) >= 2) THEN
2011 : CALL kpoint_operator_get_local(matrix_t, kpoints, kp, 1, &
2012 : kp%ot_tmat(1), kp%ot_tmat(2), &
2013 0 : matrix_t_re, matrix_t_im)
2014 : ELSE
2015 : CALL kpoint_operator_get_local(matrix_t, kpoints, kp, 1, &
2016 : kp%ot_tmat(1), kp%ot_tmat(1), &
2017 0 : matrix_t_re, matrix_t_im)
2018 0 : CALL dbcsr_set(matrix_t_im, 0.0_dp)
2019 : END IF
2020 : END IF
2021 316 : DO ispin = 1, nspin
2022 158 : ks_spin = MIN(ispin, SIZE(kp%ot_hmat, 2))
2023 158 : IF (SIZE(kp%ot_hmat, 1) >= 2) THEN
2024 : CALL kpoint_operator_get_local(matrix_ks, kpoints, kp, ks_spin, &
2025 : kp%ot_hmat(1, ks_spin), kp%ot_hmat(2, ks_spin), &
2026 158 : matrix_h_re, matrix_h_im)
2027 : ELSE
2028 : CALL kpoint_operator_get_local(matrix_ks, kpoints, kp, ks_spin, &
2029 : kp%ot_hmat(1, ks_spin), kp%ot_hmat(1, ks_spin), &
2030 0 : matrix_h_re, matrix_h_im)
2031 0 : CALL dbcsr_set(matrix_h_im, 0.0_dp)
2032 : END IF
2033 158 : CALL get_mo_set(kp%mos(1, ispin), mo_coeff=coeff_re, eigenvalues=eigenvalues)
2034 158 : IF (use_real_wfn) THEN
2035 : CALL cp_fm_create(coeff_im_work, coeff_re%matrix_struct, &
2036 0 : name='real k-point OT imaginary work')
2037 0 : CALL cp_fm_set_all(coeff_im_work, 0.0_dp)
2038 : CALL ot_eigensolver_complex(matrix_h=matrix_h_re, matrix_h_im=matrix_h_im, &
2039 : matrix_s=matrix_s_re, matrix_s_im=matrix_s_im, &
2040 : matrix_c_fm=coeff_re, matrix_c_fm_im=coeff_im_work, &
2041 : eps_gradient=eps_iter, &
2042 : iter_max=scf_control%diagonalization%max_iter, &
2043 : eigenvalues=eigenvalues, silent=.TRUE., &
2044 : ot_settings=scf_control%diagonalization%ot_settings, &
2045 : matrix_t=matrix_t_re, matrix_t_im=matrix_t_im, &
2046 0 : mo_set=kp%mos(1, ispin))
2047 0 : CALL cp_fm_release(coeff_im_work)
2048 : ELSE
2049 158 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=coeff_im)
2050 : CALL ot_eigensolver_complex(matrix_h=matrix_h_re, matrix_h_im=matrix_h_im, &
2051 : matrix_s=matrix_s_re, matrix_s_im=matrix_s_im, &
2052 : matrix_c_fm=coeff_re, matrix_c_fm_im=coeff_im, &
2053 : eps_gradient=eps_iter, &
2054 : iter_max=scf_control%diagonalization%max_iter, &
2055 : eigenvalues=eigenvalues, silent=.TRUE., &
2056 : ot_settings=scf_control%diagonalization%ot_settings, &
2057 : matrix_t=matrix_t_re, matrix_t_im=matrix_t_im, &
2058 158 : mo_set=kp%mos(1, ispin))
2059 2774 : kp%mos(2, ispin)%eigenvalues = eigenvalues
2060 : END IF
2061 158 : CALL dbcsr_release_p(matrix_h_re)
2062 316 : CALL dbcsr_release_p(matrix_h_im)
2063 : END DO
2064 158 : CALL dbcsr_release_p(matrix_s_re)
2065 158 : CALL dbcsr_release_p(matrix_s_im)
2066 158 : IF (ASSOCIATED(matrix_t_re)) CALL dbcsr_release_p(matrix_t_re)
2067 256 : IF (ASSOCIATED(matrix_t_im)) CALL dbcsr_release_p(matrix_t_im)
2068 : END DO
2069 :
2070 : CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
2071 : added_mos_auto=scf_control%added_mos_auto, &
2072 98 : added_mos_auto_grow=added_mos_auto_grow)
2073 98 : IF (added_mos_auto_grow) RETURN
2074 :
2075 98 : CALL kpoint_density_matrices(kpoints)
2076 98 : fmwork => scf_env%scf_work1
2077 : CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
2078 98 : matrix_s(1, 1)%matrix, sab_nl, fmwork, overlap_rs=matrix_s)
2079 98 : IF (scf_env%mixing_method == 0) THEN
2080 0 : scf_env%iter_method = 'NoMix/OTdiag.'
2081 98 : ELSE IF (scf_env%mixing_method == 1) THEN
2082 60 : scf_env%iter_param = scf_env%p_mix_alpha
2083 60 : scf_env%iter_method = 'P_Mix/OTdiag.'
2084 : ELSE
2085 38 : scf_env%iter_param = scf_env%mixing_store%alpha
2086 38 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//'/OTdiag.'
2087 : END IF
2088 98 : END SUBROUTINE do_ot_diag_kp
2089 :
2090 : ! **************************************************************************************************
2091 : !> \brief Solve a set restricted open Kohn-Sham (ROKS) equations based on the
2092 : !> alpha and beta Kohn-Sham matrices from unrestricted Kohn-Sham.
2093 : !> \param scf_env ...
2094 : !> \param mos ...
2095 : !> \param matrix_ks ...
2096 : !> \param matrix_s ...
2097 : !> \param scf_control ...
2098 : !> \param scf_section ...
2099 : !> \param diis_step ...
2100 : !> \param orthogonal_basis ...
2101 : !> \par History
2102 : !> 04.2006 created [MK]
2103 : !> Revised (01.05.06,MK)
2104 : !> \note
2105 : !> this is only a high-spin ROKS.
2106 : ! **************************************************************************************************
2107 1132 : SUBROUTINE do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
2108 : scf_control, scf_section, diis_step, &
2109 : orthogonal_basis)
2110 :
2111 : ! Literature: - C. C. J. Roothaan, Rev. Mod. Phys. 32, 179 (1960)
2112 : ! - M. F. Guest and V. R. Saunders, Mol. Phys. 28(3), 819 (1974)
2113 : ! - M. Filatov and S. Shaik, Chem. Phys. Lett. 288, 689 (1998)
2114 :
2115 : TYPE(qs_scf_env_type), POINTER :: scf_env
2116 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
2117 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
2118 : TYPE(scf_control_type), POINTER :: scf_control
2119 : TYPE(section_vals_type), POINTER :: scf_section
2120 : LOGICAL, INTENT(INOUT) :: diis_step
2121 : LOGICAL, INTENT(IN) :: orthogonal_basis
2122 :
2123 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_roks_diag'
2124 :
2125 : INTEGER :: handle, homoa, homob, imo, nalpha, nao, &
2126 : nbeta, nmo
2127 : REAL(KIND=dp) :: diis_error, level_shift_loc
2128 1132 : REAL(KIND=dp), DIMENSION(:), POINTER :: eiga, eigb, occa, occb
2129 : TYPE(cp_fm_type), POINTER :: ksa, ksb, mo2ao, moa, mob, ortho, work
2130 :
2131 : ! -------------------------------------------------------------------------
2132 :
2133 1132 : CALL timeset(routineN, handle)
2134 :
2135 1132 : IF (scf_env%cholesky_method == cholesky_inverse) THEN
2136 0 : ortho => scf_env%ortho_m1
2137 : ELSE
2138 1132 : ortho => scf_env%ortho
2139 : END IF
2140 1132 : work => scf_env%scf_work2
2141 :
2142 1132 : ksa => scf_env%scf_work1(1)
2143 1132 : ksb => scf_env%scf_work1(2)
2144 :
2145 1132 : CALL copy_dbcsr_to_fm(matrix_ks(1)%matrix, ksa)
2146 1132 : CALL copy_dbcsr_to_fm(matrix_ks(2)%matrix, ksb)
2147 :
2148 : ! Get MO information
2149 :
2150 : CALL get_mo_set(mo_set=mos(1), &
2151 : nao=nao, &
2152 : nmo=nmo, &
2153 : nelectron=nalpha, &
2154 : homo=homoa, &
2155 : eigenvalues=eiga, &
2156 : occupation_numbers=occa, &
2157 1132 : mo_coeff=moa)
2158 :
2159 : CALL get_mo_set(mo_set=mos(2), &
2160 : nelectron=nbeta, &
2161 : homo=homob, &
2162 : eigenvalues=eigb, &
2163 : occupation_numbers=occb, &
2164 1132 : mo_coeff=mob)
2165 :
2166 : ! Define the amount of level-shifting
2167 :
2168 1132 : IF ((scf_control%level_shift /= 0.0_dp) .AND. &
2169 : ((scf_control%density_guess == core_guess) .OR. &
2170 : (scf_control%density_guess == restart_guess) .OR. &
2171 : (scf_env%iter_count > 1))) THEN
2172 20 : level_shift_loc = scf_control%level_shift
2173 : ELSE
2174 1112 : level_shift_loc = 0.0_dp
2175 : END IF
2176 :
2177 : IF ((scf_env%iter_count > 1) .OR. &
2178 1132 : (scf_control%density_guess == core_guess) .OR. &
2179 : (scf_control%density_guess == restart_guess)) THEN
2180 :
2181 : ! Transform the spin unrestricted alpha and beta Kohn-Sham matrices
2182 : ! from AO basis to MO basis: K(MO) = C(T)*K(AO)*C
2183 :
2184 1024 : CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
2185 1024 : CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
2186 :
2187 1024 : CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksb, moa, 0.0_dp, work)
2188 1024 : CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksb)
2189 :
2190 : ! Combine the spin unrestricted alpha and beta Kohn-Sham matrices
2191 : ! in the MO basis
2192 :
2193 1024 : IF (scf_control%roks_scheme == general_roks) THEN
2194 : CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_f, &
2195 0 : nalpha, nbeta)
2196 1024 : ELSE IF (scf_control%roks_scheme == high_spin_roks) THEN
2197 1024 : CALL combine_ks_matrices(ksa, ksb, occa, occb, scf_control%roks_parameter)
2198 : ELSE
2199 0 : CPABORT("Unknown ROKS scheme requested")
2200 : END IF
2201 :
2202 : ! Back-transform the restricted open Kohn-Sham matrix from MO basis
2203 : ! to AO basis
2204 :
2205 1024 : IF (orthogonal_basis) THEN
2206 : ! Q = C
2207 464 : mo2ao => moa
2208 : ELSE
2209 : ! Q = S*C
2210 560 : mo2ao => mob
2211 : !MK CALL copy_sm_to_fm(matrix_s(1)%matrix,work)
2212 : !MK CALL cp_fm_symm("L", "U",nao, nao, 1.0_dp, work, moa, 0.0_dp, mo2ao)
2213 560 : CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, moa, mo2ao, nao)
2214 : END IF
2215 :
2216 : ! K(AO) = Q*K(MO)*Q(T)
2217 :
2218 1024 : CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, ksa, mo2ao, 0.0_dp, work)
2219 1024 : CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, mo2ao, work, 0.0_dp, ksa)
2220 :
2221 : ELSE
2222 :
2223 : ! No transformation matrix available, yet. The closed shell part,
2224 : ! i.e. the beta Kohn-Sham matrix in AO basis, is taken.
2225 : ! There might be better choices, anyhow.
2226 :
2227 108 : CALL cp_fm_to_fm(ksb, ksa)
2228 :
2229 : END IF
2230 :
2231 : ! Update DIIS buffer and possibly perform DIIS extrapolation step
2232 :
2233 1132 : IF (scf_env%iter_count > 1) THEN
2234 1018 : IF (orthogonal_basis) THEN
2235 : CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
2236 : mo_array=mos, &
2237 : kc=scf_env%scf_work1, &
2238 : sc=work, &
2239 : delta=scf_env%iter_delta, &
2240 : error_max=diis_error, &
2241 : diis_step=diis_step, &
2242 : eps_diis=scf_control%eps_diis, &
2243 : scf_section=scf_section, &
2244 460 : roks=.TRUE.)
2245 460 : CPASSERT(scf_env%iter_delta == scf_env%iter_delta)
2246 : ELSE
2247 : CALL qs_diis_b_step(diis_buffer=scf_env%scf_diis_buffer, &
2248 : mo_array=mos, &
2249 : kc=scf_env%scf_work1, &
2250 : sc=work, &
2251 : delta=scf_env%iter_delta, &
2252 : error_max=diis_error, &
2253 : diis_step=diis_step, &
2254 : eps_diis=scf_control%eps_diis, &
2255 : scf_section=scf_section, &
2256 : s_matrix=matrix_s, &
2257 558 : roks=.TRUE.)
2258 : END IF
2259 : END IF
2260 :
2261 1132 : IF (diis_step) THEN
2262 714 : scf_env%iter_param = diis_error
2263 714 : scf_env%iter_method = "DIIS/Diag."
2264 : ELSE
2265 418 : IF (scf_env%mixing_method == 1) THEN
2266 418 : scf_env%iter_param = scf_env%p_mix_alpha
2267 418 : scf_env%iter_method = "P_Mix/Diag."
2268 0 : ELSE IF (scf_env%mixing_method > 1) THEN
2269 0 : scf_env%iter_param = scf_env%mixing_store%alpha
2270 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
2271 : END IF
2272 : END IF
2273 :
2274 1132 : scf_env%iter_delta = 0.0_dp
2275 :
2276 1132 : IF (level_shift_loc /= 0.0_dp) THEN
2277 :
2278 : ! Transform the current Kohn-Sham matrix from AO to MO basis
2279 : ! for level-shifting using the current MO set
2280 :
2281 20 : CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, moa, 0.0_dp, work)
2282 20 : CALL parallel_gemm("T", "N", nao, nao, nao, 1.0_dp, moa, work, 0.0_dp, ksa)
2283 :
2284 : ! Apply level-shifting using 50:50 split of the shift (could be relaxed)
2285 :
2286 60 : DO imo = homob + 1, homoa
2287 60 : CALL cp_fm_add_to_element(ksa, imo, imo, 0.5_dp*level_shift_loc)
2288 : END DO
2289 220 : DO imo = homoa + 1, nmo
2290 220 : CALL cp_fm_add_to_element(ksa, imo, imo, level_shift_loc)
2291 : END DO
2292 :
2293 1112 : ELSE IF (.NOT. orthogonal_basis) THEN
2294 :
2295 : ! Transform the current Kohn-Sham matrix to an orthogonal basis
2296 590 : SELECT CASE (scf_env%cholesky_method)
2297 : CASE (cholesky_reduce)
2298 0 : CALL cp_fm_cholesky_reduce(ksa, ortho)
2299 : CASE (cholesky_restore)
2300 526 : CALL cp_fm_uplo_to_full(ksa, work)
2301 : CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
2302 526 : "SOLVE", pos="RIGHT")
2303 : CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
2304 526 : "SOLVE", pos="LEFT", transa="T")
2305 : CASE (cholesky_inverse)
2306 0 : CALL cp_fm_uplo_to_full(ksa, work)
2307 : CALL cp_fm_cholesky_restore(ksa, nao, ortho, work, &
2308 0 : "MULTIPLY", pos="RIGHT")
2309 : CALL cp_fm_cholesky_restore(work, nao, ortho, ksa, &
2310 0 : "MULTIPLY", pos="LEFT", transa="T")
2311 : CASE (cholesky_off)
2312 64 : CALL cp_fm_symm("L", "U", nao, nao, 1.0_dp, ksa, ortho, 0.0_dp, work)
2313 654 : CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, ortho, work, 0.0_dp, ksa)
2314 : END SELECT
2315 :
2316 : END IF
2317 :
2318 : ! Diagonalization of the ROKS operator matrix
2319 :
2320 1132 : CALL choose_eigv_solver(ksa, work, eiga)
2321 :
2322 : ! Back-transformation of the orthonormal eigenvectors if needed
2323 :
2324 1132 : IF (level_shift_loc /= 0.0_dp) THEN
2325 : ! Use old MO set for back-transformation if level-shifting was applied
2326 20 : CALL cp_fm_to_fm(moa, ortho)
2327 20 : CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
2328 : ELSE
2329 1112 : IF (orthogonal_basis) THEN
2330 522 : CALL cp_fm_to_fm(work, moa)
2331 : ELSE
2332 1116 : SELECT CASE (scf_env%cholesky_method)
2333 : CASE (cholesky_reduce, cholesky_restore)
2334 526 : CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "SOLVE")
2335 : CASE (cholesky_inverse)
2336 0 : CALL cp_fm_cholesky_restore(work, nmo, ortho, moa, "MULTIPLY")
2337 : CASE (cholesky_off)
2338 590 : CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, ortho, work, 0.0_dp, moa)
2339 : END SELECT
2340 : END IF
2341 : END IF
2342 :
2343 : ! Correct MO eigenvalues, if level-shifting was applied
2344 :
2345 1132 : IF (level_shift_loc /= 0.0_dp) THEN
2346 60 : DO imo = homob + 1, homoa
2347 60 : eiga(imo) = eiga(imo) - 0.5_dp*level_shift_loc
2348 : END DO
2349 220 : DO imo = homoa + 1, nmo
2350 220 : eiga(imo) = eiga(imo) - level_shift_loc
2351 : END DO
2352 : END IF
2353 :
2354 : ! Update also the beta MO set
2355 :
2356 34952 : eigb(:) = eiga(:)
2357 1132 : CALL cp_fm_to_fm(moa, mob)
2358 :
2359 : ! Calculate the new alpha and beta density matrix
2360 :
2361 : ! does not yet handle k-points
2362 1132 : CALL calculate_density_matrix(mos(1), scf_env%p_mix_new(1, 1)%matrix)
2363 1132 : CALL calculate_density_matrix(mos(2), scf_env%p_mix_new(2, 1)%matrix)
2364 :
2365 1132 : CALL timestop(handle)
2366 :
2367 1132 : END SUBROUTINE do_roks_diag
2368 :
2369 : ! **************************************************************************************************
2370 : !> \brief iterative diagonalization using the block Krylov-space approach
2371 : !> \param scf_env ...
2372 : !> \param mos ...
2373 : !> \param matrix_ks ...
2374 : !> \param scf_control ...
2375 : !> \param scf_section ...
2376 : !> \param check_moconv_only ...
2377 : !> \param
2378 : !> \par History
2379 : !> 05.2009 created [MI]
2380 : ! **************************************************************************************************
2381 :
2382 112 : SUBROUTINE do_block_krylov_diag(scf_env, mos, matrix_ks, &
2383 : scf_control, scf_section, check_moconv_only)
2384 :
2385 : TYPE(qs_scf_env_type), POINTER :: scf_env
2386 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
2387 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
2388 : TYPE(scf_control_type), POINTER :: scf_control
2389 : TYPE(section_vals_type), POINTER :: scf_section
2390 : LOGICAL, INTENT(IN), OPTIONAL :: check_moconv_only
2391 :
2392 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_krylov_diag'
2393 : REAL(KIND=dp), PARAMETER :: rone = 1.0_dp, rzero = 0.0_dp
2394 :
2395 : INTEGER :: handle, homo, ispin, iter, nao, nmo, &
2396 : output_unit
2397 : LOGICAL :: converged, my_check_moconv_only
2398 : REAL(dp) :: eps_iter, t1, t2
2399 112 : REAL(KIND=dp), DIMENSION(:), POINTER :: mo_eigenvalues
2400 : TYPE(cp_fm_type), POINTER :: c0, c1, chc, evec, ks, mo_coeff, ortho, &
2401 : work
2402 : TYPE(cp_logger_type), POINTER :: logger
2403 :
2404 224 : logger => cp_get_default_logger()
2405 112 : CALL timeset(routineN, handle)
2406 :
2407 : output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%LANCZOS", &
2408 112 : extension=".scfLog")
2409 :
2410 112 : my_check_moconv_only = .FALSE.
2411 112 : IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
2412 :
2413 112 : NULLIFY (mo_coeff, ortho, work, ks)
2414 112 : NULLIFY (mo_eigenvalues)
2415 112 : NULLIFY (c0, c1)
2416 :
2417 112 : IF (scf_env%cholesky_method == cholesky_inverse) THEN
2418 38 : ortho => scf_env%ortho_m1
2419 : ELSE
2420 74 : ortho => scf_env%ortho
2421 : END IF
2422 112 : work => scf_env%scf_work2
2423 :
2424 224 : DO ispin = 1, SIZE(matrix_ks)
2425 : CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, &
2426 224 : scf_env%scf_work1(ispin))
2427 : END DO
2428 :
2429 112 : IF (scf_env%mixing_method == 1) THEN
2430 0 : scf_env%iter_param = scf_env%p_mix_alpha
2431 0 : scf_env%iter_method = "P_Mix/Lanczos"
2432 : ELSE
2433 : ! scf_env%iter_param = scf_env%mixing_store%alpha
2434 112 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Lanc."
2435 : END IF
2436 :
2437 224 : DO ispin = 1, SIZE(matrix_ks)
2438 :
2439 112 : ks => scf_env%scf_work1(ispin)
2440 112 : CALL cp_fm_uplo_to_full(ks, work)
2441 :
2442 : CALL get_mo_set(mo_set=mos(ispin), &
2443 : nao=nao, &
2444 : nmo=nmo, &
2445 : homo=homo, &
2446 : eigenvalues=mo_eigenvalues, &
2447 112 : mo_coeff=mo_coeff)
2448 :
2449 112 : NULLIFY (c0, c1)
2450 112 : c0 => scf_env%krylov_space%mo_conv(ispin)
2451 112 : c1 => scf_env%krylov_space%mo_refine(ispin)
2452 112 : SELECT CASE (scf_env%cholesky_method)
2453 : CASE (cholesky_reduce)
2454 0 : CALL cp_fm_cholesky_reduce(ks, ortho)
2455 0 : CALL cp_fm_uplo_to_full(ks, work)
2456 0 : CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
2457 : CASE (cholesky_restore)
2458 : CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
2459 74 : "SOLVE", pos="RIGHT")
2460 : CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
2461 74 : "SOLVE", pos="LEFT", transa="T")
2462 74 : CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "MULTIPLY")
2463 : CASE (cholesky_inverse)
2464 : CALL cp_fm_cholesky_restore(ks, nao, ortho, work, &
2465 38 : "MULTIPLY", pos="RIGHT")
2466 : CALL cp_fm_cholesky_restore(work, nao, ortho, ks, &
2467 38 : "MULTIPLY", pos="LEFT", transa="T")
2468 150 : CALL cp_fm_cholesky_restore(mo_coeff, nmo, ortho, c0, "SOLVE")
2469 : END SELECT
2470 :
2471 112 : scf_env%krylov_space%nmo_nc = nmo
2472 112 : scf_env%krylov_space%nmo_conv = 0
2473 :
2474 112 : t1 = m_walltime()
2475 112 : IF (output_unit > 0) THEN
2476 0 : WRITE (output_unit, "(/T15,A)") '<<<<<<<<< LANCZOS REFINEMENT <<<<<<<<<<'
2477 : WRITE (output_unit, "(T8,A,T15,A,T23,A,T36,A,T49,A,T60,A,/,T8,A)") &
2478 0 : " Spin ", " Cycle ", &
2479 0 : " conv. MOS ", " B2MAX ", " B2MIN ", " Time", REPEAT("-", 60)
2480 : END IF
2481 112 : eps_iter = MAX(scf_env%krylov_space%eps_conv, scf_env%krylov_space%eps_adapt*scf_env%iter_delta)
2482 112 : iter = 0
2483 112 : converged = .FALSE.
2484 : !Check convergence of MOS
2485 336 : IF (my_check_moconv_only) THEN
2486 :
2487 : CALL lanczos_refinement(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
2488 0 : nao, eps_iter, ispin, check_moconv_only=my_check_moconv_only)
2489 0 : t2 = m_walltime()
2490 0 : IF (output_unit > 0) THEN
2491 : WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
2492 0 : ispin, iter, scf_env%krylov_space%nmo_conv, &
2493 0 : scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
2494 : END IF
2495 :
2496 : CYCLE
2497 : ELSE
2498 : !Block Lanczos refinement
2499 842 : DO iter = 1, scf_env%krylov_space%max_iter
2500 : CALL lanczos_refinement_2v(scf_env%krylov_space, ks, c0, c1, mo_eigenvalues, &
2501 740 : nao, eps_iter, ispin)
2502 740 : t2 = m_walltime()
2503 740 : IF (output_unit > 0) THEN
2504 : WRITE (output_unit, '(T8,I3,T16,I5,T24,I6,T33,E12.4,2x,E12.4,T60,F8.3)') &
2505 0 : ispin, iter, scf_env%krylov_space%nmo_conv, &
2506 0 : scf_env%krylov_space%max_res_norm, scf_env%krylov_space%min_res_norm, t2 - t1
2507 : END IF
2508 740 : t1 = m_walltime()
2509 842 : IF (scf_env%krylov_space%max_res_norm < eps_iter) THEN
2510 10 : converged = .TRUE.
2511 10 : IF (output_unit > 0) WRITE (output_unit, *) &
2512 0 : " Reached convergence in ", iter, " iterations "
2513 : EXIT
2514 : END IF
2515 : END DO
2516 :
2517 112 : IF (.NOT. converged .AND. output_unit > 0) THEN
2518 : WRITE (output_unit, "(T4, A)") " WARNING Lanczos refinement could "// &
2519 0 : "not converge all the mos:"
2520 0 : WRITE (output_unit, "(T40,A,T70,I10)") " number of not converged mos ", &
2521 0 : scf_env%krylov_space%nmo_nc
2522 0 : WRITE (output_unit, "(T40,A,T70,E10.2)") " max norm of the residual ", &
2523 0 : scf_env%krylov_space%max_res_norm
2524 :
2525 : END IF
2526 :
2527 : ! For the moment skip the re-orthogonalization
2528 : IF (.FALSE.) THEN
2529 : !Re-orthogonalization
2530 : NULLIFY (chc, evec)
2531 : chc => scf_env%krylov_space%chc_mat(ispin)
2532 : evec => scf_env%krylov_space%c_vec(ispin)
2533 : CALL parallel_gemm('N', 'N', nao, nmo, nao, rone, ks, c0, rzero, work)
2534 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, rone, c0, work, rzero, chc)
2535 : !Diagonalize (C^t)HC
2536 : CALL choose_eigv_solver(chc, evec, mo_eigenvalues)
2537 : !Rotate the C vectors
2538 : CALL parallel_gemm('N', 'N', nao, nmo, nmo, rone, c0, evec, rzero, c1)
2539 : c0 => scf_env%krylov_space%mo_refine(ispin)
2540 : END IF
2541 :
2542 112 : IF (scf_env%cholesky_method == cholesky_inverse) THEN
2543 38 : CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "MULTIPLY")
2544 : ELSE
2545 74 : CALL cp_fm_cholesky_restore(c0, nmo, ortho, mo_coeff, "SOLVE")
2546 : END IF
2547 :
2548 112 : IF (.NOT. scf_control%gce%do_gce) THEN
2549 : CALL set_mo_occupation(mo_set=mos(ispin), &
2550 112 : smear=scf_control%smear)
2551 : ELSE
2552 : CALL set_mo_occupation(mo_set=mos(ispin), &
2553 : smear=scf_control%smear, &
2554 0 : gce=scf_control%gce)
2555 : END IF
2556 :
2557 : ! does not yet handle k-points
2558 : CALL calculate_density_matrix(mos(ispin), &
2559 112 : scf_env%p_mix_new(ispin, 1)%matrix)
2560 : END IF
2561 : END DO ! ispin
2562 :
2563 112 : IF (output_unit > 0) THEN
2564 0 : WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END LANCZOS REFINEMENT <<<<<<<<<<'
2565 : END IF
2566 :
2567 : CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
2568 112 : "PRINT%LANCZOS")
2569 :
2570 112 : CALL timestop(handle)
2571 :
2572 112 : END SUBROUTINE do_block_krylov_diag
2573 :
2574 : ! **************************************************************************************************
2575 : !> \brief iterative diagonalization using the block davidson space approach
2576 : !> \param qs_env ...
2577 : !> \param scf_env ...
2578 : !> \param mos ...
2579 : !> \param matrix_ks ...
2580 : !> \param matrix_s ...
2581 : !> \param scf_control ...
2582 : !> \param scf_section ...
2583 : !> \param check_moconv_only ...
2584 : !> \param
2585 : !> \par History
2586 : !> 05.2011 created [MI]
2587 : ! **************************************************************************************************
2588 :
2589 94 : SUBROUTINE do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, &
2590 : scf_control, scf_section, check_moconv_only)
2591 :
2592 : TYPE(qs_environment_type), POINTER :: qs_env
2593 : TYPE(qs_scf_env_type), POINTER :: scf_env
2594 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
2595 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
2596 : TYPE(scf_control_type), POINTER :: scf_control
2597 : TYPE(section_vals_type), POINTER :: scf_section
2598 : LOGICAL, INTENT(IN), OPTIONAL :: check_moconv_only
2599 :
2600 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_davidson_diag'
2601 :
2602 : INTEGER :: handle, ispin, nspins, output_unit
2603 : LOGICAL :: do_prec, my_check_moconv_only
2604 : TYPE(cp_logger_type), POINTER :: logger
2605 :
2606 94 : logger => cp_get_default_logger()
2607 94 : CALL timeset(routineN, handle)
2608 :
2609 : output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DAVIDSON", &
2610 94 : extension=".scfLog")
2611 :
2612 94 : IF (output_unit > 0) THEN
2613 0 : WRITE (output_unit, "(/T15,A)") '<<<<<<<<< DAVIDSON ITERATIONS <<<<<<<<<<'
2614 : END IF
2615 :
2616 94 : IF (scf_env%mixing_method == 1) THEN
2617 0 : scf_env%iter_param = scf_env%p_mix_alpha
2618 0 : scf_env%iter_method = "P_Mix/Dav."
2619 : ELSE
2620 94 : scf_env%iter_param = scf_env%mixing_store%alpha
2621 94 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Dav."
2622 : END IF
2623 :
2624 94 : my_check_moconv_only = .FALSE.
2625 94 : IF (PRESENT(check_moconv_only)) my_check_moconv_only = check_moconv_only
2626 94 : do_prec = .FALSE.
2627 94 : IF (scf_env%block_davidson_env(1)%prec_type /= 0 .AND. &
2628 : scf_env%iter_count >= scf_env%block_davidson_env(1)%first_prec) THEN
2629 84 : do_prec = .TRUE.
2630 : END IF
2631 :
2632 94 : nspins = SIZE(matrix_ks)
2633 :
2634 94 : IF (do_prec .AND. (scf_env%iter_count == scf_env%block_davidson_env(1)%first_prec .OR. &
2635 : MODULO(scf_env%iter_count, scf_env%block_davidson_env(1)%niter_new_prec) == 0)) THEN
2636 : CALL restart_preconditioner(qs_env, scf_env%ot_preconditioner, &
2637 18 : prec_type=scf_env%block_davidson_env(1)%prec_type, nspins=nspins)
2638 : CALL prepare_preconditioner(qs_env, mos, matrix_ks, matrix_s, scf_env%ot_preconditioner, &
2639 : scf_env%block_davidson_env(1)%prec_type, &
2640 : scf_env%block_davidson_env(1)%solver_type, &
2641 : scf_env%block_davidson_env(1)%energy_gap, nspins, &
2642 : convert_to_dbcsr=scf_env%block_davidson_env(1)%use_sparse_mos, &
2643 18 : full_mo_set=.TRUE.)
2644 : END IF
2645 :
2646 198 : DO ispin = 1, nspins
2647 198 : IF (scf_env%block_davidson_env(ispin)%use_sparse_mos) THEN
2648 64 : IF (.NOT. do_prec) THEN
2649 : CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
2650 8 : matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
2651 : ELSE
2652 : CALL generate_extended_space_sparse(scf_env%block_davidson_env(ispin), mos(ispin), &
2653 : matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
2654 56 : scf_env%ot_preconditioner(ispin)%preconditioner)
2655 : END IF
2656 :
2657 : ELSE
2658 40 : IF (.NOT. do_prec) THEN
2659 : CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
2660 4 : matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit)
2661 : ELSE
2662 : CALL generate_extended_space(scf_env%block_davidson_env(ispin), mos(ispin), &
2663 : matrix_ks(ispin)%matrix, matrix_s(1)%matrix, output_unit, &
2664 36 : scf_env%ot_preconditioner(ispin)%preconditioner)
2665 : END IF
2666 : END IF
2667 : END DO !ispin
2668 :
2669 94 : IF (.NOT. scf_control%gce%do_gce) THEN
2670 : CALL set_mo_occupation(mo_array=mos, &
2671 94 : smear=scf_control%smear)
2672 : ELSE
2673 : CALL set_mo_occupation(mo_array=mos, &
2674 : smear=scf_control%smear, &
2675 0 : gce=scf_control%gce)
2676 : END IF
2677 :
2678 198 : DO ispin = 1, nspins
2679 : ! does not yet handle k-points
2680 : CALL calculate_density_matrix(mos(ispin), &
2681 198 : scf_env%p_mix_new(ispin, 1)%matrix)
2682 : END DO
2683 :
2684 94 : IF (output_unit > 0) THEN
2685 0 : WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END DAVIDSON ITERATION <<<<<<<<<<'
2686 : END IF
2687 :
2688 : CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
2689 94 : "PRINT%DAVIDSON")
2690 :
2691 94 : CALL timestop(handle)
2692 :
2693 94 : END SUBROUTINE do_block_davidson_diag
2694 :
2695 : ! **************************************************************************************************
2696 : !> \brief block-Davidson SCF step for complex K points, one channel per
2697 : !> (local kpoint, spin); mirrors do_block_davidson_diag for the
2698 : !> preconditioner scheduling and do_general_diag_kp for the H(k)/S(k)
2699 : !> assembly and the density exit chain
2700 : !> \param qs_env ...
2701 : !> \param scf_env ...
2702 : !> \param matrix_ks_kp real-space Kohn-Sham matrices, dbcsr image set
2703 : !> \param matrix_s_kp real-space overlap matrix, dbcsr image set
2704 : !> \param kpoints ...
2705 : !> \param scf_control ...
2706 : !> \param added_mos_auto_grow ...
2707 : ! **************************************************************************************************
2708 936 : SUBROUTINE do_block_davidson_diag_kp(qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, &
2709 : scf_control, added_mos_auto_grow)
2710 :
2711 : TYPE(qs_environment_type), POINTER :: qs_env
2712 : TYPE(qs_scf_env_type), POINTER :: scf_env
2713 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp, matrix_s_kp
2714 : TYPE(kpoint_type), POINTER :: kpoints
2715 : TYPE(scf_control_type), POINTER :: scf_control
2716 : LOGICAL, INTENT(OUT), OPTIONAL :: added_mos_auto_grow
2717 :
2718 : CHARACTER(LEN=*), PARAMETER :: routineN = 'do_block_davidson_diag_kp'
2719 : REAL(KIND=dp), PARAMETER :: empty_factor = 5.0_dp, &
2720 : eps_iter_cap = 1.0E-4_dp
2721 :
2722 : INTEGER :: channel, first_prec, handle, ispin, iw, &
2723 : iwork, kplocal, kpmax, local_kpoint, &
2724 : nchannels, nspin, output_unit
2725 : INTEGER, DIMENSION(2) :: kp_range
2726 936 : INTEGER, DIMENSION(:, :), POINTER :: kp_dist
2727 936 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
2728 : LOGICAL :: do_prec, my_added_mos_auto_grow, &
2729 : use_real_wfn
2730 : REAL(KIND=dp) :: eps_iter, eps_iter_empty
2731 936 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp
2732 : TYPE(cp_cfm_type) :: cksmat, csmat, csmat_base
2733 936 : TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER :: ao_ao_fm_pools, kp_ao_ao_fm_pools
2734 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct
2735 936 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
2736 : TYPE(cp_logger_type), POINTER :: logger
2737 : TYPE(kpoint_env_type), POINTER :: kp
2738 936 : TYPE(kpoint_operator_context_type) :: op_ctx
2739 : TYPE(mp_para_env_type), POINTER :: para_env
2740 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2741 936 : POINTER :: sab_nl
2742 : TYPE(qs_matrix_pools_type), POINTER :: kp_mpools, mpools
2743 : TYPE(section_vals_type), POINTER :: scf_section
2744 :
2745 : ! bounds of the adaptive inner tolerance. The loose phase is capped for
2746 : ! the residual-norm semantics of EPS_ITER. A residual of order 1/k would
2747 : ! leave an eigenvector error of order 10 percent at a typical metallic
2748 : ! gap. Unoccupied MOS converge empty_factor times looser. The tracking
2749 : ! divides the mixing delta by noise_scale: the SCF convergence measure
2750 : ! is the LARGEST ELEMENT of the density residual, in which the
2751 : ! per-column residuals of a whole block accumulate. The measured
2752 : ! amplification is ~20 on a smeared Bi2S3/MoS2 slab, so tracking at
2753 : ! delta/100 keeps the injected noise below the outer convergence level.
2754 :
2755 1872 : logger => cp_get_default_logger()
2756 936 : CALL timeset(routineN, handle)
2757 :
2758 936 : scf_section => section_vals_get_subs_vals(qs_env%input, "DFT%SCF")
2759 : output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%DAVIDSON", &
2760 936 : extension=".scfLog")
2761 936 : IF (output_unit > 0) THEN
2762 0 : WRITE (output_unit, "(/T15,A)") '<<<<<<<<< DAVIDSON ITERATIONS <<<<<<<<<<'
2763 : END IF
2764 :
2765 : CALL get_kpoint_info(kpoints, kp_range=kp_range, kp_dist=kp_dist, xkp=xkp, &
2766 : use_real_wfn=use_real_wfn, sab_nl=sab_nl, &
2767 936 : cell_to_index=cell_to_index, mpools=kp_mpools)
2768 936 : IF (use_real_wfn) THEN
2769 0 : CPABORT('Davidson Kp requires complex K-point MOS')
2770 : END IF
2771 936 : para_env => kpoints%blacs_env_all%para_env
2772 936 : kplocal = kp_range(2) - kp_range(1) + 1
2773 2444 : kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
2774 936 : nspin = SIZE(matrix_ks_kp, 1)
2775 936 : nchannels = kplocal*nspin
2776 :
2777 936 : IF (scf_env%mixing_method == 1) THEN
2778 684 : scf_env%iter_param = scf_env%p_mix_alpha
2779 684 : scf_env%iter_method = "P_Mix/Dav."
2780 252 : ELSE IF (scf_env%mixing_method > 1) THEN
2781 252 : scf_env%iter_param = scf_env%mixing_store%alpha
2782 252 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Dav."
2783 : END IF
2784 :
2785 : ! preconditioner scheduling, mirrors do_block_davidson_diag. The first
2786 : ! K-point SCF step cold-starts unless extrapolation prefilled the MOS
2787 : ! (mos_prefilled). The FULL_ALL maker consumes the MO coefficients and
2788 : ! eigenvalues, so building before the first solve completed would feed it
2789 : ! uninitialized data and stall the Davidson convergence. Keep first_prec
2790 : ! clamped past that step in both cases. Warming it up under prefilled MOS
2791 : ! would mix two variables at once.
2792 936 : first_prec = MAX(scf_env%block_davidson_env(1)%first_prec, 2)
2793 936 : do_prec = .FALSE.
2794 936 : IF (scf_env%block_davidson_env(1)%prec_type /= ot_precond_none .AND. &
2795 : scf_env%iter_count >= first_prec) THEN
2796 836 : do_prec = .TRUE.
2797 : END IF
2798 : ! adaptive inner tolerance from EPS_ADAPT: loose while the density is
2799 : ! still far from self-consistency, tightening with the outer error
2800 : ! scaled by noise_scale (mirrors the block Krylov scheduling in
2801 : ! do_block_krylov_diag). The
2802 : ! ratchet is monotone across SCF steps: the threshold may tighten but
2803 : ! never relax again. A rebounding outer error would otherwise re-loosen
2804 : ! the solver, and the run could stop on a near-zero mixing delta of a
2805 : ! pair of identical, sloppily converged densities. The cap bounds the
2806 : ! early loose phase. Unoccupied MOS converge empty_factor times
2807 : ! looser (the occupancy decides which columns qualify, see
2808 : ! generate_extended_space_c). There is no restoration of the
2809 : ! user threshold at the end. The tolerance stays a margin below the
2810 : ! outer error. The MOS the run exits with satisfy that same margin
2811 : ! rather than the nominal EPS_ITER.
2812 936 : eps_iter = scf_env%block_davidson_env(1)%eps_iter
2813 936 : eps_iter_empty = eps_iter
2814 936 : IF (scf_control%diagonalization%eps_adapt > 0.0_dp .AND. scf_env%iter_delta > 0.0_dp) THEN
2815 : ! stall escape: when the mixing delta sank below the tolerance the
2816 : ! last solve used, that solve's own sloppiness may be the noise floor
2817 : ! pinning the delta. Tighten one decade below what that solve used.
2818 : ! Tightening relative to the OPERATING tolerance instead of the
2819 : ! dipped delta bounds the reaction to transient mixing dips (a
2820 : ! momentary overshoot must not collapse the threshold by orders of
2821 : ! magnitude and destabilise the mixer), while a genuine stall moves
2822 : ! the threshold down decade by decade. Checking on the stall alone
2823 : ! keeps the loose phase as loose as EPS_ADAPT allows
2824 104 : IF (scf_env%iter_delta < scf_env%block_davidson_env(1)%eps_iter_used) THEN
2825 : scf_env%block_davidson_env(1)%eps_iter_prev = &
2826 : MIN(scf_env%block_davidson_env(1)%eps_iter_prev, &
2827 : MAX(scf_env%block_davidson_env(1)%eps_iter, &
2828 8 : 0.1_dp*scf_env%block_davidson_env(1)%eps_iter_used))
2829 : END IF
2830 : ! candidate: looser than the user value, capped; ratchet: only
2831 : ! tighter than the previous adaptive value, which lives in the
2832 : ! persistent channel settings (a local variable would reset on
2833 : ! every call into this driver)
2834 : eps_iter = MIN(MAX(eps_iter, MIN(scf_control%diagonalization%eps_adapt*scf_env%iter_delta/ &
2835 : scf_env%block_davidson_env(1)%noise_scale, &
2836 104 : eps_iter_cap)), scf_env%block_davidson_env(1)%eps_iter_prev)
2837 104 : eps_iter_empty = empty_factor*eps_iter
2838 : ! record what this solve uses, after every override above: the outer
2839 : ! loop compares the mixing delta against it (qs_scf_check_inner_exit)
2840 104 : scf_env%block_davidson_env(1)%eps_iter_prev = eps_iter
2841 104 : scf_env%block_davidson_env(1)%eps_iter_used = eps_iter
2842 : END IF
2843 : ! schedule trace of the adaptive tolerance, one line per SCF step at
2844 : ! DEBUG print level
2845 936 : IF (scf_control%diagonalization%eps_adapt > 0.0_dp .AND. para_env%is_source() .AND. &
2846 : logger%iter_info%print_level >= debug_print_level) THEN
2847 0 : iw = cp_logger_get_default_unit_nr()
2848 0 : IF (iw > 0) THEN
2849 : WRITE (UNIT=iw, FMT="(T3,'EPS_ADAPT step',I5,' delta=',ES9.2,' eps_occ=',ES9.2,' eps_empty=',ES9.2)") &
2850 0 : scf_env%iter_count, scf_env%iter_delta, eps_iter, eps_iter_empty
2851 : END IF
2852 : END IF
2853 :
2854 : ! work matrices: global scratch fms (also the operator-context
2855 : ! template), two k-group fms as preconditioner outputs, and the
2856 : ! complex H(k)/S(k)
2857 936 : CALL get_qs_env(qs_env, mpools=mpools)
2858 936 : CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
2859 4680 : ALLOCATE (fmwork(4))
2860 4680 : DO iwork = 1, 4
2861 4680 : CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmwork(iwork))
2862 : END DO
2863 936 : CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), nspin)
2864 936 : CALL kpoint_operator_prepare(op_ctx, matrix_ks_kp, kpoint_slot_ks)
2865 936 : CALL kpoint_operator_prepare(op_ctx, matrix_s_kp, kpoint_slot_s, matrix_row=kpoint_spin_free)
2866 936 : CALL mpools_get(kp_mpools, ao_ao_fm_pools=kp_ao_ao_fm_pools)
2867 936 : matrix_struct => fm_pool_get_el_struct(kp_ao_ao_fm_pools(1)%pool)
2868 936 : CALL cp_cfm_create(cksmat, matrix_struct, name="dav_hk")
2869 936 : CALL cp_cfm_create(csmat, matrix_struct, name="dav_sk")
2870 936 : CALL cp_cfm_create(csmat_base, matrix_struct, name="dav_sk_base")
2871 :
2872 936 : IF (do_prec .AND. (scf_env%iter_count == first_prec .OR. &
2873 : MODULO(scf_env%iter_count, &
2874 : scf_env%block_davidson_env(1)%niter_new_prec) == 0)) THEN
2875 : CALL davidson_kp_prepare_preconditioners( &
2876 58 : qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, op_ctx)
2877 : END IF
2878 :
2879 2876 : DO local_kpoint = 1, kpmax
2880 : ! Every k-point group executes the same sequence of global transforms.
2881 : ! Groups without a k point in the last round still participate
2882 : ! in the service calls, but skip their local solver work.
2883 : CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_s_kp, &
2884 1940 : cmat=csmat_base, matrix_row=kpoint_spin_free, slot=kpoint_slot_s)
2885 :
2886 4892 : DO ispin = 1, nspin
2887 : CALL kpoint_operator_get(op_ctx, local_kpoint, ispin, matrix_ks_kp, &
2888 2016 : cmat=cksmat, matrix_row=ispin, slot=kpoint_slot_ks)
2889 2016 : IF (local_kpoint > kplocal) CYCLE
2890 2016 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2891 2016 : CALL cp_cfm_to_cfm(csmat_base, csmat)
2892 :
2893 3956 : IF (scf_env%iter_count == 1 .AND. .NOT. kp%mos_prefilled) THEN
2894 : ! K-point MOS enter the first SCF step allocated but uninitialized.
2895 : ! The stored S(k) copy is restored for every spin because
2896 : ! cp_cfm_geeig overwrites its matrix arguments.
2897 74 : CALL cold_start_mo_init(kp, ispin, cksmat, csmat)
2898 : ELSE
2899 1942 : channel = (local_kpoint - 1)*nspin + ispin
2900 1942 : IF (do_prec) THEN
2901 : CALL generate_extended_space_c(scf_env%block_davidson_env(channel), &
2902 : kp%mos(1:2, ispin), cksmat, csmat, output_unit, &
2903 : eps_iter, eps_iter_empty, &
2904 1814 : scf_env%ot_preconditioner(channel)%preconditioner)
2905 : ELSE
2906 : CALL generate_extended_space_c(scf_env%block_davidson_env(channel), &
2907 : kp%mos(1:2, ispin), cksmat, csmat, output_unit, &
2908 128 : eps_iter, eps_iter_empty)
2909 : END IF
2910 : END IF
2911 : END DO
2912 : END DO
2913 :
2914 : ! occupations and density, same exit chain as do_general_diag_kp
2915 : my_added_mos_auto_grow = .FALSE.
2916 : CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
2917 : added_mos_auto=scf_control%added_mos_auto, &
2918 936 : added_mos_auto_grow=my_added_mos_auto_grow)
2919 936 : IF (my_added_mos_auto_grow) THEN
2920 : ! the virtual-space buffer is too small for the smearing tail; the
2921 : ! outer loop grows the MOS and redoes this SCF step, the density of
2922 : ! the abandoned step must not be assembled
2923 4 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
2924 : ELSE
2925 932 : CALL kpoint_density_matrices(kpoints)
2926 : CALL kpoint_density_transform(kpoints, scf_env%p_mix_new, .FALSE., &
2927 932 : matrix_s_kp(1, 1)%matrix, sab_nl, fmwork, overlap_rs=matrix_s_kp)
2928 : END IF
2929 :
2930 936 : CALL cp_cfm_release(cksmat)
2931 936 : CALL cp_cfm_release(csmat)
2932 936 : CALL cp_cfm_release(csmat_base)
2933 936 : CALL kpoint_operator_context_release(op_ctx)
2934 4680 : DO iwork = 1, 4
2935 4680 : CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmwork(iwork))
2936 : END DO
2937 936 : DEALLOCATE (fmwork)
2938 :
2939 936 : IF (output_unit > 0) THEN
2940 0 : WRITE (output_unit, "(T15,A/)") '<<<<<<<<< END DAVIDSON ITERATION <<<<<<<<<<'
2941 : END IF
2942 : CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
2943 936 : "PRINT%DAVIDSON")
2944 :
2945 936 : CALL timestop(handle)
2946 :
2947 2808 : END SUBROUTINE do_block_davidson_diag_kp
2948 :
2949 : ! **************************************************************************************************
2950 : !> \brief first-SCF-step initialization of the K-point MOS of one spin by one
2951 : !> direct diagonalization of H(k); both arguments are assembled by the
2952 : !> caller because cp_cfm_geeig overwrites them
2953 : !> \param kp kpoint environment holding the MOS pair
2954 : !> \param ispin ...
2955 : !> \param cksmat complex H(k), assembled by the caller
2956 : !> \param csmat complex S(k), assembled by the caller
2957 : ! **************************************************************************************************
2958 222 : SUBROUTINE cold_start_mo_init(kp, ispin, cksmat, csmat)
2959 :
2960 : TYPE(kpoint_env_type), POINTER :: kp
2961 : INTEGER, INTENT(IN) :: ispin
2962 : TYPE(cp_cfm_type) :: cksmat, csmat
2963 :
2964 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cold_start_mo_init'
2965 :
2966 : INTEGER :: handle
2967 74 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
2968 : TYPE(cp_cfm_type) :: cmos, cwork
2969 : TYPE(cp_fm_type), POINTER :: imos, rmos
2970 :
2971 74 : CALL timeset(routineN, handle)
2972 :
2973 74 : CALL get_mo_set(kp%mos(1, ispin), mo_coeff=rmos, eigenvalues=eigenvalues)
2974 74 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=imos)
2975 74 : CALL cp_cfm_create(cmos, rmos%matrix_struct, name="dav_cold_cmos")
2976 74 : CALL cp_cfm_create(cwork, cksmat%matrix_struct, name="dav_cold_cwork")
2977 74 : CALL cp_cfm_geeig(cksmat, csmat, cmos, eigenvalues, cwork)
2978 748 : kp%mos(2, ispin)%eigenvalues = eigenvalues
2979 74 : CALL cp_cfm_to_fm(cmos, rmos, imos)
2980 74 : CALL cp_cfm_release(cmos)
2981 74 : CALL cp_cfm_release(cwork)
2982 :
2983 74 : CALL timestop(handle)
2984 :
2985 74 : END SUBROUTINE cold_start_mo_init
2986 :
2987 : ! **************************************************************************************************
2988 : !> \brief builds one complex K-point preconditioner per (local kpoint, spin)
2989 : !> channel; mirrors prepare_qs_ot_kpoint_preconditioners
2990 : !> \param qs_env ...
2991 : !> \param scf_env ...
2992 : !> \param matrix_ks_kp ...
2993 : !> \param matrix_s_kp ...
2994 : !> \param kpoints ...
2995 : !> \param op_ctx ...
2996 : ! **************************************************************************************************
2997 58 : SUBROUTINE davidson_kp_prepare_preconditioners( &
2998 : qs_env, scf_env, matrix_ks_kp, matrix_s_kp, kpoints, op_ctx)
2999 :
3000 : TYPE(qs_environment_type), POINTER :: qs_env
3001 : TYPE(qs_scf_env_type), POINTER :: scf_env
3002 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp, matrix_s_kp
3003 : TYPE(kpoint_type), POINTER :: kpoints
3004 : TYPE(kpoint_operator_context_type) :: op_ctx
3005 :
3006 : CHARACTER(LEN=*), PARAMETER :: routineN = 'davidson_kp_prepare_preconditioners'
3007 :
3008 : INTEGER :: channel, handle, ispin, kplocal, kpmax, &
3009 : local_kpoint, nchannels, nmo, nspin, &
3010 : prec_type, solver_type
3011 : INTEGER, DIMENSION(2) :: kp_range
3012 58 : INTEGER, DIMENSION(:, :), POINTER :: kp_dist
3013 58 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
3014 : REAL(KIND=dp) :: energy_gap
3015 58 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues
3016 58 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp
3017 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
3018 : TYPE(cp_cfm_type) :: matrix_c, matrix_h, matrix_s
3019 : TYPE(cp_fm_type), POINTER :: mo_coeff_im, mo_coeff_re
3020 58 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_t_kp
3021 : TYPE(dbcsr_type), POINTER :: matrix_h_im, matrix_h_re, matrix_s_im, &
3022 : matrix_s_re, matrix_t_im, matrix_t_re
3023 : TYPE(kpoint_env_type), POINTER :: kp
3024 : TYPE(mp_para_env_type), POINTER :: para_env
3025 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3026 58 : POINTER :: sab_nl
3027 :
3028 58 : CALL timeset(routineN, handle)
3029 :
3030 : CALL get_kpoint_info(kpoints, kp_range=kp_range, kp_dist=kp_dist, xkp=xkp, sab_nl=sab_nl, &
3031 58 : cell_to_index=cell_to_index)
3032 58 : CALL get_qs_env(qs_env, kinetic_kp=matrix_t_kp)
3033 : ! the preconditioner fms must live on the kpoint-group BLACS context,
3034 : ! the context of the MOS they are applied with
3035 58 : blacs_env => kpoints%blacs_env
3036 58 : para_env => kpoints%para_env_kp
3037 58 : kplocal = kp_range(2) - kp_range(1) + 1
3038 152 : kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
3039 58 : nspin = SIZE(matrix_ks_kp, 1)
3040 58 : nchannels = kplocal*nspin
3041 58 : prec_type = scf_env%block_davidson_env(1)%prec_type
3042 58 : solver_type = scf_env%block_davidson_env(1)%solver_type
3043 58 : energy_gap = scf_env%block_davidson_env(1)%energy_gap
3044 :
3045 : ! channel storage: every (kpoint, spin) channel carries its own
3046 : ! preconditioner, because S(k) and H(k) differ per kpoint. The Gamma
3047 : ! reuse pattern of restart_preconditioner (a single entry for the
3048 : ! spin-independent types) must not be used here.
3049 58 : IF (ASSOCIATED(scf_env%ot_preconditioner)) THEN
3050 120 : DO channel = 1, SIZE(scf_env%ot_preconditioner)
3051 120 : IF (ASSOCIATED(scf_env%ot_preconditioner(channel)%preconditioner)) THEN
3052 82 : CALL destroy_preconditioner(scf_env%ot_preconditioner(channel)%preconditioner)
3053 82 : DEALLOCATE (scf_env%ot_preconditioner(channel)%preconditioner)
3054 : END IF
3055 : END DO
3056 38 : DEALLOCATE (scf_env%ot_preconditioner)
3057 38 : NULLIFY (scf_env%ot_preconditioner)
3058 : END IF
3059 302 : ALLOCATE (scf_env%ot_preconditioner(nchannels))
3060 186 : DO channel = 1, nchannels
3061 640 : ALLOCATE (scf_env%ot_preconditioner(channel)%preconditioner)
3062 : CALL init_preconditioner(scf_env%ot_preconditioner(channel)%preconditioner, &
3063 186 : para_env, blacs_env)
3064 : END DO
3065 :
3066 58 : NULLIFY (eigenvalues, matrix_h_im, matrix_h_re, matrix_s_im, matrix_s_re, &
3067 58 : matrix_t_im, matrix_t_re, mo_coeff_im, mo_coeff_re)
3068 58 : IF (prec_type == ot_precond_full_kinetic) THEN
3069 28 : CPASSERT(ASSOCIATED(matrix_t_kp))
3070 28 : CALL kpoint_operator_prepare(op_ctx, matrix_t_kp, kpoint_slot_t, matrix_row=kpoint_spin_free)
3071 : END IF
3072 :
3073 182 : DO local_kpoint = 1, kpmax
3074 : ! S(k) is spin independent. Build it with the same global-group
3075 : ! redistribution protocol as the Davidson operator itself, directly
3076 : ! as the group-local block-cyclic DBCSR pair of the preconditioner
3077 : ! makers.
3078 124 : CALL dbcsr_init_p(matrix_s_re)
3079 124 : CALL dbcsr_init_p(matrix_s_im)
3080 : CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_s_kp, &
3081 : mat_re=matrix_s_re, mat_im=matrix_s_im, &
3082 124 : matrix_row=kpoint_spin_free, slot=kpoint_slot_s)
3083 :
3084 124 : IF (prec_type == ot_precond_full_kinetic) THEN
3085 56 : CALL dbcsr_init_p(matrix_t_re)
3086 56 : CALL dbcsr_init_p(matrix_t_im)
3087 : CALL kpoint_operator_get(op_ctx, local_kpoint, kpoint_spin_free, matrix_t_kp, &
3088 : mat_re=matrix_t_re, mat_im=matrix_t_im, &
3089 56 : matrix_row=kpoint_spin_free, slot=kpoint_slot_t)
3090 : END IF
3091 :
3092 252 : DO ispin = 1, nspin
3093 128 : IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
3094 56 : CALL dbcsr_init_p(matrix_h_re)
3095 56 : CALL dbcsr_init_p(matrix_h_im)
3096 : CALL kpoint_operator_get(op_ctx, local_kpoint, ispin, matrix_ks_kp, &
3097 56 : mat_re=matrix_h_re, mat_im=matrix_h_im, matrix_row=ispin, slot=kpoint_slot_ks)
3098 : END IF
3099 128 : IF (local_kpoint <= kplocal) THEN
3100 128 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
3101 128 : channel = (local_kpoint - 1)*nspin + ispin
3102 128 : IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
3103 : ! Davidson iterates the full MO set, so its active space is all nmo
3104 : ! MOs of the channel: assemble the complex channel matrices on the
3105 : ! kpoint-group context and call the complex H-based cores directly
3106 : ! (mirrors the complex preconditioners of the K-point OT case; the
3107 : ! FULL_SINGLE_INVERSE variant trades the state selectivity of
3108 : ! FULL_ALL for one shifted factorization and a gemm application)
3109 : CALL get_mo_set(kp%mos(1, ispin), mo_coeff=mo_coeff_re, eigenvalues=eigenvalues, &
3110 56 : nmo=nmo)
3111 56 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
3112 56 : CALL cp_cfm_create(matrix_c, mo_coeff_re%matrix_struct, name="dav pc C")
3113 56 : CALL cp_cfm_scale_and_add_fm(z_zero, matrix_c, z_one, mo_coeff_re)
3114 56 : CALL cp_cfm_scale_and_add_fm(z_one, matrix_c, gaussi, mo_coeff_im)
3115 : CALL dbcsr_pair_to_cfm(matrix_h_re, matrix_h_im, &
3116 : scf_env%ot_preconditioner(channel)%preconditioner, &
3117 56 : 'dav pc H', matrix_h)
3118 : CALL dbcsr_pair_to_cfm(matrix_s_re, matrix_s_im, &
3119 : scf_env%ot_preconditioner(channel)%preconditioner, &
3120 56 : 'dav pc S', matrix_s)
3121 56 : IF (prec_type == ot_precond_full_all) THEN
3122 : CALL make_complex_full_all(scf_env%ot_preconditioner(channel)%preconditioner, &
3123 : matrix_c, matrix_h, matrix_s, eigenvalues(1:nmo), &
3124 40 : energy_gap)
3125 : ELSE
3126 : CALL make_complex_full_single_inverse( &
3127 : scf_env%ot_preconditioner(channel)%preconditioner, &
3128 16 : matrix_c, matrix_h, matrix_s, energy_gap)
3129 : END IF
3130 56 : CALL cp_cfm_release(matrix_c)
3131 56 : CALL cp_cfm_release(matrix_h)
3132 56 : CALL cp_cfm_release(matrix_s)
3133 72 : ELSE IF (prec_type == ot_precond_full_kinetic) THEN
3134 : CALL make_preconditioner_complex_full_kinetic( &
3135 : scf_env%ot_preconditioner(channel)%preconditioner, &
3136 56 : matrix_t_re, matrix_t_im, matrix_s_re, matrix_s_im, energy_gap, solver_type)
3137 16 : ELSE IF (prec_type == ot_precond_s_inverse) THEN
3138 : CALL make_preconditioner_complex_full_s_inverse( &
3139 : scf_env%ot_preconditioner(channel)%preconditioner, &
3140 16 : matrix_s_re, matrix_s_im, solver_type)
3141 : END IF
3142 : END IF
3143 252 : IF (prec_type == ot_precond_full_all .OR. prec_type == ot_precond_full_single_inverse) THEN
3144 56 : CALL dbcsr_release_p(matrix_h_re)
3145 56 : CALL dbcsr_release_p(matrix_h_im)
3146 : END IF
3147 : END DO
3148 :
3149 124 : CALL dbcsr_release_p(matrix_s_re)
3150 124 : CALL dbcsr_release_p(matrix_s_im)
3151 182 : IF (prec_type == ot_precond_full_kinetic) THEN
3152 56 : CALL dbcsr_release_p(matrix_t_re)
3153 56 : CALL dbcsr_release_p(matrix_t_im)
3154 : END IF
3155 : END DO
3156 :
3157 58 : CALL timestop(handle)
3158 :
3159 58 : END SUBROUTINE davidson_kp_prepare_preconditioners
3160 :
3161 : ! **************************************************************************************************
3162 : !> \brief Kpoint diagonalization routine
3163 : !> Transforms matrices to kpoint, distributes kpoint groups, performs diagonalization
3164 : !> \param matrix_s Overlap matrices (RS indices, global)
3165 : !> \param kpoints Kpoint environment
3166 : !> \param fmwork full matrices distributed over all groups
3167 : !> \par History
3168 : !> 02.2026 created [JGH]
3169 : ! **************************************************************************************************
3170 12 : SUBROUTINE diag_kp_smat(matrix_s, kpoints, fmwork)
3171 :
3172 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s
3173 : TYPE(kpoint_type), POINTER :: kpoints
3174 : TYPE(cp_fm_type), DIMENSION(:) :: fmwork
3175 :
3176 : CHARACTER(len=*), PARAMETER :: routineN = 'diag_kp_smat'
3177 : COMPLEX(KIND=dp), PARAMETER :: cone = (1.0_dp, 0.0_dp), &
3178 : czero = (0.0_dp, 0.0_dp)
3179 :
3180 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:) :: ceig
3181 : INTEGER :: handle, ikp, kplocal, kpmax, nao
3182 : INTEGER, DIMENSION(2) :: kp_range
3183 12 : INTEGER, DIMENSION(:, :), POINTER :: kp_dist
3184 : LOGICAL :: use_real_wfn
3185 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues
3186 : TYPE(cp_cfm_type) :: csmat, cwork
3187 12 : TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER :: ao_ao_fm_pools
3188 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct
3189 : TYPE(cp_fm_type) :: fmlocal, rsmat
3190 : TYPE(kpoint_env_type), POINTER :: kp
3191 12 : TYPE(kpoint_operator_context_type) :: op_ctx
3192 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3193 12 : POINTER :: sab_nl
3194 : TYPE(qs_matrix_pools_type), POINTER :: mpools
3195 :
3196 12 : CALL timeset(routineN, handle)
3197 :
3198 12 : NULLIFY (sab_nl)
3199 : CALL get_kpoint_info(kpoints, use_real_wfn=use_real_wfn, kp_range=kp_range, &
3200 12 : kp_dist=kp_dist, sab_nl=sab_nl)
3201 12 : CPASSERT(ASSOCIATED(sab_nl))
3202 12 : kplocal = kp_range(2) - kp_range(1) + 1
3203 24 : kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
3204 :
3205 : ! fm pools to be used within a kpoint group
3206 12 : CALL get_kpoint_info(kpoints, mpools=mpools)
3207 12 : CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
3208 :
3209 12 : CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
3210 12 : CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
3211 :
3212 12 : IF (use_real_wfn) THEN
3213 0 : CALL cp_fm_create(rsmat, matrix_struct)
3214 : ELSE
3215 12 : CALL cp_cfm_create(csmat, matrix_struct)
3216 12 : CALL cp_cfm_create(cwork, matrix_struct)
3217 : END IF
3218 :
3219 12 : CALL cp_fm_get_info(fmwork(1), nrow_global=nao)
3220 60 : ALLOCATE (eigenvalues(nao), ceig(nao))
3221 :
3222 : ! The overlap is spin free: the routine drives every instance under the
3223 : ! single spin-free key.
3224 12 : CALL kpoint_operator_context_create(op_ctx, kpoints, fmwork(1), 1)
3225 12 : CALL kpoint_operator_prepare(op_ctx, matrix_s, kpoint_slot_s, matrix_row=kpoint_spin_free)
3226 268 : DO ikp = 1, kpmax
3227 : CALL kpoint_operator_start(op_ctx, ikp, kpoint_spin_free, matrix_s, kpoint_slot_s, &
3228 268 : use_grid=.FALSE., matrix_row=kpoint_spin_free)
3229 : END DO
3230 :
3231 : ! Finish communication then diagonalise in each group
3232 268 : DO ikp = 1, kpmax
3233 256 : IF (use_real_wfn) THEN
3234 0 : CALL kpoint_operator_finish(op_ctx, ikp, kpoint_spin_free, kpoint_slot_s, fm_re=rsmat)
3235 : ELSE
3236 256 : CALL kpoint_operator_finish(op_ctx, ikp, kpoint_spin_free, kpoint_slot_s, csmat)
3237 : END IF
3238 :
3239 : ! Each kpoint group has now information on a kpoint to be diagonalized
3240 : ! Eigensolver Hermite or Symmetric
3241 256 : IF (ikp > kplocal) CYCLE
3242 256 : kp => kpoints%kp_env(ikp)%kpoint_env
3243 256 : IF (use_real_wfn) THEN
3244 0 : CALL choose_eigv_solver(rsmat, fmlocal, eigenvalues)
3245 : ELSE
3246 256 : CALL cp_cfm_heevd(csmat, cwork, eigenvalues)
3247 : END IF
3248 2680 : CPASSERT(ALL(eigenvalues(1:nao) >= 0.0_dp))
3249 268 : IF (use_real_wfn) THEN
3250 0 : CALL cp_fm_release(kp%shalf)
3251 0 : CALL cp_fm_create(kp%shalf, matrix_struct)
3252 0 : eigenvalues(1:nao) = SQRT(eigenvalues(1:nao))
3253 0 : CALL cp_fm_to_fm(fmlocal, rsmat)
3254 0 : CALL cp_fm_column_scale(rsmat, eigenvalues)
3255 : CALL parallel_gemm("N", "T", nao, nao, nao, 1.0_dp, rsmat, fmlocal, &
3256 0 : 0.0_dp, kp%shalf)
3257 : ELSE
3258 256 : CALL cp_cfm_release(kp%cshalf)
3259 256 : CALL cp_cfm_create(kp%cshalf, matrix_struct)
3260 2680 : ceig(1:nao) = SQRT(eigenvalues(1:nao))
3261 256 : CALL cp_cfm_to_cfm(cwork, csmat)
3262 256 : CALL cp_cfm_column_scale(csmat, ceig)
3263 : CALL parallel_gemm("N", "C", nao, nao, nao, cone, csmat, cwork, &
3264 256 : czero, kp%cshalf)
3265 : END IF
3266 : END DO
3267 :
3268 12 : CALL kpoint_operator_context_release(op_ctx)
3269 :
3270 : ! All done
3271 12 : DEALLOCATE (eigenvalues, ceig)
3272 :
3273 12 : IF (use_real_wfn) THEN
3274 0 : CALL cp_fm_release(rsmat)
3275 : ELSE
3276 12 : CALL cp_cfm_release(csmat)
3277 12 : CALL cp_cfm_release(cwork)
3278 : END IF
3279 12 : CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
3280 :
3281 12 : CALL timestop(handle)
3282 :
3283 48 : END SUBROUTINE diag_kp_smat
3284 :
3285 : END MODULE qs_scf_diagonalization
|