Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 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 580 : 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 580 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe_asymm, matrix_pe_symm, &
179 580 : matrix_s, matrix_s_aux_fit
180 : TYPE(dft_control_type), POINTER :: dft_control
181 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
182 :
183 580 : CALL timeset(routineN, handle)
184 :
185 580 : CALL get_qs_env(qs_env, dft_control=dft_control)
186 :
187 580 : CALL cite_reference(Hehn2022)
188 580 : CALL cite_reference(Hehn2024)
189 580 : IF (dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc) CALL cite_reference(Sertcan2024)
190 :
191 580 : nspins = dft_control%nspins
192 580 : tddfpt_control => dft_control%tddfpt2_control
193 580 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
194 568 : do_sf = .FALSE.
195 : ELSE
196 12 : do_sf = .TRUE.
197 : END IF
198 :
199 : ! disable RES-TDDFPT for now
200 1268 : DO ispin = 1, nspins
201 1268 : 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 580 : 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 2428 : 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 1268 : DO ispin = 1, nspins
217 688 : CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=matrix_struct)
218 688 : CALL cp_fm_create(ex_env%cpmos(ispin), matrix_struct)
219 1268 : CALL cp_fm_set_all(ex_env%cpmos(ispin), 0.0_dp)
220 : END DO
221 580 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
222 580 : 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 580 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe, nspins)
227 580 : CALL dbcsr_allocate_matrix_set(matrix_pe_symm, nspins)
228 580 : CALL dbcsr_allocate_matrix_set(matrix_pe_asymm, nspins)
229 1268 : DO ispin = 1, nspins
230 :
231 : ! Initialize matrix_pe as a sparse matrix with zeros
232 688 : ALLOCATE (ex_env%matrix_pe(ispin)%matrix)
233 688 : CALL dbcsr_create(ex_env%matrix_pe(ispin)%matrix, template=matrix_s(1)%matrix)
234 688 : CALL dbcsr_copy(ex_env%matrix_pe(ispin)%matrix, matrix_s(1)%matrix)
235 688 : CALL dbcsr_set(ex_env%matrix_pe(ispin)%matrix, 0.0_dp)
236 :
237 688 : ALLOCATE (matrix_pe_symm(ispin)%matrix)
238 688 : CALL dbcsr_create(matrix_pe_symm(ispin)%matrix, template=matrix_s(1)%matrix)
239 688 : CALL dbcsr_copy(matrix_pe_symm(ispin)%matrix, ex_env%matrix_pe(ispin)%matrix)
240 :
241 688 : ALLOCATE (matrix_pe_asymm(ispin)%matrix)
242 : CALL dbcsr_create(matrix_pe_asymm(ispin)%matrix, template=matrix_s(1)%matrix, &
243 688 : matrix_type=dbcsr_type_antisymmetric)
244 688 : CALL dbcsr_complete_redistribute(ex_env%matrix_pe(ispin)%matrix, matrix_pe_asymm(ispin)%matrix)
245 :
246 688 : IF (do_sf) THEN
247 : spin = 1
248 : ELSE
249 664 : 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 1268 : 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 580 : IF (dft_control%do_admm) THEN
258 128 : CALL get_qs_env(qs_env, admm_env=admm_env)
259 128 : CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
260 128 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_pe_admm, nspins)
261 276 : DO ispin = 1, nspins
262 148 : ALLOCATE (ex_env%matrix_pe_admm(ispin)%matrix)
263 148 : CALL dbcsr_create(ex_env%matrix_pe_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
264 148 : CALL dbcsr_copy(ex_env%matrix_pe_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
265 148 : 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 276 : admm_env, ex_env%matrix_pe_admm(ispin)%matrix)
268 : END DO
269 : END IF
270 : !
271 580 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_hz, nspins)
272 1268 : DO ispin = 1, nspins
273 688 : ALLOCATE (ex_env%matrix_hz(ispin)%matrix)
274 688 : CALL dbcsr_create(ex_env%matrix_hz(ispin)%matrix, template=matrix_s(1)%matrix)
275 688 : CALL dbcsr_copy(ex_env%matrix_hz(ispin)%matrix, matrix_s(1)%matrix)
276 1268 : 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 580 : 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 564 : gs_mos, ex_env%matrix_hz, ex_env%cpmos)
284 : END IF
285 : !
286 580 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1, SIZE(ex_env%evect, 1))
287 580 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_asymm, SIZE(ex_env%evect, 1))
288 1256 : DO ispin = 1, SIZE(ex_env%evect, 1)
289 676 : ALLOCATE (ex_env%matrix_px1(ispin)%matrix)
290 676 : CALL dbcsr_create(ex_env%matrix_px1(ispin)%matrix, template=matrix_s(1)%matrix)
291 676 : CALL dbcsr_copy(ex_env%matrix_px1(ispin)%matrix, matrix_s(1)%matrix)
292 676 : CALL dbcsr_set(ex_env%matrix_px1(ispin)%matrix, 0.0_dp)
293 :
294 676 : 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 676 : matrix_type=dbcsr_type_antisymmetric)
297 1256 : CALL dbcsr_complete_redistribute(ex_env%matrix_px1(ispin)%matrix, ex_env%matrix_px1_asymm(ispin)%matrix)
298 : END DO
299 : ! Kernel ADMM
300 580 : IF (tddfpt_control%do_admm) THEN
301 64 : CALL get_qs_env(qs_env, admm_env=admm_env)
302 64 : CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
303 64 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm, SIZE(ex_env%evect, 1))
304 64 : CALL dbcsr_allocate_matrix_set(ex_env%matrix_px1_admm_asymm, SIZE(ex_env%evect, 1))
305 132 : DO ispin = 1, SIZE(ex_env%evect, 1)
306 68 : ALLOCATE (ex_env%matrix_px1_admm(ispin)%matrix)
307 68 : CALL dbcsr_create(ex_env%matrix_px1_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
308 68 : CALL dbcsr_copy(ex_env%matrix_px1_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
309 68 : CALL dbcsr_set(ex_env%matrix_px1_admm(ispin)%matrix, 0.0_dp)
310 :
311 68 : 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 68 : matrix_type=dbcsr_type_antisymmetric)
314 : CALL dbcsr_complete_redistribute(ex_env%matrix_px1_admm(ispin)%matrix, &
315 132 : 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 580 : 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 580 : CALL tddfpt_resvec3(qs_env, ex_env%cpmos, work_matrices)
322 :
323 580 : CALL dbcsr_deallocate_matrix_set(matrix_pe_symm)
324 580 : CALL dbcsr_deallocate_matrix_set(matrix_pe_asymm)
325 :
326 580 : CALL timestop(handle)
327 :
328 580 : 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 580 : 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 580 : INTEGER, ALLOCATABLE, DIMENSION(:) :: natom_of_kind
355 : LOGICAL :: debug_forces
356 : REAL(KIND=dp) :: ehartree, exc
357 580 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
358 : TYPE(dft_control_type), POINTER :: dft_control
359 580 : TYPE(qs_force_type), DIMENSION(:), POINTER :: ks_force, td_force
360 :
361 580 : CALL timeset(routineN, handle)
362 :
363 : ! for extended debug output
364 580 : 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 580 : atomic_kind_set=atomic_kind_set)
368 580 : CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, natom_of_kind=natom_of_kind)
369 580 : NULLIFY (td_force)
370 580 : CALL allocate_qs_force(td_force, natom_of_kind)
371 580 : DEALLOCATE (natom_of_kind)
372 580 : CALL zero_qs_force(td_force)
373 580 : CALL set_qs_env(qs_env, force=td_force)
374 : !
375 580 : 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 564 : 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 564 : 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 564 : ex_env%vh_rspace)
386 : CALL tddfpt_force_direct(qs_env, ex_env, gs_mos, kernel_env, sub_env, &
387 564 : work_matrices, debug_forces)
388 : END IF
389 : !
390 : ! add TD and KS forces
391 580 : CALL get_qs_env(qs_env, force=td_force)
392 580 : CALL sum_qs_force(ks_force, td_force)
393 580 : CALL set_qs_env(qs_env, force=ks_force)
394 580 : CALL deallocate_qs_force(td_force)
395 : !
396 580 : CALL timestop(handle)
397 :
398 580 : 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 580 : 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 580 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ftot1, ftot2
436 : REAL(KIND=dp), DIMENSION(3) :: fodeb
437 580 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
438 580 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: evect
439 : TYPE(cp_logger_type), POINTER :: logger
440 580 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s, matrix_wx1, &
441 580 : 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 580 : POINTER :: sab_orb
446 580 : 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 580 : CALL timeset(routineN, handle)
451 :
452 580 : logger => cp_get_default_logger()
453 580 : IF (logger%para_env%is_source()) THEN
454 290 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
455 : ELSE
456 : iounit = -1
457 : END IF
458 :
459 580 : evect => ex_env%evect
460 :
461 : CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, para_env=para_env, &
462 580 : sab_orb=sab_orb, dft_control=dft_control, force=force)
463 580 : NULLIFY (tddfpt_control)
464 580 : tddfpt_control => dft_control%tddfpt2_control
465 580 : IF (tddfpt_control%spinflip == no_sf_tddfpt) THEN
466 : do_sf = .FALSE.
467 : ELSE
468 12 : do_sf = .TRUE.
469 : END IF
470 580 : nspins = dft_control%nspins
471 :
472 580 : IF (debug_forces) THEN
473 58 : CALL get_qs_env(qs_env, natom=natom, atomic_kind_set=atomic_kind_set)
474 174 : ALLOCATE (ftot1(3, natom))
475 58 : 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 580 : 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 580 : NULLIFY (matrix_wx1, matrix_wz)
484 580 : CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
485 580 : matrix_wx1 => ex_env%matrix_wx1
486 580 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
487 1268 : DO ispin = 1, nspins
488 688 : IF (do_sf) THEN
489 : spin = 1
490 : ELSE
491 664 : spin = ispin
492 : END IF
493 : ! Create and initialize the Lambda matrix as a sparse matrix
494 688 : ALLOCATE (matrix_wz(ispin)%matrix)
495 688 : CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
496 688 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
497 688 : 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 688 : IF (.NOT. (do_sf .AND. (ispin == 1))) THEN
501 676 : CALL cp_fm_get_info(evect(spin), ncol_global=nact)
502 676 : CALL cp_dbcsr_plus_fm_fm_t(matrix_wz(ispin)%matrix, matrix_v=evect(spin), ncol=nact)
503 676 : evalue = ex_env%evalue
504 676 : IF (tddfpt_control%oe_corr == oe_shift) THEN
505 4 : evalue = ex_env%evalue - tddfpt_control%ev_shift
506 : END IF
507 676 : 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 1268 : 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 676 : matrix_wz(ispin)%matrix)
514 : END IF
515 : END DO
516 580 : 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 580 : NULLIFY (scrm)
521 754 : 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 580 : matrix_p=matrix_wz(1)%matrix)
529 580 : CALL dbcsr_deallocate_matrix_set(scrm)
530 580 : CALL dbcsr_deallocate_matrix_set(matrix_wz)
531 580 : IF (debug_forces) THEN
532 232 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
533 58 : CALL para_env%sum(fodeb)
534 58 : 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 580 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, matrix_ks=matrix_ks)
540 580 : NULLIFY (matrix_wz)
541 580 : CALL dbcsr_allocate_matrix_set(matrix_wz, nspins)
542 1268 : DO ispin = 1, nspins
543 688 : ALLOCATE (matrix_wz(ispin)%matrix)
544 688 : CALL dbcsr_create(matrix=matrix_wz(ispin)%matrix, template=matrix_s(1)%matrix)
545 688 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_wz(ispin)%matrix, sab_orb)
546 688 : 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 1268 : IF (.NOT. (do_sf .AND. (ispin == 2))) THEN
550 676 : evalue = ex_env%evalue
551 676 : IF (tddfpt_control%oe_corr == oe_shift) THEN
552 4 : evalue = ex_env%evalue - tddfpt_control%ev_shift
553 : END IF
554 676 : IF (do_sf) THEN
555 : spin = 2
556 : ELSE
557 664 : spin = ispin
558 : END IF
559 : CALL calculate_xwx_matrix(gs_mos(ispin)%mos_active, evect(ispin), matrix_s(1)%matrix, &
560 676 : matrix_ks(spin)%matrix, matrix_wz(ispin)%matrix, evalue)
561 : END IF
562 : END DO
563 580 : 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 580 : NULLIFY (scrm)
568 754 : 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 580 : matrix_p=matrix_wz(1)%matrix)
574 580 : CALL dbcsr_deallocate_matrix_set(scrm)
575 580 : CALL dbcsr_deallocate_matrix_set(matrix_wz)
576 580 : IF (debug_forces) THEN
577 232 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
578 58 : CALL para_env%sum(fodeb)
579 58 : 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 580 : IF (ASSOCIATED(matrix_wx1)) THEN
586 512 : 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 416 : 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 512 : NULLIFY (scrm)
594 668 : 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 512 : matrix_p=matrix_wx1(1)%matrix)
600 512 : CALL dbcsr_deallocate_matrix_set(scrm)
601 512 : IF (debug_forces) THEN
602 208 : fodeb(1:3) = force(1)%overlap(1:3, 1) - fodeb(1:3)
603 52 : CALL para_env%sum(fodeb)
604 52 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: D^XKP*dS ", fodeb
605 : END IF
606 : END IF
607 :
608 580 : IF (debug_forces) THEN
609 174 : ALLOCATE (ftot2(3, natom))
610 58 : CALL total_qs_force(ftot2, force, atomic_kind_set)
611 232 : fodeb(1:3) = ftot2(1:3, 1) - ftot1(1:3, 1)
612 58 : CALL para_env%sum(fodeb)
613 58 : IF (iounit > 0) WRITE (iounit, "(T3,A,T30,3F16.8)") "DEBUG:: Excitation Force", fodeb
614 58 : DEALLOCATE (ftot1, ftot2)
615 : END IF
616 :
617 580 : CALL timestop(handle)
618 :
619 1160 : 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 2752 : 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 688 : CALL timeset(routineN, handle)
647 688 : CALL cp_fm_get_info(mos_active, nrow_global=nao, ncol_global=norb)
648 688 : CALL cp_fm_get_info(evect, nrow_global=nao, ncol_global=nact)
649 688 : CPASSERT(norb == nact)
650 :
651 : ! matrix_pe = X*X^T
652 688 : IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 2))) THEN
653 676 : 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 688 : IF (.NOT. do_sf .OR. (do_sf .AND. (spin == 1))) THEN
658 676 : CALL cp_fm_get_info(evect, matrix_struct=fmstruct)
659 676 : NULLIFY (fmstruct2)
660 : CALL cp_fm_struct_create(fmstruct=fmstruct2, template_fmstruct=fmstruct, &
661 676 : nrow_global=norb, ncol_global=norb)
662 676 : CALL cp_fm_create(xxmat, matrix_struct=fmstruct2)
663 676 : CALL cp_fm_struct_release(fmstruct2)
664 676 : CALL cp_fm_create(cxmat, matrix_struct=fmstruct)
665 : ! S*X
666 676 : 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 676 : CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, cxmat, evect, 0.0_dp, xxmat)
669 : ! C*X^T*S*X
670 676 : CALL parallel_gemm('N', 'N', nao, norb, norb, 1.0_dp, mos_active, xxmat, 0.0_dp, cxmat)
671 676 : 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 676 : ncol=norb, alpha=-1.0_dp, symmetry_mode=1)
675 676 : CALL cp_fm_release(cxmat)
676 : END IF
677 : !
678 : ! Test for Tr(Pe*S)=0
679 688 : CALL dbcsr_dot(matrix_pe, matrix_s, tmp)
680 688 : IF (.NOT. do_sf) THEN
681 664 : 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 688 : CALL timestop(handle)
726 :
727 688 : 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 148 : 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 148 : CALL timeset(routineN, handle)
746 : !
747 148 : nao_aux = admm_env%nao_aux_fit
748 148 : nao = admm_env%nao_orb
749 : !
750 148 : 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 148 : 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 148 : admm_env%work_aux_aux)
757 148 : CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, matrix_pe_admm, keep_sparsity=.TRUE.)
758 : !
759 148 : CALL timestop(handle)
760 :
761 148 : 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 564 : 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 564 : REAL(KIND=dp), DIMENSION(:), POINTER :: Qlm_tot
795 : TYPE(admm_type), POINTER :: admm_env
796 564 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
797 : TYPE(cp_fm_type), POINTER :: mos
798 : TYPE(cp_logger_type), POINTER :: logger
799 564 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: msaux
800 564 : 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 564 : 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 564 : 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 564 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g, rho_g_aux, rhoz_g_aux, trho_g, &
812 564 : 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 564 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r, rho_r_aux, rhoz_r_aux, tau_r, &
818 564 : trho_r, trho_xc_r, v_xc, v_xc_tau
819 564 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
820 : TYPE(qs_ks_env_type), POINTER :: ks_env
821 : TYPE(qs_rho_type), POINTER :: rho, rho_aux_fit, rho_xc, rhoz_aux, trho
822 564 : TYPE(rho_atom_type), DIMENSION(:), POINTER :: rho1_atom_set, rho_atom_set
823 : TYPE(section_vals_type), POINTER :: hfx_section, input, xc_section
824 : TYPE(task_list_type), POINTER :: task_list
825 :
826 564 : CALL timeset(routineN, handle)
827 :
828 564 : NULLIFY (pw_env)
829 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, ks_env=ks_env, &
830 564 : dft_control=dft_control, para_env=para_env)
831 564 : CPASSERT(ASSOCIATED(pw_env))
832 564 : nspins = dft_control%nspins
833 564 : gapw = dft_control%qs_control%gapw
834 564 : gapw_xc = dft_control%qs_control%gapw_xc
835 :
836 564 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_exck)
837 564 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxsr)
838 564 : CPASSERT(.NOT. dft_control%tddfpt2_control%do_hfxlr)
839 :
840 564 : NULLIFY (auxbas_pw_pool, poisson_env)
841 : ! gets the tmp grids
842 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
843 564 : poisson_env=poisson_env)
844 :
845 564 : CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
846 564 : CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
847 564 : CALL auxbas_pw_pool%create_pw(v_hartree_rspace)
848 :
849 4164 : ALLOCATE (trho_r(nspins), trho_g(nspins))
850 1236 : DO ispin = 1, nspins
851 672 : CALL auxbas_pw_pool%create_pw(trho_r(ispin))
852 1236 : CALL auxbas_pw_pool%create_pw(trho_g(ispin))
853 : END DO
854 564 : IF (gapw_xc) THEN
855 70 : ALLOCATE (trho_xc_r(nspins), trho_xc_g(nspins))
856 28 : DO ispin = 1, nspins
857 14 : CALL auxbas_pw_pool%create_pw(trho_xc_r(ispin))
858 28 : CALL auxbas_pw_pool%create_pw(trho_xc_g(ispin))
859 : END DO
860 : END IF
861 :
862 : ! GAPW/GAPW_XC initializations
863 564 : NULLIFY (hartree_local, local_rho_set)
864 564 : IF (gapw) THEN
865 : CALL get_qs_env(qs_env, &
866 : atomic_kind_set=atomic_kind_set, &
867 : natom=natom, &
868 64 : qs_kind_set=qs_kind_set)
869 64 : CALL local_rho_set_create(local_rho_set)
870 : CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
871 64 : qs_kind_set, dft_control, para_env)
872 : CALL init_rho0(local_rho_set, qs_env, dft_control%qs_control%gapw_control, &
873 64 : zcore=0.0_dp)
874 64 : CALL rho0_s_grid_create(pw_env, local_rho_set%rho0_mpole)
875 64 : CALL hartree_local_create(hartree_local)
876 64 : CALL init_coulomb_local(hartree_local, natom)
877 500 : ELSEIF (gapw_xc) THEN
878 : CALL get_qs_env(qs_env, &
879 : atomic_kind_set=atomic_kind_set, &
880 14 : qs_kind_set=qs_kind_set)
881 14 : CALL local_rho_set_create(local_rho_set)
882 : CALL allocate_rho_atom_internals(local_rho_set%rho_atom_set, atomic_kind_set, &
883 14 : qs_kind_set, dft_control, para_env)
884 : END IF
885 :
886 564 : total_rho = 0.0_dp
887 564 : CALL pw_zero(rho_tot_gspace)
888 1236 : DO ispin = 1, nspins
889 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
890 : rho=trho_r(ispin), &
891 : rho_gspace=trho_g(ispin), &
892 : soft_valid=gapw, &
893 672 : total_rho=total_rho(ispin))
894 672 : CALL pw_axpy(trho_g(ispin), rho_tot_gspace)
895 1236 : IF (gapw_xc) THEN
896 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=matrix_pe(ispin)%matrix, &
897 : rho=trho_xc_r(ispin), &
898 : rho_gspace=trho_xc_g(ispin), &
899 : soft_valid=gapw_xc, &
900 14 : total_rho=rhotot)
901 : END IF
902 : END DO
903 :
904 : ! GAPW o GAPW_XC require the calculation of hard and soft local densities
905 564 : IF (gapw .OR. gapw_xc) THEN
906 78 : CALL get_qs_env(qs_env=qs_env, oce=oce, sab_orb=sab)
907 : CALL calculate_rho_atom_coeff(qs_env, matrix_pe, local_rho_set%rho_atom_set, &
908 78 : qs_kind_set, oce, sab, para_env)
909 78 : CALL prepare_gapw_den(qs_env, local_rho_set, do_rho0=gapw)
910 : END IF
911 1692 : rhotot = SUM(total_rho)
912 564 : IF (gapw) THEN
913 64 : CALL get_rho0_mpole(local_rho_set%rho0_mpole, Qlm_tot=Qlm_tot)
914 64 : rhotot = rhotot + local_rho_set%rho0_mpole%total_rho0_h
915 64 : CALL pw_axpy(local_rho_set%rho0_mpole%rho0_s_gs, rho_tot_gspace)
916 64 : IF (ASSOCIATED(local_rho_set%rho0_mpole%rhoz_cneo_s_gs)) THEN
917 0 : CALL pw_axpy(local_rho_set%rho0_mpole%rhoz_cneo_s_gs, rho_tot_gspace)
918 : END IF
919 : END IF
920 :
921 564 : IF (ABS(rhotot) > 1.e-05_dp) THEN
922 20 : logger => cp_get_default_logger()
923 20 : IF (logger%para_env%is_source()) THEN
924 10 : iounit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
925 : ELSE
926 : iounit = -1
927 : END IF
928 20 : CPWARN("Real space electron count of excitation density is non-zero.")
929 20 : IF (iounit > 0) THEN
930 10 : WRITE (iounit, "(T2,A,T61,G20.10)") "Measured electron count is ", rhotot
931 10 : WRITE (iounit, "(T2,A,/)") REPEAT("*", 79)
932 : END IF
933 : END IF
934 :
935 : ! calculate associated hartree potential
936 : CALL pw_poisson_solve(poisson_env, rho_tot_gspace, thartree, &
937 564 : v_hartree_gspace)
938 564 : CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
939 564 : CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
940 564 : IF (gapw) THEN
941 : CALL Vh_1c_gg_integrals(qs_env, thartree, hartree_local%ecoul_1c, &
942 64 : local_rho_set, para_env, tddft=.TRUE.)
943 : CALL integrate_vhg0_rspace(qs_env, v_hartree_rspace, para_env, &
944 : calculate_forces=.FALSE., &
945 64 : local_rho_set=local_rho_set)
946 : END IF
947 :
948 : ! Fxc*drho term
949 564 : CALL get_qs_env(qs_env, rho=rho)
950 564 : CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
951 : !
952 564 : CALL get_qs_env(qs_env, input=input)
953 564 : IF (dft_control%do_admm) THEN
954 128 : CALL get_qs_env(qs_env, admm_env=admm_env)
955 128 : xc_section => admm_env%xc_section_primary
956 : ELSE
957 436 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
958 : END IF
959 : !
960 564 : deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
961 564 : IF (deriv2_analytic) THEN
962 564 : NULLIFY (v_xc, v_xc_tau, tau_r)
963 564 : IF (gapw_xc) THEN
964 14 : CALL get_qs_env(qs_env=qs_env, rho_xc=rho_xc)
965 14 : CALL qs_fxc_analytic(rho_xc, trho_xc_r, tau_r, xc_section, auxbas_pw_pool, .FALSE., v_xc, v_xc_tau)
966 : ELSE
967 550 : CALL qs_fxc_analytic(rho, trho_r, tau_r, xc_section, auxbas_pw_pool, .FALSE., v_xc, v_xc_tau)
968 : END IF
969 564 : IF (gapw .OR. gapw_xc) THEN
970 78 : CALL get_qs_env(qs_env, rho_atom_set=rho_atom_set)
971 78 : rho1_atom_set => local_rho_set%rho_atom_set
972 : CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, para_env, &
973 78 : do_triplet=.FALSE.)
974 : END IF
975 : ELSE
976 0 : CPABORT("NYA 00006")
977 0 : NULLIFY (v_xc, trho)
978 0 : ALLOCATE (trho)
979 0 : CALL qs_rho_create(trho)
980 0 : CALL qs_rho_set(trho, rho_r=trho_r, rho_g=trho_g)
981 0 : CALL qs_fxc_fdiff(ks_env, rho, trho, xc_section, 6, .FALSE., v_xc, v_xc_tau)
982 0 : DEALLOCATE (trho)
983 : END IF
984 :
985 1236 : DO ispin = 1, nspins
986 672 : CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
987 1236 : CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
988 : END DO
989 564 : IF (gapw_xc) THEN
990 28 : DO ispin = 1, nspins
991 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
992 : hmat=matrix_hz(ispin), &
993 14 : calculate_forces=.FALSE.)
994 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
995 : hmat=matrix_hz(ispin), &
996 28 : gapw=gapw_xc, calculate_forces=.FALSE.)
997 : END DO
998 : ELSE
999 : ! vtot = v_xc(ispin) + v_hartree
1000 1208 : DO ispin = 1, nspins
1001 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
1002 : hmat=matrix_hz(ispin), &
1003 658 : gapw=gapw, calculate_forces=.FALSE.)
1004 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hartree_rspace, &
1005 : hmat=matrix_hz(ispin), &
1006 1208 : gapw=gapw, calculate_forces=.FALSE.)
1007 : END DO
1008 : END IF
1009 564 : IF (gapw .OR. gapw_xc) THEN
1010 78 : mhz(1:nspins, 1:1) => matrix_hz(1:nspins)
1011 78 : mpe(1:nspins, 1:1) => matrix_pe(1:nspins)
1012 : CALL update_ks_atom(qs_env, mhz, mpe, forces=.FALSE., &
1013 78 : rho_atom_external=local_rho_set%rho_atom_set)
1014 : END IF
1015 :
1016 564 : CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
1017 564 : CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
1018 564 : CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
1019 1236 : DO ispin = 1, nspins
1020 672 : CALL auxbas_pw_pool%give_back_pw(trho_r(ispin))
1021 672 : CALL auxbas_pw_pool%give_back_pw(trho_g(ispin))
1022 1236 : CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
1023 : END DO
1024 564 : DEALLOCATE (trho_r, trho_g, v_xc)
1025 564 : IF (gapw_xc) THEN
1026 28 : DO ispin = 1, nspins
1027 14 : CALL auxbas_pw_pool%give_back_pw(trho_xc_r(ispin))
1028 28 : CALL auxbas_pw_pool%give_back_pw(trho_xc_g(ispin))
1029 : END DO
1030 14 : DEALLOCATE (trho_xc_r, trho_xc_g)
1031 : END IF
1032 564 : IF (ASSOCIATED(v_xc_tau)) THEN
1033 0 : DO ispin = 1, nspins
1034 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
1035 : END DO
1036 0 : DEALLOCATE (v_xc_tau)
1037 : END IF
1038 564 : IF (dft_control%do_admm) THEN
1039 128 : IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1040 : ! add ADMM xc_section_aux terms: f_x[rhoz_ADMM]
1041 78 : CALL get_qs_env(qs_env, admm_env=admm_env)
1042 : CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, matrix_s_aux_fit=msaux, &
1043 78 : task_list_aux_fit=task_list)
1044 78 : basis_type = "AUX_FIT"
1045 : !
1046 78 : NULLIFY (mpe, mhz)
1047 398 : ALLOCATE (mpe(nspins, 1))
1048 78 : CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
1049 164 : DO ispin = 1, nspins
1050 86 : ALLOCATE (mhz(ispin, 1)%matrix)
1051 86 : CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
1052 86 : CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
1053 86 : CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
1054 164 : mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
1055 : END DO
1056 : !
1057 : ! GAPW/GAPW_XC initializations
1058 78 : NULLIFY (local_rho_set_admm)
1059 78 : IF (admm_env%do_gapw) THEN
1060 4 : basis_type = "AUX_FIT_SOFT"
1061 4 : task_list => admm_env%admm_gapw_env%task_list
1062 4 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
1063 4 : CALL get_admm_env(admm_env, sab_aux_fit=sab_aux_fit)
1064 4 : CALL local_rho_set_create(local_rho_set_admm)
1065 : CALL allocate_rho_atom_internals(local_rho_set_admm%rho_atom_set, atomic_kind_set, &
1066 4 : admm_env%admm_gapw_env%admm_kind_set, dft_control, para_env)
1067 : CALL calculate_rho_atom_coeff(qs_env, matrix_pe_admm, &
1068 : rho_atom_set=local_rho_set_admm%rho_atom_set, &
1069 : qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
1070 4 : oce=admm_env%admm_gapw_env%oce, sab=sab_aux_fit, para_env=para_env)
1071 : CALL prepare_gapw_den(qs_env, local_rho_set=local_rho_set_admm, &
1072 4 : do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
1073 : END IF
1074 : !
1075 78 : xc_section => admm_env%xc_section_aux
1076 : !
1077 78 : NULLIFY (rho_g_aux, rho_r_aux, rhoz_g_aux, rhoz_r_aux)
1078 78 : CALL qs_rho_get(rho_aux_fit, rho_r=rho_r_aux, rho_g=rho_g_aux)
1079 : ! rhoz_aux
1080 406 : ALLOCATE (rhoz_r_aux(nspins), rhoz_g_aux(nspins))
1081 164 : DO ispin = 1, nspins
1082 86 : CALL auxbas_pw_pool%create_pw(rhoz_r_aux(ispin))
1083 164 : CALL auxbas_pw_pool%create_pw(rhoz_g_aux(ispin))
1084 : END DO
1085 164 : DO ispin = 1, nspins
1086 : CALL calculate_rho_elec(ks_env=ks_env, matrix_p=mpe(ispin, 1)%matrix, &
1087 : rho=rhoz_r_aux(ispin), rho_gspace=rhoz_g_aux(ispin), &
1088 : basis_type=basis_type, &
1089 164 : task_list_external=task_list)
1090 : END DO
1091 : !
1092 78 : NULLIFY (v_xc)
1093 78 : deriv2_analytic = section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")
1094 78 : IF (deriv2_analytic) THEN
1095 78 : NULLIFY (tau_r)
1096 78 : CALL qs_fxc_analytic(rho_aux_fit, rhoz_r_aux, tau_r, xc_section, auxbas_pw_pool, .FALSE., v_xc, v_xc_tau)
1097 : ELSE
1098 0 : CPABORT("NYA 00007")
1099 : NULLIFY (rhoz_aux)
1100 0 : ALLOCATE (rhoz_aux)
1101 0 : CALL qs_rho_create(rhoz_aux)
1102 0 : CALL qs_rho_set(rhoz_aux, rho_r=rhoz_r_aux, rho_g=rhoz_g_aux)
1103 0 : CALL qs_fxc_fdiff(ks_env, rho_aux_fit, rhoz_aux, xc_section, 6, .FALSE., v_xc, v_xc_tau)
1104 0 : DEALLOCATE (rhoz_aux)
1105 : END IF
1106 : !
1107 164 : DO ispin = 1, nspins
1108 86 : CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
1109 : CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_xc(ispin), &
1110 : hmat=mhz(ispin, 1), basis_type=basis_type, &
1111 : calculate_forces=.FALSE., &
1112 164 : task_list_external=task_list)
1113 : END DO
1114 164 : DO ispin = 1, nspins
1115 86 : CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
1116 86 : CALL auxbas_pw_pool%give_back_pw(rhoz_r_aux(ispin))
1117 164 : CALL auxbas_pw_pool%give_back_pw(rhoz_g_aux(ispin))
1118 : END DO
1119 78 : DEALLOCATE (v_xc, rhoz_r_aux, rhoz_g_aux)
1120 : !
1121 78 : IF (admm_env%do_gapw) THEN
1122 4 : rho_atom_set => admm_env%admm_gapw_env%local_rho_set%rho_atom_set
1123 4 : rho1_atom_set => local_rho_set_admm%rho_atom_set
1124 : CALL calculate_xc_2nd_deriv_atom(rho_atom_set, rho1_atom_set, qs_env, xc_section, &
1125 4 : para_env, kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
1126 : CALL update_ks_atom(qs_env, mhz(:, 1), matrix_pe_admm, forces=.FALSE., tddft=.FALSE., &
1127 : rho_atom_external=rho1_atom_set, &
1128 : kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
1129 : oce_external=admm_env%admm_gapw_env%oce, &
1130 4 : sab_external=sab_aux_fit)
1131 : END IF
1132 : !
1133 78 : nao = admm_env%nao_orb
1134 78 : nao_aux = admm_env%nao_aux_fit
1135 78 : ALLOCATE (dbwork)
1136 78 : CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
1137 164 : DO ispin = 1, nspins
1138 : CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
1139 86 : admm_env%work_aux_orb, nao)
1140 : CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
1141 : 1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
1142 86 : admm_env%work_orb_orb)
1143 86 : CALL dbcsr_copy(dbwork, matrix_hz(1)%matrix)
1144 86 : CALL dbcsr_set(dbwork, 0.0_dp)
1145 86 : CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
1146 164 : CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
1147 : END DO
1148 78 : CALL dbcsr_release(dbwork)
1149 78 : DEALLOCATE (dbwork)
1150 78 : CALL dbcsr_deallocate_matrix_set(mhz)
1151 78 : DEALLOCATE (mpe)
1152 78 : IF (admm_env%do_gapw) THEN
1153 4 : IF (ASSOCIATED(local_rho_set_admm)) CALL local_rho_set_release(local_rho_set_admm)
1154 : END IF
1155 : END IF
1156 : END IF
1157 564 : IF (gapw .OR. gapw_xc) THEN
1158 78 : IF (ASSOCIATED(local_rho_set)) CALL local_rho_set_release(local_rho_set)
1159 78 : IF (ASSOCIATED(hartree_local)) CALL hartree_local_release(hartree_local)
1160 : END IF
1161 :
1162 : ! HFX
1163 564 : hfx_section => section_vals_get_subs_vals(xc_section, "HF")
1164 564 : CALL section_vals_get(hfx_section, explicit=do_hfx)
1165 564 : IF (do_hfx) THEN
1166 252 : CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
1167 252 : CPASSERT(n_rep_hf == 1)
1168 : CALL section_vals_val_get(hfx_section, "TREAT_LSD_IN_CORE", l_val=hfx_treat_lsd_in_core, &
1169 252 : i_rep_section=1)
1170 252 : mspin = 1
1171 252 : IF (hfx_treat_lsd_in_core) mspin = nspins
1172 : !
1173 : CALL get_qs_env(qs_env=qs_env, rho=rho, x_data=x_data, para_env=para_env, &
1174 252 : s_mstruct_changed=s_mstruct_changed)
1175 252 : distribute_fock_matrix = .TRUE.
1176 252 : IF (dft_control%do_admm) THEN
1177 128 : CALL get_qs_env(qs_env, admm_env=admm_env)
1178 128 : CALL get_admm_env(admm_env, matrix_s_aux_fit=msaux)
1179 128 : NULLIFY (mpe, mhz)
1180 660 : ALLOCATE (mpe(nspins, 1))
1181 128 : CALL dbcsr_allocate_matrix_set(mhz, nspins, 1)
1182 276 : DO ispin = 1, nspins
1183 148 : ALLOCATE (mhz(ispin, 1)%matrix)
1184 148 : CALL dbcsr_create(mhz(ispin, 1)%matrix, template=msaux(1)%matrix)
1185 148 : CALL dbcsr_copy(mhz(ispin, 1)%matrix, msaux(1)%matrix)
1186 148 : CALL dbcsr_set(mhz(ispin, 1)%matrix, 0.0_dp)
1187 276 : mpe(ispin, 1)%matrix => matrix_pe_admm(ispin)%matrix
1188 : END DO
1189 128 : IF (x_data(1, 1)%do_hfx_ri) THEN
1190 : eh1 = 0.0_dp
1191 : CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
1192 : geometry_did_change=s_mstruct_changed, nspins=nspins, &
1193 6 : hf_fraction=x_data(1, 1)%general_parameter%fraction)
1194 : ELSE
1195 244 : DO ispin = 1, mspin
1196 : eh1 = 0.0
1197 : CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
1198 : para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
1199 244 : ispin=ispin)
1200 : END DO
1201 : END IF
1202 : !
1203 128 : CPASSERT(ASSOCIATED(admm_env%work_aux_orb))
1204 128 : CPASSERT(ASSOCIATED(admm_env%work_orb_orb))
1205 128 : nao = admm_env%nao_orb
1206 128 : nao_aux = admm_env%nao_aux_fit
1207 128 : ALLOCATE (dbwork)
1208 128 : CALL dbcsr_create(dbwork, template=matrix_hz(1)%matrix)
1209 276 : DO ispin = 1, nspins
1210 : CALL cp_dbcsr_sm_fm_multiply(mhz(ispin, 1)%matrix, admm_env%A, &
1211 148 : admm_env%work_aux_orb, nao)
1212 : CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
1213 : 1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
1214 148 : admm_env%work_orb_orb)
1215 148 : CALL dbcsr_copy(dbwork, matrix_hz(ispin)%matrix)
1216 148 : CALL dbcsr_set(dbwork, 0.0_dp)
1217 148 : CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbwork, keep_sparsity=.TRUE.)
1218 276 : CALL dbcsr_add(matrix_hz(ispin)%matrix, dbwork, 1.0_dp, 1.0_dp)
1219 : END DO
1220 128 : CALL dbcsr_release(dbwork)
1221 128 : DEALLOCATE (dbwork)
1222 128 : CALL dbcsr_deallocate_matrix_set(mhz)
1223 128 : DEALLOCATE (mpe)
1224 : ELSE
1225 124 : NULLIFY (mpe, mhz)
1226 1040 : ALLOCATE (mpe(nspins, 1), mhz(nspins, 1))
1227 272 : DO ispin = 1, nspins
1228 148 : mhz(ispin, 1)%matrix => matrix_hz(ispin)%matrix
1229 272 : mpe(ispin, 1)%matrix => matrix_pe(ispin)%matrix
1230 : END DO
1231 124 : IF (x_data(1, 1)%do_hfx_ri) THEN
1232 : eh1 = 0.0_dp
1233 : CALL hfx_ri_update_ks(qs_env, x_data(1, 1)%ri_data, mhz, eh1, rho_ao=mpe, &
1234 : geometry_did_change=s_mstruct_changed, nspins=nspins, &
1235 18 : hf_fraction=x_data(1, 1)%general_parameter%fraction)
1236 : ELSE
1237 212 : DO ispin = 1, mspin
1238 : eh1 = 0.0
1239 : CALL integrate_four_center(qs_env, x_data, mhz, eh1, mpe, hfx_section, &
1240 : para_env, s_mstruct_changed, 1, distribute_fock_matrix, &
1241 212 : ispin=ispin)
1242 : END DO
1243 : END IF
1244 124 : DEALLOCATE (mpe, mhz)
1245 : END IF
1246 : END IF
1247 :
1248 564 : focc = 4.0_dp
1249 564 : IF (nspins == 2) focc = 2.0_dp
1250 1236 : DO ispin = 1, nspins
1251 672 : mos => gs_mos(ispin)%mos_occ
1252 672 : CALL cp_fm_get_info(mos, ncol_global=norb)
1253 : CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
1254 1236 : norb, alpha=focc, beta=0.0_dp)
1255 : END DO
1256 :
1257 564 : CALL timestop(handle)
1258 :
1259 1692 : END SUBROUTINE tddfpt_resvec2
1260 :
1261 : ! **************************************************************************************************
1262 : !> \brief ...
1263 : !> \param qs_env ...
1264 : !> \param matrix_pe ...
1265 : !> \param gs_mos ...
1266 : !> \param matrix_hz ...
1267 : !> \param cpmos ...
1268 : ! **************************************************************************************************
1269 16 : SUBROUTINE tddfpt_resvec2_xtb(qs_env, matrix_pe, gs_mos, matrix_hz, cpmos)
1270 :
1271 : TYPE(qs_environment_type), POINTER :: qs_env
1272 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_pe
1273 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1274 : POINTER :: gs_mos
1275 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_hz
1276 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: cpmos
1277 :
1278 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec2_xtb'
1279 :
1280 : INTEGER :: atom_a, handle, iatom, ikind, is, ispin, &
1281 : na, natom, natorb, nkind, norb, ns, &
1282 : nsgf, nspins
1283 : INTEGER, DIMENSION(25) :: lao
1284 : INTEGER, DIMENSION(5) :: occ
1285 16 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: mcharge, mcharge1
1286 16 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: aocg, aocg1, charges, charges1
1287 : REAL(KIND=dp) :: focc
1288 16 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1289 : TYPE(cp_fm_type), POINTER :: mos
1290 16 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: p_matrix
1291 16 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p, matrix_s
1292 : TYPE(dbcsr_type), POINTER :: s_matrix
1293 : TYPE(dft_control_type), POINTER :: dft_control
1294 : TYPE(mp_para_env_type), POINTER :: para_env
1295 16 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1296 16 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1297 : TYPE(qs_rho_type), POINTER :: rho
1298 : TYPE(xtb_atom_type), POINTER :: xtb_kind
1299 :
1300 16 : CALL timeset(routineN, handle)
1301 :
1302 16 : CPASSERT(ASSOCIATED(matrix_pe))
1303 :
1304 16 : CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
1305 16 : nspins = dft_control%nspins
1306 :
1307 32 : DO ispin = 1, nspins
1308 32 : CALL dbcsr_set(matrix_hz(ispin)%matrix, 0.0_dp)
1309 : END DO
1310 :
1311 16 : IF (dft_control%qs_control%xtb_control%coulomb_interaction) THEN
1312 : ! Mulliken charges
1313 : CALL get_qs_env(qs_env, rho=rho, particle_set=particle_set, &
1314 14 : matrix_s_kp=matrix_s, para_env=para_env)
1315 14 : natom = SIZE(particle_set)
1316 14 : CALL qs_rho_get(rho, rho_ao_kp=matrix_p)
1317 70 : ALLOCATE (mcharge(natom), charges(natom, 5))
1318 42 : ALLOCATE (mcharge1(natom), charges1(natom, 5))
1319 1254 : charges = 0.0_dp
1320 1254 : charges1 = 0.0_dp
1321 14 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
1322 14 : nkind = SIZE(atomic_kind_set)
1323 14 : CALL get_qs_kind_set(qs_kind_set, maxsgf=nsgf)
1324 56 : ALLOCATE (aocg(nsgf, natom))
1325 1184 : aocg = 0.0_dp
1326 42 : ALLOCATE (aocg1(nsgf, natom))
1327 1184 : aocg1 = 0.0_dp
1328 14 : p_matrix => matrix_p(:, 1)
1329 14 : s_matrix => matrix_s(1, 1)%matrix
1330 14 : CALL ao_charges(p_matrix, s_matrix, aocg, para_env)
1331 14 : CALL ao_charges(matrix_pe, s_matrix, aocg1, para_env)
1332 48 : DO ikind = 1, nkind
1333 34 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=na)
1334 34 : CALL get_qs_kind(qs_kind_set(ikind), xtb_parameter=xtb_kind)
1335 34 : CALL get_xtb_atom_param(xtb_kind, natorb=natorb, lao=lao, occupation=occ)
1336 316 : DO iatom = 1, na
1337 234 : atom_a = atomic_kind_set(ikind)%atom_list(iatom)
1338 1404 : charges(atom_a, :) = REAL(occ(:), KIND=dp)
1339 900 : DO is = 1, natorb
1340 632 : ns = lao(is) + 1
1341 632 : charges(atom_a, ns) = charges(atom_a, ns) - aocg(is, atom_a)
1342 866 : charges1(atom_a, ns) = charges1(atom_a, ns) - aocg1(is, atom_a)
1343 : END DO
1344 : END DO
1345 : END DO
1346 14 : DEALLOCATE (aocg, aocg1)
1347 248 : DO iatom = 1, natom
1348 1404 : mcharge(iatom) = SUM(charges(iatom, :))
1349 1418 : mcharge1(iatom) = SUM(charges1(iatom, :))
1350 : END DO
1351 : ! Coulomb Kernel
1352 14 : CALL xtb_coulomb_hessian(qs_env, matrix_hz, charges1, mcharge1, mcharge)
1353 : !
1354 28 : DEALLOCATE (charges, mcharge, charges1, mcharge1)
1355 : END IF
1356 :
1357 16 : focc = 2.0_dp
1358 16 : IF (nspins == 2) focc = 1.0_dp
1359 32 : DO ispin = 1, nspins
1360 16 : mos => gs_mos(ispin)%mos_occ
1361 16 : CALL cp_fm_get_info(mos, ncol_global=norb)
1362 : CALL cp_dbcsr_sm_fm_multiply(matrix_hz(ispin)%matrix, mos, cpmos(ispin), &
1363 32 : norb, alpha=focc, beta=0.0_dp)
1364 : END DO
1365 :
1366 16 : CALL timestop(handle)
1367 :
1368 32 : END SUBROUTINE tddfpt_resvec2_xtb
1369 :
1370 : ! **************************************************************************************************
1371 : !> \brief ...
1372 : !> \param qs_env ...
1373 : !> \param cpmos ...
1374 : !> \param work ...
1375 : ! **************************************************************************************************
1376 580 : SUBROUTINE tddfpt_resvec3(qs_env, cpmos, work)
1377 :
1378 : TYPE(qs_environment_type), POINTER :: qs_env
1379 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: cpmos
1380 : TYPE(tddfpt_work_matrices) :: work
1381 :
1382 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_resvec3'
1383 :
1384 : INTEGER :: handle, ispin, nao, norb, nspins
1385 : TYPE(cp_fm_struct_type), POINTER :: fmstruct
1386 : TYPE(cp_fm_type) :: cvec, umat
1387 : TYPE(cp_fm_type), POINTER :: omos
1388 : TYPE(dft_control_type), POINTER :: dft_control
1389 580 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1390 :
1391 580 : CALL timeset(routineN, handle)
1392 :
1393 580 : CALL get_qs_env(qs_env, mos=mos, dft_control=dft_control)
1394 580 : nspins = dft_control%nspins
1395 :
1396 1268 : DO ispin = 1, nspins
1397 688 : CALL get_mo_set(mos(ispin), mo_coeff=omos)
1398 : ASSOCIATE (rvecs => cpmos(ispin))
1399 688 : CALL cp_fm_get_info(rvecs, nrow_global=nao, ncol_global=norb)
1400 688 : CALL cp_fm_create(cvec, rvecs%matrix_struct, "cvec")
1401 : CALL cp_fm_struct_create(fmstruct, context=rvecs%matrix_struct%context, nrow_global=norb, &
1402 688 : ncol_global=norb, para_env=rvecs%matrix_struct%para_env)
1403 688 : CALL cp_fm_create(umat, fmstruct, "umat")
1404 688 : CALL cp_fm_struct_release(fmstruct)
1405 : !
1406 688 : CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, omos, work%S_C0(ispin), 0.0_dp, umat)
1407 688 : CALL cp_fm_copy_general(rvecs, cvec, rvecs%matrix_struct%para_env)
1408 688 : CALL parallel_gemm("N", "T", nao, norb, norb, 1.0_dp, cvec, umat, 0.0_dp, rvecs)
1409 : END ASSOCIATE
1410 688 : CALL cp_fm_release(cvec)
1411 2644 : CALL cp_fm_release(umat)
1412 : END DO
1413 :
1414 580 : CALL timestop(handle)
1415 :
1416 580 : END SUBROUTINE tddfpt_resvec3
1417 :
1418 : ! **************************************************************************************************
1419 : !> \brief Calculate direct tddft forces
1420 : !> \param qs_env ...
1421 : !> \param ex_env ...
1422 : !> \param gs_mos ...
1423 : !> \param kernel_env ...
1424 : !> \param sub_env ...
1425 : !> \param work_matrices ...
1426 : !> \param debug_forces ...
1427 : !> \par History
1428 : !> * 01.2020 screated [JGH]
1429 : ! **************************************************************************************************
1430 580 : SUBROUTINE tddfpt_kernel_force(qs_env, ex_env, gs_mos, kernel_env, sub_env, work_matrices, debug_forces)
1431 :
1432 : TYPE(qs_environment_type), POINTER :: qs_env
1433 : TYPE(excited_energy_type), POINTER :: ex_env
1434 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1435 : POINTER :: gs_mos
1436 : TYPE(kernel_env_type), INTENT(IN) :: kernel_env
1437 : TYPE(tddfpt_subgroup_env_type) :: sub_env
1438 : TYPE(tddfpt_work_matrices) :: work_matrices
1439 : LOGICAL, INTENT(IN) :: debug_forces
1440 :
1441 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_kernel_force'
1442 :
1443 : INTEGER :: handle
1444 : TYPE(dft_control_type), POINTER :: dft_control
1445 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1446 :
1447 580 : CALL timeset(routineN, handle)
1448 :
1449 580 : CALL get_qs_env(qs_env, dft_control=dft_control)
1450 580 : tddfpt_control => dft_control%tddfpt2_control
1451 :
1452 580 : IF (tddfpt_control%kernel == tddfpt_kernel_full) THEN
1453 : ! full Kernel
1454 354 : CALL fhxc_force(qs_env, ex_env, gs_mos, kernel_env%full_kernel, debug_forces)
1455 226 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_stda) THEN
1456 : ! sTDA Kernel
1457 158 : CALL stda_force(qs_env, ex_env, gs_mos, kernel_env%stda_kernel, sub_env, work_matrices, debug_forces)
1458 68 : ELSE IF (tddfpt_control%kernel == tddfpt_kernel_none) THEN
1459 : ! nothing to be done here
1460 68 : ex_env%matrix_wx1 => NULL()
1461 : ELSE
1462 0 : CPABORT('Unknown kernel type')
1463 : END IF
1464 :
1465 580 : CALL timestop(handle)
1466 :
1467 580 : END SUBROUTINE tddfpt_kernel_force
1468 :
1469 : END MODULE qs_tddfpt2_forces
|