Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief routines that build the Kohn-Sham matrix (i.e calculate the coulomb
10 : !> and xc parts
11 : !> \par History
12 : !> 05.2002 moved from qs_scf (see there the history) [fawzi]
13 : !> JGH [30.08.02] multi-grid arrays independent from density and potential
14 : !> 10.2002 introduced pools, uses updated rho as input,
15 : !> removed most temporary variables, renamed may vars,
16 : !> began conversion to LSD [fawzi]
17 : !> 10.2004 moved calculate_w_matrix here [Joost VandeVondele]
18 : !> introduced energy derivative wrt MOs [Joost VandeVondele]
19 : !> \author Fawzi Mohamed
20 : ! **************************************************************************************************
21 :
22 : MODULE qs_ks_utils
23 : USE admm_types, ONLY: admm_type,&
24 : get_admm_env
25 : USE atomic_kind_types, ONLY: atomic_kind_type
26 : USE cell_types, ONLY: cell_type
27 : USE cp_control_types, ONLY: dft_control_type
28 : USE cp_dbcsr_api, ONLY: &
29 : dbcsr_add, dbcsr_copy, dbcsr_deallocate_matrix, dbcsr_get_info, dbcsr_init_p, &
30 : dbcsr_multiply, dbcsr_p_type, dbcsr_release_p, dbcsr_scale, dbcsr_set, dbcsr_type
31 : USE cp_dbcsr_contrib, ONLY: dbcsr_dot,&
32 : dbcsr_scale_by_vector
33 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
34 : copy_fm_to_dbcsr,&
35 : cp_dbcsr_plus_fm_fm_t,&
36 : cp_dbcsr_sm_fm_multiply,&
37 : dbcsr_allocate_matrix_set,&
38 : dbcsr_deallocate_matrix_set
39 : USE cp_ddapc, ONLY: cp_ddapc_apply_CD
40 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
41 : cp_fm_struct_release,&
42 : cp_fm_struct_type
43 : USE cp_fm_types, ONLY: cp_fm_create,&
44 : cp_fm_get_info,&
45 : cp_fm_release,&
46 : cp_fm_set_all,&
47 : cp_fm_to_fm,&
48 : cp_fm_type
49 : USE cp_log_handling, ONLY: cp_get_default_logger,&
50 : cp_logger_type,&
51 : cp_to_string
52 : USE cp_output_handling, ONLY: cp_p_file,&
53 : cp_print_key_finished_output,&
54 : cp_print_key_should_output,&
55 : cp_print_key_unit_nr
56 : USE hfx_admm_utils, ONLY: tddft_hfx_matrix
57 : USE hfx_derivatives, ONLY: derivatives_four_center
58 : USE hfx_types, ONLY: hfx_type
59 : USE input_constants, ONLY: &
60 : cdft_alpha_constraint, cdft_beta_constraint, cdft_charge_constraint, &
61 : cdft_magnetization_constraint, do_admm_aux_exch_func_none, do_ppl_grid, sic_ad, sic_eo, &
62 : sic_list_all, sic_list_unpaired, sic_mauri_spz, sic_mauri_us, sic_none
63 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
64 : section_vals_type,&
65 : section_vals_val_get
66 : USE kahan_sum, ONLY: accurate_dot_product,&
67 : accurate_sum
68 : USE kinds, ONLY: default_string_length,&
69 : dp
70 : USE kpoint_types, ONLY: get_kpoint_info,&
71 : kpoint_type
72 : USE lri_environment_methods, ONLY: v_int_ppl_update
73 : USE lri_environment_types, ONLY: lri_density_type,&
74 : lri_environment_type,&
75 : lri_kind_type
76 : USE lri_forces, ONLY: calculate_lri_forces,&
77 : calculate_ri_forces
78 : USE lri_ks_methods, ONLY: calculate_lri_ks_matrix,&
79 : calculate_ri_ks_matrix
80 : USE message_passing, ONLY: mp_para_env_type
81 : USE ps_implicit_types, ONLY: MIXED_BC,&
82 : MIXED_PERIODIC_BC,&
83 : NEUMANN_BC,&
84 : PERIODIC_BC
85 : USE pw_env_types, ONLY: pw_env_get,&
86 : pw_env_type
87 : USE pw_methods, ONLY: pw_axpy,&
88 : pw_copy,&
89 : pw_integral_ab,&
90 : pw_integrate_function,&
91 : pw_scale,&
92 : pw_transfer,&
93 : pw_zero
94 : USE pw_poisson_methods, ONLY: pw_poisson_solve
95 : USE pw_poisson_types, ONLY: pw_poisson_implicit,&
96 : pw_poisson_type
97 : USE pw_pool_types, ONLY: pw_pool_type
98 : USE pw_types, ONLY: pw_c1d_gs_type,&
99 : pw_r3d_rs_type
100 : USE qs_cdft_types, ONLY: cdft_control_type
101 : USE qs_charges_types, ONLY: qs_charges_type
102 : USE qs_collocate_density, ONLY: calculate_rho_elec
103 : USE qs_energy_types, ONLY: qs_energy_type
104 : USE qs_environment_types, ONLY: get_qs_env,&
105 : qs_environment_type
106 : USE qs_force_types, ONLY: qs_force_type
107 : USE qs_integrate_potential, ONLY: integrate_v_rspace,&
108 : integrate_v_rspace_diagonal,&
109 : integrate_v_rspace_one_center
110 : USE qs_kind_types, ONLY: get_qs_kind_set,&
111 : qs_kind_type
112 : USE qs_ks_qmmm_methods, ONLY: qmmm_modify_hartree_pot
113 : USE qs_ks_types, ONLY: get_ks_env,&
114 : qs_ks_env_type
115 : USE qs_mo_types, ONLY: get_mo_set,&
116 : mo_set_type
117 : USE qs_rho_types, ONLY: qs_rho_get,&
118 : qs_rho_type
119 : USE task_list_types, ONLY: task_list_type
120 : USE virial_types, ONLY: virial_type
121 : USE xc, ONLY: xc_exc_calc,&
122 : xc_vxc_pw_create
123 : #include "./base/base_uses.f90"
124 :
125 : IMPLICIT NONE
126 :
127 : PRIVATE
128 :
129 : LOGICAL, PARAMETER :: debug_this_module = .TRUE.
130 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_ks_utils'
131 :
132 : PUBLIC :: low_spin_roks, sic_explicit_orbitals, calc_v_sic_rspace, print_densities, &
133 : print_detailed_energy, compute_matrix_vxc, sum_up_and_integrate, &
134 : calculate_zmp_potential, get_embed_potential_energy
135 :
136 : CONTAINS
137 :
138 : ! **************************************************************************************************
139 : !> \brief do ROKS calculations yielding low spin states
140 : !> \param energy ...
141 : !> \param qs_env ...
142 : !> \param dft_control ...
143 : !> \param do_hfx ...
144 : !> \param just_energy ...
145 : !> \param calculate_forces ...
146 : !> \param auxbas_pw_pool ...
147 : ! **************************************************************************************************
148 110283 : SUBROUTINE low_spin_roks(energy, qs_env, dft_control, do_hfx, just_energy, &
149 : calculate_forces, auxbas_pw_pool)
150 :
151 : TYPE(qs_energy_type), POINTER :: energy
152 : TYPE(qs_environment_type), POINTER :: qs_env
153 : TYPE(dft_control_type), POINTER :: dft_control
154 : LOGICAL, INTENT(IN) :: do_hfx, just_energy, calculate_forces
155 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
156 :
157 : CHARACTER(*), PARAMETER :: routineN = 'low_spin_roks'
158 :
159 : INTEGER :: handle, irep, ispin, iterm, k, k_alpha, &
160 : k_beta, n_rep, Nelectron, Nspin, Nterms
161 110283 : INTEGER, DIMENSION(:), POINTER :: ivec
162 110283 : INTEGER, DIMENSION(:, :, :), POINTER :: occupations
163 : LOGICAL :: compute_virial, in_range, &
164 : uniform_occupation
165 : REAL(KIND=dp) :: ehfx, exc
166 : REAL(KIND=dp), DIMENSION(3, 3) :: virial_xc_tmp
167 110283 : REAL(KIND=dp), DIMENSION(:), POINTER :: energy_scaling, rvec, scaling
168 : TYPE(cell_type), POINTER :: cell
169 110283 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_h, matrix_hfx, matrix_p, mdummy, &
170 110283 : mo_derivs, rho_ao
171 110283 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p2
172 : TYPE(dbcsr_type), POINTER :: dbcsr_deriv, fm_deriv, fm_scaled, &
173 : mo_coeff
174 110283 : TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
175 110283 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
176 : TYPE(mp_para_env_type), POINTER :: para_env
177 110283 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
178 : TYPE(pw_env_type), POINTER :: pw_env
179 : TYPE(pw_pool_type), POINTER :: xc_pw_pool
180 : TYPE(pw_r3d_rs_type) :: work_v_rspace
181 110283 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r, tau, vxc, vxc_tau
182 : TYPE(pw_r3d_rs_type), POINTER :: weights
183 : TYPE(qs_ks_env_type), POINTER :: ks_env
184 : TYPE(qs_rho_type), POINTER :: rho
185 : TYPE(section_vals_type), POINTER :: hfx_section, input, &
186 : low_spin_roks_section, xc_section
187 : TYPE(virial_type), POINTER :: virial
188 :
189 109921 : IF (.NOT. dft_control%low_spin_roks) RETURN
190 :
191 362 : CALL timeset(routineN, handle)
192 :
193 362 : NULLIFY (ks_env, rho_ao)
194 :
195 : ! Test for not compatible options
196 362 : IF (dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc) THEN
197 0 : CALL cp_abort(__LOCATION__, "GAPW/GAPW_XC are not compatible with low spin ROKS method.")
198 : END IF
199 362 : IF (dft_control%do_admm) THEN
200 0 : CALL cp_abort(__LOCATION__, "ADMM not compatible with low spin ROKS method.")
201 : END IF
202 362 : IF (dft_control%do_admm) THEN
203 0 : IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
204 : CALL cp_abort(__LOCATION__, "ADMM with XC correction functional "// &
205 0 : "not compatible with low spin ROKS method.")
206 : END IF
207 : END IF
208 362 : IF (dft_control%qs_control%semi_empirical .OR. dft_control%qs_control%dftb .OR. &
209 : dft_control%qs_control%xtb) THEN
210 0 : CALL cp_abort(__LOCATION__, "SE/xTB/DFTB are not compatible with low spin ROKS method.")
211 : END IF
212 :
213 : CALL get_qs_env(qs_env, &
214 : ks_env=ks_env, &
215 : mo_derivs=mo_derivs, &
216 : mos=mo_array, &
217 : rho=rho, &
218 : pw_env=pw_env, &
219 : xcint_weights=weights, &
220 : input=input, &
221 : cell=cell, &
222 362 : virial=virial)
223 :
224 362 : CALL qs_rho_get(rho, rho_ao=rho_ao)
225 :
226 362 : compute_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
227 362 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
228 362 : hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
229 :
230 : ! No accurate integration possible (as there is no GAPW)
231 362 : IF (ASSOCIATED(weights)) THEN
232 0 : CALL cp_abort(__LOCATION__, "No accurate xc integration possible.")
233 : END IF
234 : ! some assumptions need to be checked
235 : ! we have two spins
236 362 : CPASSERT(SIZE(mo_array, 1) == 2)
237 362 : Nspin = 2
238 : ! we want uniform occupations
239 362 : CALL get_mo_set(mo_set=mo_array(1), uniform_occupation=uniform_occupation)
240 362 : CPASSERT(uniform_occupation)
241 362 : CALL get_mo_set(mo_set=mo_array(2), mo_coeff_b=mo_coeff, uniform_occupation=uniform_occupation)
242 362 : CPASSERT(uniform_occupation)
243 362 : IF (do_hfx .AND. calculate_forces .AND. compute_virial) THEN
244 0 : CALL cp_abort(__LOCATION__, "ROKS virial with HFX not available.")
245 : END IF
246 :
247 362 : NULLIFY (dbcsr_deriv)
248 362 : CALL dbcsr_init_p(dbcsr_deriv)
249 362 : CALL dbcsr_copy(dbcsr_deriv, mo_derivs(1)%matrix)
250 362 : CALL dbcsr_set(dbcsr_deriv, 0.0_dp)
251 :
252 : ! basic info
253 362 : CALL get_mo_set(mo_set=mo_array(1), mo_coeff_b=mo_coeff)
254 362 : CALL dbcsr_get_info(mo_coeff, nfullcols_total=k_alpha)
255 362 : CALL get_mo_set(mo_set=mo_array(2), mo_coeff_b=mo_coeff)
256 362 : CALL dbcsr_get_info(mo_coeff, nfullcols_total=k_beta)
257 :
258 : ! read the input
259 362 : low_spin_roks_section => section_vals_get_subs_vals(input, "DFT%LOW_SPIN_ROKS")
260 :
261 362 : CALL section_vals_val_get(low_spin_roks_section, "ENERGY_SCALING", r_vals=rvec)
262 362 : Nterms = SIZE(rvec)
263 1086 : ALLOCATE (energy_scaling(Nterms))
264 1810 : energy_scaling = rvec !? just wondering, should this add up to 1, in which case we should cpp?
265 :
266 362 : CALL section_vals_val_get(low_spin_roks_section, "SPIN_CONFIGURATION", n_rep_val=n_rep)
267 362 : CPASSERT(n_rep == Nterms)
268 362 : CALL section_vals_val_get(low_spin_roks_section, "SPIN_CONFIGURATION", i_rep_val=1, i_vals=ivec)
269 362 : Nelectron = SIZE(ivec)
270 362 : CPASSERT(Nelectron == k_alpha - k_beta)
271 1448 : ALLOCATE (occupations(2, Nelectron, Nterms))
272 5430 : occupations = 0
273 1086 : DO iterm = 1, Nterms
274 724 : CALL section_vals_val_get(low_spin_roks_section, "SPIN_CONFIGURATION", i_rep_val=iterm, i_vals=ivec)
275 724 : CPASSERT(Nelectron == SIZE(ivec))
276 4344 : in_range = ALL(ivec >= 1) .AND. ALL(ivec <= 2)
277 724 : CPASSERT(in_range)
278 2534 : DO k = 1, Nelectron
279 2172 : occupations(ivec(k), k, iterm) = 1
280 : END DO
281 : END DO
282 :
283 : ! set up general data structures
284 : ! density matrices, kohn-sham matrices
285 :
286 362 : NULLIFY (matrix_p)
287 362 : CALL dbcsr_allocate_matrix_set(matrix_p, Nspin)
288 1086 : DO ispin = 1, Nspin
289 724 : ALLOCATE (matrix_p(ispin)%matrix)
290 : CALL dbcsr_copy(matrix_p(ispin)%matrix, rho_ao(1)%matrix, &
291 724 : name="density matrix low spin roks")
292 1086 : CALL dbcsr_set(matrix_p(ispin)%matrix, 0.0_dp)
293 : END DO
294 :
295 362 : NULLIFY (matrix_h)
296 362 : CALL dbcsr_allocate_matrix_set(matrix_h, Nspin)
297 1086 : DO ispin = 1, Nspin
298 724 : ALLOCATE (matrix_h(ispin)%matrix)
299 : CALL dbcsr_copy(matrix_h(ispin)%matrix, rho_ao(1)%matrix, &
300 724 : name="KS matrix low spin roks")
301 1086 : CALL dbcsr_set(matrix_h(ispin)%matrix, 0.0_dp)
302 : END DO
303 :
304 362 : IF (do_hfx) THEN
305 220 : NULLIFY (matrix_hfx)
306 220 : CALL dbcsr_allocate_matrix_set(matrix_hfx, Nspin)
307 660 : DO ispin = 1, Nspin
308 440 : ALLOCATE (matrix_hfx(ispin)%matrix)
309 : CALL dbcsr_copy(matrix_hfx(ispin)%matrix, rho_ao(1)%matrix, &
310 660 : name="HFX matrix low spin roks")
311 : END DO
312 : END IF
313 :
314 : ! grids in real and g space for rho and vxc
315 : ! tau functionals are not supported
316 362 : NULLIFY (tau, vxc_tau, vxc)
317 362 : CALL pw_env_get(pw_env, xc_pw_pool=xc_pw_pool)
318 :
319 1086 : ALLOCATE (rho_r(Nspin))
320 1086 : ALLOCATE (rho_g(Nspin))
321 1086 : DO ispin = 1, Nspin
322 724 : CALL auxbas_pw_pool%create_pw(rho_r(ispin))
323 1086 : CALL auxbas_pw_pool%create_pw(rho_g(ispin))
324 : END DO
325 362 : CALL auxbas_pw_pool%create_pw(work_v_rspace)
326 :
327 : ! get mo matrices needed to construct the density matrices
328 : ! we will base all on the alpha spin matrix, obviously possible in ROKS
329 362 : CALL get_mo_set(mo_set=mo_array(1), mo_coeff_b=mo_coeff)
330 362 : NULLIFY (fm_scaled, fm_deriv)
331 362 : CALL dbcsr_init_p(fm_scaled)
332 362 : CALL dbcsr_init_p(fm_deriv)
333 362 : CALL dbcsr_copy(fm_scaled, mo_coeff)
334 362 : CALL dbcsr_copy(fm_deriv, mo_coeff)
335 :
336 1086 : ALLOCATE (scaling(k_alpha))
337 :
338 : ! for each term, add it with the given scaling factor to the energy, and compute the required derivatives
339 1086 : DO iterm = 1, Nterms
340 :
341 2172 : DO ispin = 1, Nspin
342 : ! compute the proper density matrices with the required occupations
343 1448 : CALL dbcsr_set(matrix_p(ispin)%matrix, 0.0_dp)
344 11584 : scaling = 1.0_dp
345 4344 : scaling(k_alpha - Nelectron + 1:k_alpha) = occupations(ispin, :, iterm)
346 1448 : CALL dbcsr_copy(fm_scaled, mo_coeff)
347 1448 : CALL dbcsr_scale_by_vector(fm_scaled, scaling, side='right')
348 : CALL dbcsr_multiply('n', 't', 1.0_dp, mo_coeff, fm_scaled, &
349 1448 : 0.0_dp, matrix_p(ispin)%matrix, retain_sparsity=.TRUE.)
350 : ! compute the densities on the grid
351 : CALL calculate_rho_elec(matrix_p=matrix_p(ispin)%matrix, &
352 : rho=rho_r(ispin), rho_gspace=rho_g(ispin), &
353 2172 : ks_env=ks_env)
354 : END DO
355 :
356 : ! compute the exchange energies / potential if needed
357 724 : IF (just_energy) THEN
358 : exc = xc_exc_calc(rho_r=rho_r, rho_g=rho_g, tau=tau, xc_section=xc_section, &
359 88 : weights=weights, pw_pool=xc_pw_pool)
360 : ELSE
361 636 : CPASSERT(.NOT. compute_virial)
362 : CALL xc_vxc_pw_create(vxc_rho=vxc, rho_r=rho_r, &
363 : rho_g=rho_g, tau=tau, vxc_tau=vxc_tau, exc=exc, xc_section=xc_section, &
364 : weights=weights, pw_pool=xc_pw_pool, &
365 636 : compute_virial=.FALSE., virial_xc=virial_xc_tmp)
366 : END IF
367 :
368 724 : energy%exc = energy%exc + energy_scaling(iterm)*exc
369 :
370 724 : IF (do_hfx) THEN
371 : ! Add Hartree-Fock contribution
372 1320 : DO ispin = 1, Nspin
373 1320 : CALL dbcsr_set(matrix_hfx(ispin)%matrix, 0.0_dp)
374 : END DO
375 440 : ehfx = energy%ex
376 : CALL tddft_hfx_matrix(matrix_hfx, matrix_p, qs_env, &
377 440 : recalc_integrals=.FALSE., update_energy=.TRUE.)
378 440 : energy%ex = ehfx + energy_scaling(iterm)*energy%ex
379 : END IF
380 :
381 : ! add the corresponding derivatives to the MO derivatives
382 1086 : IF (.NOT. just_energy) THEN
383 : ! get the potential in matrix form
384 1908 : DO ispin = 1, Nspin
385 1272 : CALL dbcsr_set(matrix_h(ispin)%matrix, 0.0_dp)
386 : ! use a work_v_rspace
387 1272 : CALL pw_axpy(vxc(ispin), work_v_rspace, energy_scaling(iterm)*vxc(ispin)%pw_grid%dvol, 0.0_dp)
388 : CALL integrate_v_rspace(v_rspace=work_v_rspace, pmat=matrix_p(ispin), hmat=matrix_h(ispin), &
389 1272 : qs_env=qs_env, calculate_forces=calculate_forces)
390 1908 : CALL auxbas_pw_pool%give_back_pw(vxc(ispin))
391 : END DO
392 636 : DEALLOCATE (vxc)
393 :
394 636 : IF (do_hfx) THEN
395 : ! add HFX contribution
396 1104 : DO ispin = 1, Nspin
397 : CALL dbcsr_add(matrix_h(ispin)%matrix, matrix_hfx(ispin)%matrix, &
398 1104 : 1.0_dp, energy_scaling(iterm))
399 : END DO
400 368 : IF (calculate_forces) THEN
401 8 : CALL get_qs_env(qs_env, x_data=x_data, para_env=para_env)
402 8 : IF (x_data(1, 1)%n_rep_hf /= 1) THEN
403 : CALL cp_abort(__LOCATION__, "Multiple HFX section forces not compatible "// &
404 0 : "with low spin ROKS method.")
405 : END IF
406 8 : IF (x_data(1, 1)%do_hfx_ri) THEN
407 0 : CALL cp_abort(__LOCATION__, "HFX_RI forces not compatible with low spin ROKS method.")
408 : ELSE
409 8 : irep = 1
410 8 : NULLIFY (mdummy)
411 8 : matrix_p2(1:Nspin, 1:1) => matrix_p(1:Nspin)
412 : CALL derivatives_four_center(qs_env, matrix_p2, mdummy, hfx_section, para_env, &
413 : irep, compute_virial, &
414 8 : adiabatic_rescale_factor=energy_scaling(iterm))
415 : END IF
416 : END IF
417 :
418 : END IF
419 :
420 : ! add this to the mo_derivs, again based on the alpha mo_coeff
421 1908 : DO ispin = 1, Nspin
422 : CALL dbcsr_multiply('n', 'n', 1.0_dp, matrix_h(ispin)%matrix, mo_coeff, &
423 1272 : 0.0_dp, dbcsr_deriv, last_column=k_alpha)
424 :
425 10176 : scaling = 1.0_dp
426 3816 : scaling(k_alpha - Nelectron + 1:k_alpha) = occupations(ispin, :, iterm)
427 1272 : CALL dbcsr_scale_by_vector(dbcsr_deriv, scaling, side='right')
428 1908 : CALL dbcsr_add(mo_derivs(1)%matrix, dbcsr_deriv, 1.0_dp, 1.0_dp)
429 : END DO
430 :
431 : END IF
432 :
433 : END DO
434 :
435 : ! release allocated memory
436 1086 : DO ispin = 1, Nspin
437 724 : CALL auxbas_pw_pool%give_back_pw(rho_r(ispin))
438 1086 : CALL auxbas_pw_pool%give_back_pw(rho_g(ispin))
439 : END DO
440 362 : DEALLOCATE (rho_r, rho_g)
441 362 : CALL dbcsr_deallocate_matrix_set(matrix_p)
442 362 : CALL dbcsr_deallocate_matrix_set(matrix_h)
443 362 : IF (do_hfx) THEN
444 220 : CALL dbcsr_deallocate_matrix_set(matrix_hfx)
445 : END IF
446 :
447 362 : CALL auxbas_pw_pool%give_back_pw(work_v_rspace)
448 :
449 362 : CALL dbcsr_release_p(fm_deriv)
450 362 : CALL dbcsr_release_p(fm_scaled)
451 :
452 362 : DEALLOCATE (occupations)
453 362 : DEALLOCATE (energy_scaling)
454 362 : DEALLOCATE (scaling)
455 :
456 362 : CALL dbcsr_release_p(dbcsr_deriv)
457 :
458 362 : CALL timestop(handle)
459 :
460 112093 : END SUBROUTINE low_spin_roks
461 : ! **************************************************************************************************
462 : !> \brief do sic calculations on explicit orbitals
463 : !> \param energy ...
464 : !> \param qs_env ...
465 : !> \param dft_control ...
466 : !> \param poisson_env ...
467 : !> \param just_energy ...
468 : !> \param calculate_forces ...
469 : !> \param auxbas_pw_pool ...
470 : ! **************************************************************************************************
471 110283 : SUBROUTINE sic_explicit_orbitals(energy, qs_env, dft_control, poisson_env, just_energy, &
472 : calculate_forces, auxbas_pw_pool)
473 :
474 : TYPE(qs_energy_type), POINTER :: energy
475 : TYPE(qs_environment_type), POINTER :: qs_env
476 : TYPE(dft_control_type), POINTER :: dft_control
477 : TYPE(pw_poisson_type), POINTER :: poisson_env
478 : LOGICAL, INTENT(IN) :: just_energy, calculate_forces
479 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
480 :
481 : CHARACTER(*), PARAMETER :: routineN = 'sic_explicit_orbitals'
482 :
483 : INTEGER :: handle, i, Iorb, k_alpha, k_beta, Norb
484 110283 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: sic_orbital_list
485 : LOGICAL :: compute_virial, uniform_occupation
486 : REAL(KIND=dp) :: ener, exc
487 : REAL(KIND=dp), DIMENSION(3, 3) :: virial_xc_tmp
488 : TYPE(cell_type), POINTER :: cell
489 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
490 : TYPE(cp_fm_type) :: matrix_hv, matrix_v
491 110283 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: mo_derivs_local
492 : TYPE(cp_fm_type), POINTER :: mo_coeff
493 : TYPE(dbcsr_p_type) :: orb_density_matrix_p, orb_h_p
494 110283 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mo_derivs, rho_ao, tmp_dbcsr
495 : TYPE(dbcsr_type), POINTER :: orb_density_matrix, orb_h
496 110283 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
497 : TYPE(pw_c1d_gs_type) :: work_v_gspace
498 110283 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
499 : TYPE(pw_c1d_gs_type), TARGET :: orb_rho_g, tmp_g
500 : TYPE(pw_env_type), POINTER :: pw_env
501 : TYPE(pw_pool_type), POINTER :: xc_pw_pool
502 : TYPE(pw_r3d_rs_type) :: work_v_rspace
503 110283 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r, tau, vxc, vxc_tau
504 : TYPE(pw_r3d_rs_type), POINTER :: weights
505 : TYPE(pw_r3d_rs_type), TARGET :: orb_rho_r, tmp_r
506 : TYPE(qs_ks_env_type), POINTER :: ks_env
507 : TYPE(qs_rho_type), POINTER :: rho
508 : TYPE(section_vals_type), POINTER :: input, xc_section
509 : TYPE(virial_type), POINTER :: virial
510 :
511 110283 : IF (dft_control%sic_method_id /= sic_eo) RETURN
512 :
513 40 : CALL timeset(routineN, handle)
514 :
515 40 : NULLIFY (tau, vxc_tau, mo_derivs, ks_env, rho_ao)
516 :
517 : ! generate the lists of orbitals that need sic treatment
518 : CALL get_qs_env(qs_env, &
519 : ks_env=ks_env, &
520 : mo_derivs=mo_derivs, &
521 : mos=mo_array, &
522 : rho=rho, &
523 : xcint_weights=weights, &
524 : pw_env=pw_env, &
525 : input=input, &
526 : cell=cell, &
527 40 : virial=virial)
528 :
529 40 : CALL qs_rho_get(rho, rho_ao=rho_ao)
530 :
531 40 : compute_virial = virial%pv_calculate .AND. (.NOT. virial%pv_numer)
532 40 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
533 :
534 120 : DO i = 1, SIZE(mo_array) !fm->dbcsr
535 120 : IF (mo_array(i)%use_mo_coeff_b) THEN !fm->dbcsr
536 : CALL copy_dbcsr_to_fm(mo_array(i)%mo_coeff_b, &
537 80 : mo_array(i)%mo_coeff) !fm->dbcsr
538 : END IF !fm->dbcsr
539 : END DO !fm->dbcsr
540 :
541 40 : CALL pw_env_get(pw_env, xc_pw_pool=xc_pw_pool)
542 :
543 : ! we have two spins
544 40 : CPASSERT(SIZE(mo_array, 1) == 2)
545 : ! we want uniform occupations
546 40 : CALL get_mo_set(mo_set=mo_array(1), uniform_occupation=uniform_occupation)
547 40 : CPASSERT(uniform_occupation)
548 40 : CALL get_mo_set(mo_set=mo_array(2), mo_coeff=mo_coeff, uniform_occupation=uniform_occupation)
549 40 : CPASSERT(uniform_occupation)
550 :
551 40 : NULLIFY (tmp_dbcsr)
552 40 : CALL dbcsr_allocate_matrix_set(tmp_dbcsr, SIZE(mo_derivs, 1))
553 100 : DO i = 1, SIZE(mo_derivs, 1) !fm->dbcsr
554 : !
555 60 : NULLIFY (tmp_dbcsr(i)%matrix)
556 60 : CALL dbcsr_init_p(tmp_dbcsr(i)%matrix)
557 60 : CALL dbcsr_copy(tmp_dbcsr(i)%matrix, mo_derivs(i)%matrix)
558 100 : CALL dbcsr_set(tmp_dbcsr(i)%matrix, 0.0_dp)
559 : END DO !fm->dbcsr
560 :
561 40 : k_alpha = 0; k_beta = 0
562 60 : SELECT CASE (dft_control%sic_list_id)
563 : CASE (sic_list_all)
564 :
565 20 : CALL get_mo_set(mo_set=mo_array(1), mo_coeff=mo_coeff)
566 20 : CALL cp_fm_get_info(mo_coeff, ncol_global=k_alpha)
567 :
568 20 : IF (SIZE(mo_array, 1) > 1) THEN
569 20 : CALL get_mo_set(mo_set=mo_array(2), mo_coeff=mo_coeff)
570 20 : CALL cp_fm_get_info(mo_coeff, ncol_global=k_beta)
571 : END IF
572 :
573 20 : Norb = k_alpha + k_beta
574 60 : ALLOCATE (sic_orbital_list(3, Norb))
575 :
576 80 : iorb = 0
577 80 : DO i = 1, k_alpha
578 60 : iorb = iorb + 1
579 60 : sic_orbital_list(1, iorb) = 1
580 60 : sic_orbital_list(2, iorb) = i
581 80 : sic_orbital_list(3, iorb) = 1
582 : END DO
583 60 : DO i = 1, k_beta
584 20 : iorb = iorb + 1
585 20 : sic_orbital_list(1, iorb) = 2
586 20 : sic_orbital_list(2, iorb) = i
587 40 : IF (SIZE(mo_derivs, 1) == 1) THEN
588 0 : sic_orbital_list(3, iorb) = 1
589 : ELSE
590 20 : sic_orbital_list(3, iorb) = 2
591 : END IF
592 : END DO
593 :
594 : CASE (sic_list_unpaired)
595 : ! we have two spins
596 20 : CPASSERT(SIZE(mo_array, 1) == 2)
597 : ! we have them restricted
598 20 : CPASSERT(SIZE(mo_derivs, 1) == 1)
599 20 : CPASSERT(dft_control%restricted)
600 :
601 20 : CALL get_mo_set(mo_set=mo_array(1), mo_coeff=mo_coeff)
602 20 : CALL cp_fm_get_info(mo_coeff, ncol_global=k_alpha)
603 :
604 20 : CALL get_mo_set(mo_set=mo_array(2), mo_coeff=mo_coeff)
605 20 : CALL cp_fm_get_info(mo_coeff, ncol_global=k_beta)
606 :
607 20 : Norb = k_alpha - k_beta
608 60 : ALLOCATE (sic_orbital_list(3, Norb))
609 :
610 20 : iorb = 0
611 100 : DO i = k_beta + 1, k_alpha
612 40 : iorb = iorb + 1
613 40 : sic_orbital_list(1, iorb) = 1
614 40 : sic_orbital_list(2, iorb) = i
615 : ! we are guaranteed to be restricted
616 60 : sic_orbital_list(3, iorb) = 1
617 : END DO
618 :
619 : CASE DEFAULT
620 40 : CPABORT("")
621 : END SELECT
622 :
623 : ! data needed for each of the orbs
624 40 : CALL auxbas_pw_pool%create_pw(orb_rho_r)
625 40 : CALL auxbas_pw_pool%create_pw(tmp_r)
626 40 : CALL auxbas_pw_pool%create_pw(orb_rho_g)
627 40 : CALL auxbas_pw_pool%create_pw(tmp_g)
628 40 : CALL auxbas_pw_pool%create_pw(work_v_gspace)
629 40 : CALL auxbas_pw_pool%create_pw(work_v_rspace)
630 :
631 40 : ALLOCATE (orb_density_matrix)
632 : CALL dbcsr_copy(orb_density_matrix, rho_ao(1)%matrix, &
633 40 : name="orb_density_matrix")
634 40 : CALL dbcsr_set(orb_density_matrix, 0.0_dp)
635 40 : orb_density_matrix_p%matrix => orb_density_matrix
636 :
637 40 : ALLOCATE (orb_h)
638 : CALL dbcsr_copy(orb_h, rho_ao(1)%matrix, &
639 40 : name="orb_density_matrix")
640 40 : CALL dbcsr_set(orb_h, 0.0_dp)
641 40 : orb_h_p%matrix => orb_h
642 :
643 40 : CALL get_mo_set(mo_set=mo_array(1), mo_coeff=mo_coeff)
644 :
645 : CALL cp_fm_struct_create(fm_struct_tmp, ncol_global=1, &
646 40 : template_fmstruct=mo_coeff%matrix_struct)
647 40 : CALL cp_fm_create(matrix_v, fm_struct_tmp, name="matrix_v")
648 40 : CALL cp_fm_create(matrix_hv, fm_struct_tmp, name="matrix_hv")
649 40 : CALL cp_fm_struct_release(fm_struct_tmp)
650 :
651 200 : ALLOCATE (mo_derivs_local(SIZE(mo_array, 1)))
652 120 : DO I = 1, SIZE(mo_array, 1)
653 80 : CALL get_mo_set(mo_set=mo_array(i), mo_coeff=mo_coeff)
654 120 : CALL cp_fm_create(mo_derivs_local(I), mo_coeff%matrix_struct)
655 : END DO
656 :
657 120 : ALLOCATE (rho_r(2))
658 40 : rho_r(1) = orb_rho_r
659 40 : rho_r(2) = tmp_r
660 40 : CALL pw_zero(tmp_r)
661 :
662 120 : ALLOCATE (rho_g(2))
663 40 : rho_g(1) = orb_rho_g
664 40 : rho_g(2) = tmp_g
665 40 : CALL pw_zero(tmp_g)
666 :
667 40 : NULLIFY (vxc)
668 : ! now apply to SIC correction to each selected orbital
669 160 : DO iorb = 1, Norb
670 : ! extract the proper orbital from the mo_coeff
671 120 : CALL get_mo_set(mo_set=mo_array(sic_orbital_list(1, iorb)), mo_coeff=mo_coeff)
672 120 : CALL cp_fm_to_fm(mo_coeff, matrix_v, 1, sic_orbital_list(2, iorb), 1)
673 :
674 : ! construct the density matrix and the corresponding density
675 120 : CALL dbcsr_set(orb_density_matrix, 0.0_dp)
676 : CALL cp_dbcsr_plus_fm_fm_t(orb_density_matrix, matrix_v=matrix_v, ncol=1, &
677 120 : alpha=1.0_dp)
678 :
679 : CALL calculate_rho_elec(matrix_p=orb_density_matrix, &
680 : rho=orb_rho_r, rho_gspace=orb_rho_g, &
681 120 : ks_env=ks_env)
682 :
683 : ! compute the energy functional for this orbital and its derivative
684 :
685 120 : CALL pw_poisson_solve(poisson_env, orb_rho_g, ener, work_v_gspace)
686 : ! no PBC correction is done here, see "calc_v_sic_rspace" for SIC methods
687 : ! with PBC aware corrections
688 120 : energy%hartree = energy%hartree - dft_control%sic_scaling_a*ener
689 120 : IF (.NOT. just_energy) THEN
690 72 : CALL pw_transfer(work_v_gspace, work_v_rspace)
691 72 : CALL pw_scale(work_v_rspace, -dft_control%sic_scaling_a*work_v_rspace%pw_grid%dvol)
692 72 : CALL dbcsr_set(orb_h, 0.0_dp)
693 : END IF
694 :
695 120 : IF (just_energy) THEN
696 : exc = xc_exc_calc(rho_r=rho_r, rho_g=rho_g, tau=tau, xc_section=xc_section, &
697 48 : weights=weights, pw_pool=xc_pw_pool)
698 : ELSE
699 72 : CPASSERT(.NOT. compute_virial)
700 : CALL xc_vxc_pw_create(vxc_rho=vxc, rho_r=rho_r, &
701 : rho_g=rho_g, tau=tau, vxc_tau=vxc_tau, exc=exc, xc_section=xc_section, &
702 : weights=weights, pw_pool=xc_pw_pool, &
703 72 : compute_virial=compute_virial, virial_xc=virial_xc_tmp)
704 : ! add to the existing work_v_rspace
705 72 : CALL pw_axpy(vxc(1), work_v_rspace, -dft_control%sic_scaling_b*vxc(1)%pw_grid%dvol)
706 : END IF
707 120 : energy%exc = energy%exc - dft_control%sic_scaling_b*exc
708 :
709 280 : IF (.NOT. just_energy) THEN
710 : ! note, orb_h (which is being pointed to with orb_h_p) is zeroed above
711 : CALL integrate_v_rspace(v_rspace=work_v_rspace, pmat=orb_density_matrix_p, hmat=orb_h_p, &
712 72 : qs_env=qs_env, calculate_forces=calculate_forces)
713 :
714 : ! add this to the mo_derivs
715 72 : CALL cp_dbcsr_sm_fm_multiply(orb_h, matrix_v, matrix_hv, 1)
716 : ! silly trick, copy to an array of the right size and add to mo_derivs
717 72 : CALL cp_fm_set_all(mo_derivs_local(sic_orbital_list(3, iorb)), 0.0_dp)
718 72 : CALL cp_fm_to_fm(matrix_hv, mo_derivs_local(sic_orbital_list(3, iorb)), 1, 1, sic_orbital_list(2, iorb))
719 : CALL copy_fm_to_dbcsr(mo_derivs_local(sic_orbital_list(3, iorb)), &
720 72 : tmp_dbcsr(sic_orbital_list(3, iorb))%matrix)
721 : CALL dbcsr_add(mo_derivs(sic_orbital_list(3, iorb))%matrix, &
722 72 : tmp_dbcsr(sic_orbital_list(3, iorb))%matrix, 1.0_dp, 1.0_dp)
723 : !
724 : ! need to deallocate vxc
725 72 : CALL xc_pw_pool%give_back_pw(vxc(1))
726 72 : CALL xc_pw_pool%give_back_pw(vxc(2))
727 72 : DEALLOCATE (vxc)
728 :
729 : END IF
730 :
731 : END DO
732 :
733 40 : CALL auxbas_pw_pool%give_back_pw(orb_rho_r)
734 40 : CALL auxbas_pw_pool%give_back_pw(tmp_r)
735 40 : CALL auxbas_pw_pool%give_back_pw(orb_rho_g)
736 40 : CALL auxbas_pw_pool%give_back_pw(tmp_g)
737 40 : CALL auxbas_pw_pool%give_back_pw(work_v_gspace)
738 40 : CALL auxbas_pw_pool%give_back_pw(work_v_rspace)
739 :
740 40 : CALL dbcsr_deallocate_matrix(orb_density_matrix)
741 40 : CALL dbcsr_deallocate_matrix(orb_h)
742 40 : CALL cp_fm_release(matrix_v)
743 40 : CALL cp_fm_release(matrix_hv)
744 40 : CALL cp_fm_release(mo_derivs_local)
745 40 : DEALLOCATE (rho_r)
746 40 : DEALLOCATE (rho_g)
747 :
748 40 : CALL dbcsr_deallocate_matrix_set(tmp_dbcsr) !fm->dbcsr
749 :
750 40 : CALL timestop(handle)
751 :
752 110443 : END SUBROUTINE sic_explicit_orbitals
753 :
754 : ! **************************************************************************************************
755 : !> \brief do sic calculations on the spin density
756 : !> \param v_sic_rspace ...
757 : !> \param energy ...
758 : !> \param qs_env ...
759 : !> \param dft_control ...
760 : !> \param rho ...
761 : !> \param poisson_env ...
762 : !> \param just_energy ...
763 : !> \param calculate_forces ...
764 : !> \param auxbas_pw_pool ...
765 : ! **************************************************************************************************
766 110283 : SUBROUTINE calc_v_sic_rspace(v_sic_rspace, energy, &
767 : qs_env, dft_control, rho, poisson_env, just_energy, &
768 : calculate_forces, auxbas_pw_pool)
769 :
770 : TYPE(pw_r3d_rs_type), POINTER :: v_sic_rspace
771 : TYPE(qs_energy_type), POINTER :: energy
772 : TYPE(qs_environment_type), POINTER :: qs_env
773 : TYPE(dft_control_type), POINTER :: dft_control
774 : TYPE(qs_rho_type), POINTER :: rho
775 : TYPE(pw_poisson_type), POINTER :: poisson_env
776 : LOGICAL, INTENT(IN) :: just_energy, calculate_forces
777 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
778 :
779 : INTEGER :: i, nelec, nelec_a, nelec_b, nforce
780 : REAL(kind=dp) :: ener, full_scaling, scaling
781 110283 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: store_forces
782 110283 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
783 : TYPE(pw_c1d_gs_type) :: work_rho, work_v
784 110283 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
785 110283 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
786 :
787 110283 : NULLIFY (mo_array, rho_g)
788 :
789 110283 : IF (dft_control%sic_method_id == sic_none) RETURN
790 336 : IF (dft_control%sic_method_id == sic_eo) RETURN
791 :
792 296 : IF (dft_control%qs_control%gapw) &
793 0 : CPABORT("sic and GAPW not yet compatible")
794 :
795 : ! OK, right now we like two spins to do sic, could be relaxed for AD
796 296 : CPASSERT(dft_control%nspins == 2)
797 :
798 296 : CALL auxbas_pw_pool%create_pw(work_rho)
799 296 : CALL auxbas_pw_pool%create_pw(work_v)
800 :
801 296 : CALL qs_rho_get(rho, rho_g=rho_g)
802 :
803 : ! Hartree sic corrections
804 566 : SELECT CASE (dft_control%sic_method_id)
805 : CASE (sic_mauri_us, sic_mauri_spz)
806 270 : CALL pw_copy(rho_g(1), work_rho)
807 270 : CALL pw_axpy(rho_g(2), work_rho, alpha=-1._dp)
808 296 : CALL pw_poisson_solve(poisson_env, work_rho, ener, work_v)
809 : CASE (sic_ad)
810 : ! find out how many elecs we have
811 26 : CALL get_qs_env(qs_env, mos=mo_array)
812 26 : CALL get_mo_set(mo_set=mo_array(1), nelectron=nelec_a)
813 26 : CALL get_mo_set(mo_set=mo_array(2), nelectron=nelec_b)
814 26 : nelec = nelec_a + nelec_b
815 26 : CALL pw_copy(rho_g(1), work_rho)
816 26 : CALL pw_axpy(rho_g(2), work_rho)
817 26 : scaling = 1.0_dp/REAL(nelec, KIND=dp)
818 26 : CALL pw_scale(work_rho, scaling)
819 26 : CALL pw_poisson_solve(poisson_env, work_rho, ener, work_v)
820 : CASE DEFAULT
821 618 : CPABORT("Unknown sic method id")
822 : END SELECT
823 :
824 : ! Correct for DDAP charges (if any)
825 : ! storing whatever force might be there from previous decoupling
826 296 : IF (calculate_forces) THEN
827 48 : CALL get_qs_env(qs_env=qs_env, force=force)
828 48 : nforce = 0
829 112 : DO i = 1, SIZE(force)
830 112 : nforce = nforce + SIZE(force(i)%ch_pulay, 2)
831 : END DO
832 144 : ALLOCATE (store_forces(3, nforce))
833 112 : nforce = 0
834 112 : DO i = 1, SIZE(force)
835 784 : store_forces(1:3, nforce + 1:nforce + SIZE(force(i)%ch_pulay, 2)) = force(i)%ch_pulay(:, :)
836 784 : force(i)%ch_pulay(:, :) = 0.0_dp
837 112 : nforce = nforce + SIZE(force(i)%ch_pulay, 2)
838 : END DO
839 : END IF
840 :
841 : CALL cp_ddapc_apply_CD(qs_env, &
842 : work_rho, &
843 : ener, &
844 : v_hartree_gspace=work_v, &
845 : calculate_forces=calculate_forces, &
846 296 : Itype_of_density="SPIN")
847 :
848 566 : SELECT CASE (dft_control%sic_method_id)
849 : CASE (sic_mauri_us, sic_mauri_spz)
850 270 : full_scaling = -dft_control%sic_scaling_a
851 : CASE (sic_ad)
852 26 : full_scaling = -dft_control%sic_scaling_a*nelec
853 : CASE DEFAULT
854 296 : CPABORT("Unknown sic method id")
855 : END SELECT
856 296 : energy%hartree = energy%hartree + full_scaling*ener
857 :
858 : ! add scaled forces, restoring the old
859 296 : IF (calculate_forces) THEN
860 48 : nforce = 0
861 112 : DO i = 1, SIZE(force)
862 : force(i)%ch_pulay(:, :) = force(i)%ch_pulay(:, :)*full_scaling + &
863 784 : store_forces(1:3, nforce + 1:nforce + SIZE(force(i)%ch_pulay, 2))
864 112 : nforce = nforce + SIZE(force(i)%ch_pulay, 2)
865 : END DO
866 : END IF
867 :
868 296 : IF (.NOT. just_energy) THEN
869 200 : ALLOCATE (v_sic_rspace)
870 200 : CALL auxbas_pw_pool%create_pw(v_sic_rspace)
871 200 : CALL pw_transfer(work_v, v_sic_rspace)
872 : ! also take into account the scaling (in addition to the volume element)
873 : CALL pw_scale(v_sic_rspace, &
874 200 : dft_control%sic_scaling_a*v_sic_rspace%pw_grid%dvol)
875 : END IF
876 :
877 296 : CALL auxbas_pw_pool%give_back_pw(work_rho)
878 296 : CALL auxbas_pw_pool%give_back_pw(work_v)
879 :
880 110579 : END SUBROUTINE calc_v_sic_rspace
881 :
882 : ! **************************************************************************************************
883 : !> \brief ...
884 : !> \param qs_env ...
885 : !> \param rho ...
886 : ! **************************************************************************************************
887 220522 : SUBROUTINE print_densities(qs_env, rho)
888 : TYPE(qs_environment_type), POINTER :: qs_env
889 : TYPE(qs_rho_type), POINTER :: rho
890 :
891 : INTEGER :: img, ispin, n_electrons, output_unit
892 : REAL(dp) :: tot1_h, tot1_s, tot_rho_r, trace, &
893 : trace_tmp
894 110261 : REAL(KIND=dp), DIMENSION(:), POINTER :: tot_rho_r_arr
895 : TYPE(cell_type), POINTER :: cell
896 : TYPE(cp_logger_type), POINTER :: logger
897 110261 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s, rho_ao
898 : TYPE(dft_control_type), POINTER :: dft_control
899 : TYPE(qs_charges_type), POINTER :: qs_charges
900 110261 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
901 : TYPE(section_vals_type), POINTER :: input, scf_section
902 :
903 110261 : NULLIFY (qs_charges, qs_kind_set, cell, input, logger, scf_section, matrix_s, &
904 110261 : dft_control, tot_rho_r_arr, rho_ao)
905 :
906 220522 : logger => cp_get_default_logger()
907 :
908 : CALL get_qs_env(qs_env, &
909 : qs_kind_set=qs_kind_set, &
910 : cell=cell, qs_charges=qs_charges, &
911 : input=input, &
912 : matrix_s_kp=matrix_s, &
913 110261 : dft_control=dft_control)
914 :
915 110261 : CALL get_qs_kind_set(qs_kind_set, nelectron=n_electrons)
916 :
917 110261 : scf_section => section_vals_get_subs_vals(input, "DFT%SCF")
918 : output_unit = cp_print_key_unit_nr(logger, scf_section, "PRINT%TOTAL_DENSITIES", &
919 110261 : extension=".scfLog")
920 :
921 110261 : CALL qs_rho_get(rho, tot_rho_r=tot_rho_r_arr, rho_ao_kp=rho_ao)
922 110261 : n_electrons = n_electrons - dft_control%charge
923 110261 : tot_rho_r = accurate_sum(tot_rho_r_arr)
924 :
925 110261 : trace = 0
926 110261 : IF (BTEST(cp_print_key_should_output(logger%iter_info, scf_section, "PRINT%TOTAL_DENSITIES"), cp_p_file)) THEN
927 4138 : DO ispin = 1, dft_control%nspins
928 6740 : DO img = 1, dft_control%nimages
929 2602 : CALL dbcsr_dot(rho_ao(ispin, img)%matrix, matrix_s(1, img)%matrix, trace_tmp)
930 5070 : trace = trace + trace_tmp
931 : END DO
932 : END DO
933 : END IF
934 :
935 110261 : IF (output_unit > 0) THEN
936 835 : WRITE (UNIT=output_unit, FMT="(/,T3,A,T41,F20.10)") "Trace(PS):", trace
937 : WRITE (UNIT=output_unit, FMT="((T3,A,T41,2F20.10))") &
938 835 : "Electronic density on regular grids: ", &
939 835 : tot_rho_r, &
940 : tot_rho_r + &
941 835 : REAL(n_electrons, dp), &
942 835 : "Core density on regular grids:", &
943 835 : qs_charges%total_rho_core_rspace, &
944 : qs_charges%total_rho_core_rspace + &
945 : qs_charges%total_rho1_hard_nuc - &
946 1670 : REAL(n_electrons + dft_control%charge, dp)
947 : END IF
948 110261 : IF (dft_control%qs_control%gapw) THEN
949 18580 : tot1_h = qs_charges%total_rho1_hard(1)
950 18580 : tot1_s = qs_charges%total_rho1_soft(1)
951 22022 : DO ispin = 2, dft_control%nspins
952 3442 : tot1_h = tot1_h + qs_charges%total_rho1_hard(ispin)
953 22022 : tot1_s = tot1_s + qs_charges%total_rho1_soft(ispin)
954 : END DO
955 18580 : IF (output_unit > 0) THEN
956 : WRITE (UNIT=output_unit, FMT="((T3,A,T41,2F20.10))") &
957 399 : "Hard and soft densities (Lebedev):", &
958 798 : tot1_h, tot1_s
959 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
960 399 : "Total Rho_soft + Rho1_hard - Rho1_soft (r-space): ", &
961 399 : tot_rho_r + tot1_h - tot1_s, &
962 399 : "Total charge density (r-space): ", &
963 : tot_rho_r + tot1_h - tot1_s &
964 : + qs_charges%total_rho_core_rspace &
965 798 : + qs_charges%total_rho1_hard_nuc
966 399 : IF (qs_charges%total_rho1_hard_nuc /= 0.0_dp) THEN
967 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
968 0 : "Total CNEO nuc. char. den. (Lebedev): ", &
969 0 : qs_charges%total_rho1_hard_nuc, &
970 0 : "Total CNEO soft char. den. (Lebedev): ", &
971 0 : qs_charges%total_rho1_soft_nuc_lebedev, &
972 0 : "Total CNEO soft char. den. (r-space): ", &
973 0 : qs_charges%total_rho1_soft_nuc_rspace, &
974 0 : "Total soft Rho_e+n+0 (g-space):", &
975 0 : qs_charges%total_rho_gspace
976 : ELSE
977 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
978 399 : "Total Rho_soft + Rho0_soft (g-space):", &
979 798 : qs_charges%total_rho_gspace
980 : END IF
981 : END IF
982 : qs_charges%background = tot_rho_r + tot1_h - tot1_s + &
983 : qs_charges%total_rho_core_rspace + &
984 18580 : qs_charges%total_rho1_hard_nuc
985 : ! only add total_rho1_hard_nuc for gapw as cneo requires gapw
986 91681 : ELSE IF (dft_control%qs_control%gapw_xc) THEN
987 3690 : tot1_h = qs_charges%total_rho1_hard(1)
988 3690 : tot1_s = qs_charges%total_rho1_soft(1)
989 4052 : DO ispin = 2, dft_control%nspins
990 362 : tot1_h = tot1_h + qs_charges%total_rho1_hard(ispin)
991 4052 : tot1_s = tot1_s + qs_charges%total_rho1_soft(ispin)
992 : END DO
993 3690 : IF (output_unit > 0) THEN
994 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T41,2F20.10))") &
995 0 : "Hard and soft densities (Lebedev):", &
996 0 : tot1_h, tot1_s
997 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
998 0 : "Total Rho_soft + Rho1_hard - Rho1_soft (r-space): ", &
999 0 : accurate_sum(tot_rho_r_arr) + tot1_h - tot1_s
1000 : END IF
1001 : qs_charges%background = tot_rho_r + &
1002 3690 : qs_charges%total_rho_core_rspace
1003 : ELSE
1004 87991 : IF (output_unit > 0) THEN
1005 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
1006 436 : "Total charge density on r-space grids: ", &
1007 : tot_rho_r + &
1008 436 : qs_charges%total_rho_core_rspace, &
1009 436 : "Total charge density g-space grids: ", &
1010 872 : qs_charges%total_rho_gspace
1011 : END IF
1012 : qs_charges%background = tot_rho_r + &
1013 87991 : qs_charges%total_rho_core_rspace
1014 : END IF
1015 110261 : IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="()")
1016 110261 : qs_charges%background = qs_charges%background/cell%deth
1017 :
1018 : CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
1019 110261 : "PRINT%TOTAL_DENSITIES")
1020 :
1021 110261 : END SUBROUTINE print_densities
1022 :
1023 : ! **************************************************************************************************
1024 : !> \brief Print detailed energies
1025 : !>
1026 : !> \param qs_env ...
1027 : !> \param dft_control ...
1028 : !> \param input ...
1029 : !> \param energy ...
1030 : !> \param mulliken_order_p ...
1031 : !> \par History
1032 : !> refactoring 04.03.2011 [MI]
1033 : !> \author
1034 : ! **************************************************************************************************
1035 110261 : SUBROUTINE print_detailed_energy(qs_env, dft_control, input, energy, mulliken_order_p)
1036 :
1037 : TYPE(qs_environment_type), POINTER :: qs_env
1038 : TYPE(dft_control_type), POINTER :: dft_control
1039 : TYPE(section_vals_type), POINTER :: input
1040 : TYPE(qs_energy_type), POINTER :: energy
1041 : REAL(KIND=dp), INTENT(IN) :: mulliken_order_p
1042 :
1043 : INTEGER :: bc, n, output_unit, psolver
1044 : REAL(KIND=dp) :: ddapc_order_p, implicit_ps_ehartree, &
1045 : s2_order_p
1046 : TYPE(cp_logger_type), POINTER :: logger
1047 : TYPE(pw_env_type), POINTER :: pw_env
1048 :
1049 110261 : logger => cp_get_default_logger()
1050 :
1051 110261 : NULLIFY (pw_env)
1052 110261 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
1053 110261 : psolver = pw_env%poisson_env%parameters%solver
1054 :
1055 : output_unit = cp_print_key_unit_nr(logger, input, "DFT%SCF%PRINT%DETAILED_ENERGY", &
1056 110261 : extension=".scfLog")
1057 110261 : IF (output_unit > 0) THEN
1058 488 : IF (dft_control%do_admm) THEN
1059 : WRITE (UNIT=output_unit, FMT="((T3,A,T60,F20.10))") &
1060 0 : "Wfn fit exchange-correlation energy: ", energy%exc_aux_fit
1061 0 : IF (dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc) THEN
1062 : WRITE (UNIT=output_unit, FMT="((T3,A,T60,F20.10))") &
1063 0 : "Wfn fit soft/hard atomic rho1 Exc contribution: ", energy%exc1_aux_fit
1064 : END IF
1065 : END IF
1066 488 : IF (dft_control%do_admm) THEN
1067 0 : IF (psolver == pw_poisson_implicit) THEN
1068 0 : implicit_ps_ehartree = pw_env%poisson_env%implicit_env%ehartree
1069 0 : bc = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
1070 0 : SELECT CASE (bc)
1071 : CASE (MIXED_PERIODIC_BC, MIXED_BC)
1072 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1073 0 : "Core Hamiltonian energy: ", energy%core, &
1074 0 : "Hartree energy: ", implicit_ps_ehartree, &
1075 0 : "Electric enthalpy: ", energy%hartree, &
1076 0 : "Exchange-correlation energy: ", energy%exc + energy%exc_aux_fit
1077 : CASE (PERIODIC_BC, NEUMANN_BC)
1078 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1079 0 : "Core Hamiltonian energy: ", energy%core, &
1080 0 : "Hartree energy: ", energy%hartree, &
1081 0 : "Exchange-correlation energy: ", energy%exc + energy%exc_aux_fit
1082 : END SELECT
1083 : ELSE
1084 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1085 0 : "Core Hamiltonian energy: ", energy%core, &
1086 0 : "Hartree energy: ", energy%hartree, &
1087 0 : "Exchange-correlation energy: ", energy%exc + energy%exc_aux_fit
1088 : END IF
1089 : ELSE
1090 : !ZMP to print some variables at each step
1091 488 : IF (dft_control%apply_external_density) THEN
1092 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1093 0 : "DOING ZMP CALCULATION FROM EXTERNAL DENSITY "
1094 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1095 0 : "Core Hamiltonian energy: ", energy%core, &
1096 0 : "Hartree energy: ", energy%hartree
1097 488 : ELSE IF (dft_control%apply_external_vxc) THEN
1098 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1099 0 : "DOING ZMP READING EXTERNAL VXC "
1100 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1101 0 : "Core Hamiltonian energy: ", energy%core, &
1102 0 : "Hartree energy: ", energy%hartree
1103 : ELSE
1104 488 : IF (psolver == pw_poisson_implicit) THEN
1105 0 : implicit_ps_ehartree = pw_env%poisson_env%implicit_env%ehartree
1106 0 : bc = pw_env%poisson_env%parameters%ps_implicit_params%boundary_condition
1107 0 : SELECT CASE (bc)
1108 : CASE (MIXED_PERIODIC_BC, MIXED_BC)
1109 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1110 0 : "Core Hamiltonian energy: ", energy%core, &
1111 0 : "Hartree energy: ", implicit_ps_ehartree, &
1112 0 : "Electric enthalpy: ", energy%hartree, &
1113 0 : "Exchange-correlation energy: ", energy%exc
1114 : CASE (PERIODIC_BC, NEUMANN_BC)
1115 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1116 0 : "Core Hamiltonian energy: ", energy%core, &
1117 0 : "Hartree energy: ", energy%hartree, &
1118 0 : "Exchange-correlation energy: ", energy%exc
1119 : END SELECT
1120 : ELSE
1121 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1122 488 : "Core Hamiltonian energy: ", energy%core, &
1123 488 : "Hartree energy: ", energy%hartree, &
1124 976 : "Exchange-correlation energy: ", energy%exc
1125 : END IF
1126 : END IF
1127 : END IF
1128 :
1129 488 : IF (dft_control%apply_external_density) THEN
1130 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1131 0 : "Integral of the (density * v_xc): ", energy%exc
1132 : END IF
1133 :
1134 488 : IF (energy%e_hartree /= 0.0_dp) &
1135 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1136 456 : "Coulomb (electron-electron) energy: ", energy%e_hartree
1137 488 : IF (energy%dispersion /= 0.0_dp) &
1138 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1139 0 : "Dispersion energy: ", energy%dispersion
1140 488 : IF (energy%efield /= 0.0_dp) &
1141 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1142 0 : "Electric field interaction energy: ", energy%efield
1143 488 : IF (energy%gcp /= 0.0_dp) &
1144 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1145 0 : "gCP energy: ", energy%gcp
1146 488 : IF (dft_control%qs_control%gapw) THEN
1147 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1148 32 : "GAPW| Exc from hard and soft atomic rho1: ", energy%exc1 + energy%exc1_aux_fit, &
1149 64 : "GAPW| local Eh = 1 center integrals: ", energy%hartree_1c
1150 : END IF
1151 488 : IF (dft_control%qs_control%gapw_xc) THEN
1152 : WRITE (UNIT=output_unit, FMT="(/,(T3,A,T61,F20.10))") &
1153 0 : "GAPW| Exc from hard and soft atomic rho1: ", energy%exc1 + energy%exc1_aux_fit
1154 : END IF
1155 488 : IF (dft_control%dft_plus_u) THEN
1156 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1157 0 : "DFT+U energy:", energy%dft_plus_u
1158 : END IF
1159 488 : IF (qs_env%qmmm) THEN
1160 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1161 0 : "QM/MM Electrostatic energy: ", energy%qmmm_el
1162 0 : IF (qs_env%qmmm_env_qm%image_charge) THEN
1163 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1164 0 : "QM/MM image charge energy: ", energy%image_charge
1165 : END IF
1166 : END IF
1167 488 : IF (dft_control%qs_control%mulliken_restraint) THEN
1168 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,2F20.10)") &
1169 0 : "Mulliken restraint (order_p,energy) : ", mulliken_order_p, energy%mulliken
1170 : END IF
1171 488 : IF (dft_control%qs_control%ddapc_restraint) THEN
1172 40 : DO n = 1, SIZE(dft_control%qs_control%ddapc_restraint_control)
1173 : ddapc_order_p = &
1174 20 : dft_control%qs_control%ddapc_restraint_control(n)%ddapc_order_p
1175 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,2F20.10)") &
1176 40 : "DDAPC restraint (order_p,energy) : ", ddapc_order_p, energy%ddapc_restraint(n)
1177 : END DO
1178 : END IF
1179 488 : IF (dft_control%qs_control%s2_restraint) THEN
1180 0 : s2_order_p = dft_control%qs_control%s2_restraint_control%s2_order_p
1181 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,2F20.10)") &
1182 0 : "S2 restraint (order_p,energy) : ", s2_order_p, energy%s2_restraint
1183 : END IF
1184 488 : IF (energy%core_cneo /= 0.0_dp) THEN
1185 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1186 0 : "CNEO| quantum nuclear core energy: ", energy%core_cneo
1187 : END IF
1188 :
1189 : END IF ! output_unit
1190 : CALL cp_print_key_finished_output(output_unit, logger, input, &
1191 110261 : "DFT%SCF%PRINT%DETAILED_ENERGY")
1192 :
1193 110261 : END SUBROUTINE print_detailed_energy
1194 :
1195 : ! **************************************************************************************************
1196 : !> \brief compute matrix_vxc, defined via the potential created by qs_vxc_create
1197 : !> ignores things like tau functional, gapw, sic, ...
1198 : !> so only OK for GGA & GPW right now
1199 : !> \param qs_env ...
1200 : !> \param v_rspace ...
1201 : !> \param matrix_vxc ...
1202 : !> \par History
1203 : !> created 23.10.2012 [Joost VandeVondele]
1204 : !> \author
1205 : ! **************************************************************************************************
1206 8 : SUBROUTINE compute_matrix_vxc(qs_env, v_rspace, matrix_vxc)
1207 : TYPE(qs_environment_type), POINTER :: qs_env
1208 : TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN) :: v_rspace
1209 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_vxc
1210 :
1211 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_matrix_vxc'
1212 :
1213 : INTEGER :: handle, ispin
1214 : LOGICAL :: gapw
1215 8 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1216 : TYPE(dft_control_type), POINTER :: dft_control
1217 :
1218 8 : CALL timeset(routineN, handle)
1219 :
1220 : ! create the matrix using matrix_ks as a template
1221 8 : IF (ASSOCIATED(matrix_vxc)) THEN
1222 0 : CALL dbcsr_deallocate_matrix_set(matrix_vxc)
1223 : END IF
1224 8 : CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
1225 36 : ALLOCATE (matrix_vxc(SIZE(matrix_ks)))
1226 20 : DO ispin = 1, SIZE(matrix_ks)
1227 12 : NULLIFY (matrix_vxc(ispin)%matrix)
1228 12 : CALL dbcsr_init_p(matrix_vxc(ispin)%matrix)
1229 : CALL dbcsr_copy(matrix_vxc(ispin)%matrix, matrix_ks(ispin)%matrix, &
1230 12 : name="Matrix VXC of spin "//cp_to_string(ispin))
1231 20 : CALL dbcsr_set(matrix_vxc(ispin)%matrix, 0.0_dp)
1232 : END DO
1233 :
1234 : ! and integrate
1235 8 : CALL get_qs_env(qs_env, dft_control=dft_control)
1236 8 : gapw = dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc
1237 20 : DO ispin = 1, SIZE(matrix_ks)
1238 : CALL integrate_v_rspace(v_rspace=v_rspace(ispin), &
1239 : hmat=matrix_vxc(ispin), &
1240 : qs_env=qs_env, &
1241 : calculate_forces=.FALSE., &
1242 12 : gapw=gapw)
1243 : ! scale by the volume element... should really become part of integrate_v_rspace
1244 20 : CALL dbcsr_scale(matrix_vxc(ispin)%matrix, v_rspace(ispin)%pw_grid%dvol)
1245 : END DO
1246 :
1247 8 : CALL timestop(handle)
1248 :
1249 8 : END SUBROUTINE compute_matrix_vxc
1250 :
1251 : ! **************************************************************************************************
1252 : !> \brief Sum up all potentials defined on the grid and integrate
1253 : !>
1254 : !> \param qs_env ...
1255 : !> \param ks_matrix ...
1256 : !> \param rho ...
1257 : !> \param my_rho ...
1258 : !> \param vppl_rspace ...
1259 : !> \param v_rspace_new ...
1260 : !> \param v_rspace_new_aux_fit ...
1261 : !> \param v_tau_rspace ...
1262 : !> \param v_tau_rspace_aux_fit ...
1263 : !> \param v_sic_rspace ...
1264 : !> \param v_spin_ddapc_rest_r ...
1265 : !> \param v_sccs_rspace ...
1266 : !> \param v_rspace_embed ...
1267 : !> \param cdft_control ...
1268 : !> \param calculate_forces ...
1269 : !> \par History
1270 : !> - refactoring 04.03.2011 [MI]
1271 : !> - SCCS implementation (16.10.2013,MK)
1272 : !> \author
1273 : ! **************************************************************************************************
1274 100841 : SUBROUTINE sum_up_and_integrate(qs_env, ks_matrix, rho, my_rho, &
1275 : vppl_rspace, v_rspace_new, &
1276 : v_rspace_new_aux_fit, v_tau_rspace, &
1277 : v_tau_rspace_aux_fit, &
1278 : v_sic_rspace, v_spin_ddapc_rest_r, &
1279 : v_sccs_rspace, v_rspace_embed, cdft_control, &
1280 : calculate_forces)
1281 :
1282 : TYPE(qs_environment_type), POINTER :: qs_env
1283 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
1284 : TYPE(qs_rho_type), POINTER :: rho
1285 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: my_rho
1286 : TYPE(pw_r3d_rs_type), POINTER :: vppl_rspace
1287 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_new, v_rspace_new_aux_fit, &
1288 : v_tau_rspace, v_tau_rspace_aux_fit
1289 : TYPE(pw_r3d_rs_type), POINTER :: v_sic_rspace, v_spin_ddapc_rest_r, &
1290 : v_sccs_rspace
1291 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_embed
1292 : TYPE(cdft_control_type), POINTER :: cdft_control
1293 : LOGICAL, INTENT(in) :: calculate_forces
1294 :
1295 : CHARACTER(LEN=*), PARAMETER :: routineN = 'sum_up_and_integrate'
1296 :
1297 : CHARACTER(LEN=default_string_length) :: basis_type
1298 : INTEGER :: handle, igroup, ikind, img, ispin, &
1299 : nkind, nspins
1300 100841 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1301 : LOGICAL :: do_ppl, gapw, gapw_xc, lrigpw, rigpw
1302 : REAL(KIND=dp) :: csign, dvol, fadm
1303 : TYPE(admm_type), POINTER :: admm_env
1304 100841 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1305 100841 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ksmat, rho_ao, rho_ao_nokp, smat
1306 100841 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_aux_fit, &
1307 100841 : matrix_ks_aux_fit_dft, rho_ao_aux, &
1308 100841 : rho_ao_kp
1309 : TYPE(dft_control_type), POINTER :: dft_control
1310 : TYPE(kpoint_type), POINTER :: kpoints
1311 : TYPE(lri_density_type), POINTER :: lri_density
1312 : TYPE(lri_environment_type), POINTER :: lri_env
1313 100841 : TYPE(lri_kind_type), DIMENSION(:), POINTER :: lri_v_int
1314 : TYPE(mp_para_env_type), POINTER :: para_env
1315 : TYPE(pw_env_type), POINTER :: pw_env
1316 : TYPE(pw_poisson_type), POINTER :: poisson_env
1317 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1318 : TYPE(pw_r3d_rs_type), POINTER :: v_rspace, vee
1319 : TYPE(qs_ks_env_type), POINTER :: ks_env
1320 : TYPE(qs_rho_type), POINTER :: rho_aux_fit
1321 : TYPE(task_list_type), POINTER :: task_list
1322 :
1323 100841 : CALL timeset(routineN, handle)
1324 :
1325 100841 : NULLIFY (auxbas_pw_pool, dft_control, pw_env, matrix_ks_aux_fit, &
1326 100841 : v_rspace, rho_aux_fit, vee, rho_ao, rho_ao_kp, rho_ao_aux, &
1327 100841 : ksmat, matrix_ks_aux_fit_dft, lri_env, lri_density, atomic_kind_set, &
1328 100841 : rho_ao_nokp, ks_env, admm_env, task_list)
1329 :
1330 : CALL get_qs_env(qs_env, &
1331 : dft_control=dft_control, &
1332 : pw_env=pw_env, &
1333 : v_hartree_rspace=v_rspace, &
1334 100841 : vee=vee)
1335 :
1336 100841 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
1337 100841 : CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
1338 100841 : gapw = dft_control%qs_control%gapw
1339 100841 : gapw_xc = dft_control%qs_control%gapw_xc
1340 100841 : do_ppl = dft_control%qs_control%do_ppl_method == do_ppl_grid
1341 :
1342 100841 : rigpw = dft_control%qs_control%rigpw
1343 100841 : lrigpw = dft_control%qs_control%lrigpw
1344 100841 : IF (lrigpw .OR. rigpw) THEN
1345 : CALL get_qs_env(qs_env, &
1346 : lri_env=lri_env, &
1347 : lri_density=lri_density, &
1348 450 : atomic_kind_set=atomic_kind_set)
1349 : END IF
1350 :
1351 100841 : nspins = dft_control%nspins
1352 :
1353 : ! sum up potentials and integrate
1354 100841 : IF (ASSOCIATED(v_rspace_new)) THEN
1355 198857 : DO ispin = 1, nspins
1356 107678 : IF (gapw_xc) THEN
1357 : ! SIC not implemented (or at least not tested)
1358 3674 : CPASSERT(dft_control%sic_method_id == sic_none)
1359 : !Only the xc potential, because it has to be integrated with the soft basis
1360 3674 : CALL pw_scale(v_rspace_new(ispin), v_rspace_new(ispin)%pw_grid%dvol)
1361 :
1362 : ! add the xc part due to v_rspace soft
1363 3674 : rho_ao => rho_ao_kp(ispin, :)
1364 3674 : ksmat => ks_matrix(ispin, :)
1365 : CALL integrate_v_rspace(v_rspace=v_rspace_new(ispin), &
1366 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1367 : qs_env=qs_env, &
1368 : calculate_forces=calculate_forces, &
1369 3674 : gapw=gapw_xc)
1370 :
1371 : ! Now the Hartree potential to be integrated with the full basis
1372 3674 : CALL pw_copy(v_rspace, v_rspace_new(ispin))
1373 : ELSE
1374 : ! Add v_hartree + v_xc = v_rspace_new
1375 104004 : CALL pw_axpy(v_rspace, v_rspace_new(ispin), 1.0_dp, v_rspace_new(ispin)%pw_grid%dvol)
1376 : END IF ! gapw_xc
1377 107678 : IF (dft_control%qs_control%ddapc_explicit_potential) THEN
1378 184 : IF (dft_control%qs_control%ddapc_restraint_is_spin) THEN
1379 184 : IF (ispin == 1) THEN
1380 92 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), 1.0_dp)
1381 : ELSE
1382 92 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), -1.0_dp)
1383 : END IF
1384 : ELSE
1385 0 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), 1.0_dp)
1386 : END IF
1387 : END IF
1388 : ! CDFT constraint contribution
1389 107678 : IF (dft_control%qs_control%cdft) THEN
1390 11336 : DO igroup = 1, SIZE(cdft_control%group)
1391 6644 : SELECT CASE (cdft_control%group(igroup)%constraint_type)
1392 : CASE (cdft_charge_constraint)
1393 16 : csign = 1.0_dp
1394 : CASE (cdft_magnetization_constraint)
1395 16 : IF (ispin == 1) THEN
1396 : csign = 1.0_dp
1397 : ELSE
1398 8 : csign = -1.0_dp
1399 : END IF
1400 : CASE (cdft_alpha_constraint)
1401 1944 : csign = 1.0_dp
1402 1944 : IF (ispin == 2) CYCLE
1403 : CASE (cdft_beta_constraint)
1404 1944 : csign = 1.0_dp
1405 1944 : IF (ispin == 1) CYCLE
1406 : CASE DEFAULT
1407 6644 : CPABORT("Unknown constraint type.")
1408 : END SELECT
1409 : CALL pw_axpy(cdft_control%group(igroup)%weight, v_rspace_new(ispin), &
1410 11336 : csign*cdft_control%strength(igroup))
1411 : END DO
1412 : END IF
1413 : ! functional derivative of the Hartree energy wrt the density in the presence of dielectric
1414 : ! (vhartree + v_eps); v_eps is nonzero only if the dielectric constant is defind as a function
1415 : ! of the charge density
1416 107678 : IF (poisson_env%parameters%solver == pw_poisson_implicit) THEN
1417 440 : dvol = poisson_env%implicit_env%v_eps%pw_grid%dvol
1418 440 : CALL pw_axpy(poisson_env%implicit_env%v_eps, v_rspace_new(ispin), dvol)
1419 : END IF
1420 : ! Add SCCS contribution
1421 107678 : IF (dft_control%do_sccs) THEN
1422 132 : CALL pw_axpy(v_sccs_rspace, v_rspace_new(ispin))
1423 : END IF
1424 : ! External electrostatic potential
1425 107678 : IF (dft_control%apply_external_potential) THEN
1426 : CALL qmmm_modify_hartree_pot(v_hartree=v_rspace_new(ispin), &
1427 364 : v_qmmm=vee, scale=-1.0_dp)
1428 : END IF
1429 107678 : IF (do_ppl) THEN
1430 66 : CPASSERT(.NOT. gapw)
1431 66 : CALL pw_axpy(vppl_rspace, v_rspace_new(ispin), vppl_rspace%pw_grid%dvol)
1432 : END IF
1433 : ! the electrostatic sic contribution
1434 108038 : SELECT CASE (dft_control%sic_method_id)
1435 : CASE (sic_none)
1436 : !
1437 : CASE (sic_mauri_us, sic_mauri_spz)
1438 360 : IF (ispin == 1) THEN
1439 180 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), -1.0_dp)
1440 : ELSE
1441 180 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), 1.0_dp)
1442 : END IF
1443 : CASE (sic_ad)
1444 107678 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), -1.0_dp)
1445 : CASE (sic_eo)
1446 : ! NOTHING TO BE DONE
1447 : END SELECT
1448 : ! DFT embedding
1449 107678 : IF (dft_control%apply_embed_pot) THEN
1450 930 : CALL pw_axpy(v_rspace_embed(ispin), v_rspace_new(ispin), v_rspace_embed(ispin)%pw_grid%dvol)
1451 930 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1452 : END IF
1453 107678 : IF (lrigpw) THEN
1454 436 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1455 436 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1456 1310 : DO ikind = 1, nkind
1457 283998 : lri_v_int(ikind)%v_int = 0.0_dp
1458 : END DO
1459 : CALL integrate_v_rspace_one_center(v_rspace_new(ispin), qs_env, &
1460 436 : lri_v_int, calculate_forces, "LRI_AUX")
1461 1310 : DO ikind = 1, nkind
1462 566686 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1463 : END DO
1464 436 : IF (lri_env%exact_1c_terms) THEN
1465 36 : rho_ao => my_rho(ispin, :)
1466 36 : ksmat => ks_matrix(ispin, :)
1467 : CALL integrate_v_rspace_diagonal(v_rspace_new(ispin), ksmat(1)%matrix, &
1468 : rho_ao(1)%matrix, qs_env, &
1469 36 : calculate_forces, "ORB")
1470 : END IF
1471 436 : IF (lri_env%ppl_ri) THEN
1472 8 : CALL v_int_ppl_update(qs_env, lri_v_int, calculate_forces)
1473 : END IF
1474 107242 : ELSEIF (rigpw) THEN
1475 26 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1476 26 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1477 52 : DO ikind = 1, nkind
1478 1144 : lri_v_int(ikind)%v_int = 0.0_dp
1479 : END DO
1480 : CALL integrate_v_rspace_one_center(v_rspace_new(ispin), qs_env, &
1481 26 : lri_v_int, calculate_forces, "RI_HXC")
1482 52 : DO ikind = 1, nkind
1483 2236 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1484 : END DO
1485 : ELSE
1486 107216 : rho_ao => my_rho(ispin, :)
1487 107216 : ksmat => ks_matrix(ispin, :)
1488 : CALL integrate_v_rspace(v_rspace=v_rspace_new(ispin), &
1489 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1490 : qs_env=qs_env, &
1491 : calculate_forces=calculate_forces, &
1492 107216 : gapw=gapw)
1493 : END IF
1494 198857 : CALL auxbas_pw_pool%give_back_pw(v_rspace_new(ispin))
1495 : END DO ! ispin
1496 :
1497 91379 : SELECT CASE (dft_control%sic_method_id)
1498 : CASE (sic_none)
1499 : CASE (sic_mauri_us, sic_mauri_spz, sic_ad)
1500 200 : CALL auxbas_pw_pool%give_back_pw(v_sic_rspace)
1501 91379 : DEALLOCATE (v_sic_rspace)
1502 : END SELECT
1503 91179 : DEALLOCATE (v_rspace_new)
1504 :
1505 : ELSE
1506 : ! not implemented (or at least not tested)
1507 9662 : CPASSERT(dft_control%sic_method_id == sic_none)
1508 9662 : CPASSERT(.NOT. dft_control%qs_control%ddapc_restraint_is_spin)
1509 21438 : DO ispin = 1, nspins
1510 : ! extra contribution attributed to the dependency of the dielectric constant to the charge density
1511 11776 : IF (poisson_env%parameters%solver == pw_poisson_implicit) THEN
1512 0 : dvol = poisson_env%implicit_env%v_eps%pw_grid%dvol
1513 0 : CALL pw_axpy(poisson_env%implicit_env%v_eps, v_rspace, dvol)
1514 : END IF
1515 : ! Add SCCS contribution
1516 11776 : IF (dft_control%do_sccs) THEN
1517 0 : CALL pw_axpy(v_sccs_rspace, v_rspace)
1518 : END IF
1519 : ! DFT embedding
1520 11776 : IF (dft_control%apply_embed_pot) THEN
1521 12 : CALL pw_axpy(v_rspace_embed(ispin), v_rspace, v_rspace_embed(ispin)%pw_grid%dvol)
1522 12 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1523 : END IF
1524 21438 : IF (lrigpw) THEN
1525 0 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1526 0 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1527 0 : DO ikind = 1, nkind
1528 0 : lri_v_int(ikind)%v_int = 0.0_dp
1529 : END DO
1530 : CALL integrate_v_rspace_one_center(v_rspace, qs_env, &
1531 0 : lri_v_int, calculate_forces, "LRI_AUX")
1532 0 : DO ikind = 1, nkind
1533 0 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1534 : END DO
1535 0 : IF (lri_env%exact_1c_terms) THEN
1536 0 : rho_ao => my_rho(ispin, :)
1537 0 : ksmat => ks_matrix(ispin, :)
1538 : CALL integrate_v_rspace_diagonal(v_rspace, ksmat(1)%matrix, &
1539 : rho_ao(1)%matrix, qs_env, &
1540 0 : calculate_forces, "ORB")
1541 : END IF
1542 0 : IF (lri_env%ppl_ri) THEN
1543 0 : CALL v_int_ppl_update(qs_env, lri_v_int, calculate_forces)
1544 : END IF
1545 11776 : ELSEIF (rigpw) THEN
1546 0 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1547 0 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1548 0 : DO ikind = 1, nkind
1549 0 : lri_v_int(ikind)%v_int = 0.0_dp
1550 : END DO
1551 : CALL integrate_v_rspace_one_center(v_rspace, qs_env, &
1552 0 : lri_v_int, calculate_forces, "RI_HXC")
1553 0 : DO ikind = 1, nkind
1554 0 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1555 : END DO
1556 : ELSE
1557 11776 : rho_ao => my_rho(ispin, :)
1558 11776 : ksmat => ks_matrix(ispin, :)
1559 : CALL integrate_v_rspace(v_rspace=v_rspace, &
1560 : pmat_kp=rho_ao, &
1561 : hmat_kp=ksmat, &
1562 : qs_env=qs_env, &
1563 : calculate_forces=calculate_forces, &
1564 11776 : gapw=gapw)
1565 : END IF
1566 : END DO
1567 : END IF ! ASSOCIATED(v_rspace_new)
1568 :
1569 : ! **** LRIGPW: KS matrix from integrated potential
1570 100841 : IF (lrigpw) THEN
1571 424 : CALL get_qs_env(qs_env, ks_env=ks_env)
1572 424 : CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
1573 424 : CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
1574 860 : DO ispin = 1, nspins
1575 436 : ksmat => ks_matrix(ispin, :)
1576 : CALL calculate_lri_ks_matrix(lri_env, lri_v_int, ksmat, atomic_kind_set, &
1577 860 : cell_to_index=cell_to_index)
1578 : END DO
1579 424 : IF (calculate_forces) THEN
1580 22 : CALL calculate_lri_forces(lri_env, lri_density, qs_env, rho_ao_kp, atomic_kind_set)
1581 : END IF
1582 100417 : ELSEIF (rigpw) THEN
1583 26 : CALL get_qs_env(qs_env, matrix_s=smat)
1584 52 : DO ispin = 1, nspins
1585 : CALL calculate_ri_ks_matrix(lri_env, lri_v_int, ks_matrix(ispin, 1)%matrix, &
1586 52 : smat(1)%matrix, atomic_kind_set, ispin)
1587 : END DO
1588 26 : IF (calculate_forces) THEN
1589 2 : rho_ao_nokp => rho_ao_kp(:, 1)
1590 2 : CALL calculate_ri_forces(lri_env, lri_density, qs_env, rho_ao_nokp, atomic_kind_set)
1591 : END IF
1592 : END IF
1593 :
1594 100841 : IF (ASSOCIATED(v_tau_rspace)) THEN
1595 1928 : IF (lrigpw .OR. rigpw) THEN
1596 0 : CPABORT("LRIGPW/RIGPW not implemented for meta-GGAs")
1597 : END IF
1598 4242 : DO ispin = 1, nspins
1599 2314 : CALL pw_scale(v_tau_rspace(ispin), v_tau_rspace(ispin)%pw_grid%dvol)
1600 :
1601 2314 : rho_ao => rho_ao_kp(ispin, :)
1602 2314 : ksmat => ks_matrix(ispin, :)
1603 : CALL integrate_v_rspace(v_rspace=v_tau_rspace(ispin), &
1604 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1605 : qs_env=qs_env, &
1606 : calculate_forces=calculate_forces, compute_tau=.TRUE., &
1607 2314 : gapw=gapw)
1608 4242 : CALL auxbas_pw_pool%give_back_pw(v_tau_rspace(ispin))
1609 : END DO
1610 1928 : DEALLOCATE (v_tau_rspace)
1611 : END IF
1612 :
1613 : ! Add contributions from ADMM if requested
1614 100841 : IF (dft_control%do_admm) THEN
1615 11284 : CALL get_qs_env(qs_env, admm_env=admm_env)
1616 : CALL get_admm_env(admm_env, matrix_ks_aux_fit_kp=matrix_ks_aux_fit, rho_aux_fit=rho_aux_fit, &
1617 11284 : matrix_ks_aux_fit_dft_kp=matrix_ks_aux_fit_dft)
1618 11284 : CALL qs_rho_get(rho_aux_fit, rho_ao_kp=rho_ao_aux)
1619 11284 : IF (ASSOCIATED(v_rspace_new_aux_fit)) THEN
1620 16744 : DO ispin = 1, nspins
1621 : ! Calculate the xc potential
1622 9134 : CALL pw_scale(v_rspace_new_aux_fit(ispin), v_rspace_new_aux_fit(ispin)%pw_grid%dvol)
1623 :
1624 : ! set matrix_ks_aux_fit_dft = matrix_ks_aux_fit(k_HF)
1625 22888 : DO img = 1, dft_control%nimages
1626 : CALL dbcsr_copy(matrix_ks_aux_fit_dft(ispin, img)%matrix, matrix_ks_aux_fit(ispin, img)%matrix, &
1627 22888 : name="DFT exch. part of matrix_ks_aux_fit")
1628 : END DO
1629 :
1630 : ! Add potential to ks_matrix aux_fit, skip integration if no DFT correction
1631 :
1632 9134 : IF (admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1633 :
1634 : !GPW by default. IF GAPW, then take relevant task list and basis
1635 9134 : CALL get_admm_env(admm_env, task_list_aux_fit=task_list)
1636 9134 : basis_type = "AUX_FIT"
1637 9134 : IF (admm_env%do_gapw) THEN
1638 2826 : task_list => admm_env%admm_gapw_env%task_list
1639 2826 : basis_type = "AUX_FIT_SOFT"
1640 : END IF
1641 9134 : fadm = 1.0_dp
1642 : ! Calculate bare scaling of force according to Merlot, 1. IF: ADMMP, 2. IF: ADMMS,
1643 9134 : IF (admm_env%do_admmp) THEN
1644 222 : fadm = admm_env%gsi(ispin)**2
1645 8912 : ELSE IF (admm_env%do_admms) THEN
1646 432 : fadm = (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)
1647 : END IF
1648 :
1649 9134 : rho_ao => rho_ao_aux(ispin, :)
1650 9134 : ksmat => matrix_ks_aux_fit(ispin, :)
1651 :
1652 : CALL integrate_v_rspace(v_rspace=v_rspace_new_aux_fit(ispin), &
1653 : pmat_kp=rho_ao, &
1654 : hmat_kp=ksmat, &
1655 : qs_env=qs_env, &
1656 : calculate_forces=calculate_forces, &
1657 : force_adm=fadm, &
1658 : gapw=.FALSE., & !even if actual GAPW calculation, want to use AUX_FIT_SOFT
1659 : basis_type=basis_type, &
1660 9134 : task_list_external=task_list)
1661 : END IF
1662 :
1663 : ! matrix_ks_aux_fit_dft(x_DFT)=matrix_ks_aux_fit_dft(old,k_HF)-matrix_ks_aux_fit(k_HF-x_DFT)
1664 22888 : DO img = 1, dft_control%nimages
1665 : CALL dbcsr_add(matrix_ks_aux_fit_dft(ispin, img)%matrix, &
1666 22888 : matrix_ks_aux_fit(ispin, img)%matrix, 1.0_dp, -1.0_dp)
1667 : END DO
1668 :
1669 16744 : CALL auxbas_pw_pool%give_back_pw(v_rspace_new_aux_fit(ispin))
1670 : END DO
1671 7610 : DEALLOCATE (v_rspace_new_aux_fit)
1672 : END IF
1673 : ! Clean up v_tau_rspace_aux_fit, which is actually not needed
1674 11284 : IF (ASSOCIATED(v_tau_rspace_aux_fit)) THEN
1675 0 : DO ispin = 1, nspins
1676 0 : CALL auxbas_pw_pool%give_back_pw(v_tau_rspace_aux_fit(ispin))
1677 : END DO
1678 0 : DEALLOCATE (v_tau_rspace_aux_fit)
1679 : END IF
1680 : END IF
1681 :
1682 100841 : IF (dft_control%apply_embed_pot) DEALLOCATE (v_rspace_embed)
1683 :
1684 100841 : CALL timestop(handle)
1685 :
1686 100841 : END SUBROUTINE sum_up_and_integrate
1687 :
1688 : !**************************************************************************
1689 : !> \brief Calculate the ZMP potential and energy as in Zhao, Morrison Parr
1690 : !> PRA 50i, 2138 (1994)
1691 : !> V_c^\lambda defined as int_rho-rho_0/r-r' or rho-rho_0 times a Lagrange
1692 : !> multiplier, plus Fermi-Amaldi potential that should give the V_xc in the
1693 : !> limit \lambda --> \infty
1694 : !>
1695 : !> \param qs_env ...
1696 : !> \param v_rspace_new ...
1697 : !> \param rho ...
1698 : !> \param exc ...
1699 : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
1700 : ! **************************************************************************************************
1701 0 : SUBROUTINE calculate_zmp_potential(qs_env, v_rspace_new, rho, exc)
1702 :
1703 : TYPE(qs_environment_type), POINTER :: qs_env
1704 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_new
1705 : TYPE(qs_rho_type), POINTER :: rho
1706 : REAL(KIND=dp) :: exc
1707 :
1708 : CHARACTER(*), PARAMETER :: routineN = 'calculate_zmp_potential'
1709 :
1710 : INTEGER :: handle, my_val, nelectron, nspins
1711 : INTEGER, DIMENSION(2) :: nelectron_spin
1712 : LOGICAL :: do_zmp_read, fermi_amaldi
1713 : REAL(KIND=dp) :: lambda
1714 0 : REAL(KIND=dp), DIMENSION(:), POINTER :: tot_rho_ext_r
1715 : TYPE(dft_control_type), POINTER :: dft_control
1716 0 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_ext_g, rho_g
1717 : TYPE(pw_env_type), POINTER :: pw_env
1718 : TYPE(pw_poisson_type), POINTER :: poisson_env
1719 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1720 : TYPE(pw_r3d_rs_type) :: v_xc_rspace
1721 0 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
1722 : TYPE(qs_ks_env_type), POINTER :: ks_env
1723 : TYPE(section_vals_type), POINTER :: ext_den_section, input
1724 :
1725 : !, v_h_gspace, &
1726 :
1727 0 : CALL timeset(routineN, handle)
1728 0 : NULLIFY (auxbas_pw_pool)
1729 0 : NULLIFY (pw_env)
1730 0 : NULLIFY (poisson_env)
1731 0 : NULLIFY (v_rspace_new)
1732 0 : NULLIFY (dft_control)
1733 0 : NULLIFY (rho_r, rho_g, tot_rho_ext_r, rho_ext_g)
1734 : CALL get_qs_env(qs_env=qs_env, &
1735 : pw_env=pw_env, &
1736 : ks_env=ks_env, &
1737 : rho=rho, &
1738 : input=input, &
1739 : nelectron_spin=nelectron_spin, &
1740 0 : dft_control=dft_control)
1741 : CALL pw_env_get(pw_env=pw_env, &
1742 : auxbas_pw_pool=auxbas_pw_pool, &
1743 0 : poisson_env=poisson_env)
1744 0 : CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
1745 0 : nspins = 1
1746 0 : ALLOCATE (v_rspace_new(nspins))
1747 0 : CALL auxbas_pw_pool%create_pw(pw=v_rspace_new(1))
1748 0 : CALL auxbas_pw_pool%create_pw(pw=v_xc_rspace)
1749 :
1750 0 : CALL pw_zero(v_rspace_new(1))
1751 0 : do_zmp_read = dft_control%apply_external_vxc
1752 0 : IF (do_zmp_read) THEN
1753 0 : CALL pw_copy(qs_env%external_vxc, v_rspace_new(1))
1754 : exc = accurate_dot_product(v_rspace_new(1)%array, rho_r(1)%array)* &
1755 0 : v_rspace_new(1)%pw_grid%dvol
1756 : ELSE
1757 0 : BLOCK
1758 : REAL(KIND=dp) :: factor
1759 : TYPE(pw_c1d_gs_type) :: rho_eff_gspace, v_xc_gspace
1760 0 : CALL auxbas_pw_pool%create_pw(pw=rho_eff_gspace)
1761 0 : CALL auxbas_pw_pool%create_pw(pw=v_xc_gspace)
1762 0 : CALL pw_zero(rho_eff_gspace)
1763 0 : CALL pw_zero(v_xc_gspace)
1764 0 : CALL pw_zero(v_xc_rspace)
1765 0 : factor = pw_integrate_function(rho_g(1))
1766 : CALL qs_rho_get(qs_env%rho_external, &
1767 : rho_g=rho_ext_g, &
1768 0 : tot_rho_r=tot_rho_ext_r)
1769 0 : factor = tot_rho_ext_r(1)/factor
1770 :
1771 0 : CALL pw_axpy(rho_g(1), rho_eff_gspace, alpha=factor)
1772 0 : CALL pw_axpy(rho_ext_g(1), rho_eff_gspace, alpha=-1.0_dp)
1773 0 : ext_den_section => section_vals_get_subs_vals(input, "DFT%EXTERNAL_DENSITY")
1774 0 : CALL section_vals_val_get(ext_den_section, "LAMBDA", r_val=lambda)
1775 0 : CALL section_vals_val_get(ext_den_section, "ZMP_CONSTRAINT", i_val=my_val)
1776 0 : CALL section_vals_val_get(ext_den_section, "FERMI_AMALDI", l_val=fermi_amaldi)
1777 :
1778 0 : CALL pw_scale(rho_eff_gspace, a=lambda)
1779 0 : nelectron = nelectron_spin(1)
1780 0 : factor = -1.0_dp/nelectron
1781 0 : CALL pw_axpy(rho_g(1), rho_eff_gspace, alpha=factor)
1782 :
1783 0 : CALL pw_poisson_solve(poisson_env, rho_eff_gspace, vhartree=v_xc_gspace)
1784 0 : CALL pw_transfer(v_xc_gspace, v_rspace_new(1))
1785 0 : CALL pw_copy(v_rspace_new(1), v_xc_rspace)
1786 :
1787 0 : exc = 0.0_dp
1788 0 : exc = pw_integral_ab(v_rspace_new(1), rho_r(1))
1789 :
1790 : !Note that this is not the xc energy but \int(\rho*v_xc)
1791 : !Vxc---> v_rspace_new
1792 : !Exc---> energy%exc
1793 0 : CALL auxbas_pw_pool%give_back_pw(rho_eff_gspace)
1794 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_gspace)
1795 : END BLOCK
1796 : END IF
1797 :
1798 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_rspace)
1799 :
1800 0 : CALL timestop(handle)
1801 :
1802 0 : END SUBROUTINE calculate_zmp_potential
1803 :
1804 : ! **************************************************************************************************
1805 : !> \brief ...
1806 : !> \param qs_env ...
1807 : !> \param rho ...
1808 : !> \param v_rspace_embed ...
1809 : !> \param dft_control ...
1810 : !> \param embed_corr ...
1811 : !> \param just_energy ...
1812 : ! **************************************************************************************************
1813 868 : SUBROUTINE get_embed_potential_energy(qs_env, rho, v_rspace_embed, dft_control, embed_corr, &
1814 : just_energy)
1815 : TYPE(qs_environment_type), POINTER :: qs_env
1816 : TYPE(qs_rho_type), POINTER :: rho
1817 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_embed
1818 : TYPE(dft_control_type), POINTER :: dft_control
1819 : REAL(KIND=dp) :: embed_corr
1820 : LOGICAL :: just_energy
1821 :
1822 : CHARACTER(*), PARAMETER :: routineN = 'get_embed_potential_energy'
1823 :
1824 : INTEGER :: handle, ispin
1825 : REAL(KIND=dp) :: embed_corr_local
1826 : TYPE(pw_env_type), POINTER :: pw_env
1827 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1828 868 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
1829 :
1830 868 : CALL timeset(routineN, handle)
1831 :
1832 868 : NULLIFY (auxbas_pw_pool)
1833 868 : NULLIFY (pw_env)
1834 868 : NULLIFY (rho_r)
1835 : CALL get_qs_env(qs_env=qs_env, &
1836 : pw_env=pw_env, &
1837 868 : rho=rho)
1838 : CALL pw_env_get(pw_env=pw_env, &
1839 868 : auxbas_pw_pool=auxbas_pw_pool)
1840 868 : CALL qs_rho_get(rho, rho_r=rho_r)
1841 3952 : ALLOCATE (v_rspace_embed(dft_control%nspins))
1842 :
1843 868 : embed_corr = 0.0_dp
1844 :
1845 2216 : DO ispin = 1, dft_control%nspins
1846 1348 : CALL auxbas_pw_pool%create_pw(pw=v_rspace_embed(ispin))
1847 1348 : CALL pw_zero(v_rspace_embed(ispin))
1848 :
1849 1348 : CALL pw_copy(qs_env%embed_pot, v_rspace_embed(ispin))
1850 1348 : embed_corr_local = 0.0_dp
1851 :
1852 : ! Spin embedding potential in open-shell case
1853 1348 : IF (dft_control%nspins == 2) THEN
1854 960 : IF (ispin == 1) CALL pw_axpy(qs_env%spin_embed_pot, v_rspace_embed(ispin), 1.0_dp)
1855 960 : IF (ispin == 2) CALL pw_axpy(qs_env%spin_embed_pot, v_rspace_embed(ispin), -1.0_dp)
1856 : END IF
1857 : ! Integrate the density*potential
1858 1348 : embed_corr_local = pw_integral_ab(v_rspace_embed(ispin), rho_r(ispin))
1859 :
1860 2216 : embed_corr = embed_corr + embed_corr_local
1861 :
1862 : END DO
1863 :
1864 : ! If only energy requiested we delete the potential
1865 868 : IF (just_energy) THEN
1866 692 : DO ispin = 1, dft_control%nspins
1867 692 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1868 : END DO
1869 286 : DEALLOCATE (v_rspace_embed)
1870 : END IF
1871 :
1872 868 : CALL timestop(handle)
1873 :
1874 868 : END SUBROUTINE get_embed_potential_energy
1875 :
1876 : END MODULE qs_ks_utils
|