Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : 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 104360 : 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(:, :), POINTER :: 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 52180 : REAL(dp), DIMENSION(:, :, :), POINTER :: deriv_data
96 : REAL(KIND=dp) :: drho_cutoff
97 : TYPE(xc_derivative_type), POINTER :: deriv_att
98 :
99 52180 : CALL timeset(routineN, handle)
100 52180 : my_only_energy = .FALSE.
101 52180 : IF (PRESENT(energy_only)) my_only_energy = energy_only
102 :
103 52180 : IF (PRESENT(adiabatic_rescale_factor)) THEN
104 52180 : 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 52180 : 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 52180 : deriv_order=deriv_order)
118 :
119 52180 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
120 :
121 52180 : NULLIFY (deriv_data)
122 :
123 : ! EXC energy
124 52180 : deriv_att => xc_dset_get_derivative(deriv_set, [INTEGER::])
125 52180 : exc = 0.0_dp
126 52180 : IF (ASSOCIATED(deriv_att)) THEN
127 52108 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
128 2998588 : DO ir = 1, nr
129 150491068 : DO ia = 1, na
130 150438960 : exc = exc + deriv_data(ia, ir, 1)*w(ia, ir)
131 : END DO
132 : END DO
133 52108 : NULLIFY (deriv_data)
134 : END IF
135 : ! Calculate the potential only if needed
136 52180 : IF (.NOT. my_only_energy) THEN
137 : ! Derivative with respect to the density
138 49156 : IF (lsd) THEN
139 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhoa])
140 8140 : IF (ASSOCIATED(deriv_att)) THEN
141 8136 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
142 54040992 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
143 8136 : NULLIFY (deriv_data)
144 : END IF
145 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhob])
146 8140 : IF (ASSOCIATED(deriv_att)) THEN
147 8136 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
148 54040992 : vxc(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
149 8136 : NULLIFY (deriv_data)
150 : END IF
151 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
152 8140 : 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 41016 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
160 41016 : IF (ASSOCIATED(deriv_att)) THEN
161 40948 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
162 230125496 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
163 40948 : NULLIFY (deriv_data)
164 : END IF
165 : END IF ! lsd
166 :
167 : ! Derivatives with respect to the gradient
168 49156 : IF (lsd) THEN
169 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa])
170 8140 : IF (ASSOCIATED(deriv_att)) THEN
171 4838 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
172 262018 : DO ir = 1, nr
173 13109498 : DO ia = 1, na
174 51647100 : DO idir = 1, 3
175 51389920 : 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 33048696 : rho_set%norm_drhoa(ia, ir, 1)*my_adiabatic_rescale_factor
179 : ELSE
180 5493744 : vxg(idir, ia, ir, 1) = 0.0_dp
181 : END IF
182 : END DO
183 : END DO
184 : END DO
185 4838 : NULLIFY (deriv_data)
186 : END IF
187 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob])
188 8140 : IF (ASSOCIATED(deriv_att)) THEN
189 4838 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
190 262018 : DO ir = 1, nr
191 13109498 : DO ia = 1, na
192 51647100 : DO idir = 1, 3
193 51389920 : 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 32393400 : rho_set%norm_drhob(ia, ir, 1)*my_adiabatic_rescale_factor
197 : ELSE
198 6149040 : vxg(idir, ia, ir, 2) = 0.0_dp
199 : END IF
200 : END DO
201 : END DO
202 : END DO
203 4838 : NULLIFY (deriv_data)
204 : END IF
205 : ! Cross Terms
206 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
207 8140 : IF (ASSOCIATED(deriv_att)) THEN
208 4790 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
209 259570 : DO ir = 1, nr
210 12987050 : DO ia = 1, na
211 51164700 : DO idir = 1, 3
212 50909920 : 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 98313444 : my_adiabatic_rescale_factor
219 : END IF
220 : END DO
221 : END DO
222 : END DO
223 4790 : NULLIFY (deriv_data)
224 : END IF
225 : ELSE
226 41016 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
227 41016 : IF (ASSOCIATED(deriv_att)) THEN
228 23372 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
229 1211572 : DO ir = 1, nr
230 60801572 : DO ia = 1, na
231 60778200 : IF (rho_set%norm_drho(ia, ir, 1) > drho_cutoff) THEN
232 205929656 : 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 205929656 : rho_set%norm_drho(ia, ir, 1)*my_adiabatic_rescale_factor
236 : END DO
237 : ELSE
238 32430344 : vxg(1:3, ia, ir, 1) = 0.0_dp
239 : END IF
240 : END DO
241 : END DO
242 23372 : NULLIFY (deriv_data)
243 : END IF
244 : END IF ! lsd
245 : ! Derivative with respect to tau
246 49156 : IF (lsd) THEN
247 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_a])
248 8140 : IF (ASSOCIATED(deriv_att)) THEN
249 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
250 0 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
251 0 : NULLIFY (deriv_data)
252 : END IF
253 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_b])
254 8140 : IF (ASSOCIATED(deriv_att)) THEN
255 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
256 0 : vtau(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
257 0 : NULLIFY (deriv_data)
258 : END IF
259 8140 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
260 8140 : 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 41016 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
268 41016 : IF (ASSOCIATED(deriv_att)) THEN
269 712 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
270 4272224 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
271 712 : NULLIFY (deriv_data)
272 : END IF
273 : END IF ! lsd
274 : END IF ! only_energy
275 :
276 52180 : CALL timestop(handle)
277 :
278 52180 : 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 60 : 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(:, :), POINTER :: 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 11166 : SUBROUTINE xc_2nd_deriv_of_r(rho_set, rho1_set, xc_section, &
401 : 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(:, :), POINTER :: 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 11166 : 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 11166 : CALL timeset(routineN, handle)
430 :
431 11166 : nspins = SIZE(vxc, 3)
432 11166 : lsd = (nspins == 2)
433 11166 : IF (ASSOCIATED(rho_set%rhoa)) THEN
434 902 : lsd = .TRUE.
435 : END IF
436 11166 : my_fac_triplet = 1.0_dp
437 11166 : IF (PRESENT(do_triplet)) THEN
438 10930 : IF (do_triplet) my_fac_triplet = -1.0_dp
439 : END IF
440 :
441 11166 : my_do_sf = .FALSE.
442 11166 : IF (PRESENT(do_sf)) my_do_sf = do_sf
443 :
444 11166 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
445 : xc_fun_section => section_vals_get_subs_vals(xc_section, &
446 11166 : "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 11166 : deriv_order=2)
454 :
455 11166 : CALL divide_by_norm_drho(deriv_set, rho_set, lsd)
456 :
457 : ! multiply by w
458 11166 : pos => deriv_set%derivs
459 75548 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
460 328488130 : deriv_att%deriv_data(:, :, 1) = w(:, :)*deriv_att%deriv_data(:, :, 1)
461 : END DO
462 :
463 11166 : NULLIFY (pw_pool)
464 45032 : ALLOCATE (vxc_pw(nspins))
465 22700 : DO ispin = 1, nspins
466 22700 : vxc_pw(ispin)%array => vxc(:, :, ispin:ispin)
467 : END DO
468 :
469 11166 : 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 11166 : xc_section, gapw=.TRUE., vxg=vxg, tddfpt_fac=my_fac_triplet, spinflip=do_sf)
473 :
474 11166 : DEALLOCATE (vxc_pw)
475 :
476 : ! zero the derivative data for the next call
477 11166 : pos => deriv_set%derivs
478 75548 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
479 164314030 : deriv_att%deriv_data = 0.0_dp
480 : END DO
481 :
482 11166 : CALL timestop(handle)
483 :
484 22332 : END SUBROUTINE xc_2nd_deriv_of_r
485 :
486 : ! **************************************************************************************************
487 : !> \brief ...
488 : !> \param rho_set ...
489 : !> \param needs ...
490 : !> \param nspins ...
491 : !> \param bo ...
492 : ! **************************************************************************************************
493 116550 : SUBROUTINE xc_rho_set_atom_update(rho_set, needs, nspins, bo)
494 :
495 : ! This routine allocates the storage arrays for rho and drho
496 : ! In calculate_vxc_atom this is called once for each atomic_kind,
497 : ! After the loop over all the atoms of the kind and over all the points
498 : ! of the radial grid for each atom, rho_set is deallocated.
499 : ! Within the same kind, at each new point on the radial grid, the rho_set
500 : ! arrays rho and drho are overwritten.
501 :
502 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
503 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
504 : INTEGER, INTENT(IN) :: nspins
505 : INTEGER, DIMENSION(2, 3), INTENT(IN) :: bo
506 :
507 : INTEGER :: idir
508 :
509 217963 : SELECT CASE (nspins)
510 : CASE (1)
511 : ! What is this for?
512 101413 : IF (needs%rho_1_3) THEN
513 4055 : NULLIFY (rho_set%rho_1_3)
514 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)))
515 4055 : rho_set%owns%rho_1_3 = .TRUE.
516 4055 : rho_set%has%rho_1_3 = .FALSE.
517 : END IF
518 : ! Allocate the storage space for the density
519 101413 : IF (needs%rho) THEN
520 101413 : NULLIFY (rho_set%rho)
521 507065 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
522 101413 : rho_set%owns%rho = .TRUE.
523 101413 : rho_set%has%rho = .FALSE.
524 : END IF
525 : ! Allocate the storage space for the norm of the gradient of the density
526 101413 : IF (needs%norm_drho) THEN
527 72439 : NULLIFY (rho_set%norm_drho)
528 362195 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
529 72439 : rho_set%owns%norm_drho = .TRUE.
530 72439 : rho_set%has%norm_drho = .FALSE.
531 : END IF
532 : ! Allocate the storage space for the three components of the gradient of the density
533 101413 : IF (needs%drho) THEN
534 204592 : DO idir = 1, 3
535 153444 : NULLIFY (rho_set%drho(idir)%array)
536 818368 : ALLOCATE (rho_set%drho(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
537 : END DO
538 51148 : rho_set%owns%drho = .TRUE.
539 51148 : rho_set%has%drho = .FALSE.
540 : END IF
541 : CASE (2)
542 : ! Allocate the storage space for the total density
543 15137 : IF (needs%rho) THEN
544 : ! this should never be the case unless you use LDA functionals with LSD
545 0 : NULLIFY (rho_set%rho)
546 0 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
547 0 : rho_set%owns%rho = .TRUE.
548 0 : rho_set%has%rho = .FALSE.
549 : END IF
550 : ! What is this for?
551 15137 : IF (needs%rho_1_3) THEN
552 0 : NULLIFY (rho_set%rho_1_3)
553 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)))
554 0 : rho_set%owns%rho_1_3 = .TRUE.
555 0 : rho_set%has%rho_1_3 = .FALSE.
556 : END IF
557 : ! What is this for?
558 15137 : IF (needs%rho_spin_1_3) THEN
559 2440 : NULLIFY (rho_set%rhoa_1_3, rho_set%rhob_1_3)
560 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)))
561 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)))
562 2440 : rho_set%owns%rho_spin_1_3 = .TRUE.
563 2440 : rho_set%has%rho_spin_1_3 = .FALSE.
564 : END IF
565 : ! Allocate the storage space for the spin densities rhoa and rhob
566 15137 : IF (needs%rho_spin) THEN
567 15137 : NULLIFY (rho_set%rhoa, rho_set%rhob)
568 75685 : ALLOCATE (rho_set%rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
569 75685 : ALLOCATE (rho_set%rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
570 15137 : rho_set%owns%rho_spin = .TRUE.
571 15137 : rho_set%has%rho_spin = .FALSE.
572 : END IF
573 : ! Allocate the storage space for the norm of the gradient of the total density
574 15137 : IF (needs%norm_drho) THEN
575 9763 : NULLIFY (rho_set%norm_drho)
576 48815 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
577 9763 : rho_set%owns%norm_drho = .TRUE.
578 9763 : rho_set%has%norm_drho = .FALSE.
579 : END IF
580 : ! Allocate the storage space for the norm of the gradient of rhoa and of rhob separatedly
581 15137 : IF (needs%norm_drho_spin) THEN
582 9811 : NULLIFY (rho_set%norm_drhoa, rho_set%norm_drhob)
583 49055 : ALLOCATE (rho_set%norm_drhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
584 49055 : ALLOCATE (rho_set%norm_drhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
585 9811 : rho_set%owns%norm_drho_spin = .TRUE.
586 9811 : rho_set%has%norm_drho_spin = .FALSE.
587 : END IF
588 : ! Allocate the storage space for the components of the gradient for the total rho
589 15137 : IF (needs%drho) THEN
590 0 : DO idir = 1, 3
591 0 : NULLIFY (rho_set%drho(idir)%array)
592 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)))
593 : END DO
594 0 : rho_set%owns%drho = .TRUE.
595 0 : rho_set%has%drho = .FALSE.
596 : END IF
597 : ! Allocate the storage space for the components of the gradient for rhoa and rhob
598 131687 : IF (needs%drho_spin) THEN
599 35728 : DO idir = 1, 3
600 26796 : NULLIFY (rho_set%drhoa(idir)%array, rho_set%drhob(idir)%array)
601 133980 : ALLOCATE (rho_set%drhoa(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
602 142912 : ALLOCATE (rho_set%drhob(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
603 : END DO
604 8932 : rho_set%owns%drho_spin = .TRUE.
605 8932 : rho_set%has%drho_spin = .FALSE.
606 : END IF
607 : !
608 : END SELECT
609 :
610 : ! tau part
611 116550 : IF (needs%tau) THEN
612 1092 : NULLIFY (rho_set%tau)
613 5460 : ALLOCATE (rho_set%tau(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
614 1092 : rho_set%owns%tau = .TRUE.
615 : END IF
616 116550 : IF (needs%tau_spin) THEN
617 2 : NULLIFY (rho_set%tau_a, rho_set%tau_b)
618 10 : ALLOCATE (rho_set%tau_a(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
619 10 : ALLOCATE (rho_set%tau_b(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
620 2 : rho_set%owns%tau_spin = .TRUE.
621 2 : rho_set%has%tau_spin = .FALSE.
622 : END IF
623 :
624 : ! Laplace part
625 116550 : IF (needs%laplace_rho) THEN
626 0 : NULLIFY (rho_set%laplace_rho)
627 0 : ALLOCATE (rho_set%laplace_rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
628 0 : rho_set%owns%laplace_rho = .TRUE.
629 : END IF
630 116550 : IF (needs%laplace_rho_spin) THEN
631 0 : NULLIFY (rho_set%laplace_rhoa)
632 0 : NULLIFY (rho_set%laplace_rhob)
633 0 : ALLOCATE (rho_set%laplace_rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
634 0 : ALLOCATE (rho_set%laplace_rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
635 0 : rho_set%owns%laplace_rho_spin = .TRUE.
636 0 : rho_set%has%laplace_rho_spin = .TRUE.
637 : END IF
638 :
639 116550 : END SUBROUTINE xc_rho_set_atom_update
640 :
641 : ! **************************************************************************************************
642 : !> \brief ...
643 : !> \param rho_set ...
644 : !> \param lsd ...
645 : !> \param nspins ...
646 : !> \param needs ...
647 : !> \param rho ...
648 : !> \param drho ...
649 : !> \param tau ...
650 : !> \param na ...
651 : !> \param ir ...
652 : ! **************************************************************************************************
653 4017180 : SUBROUTINE fill_rho_set(rho_set, lsd, nspins, needs, rho, drho, tau, na, ir)
654 :
655 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
656 : LOGICAL, INTENT(IN) :: lsd
657 : INTEGER, INTENT(IN) :: nspins
658 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
659 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: rho
660 : REAL(dp), DIMENSION(:, :, :, :), INTENT(IN) :: drho
661 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: tau
662 : INTEGER, INTENT(IN) :: na, ir
663 :
664 : REAL(KIND=dp), PARAMETER :: f13 = (1.0_dp/3.0_dp)
665 :
666 : INTEGER :: ia, idir, my_nspins
667 : LOGICAL :: gradient_f, tddft_split
668 :
669 4017180 : my_nspins = nspins
670 4017180 : tddft_split = .FALSE.
671 4017180 : IF (lsd .AND. nspins == 1) THEN
672 48000 : my_nspins = 2
673 48000 : tddft_split = .TRUE.
674 : END IF
675 :
676 : ! some checks
677 4017180 : IF (lsd) THEN
678 : ELSE
679 3334900 : CPASSERT(SIZE(rho, 3) == 1)
680 : END IF
681 3334900 : SELECT CASE (my_nspins)
682 : CASE (1)
683 3334900 : CPASSERT(.NOT. needs%rho_spin)
684 3334900 : CPASSERT(.NOT. needs%drho_spin)
685 3334900 : CPASSERT(.NOT. needs%norm_drho_spin)
686 3334900 : CPASSERT(.NOT. needs%rho_spin_1_3)
687 : CASE (2)
688 : CASE default
689 4017180 : CPABORT("Unsupported number of spins")
690 : END SELECT
691 :
692 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
693 4017180 : needs%drho .OR. needs%norm_drho)
694 :
695 3334900 : SELECT CASE (my_nspins)
696 : CASE (1)
697 : ! Give rho to 1/3
698 3334900 : IF (needs%rho_1_3) THEN
699 6765600 : DO ia = 1, na
700 6765600 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
701 : END DO
702 132800 : rho_set%owns%rho_1_3 = .TRUE.
703 132800 : rho_set%has%rho_1_3 = .TRUE.
704 : END IF
705 : ! Give the density
706 3334900 : IF (needs%rho) THEN
707 170259900 : DO ia = 1, na
708 170259900 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
709 : END DO
710 3334900 : rho_set%owns%rho = .TRUE.
711 3334900 : rho_set%has%rho = .TRUE.
712 : END IF
713 : ! Give the norm of the gradient of the density
714 3334900 : IF (needs%norm_drho) THEN
715 101511900 : DO ia = 1, na
716 101511900 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
717 : END DO
718 1986900 : rho_set%owns%norm_drho = .TRUE.
719 1986900 : rho_set%has%norm_drho = .TRUE.
720 : END IF
721 : ! Give the three components of the gradient of the density
722 3334900 : IF (needs%drho) THEN
723 7947600 : DO idir = 1, 3
724 306522600 : DO ia = 1, na
725 304535700 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
726 : END DO
727 : END DO
728 1986900 : rho_set%owns%drho = .TRUE.
729 1986900 : rho_set%has%drho = .TRUE.
730 : END IF
731 : CASE (2)
732 : ! Give the total density
733 682280 : IF (needs%rho) THEN
734 : ! this should never be the case unless you use LDA functionals with LSD
735 0 : IF (.NOT. tddft_split) THEN
736 0 : DO ia = 1, na
737 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1) + rho(ia, ir, 2)
738 : END DO
739 : ELSE
740 0 : DO ia = 1, na
741 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
742 : END DO
743 : END IF
744 0 : rho_set%owns%rho = .TRUE.
745 0 : rho_set%has%rho = .TRUE.
746 : END IF
747 : ! Give the total density to 1/3
748 682280 : IF (needs%rho_1_3) THEN
749 0 : IF (.NOT. tddft_split) THEN
750 0 : DO ia = 1, na
751 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1) + rho(ia, ir, 2), 0.0_dp)**f13
752 : END DO
753 : ELSE
754 0 : DO ia = 1, na
755 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
756 : END DO
757 : END IF
758 0 : rho_set%owns%rho_1_3 = .TRUE.
759 0 : rho_set%has%rho_1_3 = .TRUE.
760 : END IF
761 : ! Give the spin densities to 1/3
762 682280 : IF (needs%rho_spin_1_3) THEN
763 75480 : IF (.NOT. tddft_split) THEN
764 3837960 : DO ia = 1, na
765 3762480 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
766 3837960 : rho_set%rhob_1_3(ia, ir, 1) = MAX(rho(ia, ir, 2), 0.0_dp)**f13
767 : END DO
768 : ELSE
769 0 : DO ia = 1, na
770 0 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(0.5_dp*rho(ia, ir, 1), 0.0_dp)**f13
771 0 : rho_set%rhob_1_3(ia, ir, 1) = rho_set%rhoa_1_3(ia, ir, 1)
772 : END DO
773 : END IF
774 75480 : rho_set%owns%rho_spin_1_3 = .TRUE.
775 75480 : rho_set%has%rho_spin_1_3 = .TRUE.
776 : END IF
777 : ! Give the spin densities rhoa and rhob
778 682280 : IF (needs%rho_spin) THEN
779 682280 : IF (.NOT. tddft_split) THEN
780 32336760 : DO ia = 1, na
781 31702480 : rho_set%rhoa(ia, ir, 1) = rho(ia, ir, 1)
782 32336760 : rho_set%rhob(ia, ir, 1) = rho(ia, ir, 2)
783 : END DO
784 : ELSE
785 2448000 : DO ia = 1, na
786 2400000 : rho_set%rhoa(ia, ir, 1) = 0.5_dp*rho(ia, ir, 1)
787 2448000 : rho_set%rhob(ia, ir, 1) = rho_set%rhoa(ia, ir, 1)
788 : END DO
789 : END IF
790 682280 : rho_set%owns%rho_spin = .TRUE.
791 682280 : rho_set%has%rho_spin = .TRUE.
792 : END IF
793 : ! Give the norm of the gradient of the total density
794 682280 : IF (needs%norm_drho) THEN
795 373080 : IF (.NOT. tddft_split) THEN
796 17179560 : DO ia = 1, na
797 : rho_set%norm_drho(ia, ir, 1) = SQRT( &
798 : (drho(1, ia, ir, 1) + drho(1, ia, ir, 2))**2 + &
799 : (drho(2, ia, ir, 1) + drho(2, ia, ir, 2))**2 + &
800 17179560 : (drho(3, ia, ir, 1) + drho(3, ia, ir, 2))**2)
801 : END DO
802 : ELSE
803 1836000 : DO ia = 1, na
804 1836000 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
805 : END DO
806 : END IF
807 373080 : rho_set%owns%norm_drho = .TRUE.
808 373080 : rho_set%has%norm_drho = .TRUE.
809 : END IF
810 : ! Give the norm of the gradient of rhoa and of rhob separatedly
811 682280 : IF (needs%norm_drho_spin) THEN
812 375480 : IF (.NOT. tddft_split) THEN
813 17301960 : DO ia = 1, na
814 16962480 : rho_set%norm_drhoa(ia, ir, 1) = drho(4, ia, ir, 1)
815 17301960 : rho_set%norm_drhob(ia, ir, 1) = drho(4, ia, ir, 2)
816 : END DO
817 : ELSE
818 1836000 : DO ia = 1, na
819 1800000 : rho_set%norm_drhoa(ia, ir, 1) = 0.5_dp*drho(4, ia, ir, 1)
820 1836000 : rho_set%norm_drhob(ia, ir, 1) = rho_set%norm_drhoa(ia, ir, 1)
821 : END DO
822 : END IF
823 375480 : rho_set%owns%norm_drho_spin = .TRUE.
824 375480 : rho_set%has%norm_drho_spin = .TRUE.
825 : END IF
826 : ! Give the components of the gradient for the total rho
827 682280 : IF (needs%drho) THEN
828 0 : IF (.NOT. tddft_split) THEN
829 0 : DO idir = 1, 3
830 0 : DO ia = 1, na
831 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1) + drho(idir, ia, ir, 2)
832 : END DO
833 : END DO
834 : ELSE
835 0 : DO idir = 1, 3
836 0 : DO ia = 1, na
837 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
838 : END DO
839 : END DO
840 : END IF
841 0 : rho_set%owns%drho = .TRUE.
842 0 : rho_set%has%drho = .TRUE.
843 : END IF
844 : ! Give the components of the gradient for rhoa and rhob
845 4699460 : IF (needs%drho_spin) THEN
846 376980 : IF (.NOT. tddft_split) THEN
847 1363920 : DO idir = 1, 3
848 52476360 : DO ia = 1, na
849 51112440 : rho_set%drhoa(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
850 52135380 : rho_set%drhob(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 2)
851 : END DO
852 : END DO
853 : ELSE
854 144000 : DO idir = 1, 3
855 5544000 : DO ia = 1, na
856 5400000 : rho_set%drhoa(idir)%array(ia, ir, 1) = 0.5_dp*drho(idir, ia, ir, 1)
857 5508000 : rho_set%drhob(idir)%array(ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)
858 : END DO
859 : END DO
860 : END IF
861 376980 : rho_set%owns%drho_spin = .TRUE.
862 376980 : rho_set%has%drho_spin = .TRUE.
863 : END IF
864 : !
865 : END SELECT
866 :
867 : ! tau part
868 4017180 : IF (needs%tau .OR. needs%tau_spin) THEN
869 4017180 : CPASSERT(SIZE(tau, 3) == my_nspins)
870 : END IF
871 4017180 : IF (needs%tau) THEN
872 38200 : IF (my_nspins == 2) THEN
873 0 : DO ia = 1, na
874 0 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1) + tau(ia, ir, 2)
875 : END DO
876 0 : rho_set%owns%tau = .TRUE.
877 0 : rho_set%has%tau = .TRUE.
878 : ELSE
879 2135400 : DO ia = 1, na
880 2135400 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1)
881 : END DO
882 38200 : rho_set%owns%tau = .TRUE.
883 38200 : rho_set%has%tau = .TRUE.
884 : END IF
885 : END IF
886 4017180 : IF (needs%tau_spin) THEN
887 0 : DO ia = 1, na
888 0 : rho_set%tau_a(ia, ir, 1) = tau(ia, ir, 1)
889 0 : rho_set%tau_b(ia, ir, 1) = tau(ia, ir, 2)
890 : END DO
891 0 : rho_set%owns%tau_spin = .TRUE.
892 0 : rho_set%has%tau_spin = .TRUE.
893 : END IF
894 :
895 4017180 : END SUBROUTINE fill_rho_set
896 :
897 : END MODULE xc_atom
|