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 : MODULE xc_atom
10 :
11 : USE cp_linked_list_xc_deriv, ONLY: cp_sll_xc_deriv_next,&
12 : cp_sll_xc_deriv_type
13 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
14 : section_vals_type
15 : USE kinds, ONLY: dp
16 : USE pw_pool_types, ONLY: pw_pool_type
17 : USE pw_types, ONLY: pw_r3d_rs_type
18 : USE xc, ONLY: divide_by_norm_drho,&
19 : xc_calc_2nd_deriv_analytical
20 : USE xc_derivative_desc, ONLY: &
21 : deriv_norm_drho, deriv_norm_drhoa, deriv_norm_drhob, deriv_rho, deriv_rhoa, deriv_rhob, &
22 : deriv_tau, deriv_tau_a, deriv_tau_b
23 : USE xc_derivative_set_types, ONLY: xc_derivative_set_type,&
24 : xc_dset_get_derivative
25 : USE xc_derivative_types, ONLY: xc_derivative_get,&
26 : xc_derivative_type
27 : USE xc_derivatives, ONLY: xc_functionals_eval
28 : USE xc_rho_cflags_types, ONLY: xc_rho_cflags_type
29 : USE xc_rho_set_types, ONLY: xc_rho_set_get,&
30 : xc_rho_set_type
31 : #include "../base/base_uses.f90"
32 :
33 : IMPLICIT NONE
34 :
35 : PRIVATE
36 :
37 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_atom'
38 :
39 : PUBLIC :: vxc_of_r_new, vxc_of_r_epr, xc_rho_set_atom_update, xc_2nd_deriv_of_r, fill_rho_set
40 :
41 : CONTAINS
42 :
43 : ! **************************************************************************************************
44 : !> \brief ...
45 : !> \param xc_fun_section ...
46 : !> \param rho_set ...
47 : !> \param deriv_set ...
48 : !> \param deriv_order ...
49 : !> \param needs ...
50 : !> \param w ...
51 : !> \param lsd ...
52 : !> \param na ...
53 : !> \param nr ...
54 : !> \param exc ...
55 : !> \param vxc ...
56 : !> \param vxg ...
57 : !> \param vtau ...
58 : !> \param energy_only ...
59 : !> \param adiabatic_rescale_factor ...
60 : ! **************************************************************************************************
61 65908 : SUBROUTINE vxc_of_r_new(xc_fun_section, rho_set, deriv_set, deriv_order, needs, w, &
62 : lsd, na, nr, exc, vxc, vxg, vtau, &
63 : energy_only, adiabatic_rescale_factor)
64 :
65 : ! This routine updates rho_set by giving to it the rho and drho that are needed.
66 : ! Since for the local densities rho1_h and rho1_s local grids are used it is not possible
67 : ! to call xc_rho_set_update.
68 : ! As input of this routine one gets rho and drho on a one dimensional grid.
69 : ! The grid is the angular grid corresponding to a given point ir_pnt on the radial grid.
70 : ! The derivatives are calculated on this one dimensional grid, the results are stored in
71 : ! exc, vxc(1:na,ir_pnt,ispin), vxg(1:na,ir_pnt,ispin), vxg_cross(1:na,ir_pnt,ispin)
72 : ! Afterwords the arrays containing the derivatives are put to zero so that the routine
73 : ! can safely be called for the next radial point ir_pnt
74 :
75 : TYPE(section_vals_type), POINTER :: xc_fun_section
76 : TYPE(xc_rho_set_type), INTENT(IN) :: rho_set
77 : TYPE(xc_derivative_set_type), INTENT(IN) :: deriv_set
78 : INTEGER, INTENT(in) :: deriv_order
79 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
80 : REAL(dp), DIMENSION(:, :), INTENT(IN) :: w
81 : LOGICAL, INTENT(IN) :: lsd
82 : INTEGER, INTENT(in) :: na, nr
83 : REAL(dp) :: exc
84 : REAL(dp), DIMENSION(:, :, :), POINTER :: vxc
85 : REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
86 : REAL(dp), DIMENSION(:, :, :), POINTER :: vtau
87 : LOGICAL, INTENT(IN), OPTIONAL :: energy_only
88 : REAL(dp), INTENT(IN), OPTIONAL :: adiabatic_rescale_factor
89 :
90 : CHARACTER(LEN=*), PARAMETER :: routineN = 'vxc_of_r_new'
91 :
92 : INTEGER :: handle, ia, idir, ir
93 : LOGICAL :: gradient_f, my_only_energy
94 : REAL(dp) :: my_adiabatic_rescale_factor
95 65908 : REAL(dp), DIMENSION(:, :, :), POINTER :: deriv_data
96 : REAL(KIND=dp) :: drho_cutoff
97 : TYPE(xc_derivative_type), POINTER :: deriv_att
98 :
99 65908 : CALL timeset(routineN, handle)
100 65908 : my_only_energy = .FALSE.
101 65908 : IF (PRESENT(energy_only)) my_only_energy = energy_only
102 :
103 65908 : IF (PRESENT(adiabatic_rescale_factor)) THEN
104 65908 : my_adiabatic_rescale_factor = adiabatic_rescale_factor
105 : ELSE
106 : my_adiabatic_rescale_factor = 1.0_dp
107 : END IF
108 :
109 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
110 65908 : needs%drho .OR. needs%norm_drho)
111 :
112 : ! Calculate the derivatives
113 : CALL xc_functionals_eval(xc_fun_section, &
114 : lsd=lsd, &
115 : rho_set=rho_set, &
116 : deriv_set=deriv_set, &
117 65908 : deriv_order=deriv_order)
118 :
119 65908 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
120 :
121 65908 : NULLIFY (deriv_data)
122 :
123 : ! EXC energy
124 65908 : deriv_att => xc_dset_get_derivative(deriv_set, [INTEGER::])
125 65908 : exc = 0.0_dp
126 65908 : IF (ASSOCIATED(deriv_att)) THEN
127 65836 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
128 3698716 : DO ir = 1, nr
129 185511196 : DO ia = 1, na
130 185445360 : exc = exc + deriv_data(ia, ir, 1)*w(ia, ir)
131 : END DO
132 : END DO
133 65836 : NULLIFY (deriv_data)
134 : END IF
135 : ! Calculate the potential only if needed
136 65908 : IF (.NOT. my_only_energy) THEN
137 : ! Derivative with respect to the density
138 62884 : IF (lsd) THEN
139 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhoa])
140 8292 : IF (ASSOCIATED(deriv_att)) THEN
141 8288 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
142 54816496 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
143 8288 : NULLIFY (deriv_data)
144 : END IF
145 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhob])
146 8292 : IF (ASSOCIATED(deriv_att)) THEN
147 8288 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
148 54816496 : vxc(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
149 8288 : NULLIFY (deriv_data)
150 : END IF
151 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
152 8292 : IF (ASSOCIATED(deriv_att)) THEN
153 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
154 0 : vxc(:, :, 1) = vxc(:, :, 1) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
155 0 : vxc(:, :, 2) = vxc(:, :, 2) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
156 0 : NULLIFY (deriv_data)
157 : END IF
158 : ELSE
159 54592 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
160 54592 : IF (ASSOCIATED(deriv_att)) THEN
161 54524 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
162 299390248 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
163 54524 : NULLIFY (deriv_data)
164 : END IF
165 : END IF ! lsd
166 :
167 : ! Derivatives with respect to the gradient
168 62884 : IF (lsd) THEN
169 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa])
170 8292 : IF (ASSOCIATED(deriv_att)) THEN
171 4854 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
172 262834 : DO ir = 1, nr
173 13150314 : DO ia = 1, na
174 51807900 : DO idir = 1, 3
175 51549920 : IF (rho_set%norm_drhoa(ia, ir, 1) > drho_cutoff) THEN
176 : vxg(idir, ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)* &
177 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
178 33153096 : rho_set%norm_drhoa(ia, ir, 1)*my_adiabatic_rescale_factor
179 : ELSE
180 5509344 : vxg(idir, ia, ir, 1) = 0.0_dp
181 : END IF
182 : END DO
183 : END DO
184 : END DO
185 4854 : NULLIFY (deriv_data)
186 : END IF
187 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob])
188 8292 : IF (ASSOCIATED(deriv_att)) THEN
189 4854 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
190 262834 : DO ir = 1, nr
191 13150314 : DO ia = 1, na
192 51807900 : DO idir = 1, 3
193 51549920 : IF (rho_set%norm_drhob(ia, ir, 1) > drho_cutoff) THEN
194 : vxg(idir, ia, ir, 2) = rho_set%drhob(idir)%array(ia, ir, 1)* &
195 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
196 32497800 : rho_set%norm_drhob(ia, ir, 1)*my_adiabatic_rescale_factor
197 : ELSE
198 6164640 : vxg(idir, ia, ir, 2) = 0.0_dp
199 : END IF
200 : END DO
201 : END DO
202 : END DO
203 4854 : NULLIFY (deriv_data)
204 : END IF
205 : ! Cross Terms
206 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
207 8292 : IF (ASSOCIATED(deriv_att)) THEN
208 4806 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
209 260386 : DO ir = 1, nr
210 13027866 : DO ia = 1, na
211 51325500 : DO idir = 1, 3
212 51069920 : IF (rho_set%norm_drho(ia, ir, 1) > drho_cutoff) THEN
213 : vxg(idir, ia, ir, 1:2) = &
214 : vxg(idir, ia, ir, 1:2) + ( &
215 : rho_set%drhoa(idir)%array(ia, ir, 1) + &
216 : rho_set%drhob(idir)%array(ia, ir, 1))* &
217 : deriv_data(ia, ir, 1)*w(ia, ir)/rho_set%norm_drho(ia, ir, 1)* &
218 98627004 : my_adiabatic_rescale_factor
219 : END IF
220 : END DO
221 : END DO
222 : END DO
223 4806 : NULLIFY (deriv_data)
224 : END IF
225 : ELSE
226 54592 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
227 54592 : IF (ASSOCIATED(deriv_att)) THEN
228 33554 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
229 1730854 : DO ir = 1, nr
230 86775854 : DO ia = 1, na
231 86742300 : IF (rho_set%norm_drho(ia, ir, 1) > drho_cutoff) THEN
232 293366904 : DO idir = 1, 3
233 : vxg(idir, ia, ir, 1) = rho_set%drho(idir)%array(ia, ir, 1)* &
234 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
235 293366904 : rho_set%norm_drho(ia, ir, 1)*my_adiabatic_rescale_factor
236 : END DO
237 : ELSE
238 46813096 : vxg(1:3, ia, ir, 1) = 0.0_dp
239 : END IF
240 : END DO
241 : END DO
242 33554 : NULLIFY (deriv_data)
243 : END IF
244 : END IF ! lsd
245 : ! Derivative with respect to tau
246 62884 : IF (lsd) THEN
247 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_a])
248 8292 : IF (ASSOCIATED(deriv_att)) THEN
249 16 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
250 81632 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
251 16 : NULLIFY (deriv_data)
252 : END IF
253 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_b])
254 8292 : IF (ASSOCIATED(deriv_att)) THEN
255 16 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
256 81632 : vtau(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
257 16 : NULLIFY (deriv_data)
258 : END IF
259 8292 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
260 8292 : IF (ASSOCIATED(deriv_att)) THEN
261 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
262 0 : vtau(:, :, 1) = vtau(:, :, 1) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
263 0 : vtau(:, :, 2) = vtau(:, :, 2) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
264 0 : NULLIFY (deriv_data)
265 : END IF
266 : ELSE
267 54592 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
268 54592 : IF (ASSOCIATED(deriv_att)) THEN
269 936 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
270 5415072 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
271 936 : NULLIFY (deriv_data)
272 : END IF
273 : END IF ! lsd
274 : END IF ! only_energy
275 :
276 65908 : CALL timestop(handle)
277 :
278 65908 : END SUBROUTINE vxc_of_r_new
279 :
280 : ! **************************************************************************************************
281 : !> \brief Specific EPR version of vxc_of_r_new
282 : !> \param xc_fun_section ...
283 : !> \param rho_set ...
284 : !> \param deriv_set ...
285 : !> \param needs ...
286 : !> \param w ...
287 : !> \param lsd ...
288 : !> \param na ...
289 : !> \param nr ...
290 : !> \param exc ...
291 : !> \param vxc ...
292 : !> \param vxg ...
293 : !> \param vtau ...
294 : ! **************************************************************************************************
295 30 : SUBROUTINE vxc_of_r_epr(xc_fun_section, rho_set, deriv_set, needs, w, &
296 : lsd, na, nr, exc, vxc, vxg, vtau)
297 :
298 : TYPE(section_vals_type), POINTER :: xc_fun_section
299 : TYPE(xc_rho_set_type), INTENT(IN) :: rho_set
300 : TYPE(xc_derivative_set_type), INTENT(IN) :: deriv_set
301 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
302 : REAL(dp), DIMENSION(:, :), INTENT(IN) :: w
303 : LOGICAL, INTENT(IN) :: lsd
304 : INTEGER, INTENT(in) :: na, nr
305 : REAL(dp) :: exc
306 : REAL(dp), DIMENSION(:, :, :), POINTER :: vxc
307 : REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
308 : REAL(dp), DIMENSION(:, :, :), POINTER :: vtau
309 :
310 : CHARACTER(LEN=*), PARAMETER :: routineN = 'vxc_of_r_epr'
311 :
312 : INTEGER :: handle, ia, idir, ir, my_deriv_order
313 : LOGICAL :: gradient_f
314 : REAL(dp) :: my_adiabatic_rescale_factor
315 30 : REAL(dp), DIMENSION(:, :, :), POINTER :: deriv_data
316 : REAL(KIND=dp) :: drho_cutoff
317 : TYPE(xc_derivative_type), POINTER :: deriv_att
318 :
319 30 : CALL timeset(routineN, handle)
320 :
321 : MARK_USED(vxc)
322 : MARK_USED(vtau)
323 :
324 30 : my_adiabatic_rescale_factor = 1.0_dp
325 30 : my_deriv_order = 2
326 :
327 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
328 30 : needs%drho .OR. needs%norm_drho)
329 :
330 : ! Calculate the derivatives
331 : CALL xc_functionals_eval(xc_fun_section, &
332 : lsd=lsd, &
333 : rho_set=rho_set, &
334 : deriv_set=deriv_set, &
335 30 : deriv_order=my_deriv_order)
336 :
337 30 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
338 :
339 30 : NULLIFY (deriv_data)
340 :
341 : ! nabla v_xc (using the vxg arrays)
342 : ! there's no point doing this when lsd = false
343 30 : IF (lsd) THEN
344 30 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhoa])
345 30 : IF (ASSOCIATED(deriv_att)) THEN
346 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
347 1530 : DO ir = 1, nr
348 76530 : DO ia = 1, na
349 301500 : DO idir = 1, 3
350 : vxg(idir, ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)* &
351 300000 : deriv_data(ia, ir, 1)
352 : END DO !idir
353 : END DO !ia
354 : END DO !ir
355 30 : NULLIFY (deriv_data)
356 : END IF
357 30 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhob, deriv_rhob])
358 30 : IF (ASSOCIATED(deriv_att)) THEN
359 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
360 1530 : DO ir = 1, nr
361 76530 : DO ia = 1, na
362 301500 : DO idir = 1, 3
363 : vxg(idir, ia, ir, 2) = rho_set%drhob(idir)%array(ia, ir, 1)* &
364 300000 : deriv_data(ia, ir, 1)
365 : END DO !idir
366 : END DO !ia
367 : END DO !ir
368 30 : NULLIFY (deriv_data)
369 : END IF
370 : END IF
371 : ! EXC energy ! is that needed for epr?
372 30 : deriv_att => xc_dset_get_derivative(deriv_set, [INTEGER::])
373 30 : exc = 0.0_dp
374 30 : IF (ASSOCIATED(deriv_att)) THEN
375 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
376 1530 : DO ir = 1, nr
377 76530 : DO ia = 1, na
378 76500 : exc = exc + deriv_data(ia, ir, 1)*w(ia, ir)
379 : END DO
380 : END DO
381 30 : NULLIFY (deriv_data)
382 : END IF
383 :
384 30 : CALL timestop(handle)
385 :
386 30 : END SUBROUTINE vxc_of_r_epr
387 :
388 : ! **************************************************************************************************
389 : !> \brief ...
390 : !> \param rho_set ...
391 : !> \param rho1_set ...
392 : !> \param xc_section ...
393 : !> \param deriv_set ...
394 : !> \param w ...
395 : !> \param vxc ...
396 : !> \param vxg ...
397 : !> \param do_triplet ...
398 : !> \param do_sf ...
399 : ! **************************************************************************************************
400 19068 : SUBROUTINE xc_2nd_deriv_of_r(rho_set, rho1_set, xc_section, &
401 19068 : deriv_set, w, vxc, vxg, do_triplet, do_sf)
402 :
403 : ! As input of this routine one gets rho and drho on a one dimensional grid.
404 : ! The grid is the angular grid corresponding to a given point ir on the radial grid.
405 : ! The derivatives are calculated on this one dimensional grid, the results are stored in
406 : ! vxc(1:na,ir,ispin), vxg(1:na,ir,ispin), vxg_cross(1:na,ir,ispin)
407 : ! Afterwords the arrays containing the derivatives are put to zero so that the routine
408 : ! can safely be called for the next radial point ir
409 :
410 : TYPE(xc_rho_set_type), INTENT(IN) :: rho_set, rho1_set
411 : TYPE(section_vals_type), POINTER :: xc_section
412 : TYPE(xc_derivative_set_type), INTENT(INOUT) :: deriv_set
413 : REAL(dp), DIMENSION(:, :), INTENT(IN) :: w
414 : REAL(dp), CONTIGUOUS, DIMENSION(:, :, :), POINTER :: vxc
415 : REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
416 : LOGICAL, INTENT(IN), OPTIONAL :: do_triplet, do_sf
417 :
418 : CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_2nd_deriv_of_r'
419 :
420 : INTEGER :: handle, ispin, nspins
421 : LOGICAL :: lsd, my_do_sf
422 : REAL(dp) :: drho_cutoff, my_fac_triplet
423 : TYPE(cp_sll_xc_deriv_type), POINTER :: pos
424 : TYPE(pw_pool_type), POINTER :: pw_pool
425 19068 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: vxc_pw, vxc_tau_pw
426 : TYPE(section_vals_type), POINTER :: xc_fun_section
427 : TYPE(xc_derivative_type), POINTER :: deriv_att
428 :
429 19068 : CALL timeset(routineN, handle)
430 :
431 19068 : nspins = SIZE(vxc, 3)
432 19068 : lsd = (nspins == 2)
433 19068 : IF (ASSOCIATED(rho_set%rhoa)) THEN
434 1402 : lsd = .TRUE.
435 : END IF
436 19068 : my_fac_triplet = 1.0_dp
437 19068 : IF (PRESENT(do_triplet)) THEN
438 18720 : IF (do_triplet) my_fac_triplet = -1.0_dp
439 : END IF
440 :
441 19068 : my_do_sf = .FALSE.
442 19068 : IF (PRESENT(do_sf)) my_do_sf = do_sf
443 :
444 19068 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
445 : xc_fun_section => section_vals_get_subs_vals(xc_section, &
446 19068 : "XC_FUNCTIONAL")
447 :
448 : ! Calculate the derivatives
449 : CALL xc_functionals_eval(xc_fun_section, &
450 : lsd=lsd, &
451 : rho_set=rho_set, &
452 : deriv_set=deriv_set, &
453 19068 : deriv_order=2)
454 :
455 19068 : CALL divide_by_norm_drho(deriv_set, rho_set, lsd)
456 :
457 : ! multiply by w
458 19068 : pos => deriv_set%derivs
459 125768 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
460 272210768 : deriv_att%deriv_data(:, :, 1) = w(:, :)*deriv_att%deriv_data(:, :, 1)
461 : END DO
462 :
463 19068 : NULLIFY (pw_pool)
464 76660 : ALLOCATE (vxc_pw(nspins))
465 38524 : DO ispin = 1, nspins
466 38524 : vxc_pw(ispin)%array => vxc(:, :, ispin:ispin)
467 : END DO
468 :
469 19068 : NULLIFY (vxc_tau_pw)
470 :
471 : CALL xc_calc_2nd_deriv_analytical(vxc_pw, vxc_tau_pw, deriv_set, rho_set, rho1_set, pw_pool, &
472 : xc_section, gapw=.TRUE., vxg=vxg, &
473 19068 : tddfpt_fac=my_fac_triplet, spinflip=do_sf)
474 :
475 19068 : DEALLOCATE (vxc_pw)
476 :
477 : ! zero the derivative data for the next call
478 19068 : pos => deriv_set%derivs
479 125768 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
480 272317468 : deriv_att%deriv_data = 0.0_dp
481 : END DO
482 :
483 19068 : CALL timestop(handle)
484 :
485 38136 : END SUBROUTINE xc_2nd_deriv_of_r
486 :
487 : ! **************************************************************************************************
488 : !> \brief ...
489 : !> \param rho_set ...
490 : !> \param needs ...
491 : !> \param nspins ...
492 : !> \param bo ...
493 : ! **************************************************************************************************
494 156044 : SUBROUTINE xc_rho_set_atom_update(rho_set, needs, nspins, bo)
495 :
496 : ! This routine allocates the storage arrays for rho and drho
497 : ! In calculate_vxc_atom this is called once for each atomic_kind,
498 : ! After the loop over all the atoms of the kind and over all the points
499 : ! of the radial grid for each atom, rho_set is deallocated.
500 : ! Within the same kind, at each new point on the radial grid, the rho_set
501 : ! arrays rho and drho are overwritten.
502 :
503 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
504 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
505 : INTEGER, INTENT(IN) :: nspins
506 : INTEGER, DIMENSION(2, 3), INTENT(IN) :: bo
507 :
508 : INTEGER :: idir
509 :
510 295543 : SELECT CASE (nspins)
511 : CASE (1)
512 : ! What is this for?
513 139499 : IF (needs%rho_1_3) THEN
514 4055 : NULLIFY (rho_set%rho_1_3)
515 20275 : ALLOCATE (rho_set%rho_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
516 4055 : rho_set%owns%rho_1_3 = .TRUE.
517 4055 : rho_set%has%rho_1_3 = .FALSE.
518 : END IF
519 : ! Allocate the storage space for the density
520 139499 : IF (needs%rho) THEN
521 139499 : NULLIFY (rho_set%rho)
522 697495 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
523 139499 : rho_set%owns%rho = .TRUE.
524 139499 : rho_set%has%rho = .FALSE.
525 : END IF
526 : ! Allocate the storage space for the norm of the gradient of the density
527 139499 : IF (needs%norm_drho) THEN
528 99557 : NULLIFY (rho_set%norm_drho)
529 497785 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
530 99557 : rho_set%owns%norm_drho = .TRUE.
531 99557 : rho_set%has%norm_drho = .FALSE.
532 : END IF
533 : ! Allocate the storage space for the three components of the gradient of the density
534 139499 : IF (needs%drho) THEN
535 312960 : DO idir = 1, 3
536 234720 : NULLIFY (rho_set%drho(idir)%array)
537 1251840 : ALLOCATE (rho_set%drho(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
538 : END DO
539 78240 : rho_set%owns%drho = .TRUE.
540 78240 : rho_set%has%drho = .FALSE.
541 : END IF
542 : CASE (2)
543 : ! Allocate the storage space for the total density
544 16545 : IF (needs%rho) THEN
545 : ! this should never be the case unless you use LDA functionals with LSD
546 0 : NULLIFY (rho_set%rho)
547 0 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
548 0 : rho_set%owns%rho = .TRUE.
549 0 : rho_set%has%rho = .FALSE.
550 : END IF
551 : ! What is this for?
552 16545 : IF (needs%rho_1_3) THEN
553 0 : NULLIFY (rho_set%rho_1_3)
554 0 : ALLOCATE (rho_set%rho_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
555 0 : rho_set%owns%rho_1_3 = .TRUE.
556 0 : rho_set%has%rho_1_3 = .FALSE.
557 : END IF
558 : ! What is this for?
559 16545 : IF (needs%rho_spin_1_3) THEN
560 2440 : NULLIFY (rho_set%rhoa_1_3, rho_set%rhob_1_3)
561 12200 : ALLOCATE (rho_set%rhoa_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
562 12200 : ALLOCATE (rho_set%rhob_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
563 2440 : rho_set%owns%rho_spin_1_3 = .TRUE.
564 2440 : rho_set%has%rho_spin_1_3 = .FALSE.
565 : END IF
566 : ! Allocate the storage space for the spin densities rhoa and rhob
567 16545 : IF (needs%rho_spin) THEN
568 16545 : NULLIFY (rho_set%rhoa, rho_set%rhob)
569 82725 : ALLOCATE (rho_set%rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
570 82725 : ALLOCATE (rho_set%rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
571 16545 : rho_set%owns%rho_spin = .TRUE.
572 16545 : rho_set%has%rho_spin = .FALSE.
573 : END IF
574 : ! Allocate the storage space for the norm of the gradient of the total density
575 16545 : IF (needs%norm_drho) THEN
576 10547 : NULLIFY (rho_set%norm_drho)
577 52735 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
578 10547 : rho_set%owns%norm_drho = .TRUE.
579 10547 : rho_set%has%norm_drho = .FALSE.
580 : END IF
581 : ! Allocate the storage space for the norm of the gradient of rhoa and of rhob separatedly
582 16545 : IF (needs%norm_drho_spin) THEN
583 10595 : NULLIFY (rho_set%norm_drhoa, rho_set%norm_drhob)
584 52975 : ALLOCATE (rho_set%norm_drhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
585 52975 : ALLOCATE (rho_set%norm_drhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
586 10595 : rho_set%owns%norm_drho_spin = .TRUE.
587 10595 : rho_set%has%norm_drho_spin = .FALSE.
588 : END IF
589 : ! Allocate the storage space for the components of the gradient for the total rho
590 16545 : IF (needs%drho) THEN
591 0 : DO idir = 1, 3
592 0 : NULLIFY (rho_set%drho(idir)%array)
593 0 : ALLOCATE (rho_set%drho(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
594 : END DO
595 0 : rho_set%owns%drho = .TRUE.
596 0 : rho_set%has%drho = .FALSE.
597 : END IF
598 : ! Allocate the storage space for the components of the gradient for rhoa and rhob
599 172589 : IF (needs%drho_spin) THEN
600 38864 : DO idir = 1, 3
601 29148 : NULLIFY (rho_set%drhoa(idir)%array, rho_set%drhob(idir)%array)
602 145740 : ALLOCATE (rho_set%drhoa(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
603 155456 : ALLOCATE (rho_set%drhob(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
604 : END DO
605 9716 : rho_set%owns%drho_spin = .TRUE.
606 9716 : rho_set%has%drho_spin = .FALSE.
607 : END IF
608 : !
609 : END SELECT
610 :
611 : ! tau part
612 156044 : IF (needs%tau) THEN
613 1508 : NULLIFY (rho_set%tau)
614 7540 : ALLOCATE (rho_set%tau(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
615 1508 : rho_set%owns%tau = .TRUE.
616 : END IF
617 156044 : IF (needs%tau_spin) THEN
618 34 : NULLIFY (rho_set%tau_a, rho_set%tau_b)
619 170 : ALLOCATE (rho_set%tau_a(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
620 170 : ALLOCATE (rho_set%tau_b(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
621 34 : rho_set%owns%tau_spin = .TRUE.
622 34 : rho_set%has%tau_spin = .FALSE.
623 : END IF
624 :
625 : ! Laplace part
626 156044 : IF (needs%laplace_rho) THEN
627 0 : NULLIFY (rho_set%laplace_rho)
628 0 : ALLOCATE (rho_set%laplace_rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
629 0 : rho_set%owns%laplace_rho = .TRUE.
630 : END IF
631 156044 : IF (needs%laplace_rho_spin) THEN
632 0 : NULLIFY (rho_set%laplace_rhoa)
633 0 : NULLIFY (rho_set%laplace_rhob)
634 0 : ALLOCATE (rho_set%laplace_rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
635 0 : ALLOCATE (rho_set%laplace_rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
636 0 : rho_set%owns%laplace_rho_spin = .TRUE.
637 0 : rho_set%has%laplace_rho_spin = .TRUE.
638 : END IF
639 :
640 156044 : END SUBROUTINE xc_rho_set_atom_update
641 :
642 : ! **************************************************************************************************
643 : !> \brief ...
644 : !> \param rho_set ...
645 : !> \param lsd ...
646 : !> \param nspins ...
647 : !> \param needs ...
648 : !> \param rho ...
649 : !> \param drho ...
650 : !> \param tau ...
651 : !> \param na ...
652 : !> \param ir ...
653 : ! **************************************************************************************************
654 5440980 : SUBROUTINE fill_rho_set(rho_set, lsd, nspins, needs, rho, drho, tau, na, ir)
655 :
656 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
657 : LOGICAL, INTENT(IN) :: lsd
658 : INTEGER, INTENT(IN) :: nspins
659 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
660 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: rho
661 : REAL(dp), DIMENSION(:, :, :, :), INTENT(IN) :: drho
662 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: tau
663 : INTEGER, INTENT(IN) :: na, ir
664 :
665 : REAL(KIND=dp), PARAMETER :: f13 = (1.0_dp/3.0_dp)
666 :
667 : INTEGER :: ia, idir, my_nspins
668 : LOGICAL :: gradient_f, tddft_split
669 :
670 5440980 : my_nspins = nspins
671 5440980 : tddft_split = .FALSE.
672 5440980 : IF (lsd .AND. nspins == 1) THEN
673 90600 : my_nspins = 2
674 90600 : tddft_split = .TRUE.
675 : END IF
676 :
677 : ! some checks
678 5440980 : IF (lsd) THEN
679 : ELSE
680 4706500 : CPASSERT(SIZE(rho, 3) == 1)
681 : END IF
682 4706500 : SELECT CASE (my_nspins)
683 : CASE (1)
684 4706500 : CPASSERT(.NOT. needs%rho_spin)
685 4706500 : CPASSERT(.NOT. needs%drho_spin)
686 4706500 : CPASSERT(.NOT. needs%norm_drho_spin)
687 4706500 : CPASSERT(.NOT. needs%rho_spin_1_3)
688 : CASE (2)
689 : CASE default
690 5440980 : CPABORT("Unsupported number of spins")
691 : END SELECT
692 :
693 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
694 5440980 : needs%drho .OR. needs%norm_drho)
695 :
696 4706500 : SELECT CASE (my_nspins)
697 : CASE (1)
698 : ! Give rho to 1/3
699 4706500 : IF (needs%rho_1_3) THEN
700 6765600 : DO ia = 1, na
701 6765600 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
702 : END DO
703 132800 : rho_set%owns%rho_1_3 = .TRUE.
704 132800 : rho_set%has%rho_1_3 = .TRUE.
705 : END IF
706 : ! Give the density
707 4706500 : IF (needs%rho) THEN
708 240211500 : DO ia = 1, na
709 240211500 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
710 : END DO
711 4706500 : rho_set%owns%rho = .TRUE.
712 4706500 : rho_set%has%rho = .TRUE.
713 : END IF
714 : ! Give the norm of the gradient of the density
715 4706500 : IF (needs%norm_drho) THEN
716 151211400 : DO ia = 1, na
717 151211400 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
718 : END DO
719 2961400 : rho_set%owns%norm_drho = .TRUE.
720 2961400 : rho_set%has%norm_drho = .TRUE.
721 : END IF
722 : ! Give the three components of the gradient of the density
723 4706500 : IF (needs%drho) THEN
724 11845600 : DO idir = 1, 3
725 456595600 : DO ia = 1, na
726 453634200 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
727 : END DO
728 : END DO
729 2961400 : rho_set%owns%drho = .TRUE.
730 2961400 : rho_set%has%drho = .TRUE.
731 : END IF
732 : CASE (2)
733 : ! Give the total density
734 734480 : IF (needs%rho) THEN
735 : ! this should never be the case unless you use LDA functionals with LSD
736 0 : IF (.NOT. tddft_split) THEN
737 0 : DO ia = 1, na
738 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1) + rho(ia, ir, 2)
739 : END DO
740 : ELSE
741 0 : DO ia = 1, na
742 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
743 : END DO
744 : END IF
745 0 : rho_set%owns%rho = .TRUE.
746 0 : rho_set%has%rho = .TRUE.
747 : END IF
748 : ! Give the total density to 1/3
749 734480 : IF (needs%rho_1_3) THEN
750 0 : IF (.NOT. tddft_split) THEN
751 0 : DO ia = 1, na
752 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1) + rho(ia, ir, 2), 0.0_dp)**f13
753 : END DO
754 : ELSE
755 0 : DO ia = 1, na
756 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
757 : END DO
758 : END IF
759 0 : rho_set%owns%rho_1_3 = .TRUE.
760 0 : rho_set%has%rho_1_3 = .TRUE.
761 : END IF
762 : ! Give the spin densities to 1/3
763 734480 : IF (needs%rho_spin_1_3) THEN
764 75480 : IF (.NOT. tddft_split) THEN
765 3837960 : DO ia = 1, na
766 3762480 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
767 3837960 : rho_set%rhob_1_3(ia, ir, 1) = MAX(rho(ia, ir, 2), 0.0_dp)**f13
768 : END DO
769 : ELSE
770 0 : DO ia = 1, na
771 0 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(0.5_dp*rho(ia, ir, 1), 0.0_dp)**f13
772 0 : rho_set%rhob_1_3(ia, ir, 1) = rho_set%rhoa_1_3(ia, ir, 1)
773 : END DO
774 : END IF
775 75480 : rho_set%owns%rho_spin_1_3 = .TRUE.
776 75480 : rho_set%has%rho_spin_1_3 = .TRUE.
777 : END IF
778 : ! Give the spin densities rhoa and rhob
779 734480 : IF (needs%rho_spin) THEN
780 734480 : IF (.NOT. tddft_split) THEN
781 32826360 : DO ia = 1, na
782 32182480 : rho_set%rhoa(ia, ir, 1) = rho(ia, ir, 1)
783 32826360 : rho_set%rhob(ia, ir, 1) = rho(ia, ir, 2)
784 : END DO
785 : ELSE
786 4620600 : DO ia = 1, na
787 4530000 : rho_set%rhoa(ia, ir, 1) = 0.5_dp*rho(ia, ir, 1)
788 4620600 : rho_set%rhob(ia, ir, 1) = rho_set%rhoa(ia, ir, 1)
789 : END DO
790 : END IF
791 734480 : rho_set%owns%rho_spin = .TRUE.
792 734480 : rho_set%has%rho_spin = .TRUE.
793 : END IF
794 : ! Give the norm of the gradient of the total density
795 734480 : IF (needs%norm_drho) THEN
796 404480 : IF (.NOT. tddft_split) THEN
797 17220360 : DO ia = 1, na
798 : rho_set%norm_drho(ia, ir, 1) = SQRT( &
799 : (drho(1, ia, ir, 1) + drho(1, ia, ir, 2))**2 + &
800 : (drho(2, ia, ir, 1) + drho(2, ia, ir, 2))**2 + &
801 17220360 : (drho(3, ia, ir, 1) + drho(3, ia, ir, 2))**2)
802 : END DO
803 : ELSE
804 3396600 : DO ia = 1, na
805 3396600 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
806 : END DO
807 : END IF
808 404480 : rho_set%owns%norm_drho = .TRUE.
809 404480 : rho_set%has%norm_drho = .TRUE.
810 : END IF
811 : ! Give the norm of the gradient of rhoa and of rhob separatedly
812 734480 : IF (needs%norm_drho_spin) THEN
813 406880 : IF (.NOT. tddft_split) THEN
814 17342760 : DO ia = 1, na
815 17002480 : rho_set%norm_drhoa(ia, ir, 1) = drho(4, ia, ir, 1)
816 17342760 : rho_set%norm_drhob(ia, ir, 1) = drho(4, ia, ir, 2)
817 : END DO
818 : ELSE
819 3396600 : DO ia = 1, na
820 3330000 : rho_set%norm_drhoa(ia, ir, 1) = 0.5_dp*drho(4, ia, ir, 1)
821 3396600 : rho_set%norm_drhob(ia, ir, 1) = rho_set%norm_drhoa(ia, ir, 1)
822 : END DO
823 : END IF
824 406880 : rho_set%owns%norm_drho_spin = .TRUE.
825 406880 : rho_set%has%norm_drho_spin = .TRUE.
826 : END IF
827 : ! Give the components of the gradient for the total rho
828 734480 : IF (needs%drho) THEN
829 0 : IF (.NOT. tddft_split) THEN
830 0 : DO idir = 1, 3
831 0 : DO ia = 1, na
832 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1) + drho(idir, ia, ir, 2)
833 : END DO
834 : END DO
835 : ELSE
836 0 : DO idir = 1, 3
837 0 : DO ia = 1, na
838 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
839 : END DO
840 : END DO
841 : END IF
842 0 : rho_set%owns%drho = .TRUE.
843 0 : rho_set%has%drho = .TRUE.
844 : END IF
845 : ! Give the components of the gradient for rhoa and rhob
846 6175460 : IF (needs%drho_spin) THEN
847 408380 : IF (.NOT. tddft_split) THEN
848 1367120 : DO idir = 1, 3
849 52599560 : DO ia = 1, na
850 51232440 : rho_set%drhoa(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
851 52257780 : rho_set%drhob(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 2)
852 : END DO
853 : END DO
854 : ELSE
855 266400 : DO idir = 1, 3
856 10256400 : DO ia = 1, na
857 9990000 : rho_set%drhoa(idir)%array(ia, ir, 1) = 0.5_dp*drho(idir, ia, ir, 1)
858 10189800 : rho_set%drhob(idir)%array(ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)
859 : END DO
860 : END DO
861 : END IF
862 408380 : rho_set%owns%drho_spin = .TRUE.
863 408380 : rho_set%has%drho_spin = .TRUE.
864 : END IF
865 : !
866 : END SELECT
867 :
868 : ! tau part
869 5440980 : IF (needs%tau .OR. needs%tau_spin) THEN
870 5440980 : CPASSERT(SIZE(tau, 3) == my_nspins)
871 : END IF
872 5440980 : IF (needs%tau) THEN
873 49400 : IF (my_nspins == 2) THEN
874 0 : DO ia = 1, na
875 0 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1) + tau(ia, ir, 2)
876 : END DO
877 0 : rho_set%owns%tau = .TRUE.
878 0 : rho_set%has%tau = .TRUE.
879 : ELSE
880 2706600 : DO ia = 1, na
881 2706600 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1)
882 : END DO
883 49400 : rho_set%owns%tau = .TRUE.
884 49400 : rho_set%has%tau = .TRUE.
885 : END IF
886 : END IF
887 5440980 : IF (needs%tau_spin) THEN
888 40800 : DO ia = 1, na
889 40000 : rho_set%tau_a(ia, ir, 1) = tau(ia, ir, 1)
890 40800 : rho_set%tau_b(ia, ir, 1) = tau(ia, ir, 2)
891 : END DO
892 800 : rho_set%owns%tau_spin = .TRUE.
893 800 : rho_set%has%tau_spin = .TRUE.
894 : END IF
895 :
896 5440980 : END SUBROUTINE fill_rho_set
897 :
898 : END MODULE xc_atom
|