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 : !> \brief Utility routines for qs_scf
9 : ! **************************************************************************************************
10 : MODULE qs_scf_loop_utils
11 : USE cp_control_types, ONLY: dft_control_type,&
12 : hairy_probes_type
13 : USE cp_dbcsr_api, ONLY: dbcsr_copy,&
14 : dbcsr_get_info,&
15 : dbcsr_p_type,&
16 : dbcsr_release,&
17 : dbcsr_release_p,&
18 : dbcsr_scale,&
19 : dbcsr_set,&
20 : dbcsr_type
21 : USE cp_dbcsr_contrib, ONLY: dbcsr_dot,&
22 : dbcsr_get_diag,&
23 : dbcsr_scale_by_vector
24 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
25 : copy_fm_to_dbcsr,&
26 : cp_dbcsr_sm_fm_multiply,&
27 : dbcsr_allocate_matrix_set,&
28 : dbcsr_deallocate_matrix_set
29 : USE cp_external_control, ONLY: external_control
30 : USE cp_fm_basic_linalg, ONLY: cp_complex_fm_gemm,&
31 : cp_fm_column_scale,&
32 : cp_fm_scale_and_add
33 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
34 : cp_fm_struct_release,&
35 : cp_fm_struct_type
36 : USE cp_fm_types, ONLY: cp_fm_create,&
37 : cp_fm_get_info,&
38 : cp_fm_get_submatrix,&
39 : cp_fm_release,&
40 : cp_fm_set_submatrix,&
41 : cp_fm_to_fm,&
42 : cp_fm_type
43 : USE cp_log_handling, ONLY: cp_to_string
44 : USE ieee_arithmetic, ONLY: ieee_is_finite
45 : USE input_constants, ONLY: diag_update_method_adiis,&
46 : smear_fermi_dirac,&
47 : smear_gaussian,&
48 : smear_mp,&
49 : smear_mv
50 : USE input_section_types, ONLY: section_vals_get,&
51 : section_vals_get_subs_vals,&
52 : section_vals_type
53 : USE kinds, ONLY: default_string_length,&
54 : dp
55 : USE kpoint_methods, ONLY: kpoint_density_matrices,&
56 : kpoint_density_transform,&
57 : kpoint_set_mo_occupation
58 : USE kpoint_types, ONLY: get_kpoint_info,&
59 : kpoint_env_type,&
60 : kpoint_type
61 : USE message_passing, ONLY: mp_para_env_type
62 : USE qs_density_matrices, ONLY: calculate_density_matrix
63 : USE qs_density_mixing_types, ONLY: broyden_mixing_nr,&
64 : direct_mixing_nr,&
65 : gspace_mixing_nr,&
66 : modified_broyden_mixing_nr,&
67 : multisecant_mixing_nr,&
68 : new_pulay_mixing_nr,&
69 : no_mixing_nr,&
70 : pulay_mixing_nr
71 : USE qs_energy_types, ONLY: qs_energy_type
72 : USE qs_environment_types, ONLY: get_qs_env,&
73 : qs_environment_type
74 : USE qs_fb_env_methods, ONLY: fb_env_do_diag
75 : USE qs_gspace_mixing, ONLY: gspace_mixing
76 : USE qs_kpoint_operators, ONLY: kpoint_operator_context_create,&
77 : kpoint_operator_context_release,&
78 : kpoint_operator_context_type,&
79 : kpoint_operator_get
80 : USE qs_kpp1_env_types, ONLY: kpp1_release,&
81 : qs_kpp1_env_type
82 : USE qs_ks_types, ONLY: qs_ks_did_change,&
83 : qs_ks_env_type
84 : USE qs_linres_kernel, ONLY: apply_hxc_kernel_kp
85 : USE qs_mixing_utils, ONLY: self_consistency_check
86 : USE qs_mo_occupation, ONLY: set_mo_occupation
87 : USE qs_mo_types, ONLY: get_mo_set,&
88 : mo_set_type
89 : USE qs_mom_methods, ONLY: do_mom_diag
90 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
91 : USE qs_ot, ONLY: &
92 : qs_ot_antihermitian_spectral_norm, qs_ot_density_secant_orbital_overlaps, &
93 : qs_ot_density_secant_projected_hessian, qs_ot_density_tangent, &
94 : qs_ot_finite_rotation_response, qs_ot_fixed_n_energy_gradient, qs_ot_fixed_n_schur_block, &
95 : qs_ot_get_orbitals_complex, qs_ot_get_orbitals_ref_complex, &
96 : qs_ot_projected_response_update, qs_ot_symmetric_abs_solve
97 : USE qs_ot_minimizer, ONLY: ot_mermin_response_preparation_needed,&
98 : ot_mermin_secant_curvature,&
99 : ot_mini,&
100 : ot_mini_prepare_gradient
101 : USE qs_ot_scf, ONLY: ot_scf_destroy,&
102 : ot_scf_mini
103 : USE qs_ot_types, ONLY: qs_ot_channel_index,&
104 : qs_ot_check_channel_context,&
105 : qs_ot_type
106 : USE qs_outer_scf, ONLY: outer_loop_gradient
107 : USE qs_rho_methods, ONLY: qs_rho_update_rho
108 : USE qs_rho_types, ONLY: qs_rho_get,&
109 : qs_rho_type
110 : USE qs_scf_diagonalization, ONLY: &
111 : do_block_davidson_diag, do_block_davidson_diag_kp, do_block_krylov_diag, do_general_diag, &
112 : do_general_diag_kp, do_ot_diag, do_ot_diag_kp, do_roks_diag, do_scf_diag_subspace, &
113 : do_special_diag, qs_scf_get_ot_kpoint_operator
114 : USE qs_scf_methods, ONLY: cp_sm_mix,&
115 : scf_env_density_mixing
116 : USE qs_scf_output, ONLY: qs_scf_print_summary
117 : USE qs_scf_types, ONLY: &
118 : block_davidson_diag_method_nr, block_krylov_diag_method_nr, filter_matrix_diag_method_nr, &
119 : general_diag_method_nr, ot_diag_method_nr, ot_method_nr, qs_scf_env_type, &
120 : smeagol_method_nr, special_diag_method_nr
121 : USE scf_control_types, ONLY: scf_control_type,&
122 : smear_type
123 : USE smeagol_interface, ONLY: run_smeagol_emtrans
124 : USE smearing_utils, ONLY: Smearkp,&
125 : Smearkp2,&
126 : smearing_response_weight
127 : USE tblite_interface, ONLY: tb_native_scc_mixer_active
128 : #include "./base/base_uses.f90"
129 :
130 : IMPLICIT NONE
131 :
132 : PRIVATE
133 :
134 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_loop_utils'
135 :
136 : PUBLIC :: qs_scf_set_loop_flags, &
137 : qs_scf_new_mos, qs_scf_new_mos_kp, &
138 : qs_scf_kp_ref_refresh_ready, qs_scf_kp_search_endpoint, &
139 : qs_scf_candidate_density_delta, qs_scf_commit_density_candidate, &
140 : qs_scf_density_mixing, qs_scf_check_inner_exit, &
141 : qs_scf_check_outer_exit, qs_scf_inner_finalize, qs_scf_rho_update
142 :
143 : CONTAINS
144 :
145 : ! **************************************************************************************************
146 : !> \brief identify an accepted OT search endpoint from its iteration label
147 : !> \param method OT iteration label
148 : !> \return true for the primary endpoint of every supported minimizer
149 : ! **************************************************************************************************
150 2392 : PURE FUNCTION qs_scf_kp_search_endpoint(method) RESULT(endpoint)
151 :
152 : CHARACTER(LEN=*), INTENT(IN) :: method
153 : LOGICAL :: endpoint
154 :
155 2392 : SELECT CASE (TRIM(method))
156 : CASE ("OT CG", "OT SD", "OT DIIS", "OT BROY", "OT LBFGS")
157 1050 : endpoint = .TRUE.
158 : CASE DEFAULT
159 2392 : endpoint = .FALSE.
160 : END SELECT
161 :
162 2392 : END FUNCTION qs_scf_kp_search_endpoint
163 :
164 : ! **************************************************************************************************
165 : !> \brief decide whether a mature variable-occupation REF chart should be rebuilt
166 : !> \param accepted_searches accepted search directions in the current REF chart
167 : !> \param residual current OT residual
168 : !> \param eps_scf requested SCF threshold
169 : !> \param base_state whether the current point can start a new search direction
170 : !> \param allow_exit_window whether a prior physical REF rebuild permits an exit-only rebuild
171 : !> \return true inside the asymptotic residual window after sufficient accepted history
172 : ! **************************************************************************************************
173 1288 : PURE FUNCTION qs_scf_kp_ref_refresh_ready( &
174 : accepted_searches, residual, eps_scf, base_state, allow_exit_window) &
175 : RESULT(refresh)
176 :
177 : INTEGER, INTENT(IN) :: accepted_searches
178 : REAL(KIND=dp), INTENT(IN) :: residual, eps_scf
179 : LOGICAL, INTENT(IN) :: base_state
180 : LOGICAL, INTENT(IN), OPTIONAL :: allow_exit_window
181 : LOGICAL :: refresh
182 :
183 : INTEGER, PARAMETER :: min_accepted_searches = 12
184 :
185 : LOGICAL :: exit_window
186 : REAL(KIND=dp) :: eps
187 :
188 1288 : eps = MAX(eps_scf, EPSILON(1.0_dp))
189 1288 : exit_window = .FALSE.
190 1288 : IF (PRESENT(allow_exit_window)) exit_window = allow_exit_window
191 : refresh = base_state .AND. accepted_searches >= min_accepted_searches .AND. &
192 : ((residual > 10.0_dp*eps .AND. residual <= 0.2_dp*SQRT(eps)) .OR. &
193 1288 : (exit_window .AND. residual > 0.25_dp*eps .AND. residual <= 10.0_dp*eps))
194 :
195 1288 : END FUNCTION qs_scf_kp_ref_refresh_ready
196 :
197 : ! **************************************************************************************************
198 : !> \brief computes properties for a given hamiltonian using the current wfn
199 : !> \param scf_env ...
200 : !> \param diis_step ...
201 : !> \param energy_only ...
202 : !> \param just_energy ...
203 : !> \param exit_inner_loop ...
204 : ! **************************************************************************************************
205 25117 : SUBROUTINE qs_scf_set_loop_flags(scf_env, diis_step, &
206 : energy_only, just_energy, exit_inner_loop)
207 :
208 : TYPE(qs_scf_env_type), POINTER :: scf_env
209 : LOGICAL :: diis_step, energy_only, just_energy, &
210 : exit_inner_loop
211 :
212 : ! Some flags needed to be set at the beginning of the loop
213 :
214 25117 : diis_step = .FALSE.
215 25117 : energy_only = .FALSE.
216 25117 : just_energy = .FALSE.
217 :
218 : ! SCF loop, optimisation of the wfn coefficients
219 : ! qs_env%rho%rho_r and qs_env%rho%rho_g should be up to date here
220 :
221 25117 : scf_env%iter_count = 0
222 25117 : scf_env%adiis_check_next = .FALSE.
223 25117 : scf_env%adiis_validated = .FALSE.
224 25117 : scf_env%step_norm = 0.0_dp
225 25117 : scf_env%raw_map_delta = 0.0_dp
226 25117 : scf_env%oda_lambda = 0.0_dp
227 25117 : scf_env%oda_energy = 0.0_dp
228 25117 : scf_env%oda_gradient0 = 0.0_dp
229 25117 : scf_env%oda_gradient1 = 0.0_dp
230 25117 : scf_env%oda_evaluations = 0
231 25117 : scf_env%oda_status = ""
232 25117 : scf_env%raw_map_delta_valid = .FALSE.
233 25117 : exit_inner_loop = .FALSE.
234 :
235 25117 : END SUBROUTINE qs_scf_set_loop_flags
236 :
237 : ! **************************************************************************************************
238 : !> \brief takes known energy and derivatives and produces new wfns
239 : !> and or density matrix
240 : !> \param qs_env ...
241 : !> \param scf_env ...
242 : !> \param scf_control ...
243 : !> \param scf_section ...
244 : !> \param diis_step ...
245 : !> \param energy_only ...
246 : !> \param probe ...
247 : ! **************************************************************************************************
248 198195 : SUBROUTINE qs_scf_new_mos(qs_env, scf_env, scf_control, scf_section, diis_step, &
249 : energy_only, probe)
250 : TYPE(qs_environment_type), POINTER :: qs_env
251 : TYPE(qs_scf_env_type), POINTER :: scf_env
252 : TYPE(scf_control_type), POINTER :: scf_control
253 : TYPE(section_vals_type), POINTER :: scf_section
254 : LOGICAL :: diis_step, energy_only
255 : TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
256 : POINTER :: probe
257 :
258 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_new_mos'
259 :
260 : INTEGER :: handle, ispin
261 : LOGICAL :: disable_diis, has_unit_metric, &
262 : skip_diag_sub
263 : REAL(KIND=dp) :: saved_eps_diis
264 198195 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
265 : TYPE(dft_control_type), POINTER :: dft_control
266 198195 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
267 : TYPE(qs_energy_type), POINTER :: energy
268 : TYPE(qs_ks_env_type), POINTER :: ks_env
269 : TYPE(qs_rho_type), POINTER :: rho
270 :
271 198195 : CALL timeset(routineN, handle)
272 :
273 198195 : NULLIFY (energy, ks_env, matrix_ks, matrix_s, rho, mos, dft_control)
274 :
275 : CALL get_qs_env(qs_env=qs_env, &
276 : matrix_s=matrix_s, energy=energy, &
277 : ks_env=ks_env, &
278 : matrix_ks=matrix_ks, rho=rho, mos=mos, &
279 : dft_control=dft_control, &
280 198195 : has_unit_metric=has_unit_metric)
281 198195 : scf_env%iter_param = 0.0_dp
282 :
283 : disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. &
284 198195 : tb_native_scc_mixer_active(dft_control)
285 : IF (disable_diis) THEN
286 12006 : saved_eps_diis = scf_control%eps_diis
287 12006 : scf_control%eps_diis = 0.0_dp
288 : END IF
289 :
290 : ! transfer total_zeff_corr from qs_env to scf_env only if
291 : ! correct_el_density_dip is switched on [SGh]
292 198195 : IF (dft_control%correct_el_density_dip) THEN
293 40 : scf_env%sum_zeff_corr = qs_env%total_zeff_corr
294 40 : IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
295 40 : IF (scf_env%method /= general_diag_method_nr) THEN
296 : CALL cp_abort(__LOCATION__, &
297 : "Please use ALGORITHM STANDARD in "// &
298 : "SCF%DIAGONALIZATION if "// &
299 : "CORE_CORRECTION /= 0.0 and "// &
300 0 : "SURFACE_DIPOLE_CORRECTION TRUE ")
301 40 : ELSE IF (dft_control%roks) THEN
302 : CALL cp_abort(__LOCATION__, &
303 : "Combination of "// &
304 : "CORE_CORRECTION /= 0.0 and "// &
305 : "SURFACE_DIPOLE_CORRECTION TRUE "// &
306 0 : "is not implemented with ROKS")
307 40 : ELSE IF (scf_control%diagonalization%mom) THEN
308 : CALL cp_abort(__LOCATION__, &
309 : "Combination of "// &
310 : "CORE_CORRECTION /= 0.0 and "// &
311 : "SURFACE_DIPOLE_CORRECTION TRUE "// &
312 0 : "is not implemented with SCF%MOM")
313 : END IF
314 : END IF
315 : END IF
316 :
317 198195 : SELECT CASE (scf_env%method)
318 : CASE DEFAULT
319 : CALL cp_abort(__LOCATION__, &
320 : "unknown scf method: "// &
321 0 : cp_to_string(scf_env%method))
322 :
323 : ! *************************************************************************
324 : ! Filter matrix diagonalisation: ugly implementation at this point of time
325 : ! *************************************************************************
326 : CASE (filter_matrix_diag_method_nr)
327 :
328 80 : IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
329 : CALL cp_abort(__LOCATION__, &
330 : "CORE_CORRECTION /= 0.0 plus SURFACE_DIPOLE_CORRECTION TRUE "// &
331 0 : "requires SCF%DIAGONALIZATION: ALGORITHM STANDARD")
332 : END IF
333 : CALL fb_env_do_diag(scf_env%filter_matrix_env, qs_env, &
334 80 : matrix_ks, matrix_s, scf_section, diis_step)
335 :
336 : ! Diagonlization in non orthonormal case
337 : CASE (general_diag_method_nr)
338 99575 : IF (dft_control%roks) THEN
339 : CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
340 : scf_control, scf_section, diis_step, &
341 610 : has_unit_metric)
342 : ELSE
343 98965 : IF (scf_control%diagonalization%mom) THEN
344 : CALL do_mom_diag(scf_env, mos, matrix_ks, &
345 : matrix_s, scf_control, scf_section, &
346 324 : diis_step)
347 : ELSE
348 98641 : IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
349 : CALL do_general_diag(scf_env, mos, matrix_ks, &
350 : matrix_s, scf_control, scf_section, &
351 : diis_step, &
352 14 : probe)
353 : ELSE
354 : CALL do_general_diag(scf_env, mos, matrix_ks, &
355 : matrix_s, scf_control, scf_section, &
356 98627 : diis_step)
357 : END IF
358 : END IF
359 98965 : IF (scf_control%do_diag_sub) THEN
360 : skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
361 10 : (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
362 : IF (.NOT. skip_diag_sub) THEN
363 : CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
364 10 : ks_env, scf_section, scf_control)
365 : END IF
366 : END IF
367 : END IF
368 : ! Diagonlization in orthonormal case
369 : CASE (special_diag_method_nr)
370 18398 : IF (dft_control%roks) THEN
371 : CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
372 : scf_control, scf_section, diis_step, &
373 522 : has_unit_metric)
374 : ELSE
375 : CALL do_special_diag(scf_env, mos, matrix_ks, &
376 : scf_control, scf_section, &
377 17876 : diis_step)
378 : END IF
379 : ! OT diagonalization
380 : CASE (ot_diag_method_nr)
381 : CALL do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
382 202 : scf_control, scf_section, diis_step)
383 : ! Block Krylov diagonlization
384 : CASE (block_krylov_diag_method_nr)
385 40 : IF ((scf_env%krylov_space%eps_std_diag > 0.0_dp) .AND. &
386 : (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%krylov_space%eps_std_diag)) THEN
387 2 : IF (scf_env%krylov_space%always_check_conv) THEN
388 : CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
389 0 : scf_control, scf_section, check_moconv_only=.TRUE.)
390 : END IF
391 : CALL do_general_diag(scf_env, mos, matrix_ks, &
392 2 : matrix_s, scf_control, scf_section, diis_step)
393 : ELSE
394 : CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
395 38 : scf_control, scf_section)
396 : END IF
397 40 : IF (scf_control%do_diag_sub) THEN
398 : skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
399 0 : (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
400 : IF (.NOT. skip_diag_sub) THEN
401 : CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
402 0 : ks_env, scf_section, scf_control)
403 : END IF
404 : END IF
405 : ! Block Davidson diagonlization
406 : CASE (block_davidson_diag_method_nr)
407 : CALL do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, scf_control, &
408 94 : scf_section, .FALSE.)
409 : ! OT without diagonlization. Needs special treatment for SCP runs
410 : CASE (ot_method_nr)
411 : CALL qs_scf_loop_do_ot(qs_env, scf_env, scf_control%smear, mos, rho, &
412 : qs_env%mo_derivs, energy%total, &
413 198195 : matrix_s, energy_only=energy_only, has_unit_metric=has_unit_metric)
414 : END SELECT
415 198195 : IF (disable_diis) scf_control%eps_diis = saved_eps_diis
416 :
417 198195 : energy%kTS = 0.0_dp
418 198195 : energy%efermi = 0.0_dp
419 198195 : CALL get_qs_env(qs_env, mos=mos)
420 429943 : DO ispin = 1, SIZE(mos)
421 231748 : energy%kTS = energy%kTS + mos(ispin)%kTS
422 429943 : energy%efermi = energy%efermi + mos(ispin)%mu
423 : END DO
424 198195 : energy%efermi = energy%efermi/REAL(SIZE(mos), KIND=dp)
425 :
426 198195 : CALL timestop(handle)
427 :
428 198195 : END SUBROUTINE qs_scf_new_mos
429 :
430 : ! **************************************************************************************************
431 : !> \brief Updates MOs and density matrix using diagonalization
432 : !> Kpoint code
433 : !> \param qs_env ...
434 : !> \param scf_env ...
435 : !> \param scf_control ...
436 : !> \param diis_step ...
437 : !> \param probe ...
438 : !> \param ot_kp_subspace_refresh ...
439 : !> \param allow_ot_kp_subspace_refresh ...
440 : !> \param allow_ot_kp_exit_refresh ...
441 : !> \param accepted_ot_kp_searches ...
442 : !> \param added_mos_auto_grow ...
443 : !> \param energy_only ...
444 : ! **************************************************************************************************
445 36378 : SUBROUTINE qs_scf_new_mos_kp(qs_env, scf_env, scf_control, diis_step, probe, &
446 : ot_kp_subspace_refresh, allow_ot_kp_subspace_refresh, &
447 : allow_ot_kp_exit_refresh, accepted_ot_kp_searches, &
448 : added_mos_auto_grow, energy_only)
449 : TYPE(qs_environment_type), POINTER :: qs_env
450 : TYPE(qs_scf_env_type), POINTER :: scf_env
451 : TYPE(scf_control_type), POINTER :: scf_control
452 : LOGICAL :: diis_step
453 : TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
454 : POINTER :: probe
455 : LOGICAL, INTENT(OUT), OPTIONAL :: ot_kp_subspace_refresh
456 : LOGICAL, INTENT(IN), OPTIONAL :: allow_ot_kp_subspace_refresh, &
457 : allow_ot_kp_exit_refresh
458 : INTEGER, INTENT(IN), OPTIONAL :: accepted_ot_kp_searches
459 : LOGICAL, INTENT(OUT), OPTIONAL :: added_mos_auto_grow, energy_only
460 :
461 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_new_mos_kp'
462 :
463 : INTEGER :: accepted_searches, handle, ispin, &
464 : refresh_count
465 : LOGICAL :: allow_exit_refresh, allow_refresh, base_state, disable_diis, has_unit_metric, &
466 : my_added_mos_auto_grow, ot_energy_only, refresh
467 : REAL(dp) :: diis_error, residual, saved_eps_diis
468 36378 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s, matrix_t
469 : TYPE(dft_control_type), POINTER :: dft_control
470 : TYPE(kpoint_type), POINTER :: kpoints
471 36378 : TYPE(mo_set_type), DIMENSION(:, :), POINTER :: mos
472 : TYPE(mp_para_env_type), POINTER :: para_env
473 : TYPE(qs_energy_type), POINTER :: energy
474 :
475 36378 : CALL timeset(routineN, handle)
476 :
477 36378 : allow_refresh = .FALSE.
478 36378 : allow_exit_refresh = .FALSE.
479 36378 : accepted_searches = 0
480 36378 : my_added_mos_auto_grow = .FALSE.
481 36378 : refresh = .FALSE.
482 36378 : IF (PRESENT(allow_ot_kp_subspace_refresh)) allow_refresh = allow_ot_kp_subspace_refresh
483 36378 : IF (PRESENT(allow_ot_kp_exit_refresh)) allow_exit_refresh = allow_ot_kp_exit_refresh
484 36378 : IF (PRESENT(accepted_ot_kp_searches)) accepted_searches = accepted_ot_kp_searches
485 36378 : IF (PRESENT(ot_kp_subspace_refresh)) ot_kp_subspace_refresh = .FALSE.
486 36378 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .FALSE.
487 36378 : IF (PRESENT(energy_only)) energy_only = .FALSE.
488 :
489 36378 : NULLIFY (dft_control, energy, kpoints, matrix_ks, matrix_s, matrix_t, para_env)
490 :
491 36378 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, energy=energy, kpoints=kpoints)
492 36378 : CALL get_kpoint_info(kpoints, para_env=para_env)
493 36378 : CPASSERT(ASSOCIATED(para_env))
494 36378 : scf_env%iter_param = 0.0_dp
495 : disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. &
496 36378 : tb_native_scc_mixer_active(dft_control)
497 : IF (disable_diis) THEN
498 10420 : saved_eps_diis = scf_control%eps_diis
499 10420 : scf_control%eps_diis = 0.0_dp
500 : END IF
501 :
502 36378 : IF (dft_control%roks .AND. scf_env%method /= ot_method_nr) THEN
503 0 : CPABORT("KP code: ROKS method not available: ")
504 : END IF
505 :
506 36378 : SELECT CASE (scf_env%method)
507 : CASE DEFAULT
508 : CALL cp_abort(__LOCATION__, &
509 : "KP code: Unknown scf method: "// &
510 0 : cp_to_string(scf_env%method))
511 : CASE (general_diag_method_nr)
512 : ! Diagonlization in non orthonormal case
513 32994 : CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
514 32994 : IF (scf_control%diagonalization%update_method == diag_update_method_adiis) THEN
515 122 : CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
516 122 : diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
517 : END IF
518 32994 : IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
519 0 : scf_control%smear%do_smear = .FALSE.
520 : CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
521 0 : diis_step, diis_error, qs_env, probe)
522 : ELSE
523 : CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
524 : diis_step, diis_error, qs_env, &
525 32994 : added_mos_auto_grow=my_added_mos_auto_grow)
526 : END IF
527 32994 : IF (my_added_mos_auto_grow) THEN
528 0 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
529 0 : IF (disable_diis) scf_control%eps_diis = saved_eps_diis
530 0 : CALL timestop(handle)
531 6 : RETURN
532 : END IF
533 32994 : IF (scf_control%diagonalization%update_method == diag_update_method_adiis .AND. &
534 0 : .NOT. diis_step) THEN
535 74 : scf_env%iter_param = diis_error
536 74 : IF (scf_env%scf_subspace_buffer%last_restart) THEN
537 0 : scf_env%iter_method = "ADIIS/Rst."
538 : ELSE
539 74 : scf_env%iter_method = "ADIIS/Diag."
540 : END IF
541 32920 : ELSE IF (diis_step) THEN
542 10294 : scf_env%iter_param = diis_error
543 10294 : scf_env%iter_method = "DIIS/Diag."
544 : ELSE
545 22626 : IF (scf_env%mixing_method == 0) THEN
546 0 : scf_env%iter_method = "NoMix/Diag."
547 22626 : ELSE IF (scf_env%mixing_method == 1) THEN
548 20082 : scf_env%iter_param = scf_env%p_mix_alpha
549 20082 : scf_env%iter_method = "P_Mix/Diag."
550 2544 : ELSE IF (scf_env%mixing_method > 1) THEN
551 2544 : scf_env%iter_param = scf_env%mixing_store%alpha
552 2544 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
553 : END IF
554 : END IF
555 : CASE (special_diag_method_nr)
556 0 : CALL get_qs_env(qs_env=qs_env, has_unit_metric=has_unit_metric)
557 0 : CPASSERT(has_unit_metric)
558 : ! Diagonlization in orthonormal case
559 : CALL cp_abort(__LOCATION__, &
560 : "KP code: Scf method not available: "// &
561 0 : cp_to_string(scf_env%method))
562 : CASE (ot_diag_method_nr)
563 58 : CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s, kinetic_kp=matrix_t)
564 : CALL do_ot_diag_kp(matrix_ks, matrix_s, matrix_t, kpoints, scf_env, scf_control, &
565 58 : diis_step, my_added_mos_auto_grow)
566 58 : IF (my_added_mos_auto_grow) THEN
567 0 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
568 0 : IF (disable_diis) scf_control%eps_diis = saved_eps_diis
569 0 : CALL timestop(handle)
570 0 : RETURN
571 : END IF
572 : CASE (block_krylov_diag_method_nr)
573 : CALL cp_abort(__LOCATION__, &
574 : "KP code: Scf method not available: "// &
575 0 : cp_to_string(scf_env%method))
576 : CASE (block_davidson_diag_method_nr)
577 932 : CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
578 : CALL do_block_davidson_diag_kp(qs_env, scf_env, matrix_ks, matrix_s, kpoints, &
579 932 : scf_control)
580 : CASE (ot_method_nr)
581 2394 : CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
582 : base_state = .NOT. scf_env%qs_ot_env(1)%energy_only .AND. &
583 : (scf_env%qs_ot_env(1)%line_search_count == 0 .OR. &
584 2394 : scf_env%qs_ot_env(1)%line_search_might_be_done)
585 2394 : residual = MAX(scf_env%iter_delta, scf_env%qs_ot_env(1)%delta)
586 : refresh = (allow_refresh .OR. allow_exit_refresh) .AND. &
587 : scf_env%qs_ot_env(1)%settings%do_ener .AND. &
588 : scf_env%qs_ot_env(1)%settings%occupation_preconditioner .AND. &
589 : (dft_control%smear .OR. scf_control%smear%do_smear) .AND. &
590 : qs_scf_kp_ref_refresh_ready(accepted_searches, residual, &
591 2394 : scf_control%eps_scf, base_state, allow_exit_refresh)
592 2394 : refresh_count = MERGE(1, 0, refresh)
593 2394 : CALL para_env%sum(refresh_count)
594 2394 : refresh = refresh_count > 0
595 2394 : IF (refresh) THEN
596 24 : IF (PRESENT(ot_kp_subspace_refresh)) ot_kp_subspace_refresh = .TRUE.
597 : ELSE
598 : CALL qs_scf_loop_do_ot_kp(qs_env, scf_env, matrix_ks, matrix_s, &
599 2370 : my_added_mos_auto_grow, ot_energy_only)
600 2370 : IF (PRESENT(energy_only)) energy_only = ot_energy_only
601 2370 : IF (my_added_mos_auto_grow) THEN
602 6 : IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
603 6 : IF (disable_diis) scf_control%eps_diis = saved_eps_diis
604 6 : CALL timestop(handle)
605 6 : RETURN
606 : END IF
607 2364 : IF (allow_exit_refresh .AND. scf_env%iter_delta <= scf_control%eps_scf) THEN
608 14 : base_state = qs_scf_kp_search_endpoint(scf_env%iter_method)
609 : refresh = qs_scf_kp_ref_refresh_ready( &
610 : accepted_searches, scf_env%iter_delta, scf_control%eps_scf, &
611 14 : base_state, allow_exit_window=.TRUE.)
612 14 : IF (refresh .AND. PRESENT(ot_kp_subspace_refresh)) THEN
613 0 : ot_kp_subspace_refresh = .TRUE.
614 : END IF
615 : END IF
616 2364 : refresh_count = MERGE(1, 0, refresh)
617 2364 : CALL para_env%sum(refresh_count)
618 2364 : refresh = refresh_count > 0
619 2364 : IF (refresh .AND. PRESENT(ot_kp_subspace_refresh)) THEN
620 0 : ot_kp_subspace_refresh = .TRUE.
621 : END IF
622 : END IF
623 : CASE (smeagol_method_nr)
624 : ! SMEAGOL interface
625 0 : diis_step = .FALSE.
626 0 : IF (scf_env%mixing_method == 0) THEN
627 0 : scf_env%iter_method = "NoMix/SMGL"
628 0 : ELSE IF (scf_env%mixing_method == 1) THEN
629 0 : scf_env%iter_param = scf_env%p_mix_alpha
630 0 : scf_env%iter_method = "P_Mix/SMGL"
631 0 : ELSE IF (scf_env%mixing_method > 1) THEN
632 0 : scf_env%iter_param = scf_env%mixing_store%alpha
633 0 : scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/SMGL"
634 : END IF
635 36436 : CALL run_smeagol_emtrans(qs_env, last=.FALSE., iter=scf_env%iter_count, rho_ao_kp=scf_env%p_mix_new)
636 : END SELECT
637 36372 : IF (disable_diis) scf_control%eps_diis = saved_eps_diis
638 :
639 36372 : CALL get_qs_env(qs_env=qs_env, energy=energy)
640 36372 : energy%kTS = 0.0_dp
641 36372 : energy%efermi = 0.0_dp
642 36372 : mos => kpoints%kp_env(1)%kpoint_env%mos
643 74950 : DO ispin = 1, SIZE(mos, 2)
644 38578 : energy%kTS = energy%kTS + mos(1, ispin)%kTS
645 74950 : energy%efermi = energy%efermi + mos(1, ispin)%mu
646 : END DO
647 36372 : energy%efermi = energy%efermi/REAL(SIZE(mos, 2), KIND=dp)
648 :
649 36372 : CALL timestop(handle)
650 :
651 36378 : END SUBROUTINE qs_scf_new_mos_kp
652 :
653 : ! **************************************************************************************************
654 : !> \brief K-point OT driver for local complex spin/k-point channels
655 : !> \param qs_env ...
656 : !> \param scf_env ...
657 : !> \param matrix_ks ...
658 : !> \param matrix_s ...
659 : !> \param added_mos_auto_grow ...
660 : !> \param energy_only ...
661 : ! **************************************************************************************************
662 2370 : SUBROUTINE qs_scf_loop_do_ot_kp(qs_env, scf_env, matrix_ks, matrix_s, added_mos_auto_grow, energy_only)
663 :
664 : TYPE(qs_environment_type), POINTER :: qs_env
665 : TYPE(qs_scf_env_type), POINTER :: scf_env
666 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s
667 : LOGICAL, INTENT(OUT) :: added_mos_auto_grow, energy_only
668 :
669 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_loop_do_ot_kp'
670 :
671 : INTEGER :: energy_spin, energy_start, first_channel, handle, homo, icomponent, ikpoint, &
672 : ispin, local_channel, local_kpoint, nao, nkp_groups, nkpoint, nlocal_channels, nmo, &
673 : nspin_energy, nspin_ot
674 : INTEGER, DIMENSION(2) :: kp_range
675 : LOGICAL :: ot_gradient_prepared, &
676 : physical_base_state, restricted_roks, &
677 : transfer_step, use_real_wfn
678 : REAL(KIND=dp) :: trial_kTS
679 2370 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: orbital_scaling_factor, roks_occupation, &
680 2370 : trial_mu
681 2370 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: trial_eigenvalues, trial_occupation
682 2370 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvalues, occupation_numbers, wkp
683 : TYPE(cp_fm_struct_type), POINTER :: active_mo_struct, chc_struct
684 : TYPE(cp_fm_type) :: active_mo_coeff, active_mo_coeff_im, &
685 : chc_im, chc_re, hc_im, hc_re, &
686 : hc_roks_im, hc_roks_re
687 2370 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
688 : TYPE(cp_fm_type), POINTER :: mo_coeff, mo_coeff_im, mo_coeff_target
689 2370 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_hc, matrix_hc_im, &
690 2370 : matrix_hc_physical, &
691 2370 : matrix_hc_physical_im
692 2370 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: density_target, rho_ao_kp
693 : TYPE(dbcsr_type), POINTER :: matrix_k_im, matrix_k_re, matrix_s_im, &
694 : matrix_s_re
695 : TYPE(dft_control_type), POINTER :: dft_control
696 : TYPE(kpoint_env_type), POINTER :: kp
697 : TYPE(kpoint_type), POINTER :: kpoints
698 : TYPE(mp_para_env_type), POINTER :: para_env_inter_kp
699 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
700 2370 : POINTER :: sab_nl
701 : TYPE(qs_energy_type), POINTER :: energy
702 2370 : TYPE(qs_ot_type), DIMENSION(:), POINTER :: local_ot_env
703 : TYPE(qs_rho_type), POINTER :: rho
704 : TYPE(scf_control_type), POINTER :: scf_control
705 :
706 2370 : CALL timeset(routineN, handle)
707 2370 : added_mos_auto_grow = .FALSE.
708 2370 : ot_gradient_prepared = .FALSE.
709 :
710 2370 : NULLIFY (active_mo_struct, chc_struct, density_target, dft_control, energy, fmwork, kpoints, &
711 2370 : local_ot_env, matrix_hc, matrix_hc_im, matrix_k_im, matrix_k_re, matrix_s_im, &
712 2370 : matrix_hc_physical, matrix_hc_physical_im, matrix_s_re, mo_coeff, mo_coeff_im, &
713 2370 : occupation_numbers, para_env_inter_kp, rho, &
714 2370 : rho_ao_kp, sab_nl, scf_control, wkp)
715 :
716 2370 : CPASSERT(ASSOCIATED(scf_env%qs_ot_env))
717 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, energy=energy, kpoints=kpoints, rho=rho, &
718 2370 : scf_control=scf_control)
719 : CALL get_kpoint_info(kpoints, nkp=nkpoint, wkp=wkp, use_real_wfn=use_real_wfn, &
720 : kp_range=kp_range, nkp_groups=nkp_groups, para_env_inter_kp=para_env_inter_kp, &
721 2370 : sab_nl=sab_nl)
722 2370 : fmwork => scf_env%scf_work1
723 2370 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
724 2370 : CPASSERT(ASSOCIATED(sab_nl))
725 2370 : CPASSERT(ASSOCIATED(matrix_ks))
726 2370 : CPASSERT(ASSOCIATED(matrix_s))
727 :
728 2370 : IF (use_real_wfn) THEN
729 : CALL cp_abort(__LOCATION__, &
730 0 : "K-point OT driver currently supports complex k-point wavefunctions only.")
731 : END IF
732 2370 : IF (scf_env%qs_ot_env(1)%settings%ot_algorithm /= "TOD" .AND. &
733 : scf_env%qs_ot_env(1)%settings%ot_algorithm /= "REF") THEN
734 : CALL cp_abort(__LOCATION__, &
735 0 : "K-point OT driver supports OT%ALGORITHM STRICT or IRAC.")
736 : END IF
737 2370 : kp => kpoints%kp_env(1)%kpoint_env
738 2370 : restricted_roks = dft_control%restricted
739 2370 : nspin_ot = MERGE(1, SIZE(kp%mos, 2), restricted_roks)
740 2370 : nspin_energy = MERGE(SIZE(kp%mos, 2), nspin_ot, restricted_roks)
741 : CALL qs_ot_check_channel_context(scf_env%qs_ot_env, nspin_ot, &
742 : nkpoint=nkpoint, &
743 : restricted=ANY(scf_env%qs_ot_env(:)%restricted), &
744 : require_kpoint=.TRUE., &
745 : kp_range=kp_range, &
746 : wkp=wkp, &
747 : require_local_state=.TRUE., &
748 7184 : require_complex_state=.TRUE.)
749 :
750 2370 : IF (nkp_groups > 1) THEN
751 744 : transfer_step = .FALSE.
752 : CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .FALSE., &
753 744 : transfer_step, store_ot_matrices=.TRUE., transfer_only=.TRUE.)
754 : END IF
755 :
756 2370 : first_channel = qs_ot_channel_index(1, kp_range(1), nspin_ot)
757 2370 : nlocal_channels = SIZE(kpoints%kp_env)*nspin_ot
758 2370 : local_ot_env => scf_env%qs_ot_env(first_channel:first_channel + nlocal_channels - 1)
759 2370 : local_ot_env(1)%etotal = energy%total
760 : physical_base_state = local_ot_env(1)%settings%do_ener .AND. &
761 : .NOT. local_ot_env(1)%energy_only .AND. &
762 : (local_ot_env(1)%line_search_count == 0 .OR. &
763 2370 : local_ot_env(1)%line_search_might_be_done)
764 :
765 11012 : ALLOCATE (matrix_hc(nlocal_channels))
766 8642 : ALLOCATE (matrix_hc_im(nlocal_channels))
767 2370 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
768 4152 : ALLOCATE (matrix_hc_physical(nlocal_channels))
769 4152 : ALLOCATE (matrix_hc_physical_im(nlocal_channels))
770 : END IF
771 6272 : DO local_channel = 1, nlocal_channels
772 3902 : NULLIFY (matrix_hc(local_channel)%matrix)
773 3902 : NULLIFY (matrix_hc_im(local_channel)%matrix)
774 3902 : ALLOCATE (matrix_hc(local_channel)%matrix)
775 3902 : ALLOCATE (matrix_hc_im(local_channel)%matrix)
776 3902 : CALL dbcsr_copy(matrix_hc(local_channel)%matrix, local_ot_env(local_channel)%matrix_x, name="matrix_hc")
777 : CALL dbcsr_copy(matrix_hc_im(local_channel)%matrix, local_ot_env(local_channel)%matrix_x_im, &
778 3902 : name="matrix_hc_im")
779 3902 : CALL dbcsr_set(matrix_hc(local_channel)%matrix, 0.0_dp)
780 3902 : CALL dbcsr_set(matrix_hc_im(local_channel)%matrix, 0.0_dp)
781 6272 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
782 1688 : NULLIFY (matrix_hc_physical(local_channel)%matrix)
783 1688 : NULLIFY (matrix_hc_physical_im(local_channel)%matrix)
784 1688 : ALLOCATE (matrix_hc_physical(local_channel)%matrix)
785 1688 : ALLOCATE (matrix_hc_physical_im(local_channel)%matrix)
786 : CALL dbcsr_copy(matrix_hc_physical(local_channel)%matrix, &
787 1688 : local_ot_env(local_channel)%matrix_x, name="matrix_hc_physical")
788 : CALL dbcsr_copy(matrix_hc_physical_im(local_channel)%matrix, &
789 1688 : local_ot_env(local_channel)%matrix_x_im, name="matrix_hc_physical_im")
790 1688 : CALL dbcsr_set(matrix_hc_physical(local_channel)%matrix, 0.0_dp)
791 1688 : CALL dbcsr_set(matrix_hc_physical_im(local_channel)%matrix, 0.0_dp)
792 : END IF
793 : END DO
794 :
795 6068 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
796 3698 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
797 3698 : ikpoint = kp%nkpoint
798 3698 : CPASSERT(ASSOCIATED(kp%ot_hmat))
799 3698 : CPASSERT(SIZE(kp%ot_hmat, 1) >= 2)
800 9970 : DO ispin = 1, nspin_ot
801 3902 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
802 : CALL qs_scf_get_ot_kpoint_operator( &
803 : matrix_ks, kpoints, kp, MIN(ispin, SIZE(matrix_ks, 1)), &
804 : kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
805 3902 : kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))), matrix_k_re, matrix_k_im)
806 3902 : IF (physical_base_state .AND. nkp_groups == 1) THEN
807 : ! The direct single-group transform bypasses the full-matrix cache. Synchronize it
808 : ! at accepted endpoints so the physical Mermin history sees the H(k) used for H(k)C(k).
809 : CALL copy_dbcsr_to_fm( &
810 810 : matrix_k_re, kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))))
811 : CALL copy_dbcsr_to_fm( &
812 810 : matrix_k_im, kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))))
813 : END IF
814 :
815 : CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, nao=nao, nmo=nmo, &
816 3902 : occupation_numbers=occupation_numbers)
817 3902 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
818 3902 : IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
819 3902 : CPASSERT(homo >= 1 .AND. homo <= nmo)
820 3902 : IF (.NOT. local_ot_env(local_channel)%settings%do_ener) THEN
821 18390 : IF (MAXVAL(ABS(occupation_numbers(1:homo) - occupation_numbers(1))) > &
822 : 100.0_dp*EPSILON(1.0_dp)) THEN
823 : CALL cp_abort(__LOCATION__, &
824 0 : "Fixed-occupation K-point OT requires uniform occupations within each channel.")
825 : END IF
826 2062 : IF (occupation_numbers(1) <= 100.0_dp*EPSILON(1.0_dp)) THEN
827 : CALL cp_abort(__LOCATION__, &
828 0 : "Fixed-occupation K-point OT encountered an empty active orbital block.")
829 : END IF
830 2062 : IF (homo < nmo) THEN
831 128 : IF (MAXVAL(ABS(occupation_numbers(homo + 1:nmo))) > 100.0_dp*EPSILON(1.0_dp)) THEN
832 : CALL cp_abort(__LOCATION__, &
833 0 : "Fixed-occupation K-point OT cannot optimize occupied padded MO columns.")
834 : END IF
835 : END IF
836 : END IF
837 : CALL cp_fm_struct_create(active_mo_struct, template_fmstruct=mo_coeff%matrix_struct, &
838 3902 : ncol_global=homo)
839 3902 : CALL cp_fm_create(active_mo_coeff, active_mo_struct)
840 3902 : CALL cp_fm_create(active_mo_coeff_im, active_mo_struct)
841 3902 : CALL cp_fm_to_fm(mo_coeff, active_mo_coeff, homo)
842 3902 : CALL cp_fm_to_fm(mo_coeff_im, active_mo_coeff_im, homo)
843 3902 : CALL cp_fm_create(hc_re, active_mo_struct)
844 3902 : CALL cp_fm_create(hc_im, active_mo_struct)
845 :
846 3902 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff, hc_re, homo)
847 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff_im, hc_re, homo, &
848 3902 : alpha=-1.0_dp, beta=1.0_dp)
849 3902 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff_im, hc_im, homo)
850 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff, hc_im, homo, &
851 3902 : alpha=1.0_dp, beta=1.0_dp)
852 :
853 3902 : IF (restricted_roks) THEN
854 : ! ROKS has one complex orbital variable but two spin densities. Form the exact
855 : ! shared-orbital derivative before handing it to the one-channel OT minimizer.
856 206 : IF (local_ot_env(local_channel)%settings%do_ener) THEN
857 : CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
858 32 : nrow_global=homo, ncol_global=homo)
859 32 : CALL cp_fm_create(chc_re, chc_struct)
860 32 : CALL cp_fm_create(chc_im, chc_struct)
861 : CALL multiply_complex_fm_adjoint( &
862 : active_mo_coeff, active_mo_coeff_im, hc_re, hc_im, &
863 32 : chc_re, chc_im, 1.0_dp, 0.0_dp)
864 32 : CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
865 : CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
866 32 : local_ot_env(local_channel)%ener_rayleigh(1:homo))
867 : CALL local_ot_env(local_channel)%para_env%sum( &
868 640 : local_ot_env(local_channel)%ener_rayleigh(1:homo))
869 32 : CALL cp_fm_release(chc_im)
870 32 : CALL cp_fm_release(chc_re)
871 32 : CALL cp_fm_struct_release(chc_struct)
872 : END IF
873 206 : CALL cp_fm_column_scale(hc_re, occupation_numbers(1:homo))
874 206 : CALL cp_fm_column_scale(hc_im, occupation_numbers(1:homo))
875 206 : CALL dbcsr_release_p(matrix_k_re)
876 206 : CALL dbcsr_release_p(matrix_k_im)
877 :
878 : CALL qs_scf_get_ot_kpoint_operator( &
879 : matrix_ks, kpoints, kp, 2, kp%ot_hmat(1, 2), kp%ot_hmat(2, 2), &
880 206 : matrix_k_re, matrix_k_im)
881 206 : CALL get_mo_set(kp%mos(1, 2), occupation_numbers=occupation_numbers, nmo=nmo)
882 618 : ALLOCATE (roks_occupation(homo))
883 206 : roks_occupation(:) = 0.0_dp
884 858 : roks_occupation(1:MIN(homo, nmo)) = occupation_numbers(1:MIN(homo, nmo))
885 :
886 206 : CALL cp_fm_create(hc_roks_re, active_mo_struct)
887 206 : CALL cp_fm_create(hc_roks_im, active_mo_struct)
888 206 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff, hc_roks_re, homo)
889 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff_im, hc_roks_re, homo, &
890 206 : alpha=-1.0_dp, beta=1.0_dp)
891 206 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff_im, hc_roks_im, homo)
892 : CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff, hc_roks_im, homo, &
893 206 : alpha=1.0_dp, beta=1.0_dp)
894 206 : IF (local_ot_env(local_channel)%settings%do_ener) THEN
895 : CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
896 32 : nrow_global=homo, ncol_global=homo)
897 32 : CALL cp_fm_create(chc_re, chc_struct)
898 32 : CALL cp_fm_create(chc_im, chc_struct)
899 : CALL multiply_complex_fm_adjoint( &
900 : active_mo_coeff, active_mo_coeff_im, hc_roks_re, hc_roks_im, &
901 32 : chc_re, chc_im, 1.0_dp, 0.0_dp)
902 32 : CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
903 : CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
904 32 : local_ot_env(local_channel)%ener_rayleigh(homo + 1:2*homo))
905 : CALL local_ot_env(local_channel)%para_env%sum( &
906 640 : local_ot_env(local_channel)%ener_rayleigh(homo + 1:2*homo))
907 32 : CALL cp_fm_release(chc_im)
908 32 : CALL cp_fm_release(chc_re)
909 32 : CALL cp_fm_struct_release(chc_struct)
910 : END IF
911 206 : CALL cp_fm_column_scale(hc_roks_re, roks_occupation)
912 206 : CALL cp_fm_column_scale(hc_roks_im, roks_occupation)
913 206 : CALL cp_fm_scale_and_add(1.0_dp, hc_re, 1.0_dp, hc_roks_re)
914 206 : CALL cp_fm_scale_and_add(1.0_dp, hc_im, 1.0_dp, hc_roks_im)
915 206 : CALL cp_fm_release(hc_roks_re)
916 206 : CALL cp_fm_release(hc_roks_im)
917 618 : DEALLOCATE (roks_occupation)
918 : END IF
919 :
920 3902 : IF (local_ot_env(local_channel)%settings%do_ener) THEN
921 : CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
922 1840 : nrow_global=homo, ncol_global=homo)
923 1840 : CALL cp_fm_create(chc_re, chc_struct)
924 1840 : CALL cp_fm_create(chc_im, chc_struct)
925 : CALL multiply_complex_fm_adjoint( &
926 : active_mo_coeff, active_mo_coeff_im, hc_re, hc_im, &
927 1840 : chc_re, chc_im, 1.0_dp, 0.0_dp)
928 1840 : CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
929 1840 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_chc_im))
930 1840 : CALL copy_fm_to_dbcsr(chc_im, local_ot_env(local_channel)%rot_mat_chc_im)
931 1840 : IF (.NOT. restricted_roks) THEN
932 : CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
933 1808 : local_ot_env(local_channel)%ener_rayleigh)
934 1808 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%para_env))
935 : CALL local_ot_env(local_channel)%para_env%sum( &
936 25952 : local_ot_env(local_channel)%ener_rayleigh)
937 : END IF
938 1840 : CALL cp_fm_release(chc_im)
939 1840 : CALL cp_fm_release(chc_re)
940 1840 : CALL cp_fm_struct_release(chc_struct)
941 : END IF
942 :
943 3902 : CALL copy_fm_to_dbcsr(hc_re, matrix_hc(local_channel)%matrix)
944 3902 : CALL copy_fm_to_dbcsr(hc_im, matrix_hc_im(local_channel)%matrix)
945 :
946 3902 : CALL cp_fm_release(active_mo_coeff)
947 3902 : CALL cp_fm_release(active_mo_coeff_im)
948 3902 : CALL cp_fm_release(hc_re)
949 3902 : CALL cp_fm_release(hc_im)
950 3902 : CALL cp_fm_struct_release(active_mo_struct)
951 3902 : CALL dbcsr_release_p(matrix_k_re)
952 19306 : CALL dbcsr_release_p(matrix_k_im)
953 : END DO
954 : END DO
955 :
956 2370 : IF (local_ot_env(1)%settings%do_ener) THEN
957 : CALL qs_scf_loop_collect_ot_kp_trial_smearing( &
958 : kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
959 : kp_range, wkp, para_env_inter_kp, scf_control%smear, &
960 1384 : trial_eigenvalues, trial_occupation, trial_mu, trial_kTS)
961 : END IF
962 :
963 6068 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
964 3698 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
965 3698 : ikpoint = kp%nkpoint
966 9970 : DO ispin = 1, nspin_ot
967 3902 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
968 : CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, nmo=nmo, &
969 3902 : occupation_numbers=occupation_numbers)
970 3902 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
971 3902 : IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
972 3902 : IF (physical_base_state .AND. .NOT. restricted_roks .AND. &
973 : local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
974 : CALL qs_scf_kp_roll_physical_secant( &
975 : local_ot_env(local_channel), mo_coeff, mo_coeff_im, &
976 : kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
977 : kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
978 868 : trial_occupation(:, ikpoint, ispin))
979 : END IF
980 3902 : IF (local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
981 : CALL dbcsr_copy(matrix_hc_physical(local_channel)%matrix, &
982 1688 : matrix_hc(local_channel)%matrix)
983 : CALL dbcsr_copy(matrix_hc_physical_im(local_channel)%matrix, &
984 1688 : matrix_hc_im(local_channel)%matrix)
985 5064 : ALLOCATE (orbital_scaling_factor(homo))
986 1688 : IF (restricted_roks) THEN
987 336 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
988 : ELSE
989 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)* &
990 10384 : trial_occupation(1:homo, ikpoint, ispin)
991 : END IF
992 : CALL dbcsr_scale_by_vector(matrix_hc_physical(local_channel)%matrix, &
993 1688 : alpha=orbital_scaling_factor, side='right')
994 : CALL dbcsr_scale_by_vector(matrix_hc_physical_im(local_channel)%matrix, &
995 1688 : alpha=orbital_scaling_factor, side='right')
996 1688 : DEALLOCATE (orbital_scaling_factor)
997 : END IF
998 11706 : ALLOCATE (orbital_scaling_factor(homo))
999 3902 : IF (local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
1000 10720 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
1001 2214 : ELSE IF (restricted_roks) THEN
1002 522 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
1003 2040 : ELSE IF (local_ot_env(local_channel)%settings%do_ener) THEN
1004 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)* &
1005 3496 : trial_occupation(1:homo, ikpoint, ispin)
1006 : ELSE
1007 17868 : orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)*occupation_numbers(1:homo)
1008 : END IF
1009 : CALL dbcsr_scale_by_vector(matrix_hc(local_channel)%matrix, &
1010 3902 : alpha=orbital_scaling_factor, side='right')
1011 : CALL dbcsr_scale_by_vector(matrix_hc_im(local_channel)%matrix, &
1012 3902 : alpha=orbital_scaling_factor, side='right')
1013 11502 : DEALLOCATE (orbital_scaling_factor)
1014 : END DO
1015 : END DO
1016 :
1017 2370 : IF (local_ot_env(1)%settings%do_ener) THEN
1018 1384 : local_ot_env(1)%etotal = energy%total - energy%kTS + trial_kTS
1019 : CALL qs_scf_loop_prepare_ot_kp_energy_gradient( &
1020 : kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
1021 : wkp, para_env_inter_kp, scf_control%smear, &
1022 1384 : trial_eigenvalues, trial_occupation, trial_mu)
1023 1384 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
1024 : CALL ot_mini_prepare_gradient( &
1025 : local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
1026 : matrix_hc_physical=matrix_hc_physical, &
1027 : matrix_hc_physical_im=matrix_hc_physical_im, &
1028 1232 : para_env_inter_kp=para_env_inter_kp)
1029 : ELSE
1030 : CALL ot_mini_prepare_gradient( &
1031 : local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
1032 152 : para_env_inter_kp=para_env_inter_kp)
1033 : END IF
1034 1384 : ot_gradient_prepared = .TRUE.
1035 : ! A coupled response direction is consumed only when the minimizer starts a new
1036 : ! search. Line-search trial points still need their physical gradient, but rebuilding
1037 : ! the dense finite-rotation Hessian there cannot affect the accepted direction.
1038 1384 : IF (physical_base_state) THEN
1039 : CALL qs_scf_loop_prepare_ot_kp_rotation_response( &
1040 : qs_env, kpoints, local_ot_env, first_channel, nspin_ot, restricted_roks, &
1041 : wkp, para_env_inter_kp, sab_nl, fmwork, rho_ao_kp, &
1042 758 : scf_control%smear, trial_eigenvalues, trial_occupation, trial_mu)
1043 : END IF
1044 : IF (physical_base_state .AND. &
1045 758 : local_ot_env(1)%settings%occupation_preconditioner .AND. &
1046 : (local_ot_env(1)%settings%ot_method == "CG" .OR. &
1047 : local_ot_env(1)%settings%ot_method == "LBFG")) THEN
1048 694 : DO local_channel = 1, nlocal_channels
1049 1166 : CALL qs_scf_kp_store_mermin_gradient(local_ot_env(local_channel))
1050 : END DO
1051 : END IF
1052 : END IF
1053 2370 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
1054 : CALL ot_mini(local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
1055 : matrix_hc_physical=matrix_hc_physical, &
1056 : matrix_hc_physical_im=matrix_hc_physical_im, &
1057 : para_env_inter_kp=para_env_inter_kp, &
1058 1232 : gradient_prepared=ot_gradient_prepared)
1059 : ELSE
1060 : CALL ot_mini(local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
1061 : para_env_inter_kp=para_env_inter_kp, &
1062 1138 : gradient_prepared=ot_gradient_prepared)
1063 : END IF
1064 2370 : scf_env%iter_delta = local_ot_env(1)%delta
1065 2370 : energy_only = local_ot_env(1)%energy_only
1066 :
1067 6068 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
1068 3698 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1069 3698 : ikpoint = kp%nkpoint
1070 3698 : CPASSERT(ASSOCIATED(kp%ot_smat))
1071 3698 : CPASSERT(SIZE(kp%ot_smat) >= 2)
1072 : CALL qs_scf_get_ot_kpoint_operator(matrix_s, kpoints, kp, 1, &
1073 : kp%ot_smat(1), kp%ot_smat(2), &
1074 3698 : matrix_s_re, matrix_s_im)
1075 7600 : DO ispin = 1, nspin_ot
1076 3902 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
1077 : CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, eigenvalues=eigenvalues, &
1078 3902 : nao=nao, nmo=nmo)
1079 3902 : CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
1080 3902 : IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
1081 1170 : SELECT CASE (local_ot_env(local_channel)%settings%ot_algorithm)
1082 : CASE ("TOD")
1083 : CALL qs_ot_get_orbitals_complex(matrix_hc(local_channel)%matrix, &
1084 : matrix_hc_im(local_channel)%matrix, &
1085 : matrix_s_re, matrix_s_im, &
1086 1170 : local_ot_env(local_channel))
1087 : CASE ("REF")
1088 : CALL qs_ot_get_orbitals_ref_complex(matrix_hc(local_channel)%matrix, &
1089 : matrix_hc_im(local_channel)%matrix, &
1090 : matrix_s_re, matrix_s_im, &
1091 2732 : local_ot_env(local_channel), local_ot_env(1))
1092 : CASE DEFAULT
1093 3902 : CPABORT("K-point OT orbital update requires ALGORITHM STRICT or IRAC")
1094 : END SELECT
1095 : CALL cp_fm_struct_create(active_mo_struct, template_fmstruct=mo_coeff%matrix_struct, &
1096 3902 : ncol_global=homo)
1097 3902 : CALL cp_fm_create(active_mo_coeff, active_mo_struct)
1098 3902 : CALL cp_fm_create(active_mo_coeff_im, active_mo_struct)
1099 3902 : CALL copy_dbcsr_to_fm(matrix_hc(local_channel)%matrix, active_mo_coeff)
1100 3902 : CALL copy_dbcsr_to_fm(matrix_hc_im(local_channel)%matrix, active_mo_coeff_im)
1101 3902 : CALL cp_fm_to_fm(active_mo_coeff, mo_coeff, homo)
1102 3902 : CALL cp_fm_to_fm(active_mo_coeff_im, mo_coeff_im, homo)
1103 3902 : IF (local_ot_env(local_channel)%settings%do_ener .AND. .NOT. restricted_roks) THEN
1104 13880 : eigenvalues(1:homo) = local_ot_env(local_channel)%ener_x(:)
1105 25952 : kp%mos(2, ispin)%eigenvalues(1:homo) = local_ot_env(local_channel)%ener_x(:)
1106 : END IF
1107 3902 : CALL cp_fm_release(active_mo_coeff)
1108 3902 : CALL cp_fm_release(active_mo_coeff_im)
1109 15404 : CALL cp_fm_struct_release(active_mo_struct)
1110 : END DO
1111 3698 : IF (restricted_roks) THEN
1112 206 : CPASSERT(SIZE(kp%mos, 2) == 2)
1113 618 : DO icomponent = 1, 2
1114 412 : CALL get_mo_set(kp%mos(icomponent, 1), mo_coeff=mo_coeff)
1115 412 : CALL get_mo_set(kp%mos(icomponent, 2), mo_coeff=mo_coeff_target)
1116 618 : CALL cp_fm_to_fm(mo_coeff, mo_coeff_target)
1117 : END DO
1118 206 : IF (local_ot_env(local_channel)%settings%do_ener) THEN
1119 96 : DO energy_spin = 1, nspin_energy
1120 64 : energy_start = (energy_spin - 1)*homo + 1
1121 : kp%mos(1, energy_spin)%eigenvalues(1:homo) = &
1122 1280 : local_ot_env(local_channel)%ener_x(energy_start:energy_start + homo - 1)
1123 : kp%mos(2, energy_spin)%eigenvalues(1:homo) = &
1124 1312 : local_ot_env(local_channel)%ener_x(energy_start:energy_start + homo - 1)
1125 : END DO
1126 : END IF
1127 : END IF
1128 3698 : CALL dbcsr_release_p(matrix_s_re)
1129 6068 : CALL dbcsr_release_p(matrix_s_im)
1130 : END DO
1131 :
1132 2370 : IF (local_ot_env(1)%settings%do_ener) THEN
1133 : CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
1134 : added_mos_auto=scf_control%added_mos_auto, &
1135 : added_mos_auto_grow=added_mos_auto_grow, &
1136 1384 : separate_spin_occupations=restricted_roks)
1137 : END IF
1138 :
1139 2370 : IF (ALLOCATED(trial_eigenvalues)) DEALLOCATE (trial_eigenvalues)
1140 2370 : IF (ALLOCATED(trial_occupation)) DEALLOCATE (trial_occupation)
1141 2370 : IF (ALLOCATED(trial_mu)) DEALLOCATE (trial_mu)
1142 :
1143 2370 : IF (.NOT. added_mos_auto_grow) THEN
1144 2364 : fmwork => scf_env%scf_work1
1145 2364 : IF (ASSOCIATED(scf_env%p_mix_new)) THEN
1146 0 : density_target => scf_env%p_mix_new
1147 : ELSE
1148 2364 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
1149 2364 : density_target => rho_ao_kp
1150 : END IF
1151 2364 : CALL kpoint_density_matrices(kpoints)
1152 : CALL kpoint_density_transform(kpoints, density_target, .FALSE., &
1153 : matrix_s(1, 1)%matrix, sab_nl, fmwork, &
1154 2364 : overlap_rs=matrix_s)
1155 : END IF
1156 2370 : scf_env%iter_method = scf_env%qs_ot_env(first_channel)%OT_METHOD_FULL
1157 2370 : scf_env%iter_param = scf_env%qs_ot_env(first_channel)%ds_min
1158 2370 : qs_env%broyden_adaptive_sigma = scf_env%qs_ot_env(first_channel)%broyden_adaptive_sigma
1159 :
1160 6272 : DO local_channel = 1, nlocal_channels
1161 3902 : CALL dbcsr_release(matrix_hc(local_channel)%matrix)
1162 3902 : CALL dbcsr_release(matrix_hc_im(local_channel)%matrix)
1163 3902 : DEALLOCATE (matrix_hc(local_channel)%matrix)
1164 3902 : DEALLOCATE (matrix_hc_im(local_channel)%matrix)
1165 6272 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
1166 1688 : CALL dbcsr_release(matrix_hc_physical(local_channel)%matrix)
1167 1688 : CALL dbcsr_release(matrix_hc_physical_im(local_channel)%matrix)
1168 1688 : DEALLOCATE (matrix_hc_physical(local_channel)%matrix)
1169 1688 : DEALLOCATE (matrix_hc_physical_im(local_channel)%matrix)
1170 : END IF
1171 : END DO
1172 2370 : DEALLOCATE (matrix_hc, matrix_hc_im)
1173 2370 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
1174 1232 : DEALLOCATE (matrix_hc_physical, matrix_hc_physical_im)
1175 : END IF
1176 :
1177 2370 : CALL timestop(handle)
1178 :
1179 4740 : END SUBROUTINE qs_scf_loop_do_ot_kp
1180 :
1181 : ! **************************************************************************************************
1182 : !> \brief roll one accepted physical K-point Mermin endpoint into a bounded response history
1183 : !> \param qs_ot_env local spin/K-point OT channel
1184 : !> \param c_re current real orbital coefficients
1185 : !> \param c_im current imaginary orbital coefficients
1186 : !> \param h_re current real self-consistent Hamiltonian
1187 : !> \param h_im current imaginary self-consistent Hamiltonian
1188 : !> \param occupation current fixed-N occupations
1189 : ! **************************************************************************************************
1190 868 : SUBROUTINE qs_scf_kp_roll_physical_secant(qs_ot_env, c_re, c_im, h_re, h_im, occupation)
1191 : TYPE(qs_ot_type) :: qs_ot_env
1192 : TYPE(cp_fm_type), INTENT(IN), TARGET :: c_re, c_im, h_re, h_im
1193 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: occupation
1194 :
1195 : INTEGER :: nmo
1196 : LOGICAL :: previous_valid
1197 :
1198 868 : nmo = SIZE(occupation)
1199 868 : CPASSERT(nmo > 0)
1200 : previous_valid = qs_ot_env%mermin_physical_ref_valid .AND. &
1201 : ASSOCIATED(qs_ot_env%fm_mermin_c0) .AND. &
1202 : ASSOCIATED(qs_ot_env%fm_mermin_c0_im) .AND. &
1203 : ASSOCIATED(qs_ot_env%fm_mermin_h0) .AND. &
1204 : ASSOCIATED(qs_ot_env%fm_mermin_h0_im) .AND. &
1205 868 : ALLOCATED(qs_ot_env%mermin_occupation0)
1206 768 : IF (previous_valid) previous_valid = SIZE(qs_ot_env%mermin_occupation0) == nmo
1207 100 : qs_ot_env%mermin_physical_secant_valid = .FALSE.
1208 768 : IF (previous_valid) THEN
1209 : CALL store_physical_fm_matrix( &
1210 768 : qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c_previous, "mermin_previous_c")
1211 : CALL store_physical_fm_matrix( &
1212 768 : qs_ot_env%fm_mermin_c0_im, qs_ot_env%fm_mermin_c_previous_im, "mermin_previous_c_im")
1213 768 : CALL store_physical_fm_matrix(h_re, qs_ot_env%fm_mermin_y_previous, "mermin_previous_y")
1214 768 : CALL store_physical_fm_matrix(h_im, qs_ot_env%fm_mermin_y_previous_im, "mermin_previous_y_im")
1215 : CALL cp_fm_scale_and_add( &
1216 768 : 1.0_dp, qs_ot_env%fm_mermin_y_previous, -1.0_dp, qs_ot_env%fm_mermin_h0)
1217 : CALL cp_fm_scale_and_add( &
1218 768 : 1.0_dp, qs_ot_env%fm_mermin_y_previous_im, -1.0_dp, qs_ot_env%fm_mermin_h0_im)
1219 768 : IF (ALLOCATED(qs_ot_env%mermin_occupation_previous)) THEN
1220 680 : IF (SIZE(qs_ot_env%mermin_occupation_previous) /= nmo) THEN
1221 0 : DEALLOCATE (qs_ot_env%mermin_occupation_previous)
1222 : END IF
1223 : END IF
1224 768 : IF (.NOT. ALLOCATED(qs_ot_env%mermin_occupation_previous)) THEN
1225 264 : ALLOCATE (qs_ot_env%mermin_occupation_previous(nmo))
1226 : END IF
1227 5400 : qs_ot_env%mermin_occupation_previous(:) = qs_ot_env%mermin_occupation0(:)
1228 768 : qs_ot_env%mermin_physical_secant_valid = .TRUE.
1229 : END IF
1230 :
1231 868 : CALL store_physical_fm_matrix(c_re, qs_ot_env%fm_mermin_c0, "mermin_c0")
1232 868 : CALL store_physical_fm_matrix(c_im, qs_ot_env%fm_mermin_c0_im, "mermin_c0_im")
1233 868 : CALL store_physical_fm_matrix(h_re, qs_ot_env%fm_mermin_h0, "mermin_h0")
1234 868 : CALL store_physical_fm_matrix(h_im, qs_ot_env%fm_mermin_h0_im, "mermin_h0_im")
1235 868 : IF (ALLOCATED(qs_ot_env%mermin_occupation0)) THEN
1236 768 : IF (SIZE(qs_ot_env%mermin_occupation0) /= nmo) DEALLOCATE (qs_ot_env%mermin_occupation0)
1237 : END IF
1238 1068 : IF (.NOT. ALLOCATED(qs_ot_env%mermin_occupation0)) ALLOCATE (qs_ot_env%mermin_occupation0(nmo))
1239 6084 : qs_ot_env%mermin_occupation0(:) = occupation(:)
1240 868 : qs_ot_env%mermin_physical_ref_valid = .TRUE.
1241 :
1242 868 : END SUBROUTINE qs_scf_kp_roll_physical_secant
1243 :
1244 : ! **************************************************************************************************
1245 : !> \brief store the raw physical Mermin gradient at one accepted K-point endpoint
1246 : !> \param qs_ot_env local spin/K-point OT channel
1247 : ! **************************************************************************************************
1248 408 : SUBROUTINE qs_scf_kp_store_mermin_gradient(qs_ot_env)
1249 : TYPE(qs_ot_type) :: qs_ot_env
1250 :
1251 408 : CPASSERT(ASSOCIATED(qs_ot_env%matrix_mermin_g0))
1252 408 : CPASSERT(ASSOCIATED(qs_ot_env%matrix_mermin_g0_im))
1253 408 : CPASSERT(ASSOCIATED(qs_ot_env%rot_mat_mermin_g0))
1254 408 : CPASSERT(ASSOCIATED(qs_ot_env%rot_mat_mermin_g0_im))
1255 408 : CPASSERT(ALLOCATED(qs_ot_env%ener_mermin_g0))
1256 408 : CPASSERT(SIZE(qs_ot_env%ener_mermin_g0) == SIZE(qs_ot_env%ener_gx))
1257 :
1258 408 : CALL dbcsr_copy(qs_ot_env%matrix_mermin_g0, qs_ot_env%matrix_gx)
1259 408 : CALL dbcsr_copy(qs_ot_env%matrix_mermin_g0_im, qs_ot_env%matrix_gx_im)
1260 408 : CALL dbcsr_copy(qs_ot_env%rot_mat_mermin_g0, qs_ot_env%rot_mat_gx)
1261 408 : CALL dbcsr_copy(qs_ot_env%rot_mat_mermin_g0_im, qs_ot_env%rot_mat_gx_im)
1262 2568 : qs_ot_env%ener_mermin_g0(:) = qs_ot_env%ener_gx(:)
1263 408 : qs_ot_env%mermin_gradient_ref_valid = .TRUE.
1264 :
1265 408 : END SUBROUTINE qs_scf_kp_store_mermin_gradient
1266 :
1267 : ! **************************************************************************************************
1268 : !> \brief copy an owned physical full-matrix snapshot, reallocating on shape changes
1269 : !> \param source transient or persistent source matrix
1270 : !> \param snapshot owned response-history matrix
1271 : !> \param name matrix name
1272 : ! **************************************************************************************************
1273 6544 : SUBROUTINE store_physical_fm_matrix(source, snapshot, name)
1274 : TYPE(cp_fm_type), INTENT(IN), TARGET :: source
1275 : TYPE(cp_fm_type), INTENT(INOUT), POINTER :: snapshot
1276 : CHARACTER(LEN=*), INTENT(IN) :: name
1277 :
1278 : INTEGER :: ncol_snapshot, ncol_source, &
1279 : nrow_snapshot, nrow_source
1280 : LOGICAL :: shape_changed
1281 :
1282 6544 : CALL cp_fm_get_info(source, nrow_global=nrow_source, ncol_global=ncol_source)
1283 6544 : shape_changed = .FALSE.
1284 6544 : IF (ASSOCIATED(snapshot)) THEN
1285 5792 : CALL cp_fm_get_info(snapshot, nrow_global=nrow_snapshot, ncol_global=ncol_snapshot)
1286 5792 : shape_changed = nrow_snapshot /= nrow_source .OR. ncol_snapshot /= ncol_source
1287 : IF (shape_changed) THEN
1288 0 : CALL cp_fm_release(snapshot)
1289 0 : DEALLOCATE (snapshot)
1290 : END IF
1291 : END IF
1292 6544 : IF (.NOT. ASSOCIATED(snapshot)) THEN
1293 752 : ALLOCATE (snapshot)
1294 752 : CALL cp_fm_create(snapshot, source%matrix_struct, name=name)
1295 : END IF
1296 6544 : CALL cp_fm_to_fm(source, snapshot)
1297 :
1298 6544 : END SUBROUTINE store_physical_fm_matrix
1299 :
1300 : ! **************************************************************************************************
1301 : !> \brief project one accepted physical Hxc secant onto current-orbital density tangents
1302 : !> \param qs_ot_env channel owning the accepted endpoint snapshots
1303 : !> \param overlap_re real part of the AO overlap matrix
1304 : !> \param overlap_im imaginary part of the AO overlap matrix
1305 : !> \param density_modes current-orbital density tangents including the K-point weight
1306 : !> \param kpoint_weight irreducible K-point weight
1307 : !> \param density_norm_sq physical density-step norm
1308 : !> \param response_work density/Hamiltonian response work
1309 : !> \param density_overlap projections of the density step onto density_modes
1310 : !> \param response_overlap projections of the Hamiltonian step onto density_modes
1311 : !> \param valid whether a finite accepted secant was available
1312 : ! **************************************************************************************************
1313 182 : SUBROUTINE qs_scf_kp_physical_secant_overlaps( &
1314 182 : qs_ot_env, overlap_re, overlap_im, density_modes, kpoint_weight, density_norm_sq, &
1315 182 : response_work, density_overlap, response_overlap, valid)
1316 :
1317 : TYPE(qs_ot_type), INTENT(IN) :: qs_ot_env
1318 : TYPE(cp_fm_type), INTENT(IN) :: overlap_re, overlap_im
1319 : COMPLEX(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: density_modes
1320 : REAL(KIND=dp), INTENT(IN) :: kpoint_weight
1321 : REAL(KIND=dp), INTENT(OUT) :: density_norm_sq, response_work
1322 : REAL(KIND=dp), DIMENSION(:), INTENT(OUT) :: density_overlap, response_overlap
1323 : LOGICAL, INTENT(OUT) :: valid
1324 :
1325 182 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: hamiltonian_step_current, &
1326 182 : hamiltonian_step_previous, &
1327 182 : overlap_previous_current
1328 : INTEGER :: nmo
1329 182 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: dense_im, dense_re
1330 : TYPE(cp_fm_type) :: action_im, action_re, cross_im, cross_re, &
1331 : projection_im, projection_re
1332 :
1333 182 : nmo = SIZE(density_modes, 1)
1334 0 : CPASSERT(nmo > 0)
1335 182 : CPASSERT(SIZE(density_modes, 2) == nmo)
1336 182 : CPASSERT(SIZE(density_overlap) == SIZE(density_modes, 3))
1337 182 : CPASSERT(SIZE(response_overlap) == SIZE(density_modes, 3))
1338 : valid = qs_ot_env%mermin_physical_secant_valid .AND. &
1339 : ASSOCIATED(qs_ot_env%fm_mermin_c0) .AND. &
1340 : ASSOCIATED(qs_ot_env%fm_mermin_c0_im) .AND. &
1341 : ASSOCIATED(qs_ot_env%fm_mermin_c_previous) .AND. &
1342 : ASSOCIATED(qs_ot_env%fm_mermin_c_previous_im) .AND. &
1343 : ASSOCIATED(qs_ot_env%fm_mermin_y_previous) .AND. &
1344 : ASSOCIATED(qs_ot_env%fm_mermin_y_previous_im) .AND. &
1345 : ALLOCATED(qs_ot_env%mermin_occupation0) .AND. &
1346 182 : ALLOCATED(qs_ot_env%mermin_occupation_previous)
1347 182 : density_norm_sq = 0.0_dp
1348 182 : response_work = 0.0_dp
1349 546 : density_overlap(:) = 0.0_dp
1350 546 : response_overlap(:) = 0.0_dp
1351 182 : IF (.NOT. valid) RETURN
1352 182 : CPASSERT(SIZE(qs_ot_env%mermin_occupation0) == nmo)
1353 182 : CPASSERT(SIZE(qs_ot_env%mermin_occupation_previous) == nmo)
1354 :
1355 : CALL cp_fm_create(action_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
1356 182 : name="mermin_hxc_action_re", set_zero=.TRUE.)
1357 : CALL cp_fm_create(action_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
1358 182 : name="mermin_hxc_action_im", set_zero=.TRUE.)
1359 : CALL cp_fm_create(cross_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
1360 182 : name="mermin_hxc_cross_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1361 : CALL cp_fm_create(cross_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
1362 182 : name="mermin_hxc_cross_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1363 : CALL cp_fm_create(projection_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
1364 182 : name="mermin_hxc_projection_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1365 : CALL cp_fm_create(projection_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
1366 182 : name="mermin_hxc_projection_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1367 : ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo), &
1368 : hamiltonian_step_current(nmo, nmo), hamiltonian_step_previous(nmo, nmo), &
1369 2366 : overlap_previous_current(nmo, nmo))
1370 :
1371 : CALL multiply_complex_fm_nn( &
1372 : overlap_re, overlap_im, qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c0_im, &
1373 182 : action_re, action_im, 1.0_dp, 0.0_dp)
1374 : CALL multiply_complex_fm_adjoint( &
1375 : qs_ot_env%fm_mermin_c_previous, qs_ot_env%fm_mermin_c_previous_im, &
1376 182 : action_re, action_im, cross_re, cross_im, 1.0_dp, 0.0_dp)
1377 182 : CALL cp_fm_get_submatrix(cross_re, dense_re)
1378 182 : CALL cp_fm_get_submatrix(cross_im, dense_im)
1379 6530 : overlap_previous_current(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
1380 :
1381 : CALL project_physical_response( &
1382 : qs_ot_env, qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c0_im, &
1383 182 : action_re, action_im, projection_re, projection_im, hamiltonian_step_current)
1384 : CALL project_physical_response( &
1385 : qs_ot_env, qs_ot_env%fm_mermin_c_previous, qs_ot_env%fm_mermin_c_previous_im, &
1386 182 : action_re, action_im, projection_re, projection_im, hamiltonian_step_previous)
1387 : CALL qs_ot_density_secant_orbital_overlaps( &
1388 : overlap_previous_current, qs_ot_env%mermin_occupation_previous, &
1389 : qs_ot_env%mermin_occupation0, hamiltonian_step_previous, hamiltonian_step_current, &
1390 : density_modes, kpoint_weight, density_norm_sq, response_work, density_overlap, &
1391 182 : response_overlap, valid)
1392 :
1393 0 : DEALLOCATE (dense_re, dense_im, hamiltonian_step_current, &
1394 182 : hamiltonian_step_previous, overlap_previous_current)
1395 182 : CALL cp_fm_release(action_re)
1396 182 : CALL cp_fm_release(action_im)
1397 182 : CALL cp_fm_release(cross_re)
1398 182 : CALL cp_fm_release(cross_im)
1399 182 : CALL cp_fm_release(projection_re)
1400 364 : CALL cp_fm_release(projection_im)
1401 :
1402 : CONTAINS
1403 :
1404 : ! **************************************************************************************************
1405 : !> \brief ...
1406 : !> \param env ...
1407 : !> \param c_re ...
1408 : !> \param c_im ...
1409 : !> \param action_re ...
1410 : !> \param action_im ...
1411 : !> \param projected_re ...
1412 : !> \param projected_im ...
1413 : !> \param projected ...
1414 : ! **************************************************************************************************
1415 364 : SUBROUTINE project_physical_response( &
1416 364 : env, c_re, c_im, action_re, action_im, projected_re, projected_im, projected)
1417 : TYPE(qs_ot_type), INTENT(IN) :: env
1418 : TYPE(cp_fm_type), INTENT(IN) :: c_re, c_im, action_re, action_im, &
1419 : projected_re, projected_im
1420 : COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: projected
1421 :
1422 : CALL multiply_complex_fm_nn( &
1423 : env%fm_mermin_y_previous, env%fm_mermin_y_previous_im, c_re, c_im, &
1424 364 : action_re, action_im, 1.0_dp, 0.0_dp)
1425 : CALL multiply_complex_fm_adjoint( &
1426 364 : c_re, c_im, action_re, action_im, projected_re, projected_im, 1.0_dp, 0.0_dp)
1427 364 : CALL cp_fm_get_submatrix(projected_re, dense_re)
1428 364 : CALL cp_fm_get_submatrix(projected_im, dense_im)
1429 13060 : projected(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
1430 26120 : projected(:, :) = 0.5_dp*(projected + CONJG(TRANSPOSE(projected)))
1431 364 : END SUBROUTINE project_physical_response
1432 :
1433 : END SUBROUTINE qs_scf_kp_physical_secant_overlaps
1434 :
1435 : ! **************************************************************************************************
1436 : !> \brief accumulate C=beta*C+alpha*A*B for split-complex distributed full matrices
1437 : !> \param a_re ...
1438 : !> \param a_im ...
1439 : !> \param b_re ...
1440 : !> \param b_im ...
1441 : !> \param c_re ...
1442 : !> \param c_im ...
1443 : !> \param alpha ...
1444 : !> \param beta ...
1445 : ! **************************************************************************************************
1446 2292 : SUBROUTINE multiply_complex_fm_nn(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
1447 : TYPE(cp_fm_type), INTENT(IN) :: a_re, a_im, b_re, b_im, c_re, c_im
1448 : REAL(KIND=dp), INTENT(IN) :: alpha, beta
1449 :
1450 : INTEGER :: k, k_b, m, m_c, n, n_c
1451 :
1452 764 : CALL cp_fm_get_info(a_re, nrow_global=m, ncol_global=k)
1453 764 : CALL cp_fm_get_info(b_re, nrow_global=k_b, ncol_global=n)
1454 764 : CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
1455 764 : CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
1456 764 : CALL cp_complex_fm_gemm('N', 'N', m, n, k, alpha, a_re, a_im, b_re, b_im, beta, c_re, c_im)
1457 :
1458 764 : END SUBROUTINE multiply_complex_fm_nn
1459 :
1460 : ! **************************************************************************************************
1461 : !> \brief accumulate C=beta*C+alpha*A^H*B for split-complex distributed full matrices
1462 : !> \param a_re ...
1463 : !> \param a_im ...
1464 : !> \param b_re ...
1465 : !> \param b_im ...
1466 : !> \param c_re ...
1467 : !> \param c_im ...
1468 : !> \param alpha ...
1469 : !> \param beta ...
1470 : ! **************************************************************************************************
1471 8004 : SUBROUTINE multiply_complex_fm_adjoint(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
1472 : TYPE(cp_fm_type), INTENT(IN) :: a_re, a_im, b_re, b_im, c_re, c_im
1473 : REAL(KIND=dp), INTENT(IN) :: alpha, beta
1474 :
1475 : INTEGER :: k, k_b, m, m_c, n, n_c
1476 :
1477 2668 : CALL cp_fm_get_info(a_re, nrow_global=k, ncol_global=m)
1478 2668 : CALL cp_fm_get_info(b_re, nrow_global=k_b, ncol_global=n)
1479 2668 : CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
1480 2668 : CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
1481 2668 : CALL cp_complex_fm_gemm('C', 'N', m, n, k, alpha, a_re, a_im, b_re, b_im, beta, c_re, c_im)
1482 :
1483 2668 : END SUBROUTINE multiply_complex_fm_adjoint
1484 :
1485 : ! **************************************************************************************************
1486 : !> \brief accumulate C=beta*C+alpha*A*B^H for split-complex distributed full matrices
1487 : !> \param a_re real part of A
1488 : !> \param a_im imaginary part of A
1489 : !> \param b_re real part of B
1490 : !> \param b_im imaginary part of B
1491 : !> \param c_re real part of C
1492 : !> \param c_im imaginary part of C
1493 : !> \param alpha product scaling factor
1494 : !> \param beta initial C scaling factor
1495 : ! **************************************************************************************************
1496 654 : SUBROUTINE multiply_complex_fm_right_adjoint(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
1497 : TYPE(cp_fm_type), INTENT(IN) :: a_re, a_im, b_re, b_im, c_re, c_im
1498 : REAL(KIND=dp), INTENT(IN) :: alpha, beta
1499 :
1500 : INTEGER :: k, k_b, m, m_c, n, n_c
1501 :
1502 218 : CALL cp_fm_get_info(a_re, nrow_global=m, ncol_global=k)
1503 218 : CALL cp_fm_get_info(b_re, nrow_global=n, ncol_global=k_b)
1504 218 : CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
1505 218 : CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
1506 218 : CALL cp_complex_fm_gemm('N', 'C', m, n, k, alpha, a_re, a_im, b_re, b_im, beta, c_re, c_im)
1507 :
1508 218 : END SUBROUTINE multiply_complex_fm_right_adjoint
1509 :
1510 : ! **************************************************************************************************
1511 : !> \brief evaluate the exact GPW Hartree-XC curvature of a complex K-point density mode
1512 : !> \param qs_env ground-state QS environment defining the current density and XC kernel
1513 : !> \param kpoints K-point environment and group distribution
1514 : !> \param local_ot_env local spin/K-point OT channels
1515 : !> \param first_channel global index of the first local channel
1516 : !> \param nspin_ot number of physical spin channels
1517 : !> \param wkp irreducible K-point weights
1518 : !> \param para_env_inter_kp communicator between distributed K-point groups
1519 : !> \param sab_nl real-space neighbor lists used by the K-point density transform
1520 : !> \param fmwork full-matrix workspaces on the global communicator
1521 : !> \param rho_ao_kp template AO density matrices for the real-space images
1522 : !> \param channel_density_modes weighted current-orbital density modes per local channel
1523 : !> \param number_of_modes number of populated modes to apply
1524 : !> \param projected_hxc projected Hartree-XC Hessian in the supplied density-mode basis
1525 : !> \param valid whether the projected block is finite and Hermitian within tolerance
1526 : ! **************************************************************************************************
1527 88 : SUBROUTINE qs_scf_kp_exact_hxc_projected( &
1528 : qs_env, kpoints, local_ot_env, first_channel, nspin_ot, wkp, para_env_inter_kp, &
1529 176 : sab_nl, fmwork, rho_ao_kp, channel_density_modes, number_of_modes, &
1530 88 : projected_hxc, valid)
1531 :
1532 : TYPE(qs_environment_type), POINTER :: qs_env
1533 : TYPE(kpoint_type), POINTER :: kpoints
1534 : TYPE(qs_ot_type), DIMENSION(:), POINTER :: local_ot_env
1535 : INTEGER, INTENT(IN) :: first_channel, nspin_ot
1536 : REAL(KIND=dp), DIMENSION(:), POINTER :: wkp
1537 : TYPE(mp_para_env_type), POINTER :: para_env_inter_kp
1538 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1539 : POINTER :: sab_nl
1540 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
1541 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
1542 : COMPLEX(KIND=dp), DIMENSION(:, :, :, :), &
1543 : INTENT(IN) :: channel_density_modes
1544 : INTEGER, INTENT(IN) :: number_of_modes
1545 : REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: projected_hxc
1546 : LOGICAL, INTENT(OUT) :: valid
1547 :
1548 88 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: projected
1549 : INTEGER :: ikpoint, ispin, local_channel, local_kpoint, nao, nimages, nkp_groups, &
1550 : nlocal_kpoints, nmo, nmode, response_mode, test_mode
1551 : LOGICAL :: do_hfx
1552 : REAL(KIND=dp) :: symmetry_error, symmetry_scale
1553 88 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: dense_im, dense_re
1554 : TYPE(cp_fm_type) :: action_im, action_re, density_im, &
1555 : density_re, projected_im, projected_re
1556 88 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: operator_im, operator_re
1557 88 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: density_kp
1558 88 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: density_rs, potential_rs
1559 : TYPE(dbcsr_type), POINTER :: matrix_k_im, matrix_k_re, template
1560 : TYPE(dft_control_type), POINTER :: dft_control
1561 : TYPE(kpoint_env_type), POINTER :: kp
1562 88 : TYPE(kpoint_operator_context_type) :: hxc_op_ctx
1563 : TYPE(qs_kpp1_env_type) :: kernel_env
1564 : TYPE(section_vals_type), POINTER :: hfx_section, input
1565 :
1566 616 : projected_hxc(:, :) = 0.0_dp
1567 88 : symmetry_error = 0.0_dp
1568 88 : valid = .FALSE.
1569 88 : NULLIFY (density_rs, dft_control, hfx_section, input, matrix_k_im, matrix_k_re, &
1570 88 : potential_rs, template)
1571 88 : CALL get_qs_env(qs_env, dft_control=dft_control, input=input)
1572 : IF (dft_control%qs_control%semi_empirical .OR. dft_control%qs_control%dftb .OR. &
1573 : dft_control%qs_control%xtb .OR. dft_control%qs_control%gapw .OR. &
1574 : dft_control%qs_control%gapw_xc .OR. dft_control%qs_control%lrigpw .OR. &
1575 88 : dft_control%qs_control%rigpw .OR. dft_control%do_admm) RETURN
1576 88 : hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
1577 88 : CALL section_vals_get(hfx_section, explicit=do_hfx)
1578 88 : IF (do_hfx) RETURN
1579 88 : CALL get_kpoint_info(kpoints, nkp_groups=nkp_groups)
1580 :
1581 88 : nlocal_kpoints = SIZE(kpoints%kp_env)
1582 88 : nmo = SIZE(channel_density_modes, 1)
1583 88 : nmode = number_of_modes
1584 88 : nimages = SIZE(rho_ao_kp, 2)
1585 88 : CPASSERT(nmo > 0)
1586 88 : CPASSERT(nmode > 0 .AND. nmode <= SIZE(channel_density_modes, 3))
1587 88 : CPASSERT(SIZE(channel_density_modes, 2) == nmo)
1588 88 : CPASSERT(SIZE(channel_density_modes, 4) == SIZE(local_ot_env))
1589 88 : CPASSERT(SIZE(projected_hxc, 1) >= nmode .AND. SIZE(projected_hxc, 2) >= nmode)
1590 88 : CPASSERT(SIZE(rho_ao_kp, 1) == nspin_ot)
1591 88 : CPASSERT(ASSOCIATED(fmwork))
1592 :
1593 88 : template => rho_ao_kp(1, 1)%matrix
1594 88 : CALL cp_fm_get_info(local_ot_env(1)%fm_mermin_c0, nrow_global=nao)
1595 964 : ALLOCATE (operator_re(nlocal_kpoints, nspin_ot), operator_im(nlocal_kpoints, nspin_ot))
1596 218 : DO local_kpoint = 1, nlocal_kpoints
1597 348 : DO ispin = 1, nspin_ot
1598 : local_channel = qs_ot_channel_index( &
1599 : ispin, kpoints%kp_env(local_kpoint)%kpoint_env%nkpoint, nspin_ot) - &
1600 130 : first_channel + 1
1601 : CALL cp_fm_create(operator_re(local_kpoint, ispin), &
1602 : local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1603 130 : name="hxc_operator_k_re", nrow=nao, ncol=nao, set_zero=.TRUE.)
1604 : CALL cp_fm_create(operator_im(local_kpoint, ispin), &
1605 : local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1606 260 : name="hxc_operator_k_im", nrow=nao, ncol=nao, set_zero=.TRUE.)
1607 : END DO
1608 : END DO
1609 792 : ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo), projected(nmo, nmo))
1610 : ! The group communicators do not own the complete real-space operator;
1611 : ! redistribute it to every group through the service. The fm pair lives
1612 : ! on the OT channel distribution; the service transfers into it
1613 : ! directly, whatever that distribution is. The context spans every
1614 : ! response mode: nothing inside the loop changes the host k-point
1615 : ! environment, and every mode rebuilds potential_rs from the same
1616 : ! rho_ao_kp template, so the work trio distribution stays valid.
1617 88 : IF (nkp_groups > 1) THEN
1618 34 : CALL kpoint_operator_context_create(hxc_op_ctx, kpoints, fmwork(1), nspin_ot)
1619 : END IF
1620 236 : DO response_mode = 1, nmode
1621 1472 : ALLOCATE (density_kp(nlocal_kpoints, 2, nspin_ot))
1622 366 : DO local_kpoint = 1, nlocal_kpoints
1623 218 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1624 218 : ikpoint = kp%nkpoint
1625 584 : DO ispin = 1, nspin_ot
1626 218 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
1627 218 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%fm_mermin_c0))
1628 218 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%fm_mermin_c0_im))
1629 : CALL cp_fm_create(density_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1630 218 : name="hxc_density_mode_re", nrow=nmo, ncol=nmo)
1631 : CALL cp_fm_create(density_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1632 218 : name="hxc_density_mode_im", nrow=nmo, ncol=nmo)
1633 : CALL cp_fm_set_submatrix( &
1634 : density_re, REAL(channel_density_modes(:, :, response_mode, local_channel), &
1635 8094 : KIND=dp)/wkp(ikpoint))
1636 : CALL cp_fm_set_submatrix( &
1637 : density_im, AIMAG(channel_density_modes(:, :, response_mode, local_channel))/ &
1638 8094 : wkp(ikpoint))
1639 : CALL cp_fm_create(action_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1640 218 : name="hxc_density_action_re", set_zero=.TRUE.)
1641 : CALL cp_fm_create(action_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1642 218 : name="hxc_density_action_im", set_zero=.TRUE.)
1643 : CALL multiply_complex_fm_nn( &
1644 : local_ot_env(local_channel)%fm_mermin_c0, &
1645 : local_ot_env(local_channel)%fm_mermin_c0_im, density_re, density_im, &
1646 218 : action_re, action_im, 1.0_dp, 0.0_dp)
1647 218 : CALL cp_fm_get_info(local_ot_env(local_channel)%fm_mermin_c0, nrow_global=nao)
1648 : CALL cp_fm_create(density_kp(local_kpoint, 1, ispin), &
1649 : local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1650 218 : name="hxc_density_k_re", nrow=nao, ncol=nao, set_zero=.TRUE.)
1651 : CALL cp_fm_create(density_kp(local_kpoint, 2, ispin), &
1652 : local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1653 218 : name="hxc_density_k_im", nrow=nao, ncol=nao, set_zero=.TRUE.)
1654 : CALL multiply_complex_fm_right_adjoint( &
1655 : action_re, action_im, local_ot_env(local_channel)%fm_mermin_c0, &
1656 : local_ot_env(local_channel)%fm_mermin_c0_im, &
1657 : density_kp(local_kpoint, 1, ispin), density_kp(local_kpoint, 2, ispin), &
1658 218 : 1.0_dp, 0.0_dp)
1659 218 : CALL cp_fm_release(action_re)
1660 218 : CALL cp_fm_release(action_im)
1661 218 : CALL cp_fm_release(density_re)
1662 872 : CALL cp_fm_release(density_im)
1663 : END DO
1664 : END DO
1665 :
1666 148 : CALL dbcsr_allocate_matrix_set(density_rs, nspin_ot, nimages)
1667 296 : DO ispin = 1, nspin_ot
1668 29220 : DO local_kpoint = 1, nimages
1669 28924 : ALLOCATE (density_rs(ispin, local_kpoint)%matrix)
1670 : CALL dbcsr_copy(density_rs(ispin, local_kpoint)%matrix, &
1671 28924 : rho_ao_kp(ispin, local_kpoint)%matrix, name="Hxc density response")
1672 29072 : CALL dbcsr_set(density_rs(ispin, local_kpoint)%matrix, 0.0_dp)
1673 : END DO
1674 : END DO
1675 : CALL kpoint_density_transform(kpoints, density_rs, .FALSE., template, sab_nl, fmwork, &
1676 148 : pmat_ext=density_kp)
1677 366 : DO local_kpoint = 1, nlocal_kpoints
1678 584 : DO ispin = 1, nspin_ot
1679 218 : CALL cp_fm_release(density_kp(local_kpoint, 1, ispin))
1680 436 : CALL cp_fm_release(density_kp(local_kpoint, 2, ispin))
1681 : END DO
1682 : END DO
1683 148 : DEALLOCATE (density_kp)
1684 :
1685 148 : CALL apply_hxc_kernel_kp(qs_env, kernel_env, density_rs, potential_rs)
1686 148 : IF (nkp_groups > 1) THEN
1687 112 : DO local_kpoint = 1, nlocal_kpoints
1688 168 : DO ispin = 1, nspin_ot
1689 : CALL kpoint_operator_get(hxc_op_ctx, local_kpoint, ispin, potential_rs, &
1690 : fm_re=operator_re(local_kpoint, ispin), &
1691 112 : fm_im=operator_im(local_kpoint, ispin), matrix_row=ispin)
1692 : END DO
1693 : END DO
1694 : END IF
1695 366 : DO local_kpoint = 1, nlocal_kpoints
1696 218 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1697 218 : ikpoint = kp%nkpoint
1698 584 : DO ispin = 1, nspin_ot
1699 218 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
1700 : CALL cp_fm_create(action_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1701 218 : name="hxc_potential_action_re", set_zero=.TRUE.)
1702 : CALL cp_fm_create(action_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1703 218 : name="hxc_potential_action_im", set_zero=.TRUE.)
1704 : CALL qs_scf_get_ot_kpoint_operator( &
1705 : potential_rs, kpoints, kp, ispin, operator_re(local_kpoint, ispin), &
1706 218 : operator_im(local_kpoint, ispin), matrix_k_re, matrix_k_im)
1707 : CALL cp_dbcsr_sm_fm_multiply( &
1708 218 : matrix_k_re, local_ot_env(local_channel)%fm_mermin_c0, action_re, nmo)
1709 : CALL cp_dbcsr_sm_fm_multiply( &
1710 : matrix_k_im, local_ot_env(local_channel)%fm_mermin_c0_im, action_re, nmo, &
1711 218 : alpha=-1.0_dp, beta=1.0_dp)
1712 : CALL cp_dbcsr_sm_fm_multiply( &
1713 218 : matrix_k_re, local_ot_env(local_channel)%fm_mermin_c0_im, action_im, nmo)
1714 : CALL cp_dbcsr_sm_fm_multiply( &
1715 : matrix_k_im, local_ot_env(local_channel)%fm_mermin_c0, action_im, nmo, &
1716 218 : alpha=1.0_dp, beta=1.0_dp)
1717 : CALL cp_fm_create(projected_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1718 218 : name="hxc_projected_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1719 : CALL cp_fm_create(projected_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
1720 218 : name="hxc_projected_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
1721 : CALL multiply_complex_fm_adjoint( &
1722 : local_ot_env(local_channel)%fm_mermin_c0, &
1723 : local_ot_env(local_channel)%fm_mermin_c0_im, action_re, action_im, &
1724 218 : projected_re, projected_im, 1.0_dp, 0.0_dp)
1725 218 : CALL cp_fm_get_submatrix(projected_re, dense_re)
1726 218 : CALL cp_fm_get_submatrix(projected_im, dense_im)
1727 8094 : projected(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
1728 612 : DO test_mode = 1, nmode
1729 : projected_hxc(test_mode, response_mode) = &
1730 : projected_hxc(test_mode, response_mode) + REAL(SUM( &
1731 14856 : CONJG(channel_density_modes(:, :, test_mode, local_channel))*projected), KIND=dp)
1732 : END DO
1733 218 : CALL cp_fm_release(projected_re)
1734 218 : CALL cp_fm_release(projected_im)
1735 218 : CALL cp_fm_release(action_re)
1736 218 : CALL cp_fm_release(action_im)
1737 218 : CALL dbcsr_release_p(matrix_k_re)
1738 436 : CALL dbcsr_release_p(matrix_k_im)
1739 : END DO
1740 : END DO
1741 148 : CALL dbcsr_deallocate_matrix_set(density_rs)
1742 148 : CALL dbcsr_deallocate_matrix_set(potential_rs)
1743 236 : NULLIFY (density_rs, potential_rs)
1744 : END DO
1745 88 : IF (nkp_groups > 1) THEN
1746 34 : CALL kpoint_operator_context_release(hxc_op_ctx)
1747 : END IF
1748 :
1749 1144 : CALL para_env_inter_kp%sum(projected_hxc)
1750 : symmetry_error = MAXVAL(ABS( &
1751 : projected_hxc(1:nmode, 1:nmode) - &
1752 504 : TRANSPOSE(projected_hxc(1:nmode, 1:nmode))))
1753 : symmetry_scale = MAX(SQRT(EPSILON(1.0_dp)), &
1754 504 : MAXVAL(ABS(projected_hxc(1:nmode, 1:nmode))))
1755 : projected_hxc(1:nmode, 1:nmode) = 0.5_dp*( &
1756 : projected_hxc(1:nmode, 1:nmode) + &
1757 920 : TRANSPOSE(projected_hxc(1:nmode, 1:nmode)))
1758 : valid = ALL(ieee_is_finite(projected_hxc(1:nmode, 1:nmode))) .AND. &
1759 : ieee_is_finite(symmetry_error) .AND. &
1760 504 : symmetry_error <= 1.0E-10_dp*symmetry_scale
1761 :
1762 88 : DEALLOCATE (dense_re, dense_im, projected)
1763 218 : DO local_kpoint = 1, nlocal_kpoints
1764 348 : DO ispin = 1, nspin_ot
1765 130 : CALL cp_fm_release(operator_re(local_kpoint, ispin))
1766 260 : CALL cp_fm_release(operator_im(local_kpoint, ispin))
1767 : END DO
1768 : END DO
1769 88 : DEALLOCATE (operator_re, operator_im)
1770 88 : CALL kpp1_release(kernel_env)
1771 :
1772 352 : END SUBROUTINE qs_scf_kp_exact_hxc_projected
1773 :
1774 : ! **************************************************************************************************
1775 : !> \brief collect the global fixed-N trial smearing state used by k-point OT
1776 : !> \param kpoints ...
1777 : !> \param local_ot_env ...
1778 : !> \param first_channel ...
1779 : !> \param nspin_ot ...
1780 : !> \param nspin_energy number of physical spin-resolved auxiliary-energy blocks
1781 : !> \param restricted_roks whether both energy blocks share one orbital channel
1782 : !> \param kp_range ...
1783 : !> \param wkp ...
1784 : !> \param para_env_inter_kp ...
1785 : !> \param smear ...
1786 : !> \param trial_eigenvalues ...
1787 : !> \param trial_occupation ...
1788 : !> \param trial_mu chemical potential for each spin channel
1789 : !> \param trial_kTS ...
1790 : ! **************************************************************************************************
1791 1384 : SUBROUTINE qs_scf_loop_collect_ot_kp_trial_smearing( &
1792 : kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
1793 : kp_range, wkp, para_env_inter_kp, smear, trial_eigenvalues, trial_occupation, trial_mu, trial_kTS)
1794 :
1795 : TYPE(kpoint_type), POINTER :: kpoints
1796 : TYPE(qs_ot_type), DIMENSION(:), POINTER :: local_ot_env
1797 : INTEGER, INTENT(IN) :: first_channel, nspin_ot, nspin_energy
1798 : LOGICAL, INTENT(IN) :: restricted_roks
1799 : INTEGER, DIMENSION(2), INTENT(IN) :: kp_range
1800 : REAL(KIND=dp), DIMENSION(:), POINTER :: wkp
1801 : TYPE(mp_para_env_type), POINTER :: para_env_inter_kp
1802 : TYPE(smear_type), INTENT(IN) :: smear
1803 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
1804 : INTENT(OUT) :: trial_eigenvalues, trial_occupation
1805 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
1806 : INTENT(OUT) :: trial_mu
1807 : REAL(KIND=dp), INTENT(OUT) :: trial_kTS
1808 :
1809 : INTEGER :: energy_start, ikpoint, ispin, &
1810 : local_channel, local_kpoint, ne_a, &
1811 : ne_b, nelectron, nkpoint, nmo
1812 : REAL(KIND=dp) :: kTS, mu, nel, sigma
1813 : REAL(KIND=dp), DIMENSION(2) :: mus
1814 : TYPE(kpoint_env_type), POINTER :: kp
1815 :
1816 1384 : CPASSERT(smear%do_smear)
1817 2618 : SELECT CASE (smear%method)
1818 : CASE (smear_fermi_dirac)
1819 1234 : sigma = smear%electronic_temperature
1820 : CASE (smear_gaussian, smear_mp, smear_mv)
1821 150 : sigma = smear%smearing_width
1822 : CASE DEFAULT
1823 1384 : CPABORT("K-point Mermin OT does not support the selected smearing method")
1824 : END SELECT
1825 1384 : CPASSERT(sigma > EPSILON(sigma))
1826 1384 : CPASSERT(ASSOCIATED(para_env_inter_kp))
1827 1384 : CALL get_kpoint_info(kpoints, nkp=nkpoint)
1828 1384 : kp => kpoints%kp_env(1)%kpoint_env
1829 1384 : CALL get_mo_set(kp%mos(1, 1), nelectron=nelectron, nmo=nmo)
1830 1384 : ne_a = nelectron
1831 1384 : ne_b = 0
1832 1384 : IF (nspin_energy == 2) CALL get_mo_set(kp%mos(1, 2), nelectron=ne_b)
1833 :
1834 6920 : ALLOCATE (trial_eigenvalues(nmo, nkpoint, nspin_energy))
1835 5536 : ALLOCATE (trial_occupation(nmo, nkpoint, nspin_energy))
1836 4152 : ALLOCATE (trial_mu(nspin_energy))
1837 1384 : trial_eigenvalues(:, :, :) = 0.0_dp
1838 1384 : trial_occupation(:, :, :) = 0.0_dp
1839 1384 : mus(:) = 0.0_dp
1840 :
1841 3084 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
1842 1700 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1843 1700 : ikpoint = kp%nkpoint
1844 1700 : CPASSERT(ikpoint >= kp_range(1) .AND. ikpoint <= kp_range(2))
1845 4956 : DO ispin = 1, nspin_energy
1846 : local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
1847 3680 : ikpoint, nspin_ot) - first_channel + 1
1848 1872 : energy_start = 1
1849 1872 : IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
1850 : trial_eigenvalues(1:nmo, ikpoint, ispin) = &
1851 16252 : local_ot_env(local_channel)%ener_x(energy_start:energy_start + nmo - 1)
1852 : END DO
1853 : END DO
1854 1384 : CALL para_env_inter_kp%sum(trial_eigenvalues)
1855 :
1856 1384 : IF (nspin_energy == 1) THEN
1857 1212 : nel = REAL(nelectron, KIND=dp)
1858 : CALL Smearkp(trial_occupation(:, :, 1), mus(1), trial_kTS, &
1859 1212 : trial_eigenvalues(:, :, 1), nel, wkp, sigma, 2.0_dp, smear%method)
1860 172 : ELSE IF (restricted_roks .OR. smear%fixed_mag_mom > 0.0_dp) THEN
1861 76 : nel = REAL(ne_a, KIND=dp)
1862 : CALL Smearkp(trial_occupation(:, :, 1), mus(1), kTS, &
1863 76 : trial_eigenvalues(:, :, 1), nel, wkp, sigma, 1.0_dp, smear%method)
1864 76 : trial_kTS = kTS
1865 76 : nel = REAL(ne_b, KIND=dp)
1866 : CALL Smearkp(trial_occupation(:, :, 2), mus(2), kTS, &
1867 76 : trial_eigenvalues(:, :, 2), nel, wkp, sigma, 1.0_dp, smear%method)
1868 76 : trial_kTS = trial_kTS + kTS
1869 : ELSE
1870 96 : nel = REAL(ne_a + ne_b, KIND=dp)
1871 : CALL Smearkp2(trial_occupation, mu, trial_kTS, trial_eigenvalues, nel, wkp, &
1872 96 : sigma, smear%method)
1873 288 : mus(1:2) = mu
1874 : END IF
1875 2940 : trial_mu(:) = mus(1:nspin_energy)
1876 1384 : END SUBROUTINE qs_scf_loop_collect_ot_kp_trial_smearing
1877 :
1878 : ! **************************************************************************************************
1879 : !> \brief construct auxiliary-energy gradients on the global fixed-N Mermin surface
1880 : !> \param kpoints ...
1881 : !> \param local_ot_env ...
1882 : !> \param first_channel ...
1883 : !> \param nspin_ot ...
1884 : !> \param nspin_energy ...
1885 : !> \param restricted_roks ...
1886 : !> \param wkp ...
1887 : !> \param para_env_inter_kp ...
1888 : !> \param smear ...
1889 : !> \param trial_eigenvalues ...
1890 : !> \param trial_occupation ...
1891 : !> \param trial_mu ...
1892 : ! **************************************************************************************************
1893 1384 : SUBROUTINE qs_scf_loop_prepare_ot_kp_energy_gradient( &
1894 : kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
1895 1384 : wkp, para_env_inter_kp, smear, trial_eigenvalues, trial_occupation, trial_mu)
1896 :
1897 : TYPE(kpoint_type), POINTER :: kpoints
1898 : TYPE(qs_ot_type), DIMENSION(:), POINTER :: local_ot_env
1899 : INTEGER, INTENT(IN) :: first_channel, nspin_ot, nspin_energy
1900 : LOGICAL, INTENT(IN) :: restricted_roks
1901 : REAL(KIND=dp), DIMENSION(:), POINTER :: wkp
1902 : TYPE(mp_para_env_type), POINTER :: para_env_inter_kp
1903 : TYPE(smear_type), INTENT(IN) :: smear
1904 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: trial_eigenvalues, trial_occupation
1905 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: trial_mu
1906 :
1907 : INTEGER :: energy_start, group, ikpoint, imo, &
1908 : ispin, local_channel, local_kpoint, &
1909 : ngroups, nmo
1910 : REAL(KIND=dp) :: fixed_n_mean, maxocc, sigma
1911 1384 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: fixed_n_residual, fixed_n_weight, &
1912 1384 : preconditioner_count, &
1913 1384 : preconditioner_shift, response_weight
1914 : TYPE(kpoint_env_type), POINTER :: kp
1915 :
1916 1384 : IF (.NOT. local_ot_env(1)%settings%do_ener) RETURN
1917 :
1918 1384 : CPASSERT(smear%do_smear)
1919 1384 : CPASSERT(ASSOCIATED(para_env_inter_kp))
1920 2618 : SELECT CASE (smear%method)
1921 : CASE (smear_fermi_dirac)
1922 1234 : sigma = smear%electronic_temperature
1923 : CASE (smear_gaussian, smear_mp, smear_mv)
1924 150 : sigma = smear%smearing_width
1925 : CASE DEFAULT
1926 1384 : CPABORT("K-point Mermin OT does not support the selected smearing method")
1927 : END SELECT
1928 1384 : CPASSERT(sigma > EPSILON(sigma))
1929 :
1930 1384 : ngroups = 1
1931 1384 : IF (restricted_roks .OR. &
1932 76 : (nspin_energy == 2 .AND. smear%fixed_mag_mom > 0.0_dp)) ngroups = 2
1933 1384 : nmo = SIZE(trial_eigenvalues, 1)
1934 : ALLOCATE (fixed_n_residual(ngroups), fixed_n_weight(ngroups), &
1935 : preconditioner_count(ngroups), preconditioner_shift(ngroups), &
1936 9688 : response_weight(nmo))
1937 1384 : fixed_n_residual(:) = 0.0_dp
1938 1384 : fixed_n_weight(:) = 0.0_dp
1939 1384 : preconditioner_count(:) = 0.0_dp
1940 1384 : preconditioner_shift(:) = 0.0_dp
1941 :
1942 3084 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
1943 1700 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1944 1700 : ikpoint = kp%nkpoint
1945 4956 : DO ispin = 1, nspin_energy
1946 1872 : group = MERGE(ispin, 1, ngroups == nspin_energy)
1947 : local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
1948 3680 : ikpoint, nspin_ot) - first_channel + 1
1949 1872 : energy_start = 1
1950 1872 : IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
1951 1872 : CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc, nmo=nmo)
1952 1872 : CPASSERT(maxocc > EPSILON(maxocc))
1953 1872 : CPASSERT(energy_start + nmo - 1 <= SIZE(local_ot_env(local_channel)%ener_x))
1954 : CALL smearing_response_weight( &
1955 : response_weight, trial_occupation(:, ikpoint, ispin), &
1956 : trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
1957 1872 : smear%method)
1958 14552 : response_weight(:) = wkp(ikpoint)*response_weight
1959 18124 : DO imo = 1, nmo
1960 : fixed_n_weight(group) = fixed_n_weight(group) + &
1961 12680 : response_weight(imo)
1962 : fixed_n_residual(group) = fixed_n_residual(group) + &
1963 : response_weight(imo)* &
1964 : (local_ot_env(local_channel)%ener_rayleigh(energy_start + imo - 1) - &
1965 14552 : trial_eigenvalues(imo, ikpoint, ispin))
1966 : END DO
1967 : END DO
1968 : END DO
1969 1384 : CALL para_env_inter_kp%sum(fixed_n_weight)
1970 1384 : CALL para_env_inter_kp%sum(fixed_n_residual)
1971 :
1972 1384 : IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
1973 2780 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
1974 1548 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
1975 1548 : ikpoint = kp%nkpoint
1976 4500 : DO ispin = 1, nspin_energy
1977 1720 : group = MERGE(ispin, 1, ngroups == nspin_energy)
1978 : local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
1979 3376 : ikpoint, nspin_ot) - first_channel + 1
1980 1720 : CALL get_mo_set(kp%mos(1, ispin), nmo=nmo)
1981 1720 : energy_start = 1
1982 1720 : IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
1983 1720 : fixed_n_mean = 0.0_dp
1984 1720 : IF (ABS(fixed_n_weight(group)) > EPSILON(fixed_n_weight(group))) THEN
1985 1676 : fixed_n_mean = fixed_n_residual(group)/fixed_n_weight(group)
1986 : END IF
1987 : local_ot_env(local_channel)%ener_preconditioned_gx( &
1988 : energy_start:energy_start + nmo - 1) = fixed_n_mean - &
1989 : (local_ot_env(local_channel)%ener_rayleigh( &
1990 : energy_start:energy_start + nmo - 1) - &
1991 11056 : trial_eigenvalues(:, ikpoint, ispin))
1992 : preconditioner_shift(group) = preconditioner_shift(group) + &
1993 : SUM(local_ot_env(local_channel)%ener_preconditioned_gx( &
1994 11056 : energy_start:energy_start + nmo - 1))
1995 4988 : preconditioner_count(group) = preconditioner_count(group) + REAL(nmo, KIND=dp)
1996 : END DO
1997 : END DO
1998 1232 : CALL para_env_inter_kp%sum(preconditioner_shift)
1999 1232 : CALL para_env_inter_kp%sum(preconditioner_count)
2000 : END IF
2001 :
2002 3084 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2003 1700 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2004 1700 : ikpoint = kp%nkpoint
2005 4956 : DO ispin = 1, nspin_energy
2006 1872 : group = MERGE(ispin, 1, ngroups == nspin_energy)
2007 : local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
2008 3680 : ikpoint, nspin_ot) - first_channel + 1
2009 1872 : CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc, nmo=nmo)
2010 1872 : energy_start = 1
2011 1872 : IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
2012 1872 : IF (local_ot_env(local_channel)%settings%occupation_preconditioner .AND. &
2013 : preconditioner_count(group) > 0.0_dp) THEN
2014 : local_ot_env(local_channel)%ener_preconditioned_gx( &
2015 : energy_start:energy_start + nmo - 1) = &
2016 : local_ot_env(local_channel)%ener_preconditioned_gx( &
2017 : energy_start:energy_start + nmo - 1) - &
2018 11056 : preconditioner_shift(group)/preconditioner_count(group)
2019 : END IF
2020 : CALL smearing_response_weight( &
2021 : response_weight, trial_occupation(:, ikpoint, ispin), &
2022 : trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
2023 1872 : smear%method)
2024 14552 : response_weight(:) = wkp(ikpoint)*response_weight
2025 : CALL qs_ot_fixed_n_energy_gradient( &
2026 : local_ot_env(local_channel)%ener_rayleigh(energy_start:energy_start + nmo - 1), &
2027 : trial_eigenvalues(:, ikpoint, ispin), &
2028 : response_weight, fixed_n_weight(group), fixed_n_residual(group), &
2029 5444 : local_ot_env(local_channel)%ener_gx(energy_start:energy_start + nmo - 1))
2030 : END DO
2031 : END DO
2032 :
2033 0 : DEALLOCATE (fixed_n_residual, fixed_n_weight, preconditioner_count, preconditioner_shift, &
2034 1384 : response_weight)
2035 :
2036 1384 : END SUBROUTINE qs_scf_loop_prepare_ot_kp_energy_gradient
2037 :
2038 : ! **************************************************************************************************
2039 : !> \brief build a coupled finite-complex rotation/energy preconditioner for K-point Mermin OT
2040 : !> \param qs_env ground-state QS environment defining the current density and XC kernel
2041 : !> \param kpoints K-point environment
2042 : !> \param local_ot_env local spin/K-point OT channels
2043 : !> \param first_channel global index of the first local channel
2044 : !> \param nspin_ot number of spin channels
2045 : !> \param restricted_roks whether two physical spin densities share each orbital channel
2046 : !> \param wkp irreducible K-point weights
2047 : !> \param para_env_inter_kp communicator between distributed K-point groups
2048 : !> \param sab_nl real-space neighbor lists used by the K-point density transform
2049 : !> \param fmwork full-matrix workspaces on the global communicator
2050 : !> \param rho_ao_kp template AO density matrices for the real-space images
2051 : !> \param smear smearing settings
2052 : !> \param trial_eigenvalues current auxiliary band energies
2053 : !> \param trial_occupation current fixed-N occupations
2054 : !> \param trial_mu chemical potential for each spin channel
2055 : ! **************************************************************************************************
2056 758 : SUBROUTINE qs_scf_loop_prepare_ot_kp_rotation_response( &
2057 : qs_env, kpoints, local_ot_env, first_channel, nspin_ot, restricted_roks, &
2058 : wkp, para_env_inter_kp, sab_nl, fmwork, rho_ao_kp, smear, &
2059 758 : trial_eigenvalues, trial_occupation, trial_mu)
2060 : TYPE(qs_environment_type), POINTER :: qs_env
2061 : TYPE(kpoint_type), POINTER :: kpoints
2062 : TYPE(qs_ot_type), DIMENSION(:), POINTER :: local_ot_env
2063 : INTEGER, INTENT(IN) :: first_channel, nspin_ot
2064 : LOGICAL, INTENT(IN) :: restricted_roks
2065 : REAL(KIND=dp), DIMENSION(:), POINTER :: wkp
2066 : TYPE(mp_para_env_type), POINTER :: para_env_inter_kp
2067 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2068 : POINTER :: sab_nl
2069 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: fmwork
2070 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
2071 : TYPE(smear_type), INTENT(IN) :: smear
2072 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: trial_eigenvalues, trial_occupation
2073 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: trial_mu
2074 :
2075 : INTEGER, PARAMETER :: finite_response_max_rotation = 800
2076 : REAL(KIND=dp), PARAMETER :: rotation_trust_rms = 0.25_dp, rotation_trust_spectral = 0.25_dp
2077 :
2078 758 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: chc, generator
2079 758 : COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: channel_generator, density_modes
2080 : COMPLEX(KIND=dp), ALLOCATABLE, &
2081 758 : DIMENSION(:, :, :, :) :: channel_density_modes
2082 : INTEGER :: failure, gradient_secant_failure, group, i, ikpoint, ispin, j, local_channel, &
2083 : local_kpoint, ngroups, nlocal_channels, nmo, nrotation, r
2084 : LOGICAL :: accepted_cross_valid, accepted_curvature_valid, exact_hxc_valid, &
2085 : hxc_channel_valid, hxc_valid, projected_update_valid, shadow_pending, solve_valid
2086 : REAL(KIND=dp) :: accepted_cross, accepted_curvature, denominator, hxc_density_norm_sq, &
2087 : hxc_density_norm_sq_channel, hxc_response_work, hxc_response_work_channel, maxocc, &
2088 : response_cross, response_scale, sigma, tmp, unscaled_rotation_norm
2089 758 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coupling, curvature_sum, energy_count, &
2090 758 : energy_mean, energy_metric_step, energy_shift, energy_weighted_sum, rayleigh_step, &
2091 758 : response_curvature, response_weight, rotation_count, rotation_norm, rotation_scale, &
2092 758 : schur_rhs, shadow_curvature, shadow_energy_mean, shadow_energy_metric_step, &
2093 758 : shadow_energy_weighted_sum, shadow_rayleigh_step, vy, vz
2094 758 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: channel_response_weight, &
2095 758 : channel_rotation_gradient, chc_im, chc_re, dense_im, dense_re, generator_im, &
2096 758 : generator_re, previous_rotation_step, rayleigh_response, rhs, rotation_gradient, &
2097 758 : rotation_hessian, rotation_step, rotation_y, rotation_z, schur_block, solution
2098 758 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: channel_rayleigh_response, &
2099 758 : channel_rotation_hessian
2100 : REAL(KIND=dp), DIMENSION(2) :: hxc_density_overlap, hxc_density_overlap_channel, &
2101 : hxc_response_overlap, hxc_response_overlap_channel, projected_coefficients, &
2102 : projected_gradient
2103 : REAL(KIND=dp), DIMENSION(2, 2) :: exact_hxc_correction, hxc_correction, &
2104 : projected_hessian
2105 : TYPE(kpoint_env_type), POINTER :: kp
2106 :
2107 758 : nlocal_channels = SIZE(local_ot_env)
2108 1720 : DO local_channel = 1, nlocal_channels
2109 962 : local_ot_env(local_channel)%rotation_response_valid = .FALSE.
2110 962 : IF (ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx)) THEN
2111 884 : CALL dbcsr_set(local_ot_env(local_channel)%rot_mat_response_gx, 0.0_dp)
2112 : END IF
2113 962 : IF (ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx_im)) THEN
2114 884 : CALL dbcsr_set(local_ot_env(local_channel)%rot_mat_response_gx_im, 0.0_dp)
2115 : END IF
2116 962 : IF (ASSOCIATED(local_ot_env(local_channel)%ener_response_gx)) THEN
2117 6388 : local_ot_env(local_channel)%ener_response_gx(:) = 0.0_dp
2118 : END IF
2119 962 : IF (ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx)) THEN
2120 408 : CALL dbcsr_set(local_ot_env(local_channel)%matrix_response_gx, 0.0_dp)
2121 : END IF
2122 1720 : IF (ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx_im)) THEN
2123 408 : CALL dbcsr_set(local_ot_env(local_channel)%matrix_response_gx_im, 0.0_dp)
2124 : END IF
2125 : END DO
2126 758 : local_ot_env(1)%response_model_curvature = 0.0_dp
2127 758 : local_ot_env(1)%response_shadow_curvature = 0.0_dp
2128 758 : local_ot_env(1)%response_hxc_direction_valid = .FALSE.
2129 : IF (.NOT. local_ot_env(1)%settings%occupation_preconditioner .OR. &
2130 758 : .NOT. local_ot_env(1)%settings%do_rotation .OR. &
2131 : .NOT. local_ot_env(1)%settings%do_ener) RETURN
2132 : ! The dense candidate is accepted through a physical line search. DIIS and Broyden use the
2133 : ! cheaper fixed-N response in their history residuals, but have no comparable accepted-step
2134 : ! model and therefore must not pay for an unused finite-response construction.
2135 680 : IF (local_ot_env(1)%settings%ot_method /= "CG" .AND. &
2136 : local_ot_env(1)%settings%ot_method /= "LBFG") RETURN
2137 : ! The shared ROKS orbital uses the exact occupation-weighted alpha+beta gradient and the two
2138 : ! fixed-N energy blocks use their dense projected preconditioner. The Hxc response history
2139 : ! below is spin-channel-local, so do not construct a falsely alpha-only coupled candidate.
2140 286 : IF (restricted_roks) RETURN
2141 270 : IF (.NOT. ot_mermin_response_preparation_needed( &
2142 : local_ot_env(1)%delta, local_ot_env(1)%response_candidate_directions, &
2143 : local_ot_env(1)%response_shadow_good_samples, &
2144 : local_ot_env(1)%response_candidate_good_samples, &
2145 : local_ot_env(1)%response_candidate_cooldown, &
2146 : local_ot_env(1)%response_shadow_pending)) RETURN
2147 158 : CPASSERT(smear%do_smear)
2148 158 : CPASSERT(ASSOCIATED(para_env_inter_kp))
2149 280 : SELECT CASE (smear%method)
2150 : CASE (smear_fermi_dirac)
2151 122 : sigma = smear%electronic_temperature
2152 : CASE (smear_gaussian, smear_mp, smear_mv)
2153 36 : sigma = smear%smearing_width
2154 : CASE DEFAULT
2155 158 : RETURN
2156 : END SELECT
2157 158 : CPASSERT(sigma > EPSILON(sigma))
2158 :
2159 158 : nmo = SIZE(local_ot_env(1)%ener_x)
2160 158 : nrotation = nmo*(nmo - 1)
2161 158 : IF (nrotation <= 0 .OR. nrotation > finite_response_max_rotation) RETURN
2162 400 : DO local_channel = 1, nlocal_channels
2163 242 : CPASSERT(local_ot_env(local_channel)%has_complex_kpoint_state)
2164 242 : CPASSERT(SIZE(local_ot_env(local_channel)%ener_x) == nmo)
2165 242 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx))
2166 242 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx_im))
2167 400 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%ener_response_gx))
2168 : END DO
2169 :
2170 158 : ngroups = 1
2171 158 : IF (nspin_ot == 2 .AND. smear%fixed_mag_mom > 0.0_dp) ngroups = 2
2172 158 : shadow_pending = local_ot_env(1)%response_shadow_pending
2173 : ALLOCATE (coupling(nrotation), curvature_sum(ngroups), energy_count(ngroups), &
2174 : energy_mean(ngroups), energy_metric_step(nmo), energy_shift(ngroups), &
2175 : energy_weighted_sum(ngroups), rayleigh_step(nmo), response_curvature(ngroups), &
2176 : response_weight(nmo), rotation_count(ngroups), &
2177 : rotation_norm(ngroups), rotation_scale(ngroups), schur_rhs(nrotation), &
2178 : shadow_curvature(ngroups), shadow_energy_mean(ngroups), &
2179 : shadow_energy_metric_step(nmo), shadow_energy_weighted_sum(ngroups), &
2180 : shadow_rayleigh_step(nmo), &
2181 : vy(ngroups), vz(ngroups), rayleigh_response(nmo, nrotation), &
2182 : rhs(nrotation, 2), rotation_gradient(nrotation, 1), &
2183 : rotation_hessian(nrotation, nrotation), &
2184 : previous_rotation_step(nrotation, nlocal_channels), &
2185 : rotation_step(nrotation, nlocal_channels), &
2186 : rotation_y(nrotation, nlocal_channels), rotation_z(nrotation, nlocal_channels), &
2187 : schur_block(nrotation, nrotation), solution(nrotation, 2), &
2188 : channel_rayleigh_response(nmo, nrotation, nlocal_channels), &
2189 : channel_rotation_hessian(nrotation, nrotation, nlocal_channels), &
2190 : channel_rotation_gradient(nrotation, nlocal_channels), &
2191 : channel_response_weight(nmo, nlocal_channels), &
2192 10428 : channel_generator(nmo, nmo, nlocal_channels), density_modes(nmo, nmo, 2))
2193 790 : ALLOCATE (channel_density_modes(nmo, nmo, 2, nlocal_channels))
2194 158 : curvature_sum(:) = 0.0_dp
2195 158 : vy(:) = 0.0_dp
2196 158 : vz(:) = 0.0_dp
2197 158 : rotation_y(:, :) = 0.0_dp
2198 158 : rotation_z(:, :) = 0.0_dp
2199 158 : previous_rotation_step(:, :) = 0.0_dp
2200 158 : channel_rayleigh_response(:, :, :) = 0.0_dp
2201 158 : channel_rotation_hessian(:, :, :) = 0.0_dp
2202 158 : channel_rotation_gradient(:, :) = 0.0_dp
2203 158 : channel_response_weight(:, :) = 0.0_dp
2204 158 : channel_generator(:, :, :) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
2205 158 : channel_density_modes(:, :, :, :) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
2206 158 : failure = 0
2207 158 : response_cross = 0.0_dp
2208 :
2209 382 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2210 224 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2211 224 : ikpoint = kp%nkpoint
2212 624 : DO ispin = 1, nspin_ot
2213 242 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2214 242 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2215 242 : CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc)
2216 242 : CPASSERT(maxocc > EPSILON(maxocc))
2217 : CALL smearing_response_weight( &
2218 : response_weight, trial_occupation(:, ikpoint, ispin), &
2219 : trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
2220 242 : smear%method)
2221 1358 : response_weight(:) = wkp(ikpoint)*response_weight
2222 1358 : curvature_sum(group) = curvature_sum(group) + SUM(response_weight)
2223 :
2224 : CALL qs_scf_loop_ot_matrix_to_dense( &
2225 242 : local_ot_env(local_channel)%rot_mat_chc, local_ot_env(local_channel), chc_re)
2226 : CALL qs_scf_loop_ot_matrix_to_dense( &
2227 242 : local_ot_env(local_channel)%rot_mat_chc_im, local_ot_env(local_channel), chc_im)
2228 : CALL qs_scf_loop_ot_matrix_to_dense( &
2229 242 : local_ot_env(local_channel)%rot_mat_x, local_ot_env(local_channel), generator_re)
2230 : CALL qs_scf_loop_ot_matrix_to_dense( &
2231 242 : local_ot_env(local_channel)%rot_mat_x_im, local_ot_env(local_channel), generator_im)
2232 1452 : ALLOCATE (chc(nmo, nmo), generator(nmo, nmo))
2233 7238 : chc(:, :) = CMPLX(chc_re, chc_im, KIND=dp)
2234 7238 : generator(:, :) = CMPLX(generator_re, generator_im, KIND=dp)
2235 7238 : channel_generator(:, :, local_channel) = generator
2236 : CALL qs_ot_finite_rotation_response( &
2237 : chc, generator, trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
2238 242 : rotation_gradient(:, 1), rotation_hessian, rayleigh_response)
2239 5006 : channel_rotation_gradient(:, local_channel) = rotation_gradient(:, 1)
2240 184406 : channel_rotation_hessian(:, :, local_channel) = rotation_hessian
2241 1358 : channel_response_weight(:, local_channel) = response_weight
2242 : CALL qs_ot_fixed_n_schur_block( &
2243 : rotation_hessian, rayleigh_response, response_weight, rotation_gradient(:, 1), &
2244 242 : local_ot_env(local_channel)%ener_gx, schur_block, coupling, schur_rhs)
2245 5006 : rhs(:, 1) = schur_rhs
2246 5006 : rhs(:, 2) = coupling
2247 : CALL qs_ot_symmetric_abs_solve( &
2248 242 : schur_block, rhs, solution, solve_valid, relative_floor=1.0E-4_dp)
2249 242 : IF (solve_valid) THEN
2250 4820 : rotation_y(:, local_channel) = solution(:, 1)
2251 4820 : rotation_z(:, local_channel) = solution(:, 2)
2252 34004 : channel_rayleigh_response(:, :, local_channel) = rayleigh_response
2253 4820 : vy(group) = vy(group) + DOT_PRODUCT(coupling, solution(:, 1))
2254 4820 : vz(group) = vz(group) + DOT_PRODUCT(coupling, solution(:, 2))
2255 : ELSE
2256 30 : failure = 1
2257 : END IF
2258 242 : IF (shadow_pending .AND. local_ot_env(local_channel)%use_dx) THEN
2259 : CALL qs_scf_loop_ot_matrix_to_dense( &
2260 124 : local_ot_env(local_channel)%rot_mat_dx, local_ot_env(local_channel), dense_re)
2261 : CALL qs_scf_loop_ot_matrix_to_dense( &
2262 124 : local_ot_env(local_channel)%rot_mat_dx_im, local_ot_env(local_channel), dense_im)
2263 124 : r = 0
2264 648 : DO i = 1, nmo - 1
2265 2172 : DO j = i + 1, nmo
2266 1524 : r = r + 1
2267 1524 : previous_rotation_step(r, local_channel) = dense_re(i, j)
2268 1524 : r = r + 1
2269 2048 : previous_rotation_step(r, local_channel) = dense_im(i, j)
2270 : END DO
2271 : END DO
2272 124 : CPASSERT(r == nrotation)
2273 124 : DEALLOCATE (dense_im, dense_re)
2274 : END IF
2275 708 : DEALLOCATE (chc, generator, chc_im, chc_re, generator_im, generator_re)
2276 : END DO
2277 : END DO
2278 :
2279 158 : CALL para_env_inter_kp%sum(curvature_sum)
2280 158 : CALL para_env_inter_kp%sum(vy)
2281 158 : CALL para_env_inter_kp%sum(vz)
2282 158 : CALL para_env_inter_kp%sum(failure)
2283 158 : IF (failure /= 0) THEN
2284 0 : DEALLOCATE (coupling, curvature_sum, energy_count, energy_mean, energy_metric_step, &
2285 0 : energy_shift, energy_weighted_sum, rayleigh_step, response_curvature, &
2286 0 : response_weight, shadow_curvature, shadow_energy_mean, &
2287 0 : shadow_energy_metric_step, shadow_energy_weighted_sum, shadow_rayleigh_step, &
2288 0 : rotation_count, rotation_norm, rotation_scale, schur_rhs, vy, vz, &
2289 0 : rayleigh_response, rhs, rotation_gradient, rotation_hessian, &
2290 0 : previous_rotation_step, rotation_step, &
2291 0 : rotation_y, rotation_z, schur_block, solution, channel_rayleigh_response, &
2292 0 : channel_rotation_hessian, channel_rotation_gradient, channel_response_weight, &
2293 0 : channel_density_modes, channel_generator, &
2294 30 : density_modes)
2295 30 : RETURN
2296 : END IF
2297 :
2298 128 : rotation_norm(:) = 0.0_dp
2299 128 : rotation_count(:) = 0.0_dp
2300 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2301 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2302 170 : ikpoint = kp%nkpoint
2303 480 : DO ispin = 1, nspin_ot
2304 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2305 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2306 182 : denominator = curvature_sum(group) + vz(group)
2307 182 : IF (ABS(denominator) > EPSILON(denominator)) THEN
2308 : rotation_step(:, local_channel) = rotation_y(:, local_channel) - &
2309 4478 : rotation_z(:, local_channel)*vy(group)/denominator
2310 : ELSE
2311 156 : rotation_step(:, local_channel) = rotation_y(:, local_channel)
2312 : END IF
2313 : rotation_norm(group) = rotation_norm(group) + &
2314 : DOT_PRODUCT(rotation_step(:, local_channel), &
2315 4634 : rotation_step(:, local_channel))
2316 352 : rotation_count(group) = rotation_count(group) + REAL(nrotation, KIND=dp)
2317 : END DO
2318 : END DO
2319 128 : CALL para_env_inter_kp%sum(rotation_norm)
2320 128 : CALL para_env_inter_kp%sum(rotation_count)
2321 268 : rotation_scale(:) = 1.0_dp
2322 268 : DO group = 1, ngroups
2323 268 : IF (rotation_norm(group) > EPSILON(rotation_norm(group))) THEN
2324 : rotation_scale(group) = MIN( &
2325 140 : 1.0_dp, rotation_trust_rms*SQRT(rotation_count(group)/rotation_norm(group)))
2326 : END IF
2327 : END DO
2328 :
2329 128 : energy_shift(:) = 0.0_dp
2330 128 : energy_count(:) = 0.0_dp
2331 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2332 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2333 170 : ikpoint = kp%nkpoint
2334 480 : DO ispin = 1, nspin_ot
2335 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2336 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2337 4634 : rotation_step(:, local_channel) = rotation_scale(group)*rotation_step(:, local_channel)
2338 : local_ot_env(local_channel)%ener_response_gx(:) = &
2339 : local_ot_env(local_channel)%ener_preconditioned_gx + &
2340 : MATMUL(channel_rayleigh_response(:, :, local_channel), &
2341 35258 : rotation_step(:, local_channel))
2342 : energy_shift(group) = energy_shift(group) + &
2343 1130 : SUM(local_ot_env(local_channel)%ener_response_gx)
2344 182 : energy_count(group) = energy_count(group) + REAL(nmo, KIND=dp)
2345 :
2346 1092 : ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
2347 182 : dense_re(:, :) = 0.0_dp
2348 182 : dense_im(:, :) = 0.0_dp
2349 182 : r = 0
2350 948 : DO i = 1, nmo - 1
2351 3174 : DO j = i + 1, nmo
2352 2226 : r = r + 1
2353 2226 : dense_re(i, j) = rotation_step(r, local_channel)
2354 2226 : dense_re(j, i) = -rotation_step(r, local_channel)
2355 2226 : r = r + 1
2356 2226 : dense_im(i, j) = rotation_step(r, local_channel)
2357 2992 : dense_im(j, i) = rotation_step(r, local_channel)
2358 : END DO
2359 : END DO
2360 182 : CPASSERT(r == nrotation)
2361 : CALL qs_scf_loop_ot_dense_to_matrix( &
2362 : dense_re, local_ot_env(local_channel), &
2363 182 : local_ot_env(local_channel)%rot_mat_response_gx)
2364 : CALL qs_scf_loop_ot_dense_to_matrix( &
2365 : dense_im, local_ot_env(local_channel), &
2366 182 : local_ot_env(local_channel)%rot_mat_response_gx_im)
2367 182 : local_ot_env(local_channel)%rotation_response_valid = .TRUE.
2368 352 : DEALLOCATE (dense_im, dense_re)
2369 : END DO
2370 : END DO
2371 128 : CALL para_env_inter_kp%sum(energy_shift)
2372 128 : CALL para_env_inter_kp%sum(energy_count)
2373 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2374 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2375 170 : ikpoint = kp%nkpoint
2376 480 : DO ispin = 1, nspin_ot
2377 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2378 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2379 352 : IF (energy_count(group) > 0.0_dp) THEN
2380 : local_ot_env(local_channel)%ener_response_gx(:) = &
2381 : local_ot_env(local_channel)%ener_response_gx - &
2382 1130 : energy_shift(group)/energy_count(group)
2383 : END IF
2384 : END DO
2385 : END DO
2386 :
2387 : ! The accepted gradient difference supplies the missing total cross curvature between the
2388 : ! finite rotation/energy candidate and the preceding accepted product direction. Keep the
2389 : ! dedicated endpoint history separate from CG's preconditioned-gradient history.
2390 128 : accepted_cross = 0.0_dp
2391 128 : accepted_cross_valid = .FALSE.
2392 128 : gradient_secant_failure = 0
2393 128 : IF (shadow_pending .AND. ABS(local_ot_env(1)%ds_min) > SQRT(EPSILON(1.0_dp))) THEN
2394 204 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2395 116 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2396 116 : ikpoint = kp%nkpoint
2397 328 : DO ispin = 1, nspin_ot
2398 124 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2399 : IF (local_ot_env(local_channel)%mermin_gradient_ref_valid .AND. &
2400 : ASSOCIATED(local_ot_env(local_channel)%rot_mat_mermin_g0) .AND. &
2401 124 : ASSOCIATED(local_ot_env(local_channel)%rot_mat_mermin_g0_im) .AND. &
2402 116 : ALLOCATED(local_ot_env(local_channel)%ener_mermin_g0)) THEN
2403 : CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_gx, &
2404 124 : local_ot_env(local_channel)%rot_mat_response_gx, tmp)
2405 124 : accepted_cross = accepted_cross + 0.5_dp*tmp
2406 : CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_mermin_g0, &
2407 124 : local_ot_env(local_channel)%rot_mat_response_gx, tmp)
2408 124 : accepted_cross = accepted_cross - 0.5_dp*tmp
2409 : CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_gx_im, &
2410 124 : local_ot_env(local_channel)%rot_mat_response_gx_im, tmp)
2411 124 : accepted_cross = accepted_cross + 0.5_dp*tmp
2412 : CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_mermin_g0_im, &
2413 124 : local_ot_env(local_channel)%rot_mat_response_gx_im, tmp)
2414 124 : accepted_cross = accepted_cross - 0.5_dp*tmp
2415 : accepted_cross = accepted_cross + &
2416 : DOT_PRODUCT( &
2417 : local_ot_env(local_channel)%ener_gx - &
2418 : local_ot_env(local_channel)%ener_mermin_g0, &
2419 772 : local_ot_env(local_channel)%ener_response_gx)
2420 : ELSE
2421 0 : gradient_secant_failure = 1
2422 : END IF
2423 : END DO
2424 : END DO
2425 88 : CALL para_env_inter_kp%sum(accepted_cross)
2426 88 : CALL para_env_inter_kp%sum(gradient_secant_failure)
2427 88 : IF (gradient_secant_failure == 0) THEN
2428 88 : accepted_cross = accepted_cross/local_ot_env(1)%ds_min
2429 88 : accepted_cross_valid = ieee_is_finite(accepted_cross)
2430 : END IF
2431 : END IF
2432 : ! Evaluate the signed finite response in the same fixed-N tangent used to build the Schur
2433 : ! step. This is a prediction only; the minimizer calibrates it against accepted Mermin drops
2434 : ! before the candidate can be reused.
2435 128 : energy_weighted_sum(:) = 0.0_dp
2436 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2437 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2438 170 : ikpoint = kp%nkpoint
2439 480 : DO ispin = 1, nspin_ot
2440 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2441 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2442 : energy_weighted_sum(group) = energy_weighted_sum(group) + &
2443 : DOT_PRODUCT(channel_response_weight(:, local_channel), &
2444 1300 : local_ot_env(local_channel)%ener_response_gx)
2445 : END DO
2446 : END DO
2447 128 : CALL para_env_inter_kp%sum(energy_weighted_sum)
2448 128 : energy_mean(:) = 0.0_dp
2449 268 : DO group = 1, ngroups
2450 268 : IF (ABS(curvature_sum(group)) > EPSILON(curvature_sum(group))) THEN
2451 128 : energy_mean(group) = energy_weighted_sum(group)/curvature_sum(group)
2452 : END IF
2453 : END DO
2454 :
2455 128 : response_curvature(:) = 0.0_dp
2456 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2457 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2458 170 : ikpoint = kp%nkpoint
2459 480 : DO ispin = 1, nspin_ot
2460 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2461 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2462 : energy_metric_step(:) = channel_response_weight(:, local_channel)* &
2463 : (local_ot_env(local_channel)%ener_response_gx - &
2464 1130 : energy_mean(group))
2465 : rayleigh_step(:) = MATMUL(channel_rayleigh_response(:, :, local_channel), &
2466 33362 : rotation_step(:, local_channel))
2467 : response_curvature(group) = response_curvature(group) + &
2468 : DOT_PRODUCT(rotation_step(:, local_channel), &
2469 546 : MATMUL(channel_rotation_hessian(:, :, local_channel), &
2470 : rotation_step(:, local_channel))) - &
2471 : 2.0_dp*DOT_PRODUCT(rayleigh_step, energy_metric_step) + &
2472 188776 : DOT_PRODUCT(local_ot_env(local_channel)%ener_response_gx, energy_metric_step)
2473 : END DO
2474 : END DO
2475 128 : CALL para_env_inter_kp%sum(response_curvature)
2476 268 : local_ot_env(1)%response_model_curvature = SUM(response_curvature)
2477 :
2478 128 : IF (shadow_pending) THEN
2479 88 : shadow_energy_weighted_sum(:) = 0.0_dp
2480 204 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2481 116 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2482 116 : ikpoint = kp%nkpoint
2483 328 : DO ispin = 1, nspin_ot
2484 124 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2485 124 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2486 : shadow_energy_weighted_sum(group) = shadow_energy_weighted_sum(group) + &
2487 : DOT_PRODUCT(channel_response_weight(:, local_channel), &
2488 888 : local_ot_env(local_channel)%ener_dx)
2489 : END DO
2490 : END DO
2491 88 : CALL para_env_inter_kp%sum(shadow_energy_weighted_sum)
2492 88 : shadow_energy_mean(:) = 0.0_dp
2493 184 : DO group = 1, ngroups
2494 184 : IF (ABS(curvature_sum(group)) > EPSILON(curvature_sum(group))) THEN
2495 88 : shadow_energy_mean(group) = shadow_energy_weighted_sum(group)/curvature_sum(group)
2496 : END IF
2497 : END DO
2498 :
2499 88 : shadow_curvature(:) = 0.0_dp
2500 88 : projected_gradient(:) = 0.0_dp
2501 204 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2502 116 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2503 116 : ikpoint = kp%nkpoint
2504 328 : DO ispin = 1, nspin_ot
2505 124 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2506 124 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2507 : energy_metric_step(:) = channel_response_weight(:, local_channel)* &
2508 : (local_ot_env(local_channel)%ener_response_gx - &
2509 772 : energy_mean(group))
2510 : shadow_energy_metric_step(:) = channel_response_weight(:, local_channel)* &
2511 : (local_ot_env(local_channel)%ener_dx - &
2512 772 : shadow_energy_mean(group))
2513 : rayleigh_step(:) = MATMUL(channel_rayleigh_response(:, :, local_channel), &
2514 22804 : rotation_step(:, local_channel))
2515 : shadow_rayleigh_step(:) = MATMUL( &
2516 : channel_rayleigh_response(:, :, local_channel), &
2517 22804 : previous_rotation_step(:, local_channel))
2518 : shadow_curvature(group) = shadow_curvature(group) + &
2519 : DOT_PRODUCT(previous_rotation_step(:, local_channel), &
2520 372 : MATMUL(channel_rotation_hessian(:, :, local_channel), &
2521 : previous_rotation_step(:, local_channel))) - &
2522 : 2.0_dp*DOT_PRODUCT(shadow_rayleigh_step, &
2523 : shadow_energy_metric_step) + &
2524 : DOT_PRODUCT(local_ot_env(local_channel)%ener_dx, &
2525 128332 : shadow_energy_metric_step)
2526 : response_cross = response_cross + &
2527 : DOT_PRODUCT(rotation_step(:, local_channel), &
2528 372 : MATMUL(channel_rotation_hessian(:, :, local_channel), &
2529 : previous_rotation_step(:, local_channel))) - &
2530 : DOT_PRODUCT(rayleigh_step, shadow_energy_metric_step) - &
2531 : DOT_PRODUCT(shadow_rayleigh_step, energy_metric_step) + &
2532 : 0.5_dp*( &
2533 : DOT_PRODUCT(local_ot_env(local_channel)%ener_response_gx, &
2534 : shadow_energy_metric_step) + &
2535 129628 : DOT_PRODUCT(local_ot_env(local_channel)%ener_dx, energy_metric_step))
2536 : projected_gradient(1) = projected_gradient(1) + &
2537 : DOT_PRODUCT(channel_rotation_gradient(:, local_channel), &
2538 : rotation_step(:, local_channel)) + &
2539 : DOT_PRODUCT(local_ot_env(local_channel)%ener_gx, &
2540 3820 : local_ot_env(local_channel)%ener_response_gx)
2541 : CALL dbcsr_dot(local_ot_env(local_channel)%matrix_gx, &
2542 124 : local_ot_env(local_channel)%matrix_dx, tmp)
2543 124 : projected_gradient(2) = projected_gradient(2) + tmp
2544 : CALL dbcsr_dot(local_ot_env(local_channel)%matrix_gx_im, &
2545 124 : local_ot_env(local_channel)%matrix_dx_im, tmp)
2546 124 : projected_gradient(2) = projected_gradient(2) + tmp
2547 : projected_gradient(2) = projected_gradient(2) + &
2548 : DOT_PRODUCT(channel_rotation_gradient(:, local_channel), &
2549 : previous_rotation_step(:, local_channel)) + &
2550 : DOT_PRODUCT(local_ot_env(local_channel)%ener_gx, &
2551 4060 : local_ot_env(local_channel)%ener_dx)
2552 : END DO
2553 : END DO
2554 88 : CALL para_env_inter_kp%sum(shadow_curvature)
2555 88 : CALL para_env_inter_kp%sum(response_cross)
2556 88 : CALL para_env_inter_kp%sum(projected_gradient)
2557 184 : local_ot_env(1)%response_shadow_curvature = SUM(shadow_curvature)
2558 : END IF
2559 :
2560 : ! The frozen-H finite response above omits the self-consistent Hxc density response. Project
2561 : ! the most recent accepted physical density/Hamiltonian secant onto both the candidate and
2562 : ! conventional accepted directions. All spin/K-point overlaps are accumulated before the
2563 : ! minimum-Frobenius secant is formed: this is the direct-sum spin response, including the Hxc
2564 : ! cross-spin coupling, and not a sum of independently fitted spin Hessians. The resulting
2565 : ! sign-aware rank-two response is calibrated against accepted Mermin drops before it can replace
2566 : ! the conventional search direction.
2567 128 : hxc_density_norm_sq = 0.0_dp
2568 128 : hxc_response_work = 0.0_dp
2569 128 : hxc_density_overlap(:) = 0.0_dp
2570 128 : hxc_response_overlap(:) = 0.0_dp
2571 128 : failure = 0
2572 298 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2573 170 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2574 170 : ikpoint = kp%nkpoint
2575 170 : CPASSERT(ASSOCIATED(kp%ot_smat))
2576 170 : CPASSERT(SIZE(kp%ot_smat) >= 2)
2577 480 : DO ispin = 1, nspin_ot
2578 182 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2579 182 : local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2580 : energy_metric_step(:) = -channel_response_weight(:, local_channel)* &
2581 : (local_ot_env(local_channel)%ener_response_gx - &
2582 1130 : energy_mean(group))
2583 : CALL qs_ot_density_tangent( &
2584 : channel_generator(:, :, local_channel), &
2585 : trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
2586 182 : rotation_step(:, local_channel), energy_metric_step, density_modes(:, :, 1))
2587 6530 : channel_density_modes(:, :, 1, local_channel) = density_modes(:, :, 1)
2588 6530 : density_modes(:, :, 2) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
2589 182 : IF (shadow_pending) THEN
2590 : energy_metric_step(:) = -channel_response_weight(:, local_channel)* &
2591 : (local_ot_env(local_channel)%ener_dx - &
2592 772 : shadow_energy_mean(group))
2593 : CALL qs_ot_density_tangent( &
2594 : channel_generator(:, :, local_channel), &
2595 : trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
2596 : previous_rotation_step(:, local_channel), energy_metric_step, &
2597 124 : density_modes(:, :, 2))
2598 4468 : channel_density_modes(:, :, 2, local_channel) = density_modes(:, :, 2)
2599 : END IF
2600 : CALL qs_scf_kp_physical_secant_overlaps( &
2601 : local_ot_env(local_channel), kp%ot_smat(1), kp%ot_smat(2), density_modes, &
2602 : wkp(ikpoint), hxc_density_norm_sq_channel, hxc_response_work_channel, &
2603 182 : hxc_density_overlap_channel, hxc_response_overlap_channel, hxc_channel_valid)
2604 352 : IF (hxc_channel_valid) THEN
2605 182 : hxc_density_norm_sq = hxc_density_norm_sq + hxc_density_norm_sq_channel
2606 182 : hxc_response_work = hxc_response_work + hxc_response_work_channel
2607 546 : hxc_density_overlap(:) = hxc_density_overlap + hxc_density_overlap_channel
2608 546 : hxc_response_overlap(:) = hxc_response_overlap + hxc_response_overlap_channel
2609 : ELSE
2610 0 : failure = 1
2611 : END IF
2612 : END DO
2613 : END DO
2614 128 : exact_hxc_correction(:, :) = 0.0_dp
2615 128 : exact_hxc_valid = .FALSE.
2616 128 : IF (local_ot_env(1)%settings%ot_method == "CG") THEN
2617 : CALL qs_scf_kp_exact_hxc_projected( &
2618 : qs_env, kpoints, local_ot_env, first_channel, nspin_ot, wkp, para_env_inter_kp, &
2619 : sab_nl, fmwork, rho_ao_kp, channel_density_modes, MERGE(2, 1, shadow_pending), &
2620 116 : exact_hxc_correction, exact_hxc_valid)
2621 : END IF
2622 128 : CALL para_env_inter_kp%sum(failure)
2623 128 : CALL para_env_inter_kp%sum(hxc_density_norm_sq)
2624 128 : CALL para_env_inter_kp%sum(hxc_response_work)
2625 128 : CALL para_env_inter_kp%sum(hxc_density_overlap)
2626 128 : CALL para_env_inter_kp%sum(hxc_response_overlap)
2627 128 : hxc_correction(:, :) = 0.0_dp
2628 128 : hxc_valid = .FALSE.
2629 128 : IF (failure == 0) THEN
2630 128 : IF (shadow_pending .AND. &
2631 : ABS(local_ot_env(1)%ds_min) > SQRT(EPSILON(1.0_dp))) THEN
2632 : CALL qs_ot_density_secant_projected_hessian( &
2633 : hxc_density_norm_sq, hxc_response_work, hxc_density_overlap, &
2634 : hxc_response_overlap, hxc_correction, hxc_valid, &
2635 88 : secant_mode=2, secant_position=local_ot_env(1)%ds_min)
2636 : ELSE
2637 : CALL qs_ot_density_secant_projected_hessian( &
2638 : hxc_density_norm_sq, hxc_response_work, hxc_density_overlap, &
2639 40 : hxc_response_overlap, hxc_correction, hxc_valid)
2640 : END IF
2641 : END IF
2642 128 : IF (exact_hxc_valid) THEN
2643 88 : hxc_correction(:, :) = exact_hxc_correction
2644 88 : hxc_valid = .TRUE.
2645 : END IF
2646 128 : IF (hxc_valid) THEN
2647 : local_ot_env(1)%response_model_curvature = &
2648 128 : local_ot_env(1)%response_model_curvature + hxc_correction(1, 1)
2649 128 : IF (shadow_pending) THEN
2650 : local_ot_env(1)%response_shadow_curvature = &
2651 88 : local_ot_env(1)%response_shadow_curvature + hxc_correction(2, 2)
2652 : END IF
2653 88 : IF (shadow_pending) THEN
2654 : CALL ot_mermin_secant_curvature( &
2655 : local_ot_env(1)%response_reference_energy, local_ot_env(1)%etotal, &
2656 : local_ot_env(1)%response_predicted_slope, local_ot_env(1)%ds_min, &
2657 88 : accepted_curvature, accepted_curvature_valid)
2658 184 : projected_hessian(1, 1) = SUM(response_curvature)
2659 88 : projected_hessian(1, 2) = response_cross
2660 88 : projected_hessian(2, 1) = response_cross
2661 184 : projected_hessian(2, 2) = SUM(shadow_curvature)
2662 88 : IF (accepted_cross_valid) THEN
2663 88 : projected_hessian(1, 2) = accepted_cross - hxc_correction(1, 2)
2664 88 : projected_hessian(2, 1) = projected_hessian(1, 2)
2665 : END IF
2666 88 : IF (accepted_curvature_valid) THEN
2667 88 : projected_hessian(2, 2) = accepted_curvature - hxc_correction(2, 2)
2668 88 : local_ot_env(1)%response_shadow_curvature = accepted_curvature
2669 : END IF
2670 : CALL qs_ot_projected_response_update( &
2671 : projected_hessian, hxc_correction, projected_coefficients, projected_update_valid, &
2672 88 : projected_gradient=projected_gradient)
2673 88 : IF (projected_update_valid) THEN
2674 88 : rotation_norm(:) = 0.0_dp
2675 88 : rotation_count(:) = 0.0_dp
2676 204 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2677 116 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2678 116 : ikpoint = kp%nkpoint
2679 328 : DO ispin = 1, nspin_ot
2680 124 : group = MERGE(ispin, 1, ngroups == nspin_ot)
2681 : local_channel = &
2682 124 : qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2683 : rotation_step(:, local_channel) = &
2684 : projected_coefficients(1)*rotation_step(:, local_channel) + &
2685 3172 : projected_coefficients(2)*previous_rotation_step(:, local_channel)
2686 : local_ot_env(local_channel)%ener_response_gx(:) = &
2687 : projected_coefficients(1)* &
2688 : local_ot_env(local_channel)%ener_response_gx + &
2689 772 : projected_coefficients(2)*local_ot_env(local_channel)%ener_dx
2690 : rotation_norm(group) = rotation_norm(group) + &
2691 : DOT_PRODUCT(rotation_step(:, local_channel), &
2692 3172 : rotation_step(:, local_channel))
2693 240 : rotation_count(group) = rotation_count(group) + REAL(nrotation, KIND=dp)
2694 : END DO
2695 : END DO
2696 88 : CALL para_env_inter_kp%sum(rotation_norm)
2697 88 : CALL para_env_inter_kp%sum(rotation_count)
2698 88 : response_scale = 1.0_dp
2699 184 : IF (SUM(rotation_norm) > EPSILON(SUM(rotation_norm))) THEN
2700 : response_scale = MIN( &
2701 : 1.0_dp, rotation_trust_rms* &
2702 280 : SQRT(SUM(rotation_count)/SUM(rotation_norm)))
2703 : END IF
2704 88 : unscaled_rotation_norm = 0.0_dp
2705 212 : DO local_channel = 1, nlocal_channels
2706 744 : ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
2707 124 : dense_re(:, :) = 0.0_dp
2708 124 : dense_im(:, :) = 0.0_dp
2709 124 : r = 0
2710 648 : DO i = 1, nmo - 1
2711 2172 : DO j = i + 1, nmo
2712 1524 : r = r + 1
2713 1524 : dense_re(i, j) = rotation_step(r, local_channel)
2714 1524 : dense_re(j, i) = -rotation_step(r, local_channel)
2715 1524 : r = r + 1
2716 1524 : dense_im(i, j) = rotation_step(r, local_channel)
2717 2048 : dense_im(j, i) = rotation_step(r, local_channel)
2718 : END DO
2719 : END DO
2720 124 : CPASSERT(r == nrotation)
2721 : unscaled_rotation_norm = MAX( &
2722 : unscaled_rotation_norm, qs_ot_antihermitian_spectral_norm( &
2723 4468 : CMPLX(dense_re, dense_im, KIND=dp)))
2724 212 : DEALLOCATE (dense_im, dense_re)
2725 : END DO
2726 88 : CALL para_env_inter_kp%max(unscaled_rotation_norm)
2727 88 : IF (unscaled_rotation_norm > EPSILON(unscaled_rotation_norm)) THEN
2728 : response_scale = MIN( &
2729 : response_scale, &
2730 88 : rotation_trust_spectral/unscaled_rotation_norm)
2731 : END IF
2732 204 : DO local_kpoint = 1, SIZE(kpoints%kp_env)
2733 116 : kp => kpoints%kp_env(local_kpoint)%kpoint_env
2734 116 : ikpoint = kp%nkpoint
2735 328 : DO ispin = 1, nspin_ot
2736 : local_channel = &
2737 124 : qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
2738 : rotation_step(:, local_channel) = &
2739 3172 : response_scale*rotation_step(:, local_channel)
2740 : local_ot_env(local_channel)%ener_response_gx(:) = &
2741 772 : response_scale*local_ot_env(local_channel)%ener_response_gx
2742 124 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx))
2743 124 : CPASSERT(ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx_im))
2744 : CALL dbcsr_copy(local_ot_env(local_channel)%matrix_response_gx, &
2745 124 : local_ot_env(local_channel)%matrix_dx)
2746 : CALL dbcsr_scale(local_ot_env(local_channel)%matrix_response_gx, &
2747 124 : response_scale*projected_coefficients(2))
2748 : CALL dbcsr_copy(local_ot_env(local_channel)%matrix_response_gx_im, &
2749 124 : local_ot_env(local_channel)%matrix_dx_im)
2750 : CALL dbcsr_scale(local_ot_env(local_channel)%matrix_response_gx_im, &
2751 124 : response_scale*projected_coefficients(2))
2752 744 : ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
2753 124 : dense_re(:, :) = 0.0_dp
2754 124 : dense_im(:, :) = 0.0_dp
2755 124 : r = 0
2756 648 : DO i = 1, nmo - 1
2757 2172 : DO j = i + 1, nmo
2758 1524 : r = r + 1
2759 1524 : dense_re(i, j) = rotation_step(r, local_channel)
2760 1524 : dense_re(j, i) = -rotation_step(r, local_channel)
2761 1524 : r = r + 1
2762 1524 : dense_im(i, j) = rotation_step(r, local_channel)
2763 2048 : dense_im(j, i) = rotation_step(r, local_channel)
2764 : END DO
2765 : END DO
2766 124 : CPASSERT(r == nrotation)
2767 : CALL qs_scf_loop_ot_dense_to_matrix( &
2768 : dense_re, local_ot_env(local_channel), &
2769 124 : local_ot_env(local_channel)%rot_mat_response_gx)
2770 : CALL qs_scf_loop_ot_dense_to_matrix( &
2771 : dense_im, local_ot_env(local_channel), &
2772 124 : local_ot_env(local_channel)%rot_mat_response_gx_im)
2773 240 : DEALLOCATE (dense_im, dense_re)
2774 : END DO
2775 : END DO
2776 88 : local_ot_env(1)%response_hxc_direction_valid = .TRUE.
2777 : local_ot_env(1)%response_model_curvature = response_scale**2* &
2778 : DOT_PRODUCT(projected_coefficients, &
2779 : MATMUL(projected_hessian + hxc_correction, &
2780 1320 : projected_coefficients))
2781 : END IF
2782 : END IF
2783 : END IF
2784 :
2785 0 : DEALLOCATE (coupling, curvature_sum, energy_count, energy_mean, energy_metric_step, &
2786 0 : energy_shift, energy_weighted_sum, rayleigh_step, response_curvature, &
2787 0 : response_weight, shadow_curvature, shadow_energy_mean, &
2788 0 : shadow_energy_metric_step, shadow_energy_weighted_sum, shadow_rayleigh_step, &
2789 0 : rotation_count, rotation_norm, rotation_scale, schur_rhs, vy, vz, &
2790 0 : rayleigh_response, rhs, rotation_gradient, rotation_hessian, &
2791 0 : previous_rotation_step, rotation_step, &
2792 0 : rotation_y, rotation_z, schur_block, solution, channel_rayleigh_response, &
2793 0 : channel_rotation_hessian, channel_rotation_gradient, channel_response_weight, &
2794 0 : channel_density_modes, channel_generator, &
2795 128 : density_modes)
2796 :
2797 758 : END SUBROUTINE qs_scf_loop_prepare_ot_kp_rotation_response
2798 :
2799 : ! **************************************************************************************************
2800 : !> \brief copy a distributed OT matrix to a replicated dense matrix
2801 : !> \param matrix distributed matrix
2802 : !> \param ot_env channel owning the matrix distribution
2803 : !> \param dense replicated result
2804 : ! **************************************************************************************************
2805 1216 : SUBROUTINE qs_scf_loop_ot_matrix_to_dense(matrix, ot_env, dense)
2806 : TYPE(dbcsr_type), INTENT(IN) :: matrix
2807 : TYPE(qs_ot_type), INTENT(IN) :: ot_env
2808 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
2809 : INTENT(OUT) :: dense
2810 :
2811 : INTEGER :: ncol, nrow
2812 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2813 : TYPE(cp_fm_type) :: fm
2814 :
2815 1216 : NULLIFY (fm_struct)
2816 0 : CPASSERT(ASSOCIATED(ot_env%blacs_env))
2817 1216 : CPASSERT(ASSOCIATED(ot_env%para_env))
2818 1216 : CALL dbcsr_get_info(matrix, nfullrows_total=nrow, nfullcols_total=ncol)
2819 4864 : ALLOCATE (dense(nrow, ncol))
2820 : CALL cp_fm_struct_create(fm_struct, context=ot_env%blacs_env, para_env=ot_env%para_env, &
2821 1216 : nrow_global=nrow, ncol_global=ncol)
2822 1216 : CALL cp_fm_create(fm, fm_struct)
2823 1216 : CALL copy_dbcsr_to_fm(matrix, fm)
2824 1216 : CALL cp_fm_get_submatrix(fm, dense, n_rows=nrow, n_cols=ncol)
2825 1216 : CALL cp_fm_release(fm)
2826 1216 : CALL cp_fm_struct_release(fm_struct)
2827 :
2828 3648 : END SUBROUTINE qs_scf_loop_ot_matrix_to_dense
2829 :
2830 : ! **************************************************************************************************
2831 : !> \brief copy a replicated dense matrix into a distributed OT matrix
2832 : !> \param dense replicated source
2833 : !> \param ot_env channel owning the matrix distribution
2834 : !> \param matrix distributed result
2835 : ! **************************************************************************************************
2836 612 : SUBROUTINE qs_scf_loop_ot_dense_to_matrix(dense, ot_env, matrix)
2837 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: dense
2838 : TYPE(qs_ot_type), INTENT(IN) :: ot_env
2839 : TYPE(dbcsr_type), INTENT(INOUT) :: matrix
2840 :
2841 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2842 : TYPE(cp_fm_type) :: fm
2843 :
2844 612 : NULLIFY (fm_struct)
2845 0 : CPASSERT(ASSOCIATED(ot_env%blacs_env))
2846 612 : CPASSERT(ASSOCIATED(ot_env%para_env))
2847 : CALL cp_fm_struct_create(fm_struct, context=ot_env%blacs_env, para_env=ot_env%para_env, &
2848 612 : nrow_global=SIZE(dense, 1), ncol_global=SIZE(dense, 2))
2849 612 : CALL cp_fm_create(fm, fm_struct)
2850 612 : CALL cp_fm_set_submatrix(fm, dense)
2851 612 : CALL copy_fm_to_dbcsr(fm, matrix)
2852 612 : CALL cp_fm_release(fm)
2853 612 : CALL cp_fm_struct_release(fm_struct)
2854 :
2855 612 : END SUBROUTINE qs_scf_loop_ot_dense_to_matrix
2856 :
2857 : ! **************************************************************************************************
2858 : !> \brief the inner loop of scf, specific to using to the orbital transformation method
2859 : !> basically, in goes the ks matrix out goes a new p matrix
2860 : !> \param qs_env ...
2861 : !> \param scf_env ...
2862 : !> \param smear ...
2863 : !> \param mos ...
2864 : !> \param rho ...
2865 : !> \param mo_derivs ...
2866 : !> \param total_energy ...
2867 : !> \param matrix_s ...
2868 : !> \param energy_only ...
2869 : !> \param has_unit_metric ...
2870 : !> \par History
2871 : !> 03.2006 created [Joost VandeVondele]
2872 : !> 2013 moved from qs_scf [Florian Schiffmann]
2873 : ! **************************************************************************************************
2874 79806 : SUBROUTINE qs_scf_loop_do_ot(qs_env, scf_env, smear, mos, rho, mo_derivs, total_energy, &
2875 : matrix_s, energy_only, has_unit_metric)
2876 :
2877 : TYPE(qs_environment_type), POINTER :: qs_env
2878 : TYPE(qs_scf_env_type), POINTER :: scf_env
2879 : TYPE(smear_type), POINTER :: smear
2880 : TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT) :: mos
2881 : TYPE(qs_rho_type), POINTER :: rho
2882 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mo_derivs
2883 : REAL(KIND=dp), INTENT(IN) :: total_energy
2884 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
2885 : LOGICAL, INTENT(INOUT) :: energy_only
2886 : LOGICAL, INTENT(IN) :: has_unit_metric
2887 :
2888 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_loop_do_ot'
2889 :
2890 : INTEGER :: handle, ispin
2891 79806 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho_ao
2892 : TYPE(dbcsr_type), POINTER :: orthogonality_metric
2893 :
2894 79806 : CALL timeset(routineN, handle)
2895 79806 : NULLIFY (rho_ao)
2896 :
2897 79806 : CALL qs_rho_get(rho, rho_ao=rho_ao)
2898 :
2899 79806 : IF (has_unit_metric) THEN
2900 18424 : NULLIFY (orthogonality_metric)
2901 : ELSE
2902 61382 : orthogonality_metric => matrix_s(1)%matrix
2903 : END IF
2904 :
2905 : ! in case of LSD the first spin qs_ot_env will drive the minimization
2906 : ! in the case of a restricted calculation, it will make sure the spin orbitals are equal
2907 :
2908 : CALL ot_scf_mini(mos, mo_derivs, smear, orthogonality_metric, &
2909 : total_energy, energy_only, scf_env%iter_delta, &
2910 79806 : scf_env%qs_ot_env)
2911 :
2912 174589 : DO ispin = 1, SIZE(mos)
2913 174589 : CALL set_mo_occupation(mo_set=mos(ispin), smear=smear)
2914 : END DO
2915 :
2916 174589 : DO ispin = 1, SIZE(mos)
2917 : CALL calculate_density_matrix(mos(ispin), &
2918 : rho_ao(ispin)%matrix, &
2919 174589 : use_dbcsr=.TRUE.)
2920 : END DO
2921 :
2922 79806 : scf_env%iter_method = scf_env%qs_ot_env(1)%OT_METHOD_FULL
2923 79806 : scf_env%iter_param = scf_env%qs_ot_env(1)%ds_min
2924 79806 : qs_env%broyden_adaptive_sigma = scf_env%qs_ot_env(1)%broyden_adaptive_sigma
2925 :
2926 79806 : CALL timestop(handle)
2927 :
2928 79806 : END SUBROUTINE qs_scf_loop_do_ot
2929 :
2930 : ! **************************************************************************************************
2931 : !> \brief Measure the distance between the diagonalized candidate density and the current density.
2932 : !> \param scf_env Holds SCF environment information.
2933 : !> \param rho Current electron density.
2934 : !> \param para_env Parallel environment.
2935 : !> \param delta Maximum matrix-element difference.
2936 : ! **************************************************************************************************
2937 220 : SUBROUTINE qs_scf_candidate_density_delta(scf_env, rho, para_env, delta)
2938 : TYPE(qs_scf_env_type), POINTER :: scf_env
2939 : TYPE(qs_rho_type), POINTER :: rho
2940 : TYPE(mp_para_env_type), POINTER :: para_env
2941 : REAL(KIND=dp), INTENT(OUT) :: delta
2942 :
2943 : INTEGER :: ic, ispin
2944 : REAL(KIND=dp) :: tmp
2945 220 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
2946 :
2947 220 : NULLIFY (rho_ao_kp)
2948 220 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
2949 :
2950 220 : CPASSERT(ASSOCIATED(scf_env%p_mix_new))
2951 220 : delta = 0.0_dp
2952 10852 : DO ic = 1, SIZE(scf_env%p_mix_new, 2)
2953 30388 : DO ispin = 1, SIZE(scf_env%p_mix_new, 1)
2954 : ! p_mix=1 leaves the candidate unchanged while cp_sm_mix evaluates
2955 : ! the same max-element density difference used by direct mixing.
2956 : CALL cp_sm_mix(m1=scf_env%p_mix_new(ispin, ic)%matrix, &
2957 : m2=rho_ao_kp(ispin, ic)%matrix, p_mix=1.0_dp, &
2958 19536 : delta=tmp, para_env=para_env)
2959 30168 : delta = MAX(delta, tmp)
2960 : END DO
2961 : END DO
2962 :
2963 220 : END SUBROUTINE qs_scf_candidate_density_delta
2964 :
2965 : ! **************************************************************************************************
2966 : !> \brief Commit the diagonalized candidate density without numerical mixing.
2967 : !> \param scf_env Holds SCF environment information.
2968 : !> \param rho Electron density to update.
2969 : ! **************************************************************************************************
2970 186 : SUBROUTINE qs_scf_commit_density_candidate(scf_env, rho)
2971 : TYPE(qs_scf_env_type), POINTER :: scf_env
2972 : TYPE(qs_rho_type), POINTER :: rho
2973 :
2974 : CHARACTER(len=default_string_length) :: name
2975 : INTEGER :: ic, ispin
2976 186 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
2977 :
2978 186 : NULLIFY (rho_ao_kp)
2979 186 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
2980 :
2981 186 : CPASSERT(ASSOCIATED(scf_env%p_mix_new))
2982 10242 : DO ic = 1, SIZE(scf_env%p_mix_new, 2)
2983 28698 : DO ispin = 1, SIZE(scf_env%p_mix_new, 1)
2984 18456 : CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name)
2985 28512 : CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
2986 : END DO
2987 : END DO
2988 :
2989 186 : END SUBROUTINE qs_scf_commit_density_candidate
2990 :
2991 : ! **************************************************************************************************
2992 : !> \brief Performs the requested density mixing if any needed
2993 : !> \param scf_env Holds SCF environment information
2994 : !> \param rho All data for the electron density
2995 : !> \param para_env Parallel environment
2996 : !> \param diis_step Did we do a DIIS step?
2997 : ! **************************************************************************************************
2998 231487 : SUBROUTINE qs_scf_density_mixing(scf_env, rho, para_env, diis_step)
2999 : TYPE(qs_scf_env_type), POINTER :: scf_env
3000 : TYPE(qs_rho_type), POINTER :: rho
3001 : TYPE(mp_para_env_type), POINTER :: para_env
3002 : LOGICAL :: diis_step
3003 :
3004 231487 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
3005 :
3006 231487 : NULLIFY (rho_ao_kp)
3007 :
3008 231487 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
3009 :
3010 372982 : SELECT CASE (scf_env%mixing_method)
3011 : CASE (direct_mixing_nr)
3012 : CALL scf_env_density_mixing(scf_env%p_mix_new, &
3013 : scf_env%mixing_store, rho_ao_kp, para_env, scf_env%iter_delta, scf_env%iter_count, &
3014 141495 : diis=diis_step)
3015 : CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, modified_broyden_mixing_nr, &
3016 : multisecant_mixing_nr, new_pulay_mixing_nr)
3017 : ! Compute the difference p_out-p_in
3018 : CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, scf_env%p_mix_new, &
3019 7822 : delta=scf_env%iter_delta)
3020 : CASE (no_mixing_nr)
3021 : CASE DEFAULT
3022 : CALL cp_abort(__LOCATION__, &
3023 : "unknown scf mixing method: "// &
3024 231487 : cp_to_string(scf_env%mixing_method))
3025 : END SELECT
3026 :
3027 231487 : END SUBROUTINE qs_scf_density_mixing
3028 :
3029 : ! **************************************************************************************************
3030 : !> \brief checks whether exit conditions for outer loop are satisfied
3031 : !> \param qs_env ...
3032 : !> \param scf_env ...
3033 : !> \param scf_control ...
3034 : !> \param should_stop ...
3035 : !> \param outer_loop_converged ...
3036 : !> \param exit_outer_loop ...
3037 : ! **************************************************************************************************
3038 25681 : SUBROUTINE qs_scf_check_outer_exit(qs_env, scf_env, scf_control, should_stop, &
3039 : outer_loop_converged, exit_outer_loop)
3040 : TYPE(qs_environment_type), POINTER :: qs_env
3041 : TYPE(qs_scf_env_type), POINTER :: scf_env
3042 : TYPE(scf_control_type), POINTER :: scf_control
3043 : LOGICAL :: should_stop, outer_loop_converged, &
3044 : exit_outer_loop
3045 :
3046 : REAL(KIND=dp) :: outer_loop_eps
3047 :
3048 25681 : outer_loop_converged = .TRUE.
3049 25681 : IF (scf_control%outer_scf%have_scf) THEN
3050 : ! We have an outer SCF loop...
3051 6179 : scf_env%outer_scf%iter_count = scf_env%outer_scf%iter_count + 1
3052 6179 : outer_loop_converged = .FALSE.
3053 :
3054 6179 : CALL outer_loop_gradient(qs_env, scf_env)
3055 : ! Multiple constraints: get largest deviation
3056 12446 : outer_loop_eps = SQRT(MAXVAL(scf_env%outer_scf%gradient(:, scf_env%outer_scf%iter_count)**2))
3057 :
3058 6179 : IF (outer_loop_eps < scf_control%outer_scf%eps_scf) outer_loop_converged = .TRUE.
3059 : END IF
3060 :
3061 : exit_outer_loop = should_stop .OR. outer_loop_converged .OR. &
3062 25681 : scf_env%outer_scf%iter_count > scf_control%outer_scf%max_scf
3063 :
3064 25681 : END SUBROUTINE qs_scf_check_outer_exit
3065 :
3066 : ! **************************************************************************************************
3067 : !> \brief checks whether exit conditions for inner loop are satisfied
3068 : !> \param qs_env ...
3069 : !> \param scf_env ...
3070 : !> \param scf_control ...
3071 : !> \param should_stop ...
3072 : !> \param just_energy ...
3073 : !> \param exit_inner_loop ...
3074 : !> \param inner_loop_converged ...
3075 : !> \param output_unit ...
3076 : ! **************************************************************************************************
3077 463414 : SUBROUTINE qs_scf_check_inner_exit(qs_env, scf_env, scf_control, should_stop, just_energy, &
3078 : exit_inner_loop, inner_loop_converged, output_unit)
3079 : TYPE(qs_environment_type), POINTER :: qs_env
3080 : TYPE(qs_scf_env_type), POINTER :: scf_env
3081 : TYPE(scf_control_type), POINTER :: scf_control
3082 : LOGICAL :: should_stop, just_energy, &
3083 : exit_inner_loop, inner_loop_converged
3084 : INTEGER :: output_unit
3085 :
3086 : LOGICAL :: davidson_tightening, update_validated
3087 :
3088 231707 : inner_loop_converged = .FALSE.
3089 231707 : exit_inner_loop = .FALSE.
3090 231707 : update_validated = scf_control%diagonalization%update_method /= diag_update_method_adiis
3091 231707 : IF (.NOT. update_validated) THEN
3092 220 : CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
3093 : update_validated = scf_env%adiis_validated .OR. &
3094 220 : scf_env%scf_subspace_buffer%diis_weight >= 1.0_dp
3095 : END IF
3096 :
3097 : CALL external_control(should_stop, "SCF", target_time=qs_env%target_time, &
3098 231707 : start_time=qs_env%start_time)
3099 231707 : IF (scf_env%iter_delta < scf_control%eps_scf .AND. update_validated) THEN
3100 : ! nested IFs on purpose: a .AND. chain leaves the evaluation order
3101 : ! unspecified. On non-Davidson runs the env array has size zero
3102 : ! while the tightening test below indexes its first channel
3103 21897 : davidson_tightening = .FALSE.
3104 21897 : IF (scf_env%method == block_davidson_diag_method_nr) THEN
3105 34 : IF (SIZE(scf_env%block_davidson_env) > 0) THEN
3106 : davidson_tightening = scf_env%block_davidson_env(1)%eps_iter_used > &
3107 : scf_env%block_davidson_env(1)%eps_iter .AND. &
3108 34 : scf_env%iter_delta < scf_env%block_davidson_env(1)%eps_iter_used
3109 : END IF
3110 : END IF
3111 : IF (davidson_tightening) THEN
3112 : ! the adaptive inner tolerance of the Davidson solve that produced
3113 : ! this mixing delta was looser than the delta itself. The apparent
3114 : ! convergence may be nothing but the noise floor of the loose
3115 : ! solve. Tighten the ratchet one decade below what that solve used
3116 : ! and keep iterating until the delta survives a tighter solve.
3117 0 : IF (output_unit > 0) THEN
3118 : WRITE (UNIT=output_unit, FMT="(T3,A,ES9.2,A)") &
3119 0 : "*** SCF delta below the loose Davidson tolerance ", &
3120 0 : scf_env%block_davidson_env(1)%eps_iter_used, " - tightening and continuing ***"
3121 : END IF
3122 : scf_env%block_davidson_env(1)%eps_iter_prev = &
3123 : MIN(scf_env%block_davidson_env(1)%eps_iter_prev, &
3124 : MAX(scf_env%block_davidson_env(1)%eps_iter, &
3125 0 : 0.1_dp*scf_env%block_davidson_env(1)%eps_iter_used))
3126 : ELSE
3127 21897 : IF (output_unit > 0) THEN
3128 : WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
3129 11120 : "*** SCF run converged in ", scf_env%iter_count, " steps ***"
3130 : END IF
3131 21897 : inner_loop_converged = .TRUE.
3132 21897 : exit_inner_loop = .TRUE.
3133 : END IF
3134 209810 : ELSE IF (should_stop .OR. scf_env%iter_count >= scf_control%max_scf) THEN
3135 4098 : inner_loop_converged = .FALSE.
3136 4098 : IF (just_energy) THEN
3137 908 : exit_inner_loop = .FALSE.
3138 : ELSE
3139 3190 : exit_inner_loop = .TRUE.
3140 3190 : IF (output_unit > 0) THEN
3141 : WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
3142 1601 : "Leaving inner SCF loop after reaching ", scf_env%iter_count, " steps."
3143 : END IF
3144 : END IF
3145 : END IF
3146 :
3147 231707 : END SUBROUTINE qs_scf_check_inner_exit
3148 :
3149 : ! **************************************************************************************************
3150 : !> \brief undoing density mixing. Important upon convergence
3151 : !> \param scf_env ...
3152 : !> \param rho ...
3153 : !> \param dft_control ...
3154 : !> \param para_env ...
3155 : !> \param diis_step ...
3156 : ! **************************************************************************************************
3157 25087 : SUBROUTINE qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
3158 : TYPE(qs_scf_env_type), POINTER :: scf_env
3159 : TYPE(qs_rho_type), POINTER :: rho
3160 : TYPE(dft_control_type), POINTER :: dft_control
3161 : TYPE(mp_para_env_type), POINTER :: para_env
3162 : LOGICAL :: diis_step
3163 :
3164 : CHARACTER(len=default_string_length) :: name
3165 : INTEGER :: ic, ispin, nc
3166 25087 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp
3167 :
3168 25087 : NULLIFY (rho_ao_kp)
3169 :
3170 25087 : IF (scf_env%mixing_method > 0) THEN
3171 17510 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
3172 17510 : nc = SIZE(scf_env%p_mix_new, 2)
3173 34210 : SELECT CASE (scf_env%mixing_method)
3174 : CASE (direct_mixing_nr)
3175 : CALL scf_env_density_mixing(scf_env%p_mix_new, scf_env%mixing_store, &
3176 : rho_ao_kp, para_env, scf_env%iter_delta, &
3177 : scf_env%iter_count, diis=diis_step, &
3178 16700 : invert=.TRUE.)
3179 159366 : DO ic = 1, nc
3180 319326 : DO ispin = 1, dft_control%nspins
3181 159960 : CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
3182 302626 : CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
3183 : END DO
3184 : END DO
3185 : CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, modified_broyden_mixing_nr, &
3186 : multisecant_mixing_nr, new_pulay_mixing_nr)
3187 63934 : DO ic = 1, nc
3188 92740 : DO ispin = 1, dft_control%nspins
3189 46316 : CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
3190 91930 : CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
3191 : END DO
3192 : END DO
3193 : END SELECT
3194 : END IF
3195 25087 : END SUBROUTINE qs_scf_undo_mixing
3196 :
3197 : ! **************************************************************************************************
3198 : !> \brief Performs the updates rho (takes care of mixing as well)
3199 : !> \param rho ...
3200 : !> \param qs_env ...
3201 : !> \param scf_env ...
3202 : !> \param ks_env ...
3203 : !> \param mix_rho ...
3204 : ! **************************************************************************************************
3205 231719 : SUBROUTINE qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho)
3206 : TYPE(qs_rho_type), POINTER :: rho
3207 : TYPE(qs_environment_type), POINTER :: qs_env
3208 : TYPE(qs_scf_env_type), POINTER :: scf_env
3209 : TYPE(qs_ks_env_type), POINTER :: ks_env
3210 : LOGICAL, INTENT(IN) :: mix_rho
3211 :
3212 : TYPE(mp_para_env_type), POINTER :: para_env
3213 :
3214 231719 : NULLIFY (para_env)
3215 231719 : CALL get_qs_env(qs_env, para_env=para_env)
3216 : ! ** update qs_env%rho
3217 231719 : CALL qs_rho_update_rho(rho, qs_env=qs_env)
3218 : ! ** Density mixing through density matrix or on the reciprocal space grid (exclusive)
3219 231719 : IF (mix_rho) THEN
3220 : CALL gspace_mixing(qs_env, scf_env%mixing_method, scf_env%mixing_store, rho, &
3221 7012 : para_env, scf_env%iter_count)
3222 :
3223 : END IF
3224 231719 : CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
3225 :
3226 231719 : END SUBROUTINE qs_scf_rho_update
3227 :
3228 : ! **************************************************************************************************
3229 : !> \brief Performs the necessary steps before leaving innner scf loop
3230 : !> \param scf_env ...
3231 : !> \param qs_env ...
3232 : !> \param diis_step ...
3233 : !> \param output_unit ...
3234 : ! **************************************************************************************************
3235 25087 : SUBROUTINE qs_scf_inner_finalize(scf_env, qs_env, diis_step, output_unit)
3236 : TYPE(qs_scf_env_type), POINTER :: scf_env
3237 : TYPE(qs_environment_type), POINTER :: qs_env
3238 : LOGICAL :: diis_step
3239 : INTEGER, INTENT(IN) :: output_unit
3240 :
3241 : LOGICAL :: do_kpoints
3242 : TYPE(dft_control_type), POINTER :: dft_control
3243 : TYPE(mp_para_env_type), POINTER :: para_env
3244 : TYPE(qs_energy_type), POINTER :: energy
3245 : TYPE(qs_ks_env_type), POINTER :: ks_env
3246 : TYPE(qs_rho_type), POINTER :: rho
3247 :
3248 25087 : NULLIFY (energy, rho, dft_control, ks_env)
3249 :
3250 : CALL get_qs_env(qs_env=qs_env, energy=energy, ks_env=ks_env, &
3251 : rho=rho, dft_control=dft_control, para_env=para_env, &
3252 25087 : do_kpoints=do_kpoints)
3253 :
3254 25087 : CALL cleanup_scf_loop(scf_env)
3255 :
3256 : ! now, print out energies and charges corresponding to the obtained wfn
3257 : ! (this actually is not 100% consistent at this point)!
3258 25087 : CALL qs_scf_print_summary(output_unit, qs_env)
3259 :
3260 25087 : CALL qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
3261 :
3262 : ! *** update rspace rho since the mo changed
3263 : ! *** this might not always be needed (i.e. no post calculation / no forces )
3264 : ! *** but guarantees that rho and wfn are consistent at this point
3265 25087 : CALL qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho=.FALSE.)
3266 :
3267 25087 : END SUBROUTINE qs_scf_inner_finalize
3268 :
3269 : ! **************************************************************************************************
3270 : !> \brief perform cleanup operations at the end of an scf loop
3271 : !> \param scf_env ...
3272 : !> \par History
3273 : !> 03.2006 created [Joost VandeVondele]
3274 : ! **************************************************************************************************
3275 25087 : SUBROUTINE cleanup_scf_loop(scf_env)
3276 : TYPE(qs_scf_env_type), INTENT(INOUT) :: scf_env
3277 :
3278 : CHARACTER(len=*), PARAMETER :: routineN = 'cleanup_scf_loop'
3279 :
3280 : INTEGER :: handle, ispin
3281 :
3282 25087 : CALL timeset(routineN, handle)
3283 :
3284 32648 : SELECT CASE (scf_env%method)
3285 : CASE (ot_method_nr)
3286 16695 : DO ispin = 1, SIZE(scf_env%qs_ot_env)
3287 16695 : CALL ot_scf_destroy(scf_env%qs_ot_env(ispin))
3288 : END DO
3289 7561 : DEALLOCATE (scf_env%qs_ot_env)
3290 : CASE (ot_diag_method_nr)
3291 : !
3292 : CASE (general_diag_method_nr)
3293 : !
3294 : CASE (special_diag_method_nr)
3295 : !
3296 : CASE (block_krylov_diag_method_nr, block_davidson_diag_method_nr)
3297 : !
3298 : CASE (filter_matrix_diag_method_nr)
3299 : !
3300 : CASE (smeagol_method_nr)
3301 : !
3302 : CASE DEFAULT
3303 : CALL cp_abort(__LOCATION__, &
3304 : "unknown scf method method:"// &
3305 25087 : cp_to_string(scf_env%method))
3306 : END SELECT
3307 :
3308 25087 : CALL timestop(handle)
3309 :
3310 25087 : END SUBROUTINE cleanup_scf_loop
3311 :
3312 430 : END MODULE qs_scf_loop_utils
|