Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : 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, 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 epr_xc ...
60 : !> \param adiabatic_rescale_factor ...
61 : ! **************************************************************************************************
62 94260 : SUBROUTINE vxc_of_r_new(xc_fun_section, rho_set, deriv_set, deriv_order, needs, w, &
63 : lsd, na, nr, exc, vxc, vxg, vtau, &
64 : energy_only, epr_xc, adiabatic_rescale_factor)
65 :
66 : ! This routine updates rho_set by giving to it the rho and drho that are needed.
67 : ! Since for the local densities rho1_h and rho1_s local grids are used it is not possible
68 : ! to call xc_rho_set_update.
69 : ! As input of this routine one gets rho and drho on a one dimensional grid.
70 : ! The grid is the angular grid corresponding to a given point ir_pnt on the radial grid.
71 : ! The derivatives are calculated on this one dimensional grid, the results are stored in
72 : ! exc, vxc(1:na,ir_pnt,ispin), vxg(1:na,ir_pnt,ispin), vxg_cross(1:na,ir_pnt,ispin)
73 : ! Afterwords the arrays containing the derivatives are put to zero so that the routine
74 : ! can safely be called for the next radial point ir_pnt
75 :
76 : TYPE(section_vals_type), POINTER :: xc_fun_section
77 : TYPE(xc_rho_set_type), INTENT(IN) :: rho_set
78 : TYPE(xc_derivative_set_type), INTENT(IN) :: deriv_set
79 : INTEGER, INTENT(in) :: deriv_order
80 : TYPE(xc_rho_cflags_type), INTENT(in) :: needs
81 : REAL(dp), DIMENSION(:, :), POINTER :: w
82 : LOGICAL, INTENT(IN) :: lsd
83 : INTEGER, INTENT(in) :: na, nr
84 : REAL(dp) :: exc
85 : REAL(dp), DIMENSION(:, :, :), POINTER :: vxc
86 : REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
87 : REAL(dp), DIMENSION(:, :, :), POINTER :: vtau
88 : LOGICAL, INTENT(IN), OPTIONAL :: energy_only, epr_xc
89 : REAL(dp), INTENT(IN), OPTIONAL :: adiabatic_rescale_factor
90 :
91 : CHARACTER(LEN=*), PARAMETER :: routineN = 'vxc_of_r_new'
92 :
93 : INTEGER :: handle, ia, idir, ir, my_deriv_order
94 : LOGICAL :: gradient_f, my_epr_xc, my_only_energy
95 : REAL(dp) :: my_adiabatic_rescale_factor
96 47130 : REAL(dp), DIMENSION(:, :, :), POINTER :: deriv_data
97 : REAL(KIND=dp) :: drho_cutoff
98 : TYPE(xc_derivative_type), POINTER :: deriv_att
99 :
100 47130 : CALL timeset(routineN, handle)
101 47130 : my_only_energy = .FALSE.
102 47130 : IF (PRESENT(energy_only)) my_only_energy = energy_only
103 :
104 47130 : IF (PRESENT(adiabatic_rescale_factor)) THEN
105 47130 : my_adiabatic_rescale_factor = adiabatic_rescale_factor
106 : ELSE
107 : my_adiabatic_rescale_factor = 1.0_dp
108 : END IF
109 :
110 : ! needed for the epr routines
111 47130 : my_epr_xc = .FALSE.
112 47130 : IF (PRESENT(epr_xc)) my_epr_xc = epr_xc
113 47130 : my_deriv_order = deriv_order
114 47130 : IF (my_epr_xc) my_deriv_order = 2
115 :
116 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
117 47130 : needs%drho .OR. needs%norm_drho)
118 :
119 : ! Calculate the derivatives
120 : CALL xc_functionals_eval(xc_fun_section, &
121 : lsd=lsd, &
122 : rho_set=rho_set, &
123 : deriv_set=deriv_set, &
124 47130 : deriv_order=my_deriv_order)
125 :
126 47130 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
127 :
128 47130 : NULLIFY (deriv_data)
129 :
130 47130 : IF (my_epr_xc) THEN
131 : ! nabla v_xc (using the vxg arrays)
132 : ! there's no point doing this when lsd = false
133 30 : IF (lsd) THEN
134 30 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhoa, deriv_rhoa])
135 30 : IF (ASSOCIATED(deriv_att)) THEN
136 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
137 1530 : DO ir = 1, nr
138 76530 : DO ia = 1, na
139 301500 : DO idir = 1, 3
140 : vxg(idir, ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)* &
141 300000 : deriv_data(ia, ir, 1)
142 : END DO !idir
143 : END DO !ia
144 : END DO !ir
145 30 : NULLIFY (deriv_data)
146 : END IF
147 30 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhob, deriv_rhob])
148 30 : IF (ASSOCIATED(deriv_att)) THEN
149 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
150 1530 : DO ir = 1, nr
151 76530 : DO ia = 1, na
152 301500 : DO idir = 1, 3
153 : vxg(idir, ia, ir, 2) = rho_set%drhob(idir)%array(ia, ir, 1)* &
154 300000 : deriv_data(ia, ir, 1)
155 : END DO !idir
156 : END DO !ia
157 : END DO !ir
158 30 : NULLIFY (deriv_data)
159 : END IF
160 : END IF
161 : ! EXC energy ! is that needed for epr?
162 30 : deriv_att => xc_dset_get_derivative(deriv_set, [INTEGER::])
163 30 : exc = 0.0_dp
164 30 : IF (ASSOCIATED(deriv_att)) THEN
165 30 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
166 1530 : DO ir = 1, nr
167 76530 : DO ia = 1, na
168 76500 : exc = exc + deriv_data(ia, ir, 1)*w(ia, ir)
169 : END DO
170 : END DO
171 30 : NULLIFY (deriv_data)
172 : END IF
173 : ELSE
174 : ! EXC energy
175 47100 : deriv_att => xc_dset_get_derivative(deriv_set, [INTEGER::])
176 47100 : exc = 0.0_dp
177 47100 : IF (ASSOCIATED(deriv_att)) THEN
178 47028 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
179 2735508 : DO ir = 1, nr
180 137327988 : DO ia = 1, na
181 137280960 : exc = exc + deriv_data(ia, ir, 1)*w(ia, ir)
182 : END DO
183 : END DO
184 47028 : NULLIFY (deriv_data)
185 : END IF
186 : ! Calculate the potential only if needed
187 47100 : IF (.NOT. my_only_energy) THEN
188 : ! Derivative with respect to the density
189 45024 : IF (lsd) THEN
190 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhoa])
191 7638 : IF (ASSOCIATED(deriv_att)) THEN
192 7634 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
193 51234988 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
194 7634 : NULLIFY (deriv_data)
195 : END IF
196 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rhob])
197 7638 : IF (ASSOCIATED(deriv_att)) THEN
198 7634 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
199 51234988 : vxc(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
200 7634 : NULLIFY (deriv_data)
201 : END IF
202 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
203 7638 : IF (ASSOCIATED(deriv_att)) THEN
204 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
205 0 : vxc(:, :, 1) = vxc(:, :, 1) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
206 0 : vxc(:, :, 2) = vxc(:, :, 2) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
207 0 : NULLIFY (deriv_data)
208 : END IF
209 : ELSE
210 37386 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_rho])
211 37386 : IF (ASSOCIATED(deriv_att)) THEN
212 37318 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
213 211605236 : vxc(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
214 37318 : NULLIFY (deriv_data)
215 : END IF
216 : END IF ! lsd
217 :
218 : ! Derivatives with respect to the gradient
219 45024 : IF (lsd) THEN
220 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa])
221 7638 : IF (ASSOCIATED(deriv_att)) THEN
222 4372 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
223 238252 : DO ir = 1, nr
224 11920732 : DO ia = 1, na
225 46963800 : DO idir = 1, 3
226 46729920 : IF (rho_set%norm_drhoa(ia, ir, 1) > drho_cutoff) THEN
227 : vxg(idir, ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)* &
228 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
229 29872818 : rho_set%norm_drhoa(ia, ir, 1)*my_adiabatic_rescale_factor
230 : ELSE
231 5174622 : vxg(idir, ia, ir, 1) = 0.0_dp
232 : END IF
233 : END DO
234 : END DO
235 : END DO
236 4372 : NULLIFY (deriv_data)
237 : END IF
238 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob])
239 7638 : IF (ASSOCIATED(deriv_att)) THEN
240 4372 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
241 238252 : DO ir = 1, nr
242 11920732 : DO ia = 1, na
243 46963800 : DO idir = 1, 3
244 46729920 : IF (rho_set%norm_drhob(ia, ir, 1) > drho_cutoff) THEN
245 : vxg(idir, ia, ir, 2) = rho_set%drhob(idir)%array(ia, ir, 1)* &
246 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
247 29374686 : rho_set%norm_drhob(ia, ir, 1)*my_adiabatic_rescale_factor
248 : ELSE
249 5672754 : vxg(idir, ia, ir, 2) = 0.0_dp
250 : END IF
251 : END DO
252 : END DO
253 : END DO
254 4372 : NULLIFY (deriv_data)
255 : END IF
256 : ! Cross Terms
257 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
258 7638 : IF (ASSOCIATED(deriv_att)) THEN
259 4324 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
260 235804 : DO ir = 1, nr
261 11798284 : DO ia = 1, na
262 46481400 : DO idir = 1, 3
263 46249920 : IF (rho_set%norm_drho(ia, ir, 1) > drho_cutoff) THEN
264 : vxg(idir, ia, ir, 1:2) = &
265 : vxg(idir, ia, ir, 1:2) + ( &
266 : rho_set%drhoa(idir)%array(ia, ir, 1) + &
267 : rho_set%drhob(idir)%array(ia, ir, 1))* &
268 : deriv_data(ia, ir, 1)*w(ia, ir)/rho_set%norm_drho(ia, ir, 1)* &
269 88773804 : my_adiabatic_rescale_factor
270 : END IF
271 : END DO
272 : END DO
273 : END DO
274 4324 : NULLIFY (deriv_data)
275 : END IF
276 : ELSE
277 37386 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
278 37386 : IF (ASSOCIATED(deriv_att)) THEN
279 20886 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
280 1084786 : DO ir = 1, nr
281 54459786 : DO ia = 1, na
282 54438900 : IF (rho_set%norm_drho(ia, ir, 1) > drho_cutoff) THEN
283 184118912 : DO idir = 1, 3
284 : vxg(idir, ia, ir, 1) = rho_set%drho(idir)%array(ia, ir, 1)* &
285 : deriv_data(ia, ir, 1)*w(ia, ir)/ &
286 184118912 : rho_set%norm_drho(ia, ir, 1)*my_adiabatic_rescale_factor
287 : END DO
288 : ELSE
289 29381088 : vxg(1:3, ia, ir, 1) = 0.0_dp
290 : END IF
291 : END DO
292 : END DO
293 20886 : NULLIFY (deriv_data)
294 : END IF
295 : END IF ! lsd
296 : ! Derivative with respect to tau
297 45024 : IF (lsd) THEN
298 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_a])
299 7638 : IF (ASSOCIATED(deriv_att)) THEN
300 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
301 0 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
302 0 : NULLIFY (deriv_data)
303 : END IF
304 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau_b])
305 7638 : IF (ASSOCIATED(deriv_att)) THEN
306 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
307 0 : vtau(:, :, 2) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
308 0 : NULLIFY (deriv_data)
309 : END IF
310 7638 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
311 7638 : IF (ASSOCIATED(deriv_att)) THEN
312 0 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
313 0 : vtau(:, :, 1) = vtau(:, :, 1) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
314 0 : vtau(:, :, 2) = vtau(:, :, 2) + deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
315 0 : NULLIFY (deriv_data)
316 : END IF
317 : ELSE
318 37386 : deriv_att => xc_dset_get_derivative(deriv_set, [deriv_tau])
319 37386 : IF (ASSOCIATED(deriv_att)) THEN
320 616 : CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
321 3782432 : vtau(:, :, 1) = deriv_data(:, :, 1)*w(:, :)*my_adiabatic_rescale_factor
322 616 : NULLIFY (deriv_data)
323 : END IF
324 : END IF ! lsd
325 : END IF ! only_energy
326 : END IF ! epr_xc
327 :
328 47130 : CALL timestop(handle)
329 :
330 47130 : END SUBROUTINE vxc_of_r_new
331 :
332 : ! **************************************************************************************************
333 : !> \brief ...
334 : !> \param rho_set ...
335 : !> \param rho1_set ...
336 : !> \param xc_section ...
337 : !> \param deriv_set ...
338 : !> \param w ...
339 : !> \param vxc ...
340 : !> \param vxg ...
341 : !> \param do_triplet ...
342 : ! **************************************************************************************************
343 10060 : SUBROUTINE xc_2nd_deriv_of_r(rho_set, rho1_set, xc_section, &
344 : deriv_set, w, vxc, vxg, do_triplet)
345 :
346 : ! As input of this routine one gets rho and drho on a one dimensional grid.
347 : ! The grid is the angular grid corresponding to a given point ir on the radial grid.
348 : ! The derivatives are calculated on this one dimensional grid, the results are stored in
349 : ! vxc(1:na,ir,ispin), vxg(1:na,ir,ispin), vxg_cross(1:na,ir,ispin)
350 : ! Afterwords the arrays containing the derivatives are put to zero so that the routine
351 : ! can safely be called for the next radial point ir
352 :
353 : TYPE(xc_rho_set_type), INTENT(IN) :: rho_set, rho1_set
354 : TYPE(section_vals_type), POINTER :: xc_section
355 : TYPE(xc_derivative_set_type), INTENT(INOUT) :: deriv_set
356 : REAL(dp), DIMENSION(:, :), POINTER :: w
357 : REAL(dp), CONTIGUOUS, DIMENSION(:, :, :), POINTER :: vxc
358 : REAL(dp), DIMENSION(:, :, :, :), POINTER :: vxg
359 : LOGICAL, INTENT(IN), OPTIONAL :: do_triplet
360 :
361 : CHARACTER(LEN=*), PARAMETER :: routineN = 'xc_2nd_deriv_of_r'
362 :
363 : INTEGER :: handle, ispin, nspins
364 : LOGICAL :: lsd
365 : REAL(dp) :: drho_cutoff, my_fac_triplet
366 : TYPE(cp_sll_xc_deriv_type), POINTER :: pos
367 : TYPE(pw_pool_type), POINTER :: pw_pool
368 10060 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: vxc_pw, vxc_tau_pw
369 : TYPE(section_vals_type), POINTER :: xc_fun_section
370 : TYPE(xc_derivative_type), POINTER :: deriv_att
371 :
372 10060 : CALL timeset(routineN, handle)
373 :
374 10060 : nspins = SIZE(vxc, 3)
375 10060 : lsd = (nspins == 2)
376 10060 : IF (ASSOCIATED(rho_set%rhoa)) THEN
377 776 : lsd = .TRUE.
378 : END IF
379 10060 : my_fac_triplet = 1.0_dp
380 10060 : IF ((PRESENT(do_triplet)) .AND. (do_triplet)) my_fac_triplet = -1.0_dp
381 :
382 10060 : CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff)
383 : xc_fun_section => section_vals_get_subs_vals(xc_section, &
384 10060 : "XC_FUNCTIONAL")
385 :
386 : ! Calculate the derivatives
387 : CALL xc_functionals_eval(xc_fun_section, &
388 : lsd=lsd, &
389 : rho_set=rho_set, &
390 : deriv_set=deriv_set, &
391 10060 : deriv_order=2)
392 :
393 10060 : CALL divide_by_norm_drho(deriv_set, rho_set, lsd)
394 :
395 : ! multiply by w
396 10060 : pos => deriv_set%derivs
397 67236 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
398 291722012 : deriv_att%deriv_data(:, :, 1) = w(:, :)*deriv_att%deriv_data(:, :, 1)
399 : END DO
400 :
401 10060 : NULLIFY (pw_pool)
402 40368 : ALLOCATE (vxc_pw(nspins))
403 20248 : DO ispin = 1, nspins
404 20248 : vxc_pw(ispin)%array => vxc(:, :, ispin:ispin)
405 : END DO
406 :
407 10060 : NULLIFY (vxc_tau_pw)
408 :
409 : CALL xc_calc_2nd_deriv_analytical(vxc_pw, vxc_tau_pw, deriv_set, rho_set, rho1_set, pw_pool, &
410 10060 : xc_section, gapw=.TRUE., vxg=vxg, tddfpt_fac=my_fac_triplet)
411 :
412 10060 : DEALLOCATE (vxc_pw)
413 :
414 : ! zero the derivative data for the next call
415 10060 : pos => deriv_set%derivs
416 67236 : DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
417 145923212 : deriv_att%deriv_data = 0.0_dp
418 : END DO
419 :
420 10060 : CALL timestop(handle)
421 :
422 20120 : END SUBROUTINE xc_2nd_deriv_of_r
423 :
424 : ! **************************************************************************************************
425 : !> \brief ...
426 : !> \param rho_set ...
427 : !> \param needs ...
428 : !> \param nspins ...
429 : !> \param bo ...
430 : ! **************************************************************************************************
431 108270 : SUBROUTINE xc_rho_set_atom_update(rho_set, needs, nspins, bo)
432 :
433 : ! This routine allocates the storage arrays for rho and drho
434 : ! In calculate_vxc_atom this is called once for each atomic_kind,
435 : ! After the loop over all the atoms of the kind and over all the points
436 : ! of the radial grid for each atom, rho_set is deallocated.
437 : ! Within the same kind, at each new point on the radial grid, the rho_set
438 : ! arrays rho and drho are overwritten.
439 :
440 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
441 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
442 : INTEGER, INTENT(IN) :: nspins
443 : INTEGER, DIMENSION(2, 3), INTENT(IN) :: bo
444 :
445 : INTEGER :: idir
446 :
447 202393 : SELECT CASE (nspins)
448 : CASE (1)
449 : ! What is this for?
450 94123 : IF (needs%rho_1_3) THEN
451 4119 : NULLIFY (rho_set%rho_1_3)
452 20595 : ALLOCATE (rho_set%rho_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
453 4119 : rho_set%owns%rho_1_3 = .TRUE.
454 4119 : rho_set%has%rho_1_3 = .FALSE.
455 : END IF
456 : ! Allocate the storage space for the density
457 94123 : IF (needs%rho) THEN
458 94123 : NULLIFY (rho_set%rho)
459 470615 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
460 94123 : rho_set%owns%rho = .TRUE.
461 94123 : rho_set%has%rho = .FALSE.
462 : END IF
463 : ! Allocate the storage space for the norm of the gradient of the density
464 94123 : IF (needs%norm_drho) THEN
465 67101 : NULLIFY (rho_set%norm_drho)
466 335505 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
467 67101 : rho_set%owns%norm_drho = .TRUE.
468 67101 : rho_set%has%norm_drho = .FALSE.
469 : END IF
470 : ! Allocate the storage space for the three components of the gradient of the density
471 94123 : IF (needs%drho) THEN
472 183328 : DO idir = 1, 3
473 137496 : NULLIFY (rho_set%drho(idir)%array)
474 733312 : ALLOCATE (rho_set%drho(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
475 : END DO
476 45832 : rho_set%owns%drho = .TRUE.
477 45832 : rho_set%has%drho = .FALSE.
478 : END IF
479 : CASE (2)
480 : ! Allocate the storage space for the total density
481 14147 : IF (needs%rho) THEN
482 : ! this should never be the case unless you use LDA functionals with LSD
483 0 : NULLIFY (rho_set%rho)
484 0 : ALLOCATE (rho_set%rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
485 0 : rho_set%owns%rho = .TRUE.
486 0 : rho_set%has%rho = .FALSE.
487 : END IF
488 : ! What is this for?
489 14147 : IF (needs%rho_1_3) THEN
490 0 : NULLIFY (rho_set%rho_1_3)
491 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)))
492 0 : rho_set%owns%rho_1_3 = .TRUE.
493 0 : rho_set%has%rho_1_3 = .FALSE.
494 : END IF
495 : ! What is this for?
496 14147 : IF (needs%rho_spin_1_3) THEN
497 2448 : NULLIFY (rho_set%rhoa_1_3, rho_set%rhob_1_3)
498 12240 : ALLOCATE (rho_set%rhoa_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
499 12240 : ALLOCATE (rho_set%rhob_1_3(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
500 2448 : rho_set%owns%rho_spin_1_3 = .TRUE.
501 2448 : rho_set%has%rho_spin_1_3 = .FALSE.
502 : END IF
503 : ! Allocate the storage space for the spin densities rhoa and rhob
504 14147 : IF (needs%rho_spin) THEN
505 14147 : NULLIFY (rho_set%rhoa, rho_set%rhob)
506 70735 : ALLOCATE (rho_set%rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
507 70735 : ALLOCATE (rho_set%rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
508 14147 : rho_set%owns%rho_spin = .TRUE.
509 14147 : rho_set%has%rho_spin = .FALSE.
510 : END IF
511 : ! Allocate the storage space for the norm of the gradient of the total density
512 14147 : IF (needs%norm_drho) THEN
513 8745 : NULLIFY (rho_set%norm_drho)
514 43725 : ALLOCATE (rho_set%norm_drho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
515 8745 : rho_set%owns%norm_drho = .TRUE.
516 8745 : rho_set%has%norm_drho = .FALSE.
517 : END IF
518 : ! Allocate the storage space for the norm of the gradient of rhoa and of rhob separatedly
519 14147 : IF (needs%norm_drho_spin) THEN
520 8793 : NULLIFY (rho_set%norm_drhoa, rho_set%norm_drhob)
521 43965 : ALLOCATE (rho_set%norm_drhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
522 43965 : ALLOCATE (rho_set%norm_drhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
523 8793 : rho_set%owns%norm_drho_spin = .TRUE.
524 8793 : rho_set%has%norm_drho_spin = .FALSE.
525 : END IF
526 : ! Allocate the storage space for the components of the gradient for the total rho
527 14147 : IF (needs%drho) THEN
528 0 : DO idir = 1, 3
529 0 : NULLIFY (rho_set%drho(idir)%array)
530 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)))
531 : END DO
532 0 : rho_set%owns%drho = .TRUE.
533 0 : rho_set%has%drho = .FALSE.
534 : END IF
535 : ! Allocate the storage space for the components of the gradient for rhoa and rhob
536 122417 : IF (needs%drho_spin) THEN
537 31656 : DO idir = 1, 3
538 23742 : NULLIFY (rho_set%drhoa(idir)%array, rho_set%drhob(idir)%array)
539 118710 : ALLOCATE (rho_set%drhoa(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
540 126624 : ALLOCATE (rho_set%drhob(idir)%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
541 : END DO
542 7914 : rho_set%owns%drho_spin = .TRUE.
543 7914 : rho_set%has%drho_spin = .FALSE.
544 : END IF
545 : !
546 : END SELECT
547 :
548 : ! tau part
549 108270 : IF (needs%tau) THEN
550 996 : NULLIFY (rho_set%tau)
551 4980 : ALLOCATE (rho_set%tau(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
552 996 : rho_set%owns%tau = .TRUE.
553 : END IF
554 108270 : IF (needs%tau_spin) THEN
555 2 : NULLIFY (rho_set%tau_a, rho_set%tau_b)
556 10 : ALLOCATE (rho_set%tau_a(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
557 10 : ALLOCATE (rho_set%tau_b(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
558 2 : rho_set%owns%tau_spin = .TRUE.
559 2 : rho_set%has%tau_spin = .FALSE.
560 : END IF
561 :
562 : ! Laplace part
563 108270 : IF (needs%laplace_rho) THEN
564 0 : NULLIFY (rho_set%laplace_rho)
565 0 : ALLOCATE (rho_set%laplace_rho(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
566 0 : rho_set%owns%laplace_rho = .TRUE.
567 : END IF
568 108270 : IF (needs%laplace_rho_spin) THEN
569 0 : NULLIFY (rho_set%laplace_rhoa)
570 0 : NULLIFY (rho_set%laplace_rhob)
571 0 : ALLOCATE (rho_set%laplace_rhoa(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
572 0 : ALLOCATE (rho_set%laplace_rhob(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
573 0 : rho_set%owns%laplace_rho_spin = .TRUE.
574 0 : rho_set%has%laplace_rho_spin = .TRUE.
575 : END IF
576 :
577 108270 : END SUBROUTINE xc_rho_set_atom_update
578 :
579 : ! **************************************************************************************************
580 : !> \brief ...
581 : !> \param rho_set ...
582 : !> \param lsd ...
583 : !> \param nspins ...
584 : !> \param needs ...
585 : !> \param rho ...
586 : !> \param drho ...
587 : !> \param tau ...
588 : !> \param na ...
589 : !> \param ir ...
590 : ! **************************************************************************************************
591 3650380 : SUBROUTINE fill_rho_set(rho_set, lsd, nspins, needs, rho, drho, tau, na, ir)
592 :
593 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
594 : LOGICAL, INTENT(IN) :: lsd
595 : INTEGER, INTENT(IN) :: nspins
596 : TYPE(xc_rho_cflags_type), INTENT(IN) :: needs
597 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: rho
598 : REAL(dp), DIMENSION(:, :, :, :), INTENT(IN) :: drho
599 : REAL(dp), DIMENSION(:, :, :), INTENT(IN) :: tau
600 : INTEGER, INTENT(IN) :: na, ir
601 :
602 : REAL(KIND=dp), PARAMETER :: f13 = (1.0_dp/3.0_dp)
603 :
604 : INTEGER :: ia, idir, my_nspins
605 : LOGICAL :: gradient_f, tddft_split
606 :
607 3650380 : my_nspins = nspins
608 3650380 : tddft_split = .FALSE.
609 3650380 : IF (lsd .AND. nspins == 1) THEN
610 59400 : my_nspins = 2
611 59400 : tddft_split = .TRUE.
612 : END IF
613 :
614 : ! some checks
615 3650380 : IF (lsd) THEN
616 : ELSE
617 3025900 : CPASSERT(SIZE(rho, 3) == 1)
618 : END IF
619 3025900 : SELECT CASE (my_nspins)
620 : CASE (1)
621 3025900 : CPASSERT(.NOT. needs%rho_spin)
622 3025900 : CPASSERT(.NOT. needs%drho_spin)
623 3025900 : CPASSERT(.NOT. needs%norm_drho_spin)
624 3025900 : CPASSERT(.NOT. needs%rho_spin_1_3)
625 : CASE (2)
626 : CASE default
627 3650380 : CPABORT("Unsupported number of spins")
628 : END SELECT
629 :
630 : gradient_f = (needs%drho_spin .OR. needs%norm_drho_spin .OR. &
631 3650380 : needs%drho .OR. needs%norm_drho)
632 :
633 3025900 : SELECT CASE (my_nspins)
634 : CASE (1)
635 : ! Give rho to 1/3
636 3025900 : IF (needs%rho_1_3) THEN
637 6877800 : DO ia = 1, na
638 6877800 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
639 : END DO
640 135000 : rho_set%owns%rho_1_3 = .TRUE.
641 135000 : rho_set%has%rho_1_3 = .TRUE.
642 : END IF
643 : ! Give the density
644 3025900 : IF (needs%rho) THEN
645 154500900 : DO ia = 1, na
646 154500900 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
647 : END DO
648 3025900 : rho_set%owns%rho = .TRUE.
649 3025900 : rho_set%has%rho = .TRUE.
650 : END IF
651 : ! Give the norm of the gradient of the density
652 3025900 : IF (needs%norm_drho) THEN
653 89894100 : DO ia = 1, na
654 89894100 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
655 : END DO
656 1759100 : rho_set%owns%norm_drho = .TRUE.
657 1759100 : rho_set%has%norm_drho = .TRUE.
658 : END IF
659 : ! Give the three components of the gradient of the density
660 3025900 : IF (needs%drho) THEN
661 7036400 : DO idir = 1, 3
662 271441400 : DO ia = 1, na
663 269682300 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
664 : END DO
665 : END DO
666 1759100 : rho_set%owns%drho = .TRUE.
667 1759100 : rho_set%has%drho = .TRUE.
668 : END IF
669 : CASE (2)
670 : ! Give the total density
671 624480 : IF (needs%rho) THEN
672 : ! this should never be the case unless you use LDA functionals with LSD
673 0 : IF (.NOT. tddft_split) THEN
674 0 : DO ia = 1, na
675 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1) + rho(ia, ir, 2)
676 : END DO
677 : ELSE
678 0 : DO ia = 1, na
679 0 : rho_set%rho(ia, ir, 1) = rho(ia, ir, 1)
680 : END DO
681 : END IF
682 0 : rho_set%owns%rho = .TRUE.
683 0 : rho_set%has%rho = .TRUE.
684 : END IF
685 : ! Give the total density to 1/3
686 624480 : IF (needs%rho_1_3) THEN
687 0 : IF (.NOT. tddft_split) THEN
688 0 : DO ia = 1, na
689 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1) + rho(ia, ir, 2), 0.0_dp)**f13
690 : END DO
691 : ELSE
692 0 : DO ia = 1, na
693 0 : rho_set%rho_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
694 : END DO
695 : END IF
696 0 : rho_set%owns%rho_1_3 = .TRUE.
697 0 : rho_set%has%rho_1_3 = .TRUE.
698 : END IF
699 : ! Give the spin densities to 1/3
700 624480 : IF (needs%rho_spin_1_3) THEN
701 75680 : IF (.NOT. tddft_split) THEN
702 3848160 : DO ia = 1, na
703 3772480 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(rho(ia, ir, 1), 0.0_dp)**f13
704 3848160 : rho_set%rhob_1_3(ia, ir, 1) = MAX(rho(ia, ir, 2), 0.0_dp)**f13
705 : END DO
706 : ELSE
707 0 : DO ia = 1, na
708 0 : rho_set%rhoa_1_3(ia, ir, 1) = MAX(0.5_dp*rho(ia, ir, 1), 0.0_dp)**f13
709 0 : rho_set%rhob_1_3(ia, ir, 1) = rho_set%rhoa_1_3(ia, ir, 1)
710 : END DO
711 : END IF
712 75680 : rho_set%owns%rho_spin_1_3 = .TRUE.
713 75680 : rho_set%has%rho_spin_1_3 = .TRUE.
714 : END IF
715 : ! Give the spin densities rhoa and rhob
716 624480 : IF (needs%rho_spin) THEN
717 624480 : IF (.NOT. tddft_split) THEN
718 28807560 : DO ia = 1, na
719 28242480 : rho_set%rhoa(ia, ir, 1) = rho(ia, ir, 1)
720 28807560 : rho_set%rhob(ia, ir, 1) = rho(ia, ir, 2)
721 : END DO
722 : ELSE
723 3029400 : DO ia = 1, na
724 2970000 : rho_set%rhoa(ia, ir, 1) = 0.5_dp*rho(ia, ir, 1)
725 3029400 : rho_set%rhob(ia, ir, 1) = rho_set%rhoa(ia, ir, 1)
726 : END DO
727 : END IF
728 624480 : rho_set%owns%rho_spin = .TRUE.
729 624480 : rho_set%has%rho_spin = .TRUE.
730 : END IF
731 : ! Give the norm of the gradient of the total density
732 624480 : IF (needs%norm_drho) THEN
733 318280 : IF (.NOT. tddft_split) THEN
734 13986960 : DO ia = 1, na
735 : rho_set%norm_drho(ia, ir, 1) = SQRT( &
736 : (drho(1, ia, ir, 1) + drho(1, ia, ir, 2))**2 + &
737 : (drho(2, ia, ir, 1) + drho(2, ia, ir, 2))**2 + &
738 13986960 : (drho(3, ia, ir, 1) + drho(3, ia, ir, 2))**2)
739 : END DO
740 : ELSE
741 2233800 : DO ia = 1, na
742 2233800 : rho_set%norm_drho(ia, ir, 1) = drho(4, ia, ir, 1)
743 : END DO
744 : END IF
745 318280 : rho_set%owns%norm_drho = .TRUE.
746 318280 : rho_set%has%norm_drho = .TRUE.
747 : END IF
748 : ! Give the norm of the gradient of rhoa and of rhob separatedly
749 624480 : IF (needs%norm_drho_spin) THEN
750 320680 : IF (.NOT. tddft_split) THEN
751 14109360 : DO ia = 1, na
752 13832480 : rho_set%norm_drhoa(ia, ir, 1) = drho(4, ia, ir, 1)
753 14109360 : rho_set%norm_drhob(ia, ir, 1) = drho(4, ia, ir, 2)
754 : END DO
755 : ELSE
756 2233800 : DO ia = 1, na
757 2190000 : rho_set%norm_drhoa(ia, ir, 1) = 0.5_dp*drho(4, ia, ir, 1)
758 2233800 : rho_set%norm_drhob(ia, ir, 1) = rho_set%norm_drhoa(ia, ir, 1)
759 : END DO
760 : END IF
761 320680 : rho_set%owns%norm_drho_spin = .TRUE.
762 320680 : rho_set%has%norm_drho_spin = .TRUE.
763 : END IF
764 : ! Give the components of the gradient for the total rho
765 624480 : IF (needs%drho) THEN
766 0 : IF (.NOT. tddft_split) THEN
767 0 : DO idir = 1, 3
768 0 : DO ia = 1, na
769 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1) + drho(idir, ia, ir, 2)
770 : END DO
771 : END DO
772 : ELSE
773 0 : DO idir = 1, 3
774 0 : DO ia = 1, na
775 0 : rho_set%drho(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
776 : END DO
777 : END DO
778 : END IF
779 0 : rho_set%owns%drho = .TRUE.
780 0 : rho_set%has%drho = .TRUE.
781 : END IF
782 : ! Give the components of the gradient for rhoa and rhob
783 4274860 : IF (needs%drho_spin) THEN
784 322180 : IF (.NOT. tddft_split) THEN
785 1113520 : DO idir = 1, 3
786 42835960 : DO ia = 1, na
787 41722440 : rho_set%drhoa(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 1)
788 42557580 : rho_set%drhob(idir)%array(ia, ir, 1) = drho(idir, ia, ir, 2)
789 : END DO
790 : END DO
791 : ELSE
792 175200 : DO idir = 1, 3
793 6745200 : DO ia = 1, na
794 6570000 : rho_set%drhoa(idir)%array(ia, ir, 1) = 0.5_dp*drho(idir, ia, ir, 1)
795 6701400 : rho_set%drhob(idir)%array(ia, ir, 1) = rho_set%drhoa(idir)%array(ia, ir, 1)
796 : END DO
797 : END DO
798 : END IF
799 322180 : rho_set%owns%drho_spin = .TRUE.
800 322180 : rho_set%has%drho_spin = .TRUE.
801 : END IF
802 : !
803 : END SELECT
804 :
805 : ! tau part
806 3650380 : IF (needs%tau .OR. needs%tau_spin) THEN
807 3650380 : CPASSERT(SIZE(tau, 3) == my_nspins)
808 : END IF
809 3650380 : IF (needs%tau) THEN
810 33400 : IF (my_nspins == 2) THEN
811 0 : DO ia = 1, na
812 0 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1) + tau(ia, ir, 2)
813 : END DO
814 0 : rho_set%owns%tau = .TRUE.
815 0 : rho_set%has%tau = .TRUE.
816 : ELSE
817 1890600 : DO ia = 1, na
818 1890600 : rho_set%tau(ia, ir, 1) = tau(ia, ir, 1)
819 : END DO
820 33400 : rho_set%owns%tau = .TRUE.
821 33400 : rho_set%has%tau = .TRUE.
822 : END IF
823 : END IF
824 3650380 : IF (needs%tau_spin) THEN
825 0 : DO ia = 1, na
826 0 : rho_set%tau_a(ia, ir, 1) = tau(ia, ir, 1)
827 0 : rho_set%tau_b(ia, ir, 1) = tau(ia, ir, 2)
828 : END DO
829 0 : rho_set%owns%tau_spin = .TRUE.
830 0 : rho_set%has%tau_spin = .TRUE.
831 : END IF
832 :
833 3650380 : END SUBROUTINE fill_rho_set
834 :
835 : END MODULE xc_atom
|