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, compute_matrix_vxc_kp, 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 120127 : 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 120127 : INTEGER, DIMENSION(:), POINTER :: ivec
162 120127 : 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 120127 : REAL(KIND=dp), DIMENSION(:), POINTER :: energy_scaling, rvec, scaling
168 : TYPE(cell_type), POINTER :: cell
169 120127 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_h, matrix_hfx, matrix_p, mdummy, &
170 120127 : mo_derivs, rho_ao
171 120127 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_p2
172 : TYPE(dbcsr_type), POINTER :: dbcsr_deriv, fm_deriv, fm_scaled, &
173 : mo_coeff
174 120127 : TYPE(hfx_type), DIMENSION(:, :), POINTER :: x_data
175 120127 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
176 : TYPE(mp_para_env_type), POINTER :: para_env
177 120127 : 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 120127 : 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 119765 : 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 121937 : 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 120127 : 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 120127 : 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 120127 : 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 120127 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: mo_derivs, rho_ao, tmp_dbcsr
495 : TYPE(dbcsr_type), POINTER :: orb_density_matrix, orb_h
496 120127 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
497 : TYPE(pw_c1d_gs_type) :: work_v_gspace
498 120127 : 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 120127 : 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 120127 : 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 120287 : 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 120127 : 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 120127 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: store_forces
782 120127 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
783 : TYPE(pw_c1d_gs_type) :: work_rho, work_v
784 120127 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
785 120127 : TYPE(qs_force_type), DIMENSION(:), POINTER :: force
786 :
787 120127 : NULLIFY (mo_array, rho_g)
788 :
789 120127 : 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 120423 : END SUBROUTINE calc_v_sic_rspace
881 :
882 : ! **************************************************************************************************
883 : !> \brief ...
884 : !> \param qs_env ...
885 : !> \param rho ...
886 : ! **************************************************************************************************
887 240210 : 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 120105 : REAL(KIND=dp), DIMENSION(:), POINTER :: tot_rho_r_arr
895 : TYPE(cell_type), POINTER :: cell
896 : TYPE(cp_logger_type), POINTER :: logger
897 120105 : 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 120105 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
901 : TYPE(section_vals_type), POINTER :: input, scf_section
902 :
903 120105 : NULLIFY (qs_charges, qs_kind_set, cell, input, logger, scf_section, matrix_s, &
904 120105 : dft_control, tot_rho_r_arr, rho_ao)
905 :
906 240210 : 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 120105 : dft_control=dft_control)
914 :
915 120105 : CALL get_qs_kind_set(qs_kind_set, nelectron=n_electrons)
916 :
917 120105 : 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 120105 : extension=".scfLog")
920 :
921 120105 : CALL qs_rho_get(rho, tot_rho_r=tot_rho_r_arr, rho_ao_kp=rho_ao)
922 120105 : n_electrons = n_electrons - dft_control%charge
923 120105 : tot_rho_r = accurate_sum(tot_rho_r_arr)
924 :
925 120105 : trace = 0
926 120105 : IF (BTEST(cp_print_key_should_output(logger%iter_info, scf_section, "PRINT%TOTAL_DENSITIES"), cp_p_file)) THEN
927 4146 : DO ispin = 1, dft_control%nspins
928 7514 : DO img = 1, dft_control%nimages
929 3368 : CALL dbcsr_dot(rho_ao(ispin, img)%matrix, matrix_s(1, img)%matrix, trace_tmp)
930 5840 : trace = trace + trace_tmp
931 : END DO
932 : END DO
933 : END IF
934 :
935 120105 : IF (output_unit > 0) THEN
936 837 : 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 837 : "Electronic density on regular grids: ", &
939 837 : tot_rho_r, &
940 : tot_rho_r + &
941 837 : REAL(n_electrons, dp), &
942 837 : "Core density on regular grids:", &
943 837 : qs_charges%total_rho_core_rspace, &
944 : qs_charges%total_rho_core_rspace + &
945 : qs_charges%total_rho1_hard_nuc - &
946 1674 : REAL(n_electrons + dft_control%charge, dp)
947 : END IF
948 120105 : IF (dft_control%qs_control%gapw) THEN
949 20376 : tot1_h = qs_charges%total_rho1_hard(1)
950 20376 : tot1_s = qs_charges%total_rho1_soft(1)
951 24056 : DO ispin = 2, dft_control%nspins
952 3680 : tot1_h = tot1_h + qs_charges%total_rho1_hard(ispin)
953 24056 : tot1_s = tot1_s + qs_charges%total_rho1_soft(ispin)
954 : END DO
955 20376 : 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 20376 : qs_charges%total_rho1_hard_nuc
985 : ! only add total_rho1_hard_nuc for gapw as cneo requires gapw
986 99729 : ELSE IF (dft_control%qs_control%gapw_xc) THEN
987 4032 : tot1_h = qs_charges%total_rho1_hard(1)
988 4032 : tot1_s = qs_charges%total_rho1_soft(1)
989 4394 : DO ispin = 2, dft_control%nspins
990 362 : tot1_h = tot1_h + qs_charges%total_rho1_hard(ispin)
991 4394 : tot1_s = tot1_s + qs_charges%total_rho1_soft(ispin)
992 : END DO
993 4032 : 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 4032 : qs_charges%total_rho_core_rspace
1003 : ELSE
1004 95697 : IF (output_unit > 0) THEN
1005 : WRITE (UNIT=output_unit, FMT="(T3,A,T41,F20.10)") &
1006 438 : "Total charge density on r-space grids: ", &
1007 : tot_rho_r + &
1008 438 : qs_charges%total_rho_core_rspace, &
1009 438 : "Total charge density g-space grids: ", &
1010 876 : qs_charges%total_rho_gspace
1011 : END IF
1012 : qs_charges%background = tot_rho_r + &
1013 95697 : qs_charges%total_rho_core_rspace
1014 : END IF
1015 120105 : IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="()")
1016 120105 : qs_charges%background = qs_charges%background/cell%deth
1017 :
1018 : CALL cp_print_key_finished_output(output_unit, logger, scf_section, &
1019 120105 : "PRINT%TOTAL_DENSITIES")
1020 :
1021 120105 : 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 120105 : 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 120105 : logger => cp_get_default_logger()
1050 :
1051 120105 : NULLIFY (pw_env)
1052 120105 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
1053 120105 : psolver = pw_env%poisson_env%parameters%solver
1054 :
1055 : output_unit = cp_print_key_unit_nr(logger, input, "DFT%SCF%PRINT%DETAILED_ENERGY", &
1056 120105 : extension=".scfLog")
1057 120105 : IF (output_unit > 0) THEN
1058 490 : 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 490 : 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 490 : 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 490 : 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 490 : 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 490 : "Core Hamiltonian energy: ", energy%core, &
1123 490 : "Hartree energy: ", energy%hartree, &
1124 980 : "Exchange-correlation energy: ", energy%exc
1125 : END IF
1126 : END IF
1127 : END IF
1128 :
1129 490 : 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 490 : IF (energy%e_hartree /= 0.0_dp) &
1135 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1136 458 : "Coulomb (electron-electron) energy: ", energy%e_hartree
1137 490 : IF (energy%dispersion /= 0.0_dp) &
1138 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1139 0 : "Dispersion energy: ", energy%dispersion
1140 490 : 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 490 : IF (energy%gcp /= 0.0_dp) &
1144 : WRITE (UNIT=output_unit, FMT="(T3,A,T61,F20.10)") &
1145 0 : "gCP energy: ", energy%gcp
1146 490 : 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 490 : 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 490 : 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 490 : 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 490 : 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 490 : 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 490 : 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 490 : 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 120105 : "DFT%SCF%PRINT%DETAILED_ENERGY")
1192 :
1193 120105 : 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 Build the XC potential matrix for k-point/image-resolved KS matrices.
1253 : !> \param qs_env Quickstep environment
1254 : !> \param v_rspace XC potential on the real-space grid
1255 : !> \param matrix_vxc_kp k-point/image-resolved XC potential matrix
1256 : !> \author
1257 : ! **************************************************************************************************
1258 0 : SUBROUTINE compute_matrix_vxc_kp(qs_env, v_rspace, matrix_vxc_kp)
1259 : TYPE(qs_environment_type), POINTER :: qs_env
1260 : TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN) :: v_rspace
1261 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_vxc_kp
1262 :
1263 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_matrix_vxc_kp'
1264 :
1265 : INTEGER :: handle, img, ispin
1266 : LOGICAL :: gapw
1267 0 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ksmat
1268 0 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp
1269 : TYPE(dft_control_type), POINTER :: dft_control
1270 :
1271 0 : CALL timeset(routineN, handle)
1272 :
1273 : ! create the matrix using matrix_ks as a template
1274 0 : IF (ASSOCIATED(matrix_vxc_kp)) THEN
1275 0 : CALL dbcsr_deallocate_matrix_set(matrix_vxc_kp)
1276 : END IF
1277 0 : CALL get_qs_env(qs_env, dft_control=dft_control, matrix_ks_kp=matrix_ks_kp)
1278 0 : ALLOCATE (matrix_vxc_kp(SIZE(matrix_ks_kp, 1), SIZE(matrix_ks_kp, 2)))
1279 0 : DO img = 1, SIZE(matrix_ks_kp, 2)
1280 0 : DO ispin = 1, SIZE(matrix_ks_kp, 1)
1281 0 : NULLIFY (matrix_vxc_kp(ispin, img)%matrix)
1282 0 : CALL dbcsr_init_p(matrix_vxc_kp(ispin, img)%matrix)
1283 : CALL dbcsr_copy(matrix_vxc_kp(ispin, img)%matrix, matrix_ks_kp(ispin, img)%matrix, &
1284 0 : name="Matrix VXC of spin "//cp_to_string(ispin)//" image "//cp_to_string(img))
1285 0 : CALL dbcsr_set(matrix_vxc_kp(ispin, img)%matrix, 0.0_dp)
1286 : END DO
1287 : END DO
1288 :
1289 : ! and integrate
1290 0 : gapw = dft_control%qs_control%gapw .OR. dft_control%qs_control%gapw_xc
1291 0 : DO ispin = 1, SIZE(matrix_ks_kp, 1)
1292 0 : ksmat => matrix_vxc_kp(ispin, :)
1293 : CALL integrate_v_rspace(v_rspace=v_rspace(ispin), &
1294 : hmat_kp=ksmat, &
1295 : qs_env=qs_env, &
1296 : calculate_forces=.FALSE., &
1297 0 : gapw=gapw)
1298 : ! scale by the volume element... should really become part of integrate_v_rspace
1299 0 : DO img = 1, SIZE(matrix_ks_kp, 2)
1300 0 : CALL dbcsr_scale(matrix_vxc_kp(ispin, img)%matrix, v_rspace(ispin)%pw_grid%dvol)
1301 : END DO
1302 : END DO
1303 :
1304 0 : CALL timestop(handle)
1305 :
1306 0 : END SUBROUTINE compute_matrix_vxc_kp
1307 :
1308 : ! **************************************************************************************************
1309 : !> \brief Sum up all potentials defined on the grid and integrate
1310 : !>
1311 : !> \param qs_env ...
1312 : !> \param ks_matrix ...
1313 : !> \param rho ...
1314 : !> \param my_rho ...
1315 : !> \param vppl_rspace ...
1316 : !> \param v_rspace_new ...
1317 : !> \param v_rspace_new_aux_fit ...
1318 : !> \param v_tau_rspace ...
1319 : !> \param v_tau_rspace_aux_fit ...
1320 : !> \param v_sic_rspace ...
1321 : !> \param v_spin_ddapc_rest_r ...
1322 : !> \param v_sccs_rspace ...
1323 : !> \param v_rspace_embed ...
1324 : !> \param cdft_control ...
1325 : !> \param calculate_forces ...
1326 : !> \par History
1327 : !> - refactoring 04.03.2011 [MI]
1328 : !> - SCCS implementation (16.10.2013,MK)
1329 : !> \author
1330 : ! **************************************************************************************************
1331 110519 : SUBROUTINE sum_up_and_integrate(qs_env, ks_matrix, rho, my_rho, &
1332 : vppl_rspace, v_rspace_new, &
1333 : v_rspace_new_aux_fit, v_tau_rspace, &
1334 : v_tau_rspace_aux_fit, &
1335 : v_sic_rspace, v_spin_ddapc_rest_r, &
1336 : v_sccs_rspace, v_rspace_embed, cdft_control, &
1337 : calculate_forces)
1338 :
1339 : TYPE(qs_environment_type), POINTER :: qs_env
1340 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix
1341 : TYPE(qs_rho_type), POINTER :: rho
1342 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: my_rho
1343 : TYPE(pw_r3d_rs_type), POINTER :: vppl_rspace
1344 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_new, v_rspace_new_aux_fit, &
1345 : v_tau_rspace, v_tau_rspace_aux_fit
1346 : TYPE(pw_r3d_rs_type), POINTER :: v_sic_rspace, v_spin_ddapc_rest_r, &
1347 : v_sccs_rspace
1348 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_embed
1349 : TYPE(cdft_control_type), POINTER :: cdft_control
1350 : LOGICAL, INTENT(in) :: calculate_forces
1351 :
1352 : CHARACTER(LEN=*), PARAMETER :: routineN = 'sum_up_and_integrate'
1353 :
1354 : CHARACTER(LEN=default_string_length) :: basis_type
1355 : INTEGER :: handle, igroup, ikind, img, ispin, &
1356 : nkind, nspins
1357 110519 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1358 : LOGICAL :: do_ppl, gapw, gapw_xc, lrigpw, rigpw, &
1359 : use_work_v_rspace
1360 : REAL(KIND=dp) :: csign, dvol, fadm
1361 : TYPE(admm_type), POINTER :: admm_env
1362 110519 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1363 110519 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ksmat, rho_ao, rho_ao_nokp, smat
1364 110519 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_aux_fit, &
1365 110519 : matrix_ks_aux_fit_dft, rho_ao_aux, &
1366 110519 : rho_ao_kp
1367 : TYPE(dft_control_type), POINTER :: dft_control
1368 : TYPE(kpoint_type), POINTER :: kpoints
1369 : TYPE(lri_density_type), POINTER :: lri_density
1370 : TYPE(lri_environment_type), POINTER :: lri_env
1371 110519 : TYPE(lri_kind_type), DIMENSION(:), POINTER :: lri_v_int
1372 : TYPE(mp_para_env_type), POINTER :: para_env
1373 : TYPE(pw_env_type), POINTER :: pw_env
1374 : TYPE(pw_poisson_type), POINTER :: poisson_env
1375 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1376 : TYPE(pw_r3d_rs_type), POINTER :: v_rspace, v_rspace_used, vee
1377 : TYPE(pw_r3d_rs_type), TARGET :: v_rspace_work
1378 : TYPE(qs_ks_env_type), POINTER :: ks_env
1379 : TYPE(qs_rho_type), POINTER :: rho_aux_fit
1380 : TYPE(task_list_type), POINTER :: task_list
1381 :
1382 110519 : CALL timeset(routineN, handle)
1383 :
1384 110519 : NULLIFY (auxbas_pw_pool, dft_control, pw_env, matrix_ks_aux_fit, &
1385 110519 : v_rspace, rho_aux_fit, vee, rho_ao, rho_ao_kp, rho_ao_aux, &
1386 110519 : ksmat, matrix_ks_aux_fit_dft, lri_env, lri_density, atomic_kind_set, &
1387 110519 : rho_ao_nokp, ks_env, admm_env, task_list, v_rspace_used)
1388 :
1389 : CALL get_qs_env(qs_env, &
1390 : dft_control=dft_control, &
1391 : pw_env=pw_env, &
1392 : v_hartree_rspace=v_rspace, &
1393 110519 : vee=vee)
1394 :
1395 110519 : CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
1396 110519 : CALL pw_env_get(pw_env, poisson_env=poisson_env, auxbas_pw_pool=auxbas_pw_pool)
1397 110519 : gapw = dft_control%qs_control%gapw
1398 110519 : gapw_xc = dft_control%qs_control%gapw_xc
1399 110519 : do_ppl = dft_control%qs_control%do_ppl_method == do_ppl_grid
1400 :
1401 110519 : rigpw = dft_control%qs_control%rigpw
1402 110519 : lrigpw = dft_control%qs_control%lrigpw
1403 110519 : IF (lrigpw .OR. rigpw) THEN
1404 : CALL get_qs_env(qs_env, &
1405 : lri_env=lri_env, &
1406 : lri_density=lri_density, &
1407 454 : atomic_kind_set=atomic_kind_set)
1408 : END IF
1409 :
1410 110519 : nspins = dft_control%nspins
1411 :
1412 : ! sum up potentials and integrate
1413 110519 : IF (ASSOCIATED(v_rspace_new)) THEN
1414 218595 : DO ispin = 1, nspins
1415 118202 : IF (gapw_xc) THEN
1416 : ! SIC not implemented (or at least not tested)
1417 4016 : CPASSERT(dft_control%sic_method_id == sic_none)
1418 : !Only the xc potential, because it has to be integrated with the soft basis
1419 4016 : CALL pw_scale(v_rspace_new(ispin), v_rspace_new(ispin)%pw_grid%dvol)
1420 :
1421 : ! add the xc part due to v_rspace soft
1422 4016 : rho_ao => rho_ao_kp(ispin, :)
1423 4016 : ksmat => ks_matrix(ispin, :)
1424 : CALL integrate_v_rspace(v_rspace=v_rspace_new(ispin), &
1425 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1426 : qs_env=qs_env, &
1427 : calculate_forces=calculate_forces, &
1428 4016 : gapw=gapw_xc)
1429 :
1430 : ! Now the Hartree potential to be integrated with the full basis
1431 4016 : CALL pw_copy(v_rspace, v_rspace_new(ispin))
1432 : ELSE
1433 : ! Add v_hartree + v_xc = v_rspace_new
1434 114186 : CALL pw_axpy(v_rspace, v_rspace_new(ispin), 1.0_dp, v_rspace_new(ispin)%pw_grid%dvol)
1435 : END IF ! gapw_xc
1436 118202 : IF (dft_control%qs_control%ddapc_explicit_potential) THEN
1437 184 : IF (dft_control%qs_control%ddapc_restraint_is_spin) THEN
1438 184 : IF (ispin == 1) THEN
1439 92 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), 1.0_dp)
1440 : ELSE
1441 92 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), -1.0_dp)
1442 : END IF
1443 : ELSE
1444 0 : CALL pw_axpy(v_spin_ddapc_rest_r, v_rspace_new(ispin), 1.0_dp)
1445 : END IF
1446 : END IF
1447 : ! CDFT constraint contribution
1448 118202 : IF (dft_control%qs_control%cdft) THEN
1449 11744 : DO igroup = 1, SIZE(cdft_control%group)
1450 6848 : SELECT CASE (cdft_control%group(igroup)%constraint_type)
1451 : CASE (cdft_charge_constraint)
1452 16 : csign = 1.0_dp
1453 : CASE (cdft_magnetization_constraint)
1454 16 : IF (ispin == 1) THEN
1455 : csign = 1.0_dp
1456 : ELSE
1457 8 : csign = -1.0_dp
1458 : END IF
1459 : CASE (cdft_alpha_constraint)
1460 1944 : csign = 1.0_dp
1461 1944 : IF (ispin == 2) CYCLE
1462 : CASE (cdft_beta_constraint)
1463 1944 : csign = 1.0_dp
1464 1944 : IF (ispin == 1) CYCLE
1465 : CASE DEFAULT
1466 6848 : CPABORT("Unknown constraint type.")
1467 : END SELECT
1468 : CALL pw_axpy(cdft_control%group(igroup)%weight, v_rspace_new(ispin), &
1469 11744 : csign*cdft_control%strength(igroup))
1470 : END DO
1471 : END IF
1472 : ! functional derivative of the Hartree energy wrt the density in the presence of dielectric
1473 : ! (vhartree + v_eps); v_eps is nonzero only if the dielectric constant is defind as a function
1474 : ! of the charge density
1475 118202 : IF (poisson_env%parameters%solver == pw_poisson_implicit) THEN
1476 440 : dvol = poisson_env%implicit_env%v_eps%pw_grid%dvol
1477 440 : CALL pw_axpy(poisson_env%implicit_env%v_eps, v_rspace_new(ispin), dvol)
1478 : END IF
1479 : ! Add SCCS contribution
1480 118202 : IF (dft_control%do_sccs) THEN
1481 132 : CALL pw_axpy(v_sccs_rspace, v_rspace_new(ispin))
1482 : END IF
1483 : ! External electrostatic potential
1484 118202 : IF (dft_control%apply_external_potential) THEN
1485 : CALL qmmm_modify_hartree_pot(v_hartree=v_rspace_new(ispin), &
1486 364 : v_qmmm=vee, scale=-1.0_dp)
1487 : END IF
1488 118202 : IF (do_ppl) THEN
1489 66 : CPASSERT(.NOT. gapw)
1490 66 : CALL pw_axpy(vppl_rspace, v_rspace_new(ispin), vppl_rspace%pw_grid%dvol)
1491 : END IF
1492 : ! the electrostatic sic contribution
1493 118562 : SELECT CASE (dft_control%sic_method_id)
1494 : CASE (sic_none)
1495 : !
1496 : CASE (sic_mauri_us, sic_mauri_spz)
1497 360 : IF (ispin == 1) THEN
1498 180 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), -1.0_dp)
1499 : ELSE
1500 180 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), 1.0_dp)
1501 : END IF
1502 : CASE (sic_ad)
1503 118202 : CALL pw_axpy(v_sic_rspace, v_rspace_new(ispin), -1.0_dp)
1504 : CASE (sic_eo)
1505 : ! NOTHING TO BE DONE
1506 : END SELECT
1507 : ! DFT embedding
1508 118202 : IF (dft_control%apply_embed_pot) THEN
1509 930 : CALL pw_axpy(v_rspace_embed(ispin), v_rspace_new(ispin), v_rspace_embed(ispin)%pw_grid%dvol)
1510 930 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1511 : END IF
1512 118202 : IF (lrigpw) THEN
1513 440 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1514 440 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1515 1316 : DO ikind = 1, nkind
1516 286360 : lri_v_int(ikind)%v_int = 0.0_dp
1517 : END DO
1518 : CALL integrate_v_rspace_one_center(v_rspace_new(ispin), qs_env, &
1519 440 : lri_v_int, calculate_forces, "LRI_AUX")
1520 1316 : DO ikind = 1, nkind
1521 571404 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1522 : END DO
1523 440 : IF (lri_env%exact_1c_terms) THEN
1524 36 : rho_ao => my_rho(ispin, :)
1525 36 : ksmat => ks_matrix(ispin, :)
1526 : CALL integrate_v_rspace_diagonal(v_rspace_new(ispin), ksmat(1)%matrix, &
1527 : rho_ao(1)%matrix, qs_env, &
1528 36 : calculate_forces, "ORB")
1529 : END IF
1530 440 : IF (lri_env%ppl_ri) THEN
1531 8 : CALL v_int_ppl_update(qs_env, lri_v_int, calculate_forces)
1532 : END IF
1533 117762 : ELSEIF (rigpw) THEN
1534 26 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1535 26 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1536 52 : DO ikind = 1, nkind
1537 1144 : lri_v_int(ikind)%v_int = 0.0_dp
1538 : END DO
1539 : CALL integrate_v_rspace_one_center(v_rspace_new(ispin), qs_env, &
1540 26 : lri_v_int, calculate_forces, "RI_HXC")
1541 52 : DO ikind = 1, nkind
1542 2236 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1543 : END DO
1544 : ELSE
1545 117736 : rho_ao => my_rho(ispin, :)
1546 117736 : ksmat => ks_matrix(ispin, :)
1547 : CALL integrate_v_rspace(v_rspace=v_rspace_new(ispin), &
1548 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1549 : qs_env=qs_env, &
1550 : calculate_forces=calculate_forces, &
1551 117736 : gapw=gapw)
1552 : END IF
1553 218595 : CALL auxbas_pw_pool%give_back_pw(v_rspace_new(ispin))
1554 : END DO ! ispin
1555 :
1556 100593 : SELECT CASE (dft_control%sic_method_id)
1557 : CASE (sic_none)
1558 : CASE (sic_mauri_us, sic_mauri_spz, sic_ad)
1559 200 : CALL auxbas_pw_pool%give_back_pw(v_sic_rspace)
1560 100593 : DEALLOCATE (v_sic_rspace)
1561 : END SELECT
1562 100393 : DEALLOCATE (v_rspace_new)
1563 :
1564 : ELSE
1565 : ! not implemented (or at least not tested)
1566 10126 : CPASSERT(dft_control%sic_method_id == sic_none)
1567 10126 : CPASSERT(.NOT. dft_control%qs_control%ddapc_restraint_is_spin)
1568 22428 : DO ispin = 1, nspins
1569 12302 : use_work_v_rspace = dft_control%qs_control%cdft
1570 12302 : IF (use_work_v_rspace) THEN
1571 168 : CALL auxbas_pw_pool%create_pw(v_rspace_work)
1572 168 : CALL pw_copy(v_rspace, v_rspace_work)
1573 168 : v_rspace_used => v_rspace_work
1574 : ELSE
1575 12134 : v_rspace_used => v_rspace
1576 : END IF
1577 : ! CDFT constraint contribution
1578 12302 : IF (dft_control%qs_control%cdft) THEN
1579 336 : DO igroup = 1, SIZE(cdft_control%group)
1580 168 : SELECT CASE (cdft_control%group(igroup)%constraint_type)
1581 : CASE (cdft_charge_constraint)
1582 0 : csign = 1.0_dp
1583 : CASE (cdft_magnetization_constraint)
1584 0 : IF (ispin == 1) THEN
1585 : csign = 1.0_dp
1586 : ELSE
1587 0 : csign = -1.0_dp
1588 : END IF
1589 : CASE (cdft_alpha_constraint)
1590 0 : csign = 1.0_dp
1591 0 : IF (ispin == 2) CYCLE
1592 : CASE (cdft_beta_constraint)
1593 0 : csign = 1.0_dp
1594 0 : IF (ispin == 1) CYCLE
1595 : CASE DEFAULT
1596 168 : CPABORT("Unknown constraint type.")
1597 : END SELECT
1598 : CALL pw_axpy(cdft_control%group(igroup)%weight, v_rspace_used, &
1599 336 : csign*cdft_control%strength(igroup))
1600 : END DO
1601 : END IF
1602 : ! extra contribution attributed to the dependency of the dielectric constant to the charge density
1603 12302 : IF (poisson_env%parameters%solver == pw_poisson_implicit) THEN
1604 0 : dvol = poisson_env%implicit_env%v_eps%pw_grid%dvol
1605 0 : CALL pw_axpy(poisson_env%implicit_env%v_eps, v_rspace_used, dvol)
1606 : END IF
1607 : ! Add SCCS contribution
1608 12302 : IF (dft_control%do_sccs) THEN
1609 0 : CALL pw_axpy(v_sccs_rspace, v_rspace_used)
1610 : END IF
1611 : ! DFT embedding
1612 12302 : IF (dft_control%apply_embed_pot) THEN
1613 12 : CALL pw_axpy(v_rspace_embed(ispin), v_rspace_used, v_rspace_embed(ispin)%pw_grid%dvol)
1614 12 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1615 : END IF
1616 12302 : IF (lrigpw) THEN
1617 0 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1618 0 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1619 0 : DO ikind = 1, nkind
1620 0 : lri_v_int(ikind)%v_int = 0.0_dp
1621 : END DO
1622 : CALL integrate_v_rspace_one_center(v_rspace_used, qs_env, &
1623 0 : lri_v_int, calculate_forces, "LRI_AUX")
1624 0 : DO ikind = 1, nkind
1625 0 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1626 : END DO
1627 0 : IF (lri_env%exact_1c_terms) THEN
1628 0 : rho_ao => my_rho(ispin, :)
1629 0 : ksmat => ks_matrix(ispin, :)
1630 : CALL integrate_v_rspace_diagonal(v_rspace_used, ksmat(1)%matrix, &
1631 : rho_ao(1)%matrix, qs_env, &
1632 0 : calculate_forces, "ORB")
1633 : END IF
1634 0 : IF (lri_env%ppl_ri) THEN
1635 0 : CALL v_int_ppl_update(qs_env, lri_v_int, calculate_forces)
1636 : END IF
1637 12302 : ELSEIF (rigpw) THEN
1638 0 : lri_v_int => lri_density%lri_coefs(ispin)%lri_kinds
1639 0 : CALL get_qs_env(qs_env, nkind=nkind, para_env=para_env)
1640 0 : DO ikind = 1, nkind
1641 0 : lri_v_int(ikind)%v_int = 0.0_dp
1642 : END DO
1643 : CALL integrate_v_rspace_one_center(v_rspace_used, qs_env, &
1644 0 : lri_v_int, calculate_forces, "RI_HXC")
1645 0 : DO ikind = 1, nkind
1646 0 : CALL para_env%sum(lri_v_int(ikind)%v_int)
1647 : END DO
1648 : ELSE
1649 12302 : rho_ao => my_rho(ispin, :)
1650 12302 : ksmat => ks_matrix(ispin, :)
1651 : CALL integrate_v_rspace(v_rspace=v_rspace_used, &
1652 : pmat_kp=rho_ao, &
1653 : hmat_kp=ksmat, &
1654 : qs_env=qs_env, &
1655 : calculate_forces=calculate_forces, &
1656 12302 : gapw=gapw)
1657 : END IF
1658 22428 : IF (use_work_v_rspace) CALL auxbas_pw_pool%give_back_pw(v_rspace_work)
1659 : END DO
1660 : END IF ! ASSOCIATED(v_rspace_new)
1661 :
1662 : ! **** LRIGPW: KS matrix from integrated potential
1663 110519 : IF (lrigpw) THEN
1664 428 : CALL get_qs_env(qs_env, ks_env=ks_env)
1665 428 : CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
1666 428 : CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
1667 868 : DO ispin = 1, nspins
1668 440 : ksmat => ks_matrix(ispin, :)
1669 : CALL calculate_lri_ks_matrix(lri_env, lri_v_int, ksmat, atomic_kind_set, &
1670 868 : cell_to_index=cell_to_index)
1671 : END DO
1672 428 : IF (calculate_forces) THEN
1673 24 : CALL calculate_lri_forces(lri_env, lri_density, qs_env, rho_ao_kp, atomic_kind_set)
1674 : END IF
1675 110091 : ELSEIF (rigpw) THEN
1676 26 : CALL get_qs_env(qs_env, matrix_s=smat)
1677 52 : DO ispin = 1, nspins
1678 : CALL calculate_ri_ks_matrix(lri_env, lri_v_int, ks_matrix(ispin, 1)%matrix, &
1679 52 : smat(1)%matrix, atomic_kind_set, ispin)
1680 : END DO
1681 26 : IF (calculate_forces) THEN
1682 2 : rho_ao_nokp => rho_ao_kp(:, 1)
1683 2 : CALL calculate_ri_forces(lri_env, lri_density, qs_env, rho_ao_nokp, atomic_kind_set)
1684 : END IF
1685 : END IF
1686 :
1687 110519 : IF (ASSOCIATED(v_tau_rspace)) THEN
1688 2562 : IF (lrigpw .OR. rigpw) THEN
1689 0 : CPABORT("LRIGPW/RIGPW not implemented for meta-GGAs")
1690 : END IF
1691 5564 : DO ispin = 1, nspins
1692 3002 : CALL pw_scale(v_tau_rspace(ispin), v_tau_rspace(ispin)%pw_grid%dvol)
1693 :
1694 3002 : rho_ao => rho_ao_kp(ispin, :)
1695 3002 : ksmat => ks_matrix(ispin, :)
1696 : CALL integrate_v_rspace(v_rspace=v_tau_rspace(ispin), &
1697 : pmat_kp=rho_ao, hmat_kp=ksmat, &
1698 : qs_env=qs_env, &
1699 : calculate_forces=calculate_forces, compute_tau=.TRUE., &
1700 3002 : gapw=gapw)
1701 5564 : CALL auxbas_pw_pool%give_back_pw(v_tau_rspace(ispin))
1702 : END DO
1703 2562 : DEALLOCATE (v_tau_rspace)
1704 : END IF
1705 :
1706 : ! Add contributions from ADMM if requested
1707 110519 : IF (dft_control%do_admm) THEN
1708 11712 : CALL get_qs_env(qs_env, admm_env=admm_env)
1709 : CALL get_admm_env(admm_env, matrix_ks_aux_fit_kp=matrix_ks_aux_fit, rho_aux_fit=rho_aux_fit, &
1710 11712 : matrix_ks_aux_fit_dft_kp=matrix_ks_aux_fit_dft)
1711 11712 : CALL qs_rho_get(rho_aux_fit, rho_ao_kp=rho_ao_aux)
1712 11712 : IF (ASSOCIATED(v_rspace_new_aux_fit)) THEN
1713 17672 : DO ispin = 1, nspins
1714 : ! Calculate the xc potential
1715 9642 : CALL pw_scale(v_rspace_new_aux_fit(ispin), v_rspace_new_aux_fit(ispin)%pw_grid%dvol)
1716 :
1717 : ! set matrix_ks_aux_fit_dft = matrix_ks_aux_fit(k_HF)
1718 24304 : DO img = 1, dft_control%nimages
1719 : CALL dbcsr_copy(matrix_ks_aux_fit_dft(ispin, img)%matrix, matrix_ks_aux_fit(ispin, img)%matrix, &
1720 24304 : name="DFT exch. part of matrix_ks_aux_fit")
1721 : END DO
1722 :
1723 : ! Add potential to ks_matrix aux_fit, skip integration if no DFT correction
1724 :
1725 9642 : IF (admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
1726 :
1727 : !GPW by default. IF GAPW, then take relevant task list and basis
1728 9642 : CALL get_admm_env(admm_env, task_list_aux_fit=task_list)
1729 9642 : basis_type = "AUX_FIT"
1730 9642 : IF (admm_env%do_gapw) THEN
1731 3242 : task_list => admm_env%admm_gapw_env%task_list
1732 3242 : basis_type = "AUX_FIT_SOFT"
1733 : END IF
1734 9642 : fadm = 1.0_dp
1735 : ! Calculate bare scaling of force according to Merlot, 1. IF: ADMMP, 2. IF: ADMMS,
1736 9642 : IF (admm_env%do_admmp) THEN
1737 442 : fadm = admm_env%gsi(ispin)**2
1738 9200 : ELSE IF (admm_env%do_admms) THEN
1739 478 : fadm = (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)
1740 : END IF
1741 :
1742 9642 : rho_ao => rho_ao_aux(ispin, :)
1743 9642 : ksmat => matrix_ks_aux_fit(ispin, :)
1744 :
1745 : CALL integrate_v_rspace(v_rspace=v_rspace_new_aux_fit(ispin), &
1746 : pmat_kp=rho_ao, &
1747 : hmat_kp=ksmat, &
1748 : qs_env=qs_env, &
1749 : calculate_forces=calculate_forces, &
1750 : force_adm=fadm, &
1751 : gapw=.FALSE., & !even if actual GAPW calculation, want to use AUX_FIT_SOFT
1752 : basis_type=basis_type, &
1753 9642 : task_list_external=task_list)
1754 : END IF
1755 :
1756 : ! matrix_ks_aux_fit_dft(x_DFT)=matrix_ks_aux_fit_dft(old,k_HF)-matrix_ks_aux_fit(k_HF-x_DFT)
1757 24304 : DO img = 1, dft_control%nimages
1758 : CALL dbcsr_add(matrix_ks_aux_fit_dft(ispin, img)%matrix, &
1759 24304 : matrix_ks_aux_fit(ispin, img)%matrix, 1.0_dp, -1.0_dp)
1760 : END DO
1761 :
1762 17672 : CALL auxbas_pw_pool%give_back_pw(v_rspace_new_aux_fit(ispin))
1763 : END DO
1764 8030 : DEALLOCATE (v_rspace_new_aux_fit)
1765 : END IF
1766 : ! Clean up v_tau_rspace_aux_fit, which is actually not needed
1767 11712 : IF (ASSOCIATED(v_tau_rspace_aux_fit)) THEN
1768 0 : DO ispin = 1, nspins
1769 0 : CALL auxbas_pw_pool%give_back_pw(v_tau_rspace_aux_fit(ispin))
1770 : END DO
1771 0 : DEALLOCATE (v_tau_rspace_aux_fit)
1772 : END IF
1773 : END IF
1774 :
1775 110519 : IF (dft_control%apply_embed_pot) DEALLOCATE (v_rspace_embed)
1776 :
1777 110519 : CALL timestop(handle)
1778 :
1779 110519 : END SUBROUTINE sum_up_and_integrate
1780 :
1781 : !**************************************************************************
1782 : !> \brief Calculate the ZMP potential and energy as in Zhao, Morrison Parr
1783 : !> PRA 50i, 2138 (1994)
1784 : !> V_c^\lambda defined as int_rho-rho_0/r-r' or rho-rho_0 times a Lagrange
1785 : !> multiplier, plus Fermi-Amaldi potential that should give the V_xc in the
1786 : !> limit \lambda --> \infty
1787 : !>
1788 : !> \param qs_env ...
1789 : !> \param v_rspace_new ...
1790 : !> \param rho ...
1791 : !> \param exc ...
1792 : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
1793 : ! **************************************************************************************************
1794 0 : SUBROUTINE calculate_zmp_potential(qs_env, v_rspace_new, rho, exc)
1795 :
1796 : TYPE(qs_environment_type), POINTER :: qs_env
1797 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_new
1798 : TYPE(qs_rho_type), POINTER :: rho
1799 : REAL(KIND=dp) :: exc
1800 :
1801 : CHARACTER(*), PARAMETER :: routineN = 'calculate_zmp_potential'
1802 :
1803 : INTEGER :: handle, my_val, nelectron, nspins
1804 : INTEGER, DIMENSION(2) :: nelectron_spin
1805 : LOGICAL :: do_zmp_read, fermi_amaldi
1806 : REAL(KIND=dp) :: lambda
1807 0 : REAL(KIND=dp), DIMENSION(:), POINTER :: tot_rho_ext_r
1808 : TYPE(dft_control_type), POINTER :: dft_control
1809 0 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_ext_g, rho_g
1810 : TYPE(pw_env_type), POINTER :: pw_env
1811 : TYPE(pw_poisson_type), POINTER :: poisson_env
1812 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1813 : TYPE(pw_r3d_rs_type) :: v_xc_rspace
1814 0 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
1815 : TYPE(qs_ks_env_type), POINTER :: ks_env
1816 : TYPE(section_vals_type), POINTER :: ext_den_section, input
1817 :
1818 : !, v_h_gspace, &
1819 :
1820 0 : CALL timeset(routineN, handle)
1821 0 : NULLIFY (auxbas_pw_pool)
1822 0 : NULLIFY (pw_env)
1823 0 : NULLIFY (poisson_env)
1824 0 : NULLIFY (v_rspace_new)
1825 0 : NULLIFY (dft_control)
1826 0 : NULLIFY (rho_r, rho_g, tot_rho_ext_r, rho_ext_g)
1827 : CALL get_qs_env(qs_env=qs_env, &
1828 : pw_env=pw_env, &
1829 : ks_env=ks_env, &
1830 : rho=rho, &
1831 : input=input, &
1832 : nelectron_spin=nelectron_spin, &
1833 0 : dft_control=dft_control)
1834 : CALL pw_env_get(pw_env=pw_env, &
1835 : auxbas_pw_pool=auxbas_pw_pool, &
1836 0 : poisson_env=poisson_env)
1837 0 : CALL qs_rho_get(rho, rho_r=rho_r, rho_g=rho_g)
1838 0 : nspins = 1
1839 0 : ALLOCATE (v_rspace_new(nspins))
1840 0 : CALL auxbas_pw_pool%create_pw(pw=v_rspace_new(1))
1841 0 : CALL auxbas_pw_pool%create_pw(pw=v_xc_rspace)
1842 :
1843 0 : CALL pw_zero(v_rspace_new(1))
1844 0 : do_zmp_read = dft_control%apply_external_vxc
1845 0 : IF (do_zmp_read) THEN
1846 0 : CALL pw_copy(qs_env%external_vxc, v_rspace_new(1))
1847 : exc = accurate_dot_product(v_rspace_new(1)%array, rho_r(1)%array)* &
1848 0 : v_rspace_new(1)%pw_grid%dvol
1849 : ELSE
1850 0 : BLOCK
1851 : REAL(KIND=dp) :: factor
1852 : TYPE(pw_c1d_gs_type) :: rho_eff_gspace, v_xc_gspace
1853 0 : CALL auxbas_pw_pool%create_pw(pw=rho_eff_gspace)
1854 0 : CALL auxbas_pw_pool%create_pw(pw=v_xc_gspace)
1855 0 : CALL pw_zero(rho_eff_gspace)
1856 0 : CALL pw_zero(v_xc_gspace)
1857 0 : CALL pw_zero(v_xc_rspace)
1858 0 : factor = pw_integrate_function(rho_g(1))
1859 : CALL qs_rho_get(qs_env%rho_external, &
1860 : rho_g=rho_ext_g, &
1861 0 : tot_rho_r=tot_rho_ext_r)
1862 0 : factor = tot_rho_ext_r(1)/factor
1863 :
1864 0 : CALL pw_axpy(rho_g(1), rho_eff_gspace, alpha=factor)
1865 0 : CALL pw_axpy(rho_ext_g(1), rho_eff_gspace, alpha=-1.0_dp)
1866 0 : ext_den_section => section_vals_get_subs_vals(input, "DFT%EXTERNAL_DENSITY")
1867 0 : CALL section_vals_val_get(ext_den_section, "LAMBDA", r_val=lambda)
1868 0 : CALL section_vals_val_get(ext_den_section, "ZMP_CONSTRAINT", i_val=my_val)
1869 0 : CALL section_vals_val_get(ext_den_section, "FERMI_AMALDI", l_val=fermi_amaldi)
1870 :
1871 0 : CALL pw_scale(rho_eff_gspace, a=lambda)
1872 0 : nelectron = nelectron_spin(1)
1873 0 : factor = -1.0_dp/nelectron
1874 0 : CALL pw_axpy(rho_g(1), rho_eff_gspace, alpha=factor)
1875 :
1876 0 : CALL pw_poisson_solve(poisson_env, rho_eff_gspace, vhartree=v_xc_gspace)
1877 0 : CALL pw_transfer(v_xc_gspace, v_rspace_new(1))
1878 0 : CALL pw_copy(v_rspace_new(1), v_xc_rspace)
1879 :
1880 0 : exc = 0.0_dp
1881 0 : exc = pw_integral_ab(v_rspace_new(1), rho_r(1))
1882 :
1883 : !Note that this is not the xc energy but \int(\rho*v_xc)
1884 : !Vxc---> v_rspace_new
1885 : !Exc---> energy%exc
1886 0 : CALL auxbas_pw_pool%give_back_pw(rho_eff_gspace)
1887 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_gspace)
1888 : END BLOCK
1889 : END IF
1890 :
1891 0 : CALL auxbas_pw_pool%give_back_pw(v_xc_rspace)
1892 :
1893 0 : CALL timestop(handle)
1894 :
1895 0 : END SUBROUTINE calculate_zmp_potential
1896 :
1897 : ! **************************************************************************************************
1898 : !> \brief ...
1899 : !> \param qs_env ...
1900 : !> \param rho ...
1901 : !> \param v_rspace_embed ...
1902 : !> \param dft_control ...
1903 : !> \param embed_corr ...
1904 : !> \param just_energy ...
1905 : ! **************************************************************************************************
1906 868 : SUBROUTINE get_embed_potential_energy(qs_env, rho, v_rspace_embed, dft_control, embed_corr, &
1907 : just_energy)
1908 : TYPE(qs_environment_type), POINTER :: qs_env
1909 : TYPE(qs_rho_type), POINTER :: rho
1910 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_rspace_embed
1911 : TYPE(dft_control_type), POINTER :: dft_control
1912 : REAL(KIND=dp) :: embed_corr
1913 : LOGICAL :: just_energy
1914 :
1915 : CHARACTER(*), PARAMETER :: routineN = 'get_embed_potential_energy'
1916 :
1917 : INTEGER :: handle, ispin
1918 : REAL(KIND=dp) :: embed_corr_local
1919 : TYPE(pw_env_type), POINTER :: pw_env
1920 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1921 868 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
1922 :
1923 868 : CALL timeset(routineN, handle)
1924 :
1925 868 : NULLIFY (auxbas_pw_pool)
1926 868 : NULLIFY (pw_env)
1927 868 : NULLIFY (rho_r)
1928 : CALL get_qs_env(qs_env=qs_env, &
1929 : pw_env=pw_env, &
1930 868 : rho=rho)
1931 : CALL pw_env_get(pw_env=pw_env, &
1932 868 : auxbas_pw_pool=auxbas_pw_pool)
1933 868 : CALL qs_rho_get(rho, rho_r=rho_r)
1934 3952 : ALLOCATE (v_rspace_embed(dft_control%nspins))
1935 :
1936 868 : embed_corr = 0.0_dp
1937 :
1938 2216 : DO ispin = 1, dft_control%nspins
1939 1348 : CALL auxbas_pw_pool%create_pw(pw=v_rspace_embed(ispin))
1940 1348 : CALL pw_zero(v_rspace_embed(ispin))
1941 :
1942 1348 : CALL pw_copy(qs_env%embed_pot, v_rspace_embed(ispin))
1943 1348 : embed_corr_local = 0.0_dp
1944 :
1945 : ! Spin embedding potential in open-shell case
1946 1348 : IF (dft_control%nspins == 2) THEN
1947 960 : IF (ispin == 1) CALL pw_axpy(qs_env%spin_embed_pot, v_rspace_embed(ispin), 1.0_dp)
1948 960 : IF (ispin == 2) CALL pw_axpy(qs_env%spin_embed_pot, v_rspace_embed(ispin), -1.0_dp)
1949 : END IF
1950 : ! Integrate the density*potential
1951 1348 : embed_corr_local = pw_integral_ab(v_rspace_embed(ispin), rho_r(ispin))
1952 :
1953 2216 : embed_corr = embed_corr + embed_corr_local
1954 :
1955 : END DO
1956 :
1957 : ! If only energy requiested we delete the potential
1958 868 : IF (just_energy) THEN
1959 692 : DO ispin = 1, dft_control%nspins
1960 692 : CALL auxbas_pw_pool%give_back_pw(v_rspace_embed(ispin))
1961 : END DO
1962 286 : DEALLOCATE (v_rspace_embed)
1963 : END IF
1964 :
1965 868 : CALL timestop(handle)
1966 :
1967 868 : END SUBROUTINE get_embed_potential_energy
1968 :
1969 : END MODULE qs_ks_utils
|