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 : MODULE qs_tddfpt2_forces
9 : USE admm_types, ONLY: admm_type,&
10 : get_admm_env
11 : USE atomic_kind_types, ONLY: atomic_kind_type,&
12 : get_atomic_kind,&
13 : get_atomic_kind_set
14 : USE bibliography, ONLY: Hehn2022,&
15 : Hehn2024,&
16 : Sertcan2024,&
17 : cite_reference
18 : USE cp_control_types, ONLY: dft_control_type,&
19 : tddfpt2_control_type
20 : USE cp_dbcsr_api, ONLY: &
21 : dbcsr_add, dbcsr_complete_redistribute, dbcsr_copy, dbcsr_create, dbcsr_p_type, &
22 : dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric
23 : USE cp_dbcsr_contrib, ONLY: dbcsr_dot
24 : USE cp_dbcsr_cp2k_link, ONLY: cp_dbcsr_alloc_block_from_nbl
25 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
26 : copy_fm_to_dbcsr,&
27 : cp_dbcsr_plus_fm_fm_t,&
28 : cp_dbcsr_sm_fm_multiply,&
29 : dbcsr_allocate_matrix_set,&
30 : dbcsr_deallocate_matrix_set
31 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
32 : cp_fm_struct_release,&
33 : cp_fm_struct_type
34 : USE cp_fm_types, ONLY: cp_fm_copy_general,&
35 : cp_fm_create,&
36 : cp_fm_get_info,&
37 : cp_fm_release,&
38 : cp_fm_set_all,&
39 : cp_fm_type
40 : USE cp_log_handling, ONLY: cp_get_default_logger,&
41 : cp_logger_get_default_unit_nr,&
42 : cp_logger_type
43 : USE exstates_types, ONLY: excited_energy_type,&
44 : exstate_potential_release
45 : USE hartree_local_methods, ONLY: Vh_1c_gg_integrals,&
46 : init_coulomb_local
47 : USE hartree_local_types, ONLY: hartree_local_create,&
48 : hartree_local_release,&
49 : hartree_local_type
50 : USE hfx_energy_potential, ONLY: integrate_four_center
51 : USE hfx_ri, ONLY: hfx_ri_update_ks
52 : USE hfx_types, ONLY: hfx_type
53 : USE input_constants, ONLY: do_admm_aux_exch_func_none,&
54 : no_sf_tddfpt,&
55 : oe_shift,&
56 : tddfpt_kernel_full,&
57 : tddfpt_kernel_none,&
58 : tddfpt_kernel_stda
59 : USE input_section_types, ONLY: section_get_lval,&
60 : section_vals_get,&
61 : section_vals_get_subs_vals,&
62 : section_vals_type,&
63 : section_vals_val_get
64 : USE kinds, ONLY: default_string_length,&
65 : dp
66 : USE message_passing, ONLY: mp_para_env_type
67 : USE mulliken, ONLY: ao_charges
68 : USE parallel_gemm_api, ONLY: parallel_gemm
69 : USE particle_types, ONLY: particle_type
70 : USE pw_env_types, ONLY: pw_env_get,&
71 : pw_env_type
72 : USE pw_methods, ONLY: pw_axpy,&
73 : pw_scale,&
74 : pw_transfer,&
75 : pw_zero
76 : USE pw_poisson_methods, ONLY: pw_poisson_solve
77 : USE pw_poisson_types, ONLY: pw_poisson_type
78 : USE pw_pool_types, ONLY: pw_pool_type
79 : USE pw_types, ONLY: pw_c1d_gs_type,&
80 : pw_r3d_rs_type
81 : USE qs_collocate_density, ONLY: calculate_rho_elec
82 : USE qs_density_matrices, ONLY: calculate_wx_matrix,&
83 : calculate_xwx_matrix
84 : USE qs_environment_types, ONLY: get_qs_env,&
85 : qs_environment_type,&
86 : set_qs_env
87 : USE qs_force_types, ONLY: allocate_qs_force,&
88 : deallocate_qs_force,&
89 : qs_force_type,&
90 : sum_qs_force,&
91 : total_qs_force,&
92 : zero_qs_force
93 : USE qs_fxc, ONLY: qs_fxc_analytic,&
94 : qs_fxc_fdiff
95 : USE qs_gapw_densities, ONLY: prepare_gapw_den
96 : USE qs_integrate_potential, ONLY: integrate_v_rspace
97 : USE qs_kernel_types, ONLY: kernel_env_type
98 : USE qs_kind_types, ONLY: get_qs_kind,&
99 : get_qs_kind_set,&
100 : qs_kind_type
101 : USE qs_ks_atom, ONLY: update_ks_atom
102 : USE qs_ks_reference, ONLY: ks_ref_potential,&
103 : ks_ref_potential_atom
104 : USE qs_ks_types, ONLY: qs_ks_env_type
105 : USE qs_local_rho_types, ONLY: local_rho_set_create,&
106 : local_rho_set_release,&
107 : local_rho_type
108 : USE qs_mo_types, ONLY: get_mo_set,&
109 : mo_set_type
110 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
111 : USE qs_oce_types, ONLY: oce_matrix_type
112 : USE qs_overlap, ONLY: build_overlap_matrix
113 : USE qs_rho0_ggrid, ONLY: integrate_vhg0_rspace,&
114 : rho0_s_grid_create
115 : USE qs_rho0_methods, ONLY: init_rho0
116 : USE qs_rho0_types, ONLY: get_rho0_mpole
117 : USE qs_rho_atom_methods, ONLY: allocate_rho_atom_internals,&
118 : calculate_rho_atom_coeff
119 : USE qs_rho_atom_types, ONLY: rho_atom_type
120 : USE qs_rho_types, ONLY: qs_rho_create,&
121 : qs_rho_get,&
122 : qs_rho_set,&
123 : qs_rho_type
124 : USE qs_tddfpt2_fhxc_forces, ONLY: fhxc_force,&
125 : stda_force
126 : USE qs_tddfpt2_subgroups, ONLY: tddfpt_subgroup_env_type
127 : USE qs_tddfpt2_types, ONLY: tddfpt_ground_state_mos,&
128 : tddfpt_work_matrices
129 : USE qs_vxc_atom, ONLY: calculate_xc_2nd_deriv_atom
130 : USE task_list_types, ONLY: task_list_type
131 : USE xtb_ehess, ONLY: xtb_coulomb_hessian
132 : USE xtb_types, ONLY: get_xtb_atom_param,&
133 : xtb_atom_type
134 : #include "./base/base_uses.f90"
135 :
136 : IMPLICIT NONE
137 :
138 : PRIVATE
139 :
140 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_forces'
141 :
142 : PUBLIC :: tddfpt_forces_main
143 :
144 : ! **************************************************************************************************
145 :
146 : CONTAINS
147 :
148 : ! **************************************************************************************************
149 : !> \brief Perform TDDFPT gradient calculation. This routine calculates the response vector R of Eq. 49
150 : !> in J. Chem. Theory Comput. 2022, 18, 4186−4202 (https://doi.org/10.1021/acs.jctc.2c00144)
151 : !> in ex_env%cpmos and a few contributions to the gradient.
152 : !> \param qs_env Quickstep environment
153 : !> \param gs_mos ...
154 : !> \param ex_env Holds: Response vector ex_env%cpmos = R
155 : !> Difference density ex_env%matrix_pe = T
156 : !> Matrix ex_env%matrix_hz = H_munu[T]
157 : !> \param kernel_env ...
158 : !> \param sub_env ...
159 : !> \param work_matrices ...
160 : !> \par History
161 : !> * 10.2022 created JHU
162 : ! **************************************************************************************************
163 652 : SUBROUTINE tddfpt_forces_main(qs_env, gs_mos, ex_env, kernel_env, sub_env, work_matrices)
164 : TYPE(qs_environment_type), POINTER :: qs_env
165 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
166 : POINTER :: gs_mos
167 : TYPE(excited_energy_type), POINTER :: ex_env
168 : TYPE(kernel_env_type) :: kernel_env
169 : TYPE(tddfpt_subgroup_env_type) :: sub_env
170 : TYPE(tddfpt_work_matrices) :: work_matrices
171 :
172 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_forces_main'
173 :
174 : INTEGER :: handle, ispin, nspins, spin
175 : LOGICAL :: do_sf
176 : TYPE(admm_type), POINTER :: admm_env
177 : TYPE(cp_fm_struct_type), POINTER :: matrix_struct
178 652 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe_asymm, matrix_pe_symm, &
179 652 : matrix_s, matrix_s_aux_fit
180 : TYPE(dft_control_type), POINTER :: dft_control
181 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
182 :
183 652 : CALL timeset(routineN, handle)
184 :
185 652 : CALL get_qs_env(qs_env, dft_control=dft_control)
186 :
187 652 : CALL cite_reference(Hehn2022)
188 652 : CALL cite_reference(Hehn2024)
189 652 : IF (dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc) CALL cite_reference(Sertcan2024)
190 :
191 652 : nspins = dft_control%nspins
192 652 : tddfpt_control => dft_control%tddfpt2_control
193 652 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
194 640 : do_sf = .FALSE.
195 : ELSE
196 12 : do_sf = .TRUE.
197 : END IF
198 :
199 : ! disable RES-TDDFPT for now
200 1412 : DO ispin = 1, nspins
201 1412 : IF (gs_mos(ispin)%nmo_occ /= gs_mos(ispin)%nmo_active) THEN
202 0 : CALL cp_abort(__LOCATION__, "RES-TDDFPT Forces NYA")
203 : END IF
204 : END DO
205 :
206 : ! rhs of linres equation
207 652 : IF (ASSOCIATED(ex_env%cpmos)) THEN
208 522 : DO ispin = 1, SIZE(ex_env%cpmos)
209 522 : CALL cp_fm_release(ex_env%cpmos(ispin))
210 : END DO
211 236 : DEALLOCATE (ex_env%cpmos)
212 : END IF
213 2716 : ALLOCATE (ex_env%cpmos(nspins))
214 : ! Create and initialize rectangular matrices of nao*occ dimension for alpha and beta R vectors
215 : ! for the Z-vector equation system: AZ=-R
216 1412 : DO ispin = 1, nspins
217 760 : CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=matrix_struct)
218 760 : CALL cp_fm_create(ex_env%cpmos(ispin), matrix_struct)
219 1412 : CALL cp_fm_set_all(ex_env%cpmos(ispin), 0.0_dp)
220 : END DO
221 652 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
222 652 : NULLIFY (matrix_pe_asymm, matrix_pe_symm)
223 :
224 : ! Build difference density matrix_pe = X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
225 : !
226 652 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe, nspins)
227 652 : CALL dbcsr_allocate_matrix_set(matrix_pe_symm, nspins)
228 652 : CALL dbcsr_allocate_matrix_set(matrix_pe_asymm, nspins)
229 1412 : DO ispin = 1, nspins
230 :
231 : ! Initialize matrix_pe as a sparse matrix with zeros
232 760 : ALLOCATE (ex_env%matrix_pe(ispin)%matrix)
233 760 : CALL dbcsr_create(ex_env%matrix_pe(ispin)%matrix, template=matrix_s(1)%matrix)
234 760 : CALL dbcsr_copy(ex_env%matrix_pe(ispin)%matrix, matrix_s(1)%matrix)
235 760 : CALL dbcsr_set(ex_env%matrix_pe(ispin)%matrix, 0.0_dp)
236 :
237 760 : ALLOCATE (matrix_pe_symm(ispin)%matrix)
238 760 : CALL dbcsr_create(matrix_pe_symm(ispin)%matrix, template=matrix_s(1)%matrix)
239 760 : CALL dbcsr_copy(matrix_pe_symm(ispin)%matrix, ex_env%matrix_pe(ispin)%matrix)
240 :
241 760 : ALLOCATE (matrix_pe_asymm(ispin)%matrix)
242 : CALL dbcsr_create(matrix_pe_asymm(ispin)%matrix, template=matrix_s(1)%matrix, &
243 760 : matrix_type=dbcsr_type_antisymmetric)
244 760 : CALL dbcsr_complete_redistribute(ex_env%matrix_pe(ispin)%matrix, matrix_pe_asymm(ispin)%matrix)
245 :
246 760 : IF (do_sf) THEN
247 : spin = 1
248 : ELSE
249 736 : spin = ispin
250 : END IF
251 : ! Add difference density to matrix_pe
252 : CALL tddfpt_resvec1(ex_env%evect(spin), gs_mos(spin)%mos_active, &
253 1412 : matrix_s(1)%matrix, ex_env%matrix_pe(ispin)%matrix, ispin, do_sf)
254 : END DO
255 : !
256 : ! Project the difference density into auxiliary basis for ADMM
257 652 : IF (dft_control%do_admm) THEN
258 140 : CALL get_qs_env(qs_env, admm_env=admm_env)
259 140 : CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
260 140 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe_admm, nspins)
261 300 : DO ispin = 1, nspins
262 160 : ALLOCATE (ex_env%matrix_pe_admm(ispin)%matrix)
263 160 : CALL dbcsr_create(ex_env%matrix_pe_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
264 160 : CALL dbcsr_copy(ex_env%matrix_pe_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
265 160 : CALL dbcsr_set(ex_env%matrix_pe_admm(ispin)%matrix, 0.0_dp)
266 : CALL tddfpt_resvec1_admm(ex_env%matrix_pe(ispin)%matrix, &
267 300 : admm_env, ex_env%matrix_pe_admm(ispin)%matrix)
268 : END DO
269 : END IF
270 : !
271 652 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_hz, nspins)
272 1412 : DO ispin = 1, nspins
273 760 : ALLOCATE (ex_env%matrix_hz(ispin)%matrix)
274 760 : CALL dbcsr_create(ex_env%matrix_hz(ispin)%matrix, template=matrix_s(1)%matrix)
275 760 : CALL dbcsr_copy(ex_env%matrix_hz(ispin)%matrix, matrix_s(1)%matrix)
276 1412 : CALL dbcsr_set(ex_env%matrix_hz(ispin)%matrix, 0.0_dp)
277 : END DO
278 : ! Calculate first term of R vector: H_{\mu i\sigma}[T]
279 652 : IF (dft_control%qs_control%xtb) THEN
280 16 : CALL tddfpt_resvec2_xtb(qs_env, ex_env%matrix_pe, gs_mos, ex_env%matrix_hz, ex_env%cpmos)
281 : ELSE
282 : CALL tddfpt_resvec2(qs_env, ex_env%matrix_pe, ex_env%matrix_pe_admm, &
283 636 : gs_mos, ex_env%matrix_hz, ex_env%cpmos)
284 : END IF
285 : !
286 652 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1, SIZE(ex_env%evect, 1))
287 652 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_asymm, SIZE(ex_env%evect, 1))
288 1400 : DO ispin = 1, SIZE(ex_env%evect, 1)
289 748 : ALLOCATE (ex_env%matrix_px1(ispin)%matrix)
290 748 : CALL dbcsr_create(ex_env%matrix_px1(ispin)%matrix, template=matrix_s(1)%matrix)
291 748 : CALL dbcsr_copy(ex_env%matrix_px1(ispin)%matrix, matrix_s(1)%matrix)
292 748 : CALL dbcsr_set(ex_env%matrix_px1(ispin)%matrix, 0.0_dp)
293 :
294 748 : ALLOCATE (ex_env%matrix_px1_asymm(ispin)%matrix)
295 : CALL dbcsr_create(ex_env%matrix_px1_asymm(ispin)%matrix, template=matrix_s(1)%matrix, &
296 748 : matrix_type=dbcsr_type_antisymmetric)
297 1400 : CALL dbcsr_complete_redistribute(ex_env%matrix_px1(ispin)%matrix, ex_env%matrix_px1_asymm(ispin)%matrix)
298 : END DO
299 : ! Kernel ADMM
300 652 : IF (tddfpt_control%do_admm) THEN
301 76 : CALL get_qs_env(qs_env, admm_env=admm_env)
302 76 : CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
303 76 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm, SIZE(ex_env%evect, 1))
304 76 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm_asymm, SIZE(ex_env%evect, 1))
305 156 : DO ispin = 1, SIZE(ex_env%evect, 1)
306 80 : ALLOCATE (ex_env%matrix_px1_admm(ispin)%matrix)
307 80 : CALL dbcsr_create(ex_env%matrix_px1_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
308 80 : CALL dbcsr_copy(ex_env%matrix_px1_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
309 80 : CALL dbcsr_set(ex_env%matrix_px1_admm(ispin)%matrix, 0.0_dp)
310 :
311 80 : ALLOCATE (ex_env%matrix_px1_admm_asymm(ispin)%matrix)
312 : CALL dbcsr_create(ex_env%matrix_px1_admm_asymm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix, &
313 80 : matrix_type=dbcsr_type_antisymmetric)
314 : CALL dbcsr_complete_redistribute(ex_env%matrix_px1_admm(ispin)%matrix, &
315 156 : ex_env%matrix_px1_admm_asymm(ispin)%matrix)
316 : END DO
317 : END IF
318 : ! TDA forces. Calculates and adds all missing terms for the response vector, Eq. 49.
319 652 : CALL tddfpt_forces(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices)
320 : ! Rotate res vector cpmos into original frame of occupied orbitals.
321 652 : CALL tddfpt_resvec3(qs_env, ex_env%cpmos, work_matrices)
322 :
323 652 : CALL dbcsr_deallocate_matrix_set(matrix_pe_symm)
324 652 : CALL dbcsr_deallocate_matrix_set(matrix_pe_asymm)
325 :
326 652 : CALL timestop(handle)
327 :
328 652 : END SUBROUTINE tddfpt_forces_main
329 :
330 : ! **************************************************************************************************
331 : !> \brief Calculate direct tddft forces
332 : !> \param qs_env ...
333 : !> \param ex_env ...
334 : !> \param gs_mos ...
335 : !> \param kernel_env ...
336 : !> \param sub_env ...
337 : !> \param work_matrices ...
338 : !> \par History
339 : !> * 01.2020 screated [JGH]
340 : ! **************************************************************************************************
341 652 : SUBROUTINE tddfpt_forces(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices)
342 :
343 : TYPE(qs_environment_type), POINTER :: qs_env
344 : TYPE(excited_energy_type), POINTER :: ex_env
345 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
346 : POINTER :: gs_mos
347 : TYPE(kernel_env_type), INTENT(IN) :: kernel_env
348 : TYPE(tddfpt_subgroup_env_type) :: sub_env
349 : TYPE(tddfpt_work_matrices) :: work_matrices
350 :
351 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_forces'
352 :
353 : INTEGER :: handle
354 652 : INTEGER, ALLOCATABLE, DIMENSION(:) :: natom_of_kind
355 : LOGICAL :: debug_forces
356 : REAL(KIND=dp) :: ehartree, exc
357 652 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
358 : TYPE(dft_control_type), POINTER :: dft_control
359 652 : TYPE(qs_force_type), DIMENSION(:), POINTER :: ks_force, td_force
360 :
361 652 : CALL timeset(routineN, handle)
362 :
363 : ! for extended debug output
364 652 : debug_forces = ex_env%debug_forces
365 : ! prepare force array
366 : CALL get_qs_env(qs_env, dft_control=dft_control, force=ks_force, &
367 652 : atomic_kind_set=atomic_kind_set)
368 652 : CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, natom_of_kind=natom_of_kind)
369 652 : NULLIFY (td_force)
370 652 : CALL allocate_qs_force(td_force, natom_of_kind)
371 652 : DEALLOCATE (natom_of_kind)
372 652 : CALL zero_qs_force(td_force)
373 652 : CALL set_qs_env(qs_env, force=td_force)
374 : !
375 652 : IF (dft_control%qs_control%xtb) THEN
376 : CALL tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, &
377 16 : work_matrices, debug_forces)
378 : ELSE
379 : !
380 636 : CALL exstate_potential_release(ex_env)
381 : ! Build the values of hartree, fock and exchange-correlation potential on the grid
382 : CALL ks_ref_potential(qs_env, ex_env%vh_rspace, ex_env%vxc_rspace, &
383 636 : ex_env%vtau_rspace, ex_env%vadmm_rspace, ehartree, exc)
384 : CALL ks_ref_potential_atom(qs_env, ex_env%local_rho_set, ex_env%local_rho_set_admm, &
385 636 : ex_env%vh_rspace)
386 : CALL tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, &
387 636 : work_matrices, debug_forces)
388 : END IF
389 : !
390 : ! add TD and KS forces
391 652 : CALL get_qs_env(qs_env, force=td_force)
392 652 : CALL sum_qs_force(ks_force, td_force)
393 652 : CALL set_qs_env(qs_env, force=ks_force)
394 652 : CALL deallocate_qs_force(td_force)
395 : !
396 652 : CALL timestop(handle)
397 :
398 652 : END SUBROUTINE tddfpt_forces
399 :
400 : ! **************************************************************************************************
401 : !> \brief Calculate direct tddft forces.
402 : !> J. Chem. Theory Comput. 2022, 18, 7, 4186–4202 (https://doi.org/10.1021/acs.jctc.2c00144)
403 : !> \param qs_env ...
404 : !> \param ex_env Holds on exit
405 : !> cpmos = R, Response vector, Eq. 49.
406 : !> matrix_pe = T, Difference density, Eq. 44.
407 : !> matrix_wx1 = CK[D^X]X^T, Third term of Eq. 51.
408 : !> matrix_wz = CX^T(\omegaS - K)XC^T, Last term of Eq. 51.
409 : !> \param gs_mos ...
410 : !> \param kernel_env ...
411 : !> \param sub_env ...
412 : !> \param work_matrices ...
413 : !> \param debug_forces ...
414 : !> \par History
415 : !> * 01.2020 screated [JGH]
416 : ! **************************************************************************************************
417 652 : SUBROUTINE tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, &
418 : debug_forces)
419 :
420 : TYPE(qs_environment_type), POINTER :: qs_env
421 : TYPE(excited_energy_type), POINTER :: ex_env
422 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
423 : POINTER :: gs_mos
424 : TYPE(kernel_env_type), INTENT(IN) :: kernel_env
425 : TYPE(tddfpt_subgroup_env_type) :: sub_env
426 : TYPE(tddfpt_work_matrices) :: work_matrices
427 : LOGICAL :: debug_forces
428 :
429 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_force_direct'
430 :
431 : INTEGER :: handle, iounit, ispin, nact, natom, &
432 : nspins, spin
433 : LOGICAL :: do_sf
434 : REAL(KIND=dp) :: evalue
435 652 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ftot1, ftot2
436 : REAL(KIND=dp), DIMENSION(3) :: fodeb
437 652 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
438 652 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: evect
439 : TYPE(cp_logger_type), POINTER :: logger
440 652 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s, matrix_wx1, &
441 652 : matrix_wz, scrm
442 : TYPE(dft_control_type), POINTER :: dft_control
443 : TYPE(mp_para_env_type), POINTER :: para_env
444 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
445 652 : POINTER :: sab_orb
446 652 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
447 : TYPE(qs_ks_env_type), POINTER :: ks_env
448 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
449 :
450 652 : CALL timeset(routineN, handle)
451 :
452 652 : logger => cp_get_default_logger()
453 652 : IF (logger%para_env%is_source()) THEN
454 326 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
455 : ELSE
456 : iounit = -1
457 : END IF
458 :
459 652 : evect => ex_env%evect
460 :
461 : CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, para_env=para_env, &
462 652 : sab_orb=sab_orb, dft_control=dft_control, force=force)
463 652 : NULLIFY (tddfpt_control)
464 652 : tddfpt_control => dft_control%tddfpt2_control
465 652 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
466 : do_sf = .FALSE.
467 : ELSE
468 12 : do_sf = .TRUE.
469 : END IF
470 652 : nspins = dft_control%nspins
471 :
472 652 : IF (debug_forces) THEN
473 116 : CALL get_qs_env(qs_env, natom=natom, atomic_kind_set=atomic_kind_set)
474 348 : ALLOCATE (ftot1(3, natom))
475 116 : CALL total_qs_force(ftot1, force, atomic_kind_set)
476 : END IF
477 :
478 : ! Build last terms of the response vector, Eq. 49, and third term of Lambda_munu, Eq. 51.
479 : ! the response vector is in ex_env%cpmos and Lambda is in ex_env%matrix_wx1
480 652 : CALL tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
481 :
482 : ! Overlap matrix, build the Lambda matrix, Eq. 51.
483 652 : NULLIFY (matrix_wx1, matrix_wz)
484 652 : CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
485 652 : matrix_wx1 => ex_env%matrix_wx1
486 652 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
487 1412 : DO ispin = 1, nspins
488 760 : IF (do_sf) THEN
489 : spin = 1
490 : ELSE
491 736 : spin = ispin
492 : END IF
493 : ! Create and initialize the Lambda matrix as a sparse matrix
494 760 : ALLOCATE (matrix_wz(ispin)%matrix)
495 760 : CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
496 760 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
497 760 : CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
498 : ! For spin-flip excitations only the beta component of the Lambda matrix
499 : ! contains the excitation energy term
500 760 : IF (.NOT. (do_sf .AND. (ispin == 1))) THEN
501 748 : CALL cp_fm_get_info(evect(spin), ncol_global=nact)
502 748 : CALL cp_dbcsr_plus_fm_fm_t(matrix_wz(ispin)%matrix, matrix_v=evect(spin), ncol=nact)
503 748 : evalue = ex_env%evalue
504 748 : IF (tddfpt_control%oe_corr == oe_shift) THEN
505 4 : evalue = ex_env%evalue - tddfpt_control%ev_shift
506 : END IF
507 748 : CALL dbcsr_scale(matrix_wz(ispin)%matrix, evalue)
508 : END IF
509 : ! For spin-flip excitations only the alpha component of the Lambda matrix
510 : ! contains the occupied MO energy term
511 1412 : IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
512 : CALL calculate_wx_matrix(gs_mos(ispin)%mos_active, evect(spin), matrix_ks(ispin)%matrix, &
513 748 : matrix_wz(ispin)%matrix)
514 : END IF
515 : END DO
516 652 : IF (nspins == 2) THEN
517 : CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
518 108 : alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
519 : END IF
520 652 : NULLIFY (scrm)
521 1000 : IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
522 : ! Calculate the force contribution of matrix_xz into the force in ks_env.
523 : ! force%overlap = Tr(dS*matrix_wz), last term of Eq. 51.
524 : CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
525 : matrix_name="OVERLAP MATRIX", &
526 : basis_type_a="ORB", basis_type_b="ORB", &
527 : sab_nl=sab_orb, calculate_forces=.TRUE., &
528 652 : matrix_p=matrix_wz(1)%matrix)
529 652 : CALL dbcsr_deallocate_matrix_set(scrm)
530 652 : CALL dbcsr_deallocate_matrix_set(matrix_wz)
531 652 : IF (debug_forces) THEN
532 464 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
533 116 : CALL para_env%sum(fodeb)
534 116 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: Wx*dS ", fodeb
535 : END IF
536 :
537 : ! Overlap matrix. Build a part of the first term of Lamda, Eq. 51, corresponding to
538 : ! the second term of Eq. 41. matrix_wz = C*X^T*(omega*S - K)*X*C^T
539 652 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
540 652 : NULLIFY (matrix_wz)
541 652 : CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
542 1412 : DO ispin = 1, nspins
543 760 : ALLOCATE (matrix_wz(ispin)%matrix)
544 760 : CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
545 760 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
546 760 : CALL dbcsr_set(matrix_wz(ispin)%matrix, 0.0_dp)
547 : ! For spin-flip excitations only the alpha component of Lambda has contributions
548 : ! of this term, so skip beta
549 1412 : IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
550 748 : evalue = ex_env%evalue
551 748 : IF (tddfpt_control%oe_corr == oe_shift) THEN
552 4 : evalue = ex_env%evalue - tddfpt_control%ev_shift
553 : END IF
554 748 : IF (do_sf) THEN
555 : spin = 2
556 : ELSE
557 736 : spin = ispin
558 : END IF
559 : CALL calculate_xwx_matrix(gs_mos(ispin)%mos_active, evect(ispin), matrix_s(1)%matrix, &
560 748 : matrix_ks(spin)%matrix, matrix_wz(ispin)%matrix, evalue)
561 : END IF
562 : END DO
563 652 : IF (nspins == 2) THEN
564 : CALL dbcsr_add(matrix_wz(1)%matrix, matrix_wz(2)%matrix, &
565 108 : alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
566 : END IF
567 652 : NULLIFY (scrm)
568 1000 : IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
569 : CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
570 : matrix_name="OVERLAP MATRIX", &
571 : basis_type_a="ORB", basis_type_b="ORB", &
572 : sab_nl=sab_orb, calculate_forces=.TRUE., &
573 652 : matrix_p=matrix_wz(1)%matrix)
574 652 : CALL dbcsr_deallocate_matrix_set(scrm)
575 652 : CALL dbcsr_deallocate_matrix_set(matrix_wz)
576 652 : IF (debug_forces) THEN
577 464 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
578 116 : CALL para_env%sum(fodeb)
579 116 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: xWx*dS ", fodeb
580 : END IF
581 :
582 : ! Compute force contribution of the first term of Eq. 41 in the first term of Eq. 51
583 : ! that was calculated in tddfpt_kernel_force,
584 : ! force%overlap = 0.5C*H[T]*C^T
585 652 : IF (ASSOCIATED(matrix_wx1)) THEN
586 574 : IF (nspins == 2 .AND. .NOT. do_sf) THEN
587 : CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
588 96 : alpha_scalar=0.5_dp, beta_scalar=0.5_dp)
589 478 : ELSE IF (nspins == 2 .AND. do_sf) THEN
590 : CALL dbcsr_add(matrix_wx1(1)%matrix, matrix_wx1(2)%matrix, &
591 12 : alpha_scalar=1.0_dp, beta_scalar=1.0_dp)
592 : END IF
593 574 : NULLIFY (scrm)
594 886 : IF (debug_forces) fodeb(1:3) = force(1)%overlap(1:3, 1)
595 : CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
596 : matrix_name="OVERLAP MATRIX", &
597 : basis_type_a="ORB", basis_type_b="ORB", &
598 : sab_nl=sab_orb, calculate_forces=.TRUE., &
599 574 : matrix_p=matrix_wx1(1)%matrix)
600 574 : CALL dbcsr_deallocate_matrix_set(scrm)
601 574 : IF (debug_forces) THEN
602 416 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
603 104 : CALL para_env%sum(fodeb)
604 104 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: D^XKP*dS ", fodeb
605 : END IF
606 : END IF
607 :
608 652 : IF (debug_forces) THEN
609 348 : ALLOCATE (ftot2(3, natom))
610 116 : CALL total_qs_force(ftot2, force, atomic_kind_set)
611 464 : fodeb(1:3) = ftot2(1:3, 1) - ftot1(1:3, 1)
612 116 : CALL para_env%sum(fodeb)
613 116 : IF (iounit > 0) WRITE (iounit, "(T3,A,T30,3F16.8)") "DEBUG:: Excitation Force", fodeb
614 116 : DEALLOCATE (ftot1, ftot2)
615 : END IF
616 :
617 652 : CALL timestop(handle)
618 :
619 1304 : END SUBROUTINE tddfpt_force_direct
620 :
621 : ! **************************************************************************************************
622 : !> \brief Build the spin difference density,
623 : !> matrix_pe = matrix_pe + X*X^T - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
624 : !> \param evect ...
625 : !> \param mos_active ...
626 : !> \param matrix_s ...
627 : !> \param matrix_pe ...
628 : !> \param spin ...
629 : !> \param do_sf ...
630 : ! **************************************************************************************************
631 3040 : SUBROUTINE tddfpt_resvec1(evect, mos_active, matrix_s, matrix_pe, spin, do_sf)
632 :
633 : TYPE(cp_fm_type), INTENT(IN) :: evect, mos_active
634 : TYPE(dbcsr_type), POINTER :: matrix_s, matrix_pe
635 : INTEGER, INTENT(IN) :: spin
636 : LOGICAL, INTENT(IN) :: do_sf
637 :
638 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec1'
639 :
640 : INTEGER :: handle, iounit, nact, nao, norb
641 : REAL(KIND=dp) :: tmp
642 : TYPE(cp_fm_struct_type), POINTER :: fmstruct, fmstruct2
643 : TYPE(cp_fm_type) :: cxmat, xxmat
644 : TYPE(cp_logger_type), POINTER :: logger
645 :
646 760 : CALL timeset(routineN, handle)
647 760 : CALL cp_fm_get_info(mos_active, nrow_global=nao, ncol_global=norb)
648 760 : CALL cp_fm_get_info(evect, nrow_global=nao, ncol_global=nact)
649 760 : CPASSERT(norb == nact)
650 :
651 : ! matrix_pe = X*X^T
652 760 : IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 2))) THEN
653 748 : CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=evect, ncol=norb)
654 : END IF
655 :
656 : ! matrix_pe = matrix_pe - (C*X^T*S*X*C^T + (C*X^T*S*X*C^T)^T)/2
657 760 : IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 1))) THEN
658 748 : CALL cp_fm_get_info(evect, matrix_struct=fmstruct)
659 748 : NULLIFY (fmstruct2)
660 : CALL cp_fm_struct_create(fmstruct=fmstruct2, template_fmstruct=fmstruct, &
661 748 : nrow_global=norb, ncol_global=norb)
662 748 : CALL cp_fm_create(xxmat, matrix_struct=fmstruct2)
663 748 : CALL cp_fm_struct_release(fmstruct2)
664 748 : CALL cp_fm_create(cxmat, matrix_struct=fmstruct)
665 : ! S*X
666 748 : CALL cp_dbcsr_sm_fm_multiply(matrix_s, evect, cxmat, norb, alpha=1.0_dp, beta=0.0_dp)
667 : ! (S*X)^T*X
668 748 : CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, cxmat, evect, 0.0_dp, xxmat)
669 : ! C*X^T*S*X
670 748 : CALL parallel_gemm('N', 'N', nao, norb, norb, 1.0_dp, mos_active, xxmat, 0.0_dp, cxmat)
671 748 : CALL cp_fm_release(xxmat)
672 : ! matrix_pe = matrix_pe - (C*(C^T*X^T*S*X)^T + C^T*(C^T*X^T*S*X))/2
673 : CALL cp_dbcsr_plus_fm_fm_t(matrix_pe, matrix_v=mos_active, matrix_g=cxmat, &
674 748 : ncol=norb, alpha=-1.0_dp, symmetry_mode=1)
675 748 : CALL cp_fm_release(cxmat)
676 : END IF
677 : !
678 : ! Test for Tr(Pe*S)=0
679 760 : CALL dbcsr_dot(matrix_pe, matrix_s, tmp)
680 760 : IF (.NOT. do_sf) THEN
681 736 : IF (ABS(tmp) > 1.e-08_dp) THEN
682 0 : logger => cp_get_default_logger()
683 0 : IF (logger%para_env%is_source()) THEN
684 0 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
685 : ELSE
686 : iounit = -1
687 : END IF
688 0 : CPWARN("Electron count of excitation density matrix is non-zero.")
689 0 : IF (iounit > 0) THEN
690 0 : WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
691 0 : WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
692 : END IF
693 : END IF
694 24 : ELSE IF (spin == 1) THEN
695 12 : IF (ABS(tmp + 1) > 1.e-08_dp) THEN
696 0 : logger => cp_get_default_logger()
697 0 : IF (logger%para_env%is_source()) THEN
698 0 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
699 : ELSE
700 : iounit = -1
701 : END IF
702 0 : CPWARN("Count of occupied occupation number change is not -1.")
703 0 : IF (iounit > 0) THEN
704 0 : WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
705 0 : WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
706 : END IF
707 : END IF
708 12 : ELSE IF (spin == 2) THEN
709 12 : IF (ABS(tmp - 1) > 1.e-08_dp) THEN
710 0 : logger => cp_get_default_logger()
711 0 : IF (logger%para_env%is_source()) THEN
712 0 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
713 : ELSE
714 : iounit = -1
715 : END IF
716 0 : CPWARN("Count of unoccupied occupation number change is not 1.")
717 0 : IF (iounit > 0) THEN
718 0 : WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", tmp
719 0 : WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
720 : END IF
721 : END IF
722 : END IF
723 : !
724 :
725 760 : CALL timestop(handle)
726 :
727 760 : END SUBROUTINE tddfpt_resvec1
728 :
729 : ! **************************************************************************************************
730 : !> \brief PA = A * P * A(T)
731 : !> \param matrix_pe ...
732 : !> \param admm_env ...
733 : !> \param matrix_pe_admm ...
734 : ! **************************************************************************************************
735 160 : SUBROUTINE tddfpt_resvec1_admm(matrix_pe, admm_env, matrix_pe_admm)
736 :
737 : TYPE(dbcsr_type), POINTER :: matrix_pe
738 : TYPE(admm_type), POINTER :: admm_env
739 : TYPE(dbcsr_type), POINTER :: matrix_pe_admm
740 :
741 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec1_admm'
742 :
743 : INTEGER :: handle, nao, nao_aux
744 :
745 160 : CALL timeset(routineN, handle)
746 : !
747 160 : nao_aux = admm_env%nao_aux_fit
748 160 : nao = admm_env%nao_orb
749 : !
750 160 : CALL copy_dbcsr_to_fm(matrix_pe, admm_env%work_orb_orb)
751 : CALL parallel_gemm('N', 'N', nao_aux, nao, nao, &
752 : 1.0_dp, admm_env%A, admm_env%work_orb_orb, 0.0_dp, &
753 160 : admm_env%work_aux_orb)
754 : CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, &
755 : 1.0_dp, admm_env%work_aux_orb, admm_env%A, 0.0_dp, &
756 160 : admm_env%work_aux_aux)
757 160 : CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, matrix_pe_admm, keep_sparsity=.TRUE.)
758 : !
759 160 : CALL timestop(handle)
760 :
761 160 : END SUBROUTINE tddfpt_resvec1_admm
762 :
763 : ! **************************************************************************************************
764 : !> \brief Calculates the action of the H operator as in the first term of equation 49 in
765 : !> https://doi.org/10.1021/acs.jctc.2c00144 (J. Chem. Theory Comput. 2022, 18, 4186−4202)
766 : !> cpmos = H_{\mu i\sigma}[matrix_pe]
767 : !> \param qs_env ...
768 : !> \param matrix_pe Input square matrix with the size of the number of atomic orbitals squared nao^2
769 : !> \param matrix_pe_admm ...
770 : !> \param gs_mos ...
771 : !> \param matrix_hz Holds H_{\mu\nu\sigma}[matrix_pe] on exit
772 : !> \param cpmos ...
773 : ! **************************************************************************************************
774 636 : SUBROUTINE tddfpt_resvec2(qs_env, matrix_pe, matrix_pe_admm, gs_mos, matrix_hz, cpmos)
775 :
776 : TYPE(qs_environment_type), POINTER :: qs_env
777 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe, matrix_pe_admm
778 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
779 : POINTER :: gs_mos
780 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_hz
781 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: cpmos
782 :
783 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec2'
784 :
785 : CHARACTER(LEN=default_string_length) :: basis_type
786 : INTEGER :: handle, iounit, ispin, mspin, n_rep_hf, &
787 : nao, nao_aux, natom, norb, nspins
788 : LOGICAL :: deriv2_analytic, distribute_fock_matrix, &
789 : do_hfx, gapw, gapw_xc, &
790 : hfx_treat_lsd_in_core, &
791 : s_mstruct_changed
792 : REAL(KIND=dp) :: eh1, focc, rhotot, thartree
793 : REAL(KIND=dp), DIMENSION(2) :: total_rho
794 636 : REAL(KIND=dp), DIMENSION(:), POINTER :: Qlm_tot
795 : TYPE(admm_type), POINTER :: admm_env
796 636 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
797 : TYPE(cp_fm_type), POINTER :: mos
798 : TYPE(cp_logger_type), POINTER :: logger
799 636 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: msaux
800 636 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: mhz, mpe
801 : TYPE(dbcsr_type), POINTER :: dbwork
802 : TYPE(dft_control_type), POINTER :: dft_control
803 : TYPE(hartree_local_type), POINTER :: hartree_local
804 636 : TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
805 : TYPE(local_rho_type), POINTER :: local_rho_set, local_rho_set_admm
806 : TYPE(mp_para_env_type), POINTER :: para_env
807 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
808 636 : POINTER :: sab, sab_aux_fit
809 : TYPE(oce_matrix_type), POINTER :: oce
810 : TYPE(pw_c1d_gs_type) :: rho_tot_gspace, v_hartree_gspace
811 636 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g, rho_g_aux, rhoz_g_aux, trho_g, &
812 636 : trho_xc_g
813 : TYPE(pw_env_type), POINTER :: pw_env
814 : TYPE(pw_poisson_type), POINTER :: poisson_env
815 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
816 : TYPE(pw_r3d_rs_type) :: v_hartree_rspace
817 636 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r, rho_r_aux, rhoz_r_aux, tau_r, &
818 636 : trho_r, trho_xc_r, v_xc, v_xc_tau
819 : TYPE(pw_r3d_rs_type), POINTER :: weights
820 636 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
821 : TYPE(qs_ks_env_type), POINTER :: ks_env
822 : TYPE(qs_rho_type), POINTER :: rho, rho_aux_fit, rho_xc, rhoz_aux, trho
823 636 : TYPE(rho_atom_type), DIMENSION(:), POINTER :: rho1_atom_set, rho_atom_set
824 : TYPE(section_vals_type), POINTER :: hfx_section, input, xc_section
825 : TYPE(task_list_type), POINTER :: task_list
826 :
827 636 : CALL timeset(routineN, handle)
828 :
829 636 : NULLIFY (pw_env)
830 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, ks_env=ks_env, &
831 636 : dft_control=dft_control, para_env=para_env)
832 636 : CPASSERT(ASSOCIATED(pw_env))
833 636 : nspins = dft_control%nspins
834 636 : gapw = dft_control%qs_control%gapw
835 636 : gapw_xc = dft_control%qs_control%gapw_xc
836 :
837 636 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_exck)
838 636 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxsr)
839 636 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxlr)
840 :
841 636 : NULLIFY (auxbas_pw_pool, poisson_env)
842 : ! gets the tmp grids
843 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
844 636 : poisson_env=poisson_env)
845 :
846 636 : CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
847 636 : CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
848 636 : CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
849 :
850 4668 : ALLOCATE (trho_r(nspins), trho_g(nspins))
851 1380 : DO ispin = 1, nspins
852 744 : CALL auxbas_pw_pool%create_pw(trho_r(ispin))
853 1380 : CALL auxbas_pw_pool%create_pw(trho_g(ispin))
854 : END DO
855 636 : IF (gapw_xc) THEN
856 130 : ALLOCATE (trho_xc_r(nspins), trho_xc_g(nspins))
857 52 : DO ispin = 1, nspins
858 26 : CALL auxbas_pw_pool%create_pw(trho_xc_r(ispin))
859 52 : CALL auxbas_pw_pool%create_pw(trho_xc_g(ispin))
860 : END DO
861 : END IF
862 :
863 : ! GAPW/GAPW_XC initializations
864 636 : NULLIFY (hartree_local, local_rho_set)
865 636 : IF (gapw) THEN
866 : CALL get_qs_env(qs_env, &
867 : atomic_kind_set=atomic_kind_set, &
868 : natom=natom, &
869 124 : qs_kind_set=qs_kind_set)
870 124 : CALL local_rho_set_create(local_rho_set)
871 : CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
872 124 : qs_kind_set, dft_control, para_env)
873 : CALL init_rho0(local_rho_set, qs_env, dft_control%qs_control%gapw_control, &
874 124 : zcore=0.0_dp)
875 124 : CALL rho0_s_grid_create(pw_env, local_rho_set%rho0_mpole)
876 124 : CALL hartree_local_create(hartree_local)
877 124 : CALL init_coulomb_local(hartree_local, natom)
878 512 : ELSEIF (gapw_xc) THEN
879 : CALL get_qs_env(qs_env, &
880 : atomic_kind_set=atomic_kind_set, &
881 26 : qs_kind_set=qs_kind_set)
882 26 : CALL local_rho_set_create(local_rho_set)
883 : CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
884 26 : qs_kind_set, dft_control, para_env)
885 : END IF
886 :
887 636 : total_rho = 0.0_dp
888 636 : CALL pw_zero(rho_tot_gspace)
889 1380 : DO ispin = 1, nspins
890 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
891 : rho=trho_r(ispin), &
892 : rho_gspace=trho_g(ispin), &
893 : soft_valid=gapw, &
894 744 : total_rho=total_rho(ispin))
895 744 : CALL pw_axpy(trho_g(ispin), rho_tot_gspace)
896 1380 : IF (gapw_xc) THEN
897 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
898 : rho=trho_xc_r(ispin), &
899 : rho_gspace=trho_xc_g(ispin), &
900 : soft_valid=gapw_xc, &
901 26 : total_rho=rhotot)
902 : END IF
903 : END DO
904 :
905 : ! GAPW o GAPW_XC require the calculation of hard and soft local densities
906 636 : IF (gapw .OR. gapw_xc) THEN
907 150 : CALL get_qs_env(qs_env=qs_env, oce=oce, sab_orb=sab)
908 : CALL calculate_rho_atom_coeff(qs_env, matrix_pe, local_rho_set%rho_atom_set, &
909 150 : qs_kind_set, oce, sab, para_env)
910 150 : CALL prepare_gapw_den(qs_env, local_rho_set, do_rho0=gapw)
911 : END IF
912 1908 : rhotot = SUM(total_rho)
913 636 : IF (gapw) THEN
914 124 : CALL get_rho0_mpole(local_rho_set%rho0_mpole, Qlm_tot=Qlm_tot)
915 124 : rhotot = rhotot + local_rho_set%rho0_mpole%total_rho0_h
916 124 : CALL pw_axpy(local_rho_set%rho0_mpole%rho0_s_gs, rho_tot_gspace)
917 124 : IF (ASSOCIATED(local_rho_set%rho0_mpole%rhoz_cneo_s_gs)) THEN
918 0 : CALL pw_axpy(local_rho_set%rho0_mpole%rhoz_cneo_s_gs, rho_tot_gspace)
919 : END IF
920 : END IF
921 :
922 636 : IF (ABS(rhotot) > 1.e-05_dp) THEN
923 24 : logger => cp_get_default_logger()
924 24 : IF (logger%para_env%is_source()) THEN
925 12 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
926 : ELSE
927 : iounit = -1
928 : END IF
929 24 : CPWARN("Real space electron count of excitation density is non-zero.")
930 24 : IF (iounit > 0) THEN
931 12 : WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", rhotot
932 12 : WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
933 : END IF
934 : END IF
935 :
936 : ! calculate associated hartree potential
937 : CALL pw_poisson_solve(poisson_env, rho_tot_gspace, thartree, &
938 636 : v_hartree_gspace)
939 636 : CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
940 636 : CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
941 636 : IF (gapw) THEN
942 : CALL Vh_1c_gg_integrals(qs_env, thartree, hartree_local%ecoul_1c, &
943 124 : local_rho_set, para_env, tddft=.TRUE.)
944 : CALL integrate_vhg0_rspace(qs_env, v_hartree_rspace, para_env, &
945 : calculate_forces=.FALSE., &
946 124 : local_rho_set=local_rho_set)
947 : END IF
948 :
949 : ! Fxc*drho term
950 636 : CALL get_qs_env(qs_env, rho=rho)
951 636 : CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
952 : !
953 636 : CALL get_qs_env(qs_env, input=input)
954 636 : IF (dft_control%do_admm) THEN
955 140 : CALL get_qs_env(qs_env, admm_env=admm_env)
956 140 : xc_section => admm_env%xc_section_primary
957 : ELSE
958 496 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
959 : END IF
960 : !
961 636 : deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
962 636 : IF (deriv2_analytic) THEN
963 636 : NULLIFY (v_xc, v_xc_tau, tau_r)
964 636 : CALL get_qs_env(qs_env=qs_env, xcint_weights=weights)
965 636 : IF (gapw_xc) THEN
966 26 : CALL get_qs_env(qs_env=qs_env, rho_xc=rho_xc)
967 : CALL qs_fxc_analytic(rho_xc, trho_xc_r, tau_r, xc_section, weights, auxbas_pw_pool, &
968 26 : .FALSE., v_xc, v_xc_tau)
969 : ELSE
970 : CALL qs_fxc_analytic(rho, trho_r, tau_r, xc_section, weights, auxbas_pw_pool, &
971 610 : .FALSE., v_xc, v_xc_tau)
972 : END IF
973 636 : IF (gapw .OR. gapw_xc) THEN
974 150 : CALL get_qs_env(qs_env, rho_atom_set=rho_atom_set)
975 150 : rho1_atom_set => local_rho_set%rho_atom_set
976 : CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, para_env, &
977 150 : do_triplet=.FALSE.)
978 : END IF
979 : ELSE
980 0 : CPABORT("NYA 00006")
981 0 : NULLIFY (v_xc, trho)
982 0 : ALLOCATE (trho)
983 0 : CALL qs_rho_create(trho)
984 0 : CALL qs_rho_set(trho, rho_r=trho_r, rho_g=trho_g)
985 0 : CALL qs_fxc_fdiff(ks_env, rho, trho, xc_section, 6, .FALSE., v_xc, v_xc_tau)
986 0 : DEALLOCATE (trho)
987 : END IF
988 :
989 1380 : DO ispin = 1, nspins
990 744 : CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
991 1380 : CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
992 : END DO
993 636 : IF (gapw_xc) THEN
994 52 : DO ispin = 1, nspins
995 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
996 : hmat=matrix_hz(ispin), &
997 26 : calculate_forces=.FALSE.)
998 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
999 : hmat=matrix_hz(ispin), &
1000 52 : gapw=gapw_xc, calculate_forces=.FALSE.)
1001 : END DO
1002 : ELSE
1003 : ! vtot = v_xc(ispin) + v_hartree
1004 1328 : DO ispin = 1, nspins
1005 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
1006 : hmat=matrix_hz(ispin), &
1007 718 : gapw=gapw, calculate_forces=.FALSE.)
1008 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
1009 : hmat=matrix_hz(ispin), &
1010 1328 : gapw=gapw, calculate_forces=.FALSE.)
1011 : END DO
1012 : END IF
1013 636 : IF (gapw .OR. gapw_xc) THEN
1014 150 : mhz(1:nspins, 1:1) => matrix_hz(1:nspins)
1015 150 : mpe(1:nspins, 1:1) => matrix_pe(1:nspins)
1016 : CALL update_ks_atom(qs_env, mhz, mpe, forces=.FALSE., &
1017 150 : rho_atom_external=local_rho_set%rho_atom_set)
1018 : END IF
1019 :
1020 636 : CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
1021 636 : CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
1022 636 : CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
1023 1380 : DO ispin = 1, nspins
1024 744 : CALL auxbas_pw_pool%give_back_pw(trho_r(ispin))
1025 744 : CALL auxbas_pw_pool%give_back_pw(trho_g(ispin))
1026 1380 : CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
1027 : END DO
1028 636 : DEALLOCATE (trho_r, trho_g, v_xc)
1029 636 : IF (gapw_xc) THEN
1030 52 : DO ispin = 1, nspins
1031 26 : CALL auxbas_pw_pool%give_back_pw(trho_xc_r(ispin))
1032 52 : CALL auxbas_pw_pool%give_back_pw(trho_xc_g(ispin))
1033 : END DO
1034 26 : DEALLOCATE (trho_xc_r, trho_xc_g)
1035 : END IF
1036 636 : IF (ASSOCIATED(v_xc_tau)) THEN
1037 0 : DO ispin = 1, nspins
1038 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
1039 : END DO
1040 0 : DEALLOCATE (v_xc_tau)
1041 : END IF
1042 636 : IF (dft_control%do_admm) THEN
1043 140 : IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1044 : ! add ADMM xc_section_aux terms: f_x[rhoz_ADMM]
1045 84 : CALL get_qs_env(qs_env, admm_env=admm_env)
1046 : CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, matrix_s_aux_fit=msaux, &
1047 84 : task_list_aux_fit=task_list)
1048 84 : basis_type = "AUX_FIT"
1049 : !
1050 84 : NULLIFY (mpe, mhz)
1051 428 : ALLOCATE (mpe(nspins, 1))
1052 84 : CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
1053 176 : DO ispin = 1, nspins
1054 92 : ALLOCATE (mhz(ispin, 1)%matrix)
1055 92 : CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
1056 92 : CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
1057 92 : CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
1058 176 : mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
1059 : END DO
1060 : !
1061 : ! GAPW/GAPW_XC initializations
1062 84 : NULLIFY (local_rho_set_admm)
1063 84 : IF (admm_env%do_gapw) THEN
1064 10 : basis_type = "AUX_FIT_SOFT"
1065 10 : task_list => admm_env%admm_gapw_env%task_list
1066 10 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
1067 10 : CALL get_admm_env(admm_env, sab_aux_fit=sab_aux_fit)
1068 10 : CALL local_rho_set_create(local_rho_set_admm)
1069 : CALL allocate_rho_atom_internals(local_rho_set_admm%rho_atom_set, atomic_kind_set, &
1070 10 : admm_env%admm_gapw_env%admm_kind_set, dft_control, para_env)
1071 : CALL calculate_rho_atom_coeff(qs_env, matrix_pe_admm, &
1072 : rho_atom_set=local_rho_set_admm%rho_atom_set, &
1073 : qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
1074 10 : oce=admm_env%admm_gapw_env%oce, sab=sab_aux_fit, para_env=para_env)
1075 : CALL prepare_gapw_den(qs_env, local_rho_set=local_rho_set_admm, &
1076 10 : do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
1077 : END IF
1078 : !
1079 84 : xc_section => admm_env%xc_section_aux
1080 : !
1081 84 : NULLIFY (rho_g_aux, rho_r_aux, rhoz_g_aux, rhoz_r_aux)
1082 84 : CALL qs_rho_get(rho_aux_fit, rho_r=rho_r_aux, rho_g=rho_g_aux)
1083 : ! rhoz_aux
1084 436 : ALLOCATE (rhoz_r_aux(nspins), rhoz_g_aux(nspins))
1085 176 : DO ispin = 1, nspins
1086 92 : CALL auxbas_pw_pool%create_pw(rhoz_r_aux(ispin))
1087 176 : CALL auxbas_pw_pool%create_pw(rhoz_g_aux(ispin))
1088 : END DO
1089 176 : DO ispin = 1, nspins
1090 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=mpe(ispin, 1)%matrix, &
1091 : rho=rhoz_r_aux(ispin), rho_gspace=rhoz_g_aux(ispin), &
1092 : basis_type=basis_type, &
1093 176 : task_list_external=task_list)
1094 : END DO
1095 : !
1096 84 : NULLIFY (v_xc)
1097 84 : deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
1098 84 : IF (deriv2_analytic) THEN
1099 84 : CALL get_qs_env(qs_env=qs_env, xcint_weights=weights)
1100 84 : NULLIFY (tau_r)
1101 : CALL qs_fxc_analytic(rho_aux_fit, rhoz_r_aux, tau_r, xc_section, weights, auxbas_pw_pool, &
1102 84 : .FALSE., v_xc, v_xc_tau)
1103 : ELSE
1104 0 : CPABORT("NYA 00007")
1105 : NULLIFY (rhoz_aux)
1106 0 : ALLOCATE (rhoz_aux)
1107 0 : CALL qs_rho_create(rhoz_aux)
1108 0 : CALL qs_rho_set(rhoz_aux, rho_r=rhoz_r_aux, rho_g=rhoz_g_aux)
1109 0 : CALL qs_fxc_fdiff(ks_env, rho_aux_fit, rhoz_aux, xc_section, 6, .FALSE., v_xc, v_xc_tau)
1110 0 : DEALLOCATE (rhoz_aux)
1111 : END IF
1112 : !
1113 176 : DO ispin = 1, nspins
1114 92 : CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
1115 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
1116 : hmat=mhz(ispin, 1), basis_type=basis_type, &
1117 : calculate_forces=.FALSE., &
1118 176 : task_list_external=task_list)
1119 : END DO
1120 176 : DO ispin = 1, nspins
1121 92 : CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
1122 92 : CALL auxbas_pw_pool%give_back_pw(rhoz_r_aux(ispin))
1123 176 : CALL auxbas_pw_pool%give_back_pw(rhoz_g_aux(ispin))
1124 : END DO
1125 84 : DEALLOCATE (v_xc, rhoz_r_aux, rhoz_g_aux)
1126 : !
1127 84 : IF (admm_env%do_gapw) THEN
1128 10 : rho_atom_set => admm_env%admm_gapw_env%local_rho_set%rho_atom_set
1129 10 : rho1_atom_set => local_rho_set_admm%rho_atom_set
1130 : CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, &
1131 10 : para_env, kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
1132 : CALL update_ks_atom(qs_env, mhz(:, 1), matrix_pe_admm, forces=.FALSE., tddft=.FALSE., &
1133 : rho_atom_external=rho1_atom_set, &
1134 : kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
1135 : oce_external=admm_env%admm_gapw_env%oce, &
1136 10 : sab_external=sab_aux_fit)
1137 : END IF
1138 : !
1139 84 : nao = admm_env%nao_orb
1140 84 : nao_aux = admm_env%nao_aux_fit
1141 84 : ALLOCATE (dbwork)
1142 84 : CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
1143 176 : DO ispin = 1, nspins
1144 : CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
1145 92 : admm_env%work_aux_orb, nao)
1146 : CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
1147 : 1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
1148 92 : admm_env%work_orb_orb)
1149 92 : CALL dbcsr_copy(dbwork, matrix_hz(1)%matrix)
1150 92 : CALL dbcsr_set(dbwork, 0.0_dp)
1151 92 : CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
1152 176 : CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
1153 : END DO
1154 84 : CALL dbcsr_release(dbwork)
1155 84 : DEALLOCATE (dbwork)
1156 84 : CALL dbcsr_deallocate_matrix_set(mhz)
1157 84 : DEALLOCATE (mpe)
1158 84 : IF (admm_env%do_gapw) THEN
1159 10 : IF (ASSOCIATED(local_rho_set_admm)) CALL local_rho_set_release(local_rho_set_admm)
1160 : END IF
1161 : END IF
1162 : END IF
1163 636 : IF (gapw .OR. gapw_xc) THEN
1164 150 : IF (ASSOCIATED(local_rho_set)) CALL local_rho_set_release(local_rho_set)
1165 150 : IF (ASSOCIATED(hartree_local)) CALL hartree_local_release(hartree_local)
1166 : END IF
1167 :
1168 : ! HFX
1169 636 : hfx_section => section_vals_get_subs_vals(xc_section, "HF")
1170 636 : CALL section_vals_get(hfx_section, explicit=do_hfx)
1171 636 : IF (do_hfx) THEN
1172 278 : CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
1173 278 : CPASSERT(n_rep_hf == 1)
1174 : CALL section_vals_val_get(hfx_section, "TREAT_LSD_IN_CORE", l_val=hfx_treat_lsd_in_core, &
1175 278 : i_rep_section=1)
1176 278 : mspin = 1
1177 278 : IF (hfx_treat_lsd_in_core) mspin = nspins
1178 : !
1179 : CALL get_qs_env(qs_env=qs_env, rho=rho, x_data=x_data, para_env=para_env, &
1180 278 : s_mstruct_changed=s_mstruct_changed)
1181 278 : distribute_fock_matrix = .TRUE.
1182 278 : IF (dft_control%do_admm) THEN
1183 140 : CALL get_qs_env(qs_env, admm_env=admm_env)
1184 140 : CALL get_admm_env(admm_env, matrix_s_aux_fit=msaux)
1185 140 : NULLIFY (mpe, mhz)
1186 720 : ALLOCATE (mpe(nspins, 1))
1187 140 : CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
1188 300 : DO ispin = 1, nspins
1189 160 : ALLOCATE (mhz(ispin, 1)%matrix)
1190 160 : CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
1191 160 : CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
1192 160 : CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
1193 300 : mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
1194 : END DO
1195 140 : IF (x_data(1, 1)%do_hfx_ri) THEN
1196 : eh1 = 0.0_dp
1197 : CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
1198 : geometry_did_change=s_mstruct_changed, nspins=nspins, &
1199 6 : hf_fraction=x_data(1, 1)%general_parameter%fraction)
1200 : ELSE
1201 268 : DO ispin = 1, mspin
1202 : eh1 = 0.0
1203 : CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
1204 : para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
1205 268 : ispin=ispin)
1206 : END DO
1207 : END IF
1208 : !
1209 140 : CPASSERT(ASSOCIATED(admm_env%work_aux_orb))
1210 140 : CPASSERT(ASSOCIATED(admm_env%work_orb_orb))
1211 140 : nao = admm_env%nao_orb
1212 140 : nao_aux = admm_env%nao_aux_fit
1213 140 : ALLOCATE (dbwork)
1214 140 : CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
1215 300 : DO ispin = 1, nspins
1216 : CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
1217 160 : admm_env%work_aux_orb, nao)
1218 : CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
1219 : 1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
1220 160 : admm_env%work_orb_orb)
1221 160 : CALL dbcsr_copy(dbwork, matrix_hz(ispin)%matrix)
1222 160 : CALL dbcsr_set(dbwork, 0.0_dp)
1223 160 : CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
1224 300 : CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
1225 : END DO
1226 140 : CALL dbcsr_release(dbwork)
1227 140 : DEALLOCATE (dbwork)
1228 140 : CALL dbcsr_deallocate_matrix_set(mhz)
1229 140 : DEALLOCATE (mpe)
1230 : ELSE
1231 138 : NULLIFY (mpe, mhz)
1232 1152 : ALLOCATE (mpe(nspins, 1), mhz(nspins, 1))
1233 300 : DO ispin = 1, nspins
1234 162 : mhz(ispin, 1)%matrix => matrix_hz(ispin)%matrix
1235 300 : mpe(ispin, 1)%matrix => matrix_pe(ispin)%matrix
1236 : END DO
1237 138 : IF (x_data(1, 1)%do_hfx_ri) THEN
1238 : eh1 = 0.0_dp
1239 : CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
1240 : geometry_did_change=s_mstruct_changed, nspins=nspins, &
1241 18 : hf_fraction=x_data(1, 1)%general_parameter%fraction)
1242 : ELSE
1243 240 : DO ispin = 1, mspin
1244 : eh1 = 0.0
1245 : CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
1246 : para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
1247 240 : ispin=ispin)
1248 : END DO
1249 : END IF
1250 138 : DEALLOCATE (mpe, mhz)
1251 : END IF
1252 : END IF
1253 :
1254 636 : focc = 4.0_dp
1255 636 : IF (nspins == 2) focc = 2.0_dp
1256 1380 : DO ispin = 1, nspins
1257 744 : mos => gs_mos(ispin)%mos_occ
1258 744 : CALL cp_fm_get_info(mos, ncol_global=norb)
1259 : CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
1260 1380 : norb, alpha=focc, beta=0.0_dp)
1261 : END DO
1262 :
1263 636 : CALL timestop(handle)
1264 :
1265 1908 : END SUBROUTINE tddfpt_resvec2
1266 :
1267 : ! **************************************************************************************************
1268 : !> \brief ...
1269 : !> \param qs_env ...
1270 : !> \param matrix_pe ...
1271 : !> \param gs_mos ...
1272 : !> \param matrix_hz ...
1273 : !> \param cpmos ...
1274 : ! **************************************************************************************************
1275 16 : SUBROUTINE tddfpt_resvec2_xtb(qs_env, matrix_pe, gs_mos, matrix_hz, cpmos)
1276 :
1277 : TYPE(qs_environment_type), POINTER :: qs_env
1278 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe
1279 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1280 : POINTER :: gs_mos
1281 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_hz
1282 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: cpmos
1283 :
1284 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec2_xtb'
1285 :
1286 : INTEGER :: atom_a, handle, iatom, ikind, is, ispin, &
1287 : na, natom, natorb, nkind, norb, ns, &
1288 : nsgf, nspins
1289 : INTEGER, DIMENSION(25) :: lao
1290 : INTEGER, DIMENSION(5) :: occ
1291 16 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: mcharge, mcharge1
1292 16 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: aocg, aocg1, charges, charges1
1293 : REAL(KIND=dp) :: focc
1294 16 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1295 : TYPE(cp_fm_type), POINTER :: mos
1296 16 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: p_matrix
1297 16 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p, matrix_s
1298 : TYPE(dbcsr_type), POINTER :: s_matrix
1299 : TYPE(dft_control_type), POINTER :: dft_control
1300 : TYPE(mp_para_env_type), POINTER :: para_env
1301 16 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1302 16 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1303 : TYPE(qs_rho_type), POINTER :: rho
1304 : TYPE(xtb_atom_type), POINTER :: xtb_kind
1305 :
1306 16 : CALL timeset(routineN, handle)
1307 :
1308 16 : CPASSERT(ASSOCIATED(matrix_pe))
1309 :
1310 16 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
1311 16 : nspins = dft_control%nspins
1312 :
1313 32 : DO ispin = 1, nspins
1314 32 : CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
1315 : END DO
1316 :
1317 16 : IF (dft_control%qs_control%xtb_control%coulomb_interaction) THEN
1318 : ! Mulliken charges
1319 : CALL get_qs_env(qs_env, rho=rho, particle_set=particle_set, &
1320 14 : matrix_s_kp=matrix_s, para_env=para_env)
1321 14 : natom = SIZE(particle_set)
1322 14 : CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
1323 70 : ALLOCATE (mcharge(natom), charges(natom, 5))
1324 42 : ALLOCATE (mcharge1(natom), charges1(natom, 5))
1325 1254 : charges = 0.0_dp
1326 1254 : charges1 = 0.0_dp
1327 14 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
1328 14 : nkind = SIZE(atomic_kind_set)
1329 14 : CALL get_qs_kind_set(qs_kind_set, maxsgf=nsgf)
1330 56 : ALLOCATE (aocg(nsgf, natom))
1331 1184 : aocg = 0.0_dp
1332 42 : ALLOCATE (aocg1(nsgf, natom))
1333 1184 : aocg1 = 0.0_dp
1334 14 : p_matrix => matrix_p(:, 1)
1335 14 : s_matrix => matrix_s(1, 1)%matrix
1336 14 : CALL ao_charges(p_matrix, s_matrix, aocg, para_env)
1337 14 : CALL ao_charges(matrix_pe, s_matrix, aocg1, para_env)
1338 48 : DO ikind = 1, nkind
1339 34 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=na)
1340 34 : CALL get_qs_kind(qs_kind_set(ikind), xtb_parameter=xtb_kind)
1341 34 : CALL get_xtb_atom_param(xtb_kind, natorb=natorb, lao=lao, occupation=occ)
1342 316 : DO iatom = 1, na
1343 234 : atom_a = atomic_kind_set(ikind)%atom_list(iatom)
1344 1404 : charges(atom_a, :) = REAL(occ(:), KIND=dp)
1345 900 : DO is = 1, natorb
1346 632 : ns = lao(is) + 1
1347 632 : charges(atom_a, ns) = charges(atom_a, ns) - aocg(is, atom_a)
1348 866 : charges1(atom_a, ns) = charges1(atom_a, ns) - aocg1(is, atom_a)
1349 : END DO
1350 : END DO
1351 : END DO
1352 14 : DEALLOCATE (aocg, aocg1)
1353 248 : DO iatom = 1, natom
1354 1404 : mcharge(iatom) = SUM(charges(iatom, :))
1355 1418 : mcharge1(iatom) = SUM(charges1(iatom, :))
1356 : END DO
1357 : ! Coulomb Kernel
1358 14 : CALL xtb_coulomb_hessian(qs_env, matrix_hz, charges1, mcharge1, mcharge)
1359 : !
1360 28 : DEALLOCATE (charges, mcharge, charges1, mcharge1)
1361 : END IF
1362 :
1363 16 : focc = 2.0_dp
1364 16 : IF (nspins == 2) focc = 1.0_dp
1365 32 : DO ispin = 1, nspins
1366 16 : mos => gs_mos(ispin)%mos_occ
1367 16 : CALL cp_fm_get_info(mos, ncol_global=norb)
1368 : CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
1369 32 : norb, alpha=focc, beta=0.0_dp)
1370 : END DO
1371 :
1372 16 : CALL timestop(handle)
1373 :
1374 32 : END SUBROUTINE tddfpt_resvec2_xtb
1375 :
1376 : ! **************************************************************************************************
1377 : !> \brief ...
1378 : !> \param qs_env ...
1379 : !> \param cpmos ...
1380 : !> \param work ...
1381 : ! **************************************************************************************************
1382 652 : SUBROUTINE tddfpt_resvec3(qs_env, cpmos, work)
1383 :
1384 : TYPE(qs_environment_type), POINTER :: qs_env
1385 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: cpmos
1386 : TYPE(tddfpt_work_matrices) :: work
1387 :
1388 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec3'
1389 :
1390 : INTEGER :: handle, ispin, nao, norb, nspins
1391 : TYPE(cp_fm_struct_type), POINTER :: fmstruct
1392 : TYPE(cp_fm_type) :: cvec, umat
1393 : TYPE(cp_fm_type), POINTER :: omos
1394 : TYPE(dft_control_type), POINTER :: dft_control
1395 652 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1396 :
1397 652 : CALL timeset(routineN, handle)
1398 :
1399 652 : CALL get_qs_env(qs_env, mos=mos, dft_control=dft_control)
1400 652 : nspins = dft_control%nspins
1401 :
1402 1412 : DO ispin = 1, nspins
1403 760 : CALL get_mo_set(mos(ispin), mo_coeff=omos)
1404 : ASSOCIATE (rvecs => cpmos(ispin))
1405 760 : CALL cp_fm_get_info(rvecs, nrow_global=nao, ncol_global=norb)
1406 760 : CALL cp_fm_create(cvec, rvecs%matrix_struct, "cvec")
1407 : CALL cp_fm_struct_create(fmstruct, context=rvecs%matrix_struct%context, nrow_global=norb, &
1408 760 : ncol_global=norb, para_env=rvecs%matrix_struct%para_env)
1409 760 : CALL cp_fm_create(umat, fmstruct, "umat")
1410 760 : CALL cp_fm_struct_release(fmstruct)
1411 : !
1412 760 : CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, omos, work%S_C0(ispin), 0.0_dp, umat)
1413 760 : CALL cp_fm_copy_general(rvecs, cvec, rvecs%matrix_struct%para_env)
1414 760 : CALL parallel_gemm("N", "T", nao, norb, norb, 1.0_dp, cvec, umat, 0.0_dp, rvecs)
1415 : END ASSOCIATE
1416 760 : CALL cp_fm_release(cvec)
1417 2932 : CALL cp_fm_release(umat)
1418 : END DO
1419 :
1420 652 : CALL timestop(handle)
1421 :
1422 652 : END SUBROUTINE tddfpt_resvec3
1423 :
1424 : ! **************************************************************************************************
1425 : !> \brief Calculate direct tddft forces
1426 : !> \param qs_env ...
1427 : !> \param ex_env ...
1428 : !> \param gs_mos ...
1429 : !> \param kernel_env ...
1430 : !> \param sub_env ...
1431 : !> \param work_matrices ...
1432 : !> \param debug_forces ...
1433 : !> \par History
1434 : !> * 01.2020 screated [JGH]
1435 : ! **************************************************************************************************
1436 652 : SUBROUTINE tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
1437 :
1438 : TYPE(qs_environment_type), POINTER :: qs_env
1439 : TYPE(excited_energy_type), POINTER :: ex_env
1440 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1441 : POINTER :: gs_mos
1442 : TYPE(kernel_env_type), INTENT(IN) :: kernel_env
1443 : TYPE(tddfpt_subgroup_env_type) :: sub_env
1444 : TYPE(tddfpt_work_matrices) :: work_matrices
1445 : LOGICAL, INTENT(IN) :: debug_forces
1446 :
1447 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_kernel_force'
1448 :
1449 : INTEGER :: handle
1450 : TYPE(dft_control_type), POINTER :: dft_control
1451 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1452 :
1453 652 : CALL timeset(routineN, handle)
1454 :
1455 652 : CALL get_qs_env(qs_env, dft_control=dft_control)
1456 652 : tddfpt_control => dft_control%tddfpt2_control
1457 :
1458 652 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
1459 : ! full Kernel
1460 414 : CALL fhxc_force(qs_env, ex_env, gs_mos, kernel_env%full_kernel, debug_forces)
1461 238 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
1462 : ! sTDA Kernel
1463 160 : CALL stda_force(qs_env, ex_env, gs_mos, kernel_env%stda_kernel, sub_env, work_matrices, debug_forces)
1464 78 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
1465 : ! nothing to be done here
1466 78 : ex_env%matrix_wx1 => NULL()
1467 : ELSE
1468 0 : CPABORT('Unknown kernel type')
1469 : END IF
1470 :
1471 652 : CALL timestop(handle)
1472 :
1473 652 : END SUBROUTINE tddfpt_kernel_force
1474 :
1475 : END MODULE qs_tddfpt2_forces
|