Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 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_upper_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_upper_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(IN) :: fm_ao, fm_back
561 : INTEGER, INTENT(IN) :: transf_type_in
562 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: fm_mo_out
563 : LOGICAL, INTENT(IN), OPTIONAL :: recalc_hfx_integrals
564 :
565 : CHARACTER(LEN=*), PARAMETER :: routineN = 'cphf_like_update'
566 :
567 : INTEGER :: handle, i_global, iiB, ispin, j_global, &
568 : jjB, ncol_local, nrow_local
569 1470 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
570 1470 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: rho1_ao
571 :
572 1470 : CALL timeset(routineN, handle)
573 :
574 1470 : CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
575 :
576 : ! Determine the first-order density matrices in AO basis
577 3404 : DO ispin = 1, nspins
578 1934 : CALL dbcsr_set(p_env%p1(ispin)%matrix, 0.0_dp)
579 :
580 : ASSOCIATE (mat_in => fm_mo(ispin))
581 :
582 : ! perform back transformation
583 2284 : SELECT CASE (transf_type_in)
584 : CASE (1)
585 : ! occ-occ block
586 : CALL parallel_gemm('N', 'N', dimen, homo(ispin), homo(ispin), 1.0_dp, &
587 350 : mo_coeff_o(ispin), mat_in, 0.0_dp, fm_back)
588 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.)
589 : ! virt-virt block
590 : CALL parallel_gemm('N', 'N', dimen, virtual(ispin), virtual(ispin), 1.0_dp, &
591 : mo_coeff_v(ispin), mat_in, 0.0_dp, fm_back, &
592 : b_first_col=homo(ispin) + 1, &
593 350 : b_first_row=homo(ispin) + 1)
594 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.)
595 :
596 : CASE (3)
597 : ! virt-occ blocks
598 : CALL parallel_gemm('N', 'N', dimen, virtual(ispin), homo(ispin), 1.0_dp, &
599 1584 : mo_coeff_o(ispin), mat_in, 0.0_dp, fm_back)
600 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.)
601 : ! and symmetrize (here again multiply instead of transposing)
602 : CALL parallel_gemm('N', 'T', dimen, homo(ispin), virtual(ispin), 1.0_dp, &
603 1584 : mo_coeff_v(ispin), mat_in, 0.0_dp, fm_back)
604 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.)
605 :
606 : CASE DEFAULT
607 : ! nothing
608 : END SELECT
609 : END ASSOCIATE
610 :
611 3404 : CALL dbcsr_copy(rho1_ao(ispin)%matrix, p_env%p1(ispin)%matrix)
612 : END DO
613 :
614 1470 : CALL p_env_update_rho(p_env, qs_env)
615 :
616 1470 : IF (transf_type_in == 3) THEN
617 2790 : DO ispin = 1, nspins
618 :
619 : ! scale for the orbital energy differences for the diagonal elements
620 : CALL cp_fm_get_info(matrix=fm_mo_out(ispin), &
621 : nrow_local=nrow_local, &
622 : ncol_local=ncol_local, &
623 : row_indices=row_indices, &
624 1584 : col_indices=col_indices)
625 28696 : DO jjB = 1, ncol_local
626 25906 : j_global = col_indices(jjB)
627 77387 : DO iiB = 1, nrow_local
628 49897 : i_global = row_indices(iiB)
629 : fm_mo_out(ispin)%local_data(iiB, jjB) = fm_mo(ispin)%local_data(iiB, jjB)* &
630 75803 : (Eigenval(j_global + homo(ispin), ispin) - Eigenval(i_global, ispin))
631 : END DO
632 : END DO
633 : END DO
634 : END IF
635 :
636 1470 : CALL apply_2nd_order_kernel(qs_env, p_env, recalc_hfx_integrals)
637 :
638 3404 : DO ispin = 1, nspins
639 : ! copy back to fm
640 1934 : CALL cp_fm_set_all(fm_ao, 0.0_dp)
641 1934 : CALL copy_dbcsr_to_fm(matrix=p_env%kpp1(ispin)%matrix, fm=fm_ao)
642 1934 : CALL cp_fm_set_all(fm_back, 0.0_dp)
643 1934 : CALL cp_fm_upper_to_full(fm_ao, fm_back)
644 :
645 1470 : ASSOCIATE (mat_out => fm_mo_out(ispin))
646 :
647 : ! transform to MO basis, here we always sum the result into the input matrix
648 :
649 : ! occ-virt block
650 : CALL parallel_gemm('T', 'N', homo(ispin), dimen, dimen, 1.0_dp, &
651 1934 : mo_coeff_o(ispin), fm_ao, 0.0_dp, fm_back)
652 : CALL parallel_gemm('N', 'N', homo(ispin), virtual(ispin), dimen, 1.0_dp, &
653 1934 : fm_back, mo_coeff_v(ispin), 1.0_dp, mat_out)
654 : END ASSOCIATE
655 : END DO
656 :
657 1470 : CALL timestop(handle)
658 :
659 1470 : END SUBROUTINE cphf_like_update
660 :
661 : ! **************************************************************************************************
662 : !> \brief Low level subroutine for the iterative solution of a large
663 : !> system of linear equation
664 : !> \param qs_env ...
665 : !> \param mp2_env ...
666 : !> \param homo ...
667 : !> \param virtual ...
668 : !> \param dimen ...
669 : !> \param unit_nr ...
670 : !> \param nspins ...
671 : !> \param mo_coeff_o ...
672 : !> \param mo_coeff_v ...
673 : !> \param Eigenval ...
674 : !> \param p_env ...
675 : !> \param L_jb ...
676 : !> \param fm_G_mu_nu ...
677 : !> \param fm_back ...
678 : !> \param P_ia ...
679 : !> \author Mauro Del Ben, Vladimir Rybkin
680 : ! **************************************************************************************************
681 264 : SUBROUTINE solve_z_vector_eq_low(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
682 264 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
683 264 : L_jb, fm_G_mu_nu, fm_back, P_ia)
684 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
685 : TYPE(mp2_type), INTENT(IN) :: mp2_env
686 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
687 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
688 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
689 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
690 : INTENT(IN) :: Eigenval
691 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
692 : TYPE(cp_fm_type), DIMENSION(dimen), INTENT(IN) :: L_jb
693 : TYPE(cp_fm_type), INTENT(IN) :: fm_G_mu_nu, fm_back
694 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia
695 :
696 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_eq_low'
697 :
698 : INTEGER :: handle, i_global, iiB, ispin, j_global, &
699 : jjB, ncol_local, nrow_local
700 264 : INTEGER, DIMENSION(:), POINTER :: col_indices, row_indices
701 264 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: precond
702 :
703 264 : CALL timeset(routineN, handle)
704 :
705 : ! Pople method
706 : ! change sign to L_jb
707 614 : DO ispin = 1, nspins
708 15890 : L_jb(ispin)%local_data(:, :) = -L_jb(ispin)%local_data(:, :)
709 : END DO
710 :
711 : ! create fm structure
712 1142 : ALLOCATE (precond(nspins))
713 614 : DO ispin = 1, nspins
714 : ! create preconditioner (for now only orbital energy differences)
715 350 : CALL cp_fm_create(precond(ispin), P_ia(ispin)%matrix_struct, name="precond")
716 350 : CALL cp_fm_set_all(precond(ispin), 1.0_dp)
717 : CALL cp_fm_get_info(matrix=precond(ispin), &
718 : nrow_local=nrow_local, &
719 : ncol_local=ncol_local, &
720 : row_indices=row_indices, &
721 350 : col_indices=col_indices)
722 5946 : DO jjB = 1, ncol_local
723 5332 : j_global = col_indices(jjB)
724 15599 : DO iiB = 1, nrow_local
725 9917 : i_global = row_indices(iiB)
726 15249 : precond(ispin)%local_data(iiB, jjB) = Eigenval(j_global + homo(ispin), ispin) - Eigenval(i_global, ispin)
727 : END DO
728 : END DO
729 : END DO
730 :
731 614 : DO ispin = 1, nspins
732 15890 : precond(ispin)%local_data(:, :) = 1.0_dp/precond(ispin)%local_data(:, :)
733 : END DO
734 :
735 504 : SELECT CASE (mp2_env%ri_grad%z_solver_method)
736 : CASE (z_solver_pople)
737 : CALL solve_z_vector_pople(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
738 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
739 240 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
740 : CASE (z_solver_cg, z_solver_richardson, z_solver_sd)
741 : CALL solve_z_vector_cg(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
742 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
743 24 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
744 : CASE DEFAULT
745 264 : CPABORT("Unknown solver")
746 : END SELECT
747 :
748 264 : CALL cp_fm_release(precond)
749 :
750 264 : CALL timestop(handle)
751 :
752 528 : END SUBROUTINE solve_z_vector_eq_low
753 :
754 : ! **************************************************************************************************
755 : !> \brief ...
756 : !> \param qs_env ...
757 : !> \param mp2_env ...
758 : !> \param homo ...
759 : !> \param virtual ...
760 : !> \param dimen ...
761 : !> \param unit_nr ...
762 : !> \param nspins ...
763 : !> \param mo_coeff_o ...
764 : !> \param mo_coeff_v ...
765 : !> \param Eigenval ...
766 : !> \param p_env ...
767 : !> \param L_jb ...
768 : !> \param fm_G_mu_nu ...
769 : !> \param fm_back ...
770 : !> \param P_ia ...
771 : !> \param precond ...
772 : ! **************************************************************************************************
773 240 : SUBROUTINE solve_z_vector_pople(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
774 240 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
775 240 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
776 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
777 : TYPE(mp2_type), INTENT(IN) :: mp2_env
778 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
779 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
780 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
781 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
782 : INTENT(IN) :: Eigenval
783 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
784 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: L_jb
785 : TYPE(cp_fm_type), INTENT(IN) :: fm_G_mu_nu, fm_back
786 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia, precond
787 :
788 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_pople'
789 :
790 : INTEGER :: cycle_counter, handle, iiB, iiter, &
791 : ispin, max_num_iter, transf_type_in
792 : LOGICAL :: converged
793 : REAL(KIND=dp) :: conv, eps_conv, scale_cphf, t1, t2
794 240 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: proj_bi_xj, temp_vals, x_norm, xi_b
795 240 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: A_small, b_small, xi_Axi
796 : TYPE(cp_fm_struct_p_type), ALLOCATABLE, &
797 240 : DIMENSION(:) :: fm_struct_tmp
798 240 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: b_i, residual
799 240 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: Ax, xn
800 :
801 240 : CALL timeset(routineN, handle)
802 :
803 240 : eps_conv = mp2_env%ri_grad%cphf_eps_conv
804 :
805 240 : IF (SQRT(accurate_dot_product_spin(L_jb, L_jb)) >= eps_conv) THEN
806 :
807 240 : max_num_iter = mp2_env%ri_grad%cphf_max_num_iter
808 240 : scale_cphf = mp2_env%ri_grad%scale_step_size
809 :
810 : ! set the transformation type (equal for all methods all updates)
811 240 : transf_type_in = 3
812 :
813 : ! set convergence flag
814 240 : converged = .FALSE.
815 :
816 2418 : ALLOCATE (fm_struct_tmp(nspins), b_i(nspins), residual(nspins))
817 566 : DO ispin = 1, nspins
818 326 : fm_struct_tmp(ispin)%struct => P_ia(ispin)%matrix_struct
819 :
820 326 : CALL cp_fm_create(b_i(ispin), fm_struct_tmp(ispin)%struct, name="b_i")
821 326 : CALL cp_fm_set_all(b_i(ispin), 0.0_dp)
822 14234 : b_i(ispin)%local_data(:, :) = precond(ispin)%local_data(:, :)*L_jb(ispin)%local_data(:, :)
823 :
824 : ! create the residual vector (r), we check convergence on the norm of
825 : ! this vector r=(Ax-b)
826 326 : CALL cp_fm_create(residual(ispin), fm_struct_tmp(ispin)%struct, name="residual")
827 566 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
828 : END DO
829 :
830 240 : IF (unit_nr > 0) THEN
831 120 : WRITE (unit_nr, *)
832 120 : WRITE (unit_nr, '(T3,A)') "MP2_CPHF| Iterative solution of Z-Vector equations (Pople's method)"
833 120 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Convergence threshold:', eps_conv
834 120 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Maximum number of iterations: ', max_num_iter
835 120 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Scaling of initial guess: ', scale_cphf
836 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
837 120 : WRITE (unit_nr, '(T4,A,T15,A,T33,A)') 'Step', 'Time', 'Convergence'
838 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
839 : END IF
840 :
841 11530 : ALLOCATE (xn(nspins, max_num_iter))
842 11290 : ALLOCATE (Ax(nspins, max_num_iter))
843 720 : ALLOCATE (x_norm(max_num_iter))
844 480 : ALLOCATE (xi_b(max_num_iter))
845 960 : ALLOCATE (xi_Axi(max_num_iter, 0:max_num_iter))
846 4778 : x_norm = 0.0_dp
847 4778 : xi_b = 0.0_dp
848 134774 : xi_Axi = 0.0_dp
849 :
850 240 : cycle_counter = 0
851 1022 : DO iiter = 1, max_num_iter
852 1000 : cycle_counter = cycle_counter + 1
853 :
854 1000 : t1 = m_walltime()
855 :
856 : ! create and update x_i (orthogonalization with previous vectors)
857 2378 : DO ispin = 1, nspins
858 1378 : CALL cp_fm_create(xn(ispin, iiter), fm_struct_tmp(ispin)%struct, name="xi")
859 2378 : CALL cp_fm_set_all(xn(ispin, iiter), 0.0_dp)
860 : END DO
861 :
862 2760 : ALLOCATE (proj_bi_xj(iiter - 1))
863 2938 : proj_bi_xj = 0.0_dp
864 : ! first compute the projection of the actual b_i into all previous x_i
865 : ! already scaled with the norm of each x_i
866 2938 : DO iiB = 1, iiter - 1
867 2938 : proj_bi_xj(iiB) = proj_bi_xj(iiB) + accurate_dot_product_spin(b_i, xn(:, iiB))/x_norm(iiB)
868 : END DO
869 :
870 : ! update actual x_i
871 2378 : DO ispin = 1, nspins
872 65493 : xn(ispin, iiter)%local_data(:, :) = scale_cphf*b_i(ispin)%local_data(:, :)
873 5214 : DO iiB = 1, iiter - 1
874 : xn(ispin, iiter)%local_data(:, :) = xn(ispin, iiter)%local_data(:, :) - &
875 148494 : xn(ispin, iiB)%local_data(:, :)*proj_bi_xj(iiB)
876 : END DO
877 : END DO
878 1000 : DEALLOCATE (proj_bi_xj)
879 :
880 : ! create Ax(iiter) that will store the matrix vector product for this cycle
881 2378 : DO ispin = 1, nspins
882 1378 : CALL cp_fm_create(Ax(ispin, iiter), fm_struct_tmp(ispin)%struct, name="Ai")
883 2378 : CALL cp_fm_set_all(Ax(ispin, iiter), 0.0_dp)
884 : END DO
885 :
886 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
887 : mo_coeff_o, &
888 : mo_coeff_v, Eigenval, p_env, &
889 : xn(:, iiter), fm_G_mu_nu, fm_back, transf_type_in, &
890 1000 : Ax(:, iiter))
891 :
892 : ! in order to reduce the number of parallel sums here we
893 : ! cluster all necessary scalar products into a single vector
894 : ! temp_vals contains:
895 : ! 1:iiter -> <Ax_i|x_j>
896 : ! iiter+1 -> <x_i|b>
897 : ! iiter+2 -> <x_i|x_i>
898 :
899 3000 : ALLOCATE (temp_vals(iiter + 2))
900 5938 : temp_vals = 0.0_dp
901 : ! <Ax_i|x_j>
902 3938 : DO iiB = 1, iiter
903 3938 : temp_vals(iiB) = temp_vals(iiB) + accurate_dot_product_spin(Ax(:, iiter), xn(:, iiB))
904 : END DO
905 : ! <x_i|b>
906 1000 : temp_vals(iiter + 1) = temp_vals(iiter + 1) + accurate_dot_product_spin(xn(:, iiter), L_jb)
907 : ! norm
908 1000 : temp_vals(iiter + 2) = temp_vals(iiter + 2) + accurate_dot_product_spin(xn(:, iiter), xn(:, iiter))
909 : ! update <Ax_i|x_j>, <x_i|b> and norm <x_i|x_i>
910 3938 : xi_Axi(iiter, 1:iiter) = temp_vals(1:iiter)
911 3938 : xi_Axi(1:iiter, iiter) = temp_vals(1:iiter)
912 1000 : xi_b(iiter) = temp_vals(iiter + 1)
913 1000 : x_norm(iiter) = temp_vals(iiter + 2)
914 1000 : DEALLOCATE (temp_vals)
915 :
916 : ! solve reduced system
917 1000 : IF (ALLOCATED(A_small)) DEALLOCATE (A_small)
918 1000 : IF (ALLOCATED(b_small)) DEALLOCATE (b_small)
919 4000 : ALLOCATE (A_small(iiter, iiter))
920 3000 : ALLOCATE (b_small(iiter, 1))
921 15696 : A_small(1:iiter, 1:iiter) = xi_Axi(1:iiter, 1:iiter)
922 3938 : b_small(1:iiter, 1) = xi_b(1:iiter)
923 :
924 1000 : CALL solve_system(matrix=A_small, mysize=iiter, eigenvectors=b_small)
925 :
926 : ! check for convergence
927 2378 : DO ispin = 1, nspins
928 1378 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
929 5592 : DO iiB = 1, iiter
930 : residual(ispin)%local_data(:, :) = &
931 : residual(ispin)%local_data(:, :) + &
932 213987 : b_small(iiB, 1)*Ax(ispin, iiB)%local_data(:, :)
933 : END DO
934 :
935 : residual(ispin)%local_data(:, :) = &
936 : residual(ispin)%local_data(:, :) - &
937 66493 : L_jb(ispin)%local_data(:, :)
938 : END DO
939 :
940 1000 : conv = SQRT(accurate_dot_product_spin(residual, residual))
941 :
942 1000 : t2 = m_walltime()
943 :
944 1000 : IF (unit_nr > 0) THEN
945 500 : WRITE (unit_nr, '(T3,I5,T13,F6.1,11X,F14.8)') iiter, t2 - t1, conv
946 500 : CALL m_flush(unit_nr)
947 : END IF
948 :
949 1000 : IF (conv <= eps_conv) THEN
950 : converged = .TRUE.
951 : EXIT
952 : END IF
953 :
954 : ! update b_i for the next round
955 1874 : DO ispin = 1, nspins
956 : b_i(ispin)%local_data(:, :) = b_i(ispin)%local_data(:, :) &
957 : + precond(ispin)%local_data(:, :) &
958 53560 : *Ax(ispin, iiter)%local_data(:, :)
959 : END DO
960 :
961 804 : scale_cphf = 1.0_dp
962 :
963 : END DO
964 :
965 240 : IF (unit_nr > 0) THEN
966 120 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
967 120 : IF (converged) THEN
968 109 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations converged in', cycle_counter, ' steps'
969 : ELSE
970 11 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations NOT converged in', cycle_counter, ' steps'
971 : END IF
972 : END IF
973 :
974 : ! store solution into P_ia
975 1240 : DO iiter = 1, cycle_counter
976 2618 : DO ispin = 1, nspins
977 : P_ia(ispin)%local_data(:, :) = P_ia(ispin)%local_data(:, :) + &
978 66493 : b_small(iiter, 1)*xn(ispin, iiter)%local_data(:, :)
979 : END DO
980 : END DO
981 :
982 : ! Release arrays
983 240 : DEALLOCATE (x_norm)
984 240 : DEALLOCATE (xi_b)
985 240 : DEALLOCATE (xi_Axi)
986 :
987 240 : CALL cp_fm_release(b_i)
988 240 : CALL cp_fm_release(residual)
989 240 : CALL cp_fm_release(Ax)
990 240 : CALL cp_fm_release(xn)
991 :
992 : ELSE
993 0 : IF (unit_nr > 0) THEN
994 0 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
995 0 : WRITE (unit_nr, '(T3,A)') 'Residual smaller than EPS_CONV. Skip solution of Z-vector equation.'
996 : END IF
997 : END IF
998 :
999 240 : CALL timestop(handle)
1000 :
1001 240 : END SUBROUTINE solve_z_vector_pople
1002 :
1003 : ! **************************************************************************************************
1004 : !> \brief ...
1005 : !> \param qs_env ...
1006 : !> \param mp2_env ...
1007 : !> \param homo ...
1008 : !> \param virtual ...
1009 : !> \param dimen ...
1010 : !> \param unit_nr ...
1011 : !> \param nspins ...
1012 : !> \param mo_coeff_o ...
1013 : !> \param mo_coeff_v ...
1014 : !> \param Eigenval ...
1015 : !> \param p_env ...
1016 : !> \param L_jb ...
1017 : !> \param fm_G_mu_nu ...
1018 : !> \param fm_back ...
1019 : !> \param P_ia ...
1020 : !> \param precond ...
1021 : ! **************************************************************************************************
1022 24 : SUBROUTINE solve_z_vector_cg(qs_env, mp2_env, homo, virtual, dimen, unit_nr, nspins, &
1023 24 : mo_coeff_o, mo_coeff_v, Eigenval, p_env, &
1024 24 : L_jb, fm_G_mu_nu, fm_back, P_ia, precond)
1025 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1026 : TYPE(mp2_type), INTENT(IN) :: mp2_env
1027 : INTEGER, INTENT(IN) :: nspins, unit_nr, dimen
1028 : INTEGER, DIMENSION(nspins), INTENT(IN) :: virtual, homo
1029 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: mo_coeff_o, mo_coeff_v
1030 : REAL(KIND=dp), DIMENSION(dimen, nspins), &
1031 : INTENT(IN) :: Eigenval
1032 : TYPE(qs_p_env_type), INTENT(IN), POINTER :: p_env
1033 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: L_jb
1034 : TYPE(cp_fm_type), INTENT(IN) :: fm_G_mu_nu, fm_back
1035 : TYPE(cp_fm_type), DIMENSION(nspins), INTENT(IN) :: P_ia, precond
1036 :
1037 : CHARACTER(LEN=*), PARAMETER :: routineN = 'solve_z_vector_cg'
1038 :
1039 : INTEGER :: cycles_passed, handle, iiter, ispin, max_num_iter, restart_counter, &
1040 : restart_every, transf_type_in, z_solver_method
1041 : LOGICAL :: converged, do_restart
1042 : REAL(KIND=dp) :: eps_conv, norm_residual, norm_residual_old, &
1043 : residual_dot_diff_search_vec_new, residual_dot_diff_search_vec_old, &
1044 : residual_dot_search_vec, residual_new_dot_diff_search_vec_old, scale_result, &
1045 : scale_search, scale_step_size, search_vec_dot_A_search_vec, t1, t2
1046 : TYPE(cp_fm_struct_p_type), ALLOCATABLE, &
1047 24 : DIMENSION(:) :: fm_struct_tmp
1048 24 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: A_dot_search_vector, diff_search_vector, &
1049 24 : residual, search_vector
1050 :
1051 24 : CALL timeset(routineN, handle)
1052 :
1053 24 : max_num_iter = mp2_env%ri_grad%cphf_max_num_iter
1054 24 : eps_conv = mp2_env%ri_grad%cphf_eps_conv
1055 24 : z_solver_method = mp2_env%ri_grad%z_solver_method
1056 24 : restart_every = mp2_env%ri_grad%cphf_restart
1057 24 : scale_step_size = mp2_env%ri_grad%scale_step_size
1058 24 : transf_type_in = 3
1059 :
1060 24 : IF (unit_nr > 0) THEN
1061 12 : WRITE (unit_nr, *)
1062 8 : SELECT CASE (z_solver_method)
1063 : CASE (z_solver_cg)
1064 8 : IF (mp2_env%ri_grad%polak_ribiere) THEN
1065 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (CG with Polak-Ribiere step)'
1066 : ELSE
1067 6 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (CG with Fletcher-Reeves step)'
1068 : END IF
1069 : CASE (z_solver_richardson)
1070 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (Richardson method)'
1071 : CASE (z_solver_sd)
1072 2 : WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations (Steepest Descent method)'
1073 : CASE DEFAULT
1074 12 : CPABORT("Unknown solver")
1075 : END SELECT
1076 12 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Convergence threshold:', eps_conv
1077 12 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Maximum number of iterations: ', max_num_iter
1078 12 : WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Number of steps for restart: ', restart_every
1079 12 : WRITE (unit_nr, '(T3, A)') 'MP2_CPHF| Restart after no decrease'
1080 12 : WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Scaling factor of each step: ', scale_step_size
1081 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1082 12 : WRITE (unit_nr, '(T4,A,T13,A,T28,A,T43,A)') 'Step', 'Restart', 'Time', 'Convergence'
1083 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1084 : END IF
1085 :
1086 0 : ALLOCATE (fm_struct_tmp(nspins), residual(nspins), diff_search_vector(nspins), &
1087 312 : search_vector(nspins), A_dot_search_vector(nspins))
1088 48 : DO ispin = 1, nspins
1089 24 : fm_struct_tmp(ispin)%struct => P_ia(ispin)%matrix_struct
1090 :
1091 24 : CALL cp_fm_create(residual(ispin), fm_struct_tmp(ispin)%struct, name="residual")
1092 24 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
1093 :
1094 24 : CALL cp_fm_create(diff_search_vector(ispin), fm_struct_tmp(ispin)%struct, name="difference search vector")
1095 24 : CALL cp_fm_set_all(diff_search_vector(ispin), 0.0_dp)
1096 :
1097 24 : CALL cp_fm_create(search_vector(ispin), fm_struct_tmp(ispin)%struct, name="search vector")
1098 24 : CALL cp_fm_set_all(search_vector(ispin), 0.0_dp)
1099 :
1100 24 : CALL cp_fm_create(A_dot_search_vector(ispin), fm_struct_tmp(ispin)%struct, name="A times search vector")
1101 48 : CALL cp_fm_set_all(A_dot_search_vector(ispin), 0.0_dp)
1102 : END DO
1103 :
1104 24 : converged = .FALSE.
1105 24 : cycles_passed = max_num_iter
1106 : ! By that, we enforce the setup of the matrices
1107 24 : do_restart = .TRUE.
1108 :
1109 24 : t1 = m_walltime()
1110 :
1111 164 : DO iiter = 1, max_num_iter
1112 :
1113 : ! During the first iteration, P_ia=0 such that the application of the 2nd order matrix is zero
1114 160 : IF (do_restart) THEN
1115 : ! We do not consider the first step to be a restart
1116 : ! Do not recalculate residual if it is already enforced to save FLOPs
1117 52 : IF (.NOT. mp2_env%ri_grad%recalc_residual .OR. (iiter == 1)) THEN
1118 52 : IF (iiter > 1) THEN
1119 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1120 : mo_coeff_o, &
1121 : mo_coeff_v, Eigenval, p_env, &
1122 : P_ia, fm_G_mu_nu, fm_back, transf_type_in, &
1123 28 : residual)
1124 : ELSE
1125 24 : do_restart = .FALSE.
1126 :
1127 48 : DO ispin = 1, nspins
1128 48 : CALL cp_fm_set_all(residual(ispin), 0.0_dp)
1129 : END DO
1130 : END IF
1131 :
1132 104 : DO ispin = 1, nspins
1133 : residual(ispin)%local_data(:, :) = L_jb(ispin)%local_data(:, :) &
1134 3068 : - residual(ispin)%local_data(:, :)
1135 : END DO
1136 : END IF
1137 :
1138 104 : DO ispin = 1, nspins
1139 : diff_search_vector(ispin)%local_data(:, :) = &
1140 3016 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1141 3068 : search_vector(ispin)%local_data(:, :) = diff_search_vector(ispin)%local_data(:, :)
1142 : END DO
1143 :
1144 : restart_counter = 1
1145 : END IF
1146 :
1147 160 : norm_residual_old = SQRT(accurate_dot_product_spin(residual, residual))
1148 :
1149 160 : residual_dot_diff_search_vec_old = accurate_dot_product_spin(residual, diff_search_vector)
1150 :
1151 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1152 : mo_coeff_o, &
1153 : mo_coeff_v, Eigenval, p_env, &
1154 : search_vector, fm_G_mu_nu, fm_back, transf_type_in, &
1155 160 : A_dot_search_vector)
1156 :
1157 160 : IF (z_solver_method /= z_solver_richardson) THEN
1158 120 : search_vec_dot_A_search_vec = accurate_dot_product_spin(search_vector, A_dot_search_vector)
1159 :
1160 120 : IF (z_solver_method == z_solver_cg) THEN
1161 94 : scale_result = residual_dot_diff_search_vec_old/search_vec_dot_A_search_vec
1162 : ELSE
1163 26 : residual_dot_search_vec = accurate_dot_product_spin(residual, search_vector)
1164 26 : scale_result = residual_dot_search_vec/search_vec_dot_A_search_vec
1165 : END IF
1166 :
1167 120 : scale_result = scale_result*scale_step_size
1168 :
1169 : ELSE
1170 :
1171 : scale_result = scale_step_size
1172 :
1173 : END IF
1174 :
1175 320 : DO ispin = 1, nspins
1176 : P_ia(ispin)%local_data(:, :) = P_ia(ispin)%local_data(:, :) &
1177 9440 : + scale_result*search_vector(ispin)%local_data(:, :)
1178 : END DO
1179 :
1180 160 : IF (.NOT. mp2_env%ri_grad%recalc_residual) THEN
1181 :
1182 284 : DO ispin = 1, nspins
1183 : residual(ispin)%local_data(:, :) = residual(ispin)%local_data(:, :) &
1184 8378 : - scale_result*A_dot_search_vector(ispin)%local_data(:, :)
1185 : END DO
1186 : ELSE
1187 : CALL cphf_like_update(qs_env, homo, virtual, dimen, nspins, &
1188 : mo_coeff_o, &
1189 : mo_coeff_v, Eigenval, p_env, &
1190 : P_ia, fm_G_mu_nu, fm_back, transf_type_in, &
1191 18 : residual)
1192 :
1193 36 : DO ispin = 1, nspins
1194 1062 : residual(ispin)%local_data(:, :) = L_jb(ispin)%local_data(:, :) - residual(ispin)%local_data(:, :)
1195 : END DO
1196 : END IF
1197 :
1198 160 : norm_residual = SQRT(accurate_dot_product_spin(residual, residual))
1199 :
1200 160 : t2 = m_walltime()
1201 :
1202 160 : IF (unit_nr > 0) THEN
1203 80 : WRITE (unit_nr, '(T3,I4,T16,L1,T26,F6.1,8X,F14.8)') iiter, do_restart, t2 - t1, norm_residual
1204 80 : CALL m_flush(unit_nr)
1205 : END IF
1206 :
1207 160 : IF (norm_residual <= eps_conv) THEN
1208 20 : converged = .TRUE.
1209 20 : cycles_passed = iiter
1210 20 : EXIT
1211 : END IF
1212 :
1213 140 : t1 = m_walltime()
1214 :
1215 140 : IF (z_solver_method == z_solver_richardson) THEN
1216 80 : DO ispin = 1, nspins
1217 : search_vector(ispin)%local_data(:, :) = &
1218 2360 : scale_step_size*precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1219 : END DO
1220 100 : ELSE IF (z_solver_method == z_solver_sd) THEN
1221 44 : DO ispin = 1, nspins
1222 : search_vector(ispin)%local_data(:, :) = &
1223 1298 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1224 : END DO
1225 : ELSE
1226 78 : IF (mp2_env%ri_grad%polak_ribiere) &
1227 28 : residual_new_dot_diff_search_vec_old = accurate_dot_product_spin(residual, diff_search_vector)
1228 :
1229 156 : DO ispin = 1, nspins
1230 : diff_search_vector(ispin)%local_data(:, :) = &
1231 4602 : precond(ispin)%local_data(:, :)*residual(ispin)%local_data(:, :)
1232 : END DO
1233 :
1234 78 : residual_dot_diff_search_vec_new = accurate_dot_product_spin(residual, diff_search_vector)
1235 :
1236 78 : scale_search = residual_dot_diff_search_vec_new/residual_dot_diff_search_vec_old
1237 78 : IF (mp2_env%ri_grad%polak_ribiere) scale_search = &
1238 28 : scale_search - residual_new_dot_diff_search_vec_old/residual_dot_diff_search_vec_old
1239 :
1240 156 : DO ispin = 1, nspins
1241 : search_vector(ispin)%local_data(:, :) = scale_search*search_vector(ispin)%local_data(:, :) &
1242 4602 : + diff_search_vector(ispin)%local_data(:, :)
1243 : END DO
1244 :
1245 : ! Make new to old
1246 140 : residual_dot_diff_search_vec_old = residual_dot_diff_search_vec_new
1247 : END IF
1248 :
1249 : ! Check whether the residual decrease or restart is enforced and ask for restart
1250 140 : do_restart = (norm_residual >= norm_residual_old .OR. (MOD(restart_counter, restart_every) == 0))
1251 :
1252 140 : restart_counter = restart_counter + 1
1253 144 : norm_residual_old = norm_residual
1254 :
1255 : END DO
1256 :
1257 24 : IF (unit_nr > 0) THEN
1258 12 : WRITE (unit_nr, '(T4,A)') REPEAT("-", 40)
1259 12 : IF (converged) THEN
1260 10 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations converged in', cycles_passed, ' steps'
1261 : ELSE
1262 2 : WRITE (unit_nr, '(T3,A,I5,A)') 'Z-Vector equations NOT converged in', max_num_iter, ' steps'
1263 : END IF
1264 : END IF
1265 :
1266 24 : DEALLOCATE (fm_struct_tmp)
1267 24 : CALL cp_fm_release(residual)
1268 24 : CALL cp_fm_release(diff_search_vector)
1269 24 : CALL cp_fm_release(search_vector)
1270 24 : CALL cp_fm_release(A_dot_search_vector)
1271 :
1272 24 : CALL timestop(handle)
1273 :
1274 48 : END SUBROUTINE solve_z_vector_cg
1275 :
1276 : ! **************************************************************************************************
1277 : !> \brief ...
1278 : !> \param matrix1 ...
1279 : !> \param matrix2 ...
1280 : !> \return ...
1281 : ! **************************************************************************************************
1282 8848 : FUNCTION accurate_dot_product_spin(matrix1, matrix2) RESULT(dotproduct)
1283 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: matrix1, matrix2
1284 : REAL(KIND=dp) :: dotproduct
1285 :
1286 : INTEGER :: ispin
1287 :
1288 8848 : dotproduct = 0.0_dp
1289 21090 : DO ispin = 1, SIZE(matrix1)
1290 21090 : dotproduct = dotproduct + accurate_dot_product(matrix1(ispin)%local_data, matrix2(ispin)%local_data)
1291 : END DO
1292 8848 : CALL matrix1(1)%matrix_struct%para_env%sum(dotproduct)
1293 :
1294 8848 : END FUNCTION accurate_dot_product_spin
1295 :
1296 : ! **************************************************************************************************
1297 : !> \brief ...
1298 : !> \param qs_env ...
1299 : ! **************************************************************************************************
1300 264 : SUBROUTINE update_mp2_forces(qs_env)
1301 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1302 :
1303 : CHARACTER(LEN=*), PARAMETER :: routineN = 'update_mp2_forces'
1304 :
1305 : INTEGER :: alpha, beta, handle, idir, iounit, &
1306 : ispin, nimages, nocc, nspins
1307 : INTEGER, DIMENSION(3) :: comp
1308 264 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1309 : LOGICAL :: do_exx, do_hfx, use_virial
1310 : REAL(KIND=dp) :: e_dummy, e_hartree, e_xc, ehartree, exc
1311 : REAL(KIND=dp), DIMENSION(3) :: deb
1312 : REAL(KIND=dp), DIMENSION(3, 3) :: h_stress, pv_virial
1313 : TYPE(admm_type), POINTER :: admm_env
1314 264 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1315 : TYPE(cell_type), POINTER :: cell
1316 : TYPE(cp_logger_type), POINTER :: logger
1317 : TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:), &
1318 264 : TARGET :: matrix_ks_aux
1319 264 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_p_mp2, &
1320 264 : matrix_p_mp2_admm, matrix_s, rho1, &
1321 264 : rho_ao, rho_ao_aux, scrm
1322 264 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: rho_ao_kp, scrm_kp
1323 : TYPE(dft_control_type), POINTER :: dft_control
1324 264 : TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
1325 : TYPE(linres_control_type), POINTER :: linres_control
1326 264 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1327 : TYPE(mp_para_env_type), POINTER :: para_env
1328 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1329 264 : POINTER :: sab_orb, sac_ae, sac_ppl, sap_ppnl
1330 264 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1331 : TYPE(pw_c1d_gs_type) :: pot_g, rho_tot_g, temp_pw_g
1332 264 : TYPE(pw_c1d_gs_type), ALLOCATABLE, DIMENSION(:) :: dvg
1333 264 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g, rho_mp2_g
1334 : TYPE(pw_c1d_gs_type), POINTER :: rho_core
1335 : TYPE(pw_env_type), POINTER :: pw_env
1336 : TYPE(pw_poisson_type), POINTER :: poisson_env
1337 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1338 : TYPE(pw_r3d_rs_type) :: pot_r, vh_rspace, vhxc_rspace
1339 264 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_mp2_r, rho_mp2_r_aux, rho_r, &
1340 264 : tau_mp2_r, vadmm_rspace, vtau_rspace, &
1341 264 : vxc_rspace
1342 : TYPE(qs_dispersion_type), POINTER :: dispersion_env
1343 : TYPE(qs_energy_type), POINTER :: energy
1344 264 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
1345 264 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1346 : TYPE(qs_ks_env_type), POINTER :: ks_env
1347 : TYPE(qs_p_env_type), POINTER :: p_env
1348 : TYPE(qs_rho_type), POINTER :: rho, rho_aux
1349 : TYPE(section_vals_type), POINTER :: hfx_section, hfx_sections, input, &
1350 : xc_section
1351 : TYPE(task_list_type), POINTER :: task_list_aux_fit
1352 : TYPE(virial_type), POINTER :: virial
1353 :
1354 264 : CALL timeset(routineN, handle)
1355 :
1356 264 : NULLIFY (input, pw_env, matrix_s, rho, energy, force, virial, &
1357 264 : matrix_p_mp2, matrix_p_mp2_admm, matrix_ks, rho_core)
1358 : CALL get_qs_env(qs_env, &
1359 : ks_env=ks_env, &
1360 : dft_control=dft_control, &
1361 : pw_env=pw_env, &
1362 : input=input, &
1363 : mos=mos, &
1364 : para_env=para_env, &
1365 : matrix_s=matrix_s, &
1366 : matrix_ks=matrix_ks, &
1367 : matrix_p_mp2=matrix_p_mp2, &
1368 : matrix_p_mp2_admm=matrix_p_mp2_admm, &
1369 : rho=rho, &
1370 : cell=cell, &
1371 : force=force, &
1372 : virial=virial, &
1373 : sab_orb=sab_orb, &
1374 : energy=energy, &
1375 : rho_core=rho_core, &
1376 264 : x_data=x_data)
1377 :
1378 264 : logger => cp_get_default_logger()
1379 : iounit = cp_print_key_unit_nr(logger, input, "DFT%XC%WF_CORRELATION%PRINT", &
1380 264 : extension=".mp2Log")
1381 :
1382 264 : do_exx = .FALSE.
1383 264 : IF (qs_env%mp2_env%method == ri_rpa_method_gpw) THEN
1384 20 : hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
1385 20 : CALL section_vals_get(hfx_section, explicit=do_exx)
1386 : END IF
1387 :
1388 264 : nimages = dft_control%nimages
1389 264 : CPASSERT(nimages == 1)
1390 264 : NULLIFY (cell_to_index)
1391 :
1392 264 : p_env => qs_env%mp2_env%ri_grad%p_env
1393 :
1394 264 : CALL qs_rho_get(rho, rho_ao=rho_ao, rho_ao_kp=rho_ao_kp, rho_r=rho_r, rho_g=rho_g)
1395 264 : nspins = SIZE(rho_ao)
1396 :
1397 : ! check if we have to calculate the virial
1398 264 : use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
1399 264 : IF (use_virial) virial%pv_calculate = .TRUE.
1400 :
1401 264 : CALL zero_qs_force(force)
1402 264 : IF (use_virial) CALL zero_virial(virial, .FALSE.)
1403 :
1404 614 : DO ispin = 1, nspins
1405 614 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
1406 : END DO
1407 :
1408 264 : IF (nspins == 2) THEN
1409 86 : CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, 1.0_dp, 1.0_dp)
1410 : END IF
1411 :
1412 : ! Kinetic energy matrix
1413 264 : NULLIFY (scrm)
1414 : IF (debug_forces) THEN
1415 1056 : deb(1:3) = force(1)%kinetic(1:3, 1)
1416 264 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1417 : END IF
1418 : CALL build_kinetic_matrix(ks_env, matrix_t=scrm, &
1419 : matrix_name="KINETIC ENERGY MATRIX", &
1420 : basis_type="ORB", &
1421 : sab_nl=sab_orb, calculate_forces=.TRUE., &
1422 264 : matrix_p=rho_ao(1)%matrix)
1423 : IF (debug_forces) THEN
1424 1056 : deb(1:3) = force(1)%kinetic(1:3, 1) - deb(1:3)
1425 264 : CALL para_env%sum(deb)
1426 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dT ", deb
1427 264 : IF (use_virial) THEN
1428 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1429 50 : CALL para_env%sum(e_dummy)
1430 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: T ", e_dummy
1431 : END IF
1432 : END IF
1433 264 : CALL dbcsr_deallocate_matrix_set(scrm)
1434 :
1435 264 : IF (nspins == 2) THEN
1436 86 : CALL dbcsr_add(rho_ao(1)%matrix, rho_ao(2)%matrix, 1.0_dp, -1.0_dp)
1437 : END IF
1438 :
1439 : ! Add pseudo potential terms
1440 264 : scrm_kp(1:nspins, 1:1) => matrix_ks(1:nspins)
1441 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, particle_set=particle_set, &
1442 264 : atomic_kind_set=atomic_kind_set, sac_ae=sac_ae, sac_ppl=sac_ppl, sap_ppnl=sap_ppnl)
1443 264 : IF (ASSOCIATED(sac_ae)) THEN
1444 : IF (debug_forces) THEN
1445 0 : deb(1:3) = force(1)%all_potential(1:3, 1)
1446 0 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1447 : END IF
1448 : CALL build_core_ae(scrm_kp, rho_ao_kp, force, &
1449 : virial, .TRUE., use_virial, 1, &
1450 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sac_ae, &
1451 0 : nimages, cell_to_index)
1452 : IF (debug_forces) THEN
1453 0 : deb(1:3) = force(1)%all_potential(1:3, 1) - deb(1:3)
1454 0 : CALL para_env%sum(deb)
1455 0 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHae ", deb
1456 0 : IF (use_virial) THEN
1457 0 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1458 0 : CALL para_env%sum(e_dummy)
1459 0 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hae ", e_dummy
1460 : END IF
1461 : END IF
1462 : END IF
1463 264 : IF (ASSOCIATED(sac_ppl)) THEN
1464 : IF (debug_forces) THEN
1465 1056 : deb(1:3) = force(1)%gth_ppl(1:3, 1)
1466 264 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1467 : END IF
1468 : CALL build_core_ppl(scrm_kp, rho_ao_kp, force, &
1469 : virial, .TRUE., use_virial, 1, &
1470 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sac_ppl, &
1471 264 : nimages=1, basis_type="ORB")
1472 : IF (debug_forces) THEN
1473 1056 : deb(1:3) = force(1)%gth_ppl(1:3, 1) - deb(1:3)
1474 264 : CALL para_env%sum(deb)
1475 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHppl ", deb
1476 264 : IF (use_virial) THEN
1477 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1478 50 : CALL para_env%sum(e_dummy)
1479 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hppl ", e_dummy
1480 : END IF
1481 : END IF
1482 : END IF
1483 264 : IF (ASSOCIATED(sap_ppnl)) THEN
1484 : IF (debug_forces) THEN
1485 1016 : deb(1:3) = force(1)%gth_ppnl(1:3, 1)
1486 254 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1487 : END IF
1488 : CALL build_core_ppnl(scrm_kp, rho_ao_kp, force, &
1489 : virial, .TRUE., use_virial, 1, &
1490 : qs_kind_set, atomic_kind_set, particle_set, sab_orb, sap_ppnl, dft_control%qs_control%eps_ppnl, &
1491 254 : nimages=1, basis_type="ORB")
1492 : IF (debug_forces) THEN
1493 1016 : deb(1:3) = force(1)%gth_ppnl(1:3, 1) - deb(1:3)
1494 254 : CALL para_env%sum(deb)
1495 254 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dHppnl ", deb
1496 254 : IF (use_virial) THEN
1497 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1498 50 : CALL para_env%sum(e_dummy)
1499 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hppnl ", e_dummy
1500 : END IF
1501 : END IF
1502 : END IF
1503 :
1504 : ! Get the different components of the KS potential
1505 264 : NULLIFY (vxc_rspace, vtau_rspace, vadmm_rspace)
1506 264 : IF (use_virial) THEN
1507 50 : h_stress = 0.0_dp
1508 50 : CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, ehartree, exc, h_stress)
1509 : ! Update virial
1510 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress/REAL(para_env%num_pe, dp)
1511 650 : virial%pv_virial = virial%pv_virial + h_stress/REAL(para_env%num_pe, dp)
1512 50 : IF (.NOT. do_exx) THEN
1513 650 : virial%pv_exc = virial%pv_exc - virial%pv_xc
1514 650 : virial%pv_virial = virial%pv_virial - virial%pv_xc
1515 : ELSE
1516 0 : virial%pv_xc = 0.0_dp
1517 : END IF
1518 : IF (debug_forces) THEN
1519 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: xc ", third_tr(h_stress)
1520 50 : CALL para_env%sum(virial%pv_xc(1, 1))
1521 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Corr xc ", third_tr(virial%pv_xc)
1522 : END IF
1523 : ELSE
1524 214 : CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, ehartree, exc)
1525 : END IF
1526 :
1527 : ! Vhxc
1528 264 : CALL get_qs_env(qs_env, pw_env=pw_env)
1529 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
1530 264 : poisson_env=poisson_env)
1531 264 : CALL auxbas_pw_pool%create_pw(vhxc_rspace)
1532 864 : IF (use_virial) h_stress = virial%pv_virial
1533 : IF (debug_forces) THEN
1534 1056 : deb(1:3) = force(1)%rho_elec(1:3, 1)
1535 264 : IF (use_virial) e_dummy = third_tr(h_stress)
1536 : END IF
1537 264 : IF (do_exx) THEN
1538 16 : DO ispin = 1, nspins
1539 8 : CALL pw_transfer(vh_rspace, vhxc_rspace)
1540 8 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
1541 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1542 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1543 8 : qs_env=qs_env, calculate_forces=.TRUE.)
1544 8 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
1545 8 : CALL pw_axpy(vxc_rspace(ispin), vhxc_rspace)
1546 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1547 : hmat=matrix_ks(ispin), pmat=matrix_p_mp2(ispin), &
1548 8 : qs_env=qs_env, calculate_forces=.TRUE.)
1549 16 : IF (ASSOCIATED(vtau_rspace)) THEN
1550 : CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
1551 : hmat=matrix_ks(ispin), pmat=matrix_p_mp2(ispin), &
1552 0 : qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
1553 : END IF
1554 : END DO
1555 : ELSE
1556 598 : DO ispin = 1, nspins
1557 342 : CALL pw_transfer(vh_rspace, vhxc_rspace)
1558 342 : CALL pw_axpy(vxc_rspace(ispin), vhxc_rspace)
1559 : CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
1560 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1561 342 : qs_env=qs_env, calculate_forces=.TRUE.)
1562 598 : IF (ASSOCIATED(vtau_rspace)) THEN
1563 : CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
1564 : hmat=matrix_ks(ispin), pmat=rho_ao(ispin), &
1565 60 : qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
1566 : END IF
1567 : END DO
1568 : END IF
1569 : IF (debug_forces) THEN
1570 1056 : deb(1:3) = force(1)%rho_elec(1:3, 1) - deb(1:3)
1571 264 : CALL para_env%sum(deb)
1572 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*dVhxc ", deb
1573 264 : IF (use_virial) THEN
1574 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1575 50 : CALL para_env%sum(e_dummy)
1576 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Vhxc ", e_dummy
1577 : END IF
1578 : END IF
1579 264 : IF (use_virial) THEN
1580 650 : h_stress = virial%pv_virial - h_stress
1581 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress
1582 :
1583 50 : CALL qs_rho_get(p_env%rho1, rho_r=rho_mp2_r, tau_r=tau_mp2_r)
1584 50 : e_xc = 0.0_dp
1585 124 : DO ispin = 1, nspins
1586 : ! The potentials have been scaled in ks_ref_potential, but for pw_integral_ab, we need the unscaled potentials
1587 74 : CALL pw_scale(vxc_rspace(ispin), 1.0_dp/vxc_rspace(ispin)%pw_grid%dvol)
1588 74 : e_xc = e_xc + pw_integral_ab(rho_mp2_r(ispin), vxc_rspace(ispin))
1589 74 : IF (ASSOCIATED(vtau_rspace)) CALL pw_scale(vtau_rspace(ispin), 1.0_dp/vtau_rspace(ispin)%pw_grid%dvol)
1590 124 : IF (ASSOCIATED(vtau_rspace)) e_xc = e_xc + pw_integral_ab(tau_mp2_r(ispin), vtau_rspace(ispin))
1591 : END DO
1592 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG VIRIAL:: vxc*d1 ", e_xc
1593 200 : DO alpha = 1, 3
1594 150 : virial%pv_exc(alpha, alpha) = virial%pv_exc(alpha, alpha) - e_xc/REAL(para_env%num_pe, dp)
1595 200 : virial%pv_virial(alpha, alpha) = virial%pv_virial(alpha, alpha) - e_xc/REAL(para_env%num_pe, dp)
1596 : END DO
1597 : END IF
1598 614 : DO ispin = 1, nspins
1599 350 : CALL auxbas_pw_pool%give_back_pw(vxc_rspace(ispin))
1600 614 : IF (ASSOCIATED(vtau_rspace)) THEN
1601 60 : CALL auxbas_pw_pool%give_back_pw(vtau_rspace(ispin))
1602 : END IF
1603 : END DO
1604 264 : DEALLOCATE (vxc_rspace)
1605 264 : CALL auxbas_pw_pool%give_back_pw(vhxc_rspace)
1606 264 : IF (ASSOCIATED(vtau_rspace)) DEALLOCATE (vtau_rspace)
1607 :
1608 614 : DO ispin = 1, nspins
1609 614 : CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
1610 : END DO
1611 :
1612 : ! pw stuff
1613 264 : NULLIFY (poisson_env, auxbas_pw_pool)
1614 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
1615 264 : poisson_env=poisson_env)
1616 :
1617 : ! get some of the grids ready
1618 264 : CALL auxbas_pw_pool%create_pw(pot_r)
1619 264 : CALL auxbas_pw_pool%create_pw(pot_g)
1620 264 : CALL auxbas_pw_pool%create_pw(rho_tot_g)
1621 :
1622 264 : CALL pw_zero(rho_tot_g)
1623 :
1624 264 : CALL qs_rho_get(p_env%rho1, rho_r=rho_mp2_r, rho_g=rho_mp2_g)
1625 614 : DO ispin = 1, nspins
1626 614 : CALL pw_axpy(rho_mp2_g(ispin), rho_tot_g)
1627 : END DO
1628 :
1629 264 : IF (use_virial) THEN
1630 200 : ALLOCATE (dvg(3))
1631 200 : DO idir = 1, 3
1632 200 : CALL auxbas_pw_pool%create_pw(dvg(idir))
1633 : END DO
1634 50 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g, dvhartree=dvg)
1635 : ELSE
1636 214 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g)
1637 : END IF
1638 :
1639 264 : CALL pw_transfer(pot_g, pot_r)
1640 264 : CALL pw_scale(pot_r, pot_r%pw_grid%dvol)
1641 264 : CALL pw_axpy(pot_r, vh_rspace)
1642 :
1643 : ! calculate core forces
1644 264 : CALL integrate_v_core_rspace(vh_rspace, qs_env)
1645 : IF (debug_forces) THEN
1646 1056 : deb(:) = force(1)%rho_core(:, 1)
1647 264 : CALL para_env%sum(deb)
1648 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: core ", deb
1649 264 : IF (use_virial) THEN
1650 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1651 50 : CALL para_env%sum(e_dummy)
1652 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: core ", e_dummy
1653 : END IF
1654 : END IF
1655 264 : CALL auxbas_pw_pool%give_back_pw(vh_rspace)
1656 :
1657 264 : IF (use_virial) THEN
1658 : ! update virial if necessary with the volume term
1659 : ! first create pw auxiliary stuff
1660 50 : CALL auxbas_pw_pool%create_pw(temp_pw_g)
1661 :
1662 : ! make a copy of the MP2 density in G space
1663 50 : CALL pw_copy(rho_tot_g, temp_pw_g)
1664 :
1665 : ! calculate total SCF density and potential
1666 50 : CALL pw_copy(rho_g(1), rho_tot_g)
1667 50 : IF (nspins == 2) CALL pw_axpy(rho_g(2), rho_tot_g)
1668 50 : CALL pw_axpy(rho_core, rho_tot_g)
1669 50 : CALL pw_poisson_solve(poisson_env, rho_tot_g, vhartree=pot_g)
1670 :
1671 : ! finally update virial with the volume contribution
1672 50 : e_hartree = pw_integral_ab(temp_pw_g, pot_g)
1673 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: vh1*d0 ", e_hartree
1674 :
1675 50 : h_stress = 0.0_dp
1676 200 : DO alpha = 1, 3
1677 150 : comp = 0
1678 150 : comp(alpha) = 1
1679 150 : CALL pw_copy(pot_g, rho_tot_g)
1680 150 : CALL pw_derive(rho_tot_g, comp)
1681 150 : h_stress(alpha, alpha) = -e_hartree
1682 500 : DO beta = alpha, 3
1683 : h_stress(alpha, beta) = h_stress(alpha, beta) &
1684 300 : - 2.0_dp*pw_integral_ab(rho_tot_g, dvg(beta))/fourpi
1685 450 : h_stress(beta, alpha) = h_stress(alpha, beta)
1686 : END DO
1687 : END DO
1688 50 : IF (debug_forces .AND. iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Hartree ", third_tr(h_stress)
1689 :
1690 : ! free stuff
1691 50 : CALL auxbas_pw_pool%give_back_pw(temp_pw_g)
1692 200 : DO idir = 1, 3
1693 200 : CALL auxbas_pw_pool%give_back_pw(dvg(idir))
1694 : END DO
1695 50 : DEALLOCATE (dvg)
1696 :
1697 650 : virial%pv_ehartree = virial%pv_ehartree + h_stress/REAL(para_env%num_pe, dp)
1698 650 : virial%pv_virial = virial%pv_virial + h_stress/REAL(para_env%num_pe, dp)
1699 :
1700 : END IF
1701 :
1702 614 : DO ispin = 1, nspins
1703 350 : CALL dbcsr_set(p_env%kpp1(ispin)%matrix, 0.0_dp)
1704 614 : IF (dft_control%do_admm) CALL dbcsr_set(p_env%kpp1_admm(ispin)%matrix, 0.0_dp)
1705 : END DO
1706 :
1707 264 : CALL get_qs_env(qs_env=qs_env, linres_control=linres_control)
1708 :
1709 264 : IF (dft_control%do_admm) THEN
1710 40 : CALL get_qs_env(qs_env, admm_env=admm_env)
1711 40 : xc_section => admm_env%xc_section_primary
1712 : ELSE
1713 224 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
1714 : END IF
1715 :
1716 264 : IF (use_virial) THEN
1717 50 : h_stress = 0.0_dp
1718 650 : pv_virial = virial%pv_virial
1719 : END IF
1720 : IF (debug_forces) THEN
1721 1056 : deb = force(1)%rho_elec(1:3, 1)
1722 264 : IF (use_virial) e_dummy = third_tr(pv_virial)
1723 : END IF
1724 264 : CALL apply_2nd_order_kernel(qs_env, p_env, .FALSE., .TRUE., use_virial, h_stress)
1725 264 : IF (use_virial) THEN
1726 650 : virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_virial)
1727 : IF (debug_forces) THEN
1728 650 : e_dummy = third_tr(virial%pv_virial - pv_virial)
1729 50 : CALL para_env%sum(e_dummy)
1730 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Kh ", e_dummy
1731 : END IF
1732 650 : virial%pv_exc = virial%pv_exc + h_stress
1733 650 : virial%pv_virial = virial%pv_virial + h_stress
1734 : IF (debug_forces) THEN
1735 50 : e_dummy = third_tr(h_stress)
1736 50 : CALL para_env%sum(e_dummy)
1737 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Kxc ", e_dummy
1738 : END IF
1739 : END IF
1740 : IF (debug_forces) THEN
1741 1056 : deb(:) = force(1)%rho_elec(:, 1) - deb
1742 264 : CALL para_env%sum(deb)
1743 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P0*Khxc ", deb
1744 264 : IF (use_virial) THEN
1745 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1746 50 : CALL para_env%sum(e_dummy)
1747 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: Khxc ", e_dummy
1748 : END IF
1749 : END IF
1750 :
1751 : ! hfx section
1752 264 : NULLIFY (hfx_sections)
1753 264 : hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
1754 264 : CALL section_vals_get(hfx_sections, explicit=do_hfx)
1755 264 : IF (do_hfx) THEN
1756 184 : IF (do_exx) THEN
1757 0 : IF (dft_control%do_admm) THEN
1758 0 : CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
1759 0 : CALL qs_rho_get(rho_aux, rho_ao=rho_ao_aux, rho_ao_kp=rho_ao_kp)
1760 0 : rho1 => p_env%p1_admm
1761 : ELSE
1762 0 : rho1 => p_env%p1
1763 : END IF
1764 : ELSE
1765 184 : IF (dft_control%do_admm) THEN
1766 36 : CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
1767 36 : CALL qs_rho_get(rho_aux, rho_ao=rho_ao_aux, rho_ao_kp=rho_ao_kp)
1768 90 : DO ispin = 1, nspins
1769 90 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
1770 : END DO
1771 36 : rho1 => p_env%p1_admm
1772 : ELSE
1773 328 : DO ispin = 1, nspins
1774 328 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, 1.0_dp)
1775 : END DO
1776 148 : rho1 => p_env%p1
1777 : END IF
1778 : END IF
1779 :
1780 184 : IF (x_data(1, 1)%do_hfx_ri) THEN
1781 :
1782 : CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
1783 : x_data(1, 1)%general_parameter%fraction, &
1784 : rho_ao=rho_ao_kp, rho_ao_resp=rho1, &
1785 6 : use_virial=use_virial, resp_only=do_exx)
1786 :
1787 : ELSE
1788 : CALL derivatives_four_center(qs_env, rho_ao_kp, rho1, hfx_sections, para_env, &
1789 178 : 1, use_virial, resp_only=do_exx)
1790 : END IF
1791 :
1792 184 : IF (use_virial) THEN
1793 338 : virial%pv_exx = virial%pv_exx - virial%pv_fock_4c
1794 338 : virial%pv_virial = virial%pv_virial - virial%pv_fock_4c
1795 : END IF
1796 : IF (debug_forces) THEN
1797 736 : deb(1:3) = force(1)%fock_4c(1:3, 1) - deb(1:3)
1798 184 : CALL para_env%sum(deb)
1799 184 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*hfx ", deb
1800 184 : IF (use_virial) THEN
1801 26 : e_dummy = third_tr(virial%pv_fock_4c)
1802 26 : CALL para_env%sum(e_dummy)
1803 26 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: hfx ", e_dummy
1804 : END IF
1805 : END IF
1806 :
1807 184 : IF (.NOT. do_exx) THEN
1808 184 : IF (dft_control%do_admm) THEN
1809 36 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
1810 90 : DO ispin = 1, nspins
1811 90 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
1812 : END DO
1813 : ELSE
1814 328 : DO ispin = 1, nspins
1815 328 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, -1.0_dp)
1816 : END DO
1817 : END IF
1818 : END IF
1819 :
1820 184 : IF (dft_control%do_admm) THEN
1821 : IF (debug_forces) THEN
1822 144 : deb = force(1)%overlap_admm(1:3, 1)
1823 36 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1824 : END IF
1825 : ! The 2nd order kernel contains a factor of two in apply_xc_admm_ao which we don't need for the projection derivatives
1826 36 : IF (nspins == 1) CALL dbcsr_scale(p_env%kpp1_admm(1)%matrix, 0.5_dp)
1827 36 : CALL admm_projection_derivative(qs_env, p_env%kpp1_admm, rho_ao)
1828 : IF (debug_forces) THEN
1829 144 : deb(:) = force(1)%overlap_admm(:, 1) - deb
1830 36 : CALL para_env%sum(deb)
1831 36 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*KADMM*dS'", deb
1832 36 : IF (use_virial) THEN
1833 12 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1834 12 : CALL para_env%sum(e_dummy)
1835 12 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: KADMM*S' ", e_dummy
1836 : END IF
1837 : END IF
1838 :
1839 162 : ALLOCATE (matrix_ks_aux(nspins))
1840 90 : DO ispin = 1, nspins
1841 54 : NULLIFY (matrix_ks_aux(ispin)%matrix)
1842 54 : ALLOCATE (matrix_ks_aux(ispin)%matrix)
1843 54 : CALL dbcsr_copy(matrix_ks_aux(ispin)%matrix, p_env%kpp1_admm(ispin)%matrix)
1844 90 : CALL dbcsr_set(matrix_ks_aux(ispin)%matrix, 0.0_dp)
1845 : END DO
1846 :
1847 : ! Calculate kernel
1848 36 : CALL tddft_hfx_matrix(matrix_ks_aux, rho_ao_aux, qs_env, .FALSE.)
1849 :
1850 36 : IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1851 24 : CALL get_qs_env(qs_env, ks_env=ks_env)
1852 24 : CALL get_admm_env(qs_env%admm_env, task_list_aux_fit=task_list_aux_fit)
1853 :
1854 60 : DO ispin = 1, nspins
1855 60 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
1856 : END DO
1857 :
1858 24 : IF (use_virial) THEN
1859 8 : CALL qs_rho_get(p_env%rho1_admm, rho_r=rho_mp2_r_aux)
1860 8 : e_xc = 0.0_dp
1861 20 : DO ispin = 1, nspins
1862 20 : e_xc = e_xc + pw_integral_ab(rho_mp2_r_aux(ispin), vadmm_rspace(ispin))
1863 : END DO
1864 :
1865 8 : e_xc = -e_xc/vadmm_rspace(1)%pw_grid%dvol/REAL(para_env%num_pe, dp)
1866 :
1867 : ! Update the virial
1868 32 : DO alpha = 1, 3
1869 24 : virial%pv_exc(alpha, alpha) = virial%pv_exc(alpha, alpha) + e_xc
1870 32 : virial%pv_virial(alpha, alpha) = virial%pv_virial(alpha, alpha) + e_xc
1871 : END DO
1872 : IF (debug_forces) THEN
1873 8 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: P1*VADMM ", e_xc
1874 : END IF
1875 : END IF
1876 :
1877 120 : IF (use_virial) h_stress = virial%pv_virial
1878 : IF (debug_forces) THEN
1879 96 : deb = force(1)%rho_elec(1:3, 1)
1880 24 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1881 : END IF
1882 60 : DO ispin = 1, nspins
1883 36 : IF (do_exx) THEN
1884 : CALL integrate_v_rspace(v_rspace=vadmm_rspace(ispin), hmat=matrix_ks_aux(ispin), qs_env=qs_env, &
1885 : calculate_forces=.TRUE., basis_type="AUX_FIT", &
1886 0 : task_list_external=task_list_aux_fit, pmat=matrix_p_mp2_admm(ispin))
1887 : ELSE
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 36 : task_list_external=task_list_aux_fit, pmat=rho_ao_aux(ispin))
1891 : END IF
1892 60 : CALL auxbas_pw_pool%give_back_pw(vadmm_rspace(ispin))
1893 : END DO
1894 120 : IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - h_stress)
1895 24 : DEALLOCATE (vadmm_rspace)
1896 : IF (debug_forces) THEN
1897 96 : deb(:) = force(1)%rho_elec(:, 1) - deb
1898 24 : CALL para_env%sum(deb)
1899 24 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*VADMM' ", deb
1900 24 : IF (use_virial) THEN
1901 8 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1902 8 : CALL para_env%sum(e_dummy)
1903 8 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: VADMM' ", e_dummy
1904 : END IF
1905 : END IF
1906 :
1907 60 : DO ispin = 1, nspins
1908 60 : CALL dbcsr_add(rho_ao_aux(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
1909 : END DO
1910 :
1911 : END IF
1912 :
1913 90 : DO ispin = 1, nspins
1914 90 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, 1.0_dp)
1915 : END DO
1916 :
1917 : IF (debug_forces) THEN
1918 144 : deb = force(1)%overlap_admm(1:3, 1)
1919 36 : IF (use_virial) e_dummy = third_tr(virial%pv_virial)
1920 : END IF
1921 : ! Add the second half of the projector deriatives contracting the first order density matrix with the fockian in the auxiliary basis
1922 36 : IF (do_exx) THEN
1923 0 : CALL admm_projection_derivative(qs_env, matrix_ks_aux, matrix_p_mp2)
1924 : ELSE
1925 36 : CALL admm_projection_derivative(qs_env, matrix_ks_aux, rho_ao)
1926 : END IF
1927 : IF (debug_forces) THEN
1928 144 : deb(:) = force(1)%overlap_admm(:, 1) - deb
1929 36 : CALL para_env%sum(deb)
1930 36 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: P*VADMM*dS'", deb
1931 36 : IF (use_virial) THEN
1932 12 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1933 12 : CALL para_env%sum(e_dummy)
1934 12 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: VADMM*S' ", e_dummy
1935 : END IF
1936 : END IF
1937 :
1938 90 : DO ispin = 1, nspins
1939 90 : CALL dbcsr_add(rho_ao(ispin)%matrix, p_env%p1(ispin)%matrix, 1.0_dp, -1.0_dp)
1940 : END DO
1941 :
1942 90 : DO ispin = 1, nspins
1943 54 : CALL dbcsr_release(matrix_ks_aux(ispin)%matrix)
1944 90 : DEALLOCATE (matrix_ks_aux(ispin)%matrix)
1945 : END DO
1946 36 : DEALLOCATE (matrix_ks_aux)
1947 : END IF
1948 : END IF
1949 :
1950 264 : CALL dbcsr_scale(p_env%w1(1)%matrix, -1.0_dp)
1951 :
1952 : ! Finish matrix_w_mp2 with occ-occ block
1953 614 : DO ispin = 1, nspins
1954 350 : CALL get_mo_set(mo_set=mos(ispin), homo=nocc, nmo=alpha)
1955 : CALL calculate_whz_matrix(mos(ispin)%mo_coeff, p_env%kpp1(ispin)%matrix, &
1956 614 : p_env%w1(1)%matrix, 1.0_dp, nocc)
1957 : END DO
1958 :
1959 264 : IF (debug_forces .AND. use_virial) e_dummy = third_tr(virial%pv_virial)
1960 :
1961 264 : NULLIFY (scrm)
1962 : CALL build_overlap_matrix(ks_env, matrix_s=scrm, &
1963 : matrix_name="OVERLAP MATRIX", &
1964 : basis_type_a="ORB", basis_type_b="ORB", &
1965 : sab_nl=sab_orb, calculate_forces=.TRUE., &
1966 264 : matrix_p=p_env%w1(1)%matrix)
1967 264 : CALL dbcsr_deallocate_matrix_set(scrm)
1968 :
1969 : IF (debug_forces) THEN
1970 1056 : deb = force(1)%overlap(1:3, 1)
1971 264 : CALL para_env%sum(deb)
1972 264 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,3F16.8)") "DEBUG:: W*dS ", deb
1973 264 : IF (use_virial) THEN
1974 50 : e_dummy = third_tr(virial%pv_virial) - e_dummy
1975 50 : CALL para_env%sum(e_dummy)
1976 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: S ", e_dummy
1977 : END IF
1978 : END IF
1979 :
1980 264 : CALL auxbas_pw_pool%give_back_pw(pot_r)
1981 264 : CALL auxbas_pw_pool%give_back_pw(pot_g)
1982 264 : CALL auxbas_pw_pool%give_back_pw(rho_tot_g)
1983 :
1984 : ! Release linres stuff
1985 264 : CALL p_env_release(p_env)
1986 264 : DEALLOCATE (p_env)
1987 264 : NULLIFY (qs_env%mp2_env%ri_grad%p_env)
1988 :
1989 264 : CALL sum_qs_force(force, qs_env%mp2_env%ri_grad%mp2_force)
1990 264 : CALL deallocate_qs_force(qs_env%mp2_env%ri_grad%mp2_force)
1991 :
1992 264 : IF (use_virial) THEN
1993 1250 : virial%pv_mp2 = qs_env%mp2_env%ri_grad%mp2_virial
1994 1250 : virial%pv_virial = virial%pv_virial + qs_env%mp2_env%ri_grad%mp2_virial
1995 : IF (debug_forces) THEN
1996 50 : e_dummy = third_tr(virial%pv_mp2)
1997 50 : CALL para_env%sum(e_dummy)
1998 50 : IF (iounit > 0) WRITE (iounit, "(T3,A,T33,F16.8)") "DEBUG VIRIAL:: MP2nonsep ", e_dummy
1999 : END IF
2000 : END IF
2001 : ! Rewind the change from the beginning
2002 264 : IF (use_virial) virial%pv_calculate = .FALSE.
2003 :
2004 : ! Add the dispersion forces and virials
2005 264 : CALL get_qs_env(qs_env, dispersion_env=dispersion_env)
2006 264 : CALL calculate_dispersion_pairpot(qs_env, dispersion_env, e_dummy, .TRUE.)
2007 :
2008 : CALL cp_print_key_finished_output(iounit, logger, input, &
2009 264 : "DFT%XC%WF_CORRELATION%PRINT")
2010 :
2011 264 : CALL timestop(handle)
2012 :
2013 528 : END SUBROUTINE update_mp2_forces
2014 :
2015 : ! **************************************************************************************************
2016 : !> \brief Calculates the third of the trace of a 3x3 matrix, for debugging purposes
2017 : !> \param matrix ...
2018 : !> \return ...
2019 : ! **************************************************************************************************
2020 965 : PURE FUNCTION third_tr(matrix)
2021 : REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN) :: matrix
2022 : REAL(KIND=dp) :: third_tr
2023 :
2024 965 : third_tr = (matrix(1, 1) + matrix(2, 2) + matrix(3, 3))/3.0_dp
2025 :
2026 965 : END FUNCTION third_tr
2027 :
2028 : END MODULE mp2_cphf
|