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