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 : ! **************************************************************************************************
9 : !> \brief Routines to calculate CPHF like update and solve Z-vector equation
10 : !> for MP2 gradients (only GPW)
11 : !> \par History
12 : !> 11.2013 created [Mauro Del Ben]
13 : ! **************************************************************************************************
14 : MODULE mp2_cphf
15 : USE admm_methods, ONLY: admm_projection_derivative
16 : USE admm_types, ONLY: admm_type,&
17 : get_admm_env
18 : USE atomic_kind_types, ONLY: atomic_kind_type
19 : USE cell_types, ONLY: cell_type
20 : USE core_ae, ONLY: build_core_ae
21 : USE core_ppl, ONLY: build_core_ppl
22 : USE core_ppnl, ONLY: build_core_ppnl
23 : USE cp_blacs_env, ONLY: cp_blacs_env_type
24 : USE cp_control_types, ONLY: dft_control_type
25 : USE cp_dbcsr_api, ONLY: dbcsr_add,&
26 : dbcsr_copy,&
27 : dbcsr_p_type,&
28 : dbcsr_release,&
29 : dbcsr_scale,&
30 : dbcsr_set
31 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
32 : cp_dbcsr_plus_fm_fm_t,&
33 : dbcsr_allocate_matrix_set,&
34 : dbcsr_deallocate_matrix_set
35 : USE cp_fm_basic_linalg, ONLY: cp_fm_uplo_to_full
36 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
37 : cp_fm_struct_p_type,&
38 : cp_fm_struct_release,&
39 : cp_fm_struct_type
40 : USE cp_fm_types, ONLY: cp_fm_create,&
41 : cp_fm_get_info,&
42 : cp_fm_release,&
43 : cp_fm_set_all,&
44 : cp_fm_to_fm_submat,&
45 : cp_fm_type
46 : USE cp_log_handling, ONLY: cp_get_default_logger,&
47 : cp_logger_type
48 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
49 : cp_print_key_unit_nr
50 : USE hfx_admm_utils, ONLY: tddft_hfx_matrix
51 : USE hfx_derivatives, ONLY: derivatives_four_center
52 : USE hfx_exx, ONLY: add_exx_to_rhs
53 : USE hfx_ri, ONLY: hfx_ri_update_forces
54 : USE hfx_types, ONLY: alloc_containers,&
55 : hfx_container_type,&
56 : hfx_init_container,&
57 : hfx_type
58 : USE input_constants, ONLY: do_admm_aux_exch_func_none,&
59 : ot_precond_full_all,&
60 : z_solver_cg,&
61 : z_solver_pople,&
62 : z_solver_richardson,&
63 : z_solver_sd
64 : USE input_section_types, ONLY: section_vals_get,&
65 : section_vals_get_subs_vals,&
66 : section_vals_type
67 : USE kahan_sum, ONLY: accurate_dot_product
68 : USE kinds, ONLY: dp
69 : USE linear_systems, ONLY: solve_system
70 : USE machine, ONLY: m_flush,&
71 : m_walltime
72 : USE mathconstants, ONLY: fourpi
73 : USE message_passing, ONLY: mp_para_env_type
74 : USE mp2_types, ONLY: mp2_type,&
75 : ri_rpa_method_gpw
76 : USE parallel_gemm_api, ONLY: parallel_gemm
77 : USE particle_types, ONLY: particle_type
78 : USE pw_env_types, ONLY: pw_env_get,&
79 : pw_env_type
80 : USE pw_methods, ONLY: pw_axpy,&
81 : pw_copy,&
82 : pw_derive,&
83 : pw_integral_ab,&
84 : pw_scale,&
85 : pw_transfer,&
86 : pw_zero
87 : USE pw_poisson_methods, ONLY: pw_poisson_solve
88 : USE pw_poisson_types, ONLY: pw_poisson_type
89 : USE pw_pool_types, ONLY: pw_pool_type
90 : USE pw_types, ONLY: pw_c1d_gs_type,&
91 : pw_r3d_rs_type
92 : USE qs_2nd_kernel_ao, ONLY: apply_2nd_order_kernel
93 : USE qs_density_matrices, ONLY: calculate_whz_matrix
94 : USE qs_dispersion_pairpot, ONLY: calculate_dispersion_pairpot
95 : USE qs_dispersion_types, ONLY: qs_dispersion_type
96 : USE qs_energy_types, ONLY: qs_energy_type
97 : USE qs_environment_types, ONLY: get_qs_env,&
98 : qs_environment_type,&
99 : set_qs_env
100 : USE qs_force_types, ONLY: deallocate_qs_force,&
101 : qs_force_type,&
102 : sum_qs_force,&
103 : zero_qs_force
104 : USE qs_integrate_potential, ONLY: integrate_v_core_rspace,&
105 : integrate_v_rspace
106 : USE qs_kind_types, ONLY: qs_kind_type
107 : USE qs_kinetic, ONLY: build_kinetic_matrix
108 : USE qs_ks_reference, ONLY: ks_ref_potential
109 : USE qs_ks_types, ONLY: qs_ks_env_type,&
110 : set_ks_env
111 : USE qs_linres_types, ONLY: linres_control_type
112 : USE qs_mo_types, ONLY: get_mo_set,&
113 : mo_set_type
114 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
115 : USE qs_overlap, ONLY: build_overlap_matrix
116 : USE qs_p_env_methods, ONLY: p_env_check_i_alloc,&
117 : p_env_create,&
118 : p_env_psi0_changed,&
119 : p_env_update_rho
120 : USE qs_p_env_types, ONLY: p_env_release,&
121 : qs_p_env_type
122 : USE qs_rho_types, ONLY: qs_rho_get,&
123 : qs_rho_type
124 : USE task_list_types, ONLY: task_list_type
125 : USE virial_types, ONLY: virial_type,&
126 : zero_virial
127 :
128 : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
129 :
130 : #include "./base/base_uses.f90"
131 :
132 : IMPLICIT NONE
133 :
134 : PRIVATE
135 :
136 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mp2_cphf'
137 : LOGICAL, PARAMETER, PRIVATE :: debug_forces = .TRUE.
138 :
139 : PUBLIC :: solve_z_vector_eq, update_mp2_forces
140 :
141 : CONTAINS
142 :
143 : ! **************************************************************************************************
144 : !> \brief Solve Z-vector equations necessary for the calculation of the MP2
145 : !> gradients, in order to be consistent here the parameters for the
146 : !> calculation of the CPHF like updats have to be exactly equal to the
147 : !> SCF case
148 : !> \param qs_env ...
149 : !> \param mp2_env ...
150 : !> \param para_env ...
151 : !> \param dft_control ...
152 : !> \param mo_coeff ...
153 : !> \param nmo ...
154 : !> \param homo ...
155 : !> \param Eigenval ...
156 : !> \param unit_nr ...
157 : !> \author Mauro Del Ben, Vladimir Rybkin
158 : ! **************************************************************************************************
159 264 : SUBROUTINE solve_z_vector_eq(qs_env, mp2_env, para_env, dft_control, &
160 264 : mo_coeff, nmo, homo, Eigenval, unit_nr)
161 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
162 : TYPE(mp2_type), INTENT(INOUT) :: mp2_env
163 : TYPE(mp_para_env_type), INTENT(IN), POINTER :: para_env
164 : TYPE(dft_control_type), INTENT(IN), POINTER :: dft_control
165 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: mo_coeff
166 : INTEGER, INTENT(IN) :: nmo
167 : INTEGER, DIMENSION(:), INTENT(IN) :: homo
168 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: Eigenval
169 : INTEGER, INTENT(IN) :: unit_nr
170 :
171 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_eq'
172 :
173 : INTEGER :: bin, dimen, handle, handle2, i, i_global, i_thread, iiB, irep, ispin, j_global, &
174 : jjB, my_bin_size, n_rep_hf, n_threads, ncol_local, nrow_local, nspins, transf_type_in
175 264 : INTEGER, ALLOCATABLE, DIMENSION(:) :: virtual
176 264 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
177 : LOGICAL :: alpha_beta, do_dynamic_load_balancing, &
178 : do_exx, do_hfx, restore_p_screen
179 : REAL(KIND=dp) :: focc
180 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
181 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
182 : TYPE(cp_fm_type) :: fm_back, fm_G_mu_nu
183 264 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: L_jb, mo_coeff_o, mo_coeff_v, P_ia, &
184 264 : P_mo, W_Mo
185 264 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_p_mp2, &
186 264 : matrix_p_mp2_admm, matrix_s, P_mu_nu, &
187 264 : rho1_ao, rho_ao, rho_ao_aux_fit
188 264 : TYPE(hfx_container_type), DIMENSION(:), POINTER :: integral_containers
189 : TYPE(hfx_container_type), POINTER :: maxval_container
190 : TYPE(hfx_type), POINTER :: actual_x_data
191 : TYPE(linres_control_type), POINTER :: linres_control
192 : TYPE(qs_ks_env_type), POINTER :: ks_env
193 : TYPE(qs_p_env_type), POINTER :: p_env
194 : TYPE(qs_rho_type), POINTER :: rho, rho_aux_fit
195 : TYPE(section_vals_type), POINTER :: hfx_section, hfx_sections, input
196 :
197 264 : CALL timeset(routineN, handle)
198 :
199 : ! start collecting stuff
200 264 : dimen = nmo
201 264 : NULLIFY (input, matrix_s, blacs_env, rho, &
202 264 : matrix_p_mp2, matrix_p_mp2_admm, matrix_ks)
203 : CALL get_qs_env(qs_env, &
204 : ks_env=ks_env, &
205 : input=input, &
206 : matrix_s=matrix_s, &
207 : matrix_ks=matrix_ks, &
208 : matrix_p_mp2=matrix_p_mp2, &
209 : matrix_p_mp2_admm=matrix_p_mp2_admm, &
210 : blacs_env=blacs_env, &
211 264 : rho=rho)
212 :
213 264 : CALL qs_rho_get(rho, rho_ao=rho_ao)
214 :
215 : ! Get number of relevant spin states
216 264 : nspins = dft_control%nspins
217 264 : alpha_beta = (nspins == 2)
218 :
219 264 : CALL MOVE_ALLOC(mp2_env%ri_grad%P_mo, P_mo)
220 264 : CALL MOVE_ALLOC(mp2_env%ri_grad%W_mo, W_mo)
221 264 : CALL MOVE_ALLOC(mp2_env%ri_grad%L_jb, L_jb)
222 :
223 792 : ALLOCATE (virtual(nspins))
224 614 : virtual(:) = dimen - homo(:)
225 :
226 264 : NULLIFY (P_mu_nu)
227 264 : CALL dbcsr_allocate_matrix_set(P_mu_nu, nspins)
228 614 : DO ispin = 1, nspins
229 350 : ALLOCATE (P_mu_nu(ispin)%matrix)
230 350 : CALL dbcsr_copy(P_mu_nu(ispin)%matrix, rho_ao(1)%matrix, name="P_mu_nu")
231 614 : CALL dbcsr_set(P_mu_nu(ispin)%matrix, 0.0_dp)
232 : END DO
233 :
234 264 : NULLIFY (fm_struct_tmp)
235 : CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
236 264 : nrow_global=dimen, ncol_global=dimen)
237 264 : CALL cp_fm_create(fm_G_mu_nu, fm_struct_tmp, name="G_mu_nu")
238 264 : CALL cp_fm_create(fm_back, fm_struct_tmp, name="fm_back")
239 264 : CALL cp_fm_struct_release(fm_struct_tmp)
240 264 : CALL cp_fm_set_all(fm_G_mu_nu, 0.0_dp)
241 264 : CALL cp_fm_set_all(fm_back, 0.0_dp)
242 :
243 1756 : ALLOCATE (mo_coeff_o(nspins), mo_coeff_v(nspins))
244 614 : DO ispin = 1, nspins
245 350 : NULLIFY (fm_struct_tmp)
246 : CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
247 350 : nrow_global=dimen, ncol_global=homo(ispin))
248 350 : CALL cp_fm_create(mo_coeff_o(ispin), fm_struct_tmp, name="mo_coeff_o")
249 350 : CALL cp_fm_struct_release(fm_struct_tmp)
250 350 : CALL cp_fm_set_all(mo_coeff_o(ispin), 0.0_dp)
251 : CALL cp_fm_to_fm_submat(msource=mo_coeff(ispin), mtarget=mo_coeff_o(ispin), &
252 : nrow=dimen, ncol=homo(ispin), &
253 : s_firstrow=1, s_firstcol=1, &
254 350 : t_firstrow=1, t_firstcol=1)
255 :
256 350 : NULLIFY (fm_struct_tmp)
257 : CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
258 350 : nrow_global=dimen, ncol_global=virtual(ispin))
259 350 : CALL cp_fm_create(mo_coeff_v(ispin), fm_struct_tmp, name="mo_coeff_v")
260 350 : CALL cp_fm_struct_release(fm_struct_tmp)
261 350 : CALL cp_fm_set_all(mo_coeff_v(ispin), 0.0_dp)
262 : CALL cp_fm_to_fm_submat(msource=mo_coeff(ispin), mtarget=mo_coeff_v(ispin), &
263 : nrow=dimen, ncol=virtual(ispin), &
264 : s_firstrow=1, s_firstcol=homo(ispin) + 1, &
265 614 : t_firstrow=1, t_firstcol=1)
266 : END DO
267 :
268 : ! hfx section
269 264 : NULLIFY (hfx_sections)
270 264 : hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
271 264 : CALL section_vals_get(hfx_sections, explicit=do_hfx, n_repetition=n_rep_hf)
272 264 : IF (do_hfx) THEN
273 : ! here we check if we have to reallocate the HFX container
274 184 : IF (mp2_env%ri_grad%free_hfx_buffer .AND. (.NOT. qs_env%x_data(1, 1)%do_hfx_ri)) THEN
275 98 : CALL timeset(routineN//"_alloc_hfx", handle2)
276 98 : n_threads = 1
277 98 : !$ n_threads = omp_get_max_threads()
278 :
279 196 : DO irep = 1, n_rep_hf
280 294 : DO i_thread = 0, n_threads - 1
281 98 : actual_x_data => qs_env%x_data(irep, i_thread + 1)
282 :
283 98 : do_dynamic_load_balancing = .TRUE.
284 98 : IF (n_threads == 1 .OR. actual_x_data%memory_parameter%do_disk_storage) do_dynamic_load_balancing = .FALSE.
285 :
286 : IF (do_dynamic_load_balancing) THEN
287 0 : my_bin_size = SIZE(actual_x_data%distribution_energy)
288 : ELSE
289 98 : my_bin_size = 1
290 : END IF
291 :
292 196 : IF (.NOT. actual_x_data%memory_parameter%do_all_on_the_fly) THEN
293 98 : CALL alloc_containers(actual_x_data%store_ints, my_bin_size)
294 :
295 196 : DO bin = 1, my_bin_size
296 98 : maxval_container => actual_x_data%store_ints%maxval_container(bin)
297 98 : integral_containers => actual_x_data%store_ints%integral_containers(:, bin)
298 98 : CALL hfx_init_container(maxval_container, actual_x_data%memory_parameter%actual_memory_usage, .FALSE.)
299 6468 : DO i = 1, 64
300 : CALL hfx_init_container(integral_containers(i), &
301 6370 : actual_x_data%memory_parameter%actual_memory_usage, .FALSE.)
302 : END DO
303 : END DO
304 : END IF
305 : END DO
306 : END DO
307 98 : CALL timestop(handle2)
308 : END IF
309 :
310 : ! set up parameters for P_screening
311 184 : restore_p_screen = qs_env%x_data(1, 1)%screening_parameter%do_initial_p_screening
312 184 : IF (qs_env%x_data(1, 1)%screening_parameter%do_initial_p_screening) THEN
313 8 : IF (mp2_env%ri_grad%free_hfx_buffer) THEN
314 8 : mp2_env%p_screen = .FALSE.
315 : ELSE
316 0 : mp2_env%p_screen = .TRUE.
317 : END IF
318 : END IF
319 : END IF
320 :
321 : ! Add exx part for RPA
322 264 : do_exx = .FALSE.
323 264 : IF (qs_env%mp2_env%method == ri_rpa_method_gpw) THEN
324 20 : hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
325 20 : CALL section_vals_get(hfx_section, explicit=do_exx)
326 : END IF
327 264 : IF (do_exx) THEN
328 : CALL add_exx_to_rhs(rhs=P_mu_nu, &
329 : qs_env=qs_env, &
330 : ext_hfx_section=hfx_section, &
331 : x_data=mp2_env%ri_rpa%x_data, &
332 : recalc_integrals=.FALSE., &
333 : do_admm=mp2_env%ri_rpa%do_admm, &
334 : do_exx=do_exx, &
335 8 : reuse_hfx=mp2_env%ri_rpa%reuse_hfx)
336 :
337 8 : focc = 1.0_dp
338 8 : IF (nspins == 1) focc = 2.0_dp
339 : !focc = 0.0_dp
340 16 : DO ispin = 1, nspins
341 8 : CALL dbcsr_add(P_mu_nu(ispin)%matrix, matrix_ks(ispin)%matrix, 1.0_dp, -1.0_dp)
342 8 : CALL copy_dbcsr_to_fm(matrix=P_mu_nu(ispin)%matrix, fm=fm_G_mu_nu)
343 : CALL parallel_gemm("N", "N", dimen, homo(ispin), dimen, 1.0_dp, &
344 8 : fm_G_mu_nu, mo_coeff_o(ispin), 0.0_dp, fm_back)
345 : CALL parallel_gemm("T", "N", homo(ispin), virtual(ispin), dimen, focc, &
346 8 : fm_back, mo_coeff_v(ispin), 1.0_dp, L_jb(ispin))
347 : CALL parallel_gemm("T", "N", homo(ispin), homo(ispin), dimen, -focc, &
348 16 : fm_back, mo_coeff_o(ispin), 1.0_dp, W_mo(ispin))
349 : END DO
350 : END IF
351 :
352 : ! Prepare arrays for linres code
353 : NULLIFY (linres_control)
354 264 : ALLOCATE (linres_control)
355 264 : linres_control%do_kernel = .TRUE.
356 : linres_control%lr_triplet = .FALSE.
357 : linres_control%linres_restart = .FALSE.
358 264 : linres_control%max_iter = mp2_env%ri_grad%cphf_max_num_iter
359 264 : linres_control%eps = mp2_env%ri_grad%cphf_eps_conv
360 264 : linres_control%eps_filter = mp2_env%mp2_gpw%eps_filter
361 264 : linres_control%restart_every = 50
362 264 : linres_control%preconditioner_type = ot_precond_full_all
363 264 : linres_control%energy_gap = 0.02_dp
364 :
365 : NULLIFY (p_env)
366 1848 : ALLOCATE (p_env)
367 264 : CALL p_env_create(p_env, qs_env, p1_option=P_mu_nu, orthogonal_orbitals=.TRUE., linres_control=linres_control)
368 264 : CALL set_qs_env(qs_env, linres_control=linres_control)
369 264 : CALL p_env_psi0_changed(p_env, qs_env)
370 264 : p_env%new_preconditioner = .TRUE.
371 264 : CALL p_env_check_i_alloc(p_env, qs_env)
372 264 : mp2_env%ri_grad%p_env => p_env
373 :
374 : ! update Lagrangian with the CPHF like update, occ-occ block, first call (recompute hfx integrals if needed)
375 264 : transf_type_in = 1
376 : ! In alpha-beta case, L_bj_alpha has Coulomb and XC alpha-alpha part
377 : ! and (only) Coulomb alpha-beta part and vice versa.
378 :
379 : ! Complete in closed shell case, alpha-alpha (Coulomb and XC)
380 : ! part of L_bj(alpha) for open shell
381 :
382 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
383 : mo_coeff_o, &
384 : mo_coeff_v, Eigenval, p_env, &
385 : P_mo, fm_G_mu_nu, fm_back, transf_type_in, &
386 : L_jb, &
387 : recalc_hfx_integrals=(.NOT. do_exx .AND. mp2_env%ri_grad%free_hfx_buffer) &
388 352 : .OR. (do_exx .AND. .NOT. mp2_env%ri_rpa%reuse_hfx))
389 :
390 : ! at this point Lagrangian is completed ready to solve the Z-vector equations
391 : ! P_ia will contain the solution of these equations
392 878 : ALLOCATE (P_ia(nspins))
393 614 : DO ispin = 1, nspins
394 350 : NULLIFY (fm_struct_tmp)
395 : CALL cp_fm_struct_create(fm_struct_tmp, para_env=para_env, context=blacs_env, &
396 350 : nrow_global=homo(ispin), ncol_global=virtual(ispin))
397 350 : CALL cp_fm_create(P_ia(ispin), fm_struct_tmp, name="P_ia")
398 350 : CALL cp_fm_struct_release(fm_struct_tmp)
399 614 : CALL cp_fm_set_all(P_ia(ispin), 0.0_dp)
400 : END DO
401 :
402 : CALL solve_z_vector_eq_low(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
403 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
404 264 : L_jb, fm_G_mu_nu, fm_back, P_ia)
405 :
406 : ! release fm stuff
407 264 : CALL cp_fm_release(fm_G_mu_nu)
408 264 : CALL cp_fm_release(L_jb)
409 264 : CALL cp_fm_release(mo_coeff_o)
410 264 : CALL cp_fm_release(mo_coeff_v)
411 :
412 614 : DO ispin = 1, nspins
413 : ! update the MP2-MO density matrix with the occ-virt block
414 : CALL cp_fm_to_fm_submat(msource=P_ia(ispin), mtarget=P_mo(ispin), &
415 : nrow=homo(ispin), ncol=virtual(ispin), &
416 : s_firstrow=1, s_firstcol=1, &
417 350 : t_firstrow=1, t_firstcol=homo(ispin) + 1)
418 : ! transpose P_MO matrix (easy way to symmetrize)
419 350 : CALL cp_fm_set_all(fm_back, 0.0_dp)
420 : ! P_mo now is ready
421 614 : CALL cp_fm_uplo_to_full(matrix=P_mo(ispin), work=fm_back)
422 : END DO
423 264 : CALL cp_fm_release(P_ia)
424 :
425 : ! do the final update to the energy weighted matrix W_MO
426 614 : DO ispin = 1, nspins
427 : CALL cp_fm_get_info(matrix=W_mo(ispin), &
428 : nrow_local=nrow_local, &
429 : ncol_local=ncol_local, &
430 : row_indices=row_indices, &
431 350 : col_indices=col_indices)
432 7216 : DO jjB = 1, ncol_local
433 6602 : j_global = col_indices(jjB)
434 6952 : IF (j_global <= homo(ispin)) THEN
435 13622 : DO iiB = 1, nrow_local
436 12352 : i_global = row_indices(iiB)
437 : W_mo(ispin)%local_data(iiB, jjB) = W_mo(ispin)%local_data(iiB, jjB) &
438 12352 : - P_mo(ispin)%local_data(iiB, jjB)*Eigenval(j_global, ispin)
439 12352 : IF (i_global == j_global .AND. nspins == 1) W_mo(ispin)%local_data(iiB, jjB) = &
440 343 : W_mo(ispin)%local_data(iiB, jjB) - 2.0_dp*Eigenval(j_global, ispin)
441 12352 : IF (i_global == j_global .AND. nspins == 2) W_mo(ispin)%local_data(iiB, jjB) = &
442 1562 : W_mo(ispin)%local_data(iiB, jjB) - Eigenval(j_global, ispin)
443 : END DO
444 : ELSE
445 66159 : DO iiB = 1, nrow_local
446 60827 : i_global = row_indices(iiB)
447 66159 : IF (i_global <= homo(ispin)) THEN
448 : ! virt-occ
449 : W_mo(ispin)%local_data(iiB, jjB) = W_mo(ispin)%local_data(iiB, jjB) &
450 9917 : - P_mo(ispin)%local_data(iiB, jjB)*Eigenval(i_global, ispin)
451 : ELSE
452 : ! virt-virt
453 : W_mo(ispin)%local_data(iiB, jjB) = W_mo(ispin)%local_data(iiB, jjB) &
454 50910 : - P_mo(ispin)%local_data(iiB, jjB)*Eigenval(j_global, ispin)
455 : END IF
456 : END DO
457 : END IF
458 : END DO
459 : END DO
460 :
461 : ! create the MP2 energy weighted density matrix
462 264 : NULLIFY (p_env%w1)
463 264 : CALL dbcsr_allocate_matrix_set(p_env%w1, 1)
464 264 : ALLOCATE (p_env%w1(1)%matrix)
465 : CALL dbcsr_copy(p_env%w1(1)%matrix, matrix_s(1)%matrix, &
466 264 : name="W MATRIX MP2")
467 264 : CALL dbcsr_set(p_env%w1(1)%matrix, 0.0_dp)
468 :
469 : ! backtnsform the collected parts of the energy-weighted density matrix into AO basis
470 614 : DO ispin = 1, nspins
471 : CALL parallel_gemm('N', 'N', dimen, dimen, dimen, 1.0_dp, &
472 350 : mo_coeff(ispin), W_mo(ispin), 0.0_dp, fm_back)
473 614 : CALL cp_dbcsr_plus_fm_fm_t(p_env%w1(1)%matrix, fm_back, mo_coeff(ispin), dimen, 1.0_dp, .TRUE., 1)
474 : END DO
475 264 : CALL cp_fm_release(W_mo)
476 :
477 264 : CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
478 :
479 614 : DO ispin = 1, nspins
480 350 : CALL dbcsr_set(p_env%p1(ispin)%matrix, 0.0_dp)
481 :
482 : CALL parallel_gemm('N', 'N', dimen, dimen, dimen, 1.0_dp, &
483 350 : mo_coeff(ispin), P_mo(ispin), 0.0_dp, fm_back)
484 350 : CALL cp_dbcsr_plus_fm_fm_t(p_env%p1(ispin)%matrix, fm_back, mo_coeff(ispin), dimen, 1.0_dp, .TRUE.)
485 :
486 614 : CALL dbcsr_copy(rho1_ao(ispin)%matrix, p_env%p1(ispin)%matrix)
487 : END DO
488 264 : CALL cp_fm_release(P_mo)
489 264 : CALL cp_fm_release(fm_back)
490 :
491 264 : CALL p_env_update_rho(p_env, qs_env)
492 :
493 : ! create mp2 DBCSR density
494 264 : CALL dbcsr_allocate_matrix_set(matrix_p_mp2, nspins)
495 614 : DO ispin = 1, nspins
496 350 : ALLOCATE (matrix_p_mp2(ispin)%matrix)
497 : CALL dbcsr_copy(matrix_p_mp2(ispin)%matrix, p_env%p1(ispin)%matrix, &
498 614 : name="P MATRIX MP2")
499 : END DO
500 :
501 264 : IF (dft_control%do_admm) THEN
502 40 : CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux_fit)
503 40 : CALL qs_rho_get(rho_aux_fit, rho_ao=rho_ao_aux_fit)
504 :
505 : ! create mp2 DBCSR density in auxiliary basis
506 40 : CALL dbcsr_allocate_matrix_set(matrix_p_mp2_admm, nspins)
507 98 : DO ispin = 1, nspins
508 58 : ALLOCATE (matrix_p_mp2_admm(ispin)%matrix)
509 : CALL dbcsr_copy(matrix_p_mp2_admm(ispin)%matrix, p_env%p1_admm(ispin)%matrix, &
510 98 : name="P MATRIX MP2 ADMM")
511 : END DO
512 : END IF
513 :
514 264 : CALL set_ks_env(ks_env, matrix_p_mp2=matrix_p_mp2, matrix_p_mp2_admm=matrix_p_mp2_admm)
515 :
516 : ! We will need one more hfx calculation for HF gradient part
517 264 : mp2_env%not_last_hfx = .FALSE.
518 264 : mp2_env%p_screen = restore_p_screen
519 :
520 264 : CALL timestop(handle)
521 :
522 1056 : END SUBROUTINE solve_z_vector_eq
523 :
524 : ! **************************************************************************************************
525 : !> \brief Here we performe the CPHF like update using GPW,
526 : !> transf_type_in defines the type of transformation for the matrix in input
527 : !> transf_type_in = 1 -> occ-occ back transformation
528 : !> transf_type_in = 2 -> virt-virt back transformation
529 : !> transf_type_in = 3 -> occ-virt back transformation including the
530 : !> eigenvalues energy differences for the diagonal elements
531 : !> \param qs_env ...
532 : !> \param homo ...
533 : !> \param virtual ...
534 : !> \param dimen ...
535 : !> \param nspins ...
536 : !> \param mo_coeff_o ...
537 : !> \param mo_coeff_v ...
538 : !> \param Eigenval ...
539 : !> \param p_env ...
540 : !> \param fm_mo ...
541 : !> \param fm_ao ...
542 : !> \param fm_back ...
543 : !> \param transf_type_in ...
544 : !> \param fm_mo_out ...
545 : !> \param recalc_hfx_integrals ...
546 : !> \author Mauro Del Ben, Vladimir Rybkin
547 : ! **************************************************************************************************
548 1470 : SUBROUTINE cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
549 1470 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
550 1470 : fm_mo, fm_ao, fm_back, transf_type_in, &
551 1470 : fm_mo_out, recalc_hfx_integrals)
552 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
553 : INTEGER, INTENT(IN) :: nspins, dimen
554 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
555 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
556 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
557 : INTENT(IN) :: Eigenval
558 : TYPE(qs_p_env_type) :: p_env
559 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: fm_mo
560 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_ao
561 : TYPE(cp_fm_type), INTENT(IN) :: fm_back
562 : INTEGER, INTENT(IN) :: transf_type_in
563 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: fm_mo_out
564 : LOGICAL, INTENT(IN), OPTIONAL :: recalc_hfx_integrals
565 :
566 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cphf_like_update'
567 :
568 : INTEGER :: handle, i_global, iiB, ispin, j_global, &
569 : jjB, ncol_local, nrow_local
570 1470 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
571 1470 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho1_ao
572 :
573 1470 : CALL timeset(routineN, handle)
574 :
575 1470 : CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
576 :
577 : ! Determine the first-order density matrices in AO basis
578 3404 : DO ispin = 1, nspins
579 1934 : CALL dbcsr_set(p_env%p1(ispin)%matrix, 0.0_dp)
580 :
581 : ASSOCIATE (mat_in => fm_mo(ispin))
582 :
583 : ! perform back transformation
584 2284 : SELECT CASE (transf_type_in)
585 : CASE (1)
586 : ! occ-occ block
587 : CALL parallel_gemm('N', 'N', dimen, homo(ispin), homo(ispin), 1.0_dp, &
588 350 : mo_coeff_o(ispin), mat_in, 0.0_dp, fm_back)
589 350 : CALL cp_dbcsr_plus_fm_fm_t(p_env%p1(ispin)%matrix, fm_back, mo_coeff_o(ispin), homo(ispin), 1.0_dp, .TRUE.)
590 : ! virt-virt block
591 : CALL parallel_gemm('N', 'N', dimen, virtual(ispin), virtual(ispin), 1.0_dp, &
592 : mo_coeff_v(ispin), mat_in, 0.0_dp, fm_back, &
593 : b_first_col=homo(ispin) + 1, &
594 350 : b_first_row=homo(ispin) + 1)
595 350 : CALL cp_dbcsr_plus_fm_fm_t(p_env%p1(ispin)%matrix, fm_back, mo_coeff_v(ispin), virtual(ispin), 1.0_dp, .TRUE.)
596 :
597 : CASE (3)
598 : ! virt-occ blocks
599 : CALL parallel_gemm('N', 'N', dimen, virtual(ispin), homo(ispin), 1.0_dp, &
600 1584 : mo_coeff_o(ispin), mat_in, 0.0_dp, fm_back)
601 1584 : CALL cp_dbcsr_plus_fm_fm_t(p_env%p1(ispin)%matrix, fm_back, mo_coeff_v(ispin), virtual(ispin), 1.0_dp, .TRUE.)
602 : ! and symmetrize (here again multiply instead of transposing)
603 : CALL parallel_gemm('N', 'T', dimen, homo(ispin), virtual(ispin), 1.0_dp, &
604 1584 : mo_coeff_v(ispin), mat_in, 0.0_dp, fm_back)
605 3518 : CALL cp_dbcsr_plus_fm_fm_t(p_env%p1(ispin)%matrix, fm_back, mo_coeff_o(ispin), homo(ispin), 1.0_dp, .TRUE.)
606 :
607 : CASE DEFAULT
608 : ! nothing
609 : END SELECT
610 : END ASSOCIATE
611 :
612 3404 : CALL dbcsr_copy(rho1_ao(ispin)%matrix, p_env%p1(ispin)%matrix)
613 : END DO
614 :
615 1470 : CALL p_env_update_rho(p_env, qs_env)
616 :
617 1470 : IF (transf_type_in == 3) THEN
618 2790 : DO ispin = 1, nspins
619 :
620 : ! scale for the orbital energy differences for the diagonal elements
621 : CALL cp_fm_get_info(matrix=fm_mo_out(ispin), &
622 : nrow_local=nrow_local, &
623 : ncol_local=ncol_local, &
624 : row_indices=row_indices, &
625 1584 : col_indices=col_indices)
626 28696 : DO jjB = 1, ncol_local
627 25906 : j_global = col_indices(jjB)
628 77387 : DO iiB = 1, nrow_local
629 49897 : i_global = row_indices(iiB)
630 : fm_mo_out(ispin)%local_data(iiB, jjB) = fm_mo(ispin)%local_data(iiB, jjB)* &
631 75803 : (Eigenval(j_global + homo(ispin), ispin) - Eigenval(i_global, ispin))
632 : END DO
633 : END DO
634 : END DO
635 : END IF
636 :
637 1470 : CALL apply_2nd_order_kernel(qs_env, p_env, recalc_hfx_integrals)
638 :
639 3404 : DO ispin = 1, nspins
640 : ! copy back to fm
641 1934 : CALL cp_fm_set_all(fm_ao, 0.0_dp)
642 1934 : CALL copy_dbcsr_to_fm(matrix=p_env%kpp1(ispin)%matrix, fm=fm_ao)
643 1934 : CALL cp_fm_set_all(fm_back, 0.0_dp)
644 1934 : CALL cp_fm_uplo_to_full(fm_ao, fm_back)
645 :
646 1470 : ASSOCIATE (mat_out => fm_mo_out(ispin))
647 :
648 : ! transform to MO basis, here we always sum the result into the input matrix
649 :
650 : ! occ-virt block
651 : CALL parallel_gemm('T', 'N', homo(ispin), dimen, dimen, 1.0_dp, &
652 1934 : mo_coeff_o(ispin), fm_ao, 0.0_dp, fm_back)
653 : CALL parallel_gemm('N', 'N', homo(ispin), virtual(ispin), dimen, 1.0_dp, &
654 1934 : fm_back, mo_coeff_v(ispin), 1.0_dp, mat_out)
655 : END ASSOCIATE
656 : END DO
657 :
658 1470 : CALL timestop(handle)
659 :
660 1470 : END SUBROUTINE cphf_like_update
661 :
662 : ! **************************************************************************************************
663 : !> \brief Low level subroutine for the iterative solution of a large
664 : !> system of linear equation
665 : !> \param qs_env ...
666 : !> \param mp2_env ...
667 : !> \param homo ...
668 : !> \param virtual ...
669 : !> \param dimen ...
670 : !> \param unit_nr ...
671 : !> \param nspins ...
672 : !> \param mo_coeff_o ...
673 : !> \param mo_coeff_v ...
674 : !> \param Eigenval ...
675 : !> \param p_env ...
676 : !> \param L_jb ...
677 : !> \param fm_G_mu_nu ...
678 : !> \param fm_back ...
679 : !> \param P_ia ...
680 : !> \author Mauro Del Ben, Vladimir Rybkin
681 : ! **************************************************************************************************
682 264 : SUBROUTINE solve_z_vector_eq_low(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
683 264 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
684 264 : L_jb, fm_G_mu_nu, fm_back, P_ia)
685 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
686 : TYPE(mp2_type), INTENT(IN) :: mp2_env
687 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
688 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
689 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
690 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
691 : INTENT(IN) :: Eigenval
692 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
693 : TYPE(cp_fm_type), DIMENSION(dimen), INTENT(IN) :: L_jb
694 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_G_mu_nu
695 : TYPE(cp_fm_type), INTENT(IN) :: fm_back
696 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia
697 :
698 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_eq_low'
699 :
700 : INTEGER :: handle, i_global, iiB, ispin, j_global, &
701 : jjB, ncol_local, nrow_local
702 264 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
703 264 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: precond
704 :
705 264 : CALL timeset(routineN, handle)
706 :
707 : ! Pople method
708 : ! change sign to L_jb
709 614 : DO ispin = 1, nspins
710 15890 : L_jb(ispin)%local_data(:, :) = -L_jb(ispin)%local_data(:, :)
711 : END DO
712 :
713 : ! create fm structure
714 1142 : ALLOCATE (precond(nspins))
715 614 : DO ispin = 1, nspins
716 : ! create preconditioner (for now only orbital energy differences)
717 350 : CALL cp_fm_create(precond(ispin), P_ia(ispin)%matrix_struct, name="precond")
718 350 : CALL cp_fm_set_all(precond(ispin), 1.0_dp)
719 : CALL cp_fm_get_info(matrix=precond(ispin), &
720 : nrow_local=nrow_local, &
721 : ncol_local=ncol_local, &
722 : row_indices=row_indices, &
723 350 : col_indices=col_indices)
724 5946 : DO jjB = 1, ncol_local
725 5332 : j_global = col_indices(jjB)
726 15599 : DO iiB = 1, nrow_local
727 9917 : i_global = row_indices(iiB)
728 15249 : precond(ispin)%local_data(iiB, jjB) = Eigenval(j_global + homo(ispin), ispin) - Eigenval(i_global, ispin)
729 : END DO
730 : END DO
731 : END DO
732 :
733 614 : DO ispin = 1, nspins
734 15890 : precond(ispin)%local_data(:, :) = 1.0_dp/precond(ispin)%local_data(:, :)
735 : END DO
736 :
737 504 : SELECT CASE (mp2_env%ri_grad%z_solver_method)
738 : CASE (z_solver_pople)
739 : CALL solve_z_vector_pople(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
740 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
741 240 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
742 : CASE (z_solver_cg, z_solver_richardson, z_solver_sd)
743 : CALL solve_z_vector_cg(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
744 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
745 24 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
746 : CASE DEFAULT
747 264 : CPABORT("Unknown solver")
748 : END SELECT
749 :
750 264 : CALL cp_fm_release(precond)
751 :
752 264 : CALL timestop(handle)
753 :
754 528 : END SUBROUTINE solve_z_vector_eq_low
755 :
756 : ! **************************************************************************************************
757 : !> \brief ...
758 : !> \param qs_env ...
759 : !> \param mp2_env ...
760 : !> \param homo ...
761 : !> \param virtual ...
762 : !> \param dimen ...
763 : !> \param unit_nr ...
764 : !> \param nspins ...
765 : !> \param mo_coeff_o ...
766 : !> \param mo_coeff_v ...
767 : !> \param Eigenval ...
768 : !> \param p_env ...
769 : !> \param L_jb ...
770 : !> \param fm_G_mu_nu ...
771 : !> \param fm_back ...
772 : !> \param P_ia ...
773 : !> \param precond ...
774 : ! **************************************************************************************************
775 240 : SUBROUTINE solve_z_vector_pople(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
776 240 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
777 240 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
778 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
779 : TYPE(mp2_type), INTENT(IN) :: mp2_env
780 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
781 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
782 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
783 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
784 : INTENT(IN) :: Eigenval
785 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
786 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: L_jb
787 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_G_mu_nu
788 : TYPE(cp_fm_type), INTENT(IN) :: fm_back
789 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia, precond
790 :
791 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_pople'
792 :
793 : INTEGER :: cycle_counter, handle, iiB, iiter, &
794 : ispin, max_num_iter, transf_type_in
795 : LOGICAL :: converged
796 : REAL(KIND=dp) :: conv, eps_conv, scale_cphf, t1, t2
797 240 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: proj_bi_xj, temp_vals, x_norm, xi_b
798 240 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: A_small, b_small, xi_Axi
799 : TYPE(cp_fm_struct_p_type), ALLOCATABLE, &
800 240 : DIMENSION(:) :: fm_struct_tmp
801 240 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: b_i, residual
802 240 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: Ax, xn
803 :
804 240 : CALL timeset(routineN, handle)
805 :
806 240 : eps_conv = mp2_env%ri_grad%cphf_eps_conv
807 :
808 240 : IF (accurate_dot_product_spin(L_jb, L_jb) >= (eps_conv*eps_conv)) THEN
809 :
810 240 : max_num_iter = mp2_env%ri_grad%cphf_max_num_iter
811 240 : scale_cphf = mp2_env%ri_grad%scale_step_size
812 :
813 : ! set the transformation type (equal for all methods all updates)
814 240 : transf_type_in = 3
815 :
816 : ! set convergence flag
817 240 : converged = .FALSE.
818 :
819 2418 : ALLOCATE (fm_struct_tmp(nspins), b_i(nspins), residual(nspins))
820 566 : DO ispin = 1, nspins
821 326 : fm_struct_tmp(ispin)%struct => P_ia(ispin)%matrix_struct
822 :
823 326 : CALL cp_fm_create(b_i(ispin), fm_struct_tmp(ispin)%struct, name="b_i")
824 326 : CALL cp_fm_set_all(b_i(ispin), 0.0_dp)
825 14234 : b_i(ispin)%local_data(:, :) = precond(ispin)%local_data(:, :)*L_jb(ispin)%local_data(:, :)
826 :
827 : ! create the residual vector (r), we check convergence on the norm of
828 : ! this vector r=(Ax-b)
829 326 : CALL cp_fm_create(residual(ispin), fm_struct_tmp(ispin)%struct, name="residual")
830 566 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
831 : END DO
832 :
833 240 : IF (unit_nr > 0) THEN
834 120 : WRITE (unit_nr, *)
835 120 : WRITE (unit_nr, '(T3,A)') "MP2_CPHF| Iterative solution of Z-Vector equations (Pople's method)"
836 120 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Convergence threshold:', eps_conv
837 120 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Maximum number of iterations: ', max_num_iter
838 120 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Scaling of initial guess: ', scale_cphf
839 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
840 120 : WRITE (unit_nr, '(T4,A,T15,A,T33,A)') 'Step', 'Time', 'Convergence'
841 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
842 : END IF
843 :
844 11530 : ALLOCATE (xn(nspins, max_num_iter))
845 11290 : ALLOCATE (Ax(nspins, max_num_iter))
846 720 : ALLOCATE (x_norm(max_num_iter))
847 480 : ALLOCATE (xi_b(max_num_iter))
848 960 : ALLOCATE (xi_Axi(max_num_iter, 0:max_num_iter))
849 4778 : x_norm = 0.0_dp
850 4778 : xi_b = 0.0_dp
851 134774 : xi_Axi = 0.0_dp
852 :
853 240 : cycle_counter = 0
854 1022 : DO iiter = 1, max_num_iter
855 1000 : cycle_counter = cycle_counter + 1
856 :
857 1000 : t1 = m_walltime()
858 :
859 : ! create and update x_i (orthogonalization with previous vectors)
860 2378 : DO ispin = 1, nspins
861 1378 : CALL cp_fm_create(xn(ispin, iiter), fm_struct_tmp(ispin)%struct, name="xi")
862 2378 : CALL cp_fm_set_all(xn(ispin, iiter), 0.0_dp)
863 : END DO
864 :
865 2760 : ALLOCATE (proj_bi_xj(iiter - 1))
866 2938 : proj_bi_xj = 0.0_dp
867 : ! first compute the projection of the actual b_i into all previous x_i
868 : ! already scaled with the norm of each x_i
869 2938 : DO iiB = 1, iiter - 1
870 2938 : proj_bi_xj(iiB) = proj_bi_xj(iiB) + accurate_dot_product_spin(b_i, xn(:, iiB))/x_norm(iiB)
871 : END DO
872 :
873 : ! update actual x_i
874 2378 : DO ispin = 1, nspins
875 65493 : xn(ispin, iiter)%local_data(:, :) = scale_cphf*b_i(ispin)%local_data(:, :)
876 5214 : DO iiB = 1, iiter - 1
877 : xn(ispin, iiter)%local_data(:, :) = xn(ispin, iiter)%local_data(:, :) - &
878 148494 : xn(ispin, iiB)%local_data(:, :)*proj_bi_xj(iiB)
879 : END DO
880 : END DO
881 1000 : DEALLOCATE (proj_bi_xj)
882 :
883 : ! create Ax(iiter) that will store the matrix vector product for this cycle
884 2378 : DO ispin = 1, nspins
885 1378 : CALL cp_fm_create(Ax(ispin, iiter), fm_struct_tmp(ispin)%struct, name="Ai")
886 2378 : CALL cp_fm_set_all(Ax(ispin, iiter), 0.0_dp)
887 : END DO
888 :
889 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
890 : mo_coeff_o, &
891 : mo_coeff_v, Eigenval, p_env, &
892 : xn(:, iiter), fm_G_mu_nu, fm_back, transf_type_in, &
893 1000 : Ax(:, iiter))
894 :
895 : ! in order to reduce the number of parallel sums here we
896 : ! cluster all necessary scalar products into a single vector
897 : ! temp_vals contains:
898 : ! 1:iiter -> <Ax_i|x_j>
899 : ! iiter+1 -> <x_i|b>
900 : ! iiter+2 -> <x_i|x_i>
901 :
902 3000 : ALLOCATE (temp_vals(iiter + 2))
903 5938 : temp_vals = 0.0_dp
904 : ! <Ax_i|x_j>
905 3938 : DO iiB = 1, iiter
906 3938 : temp_vals(iiB) = temp_vals(iiB) + accurate_dot_product_spin(Ax(:, iiter), xn(:, iiB))
907 : END DO
908 : ! <x_i|b>
909 1000 : temp_vals(iiter + 1) = temp_vals(iiter + 1) + accurate_dot_product_spin(xn(:, iiter), L_jb)
910 : ! norm
911 1000 : temp_vals(iiter + 2) = temp_vals(iiter + 2) + accurate_dot_product_spin(xn(:, iiter), xn(:, iiter))
912 : ! update <Ax_i|x_j>, <x_i|b> and norm <x_i|x_i>
913 3938 : xi_Axi(iiter, 1:iiter) = temp_vals(1:iiter)
914 3938 : xi_Axi(1:iiter, iiter) = temp_vals(1:iiter)
915 1000 : xi_b(iiter) = temp_vals(iiter + 1)
916 1000 : x_norm(iiter) = temp_vals(iiter + 2)
917 1000 : DEALLOCATE (temp_vals)
918 :
919 : ! solve reduced system
920 1000 : IF (ALLOCATED(A_small)) DEALLOCATE (A_small)
921 1000 : IF (ALLOCATED(b_small)) DEALLOCATE (b_small)
922 4000 : ALLOCATE (A_small(iiter, iiter))
923 3000 : ALLOCATE (b_small(iiter, 1))
924 15696 : A_small(1:iiter, 1:iiter) = xi_Axi(1:iiter, 1:iiter)
925 3938 : b_small(1:iiter, 1) = xi_b(1:iiter)
926 :
927 1000 : CALL solve_system(matrix=A_small, mysize=iiter, eigenvectors=b_small)
928 :
929 : ! check for convergence
930 2378 : DO ispin = 1, nspins
931 1378 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
932 5592 : DO iiB = 1, iiter
933 : residual(ispin)%local_data(:, :) = &
934 : residual(ispin)%local_data(:, :) + &
935 213987 : b_small(iiB, 1)*Ax(ispin, iiB)%local_data(:, :)
936 : END DO
937 :
938 : residual(ispin)%local_data(:, :) = &
939 : residual(ispin)%local_data(:, :) - &
940 66493 : L_jb(ispin)%local_data(:, :)
941 : END DO
942 :
943 1000 : conv = SQRT(accurate_dot_product_spin(residual, residual))
944 :
945 1000 : t2 = m_walltime()
946 :
947 1000 : IF (unit_nr > 0) THEN
948 500 : WRITE (unit_nr, '(T3,I5,T13,F6.1,11X,F14.8)') iiter, t2 - t1, conv
949 500 : CALL m_flush(unit_nr)
950 : END IF
951 :
952 1000 : IF (conv <= eps_conv) THEN
953 : converged = .TRUE.
954 : EXIT
955 : END IF
956 :
957 : ! update b_i for the next round
958 1874 : DO ispin = 1, nspins
959 : b_i(ispin)%local_data(:, :) = b_i(ispin)%local_data(:, :) &
960 : + precond(ispin)%local_data(:, :) &
961 53560 : *Ax(ispin, iiter)%local_data(:, :)
962 : END DO
963 :
964 804 : scale_cphf = 1.0_dp
965 :
966 : END DO
967 :
968 240 : IF (unit_nr > 0) THEN
969 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
970 120 : IF (converged) THEN
971 109 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations converged in', cycle_counter, ' steps'
972 : ELSE
973 11 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations NOT converged in', cycle_counter, ' steps'
974 : END IF
975 : END IF
976 :
977 : ! store solution into P_ia
978 1240 : DO iiter = 1, cycle_counter
979 2618 : DO ispin = 1, nspins
980 : P_ia(ispin)%local_data(:, :) = P_ia(ispin)%local_data(:, :) + &
981 66493 : b_small(iiter, 1)*xn(ispin, iiter)%local_data(:, :)
982 : END DO
983 : END DO
984 :
985 : ! Release arrays
986 240 : DEALLOCATE (x_norm)
987 240 : DEALLOCATE (xi_b)
988 240 : DEALLOCATE (xi_Axi)
989 :
990 240 : CALL cp_fm_release(b_i)
991 240 : CALL cp_fm_release(residual)
992 240 : CALL cp_fm_release(Ax)
993 240 : CALL cp_fm_release(xn)
994 :
995 : ELSE
996 0 : IF (unit_nr > 0) THEN
997 0 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
998 0 : WRITE (unit_nr, '(T3,A)') 'Residual smaller than EPS_CONV. Skip solution of Z-vector equation.'
999 : END IF
1000 : END IF
1001 :
1002 240 : CALL timestop(handle)
1003 :
1004 240 : END SUBROUTINE solve_z_vector_pople
1005 :
1006 : ! **************************************************************************************************
1007 : !> \brief ...
1008 : !> \param qs_env ...
1009 : !> \param mp2_env ...
1010 : !> \param homo ...
1011 : !> \param virtual ...
1012 : !> \param dimen ...
1013 : !> \param unit_nr ...
1014 : !> \param nspins ...
1015 : !> \param mo_coeff_o ...
1016 : !> \param mo_coeff_v ...
1017 : !> \param Eigenval ...
1018 : !> \param p_env ...
1019 : !> \param L_jb ...
1020 : !> \param fm_G_mu_nu ...
1021 : !> \param fm_back ...
1022 : !> \param P_ia ...
1023 : !> \param precond ...
1024 : ! **************************************************************************************************
1025 24 : SUBROUTINE solve_z_vector_cg(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
1026 24 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
1027 24 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
1028 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1029 : TYPE(mp2_type), INTENT(IN) :: mp2_env
1030 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
1031 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
1032 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
1033 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
1034 : INTENT(IN) :: Eigenval
1035 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
1036 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: L_jb
1037 : TYPE(cp_fm_type), INTENT(INOUT) :: fm_G_mu_nu
1038 : TYPE(cp_fm_type), INTENT(IN) :: fm_back
1039 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia, precond
1040 :
1041 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_cg'
1042 :
1043 : INTEGER :: cycles_passed, handle, iiter, ispin, max_num_iter, restart_counter, &
1044 : restart_every, transf_type_in, z_solver_method
1045 : LOGICAL :: converged, do_restart
1046 : REAL(KIND=dp) :: eps_conv, norm_residual, norm_residual_old, &
1047 : residual_dot_diff_search_vec_new, residual_dot_diff_search_vec_old, &
1048 : residual_dot_search_vec, residual_new_dot_diff_search_vec_old, scale_result, &
1049 : scale_search, scale_step_size, search_vec_dot_A_search_vec, t1, t2
1050 : TYPE(cp_fm_struct_p_type), ALLOCATABLE, &
1051 24 : DIMENSION(:) :: fm_struct_tmp
1052 24 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: A_dot_search_vector, diff_search_vector, &
1053 24 : residual, search_vector
1054 :
1055 24 : CALL timeset(routineN, handle)
1056 :
1057 24 : max_num_iter = mp2_env%ri_grad%cphf_max_num_iter
1058 24 : eps_conv = mp2_env%ri_grad%cphf_eps_conv
1059 24 : z_solver_method = mp2_env%ri_grad%z_solver_method
1060 24 : restart_every = mp2_env%ri_grad%cphf_restart
1061 24 : scale_step_size = mp2_env%ri_grad%scale_step_size
1062 24 : transf_type_in = 3
1063 :
1064 24 : IF (unit_nr > 0) THEN
1065 12 : WRITE (unit_nr, *)
1066 8 : SELECT CASE (z_solver_method)
1067 : CASE (z_solver_cg)
1068 8 : IF (mp2_env%ri_grad%polak_ribiere) THEN
1069 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (CG with Polak-Ribiere step)'
1070 : ELSE
1071 6 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (CG with Fletcher-Reeves step)'
1072 : END IF
1073 : CASE (z_solver_richardson)
1074 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (Richardson method)'
1075 : CASE (z_solver_sd)
1076 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (Steepest Descent method)'
1077 : CASE DEFAULT
1078 12 : CPABORT("Unknown solver")
1079 : END SELECT
1080 12 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Convergence threshold:', eps_conv
1081 12 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Maximum number of iterations: ', max_num_iter
1082 12 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Number of steps for restart: ', restart_every
1083 12 : WRITE (unit_nr, '(T3, A)') 'MP2_CPHF| Restart after no decrease'
1084 12 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Scaling factor of each step: ', scale_step_size
1085 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1086 12 : WRITE (unit_nr, '(T4,A,T13,A,T28,A,T43,A)') 'Step', 'Restart', 'Time', 'Convergence'
1087 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1088 : END IF
1089 :
1090 0 : ALLOCATE (fm_struct_tmp(nspins), residual(nspins), diff_search_vector(nspins), &
1091 312 : search_vector(nspins), A_dot_search_vector(nspins))
1092 48 : DO ispin = 1, nspins
1093 24 : fm_struct_tmp(ispin)%struct => P_ia(ispin)%matrix_struct
1094 :
1095 24 : CALL cp_fm_create(residual(ispin), fm_struct_tmp(ispin)%struct, name="residual")
1096 24 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
1097 :
1098 24 : CALL cp_fm_create(diff_search_vector(ispin), fm_struct_tmp(ispin)%struct, name="difference search vector")
1099 24 : CALL cp_fm_set_all(diff_search_vector(ispin), 0.0_dp)
1100 :
1101 24 : CALL cp_fm_create(search_vector(ispin), fm_struct_tmp(ispin)%struct, name="search vector")
1102 24 : CALL cp_fm_set_all(search_vector(ispin), 0.0_dp)
1103 :
1104 24 : CALL cp_fm_create(A_dot_search_vector(ispin), fm_struct_tmp(ispin)%struct, name="A times search vector")
1105 48 : CALL cp_fm_set_all(A_dot_search_vector(ispin), 0.0_dp)
1106 : END DO
1107 :
1108 24 : converged = .FALSE.
1109 24 : cycles_passed = max_num_iter
1110 : ! By that, we enforce the setup of the matrices
1111 24 : do_restart = .TRUE.
1112 :
1113 24 : t1 = m_walltime()
1114 :
1115 164 : DO iiter = 1, max_num_iter
1116 :
1117 : ! During the first iteration, P_ia=0 such that the application of the 2nd order matrix is zero
1118 160 : IF (do_restart) THEN
1119 : ! We do not consider the first step to be a restart
1120 : ! Do not recalculate residual if it is already enforced to save FLOPs
1121 52 : IF (.NOT. mp2_env%ri_grad%recalc_residual .OR. (iiter == 1)) THEN
1122 52 : IF (iiter > 1) THEN
1123 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1124 : mo_coeff_o, &
1125 : mo_coeff_v, Eigenval, p_env, &
1126 : P_ia, fm_G_mu_nu, fm_back, transf_type_in, &
1127 28 : residual)
1128 : ELSE
1129 24 : do_restart = .FALSE.
1130 :
1131 48 : DO ispin = 1, nspins
1132 48 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
1133 : END DO
1134 : END IF
1135 :
1136 104 : DO ispin = 1, nspins
1137 : residual(ispin)%local_data(:, :) = L_jb(ispin)%local_data(:, :) &
1138 3068 : - residual(ispin)%local_data(:, :)
1139 : END DO
1140 : END IF
1141 :
1142 104 : DO ispin = 1, nspins
1143 : diff_search_vector(ispin)%local_data(:, :) = &
1144 3016 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1145 3068 : search_vector(ispin)%local_data(:, :) = diff_search_vector(ispin)%local_data(:, :)
1146 : END DO
1147 :
1148 : restart_counter = 1
1149 : END IF
1150 :
1151 160 : norm_residual_old = SQRT(accurate_dot_product_spin(residual, residual))
1152 :
1153 160 : residual_dot_diff_search_vec_old = accurate_dot_product_spin(residual, diff_search_vector)
1154 :
1155 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1156 : mo_coeff_o, &
1157 : mo_coeff_v, Eigenval, p_env, &
1158 : search_vector, fm_G_mu_nu, fm_back, transf_type_in, &
1159 160 : A_dot_search_vector)
1160 :
1161 160 : IF (z_solver_method /= z_solver_richardson) THEN
1162 120 : search_vec_dot_A_search_vec = accurate_dot_product_spin(search_vector, A_dot_search_vector)
1163 :
1164 120 : IF (z_solver_method == z_solver_cg) THEN
1165 94 : scale_result = residual_dot_diff_search_vec_old/search_vec_dot_A_search_vec
1166 : ELSE
1167 26 : residual_dot_search_vec = accurate_dot_product_spin(residual, search_vector)
1168 26 : scale_result = residual_dot_search_vec/search_vec_dot_A_search_vec
1169 : END IF
1170 :
1171 120 : scale_result = scale_result*scale_step_size
1172 :
1173 : ELSE
1174 :
1175 : scale_result = scale_step_size
1176 :
1177 : END IF
1178 :
1179 320 : DO ispin = 1, nspins
1180 : P_ia(ispin)%local_data(:, :) = P_ia(ispin)%local_data(:, :) &
1181 9440 : + scale_result*search_vector(ispin)%local_data(:, :)
1182 : END DO
1183 :
1184 160 : IF (.NOT. mp2_env%ri_grad%recalc_residual) THEN
1185 :
1186 284 : DO ispin = 1, nspins
1187 : residual(ispin)%local_data(:, :) = residual(ispin)%local_data(:, :) &
1188 8378 : - scale_result*A_dot_search_vector(ispin)%local_data(:, :)
1189 : END DO
1190 : ELSE
1191 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1192 : mo_coeff_o, &
1193 : mo_coeff_v, Eigenval, p_env, &
1194 : P_ia, fm_G_mu_nu, fm_back, transf_type_in, &
1195 18 : residual)
1196 :
1197 36 : DO ispin = 1, nspins
1198 1062 : residual(ispin)%local_data(:, :) = L_jb(ispin)%local_data(:, :) - residual(ispin)%local_data(:, :)
1199 : END DO
1200 : END IF
1201 :
1202 160 : norm_residual = SQRT(accurate_dot_product_spin(residual, residual))
1203 :
1204 160 : t2 = m_walltime()
1205 :
1206 160 : IF (unit_nr > 0) THEN
1207 80 : WRITE (unit_nr, '(T3,I4,T16,L1,T26,F6.1,8X,F14.8)') iiter, do_restart, t2 - t1, norm_residual
1208 80 : CALL m_flush(unit_nr)
1209 : END IF
1210 :
1211 160 : IF (norm_residual <= eps_conv) THEN
1212 20 : converged = .TRUE.
1213 20 : cycles_passed = iiter
1214 20 : EXIT
1215 : END IF
1216 :
1217 140 : t1 = m_walltime()
1218 :
1219 140 : IF (z_solver_method == z_solver_richardson) THEN
1220 80 : DO ispin = 1, nspins
1221 : search_vector(ispin)%local_data(:, :) = &
1222 2360 : scale_step_size*precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1223 : END DO
1224 100 : ELSE IF (z_solver_method == z_solver_sd) THEN
1225 44 : DO ispin = 1, nspins
1226 : search_vector(ispin)%local_data(:, :) = &
1227 1298 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1228 : END DO
1229 : ELSE
1230 78 : IF (mp2_env%ri_grad%polak_ribiere) &
1231 28 : residual_new_dot_diff_search_vec_old = accurate_dot_product_spin(residual, diff_search_vector)
1232 :
1233 156 : DO ispin = 1, nspins
1234 : diff_search_vector(ispin)%local_data(:, :) = &
1235 4602 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1236 : END DO
1237 :
1238 78 : residual_dot_diff_search_vec_new = accurate_dot_product_spin(residual, diff_search_vector)
1239 :
1240 78 : scale_search = residual_dot_diff_search_vec_new/residual_dot_diff_search_vec_old
1241 78 : IF (mp2_env%ri_grad%polak_ribiere) scale_search = &
1242 28 : scale_search - residual_new_dot_diff_search_vec_old/residual_dot_diff_search_vec_old
1243 :
1244 156 : DO ispin = 1, nspins
1245 : search_vector(ispin)%local_data(:, :) = scale_search*search_vector(ispin)%local_data(:, :) &
1246 4602 : + diff_search_vector(ispin)%local_data(:, :)
1247 : END DO
1248 :
1249 : ! Make new to old
1250 140 : residual_dot_diff_search_vec_old = residual_dot_diff_search_vec_new
1251 : END IF
1252 :
1253 : ! Check whether the residual decrease or restart is enforced and ask for restart
1254 140 : do_restart = (norm_residual >= norm_residual_old .OR. (MOD(restart_counter, restart_every) == 0))
1255 :
1256 140 : restart_counter = restart_counter + 1
1257 144 : norm_residual_old = norm_residual
1258 :
1259 : END DO
1260 :
1261 24 : IF (unit_nr > 0) THEN
1262 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1263 12 : IF (converged) THEN
1264 10 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations converged in', cycles_passed, ' steps'
1265 : ELSE
1266 2 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations NOT converged in', max_num_iter, ' steps'
1267 : END IF
1268 : END IF
1269 :
1270 24 : DEALLOCATE (fm_struct_tmp)
1271 24 : CALL cp_fm_release(residual)
1272 24 : CALL cp_fm_release(diff_search_vector)
1273 24 : CALL cp_fm_release(search_vector)
1274 24 : CALL cp_fm_release(A_dot_search_vector)
1275 :
1276 24 : CALL timestop(handle)
1277 :
1278 48 : END SUBROUTINE solve_z_vector_cg
1279 :
1280 : ! **************************************************************************************************
1281 : !> \brief ...
1282 : !> \param matrix1 ...
1283 : !> \param matrix2 ...
1284 : !> \return ...
1285 : ! **************************************************************************************************
1286 8848 : FUNCTION accurate_dot_product_spin(matrix1, matrix2) RESULT(dotproduct)
1287 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: matrix1, matrix2
1288 : REAL(KIND=dp) :: dotproduct
1289 :
1290 : INTEGER :: ispin
1291 :
1292 8848 : dotproduct = 0.0_dp
1293 21090 : DO ispin = 1, SIZE(matrix1)
1294 21090 : dotproduct = dotproduct + accurate_dot_product(matrix1(ispin)%local_data, matrix2(ispin)%local_data)
1295 : END DO
1296 8848 : CALL matrix1(1)%matrix_struct%para_env%sum(dotproduct)
1297 :
1298 8848 : END FUNCTION accurate_dot_product_spin
1299 :
1300 : ! **************************************************************************************************
1301 : !> \brief ...
1302 : !> \param qs_env ...
1303 : ! **************************************************************************************************
1304 264 : SUBROUTINE update_mp2_forces(qs_env)
1305 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1306 :
1307 : CHARACTER(LEN=*), PARAMETER :: routineN = 'update_mp2_forces'
1308 :
1309 : INTEGER :: alpha, beta, handle, idir, iounit, &
1310 : ispin, nimages, nocc, nspins
1311 : INTEGER, DIMENSION(3) :: comp
1312 264 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1313 : LOGICAL :: do_exx, do_hfx, use_virial
1314 : REAL(KIND=dp) :: e_dummy, e_hartree, e_xc, ehartree, exc
1315 : REAL(KIND=dp), DIMENSION(3) :: deb
1316 : REAL(KIND=dp), DIMENSION(3, 3) :: h_stress, pv_virial
1317 : TYPE(admm_type), POINTER :: admm_env
1318 264 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1319 : TYPE(cell_type), POINTER :: cell
1320 : TYPE(cp_logger_type), POINTER :: logger
1321 : TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:), &
1322 264 : TARGET :: matrix_ks_aux
1323 264 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_p_mp2, &
1324 264 : matrix_p_mp2_admm, matrix_s, rho1, &
1325 264 : rho_ao, rho_ao_aux, scrm
1326 264 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp, scrm_kp
1327 : TYPE(dft_control_type), POINTER :: dft_control
1328 264 : TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
1329 : TYPE(linres_control_type), POINTER :: linres_control
1330 264 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1331 : TYPE(mp_para_env_type), POINTER :: para_env
1332 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1333 264 : POINTER :: sab_orb, sac_ae, sac_ppl, sap_ppnl
1334 264 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1335 : TYPE(pw_c1d_gs_type) :: pot_g, rho_tot_g, temp_pw_g
1336 264 : TYPE(pw_c1d_gs_type), ALLOCATABLE, DIMENSION(:) :: dvg
1337 264 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g, rho_mp2_g
1338 : TYPE(pw_c1d_gs_type), POINTER :: rho_core
1339 : TYPE(pw_env_type), POINTER :: pw_env
1340 : TYPE(pw_poisson_type), POINTER :: poisson_env
1341 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1342 : TYPE(pw_r3d_rs_type) :: pot_r, vh_rspace, vhxc_rspace
1343 264 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_mp2_r, rho_mp2_r_aux, rho_r, &
1344 264 : tau_mp2_r, vadmm_rspace, vtau_rspace, &
1345 264 : vxc_rspace
1346 : TYPE(qs_dispersion_type), POINTER :: dispersion_env
1347 : TYPE(qs_energy_type), POINTER :: energy
1348 264 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
1349 264 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1350 : TYPE(qs_ks_env_type), POINTER :: ks_env
1351 : TYPE(qs_p_env_type), POINTER :: p_env
1352 : TYPE(qs_rho_type), POINTER :: rho, rho_aux
1353 : TYPE(section_vals_type), POINTER :: hfx_section, hfx_sections, input, &
1354 : xc_section
1355 : TYPE(task_list_type), POINTER :: task_list_aux_fit
1356 : TYPE(virial_type), POINTER :: virial
1357 :
1358 264 : CALL timeset(routineN, handle)
1359 :
1360 264 : NULLIFY (input, pw_env, matrix_s, rho, energy, force, virial, &
1361 264 : matrix_p_mp2, matrix_p_mp2_admm, matrix_ks, rho_core)
1362 : CALL get_qs_env(qs_env, &
1363 : ks_env=ks_env, &
1364 : dft_control=dft_control, &
1365 : pw_env=pw_env, &
1366 : input=input, &
1367 : mos=mos, &
1368 : para_env=para_env, &
1369 : matrix_s=matrix_s, &
1370 : matrix_ks=matrix_ks, &
1371 : matrix_p_mp2=matrix_p_mp2, &
1372 : matrix_p_mp2_admm=matrix_p_mp2_admm, &
1373 : rho=rho, &
1374 : cell=cell, &
1375 : force=force, &
1376 : virial=virial, &
1377 : sab_orb=sab_orb, &
1378 : energy=energy, &
1379 : rho_core=rho_core, &
1380 264 : x_data=x_data)
1381 :
1382 264 : logger => cp_get_default_logger()
1383 : iounit = cp_print_key_unit_nr(logger, input, "DFT%XC%WF_CORRELATION%PRINT", &
1384 264 : extension=".mp2Log")
1385 :
1386 264 : do_exx = .FALSE.
1387 264 : IF (qs_env%mp2_env%method == ri_rpa_method_gpw) THEN
1388 20 : hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
1389 20 : CALL section_vals_get(hfx_section, explicit=do_exx)
1390 : END IF
1391 :
1392 264 : nimages = dft_control%nimages
1393 264 : CPASSERT(nimages == 1)
1394 264 : NULLIFY (cell_to_index)
1395 :
1396 264 : p_env => qs_env%mp2_env%ri_grad%p_env
1397 :
1398 264 : CALL qs_rho_get(rho, rho_ao=rho_ao, rho_ao_kp=rho_ao_kp, rho_r=rho_r, rho_g=rho_g)
1399 264 : nspins = SIZE(rho_ao)
1400 :
1401 : ! check if we have to calculate the virial
1402 264 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
1403 264 : IF (use_virial) virial%pv_calculate = .TRUE.
1404 :
1405 264 : CALL zero_qs_force(force)
1406 264 : IF (use_virial) CALL zero_virial(virial, .FALSE.)
1407 :
1408 614 : DO ispin = 1, nspins
1409 614 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
1410 : END DO
1411 :
1412 264 : IF (nspins == 2) THEN
1413 86 : CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, 1.0_dp, 1.0_dp)
1414 : END IF
1415 :
1416 : ! Kinetic energy matrix
1417 264 : NULLIFY (scrm)
1418 : IF (debug_forces) THEN
1419 1056 : deb(1:3) = force(1)%kinetic(1:3, 1)
1420 264 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1421 : END IF
1422 : CALL build_kinetic_matrix(ks_env, matrix_t=scrm, &
1423 : matrix_name="KINETIC ENERGY MATRIX", &
1424 : basis_type="ORB", &
1425 : sab_nl=sab_orb, calculate_forces=.TRUE., &
1426 264 : matrix_p=rho_ao(1)%matrix)
1427 : IF (debug_forces) THEN
1428 1056 : deb(1:3) = force(1)%kinetic(1:3, 1) - deb(1:3)
1429 264 : CALL para_env%sum(deb)
1430 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dT ", deb
1431 264 : IF (use_virial) THEN
1432 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1433 50 : CALL para_env%sum(e_dummy)
1434 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: T ", e_dummy
1435 : END IF
1436 : END IF
1437 264 : CALL dbcsr_deallocate_matrix_set(scrm)
1438 :
1439 264 : IF (nspins == 2) THEN
1440 86 : CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, 1.0_dp, -1.0_dp)
1441 : END IF
1442 :
1443 : ! Add pseudo potential terms
1444 264 : scrm_kp(1:nspins, 1:1) => matrix_ks(1:nspins)
1445 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, particle_set=particle_set, &
1446 264 : atomic_kind_set=atomic_kind_set, sac_ae=sac_ae, sac_ppl=sac_ppl, sap_ppnl=sap_ppnl)
1447 264 : IF (ASSOCIATED(sac_ae)) THEN
1448 : IF (debug_forces) THEN
1449 0 : deb(1:3) = force(1)%all_potential(1:3, 1)
1450 0 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1451 : END IF
1452 : CALL build_core_ae(scrm_kp, rho_ao_kp, force, &
1453 : virial, .TRUE., use_virial, 1, &
1454 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sac_ae, &
1455 0 : nimages, cell_to_index, basis_type="ORB")
1456 : IF (debug_forces) THEN
1457 0 : deb(1:3) = force(1)%all_potential(1:3, 1) - deb(1:3)
1458 0 : CALL para_env%sum(deb)
1459 0 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHae ", deb
1460 0 : IF (use_virial) THEN
1461 0 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1462 0 : CALL para_env%sum(e_dummy)
1463 0 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hae ", e_dummy
1464 : END IF
1465 : END IF
1466 : END IF
1467 264 : IF (ASSOCIATED(sac_ppl)) THEN
1468 : IF (debug_forces) THEN
1469 1056 : deb(1:3) = force(1)%gth_ppl(1:3, 1)
1470 264 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1471 : END IF
1472 : CALL build_core_ppl(scrm_kp, rho_ao_kp, force, &
1473 : virial, .TRUE., use_virial, 1, &
1474 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sac_ppl, &
1475 264 : nimages=1, basis_type="ORB")
1476 : IF (debug_forces) THEN
1477 1056 : deb(1:3) = force(1)%gth_ppl(1:3, 1) - deb(1:3)
1478 264 : CALL para_env%sum(deb)
1479 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHppl ", deb
1480 264 : IF (use_virial) THEN
1481 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1482 50 : CALL para_env%sum(e_dummy)
1483 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hppl ", e_dummy
1484 : END IF
1485 : END IF
1486 : END IF
1487 264 : IF (ASSOCIATED(sap_ppnl)) THEN
1488 : IF (debug_forces) THEN
1489 1016 : deb(1:3) = force(1)%gth_ppnl(1:3, 1)
1490 254 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1491 : END IF
1492 : CALL build_core_ppnl(scrm_kp, rho_ao_kp, force, &
1493 : virial, .TRUE., use_virial, 1, &
1494 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sap_ppnl, dft_control%qs_control%eps_ppnl, &
1495 254 : nimages=1, basis_type="ORB")
1496 : IF (debug_forces) THEN
1497 1016 : deb(1:3) = force(1)%gth_ppnl(1:3, 1) - deb(1:3)
1498 254 : CALL para_env%sum(deb)
1499 254 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHppnl ", deb
1500 254 : IF (use_virial) THEN
1501 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1502 50 : CALL para_env%sum(e_dummy)
1503 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hppnl ", e_dummy
1504 : END IF
1505 : END IF
1506 : END IF
1507 :
1508 : ! Get the different components of the KS potential
1509 264 : NULLIFY (vxc_rspace, vtau_rspace, vadmm_rspace)
1510 264 : IF (use_virial) THEN
1511 50 : h_stress = 0.0_dp
1512 50 : CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, ehartree, exc, h_stress)
1513 : ! Update virial
1514 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress/REAL(para_env%num_pe, dp)
1515 650 : virial%pv_virial = virial%pv_virial + h_stress/REAL(para_env%num_pe, dp)
1516 50 : IF (.NOT. do_exx) THEN
1517 650 : virial%pv_exc = virial%pv_exc - virial%pv_xc
1518 650 : virial%pv_virial = virial%pv_virial - virial%pv_xc
1519 : ELSE
1520 0 : virial%pv_xc = 0.0_dp
1521 : END IF
1522 : IF (debug_forces) THEN
1523 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: xc ", third_tr(h_stress)
1524 50 : CALL para_env%sum(virial%pv_xc(1, 1))
1525 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Corr xc ", third_tr(virial%pv_xc)
1526 : END IF
1527 : ELSE
1528 214 : CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, ehartree, exc)
1529 : END IF
1530 :
1531 : ! Vhxc
1532 264 : CALL get_qs_env(qs_env, pw_env=pw_env)
1533 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
1534 264 : poisson_env=poisson_env)
1535 264 : CALL auxbas_pw_pool%create_pw(vhxc_rspace)
1536 864 : IF (use_virial) h_stress = virial%pv_virial
1537 : IF (debug_forces) THEN
1538 1056 : deb(1:3) = force(1)%rho_elec(1:3, 1)
1539 264 : IF (use_virial) e_dummy = third_tr(h_stress)
1540 : END IF
1541 264 : IF (do_exx) THEN
1542 16 : DO ispin = 1, nspins
1543 8 : CALL pw_transfer(vh_rspace, vhxc_rspace)
1544 8 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
1545 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1546 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1547 8 : qs_env=qs_env, calculate_forces=.TRUE.)
1548 8 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
1549 8 : CALL pw_axpy(vxc_rspace(ispin), vhxc_rspace)
1550 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1551 : hmat=matrix_ks(ispin), pmat=matrix_p_mp2(ispin), &
1552 8 : qs_env=qs_env, calculate_forces=.TRUE.)
1553 16 : IF (ASSOCIATED(vtau_rspace)) THEN
1554 : CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
1555 : hmat=matrix_ks(ispin), pmat=matrix_p_mp2(ispin), &
1556 0 : qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
1557 : END IF
1558 : END DO
1559 : ELSE
1560 598 : DO ispin = 1, nspins
1561 342 : CALL pw_transfer(vh_rspace, vhxc_rspace)
1562 342 : CALL pw_axpy(vxc_rspace(ispin), vhxc_rspace)
1563 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1564 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1565 342 : qs_env=qs_env, calculate_forces=.TRUE.)
1566 598 : IF (ASSOCIATED(vtau_rspace)) THEN
1567 : CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
1568 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1569 60 : qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
1570 : END IF
1571 : END DO
1572 : END IF
1573 : IF (debug_forces) THEN
1574 1056 : deb(1:3) = force(1)%rho_elec(1:3, 1) - deb(1:3)
1575 264 : CALL para_env%sum(deb)
1576 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dVhxc ", deb
1577 264 : IF (use_virial) THEN
1578 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1579 50 : CALL para_env%sum(e_dummy)
1580 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Vhxc ", e_dummy
1581 : END IF
1582 : END IF
1583 264 : IF (use_virial) THEN
1584 650 : h_stress = virial%pv_virial - h_stress
1585 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress
1586 :
1587 50 : CALL qs_rho_get(p_env%rho1, rho_r=rho_mp2_r, tau_r=tau_mp2_r)
1588 50 : e_xc = 0.0_dp
1589 124 : DO ispin = 1, nspins
1590 : ! The potentials have been scaled in ks_ref_potential, but for pw_integral_ab, we need the unscaled potentials
1591 74 : CALL pw_scale(vxc_rspace(ispin), 1.0_dp/vxc_rspace(ispin)%pw_grid%dvol)
1592 74 : e_xc = e_xc + pw_integral_ab(rho_mp2_r(ispin), vxc_rspace(ispin))
1593 74 : IF (ASSOCIATED(vtau_rspace)) CALL pw_scale(vtau_rspace(ispin), 1.0_dp/vtau_rspace(ispin)%pw_grid%dvol)
1594 124 : IF (ASSOCIATED(vtau_rspace)) e_xc = e_xc + pw_integral_ab(tau_mp2_r(ispin), vtau_rspace(ispin))
1595 : END DO
1596 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG VIRIAL:: vxc*d1 ", e_xc
1597 200 : DO alpha = 1, 3
1598 150 : virial%pv_exc(alpha, alpha) = virial%pv_exc(alpha, alpha) - e_xc/REAL(para_env%num_pe, dp)
1599 200 : virial%pv_virial(alpha, alpha) = virial%pv_virial(alpha, alpha) - e_xc/REAL(para_env%num_pe, dp)
1600 : END DO
1601 : END IF
1602 614 : DO ispin = 1, nspins
1603 350 : CALL auxbas_pw_pool%give_back_pw(vxc_rspace(ispin))
1604 614 : IF (ASSOCIATED(vtau_rspace)) THEN
1605 60 : CALL auxbas_pw_pool%give_back_pw(vtau_rspace(ispin))
1606 : END IF
1607 : END DO
1608 264 : DEALLOCATE (vxc_rspace)
1609 264 : CALL auxbas_pw_pool%give_back_pw(vhxc_rspace)
1610 264 : IF (ASSOCIATED(vtau_rspace)) DEALLOCATE (vtau_rspace)
1611 :
1612 614 : DO ispin = 1, nspins
1613 614 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
1614 : END DO
1615 :
1616 : ! pw stuff
1617 264 : NULLIFY (poisson_env, auxbas_pw_pool)
1618 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
1619 264 : poisson_env=poisson_env)
1620 :
1621 : ! get some of the grids ready
1622 264 : CALL auxbas_pw_pool%create_pw(pot_r)
1623 264 : CALL auxbas_pw_pool%create_pw(pot_g)
1624 264 : CALL auxbas_pw_pool%create_pw(rho_tot_g)
1625 :
1626 264 : CALL pw_zero(rho_tot_g)
1627 :
1628 264 : CALL qs_rho_get(p_env%rho1, rho_r=rho_mp2_r, rho_g=rho_mp2_g)
1629 614 : DO ispin = 1, nspins
1630 614 : CALL pw_axpy(rho_mp2_g(ispin), rho_tot_g)
1631 : END DO
1632 :
1633 264 : IF (use_virial) THEN
1634 200 : ALLOCATE (dvg(3))
1635 200 : DO idir = 1, 3
1636 200 : CALL auxbas_pw_pool%create_pw(dvg(idir))
1637 : END DO
1638 50 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g, dvhartree=dvg)
1639 : ELSE
1640 214 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g)
1641 : END IF
1642 :
1643 264 : CALL pw_transfer(pot_g, pot_r)
1644 264 : CALL pw_scale(pot_r, pot_r%pw_grid%dvol)
1645 264 : CALL pw_axpy(pot_r, vh_rspace)
1646 :
1647 : ! calculate core forces
1648 264 : CALL integrate_v_core_rspace(vh_rspace, qs_env)
1649 : IF (debug_forces) THEN
1650 1056 : deb(:) = force(1)%rho_core(:, 1)
1651 264 : CALL para_env%sum(deb)
1652 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: core ", deb
1653 264 : IF (use_virial) THEN
1654 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1655 50 : CALL para_env%sum(e_dummy)
1656 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: core ", e_dummy
1657 : END IF
1658 : END IF
1659 264 : CALL auxbas_pw_pool%give_back_pw(vh_rspace)
1660 :
1661 264 : IF (use_virial) THEN
1662 : ! update virial if necessary with the volume term
1663 : ! first create pw auxiliary stuff
1664 50 : CALL auxbas_pw_pool%create_pw(temp_pw_g)
1665 :
1666 : ! make a copy of the MP2 density in G space
1667 50 : CALL pw_copy(rho_tot_g, temp_pw_g)
1668 :
1669 : ! calculate total SCF density and potential
1670 50 : CALL pw_copy(rho_g(1), rho_tot_g)
1671 50 : IF (nspins == 2) CALL pw_axpy(rho_g(2), rho_tot_g)
1672 50 : CALL pw_axpy(rho_core, rho_tot_g)
1673 50 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g)
1674 :
1675 : ! finally update virial with the volume contribution
1676 50 : e_hartree = pw_integral_ab(temp_pw_g, pot_g)
1677 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: vh1*d0 ", e_hartree
1678 :
1679 50 : h_stress = 0.0_dp
1680 200 : DO alpha = 1, 3
1681 150 : comp = 0
1682 150 : comp(alpha) = 1
1683 150 : CALL pw_copy(pot_g, rho_tot_g)
1684 150 : CALL pw_derive(rho_tot_g, comp)
1685 150 : h_stress(alpha, alpha) = -e_hartree
1686 500 : DO beta = alpha, 3
1687 : h_stress(alpha, beta) = h_stress(alpha, beta) &
1688 300 : - 2.0_dp*pw_integral_ab(rho_tot_g, dvg(beta))/fourpi
1689 450 : h_stress(beta, alpha) = h_stress(alpha, beta)
1690 : END DO
1691 : END DO
1692 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hartree ", third_tr(h_stress)
1693 :
1694 : ! free stuff
1695 50 : CALL auxbas_pw_pool%give_back_pw(temp_pw_g)
1696 200 : DO idir = 1, 3
1697 200 : CALL auxbas_pw_pool%give_back_pw(dvg(idir))
1698 : END DO
1699 50 : DEALLOCATE (dvg)
1700 :
1701 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress/REAL(para_env%num_pe, dp)
1702 650 : virial%pv_virial = virial%pv_virial + h_stress/REAL(para_env%num_pe, dp)
1703 :
1704 : END IF
1705 :
1706 614 : DO ispin = 1, nspins
1707 350 : CALL dbcsr_set(p_env%kpp1(ispin)%matrix, 0.0_dp)
1708 614 : IF (dft_control%do_admm) CALL dbcsr_set(p_env%kpp1_admm(ispin)%matrix, 0.0_dp)
1709 : END DO
1710 :
1711 264 : CALL get_qs_env(qs_env=qs_env, linres_control=linres_control)
1712 :
1713 264 : IF (dft_control%do_admm) THEN
1714 40 : CALL get_qs_env(qs_env, admm_env=admm_env)
1715 40 : xc_section => admm_env%xc_section_primary
1716 : ELSE
1717 224 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
1718 : END IF
1719 :
1720 264 : IF (use_virial) THEN
1721 50 : h_stress = 0.0_dp
1722 650 : pv_virial = virial%pv_virial
1723 : END IF
1724 : IF (debug_forces) THEN
1725 1056 : deb = force(1)%rho_elec(1:3, 1)
1726 264 : IF (use_virial) e_dummy = third_tr(pv_virial)
1727 : END IF
1728 264 : CALL apply_2nd_order_kernel(qs_env, p_env, .FALSE., .TRUE., use_virial, h_stress)
1729 264 : IF (use_virial) THEN
1730 650 : virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_virial)
1731 : IF (debug_forces) THEN
1732 650 : e_dummy = third_tr(virial%pv_virial - pv_virial)
1733 50 : CALL para_env%sum(e_dummy)
1734 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Kh ", e_dummy
1735 : END IF
1736 650 : virial%pv_exc = virial%pv_exc + h_stress
1737 650 : virial%pv_virial = virial%pv_virial + h_stress
1738 : IF (debug_forces) THEN
1739 50 : e_dummy = third_tr(h_stress)
1740 50 : CALL para_env%sum(e_dummy)
1741 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Kxc ", e_dummy
1742 : END IF
1743 : END IF
1744 : IF (debug_forces) THEN
1745 1056 : deb(:) = force(1)%rho_elec(:, 1) - deb
1746 264 : CALL para_env%sum(deb)
1747 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P0*Khxc ", deb
1748 264 : IF (use_virial) THEN
1749 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1750 50 : CALL para_env%sum(e_dummy)
1751 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Khxc ", e_dummy
1752 : END IF
1753 : END IF
1754 :
1755 : ! hfx section
1756 264 : NULLIFY (hfx_sections)
1757 264 : hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
1758 264 : CALL section_vals_get(hfx_sections, explicit=do_hfx)
1759 264 : IF (do_hfx) THEN
1760 184 : IF (do_exx) THEN
1761 0 : IF (dft_control%do_admm) THEN
1762 0 : CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
1763 0 : CALL qs_rho_get(rho_aux, rho_ao=rho_ao_aux, rho_ao_kp=rho_ao_kp)
1764 0 : rho1 => p_env%p1_admm
1765 : ELSE
1766 0 : rho1 => p_env%p1
1767 : END IF
1768 : ELSE
1769 184 : IF (dft_control%do_admm) THEN
1770 36 : CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
1771 36 : CALL qs_rho_get(rho_aux, rho_ao=rho_ao_aux, rho_ao_kp=rho_ao_kp)
1772 90 : DO ispin = 1, nspins
1773 90 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
1774 : END DO
1775 36 : rho1 => p_env%p1_admm
1776 : ELSE
1777 328 : DO ispin = 1, nspins
1778 328 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, 1.0_dp)
1779 : END DO
1780 148 : rho1 => p_env%p1
1781 : END IF
1782 : END IF
1783 :
1784 184 : IF (x_data(1, 1)%do_hfx_ri) THEN
1785 :
1786 : CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
1787 : x_data(1, 1)%general_parameter%fraction, &
1788 : rho_ao=rho_ao_kp, rho_ao_resp=rho1, &
1789 6 : use_virial=use_virial, resp_only=do_exx)
1790 :
1791 : ELSE
1792 : CALL derivatives_four_center(qs_env, rho_ao_kp, rho1, hfx_sections, para_env, &
1793 178 : 1, use_virial, resp_only=do_exx)
1794 : END IF
1795 :
1796 184 : IF (use_virial) THEN
1797 338 : virial%pv_exx = virial%pv_exx - virial%pv_fock_4c
1798 338 : virial%pv_virial = virial%pv_virial - virial%pv_fock_4c
1799 : END IF
1800 : IF (debug_forces) THEN
1801 736 : deb(1:3) = force(1)%fock_4c(1:3, 1) - deb(1:3)
1802 184 : CALL para_env%sum(deb)
1803 184 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*hfx ", deb
1804 184 : IF (use_virial) THEN
1805 26 : e_dummy = third_tr(virial%pv_fock_4c)
1806 26 : CALL para_env%sum(e_dummy)
1807 26 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: hfx ", e_dummy
1808 : END IF
1809 : END IF
1810 :
1811 184 : IF (.NOT. do_exx) THEN
1812 184 : IF (dft_control%do_admm) THEN
1813 36 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
1814 90 : DO ispin = 1, nspins
1815 90 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
1816 : END DO
1817 : ELSE
1818 328 : DO ispin = 1, nspins
1819 328 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, -1.0_dp)
1820 : END DO
1821 : END IF
1822 : END IF
1823 :
1824 184 : IF (dft_control%do_admm) THEN
1825 : IF (debug_forces) THEN
1826 144 : deb = force(1)%overlap_admm(1:3, 1)
1827 36 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1828 : END IF
1829 : ! The 2nd order kernel contains a factor of two in apply_xc_admm_ao which we don't need for the projection derivatives
1830 36 : IF (nspins == 1) CALL dbcsr_scale(p_env%kpp1_admm(1)%matrix, 0.5_dp)
1831 36 : CALL admm_projection_derivative(qs_env, p_env%kpp1_admm, rho_ao)
1832 : IF (debug_forces) THEN
1833 144 : deb(:) = force(1)%overlap_admm(:, 1) - deb
1834 36 : CALL para_env%sum(deb)
1835 36 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*KADMM*dS'", deb
1836 36 : IF (use_virial) THEN
1837 12 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1838 12 : CALL para_env%sum(e_dummy)
1839 12 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: KADMM*S' ", e_dummy
1840 : END IF
1841 : END IF
1842 :
1843 162 : ALLOCATE (matrix_ks_aux(nspins))
1844 90 : DO ispin = 1, nspins
1845 54 : NULLIFY (matrix_ks_aux(ispin)%matrix)
1846 54 : ALLOCATE (matrix_ks_aux(ispin)%matrix)
1847 54 : CALL dbcsr_copy(matrix_ks_aux(ispin)%matrix, p_env%kpp1_admm(ispin)%matrix)
1848 90 : CALL dbcsr_set(matrix_ks_aux(ispin)%matrix, 0.0_dp)
1849 : END DO
1850 :
1851 : ! Calculate kernel
1852 36 : CALL tddft_hfx_matrix(matrix_ks_aux, rho_ao_aux, qs_env, .FALSE.)
1853 :
1854 36 : IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1855 24 : CALL get_qs_env(qs_env, ks_env=ks_env)
1856 24 : CALL get_admm_env(qs_env%admm_env, task_list_aux_fit=task_list_aux_fit)
1857 :
1858 60 : DO ispin = 1, nspins
1859 60 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
1860 : END DO
1861 :
1862 24 : IF (use_virial) THEN
1863 8 : CALL qs_rho_get(p_env%rho1_admm, rho_r=rho_mp2_r_aux)
1864 8 : e_xc = 0.0_dp
1865 20 : DO ispin = 1, nspins
1866 20 : e_xc = e_xc + pw_integral_ab(rho_mp2_r_aux(ispin), vadmm_rspace(ispin))
1867 : END DO
1868 :
1869 8 : e_xc = -e_xc/vadmm_rspace(1)%pw_grid%dvol/REAL(para_env%num_pe, dp)
1870 :
1871 : ! Update the virial
1872 32 : DO alpha = 1, 3
1873 24 : virial%pv_exc(alpha, alpha) = virial%pv_exc(alpha, alpha) + e_xc
1874 32 : virial%pv_virial(alpha, alpha) = virial%pv_virial(alpha, alpha) + e_xc
1875 : END DO
1876 : IF (debug_forces) THEN
1877 8 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: P1*VADMM ", e_xc
1878 : END IF
1879 : END IF
1880 :
1881 120 : IF (use_virial) h_stress = virial%pv_virial
1882 : IF (debug_forces) THEN
1883 96 : deb = force(1)%rho_elec(1:3, 1)
1884 24 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1885 : END IF
1886 60 : DO ispin = 1, nspins
1887 36 : IF (do_exx) THEN
1888 : CALL integrate_v_rspace(v_rspace=vadmm_rspace(ispin), hmat=matrix_ks_aux(ispin), qs_env=qs_env, &
1889 : calculate_forces=.TRUE., basis_type="AUX_FIT", &
1890 0 : task_list_external=task_list_aux_fit, pmat=matrix_p_mp2_admm(ispin))
1891 : ELSE
1892 : CALL integrate_v_rspace(v_rspace=vadmm_rspace(ispin), hmat=matrix_ks_aux(ispin), qs_env=qs_env, &
1893 : calculate_forces=.TRUE., basis_type="AUX_FIT", &
1894 36 : task_list_external=task_list_aux_fit, pmat=rho_ao_aux(ispin))
1895 : END IF
1896 60 : CALL auxbas_pw_pool%give_back_pw(vadmm_rspace(ispin))
1897 : END DO
1898 120 : IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - h_stress)
1899 24 : DEALLOCATE (vadmm_rspace)
1900 : IF (debug_forces) THEN
1901 96 : deb(:) = force(1)%rho_elec(:, 1) - deb
1902 24 : CALL para_env%sum(deb)
1903 24 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*VADMM' ", deb
1904 24 : IF (use_virial) THEN
1905 8 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1906 8 : CALL para_env%sum(e_dummy)
1907 8 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: VADMM' ", e_dummy
1908 : END IF
1909 : END IF
1910 :
1911 60 : DO ispin = 1, nspins
1912 60 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
1913 : END DO
1914 :
1915 : END IF
1916 :
1917 90 : DO ispin = 1, nspins
1918 90 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, 1.0_dp)
1919 : END DO
1920 :
1921 : IF (debug_forces) THEN
1922 144 : deb = force(1)%overlap_admm(1:3, 1)
1923 36 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1924 : END IF
1925 : ! Add the second half of the projector deriatives contracting the first order density matrix with the fockian in the auxiliary basis
1926 36 : IF (do_exx) THEN
1927 0 : CALL admm_projection_derivative(qs_env, matrix_ks_aux, matrix_p_mp2)
1928 : ELSE
1929 36 : CALL admm_projection_derivative(qs_env, matrix_ks_aux, rho_ao)
1930 : END IF
1931 : IF (debug_forces) THEN
1932 144 : deb(:) = force(1)%overlap_admm(:, 1) - deb
1933 36 : CALL para_env%sum(deb)
1934 36 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*VADMM*dS'", deb
1935 36 : IF (use_virial) THEN
1936 12 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1937 12 : CALL para_env%sum(e_dummy)
1938 12 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: VADMM*S' ", e_dummy
1939 : END IF
1940 : END IF
1941 :
1942 90 : DO ispin = 1, nspins
1943 90 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, -1.0_dp)
1944 : END DO
1945 :
1946 90 : DO ispin = 1, nspins
1947 54 : CALL dbcsr_release(matrix_ks_aux(ispin)%matrix)
1948 90 : DEALLOCATE (matrix_ks_aux(ispin)%matrix)
1949 : END DO
1950 36 : DEALLOCATE (matrix_ks_aux)
1951 : END IF
1952 : END IF
1953 :
1954 264 : CALL dbcsr_scale(p_env%w1(1)%matrix, -1.0_dp)
1955 :
1956 : ! Finish matrix_w_mp2 with occ-occ block
1957 614 : DO ispin = 1, nspins
1958 350 : CALL get_mo_set(mo_set=mos(ispin), homo=nocc, nmo=alpha)
1959 : CALL calculate_whz_matrix(mos(ispin)%mo_coeff, p_env%kpp1(ispin)%matrix, &
1960 614 : p_env%w1(1)%matrix, 1.0_dp, nocc)
1961 : END DO
1962 :
1963 264 : IF (debug_forces .AND. use_virial) e_dummy = third_tr(virial%pv_virial)
1964 :
1965 264 : NULLIFY (scrm)
1966 : CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
1967 : matrix_name="OVERLAP MATRIX", &
1968 : basis_type_a="ORB", basis_type_b="ORB", &
1969 : sab_nl=sab_orb, calculate_forces=.TRUE., &
1970 264 : matrix_p=p_env%w1(1)%matrix)
1971 264 : CALL dbcsr_deallocate_matrix_set(scrm)
1972 :
1973 : IF (debug_forces) THEN
1974 1056 : deb = force(1)%overlap(1:3, 1)
1975 264 : CALL para_env%sum(deb)
1976 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: W*dS ", deb
1977 264 : IF (use_virial) THEN
1978 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1979 50 : CALL para_env%sum(e_dummy)
1980 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: S ", e_dummy
1981 : END IF
1982 : END IF
1983 :
1984 264 : CALL auxbas_pw_pool%give_back_pw(pot_r)
1985 264 : CALL auxbas_pw_pool%give_back_pw(pot_g)
1986 264 : CALL auxbas_pw_pool%give_back_pw(rho_tot_g)
1987 :
1988 : ! Release linres stuff
1989 264 : CALL p_env_release(p_env)
1990 264 : DEALLOCATE (p_env)
1991 264 : NULLIFY (qs_env%mp2_env%ri_grad%p_env)
1992 :
1993 264 : CALL sum_qs_force(force, qs_env%mp2_env%ri_grad%mp2_force)
1994 264 : CALL deallocate_qs_force(qs_env%mp2_env%ri_grad%mp2_force)
1995 :
1996 264 : IF (use_virial) THEN
1997 1250 : virial%pv_mp2 = qs_env%mp2_env%ri_grad%mp2_virial
1998 1250 : virial%pv_virial = virial%pv_virial + qs_env%mp2_env%ri_grad%mp2_virial
1999 : IF (debug_forces) THEN
2000 50 : e_dummy = third_tr(virial%pv_mp2)
2001 50 : CALL para_env%sum(e_dummy)
2002 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: MP2nonsep ", e_dummy
2003 : END IF
2004 : END IF
2005 : ! Rewind the change from the beginning
2006 264 : IF (use_virial) virial%pv_calculate = .FALSE.
2007 :
2008 : ! Add the dispersion forces and virials
2009 264 : CALL get_qs_env(qs_env, dispersion_env=dispersion_env)
2010 264 : CALL calculate_dispersion_pairpot(qs_env, dispersion_env, e_dummy, .TRUE.)
2011 :
2012 : CALL cp_print_key_finished_output(iounit, logger, input, &
2013 264 : "DFT%XC%WF_CORRELATION%PRINT")
2014 :
2015 264 : CALL timestop(handle)
2016 :
2017 528 : END SUBROUTINE update_mp2_forces
2018 :
2019 : ! **************************************************************************************************
2020 : !> \brief Calculates the third of the trace of a 3x3 matrix, for debugging purposes
2021 : !> \param matrix ...
2022 : !> \return ...
2023 : ! **************************************************************************************************
2024 965 : PURE FUNCTION third_tr(matrix)
2025 : REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN) :: matrix
2026 : REAL(KIND=dp) :: third_tr
2027 :
2028 965 : third_tr = (matrix(1, 1) + matrix(2, 2) + matrix(3, 3))/3.0_dp
2029 :
2030 965 : END FUNCTION third_tr
2031 :
2032 : END MODULE mp2_cphf
|