Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief routines that build the integrals of the Vxc potential calculated
10 : !> for the atomic code
11 : ! **************************************************************************************************
12 : MODULE atom_xc
13 :
14 : USE atom_types, ONLY: atom_basis_type,&
15 : atom_type,&
16 : gth_pseudo,&
17 : opmat_type,&
18 : sgp_pseudo,&
19 : upf_pseudo
20 : USE atom_utils, ONLY: atom_core_density,&
21 : atom_density,&
22 : coulomb_potential_numeric,&
23 : integrate_grid,&
24 : numpot_matrix
25 : USE cp_files, ONLY: close_file,&
26 : open_file
27 : USE input_constants, ONLY: xc_none
28 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
29 : section_vals_type,&
30 : section_vals_val_get
31 : USE kinds, ONLY: dp
32 : USE mathconstants, ONLY: fourpi,&
33 : pi
34 : USE xc_atom, ONLY: xc_rho_set_atom_update
35 : USE xc_derivative_desc, ONLY: &
36 : deriv_norm_drho, deriv_norm_drhoa, deriv_norm_drhob, deriv_rho, deriv_rhoa, deriv_rhob, &
37 : deriv_tau, deriv_tau_a, deriv_tau_b
38 : USE xc_derivative_set_types, ONLY: xc_derivative_set_type,&
39 : xc_dset_create,&
40 : xc_dset_get_derivative,&
41 : xc_dset_release,&
42 : xc_dset_zero_all
43 : USE xc_derivative_types, ONLY: xc_derivative_get,&
44 : xc_derivative_type
45 : USE xc_derivatives, ONLY: xc_functionals_eval,&
46 : xc_functionals_get_needs
47 : USE xc_rho_cflags_types, ONLY: xc_rho_cflags_type
48 : USE xc_rho_set_types, ONLY: xc_rho_set_create,&
49 : xc_rho_set_release,&
50 : xc_rho_set_type
51 : #include "./base/base_uses.f90"
52 :
53 : IMPLICIT NONE
54 :
55 : PRIVATE
56 :
57 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'atom_xc'
58 :
59 : ! ZMP added coulomb_potential_numeric
60 : ! ZMP added public subroutines calculate_atom_zmp, calculate_atom_ext_vxc
61 : PUBLIC :: calculate_atom_vxc_lda, calculate_atom_vxc_lsd, &
62 : calculate_atom_zmp, calculate_atom_ext_vxc
63 : PUBLIC :: atom_vxc_lda, atom_vxc_lsd, atom_dpot_lda
64 :
65 : CONTAINS
66 :
67 : ! **************************************************************************************************
68 : !> \brief ZMP subroutine for the calculation of the effective constraint
69 : !> potential in the atomic code.
70 : !> \param ext_density external electron density
71 : !> \param atom information about the atomic kind
72 : !> \param lprint save exchange-correlation potential to the file 'linear_potentials.dat'
73 : !> \param xcmat exchange-correlation potential matrix
74 : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
75 : ! **************************************************************************************************
76 0 : SUBROUTINE calculate_atom_zmp(ext_density, atom, lprint, xcmat)
77 : REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: ext_density
78 : TYPE(atom_type), INTENT(INOUT) :: atom
79 : LOGICAL :: lprint
80 : TYPE(opmat_type), OPTIONAL, POINTER :: xcmat
81 :
82 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_zmp'
83 :
84 : INTEGER :: extunit, handle, ir, nr, z
85 : REAL(KIND=dp) :: int1, int2
86 0 : REAL(KIND=dp), DIMENSION(:), POINTER :: deltarho, rho_dum, vxc, vxc1, vxc2
87 0 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rho
88 :
89 0 : CALL timeset(routineN, handle)
90 :
91 0 : nr = atom%basis%grid%nr
92 0 : z = atom%z
93 0 : ALLOCATE (rho(nr, 1), vxc(nr), vxc1(nr), vxc2(nr), rho_dum(nr), deltarho(nr))
94 0 : CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
95 : !Vxc1
96 0 : int1 = integrate_grid(ext_density, atom%basis%grid)
97 0 : int1 = fourpi*int1
98 0 : CALL coulomb_potential_numeric(vxc1, rho(:, 1), atom%basis%grid)
99 :
100 0 : vxc1 = -vxc1/z
101 :
102 : !Vxc2
103 0 : rho_dum = rho(:, 1)*int1/z
104 0 : deltarho = rho_dum - ext_density
105 0 : int2 = integrate_grid(deltarho, atom%basis%grid)
106 0 : CALL coulomb_potential_numeric(vxc2, deltarho, atom%basis%grid)
107 :
108 0 : vxc2 = vxc2*atom%lambda
109 :
110 : !Vxc
111 0 : vxc = vxc1 + vxc2
112 :
113 0 : atom%energy%exc = fourpi*integrate_grid(vxc, rho(:, 1), atom%basis%grid)
114 0 : atom%rho_diff_integral = fourpi*int2
115 :
116 0 : IF (lprint) THEN
117 : CALL open_file(file_name="linear_potentials.dat", file_status="UNKNOWN", &
118 : file_form="FORMATTED", file_action="WRITE", &
119 0 : unit_number=extunit)
120 :
121 0 : WRITE (extunit, fmt='("#",T10,"R[bohr]",T36,"Rho[au]",T61,"DRho[au]",T86,"V_XC[au]",T111,"V_XC1[au]",T136,"V_XC2[au]")')
122 0 : DO ir = 1, nr
123 : WRITE (extunit, fmt='(T1,E24.15,T26,E24.15,T51,E24.15,T76,E24.15,T101,E24.15,T126,E24.15)') &
124 0 : atom%basis%grid%rad(ir), rho(ir, 1), deltarho(ir), vxc(ir), vxc1(ir), vxc2(ir)
125 : END DO
126 0 : CALL close_file(unit_number=extunit)
127 : END IF
128 :
129 0 : IF (PRESENT(xcmat)) CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
130 :
131 0 : DEALLOCATE (rho, vxc, vxc1, vxc2, rho_dum, deltarho)
132 :
133 0 : CALL timestop(handle)
134 :
135 0 : END SUBROUTINE calculate_atom_zmp
136 :
137 : ! **************************************************************************************************
138 : !> \brief ZMP subroutine for the scf external density from the external v_xc.
139 : !> \param vxc exchange-correlation potential
140 : !> \param atom information about the atomic kind
141 : !> \param lprint save exchange-correlation potential to the file 'linear_potentials.dat'
142 : !> \param xcmat exchange-correlation potential matrix
143 : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
144 : ! **************************************************************************************************
145 0 : SUBROUTINE calculate_atom_ext_vxc(vxc, atom, lprint, xcmat)
146 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: vxc
147 : TYPE(atom_type), INTENT(INOUT) :: atom
148 : LOGICAL, INTENT(in) :: lprint
149 : TYPE(opmat_type), INTENT(inout), OPTIONAL, POINTER :: xcmat
150 :
151 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_ext_vxc'
152 :
153 : INTEGER :: extunit, handle, ir, nr
154 0 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rho
155 :
156 0 : CALL timeset(routineN, handle)
157 0 : nr = atom%basis%grid%nr
158 :
159 0 : ALLOCATE (rho(nr, 1))
160 :
161 0 : CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
162 :
163 0 : IF (lprint) THEN
164 : CALL open_file(file_name="linear_potentials.dat", file_status="UNKNOWN", &
165 : file_form="FORMATTED", file_action="WRITE", &
166 0 : unit_number=extunit)
167 :
168 0 : WRITE (extunit, fmt='("#",T10,"R[bohr]",T36,"Rho[au]",T61,"V_XC[au]")')
169 0 : DO ir = 1, nr
170 : WRITE (extunit, fmt='(T1,E24.15,T26,E24.15,T51,E24.15)') &
171 0 : atom%basis%grid%rad(ir), rho(ir, 1), vxc(ir)
172 : END DO
173 0 : CALL close_file(unit_number=extunit)
174 : END IF
175 :
176 0 : atom%energy%exc = fourpi*integrate_grid(vxc, rho(:, 1), atom%basis%grid)
177 0 : IF (PRESENT(xcmat)) CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
178 :
179 0 : DEALLOCATE (rho)
180 :
181 0 : CALL timestop(handle)
182 :
183 0 : END SUBROUTINE calculate_atom_ext_vxc
184 :
185 : ! **************************************************************************************************
186 : !> \brief Calculate atomic exchange-correlation potential in spin-restricted case.
187 : !> \param xcmat exchange-correlation potential expressed in the atomic basis set
188 : !> \param atom information about the atomic kind
189 : !> \param xc_section XC input section
190 : !> \par History
191 : !> * 03.2010 extension of GTH pseudo-potential definition [Juerg Hutter]
192 : !> * 02.2010 renamed to calculate_atom_vxc_lda() [Juerg Hutter]
193 : !> * 08.2008 created [Juerg Hutter]
194 : ! **************************************************************************************************
195 135538 : SUBROUTINE calculate_atom_vxc_lda(xcmat, atom, xc_section)
196 : TYPE(opmat_type), POINTER :: xcmat
197 : TYPE(atom_type), INTENT(INOUT) :: atom
198 : TYPE(section_vals_type), POINTER :: xc_section
199 :
200 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_vxc_lda'
201 :
202 : INTEGER :: deriv_order, handle, i, l, myfun, n1, &
203 : n2, n3, nr, nspins, unit_nr
204 : INTEGER, DIMENSION(2, 3) :: bounds
205 : LOGICAL :: lsd, nlcc
206 : REAL(KIND=dp) :: density_cut, gradient_cut, tau_cut
207 135538 : REAL(KIND=dp), DIMENSION(:), POINTER :: exc, vxc
208 135538 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: drho, lap, rho, tau
209 67769 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: taumat, xcpot
210 : TYPE(section_vals_type), POINTER :: xc_fun_section
211 : TYPE(xc_derivative_set_type) :: deriv_set
212 : TYPE(xc_derivative_type), POINTER :: deriv
213 : TYPE(xc_rho_cflags_type) :: needs
214 : TYPE(xc_rho_set_type) :: rho_set
215 :
216 67769 : CALL timeset(routineN, handle)
217 :
218 67769 : nlcc = .FALSE.
219 67769 : IF (atom%potential%ppot_type == gth_pseudo) THEN
220 58985 : nlcc = atom%potential%gth_pot%nlcc
221 8784 : ELSE IF (atom%potential%ppot_type == upf_pseudo) THEN
222 142 : nlcc = atom%potential%upf_pot%core_correction
223 8642 : ELSE IF (atom%potential%ppot_type == sgp_pseudo) THEN
224 0 : nlcc = atom%potential%sgp_pot%has_nlcc
225 : END IF
226 :
227 67769 : IF (ASSOCIATED(xc_section)) THEN
228 22831 : xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
229 22831 : CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
230 :
231 22831 : IF (myfun == xc_none) THEN
232 16 : atom%energy%exc = 0._dp
233 : ELSE
234 22815 : CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
235 22815 : CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
236 22815 : CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
237 :
238 22815 : lsd = .FALSE.
239 22815 : nspins = 1
240 22815 : needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
241 :
242 : ! Prepare the structures needed to calculate and store the xc derivatives
243 :
244 : ! Array dimension: here anly one dimensional arrays are used,
245 : ! i.e. only the first column of deriv_data is read.
246 : ! The other to dimensions are set to size equal 1
247 22815 : nr = atom%basis%grid%nr
248 228150 : bounds(1:2, 1:3) = 1
249 22815 : bounds(2, 1) = nr
250 :
251 : ! create a place where to put the derivatives
252 22815 : CALL xc_dset_create(deriv_set, local_bounds=bounds)
253 : ! create the place where to store the argument for the functionals
254 : CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
255 22815 : drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
256 : ! allocate the required 3d arrays where to store rho and drho
257 22815 : CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
258 :
259 22815 : NULLIFY (rho, drho, tau)
260 22815 : IF (needs%rho) THEN
261 68445 : ALLOCATE (rho(nr, 1))
262 22815 : CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
263 22815 : IF (nlcc) THEN
264 445 : CALL atom_core_density(rho(:, 1), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
265 : END IF
266 : END IF
267 22815 : IF (needs%norm_drho) THEN
268 66207 : ALLOCATE (drho(nr, 1))
269 22069 : CALL atom_density(drho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="DER")
270 22069 : IF (nlcc) THEN
271 445 : CALL atom_core_density(drho(:, 1), atom%potential, typ="DER", rr=atom%basis%grid%rad)
272 : END IF
273 : END IF
274 22815 : IF (needs%tau) THEN
275 324 : ALLOCATE (tau(nr, 1))
276 : CALL atom_density(tau(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, &
277 108 : typ="KIN", rr=atom%basis%grid%rad2)
278 : END IF
279 22815 : IF (needs%laplace_rho) THEN
280 0 : ALLOCATE (lap(nr, 1))
281 : CALL atom_density(lap(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, &
282 0 : typ="LAP", rr=atom%basis%grid%rad2)
283 0 : IF (nlcc) THEN
284 0 : CALL atom_core_density(lap(:, 1), atom%potential, typ="LAP", rr=atom%basis%grid%rad)
285 : END IF
286 : END IF
287 :
288 22815 : CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
289 :
290 22815 : CALL xc_dset_zero_all(deriv_set)
291 :
292 22815 : deriv_order = 1
293 : CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
294 22815 : deriv_order=deriv_order)
295 :
296 : ! Integration to get the matrix elements and energy
297 22815 : deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
298 22815 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
299 22815 : atom%energy%exc = fourpi*integrate_grid(xcpot(:, 1, 1), atom%basis%grid)
300 :
301 : ! dump grid density and xcpot (xc energy?)
302 : IF (.FALSE.) THEN
303 : CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atom.dat")
304 : DO i = 1, SIZE(xcpot(:, 1, 1))
305 : WRITE (unit_nr, *) atom%basis%grid%rad(i), rho(i, 1), xcpot(i, 1, 1)
306 : END DO
307 : CALL close_file(unit_nr)
308 : END IF
309 :
310 22815 : IF (needs%rho) THEN
311 22815 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], allocate_deriv=.FALSE.)
312 22815 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
313 22815 : CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 0)
314 : IF (.FALSE.) THEN
315 : CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atompot.dat")
316 : DO i = 1, SIZE(xcpot(:, 1, 1))
317 : WRITE (unit_nr, *) atom%basis%grid%rad(i), rho(i, 1), xcpot(i, 1, 1)
318 : END DO
319 : CALL close_file(unit_nr)
320 : END IF
321 22815 : DEALLOCATE (rho)
322 : END IF
323 22815 : IF (needs%norm_drho) THEN
324 22069 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], allocate_deriv=.FALSE.)
325 22069 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
326 22069 : CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 1)
327 : IF (.FALSE.) THEN
328 : CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atomdpot.dat")
329 : DO i = 1, SIZE(xcpot(:, 1, 1))
330 : WRITE (unit_nr, *) atom%basis%grid%rad(i), drho(i, 1), xcpot(i, 1, 1)
331 : END DO
332 : CALL close_file(unit_nr)
333 : END IF
334 22069 : DEALLOCATE (drho)
335 : END IF
336 22815 : IF (needs%tau) THEN
337 108 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau], allocate_deriv=.FALSE.)
338 108 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
339 108 : n1 = SIZE(xcmat%op, 1)
340 108 : n2 = SIZE(xcmat%op, 2)
341 108 : n3 = SIZE(xcmat%op, 3)
342 540 : ALLOCATE (taumat(n1, n2, 0:n3 - 1))
343 919980 : taumat = 0._dp
344 :
345 43308 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
346 108 : CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 2)
347 43308 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
348 108 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
349 540 : DO l = 0, 3
350 1226172 : xcmat%op(:, :, l) = xcmat%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
351 : END DO
352 :
353 108 : DEALLOCATE (tau)
354 108 : DEALLOCATE (taumat)
355 : END IF
356 :
357 : ! assume lap is not really needed
358 22815 : IF (needs%laplace_rho) THEN
359 0 : DEALLOCATE (lap)
360 : END IF
361 :
362 : ! Release the xc structure used to store the xc derivatives
363 22815 : CALL xc_dset_release(deriv_set)
364 22815 : CALL xc_rho_set_release(rho_set)
365 :
366 : END IF !xc_none
367 :
368 : ELSE
369 :
370 : ! we don't have an xc_section, use a default setup
371 44938 : nr = atom%basis%grid%nr
372 224690 : ALLOCATE (rho(nr, 1), exc(nr), vxc(nr))
373 :
374 44938 : CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
375 44938 : IF (nlcc) THEN
376 386 : CALL atom_core_density(rho(:, 1), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
377 : END IF
378 44938 : CALL lda_pade(rho(:, 1), exc, vxc)
379 :
380 44938 : atom%energy%exc = fourpi*integrate_grid(exc, atom%basis%grid)
381 44938 : CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
382 :
383 44938 : DEALLOCATE (rho, exc, vxc)
384 :
385 : END IF
386 :
387 67769 : CALL timestop(handle)
388 :
389 1287611 : END SUBROUTINE calculate_atom_vxc_lda
390 :
391 : ! **************************************************************************************************
392 : !> \brief Calculate atomic exchange-correlation potential in spin-polarized case.
393 : !> \param xcmata spin-alpha exchange-correlation potential matrix
394 : !> \param xcmatb spin-beta exchange-correlation potential matrix
395 : !> \param atom information about the atomic kind
396 : !> \param xc_section XC input section
397 : !> \par History
398 : !> * 02.2010 created [Juerg Hutter]
399 : ! **************************************************************************************************
400 2950 : SUBROUTINE calculate_atom_vxc_lsd(xcmata, xcmatb, atom, xc_section)
401 : TYPE(opmat_type), POINTER :: xcmata, xcmatb
402 : TYPE(atom_type), INTENT(INOUT) :: atom
403 : TYPE(section_vals_type), POINTER :: xc_section
404 :
405 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_vxc_lsd'
406 :
407 : INTEGER :: deriv_order, handle, l, myfun, n1, n2, &
408 : n3, nr, nspins
409 : INTEGER, DIMENSION(2, 3) :: bounds
410 : LOGICAL :: lsd, nlcc
411 : REAL(KIND=dp) :: density_cut, gradient_cut, tau_cut
412 2950 : REAL(KIND=dp), DIMENSION(:), POINTER :: exc, vxca, vxcb, xfun
413 2950 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: drho, lap, rho, tau
414 1475 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: taumat, xcpot
415 : TYPE(section_vals_type), POINTER :: xc_fun_section
416 : TYPE(xc_derivative_set_type) :: deriv_set
417 : TYPE(xc_derivative_type), POINTER :: deriv
418 : TYPE(xc_rho_cflags_type) :: needs
419 : TYPE(xc_rho_set_type) :: rho_set
420 :
421 1475 : CALL timeset(routineN, handle)
422 :
423 1475 : nlcc = .FALSE.
424 1475 : IF (atom%potential%ppot_type == gth_pseudo) THEN
425 1343 : nlcc = atom%potential%gth_pot%nlcc
426 132 : ELSE IF (atom%potential%ppot_type == upf_pseudo) THEN
427 0 : nlcc = atom%potential%upf_pot%core_correction
428 0 : CPASSERT(.NOT. nlcc)
429 132 : ELSE IF (atom%potential%ppot_type == sgp_pseudo) THEN
430 0 : nlcc = atom%potential%sgp_pot%has_nlcc
431 0 : CPASSERT(.NOT. nlcc)
432 : END IF
433 :
434 1475 : IF (ASSOCIATED(xc_section)) THEN
435 921 : IF (nlcc) THEN
436 365 : nr = atom%basis%grid%nr
437 1095 : ALLOCATE (xfun(nr))
438 : END IF
439 :
440 921 : xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
441 921 : CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
442 :
443 921 : IF (myfun == xc_none) THEN
444 0 : atom%energy%exc = 0._dp
445 : ELSE
446 921 : CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
447 921 : CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
448 921 : CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
449 :
450 921 : lsd = .TRUE.
451 921 : nspins = 2
452 921 : needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
453 :
454 : ! Prepare the structures needed to calculate and store the xc derivatives
455 :
456 : ! Array dimension: here anly one dimensional arrays are used,
457 : ! i.e. only the first column of deriv_data is read.
458 : ! The other to dimensions are set to size equal 1
459 921 : nr = atom%basis%grid%nr
460 9210 : bounds(1:2, 1:3) = 1
461 921 : bounds(2, 1) = nr
462 :
463 : ! create a place where to put the derivatives
464 921 : CALL xc_dset_create(deriv_set, local_bounds=bounds)
465 : ! create the place where to store the argument for the functionals
466 : CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
467 921 : drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
468 : ! allocate the required 3d arrays where to store rho and drho
469 921 : CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
470 :
471 921 : NULLIFY (rho, drho, tau)
472 921 : IF (needs%rho_spin) THEN
473 2763 : ALLOCATE (rho(nr, 2))
474 921 : CALL atom_density(rho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="RHO")
475 921 : CALL atom_density(rho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="RHO")
476 921 : IF (nlcc) THEN
477 146365 : xfun = 0.0_dp
478 365 : CALL atom_core_density(xfun(:), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
479 292365 : rho(:, 1) = rho(:, 1) + 0.5_dp*xfun(:)
480 292365 : rho(:, 2) = rho(:, 2) + 0.5_dp*xfun(:)
481 : END IF
482 : END IF
483 921 : IF (needs%norm_drho_spin) THEN
484 2757 : ALLOCATE (drho(nr, 2))
485 919 : CALL atom_density(drho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="DER")
486 919 : CALL atom_density(drho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="DER")
487 919 : IF (nlcc) THEN
488 146365 : xfun = 0.0_dp
489 365 : CALL atom_core_density(xfun(:), atom%potential, typ="DER", rr=atom%basis%grid%rad)
490 292365 : drho(:, 1) = drho(:, 1) + 0.5_dp*xfun(:)
491 292365 : drho(:, 2) = drho(:, 2) + 0.5_dp*xfun(:)
492 : END IF
493 : END IF
494 921 : IF (needs%tau_spin) THEN
495 6 : ALLOCATE (tau(nr, 2))
496 : CALL atom_density(tau(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, &
497 2 : typ="KIN", rr=atom%basis%grid%rad2)
498 : CALL atom_density(tau(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, &
499 2 : typ="KIN", rr=atom%basis%grid%rad2)
500 : END IF
501 921 : IF (needs%laplace_rho_spin) THEN
502 0 : ALLOCATE (lap(nr, 2))
503 : CALL atom_density(lap(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, &
504 0 : typ="LAP", rr=atom%basis%grid%rad2)
505 : CALL atom_density(lap(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, &
506 0 : typ="LAP", rr=atom%basis%grid%rad2)
507 0 : IF (nlcc) THEN
508 0 : xfun = 0.0_dp
509 0 : CALL atom_core_density(xfun(:), atom%potential, typ="LAP", rr=atom%basis%grid%rad)
510 0 : lap(:, 1) = lap(:, 1) + 0.5_dp*xfun(:)
511 0 : lap(:, 2) = lap(:, 2) + 0.5_dp*xfun(:)
512 : END IF
513 : END IF
514 :
515 921 : CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
516 :
517 921 : CALL xc_dset_zero_all(deriv_set)
518 :
519 921 : deriv_order = 1
520 : CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
521 921 : deriv_order=deriv_order)
522 :
523 : ! Integration to get the matrix elements and energy
524 921 : deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
525 921 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
526 921 : atom%energy%exc = fourpi*integrate_grid(xcpot(:, 1, 1), atom%basis%grid)
527 :
528 921 : IF (needs%rho_spin) THEN
529 921 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], allocate_deriv=.FALSE.)
530 921 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
531 921 : CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 0)
532 921 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], allocate_deriv=.FALSE.)
533 921 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
534 921 : CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 0)
535 921 : DEALLOCATE (rho)
536 : END IF
537 921 : IF (needs%norm_drho_spin) THEN
538 : ! drhoa
539 919 : NULLIFY (deriv)
540 919 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], allocate_deriv=.FALSE.)
541 919 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
542 919 : CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 1)
543 : ! drhob
544 919 : NULLIFY (deriv)
545 919 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], allocate_deriv=.FALSE.)
546 919 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
547 919 : CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 1)
548 : ! Cross Terms
549 919 : NULLIFY (deriv)
550 919 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
551 919 : IF (ASSOCIATED(deriv)) THEN
552 919 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
553 919 : CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 1)
554 919 : CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 1)
555 : END IF
556 919 : DEALLOCATE (drho)
557 : END IF
558 921 : IF (needs%tau_spin) THEN
559 2 : n1 = SIZE(xcmata%op, 1)
560 2 : n2 = SIZE(xcmata%op, 2)
561 2 : n3 = SIZE(xcmata%op, 3)
562 10 : ALLOCATE (taumat(n1, n2, 0:n3 - 1))
563 :
564 2 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_a], allocate_deriv=.FALSE.)
565 2 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
566 86 : taumat = 0._dp
567 802 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
568 2 : CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 2)
569 802 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
570 2 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
571 10 : DO l = 0, 3
572 106 : xcmata%op(:, :, l) = xcmata%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
573 : END DO
574 :
575 2 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_b], allocate_deriv=.FALSE.)
576 2 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
577 86 : taumat = 0._dp
578 802 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
579 2 : CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 2)
580 802 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
581 2 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
582 10 : DO l = 0, 3
583 106 : xcmatb%op(:, :, l) = xcmatb%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
584 : END DO
585 :
586 2 : DEALLOCATE (tau)
587 2 : DEALLOCATE (taumat)
588 : END IF
589 :
590 : ! assume lap is not really needed
591 921 : IF (needs%laplace_rho_spin) THEN
592 0 : DEALLOCATE (lap)
593 : END IF
594 :
595 : ! Release the xc structure used to store the xc derivatives
596 921 : CALL xc_dset_release(deriv_set)
597 921 : CALL xc_rho_set_release(rho_set)
598 :
599 : END IF !xc_none
600 :
601 921 : IF (nlcc) DEALLOCATE (xfun)
602 :
603 : ELSE
604 :
605 : ! we don't have an xc_section, use a default setup
606 554 : nr = atom%basis%grid%nr
607 3878 : ALLOCATE (rho(nr, 2), exc(nr), vxca(nr), vxcb(nr))
608 554 : IF (nlcc) ALLOCATE (xfun(nr))
609 :
610 554 : CALL atom_density(rho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="RHO")
611 554 : CALL atom_density(rho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="RHO")
612 554 : IF (nlcc) THEN
613 0 : xfun(:) = 0.0_dp
614 0 : CALL atom_core_density(xfun(:), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
615 0 : rho(:, 1) = rho(:, 1) + 0.5_dp*xfun(:)
616 0 : rho(:, 2) = rho(:, 2) + 0.5_dp*xfun(:)
617 : END IF
618 554 : CALL lsd_pade(rho(:, 1), rho(:, 2), exc, vxca, vxcb)
619 :
620 554 : atom%energy%exc = fourpi*integrate_grid(exc, atom%basis%grid)
621 554 : CALL numpot_matrix(xcmata%op, vxca, atom%basis, 0)
622 554 : CALL numpot_matrix(xcmatb%op, vxcb, atom%basis, 0)
623 :
624 554 : DEALLOCATE (rho, exc, vxca, vxcb)
625 554 : IF (nlcc) DEALLOCATE (xfun)
626 :
627 : END IF
628 :
629 1475 : CALL timestop(handle)
630 :
631 28025 : END SUBROUTINE calculate_atom_vxc_lsd
632 :
633 : ! **************************************************************************************************
634 : !> \brief Alternative subroutine that calculates atomic exchange-correlation potential
635 : !> in spin-restricted case.
636 : !> \param basis atomic basis set
637 : !> \param pmat density matrix
638 : !> \param maxl maximum angular momentum
639 : !> \param xc_section XC input section
640 : !> \param fexc exchange-correlation energy
641 : !> \param xcmat exchange-correlation potential matrix
642 : !> \par History
643 : !> * 07.2016 ADMM analysis [Juerg Hutter]
644 : ! **************************************************************************************************
645 8 : SUBROUTINE atom_vxc_lda(basis, pmat, maxl, xc_section, fexc, xcmat)
646 : TYPE(atom_basis_type), POINTER :: basis
647 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: pmat
648 : INTEGER, INTENT(IN) :: maxl
649 : TYPE(section_vals_type), POINTER :: xc_section
650 : REAL(KIND=dp), INTENT(OUT) :: fexc
651 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: xcmat
652 :
653 : CHARACTER(LEN=*), PARAMETER :: routineN = 'atom_vxc_lda'
654 :
655 : INTEGER :: deriv_order, handle, l, myfun, n1, n2, &
656 : n3, nr, nspins
657 : INTEGER, DIMENSION(2, 3) :: bounds
658 : LOGICAL :: lsd
659 : REAL(KIND=dp) :: density_cut, gradient_cut, tau_cut
660 16 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: drho, lap, rho, tau
661 8 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: taumat, xcpot
662 : TYPE(section_vals_type), POINTER :: xc_fun_section
663 : TYPE(xc_derivative_set_type) :: deriv_set
664 : TYPE(xc_derivative_type), POINTER :: deriv
665 : TYPE(xc_rho_cflags_type) :: needs
666 : TYPE(xc_rho_set_type) :: rho_set
667 :
668 8 : CALL timeset(routineN, handle)
669 :
670 8 : CPASSERT(ASSOCIATED(xc_section))
671 :
672 8 : xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
673 8 : CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
674 :
675 8 : IF (myfun == xc_none) THEN
676 0 : fexc = 0._dp
677 : ELSE
678 8 : CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
679 8 : CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
680 8 : CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
681 :
682 8 : lsd = .FALSE.
683 8 : nspins = 1
684 8 : needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
685 :
686 : ! Prepare the structures needed to calculate and store the xc derivatives
687 :
688 : ! Array dimension: here anly one dimensional arrays are used,
689 : ! i.e. only the first column of deriv_data is read.
690 : ! The other to dimensions are set to size equal 1
691 8 : nr = basis%grid%nr
692 80 : bounds(1:2, 1:3) = 1
693 8 : bounds(2, 1) = nr
694 :
695 : ! create a place where to put the derivatives
696 8 : CALL xc_dset_create(deriv_set, local_bounds=bounds)
697 : ! create the place where to store the argument for the functionals
698 : CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
699 8 : drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
700 : ! allocate the required 3d arrays where to store rho and drho
701 8 : CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
702 :
703 8 : NULLIFY (rho, drho, tau)
704 8 : IF (needs%rho) THEN
705 24 : ALLOCATE (rho(nr, 1))
706 8 : CALL atom_density(rho(:, 1), pmat, basis, maxl, typ="RHO")
707 : END IF
708 8 : IF (needs%norm_drho) THEN
709 24 : ALLOCATE (drho(nr, 1))
710 8 : CALL atom_density(drho(:, 1), pmat, basis, maxl, typ="DER")
711 : END IF
712 8 : IF (needs%tau) THEN
713 0 : ALLOCATE (tau(nr, 1))
714 0 : CALL atom_density(tau(:, 1), pmat, basis, maxl, typ="KIN", rr=basis%grid%rad2)
715 : END IF
716 8 : IF (needs%laplace_rho) THEN
717 0 : ALLOCATE (lap(nr, 1))
718 0 : CALL atom_density(lap(:, 1), pmat, basis, maxl, typ="LAP", rr=basis%grid%rad2)
719 : END IF
720 :
721 8 : CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
722 :
723 8 : CALL xc_dset_zero_all(deriv_set)
724 :
725 8 : deriv_order = 1
726 : CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
727 8 : deriv_order=deriv_order)
728 :
729 : ! Integration to get the matrix elements and energy
730 8 : deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
731 8 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
732 8 : fexc = fourpi*integrate_grid(xcpot(:, 1, 1), basis%grid)
733 :
734 8 : IF (needs%rho) THEN
735 8 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], allocate_deriv=.FALSE.)
736 8 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
737 8 : CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 0)
738 8 : DEALLOCATE (rho)
739 : END IF
740 8 : IF (needs%norm_drho) THEN
741 8 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], allocate_deriv=.FALSE.)
742 8 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
743 8 : CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 1)
744 8 : DEALLOCATE (drho)
745 : END IF
746 8 : IF (needs%tau) THEN
747 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau], allocate_deriv=.FALSE.)
748 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
749 0 : n1 = SIZE(xcmat, 1)
750 0 : n2 = SIZE(xcmat, 2)
751 0 : n3 = SIZE(xcmat, 3)
752 0 : ALLOCATE (taumat(n1, n2, 0:n3 - 1))
753 0 : taumat = 0._dp
754 :
755 0 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
756 0 : CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 2)
757 0 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
758 0 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
759 0 : DO l = 0, 3
760 0 : xcmat(:, :, l) = xcmat(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
761 : END DO
762 :
763 0 : DEALLOCATE (tau)
764 0 : DEALLOCATE (taumat)
765 : END IF
766 :
767 : ! we assume lap is not really needed
768 8 : IF (needs%laplace_rho) THEN
769 0 : DEALLOCATE (lap)
770 : END IF
771 :
772 : ! Release the xc structure used to store the xc derivatives
773 8 : CALL xc_dset_release(deriv_set)
774 8 : CALL xc_rho_set_release(rho_set)
775 :
776 : END IF !xc_none
777 :
778 8 : CALL timestop(handle)
779 :
780 152 : END SUBROUTINE atom_vxc_lda
781 :
782 : ! **************************************************************************************************
783 : !> \brief Alternative subroutine that calculates atomic exchange-correlation potential
784 : !> in spin-polarized case.
785 : !> \param basis atomic basis set
786 : !> \param pmata spin-alpha density matrix
787 : !> \param pmatb spin-beta density matrix
788 : !> \param maxl maximum angular momentum
789 : !> \param xc_section XC input section
790 : !> \param fexc exchange-correlation energy
791 : !> \param xcmata spin-alpha exchange-correlation potential matrix
792 : !> \param xcmatb spin-beta exchange-correlation potential matrix
793 : !> \par History
794 : !> * 07.2016 ADMM analysis [Juerg Hutter]
795 : ! **************************************************************************************************
796 0 : SUBROUTINE atom_vxc_lsd(basis, pmata, pmatb, maxl, xc_section, fexc, xcmata, xcmatb)
797 : TYPE(atom_basis_type), POINTER :: basis
798 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: pmata, pmatb
799 : INTEGER, INTENT(IN) :: maxl
800 : TYPE(section_vals_type), POINTER :: xc_section
801 : REAL(KIND=dp), INTENT(OUT) :: fexc
802 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: xcmata, xcmatb
803 :
804 : CHARACTER(LEN=*), PARAMETER :: routineN = 'atom_vxc_lsd'
805 :
806 : INTEGER :: deriv_order, handle, l, myfun, n1, n2, &
807 : n3, nr, nspins
808 : INTEGER, DIMENSION(2, 3) :: bounds
809 : LOGICAL :: lsd
810 : REAL(KIND=dp) :: density_cut, gradient_cut, tau_cut
811 0 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: drho, lap, rho, tau
812 0 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: taumat, xcpot
813 : TYPE(section_vals_type), POINTER :: xc_fun_section
814 : TYPE(xc_derivative_set_type) :: deriv_set
815 : TYPE(xc_derivative_type), POINTER :: deriv
816 : TYPE(xc_rho_cflags_type) :: needs
817 : TYPE(xc_rho_set_type) :: rho_set
818 :
819 0 : CALL timeset(routineN, handle)
820 :
821 0 : CPASSERT(ASSOCIATED(xc_section))
822 :
823 0 : xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
824 0 : CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
825 :
826 0 : IF (myfun == xc_none) THEN
827 0 : fexc = 0._dp
828 : ELSE
829 0 : CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
830 0 : CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
831 0 : CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
832 :
833 0 : lsd = .TRUE.
834 0 : nspins = 2
835 0 : needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
836 :
837 : ! Prepare the structures needed to calculate and store the xc derivatives
838 :
839 : ! Array dimension: here anly one dimensional arrays are used,
840 : ! i.e. only the first column of deriv_data is read.
841 : ! The other to dimensions are set to size equal 1
842 0 : nr = basis%grid%nr
843 0 : bounds(1:2, 1:3) = 1
844 0 : bounds(2, 1) = nr
845 :
846 : ! create a place where to put the derivatives
847 0 : CALL xc_dset_create(deriv_set, local_bounds=bounds)
848 : ! create the place where to store the argument for the functionals
849 : CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
850 0 : drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
851 : ! allocate the required 3d arrays where to store rho and drho
852 0 : CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
853 :
854 0 : NULLIFY (rho, drho, tau)
855 0 : IF (needs%rho_spin) THEN
856 0 : ALLOCATE (rho(nr, 2))
857 0 : CALL atom_density(rho(:, 1), pmata, basis, maxl, typ="RHO")
858 0 : CALL atom_density(rho(:, 2), pmatb, basis, maxl, typ="RHO")
859 : END IF
860 0 : IF (needs%norm_drho_spin) THEN
861 0 : ALLOCATE (drho(nr, 2))
862 0 : CALL atom_density(drho(:, 1), pmata, basis, maxl, typ="DER")
863 0 : CALL atom_density(drho(:, 2), pmatb, basis, maxl, typ="DER")
864 : END IF
865 0 : IF (needs%tau_spin) THEN
866 0 : ALLOCATE (tau(nr, 2))
867 0 : CALL atom_density(tau(:, 1), pmata, basis, maxl, typ="KIN", rr=basis%grid%rad2)
868 0 : CALL atom_density(tau(:, 2), pmatb, basis, maxl, typ="KIN", rr=basis%grid%rad2)
869 : END IF
870 0 : IF (needs%laplace_rho_spin) THEN
871 0 : ALLOCATE (lap(nr, 2))
872 0 : CALL atom_density(lap(:, 1), pmata, basis, maxl, typ="LAP", rr=basis%grid%rad2)
873 0 : CALL atom_density(lap(:, 2), pmatb, basis, maxl, typ="LAP", rr=basis%grid%rad2)
874 : END IF
875 :
876 0 : CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
877 :
878 0 : CALL xc_dset_zero_all(deriv_set)
879 :
880 0 : deriv_order = 1
881 : CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
882 0 : deriv_order=deriv_order)
883 :
884 : ! Integration to get the matrix elements and energy
885 0 : deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
886 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
887 0 : fexc = fourpi*integrate_grid(xcpot(:, 1, 1), basis%grid)
888 :
889 0 : IF (needs%rho_spin) THEN
890 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], allocate_deriv=.FALSE.)
891 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
892 0 : CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 0)
893 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], allocate_deriv=.FALSE.)
894 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
895 0 : CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 0)
896 0 : DEALLOCATE (rho)
897 : END IF
898 0 : IF (needs%norm_drho_spin) THEN
899 : ! drhoa
900 0 : NULLIFY (deriv)
901 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], allocate_deriv=.FALSE.)
902 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
903 0 : CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 1)
904 : ! drhob
905 0 : NULLIFY (deriv)
906 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], allocate_deriv=.FALSE.)
907 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
908 0 : CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 1)
909 : ! Cross Terms
910 0 : NULLIFY (deriv)
911 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
912 0 : IF (ASSOCIATED(deriv)) THEN
913 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
914 0 : CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 1)
915 0 : CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 1)
916 : END IF
917 0 : DEALLOCATE (drho)
918 : END IF
919 0 : IF (needs%tau_spin) THEN
920 0 : n1 = SIZE(xcmata, 1)
921 0 : n2 = SIZE(xcmata, 2)
922 0 : n3 = SIZE(xcmata, 3)
923 0 : ALLOCATE (taumat(n1, n2, 0:n3 - 1))
924 :
925 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_a], allocate_deriv=.FALSE.)
926 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
927 0 : taumat = 0._dp
928 0 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
929 0 : CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 2)
930 0 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
931 0 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
932 0 : DO l = 0, 3
933 0 : xcmata(:, :, l) = xcmata(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
934 : END DO
935 :
936 0 : deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_b], allocate_deriv=.FALSE.)
937 0 : CALL xc_derivative_get(deriv, deriv_data=xcpot)
938 0 : taumat = 0._dp
939 0 : xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
940 0 : CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 2)
941 0 : xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
942 0 : CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
943 0 : DO l = 0, 3
944 0 : xcmatb(:, :, l) = xcmatb(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
945 : END DO
946 :
947 0 : DEALLOCATE (tau)
948 0 : DEALLOCATE (taumat)
949 : END IF
950 :
951 : ! Release the xc structure used to store the xc derivatives
952 0 : CALL xc_dset_release(deriv_set)
953 0 : CALL xc_rho_set_release(rho_set)
954 :
955 : END IF !xc_none
956 :
957 0 : CALL timestop(handle)
958 :
959 0 : END SUBROUTINE atom_vxc_lsd
960 :
961 : ! **************************************************************************************************
962 : !> \brief Estimate the ADMM exchange energy correction term using a model exchange functional.
963 : !> \param basis0 reference atomic basis set
964 : !> \param pmat0 reference density matrix
965 : !> \param basis1 ADMM basis set
966 : !> \param pmat1 ADMM density matrix
967 : !> \param maxl maxumum angular momentum
968 : !> \param functional name of the model exchange functional:
969 : !> "LINX" -- linear extrapolation of the Slater exchange potential [?]
970 : !> \param dfexc exchange-correlation energy difference
971 : !> \param linxpar LINX parameters
972 : !> \par History
973 : !> * 07.2016 ADMM analysis [Juerg Hutter]
974 : ! **************************************************************************************************
975 3 : SUBROUTINE atom_dpot_lda(basis0, pmat0, basis1, pmat1, maxl, functional, dfexc, linxpar)
976 : TYPE(atom_basis_type), POINTER :: basis0
977 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: pmat0
978 : TYPE(atom_basis_type), POINTER :: basis1
979 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: pmat1
980 : INTEGER, INTENT(IN) :: maxl
981 : CHARACTER(LEN=*), INTENT(IN) :: functional
982 : REAL(KIND=dp), INTENT(OUT) :: dfexc
983 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: linxpar
984 :
985 : CHARACTER(LEN=*), PARAMETER :: routineN = 'atom_dpot_lda'
986 : REAL(KIND=dp), PARAMETER :: alx = 0.20_dp, blx = -0.06_dp, &
987 : fs = -0.75_dp*(3._dp/pi)**(1._dp/3._dp)
988 :
989 : INTEGER :: handle, ir, nr
990 : REAL(KIND=dp) :: a, b, fx
991 3 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: delta, drho0, drho1, pot0, pot1, rho0, &
992 : rho1
993 :
994 3 : CALL timeset(routineN, handle)
995 :
996 3 : nr = basis0%grid%nr
997 :
998 12 : ALLOCATE (rho0(nr), drho0(nr))
999 3 : CALL atom_density(rho0, pmat0, basis0, maxl, typ="RHO")
1000 3 : CALL atom_density(drho0, pmat0, basis0, maxl, typ="DER")
1001 : !
1002 9 : ALLOCATE (rho1(nr), drho1(nr))
1003 3 : CALL atom_density(rho1, pmat1, basis1, maxl, typ="RHO")
1004 : ! CONSIDER TO REMOVE [?]: drho1 is calculated but it is not used.
1005 3 : CALL atom_density(drho1, pmat1, basis1, maxl, typ="DER")
1006 : !
1007 6 : ALLOCATE (delta(nr))
1008 3 : fx = 4.0_dp/3.0_dp
1009 1203 : delta(1:nr) = fs*(rho0(1:nr)**fx - rho1(1:nr)**fx)
1010 :
1011 6 : SELECT CASE (TRIM(functional))
1012 : CASE ("LINX")
1013 3 : IF (PRESENT(linxpar)) THEN
1014 0 : a = linxpar(1)
1015 0 : b = linxpar(2)
1016 : ELSE
1017 : a = alx
1018 : b = blx
1019 : END IF
1020 9 : ALLOCATE (pot0(nr), pot1(nr))
1021 1203 : DO ir = 1, nr
1022 1203 : IF (rho0(ir) > 1.e-12_dp) THEN
1023 1146 : pot0(ir) = 0.5_dp*drho0(ir)/(3._dp*pi*pi*rho0(ir)**fx)
1024 : ELSE
1025 54 : pot0(ir) = 0._dp
1026 : END IF
1027 : END DO
1028 1203 : pot1(1:nr) = 1._dp + (a*pot0(1:nr)**2)/(1._dp + b*pot0(1:nr)**2)
1029 1203 : pot1(1:nr) = pot1(1:nr)*delta(1:nr)
1030 3 : dfexc = fourpi*integrate_grid(pot1(1:nr), basis0%grid)
1031 3 : DEALLOCATE (pot0, pot1)
1032 : CASE DEFAULT
1033 3 : CPABORT("Unknown functional in atom_dpot_lda")
1034 : END SELECT
1035 :
1036 3 : DEALLOCATE (rho0, rho1, drho0, drho1, delta)
1037 :
1038 3 : CALL timestop(handle)
1039 :
1040 3 : END SUBROUTINE atom_dpot_lda
1041 :
1042 : ! **************************************************************************************************
1043 : !> \brief Initialise object that holds components needed to compute the exchange-correlation
1044 : !> functional on the atomic radial grid.
1045 : !> \param rho_set electron density object to initialise
1046 : !> \param nspins number of spin components
1047 : !> \param needs components needed to compute the exchange-correlation functional
1048 : !> \param rho electron density on the grid
1049 : !> \param drho first derivative of the electron density on the grid
1050 : !> \param tau kinetic energy density on the grid
1051 : !> \param lap second derivative of the electron density on the grid
1052 : !> \param na number of points on the atomic radial grid
1053 : !> \par History
1054 : !> * 02.2010 unrestricted KS and HF methods [Juerg Hutter]
1055 : !> * 08.2008 created as calculate_atom_vxc_lda() [Juerg Hutter]
1056 : ! **************************************************************************************************
1057 23744 : SUBROUTINE fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, na)
1058 :
1059 : TYPE(xc_rho_set_type), INTENT(INOUT) :: rho_set
1060 : INTEGER, INTENT(IN) :: nspins
1061 : TYPE(xc_rho_cflags_type), INTENT(in) :: needs
1062 : REAL(dp), DIMENSION(:, :), POINTER :: rho, drho, tau, lap
1063 : INTEGER, INTENT(IN) :: na
1064 :
1065 : REAL(KIND=dp), PARAMETER :: f13 = (1.0_dp/3.0_dp)
1066 :
1067 : INTEGER :: ia
1068 :
1069 46567 : SELECT CASE (nspins)
1070 : CASE (1)
1071 22823 : CPASSERT(.NOT. needs%rho_spin)
1072 22823 : CPASSERT(.NOT. needs%drho_spin)
1073 22823 : CPASSERT(.NOT. needs%norm_drho_spin)
1074 22823 : CPASSERT(.NOT. needs%rho_spin_1_3)
1075 22823 : CPASSERT(.NOT. needs%tau_spin)
1076 22823 : CPASSERT(.NOT. needs%drho)
1077 : ! Give rho to 1/3
1078 22823 : IF (needs%rho_1_3) THEN
1079 354095 : DO ia = 1, na
1080 354095 : rho_set%rho_1_3(ia, 1, 1) = MAX(rho(ia, 1), 0.0_dp)**f13
1081 : END DO
1082 895 : rho_set%owns%rho_1_3 = .TRUE.
1083 895 : rho_set%has%rho_1_3 = .TRUE.
1084 : END IF
1085 : ! Give the density
1086 22823 : IF (needs%rho) THEN
1087 9463655 : DO ia = 1, na
1088 9463655 : rho_set%rho(ia, 1, 1) = rho(ia, 1)
1089 : END DO
1090 22823 : rho_set%owns%rho = .TRUE.
1091 22823 : rho_set%has%rho = .TRUE.
1092 : END IF
1093 : ! Give the norm of the gradient of the density
1094 22823 : IF (needs%norm_drho) THEN
1095 9161877 : DO ia = 1, na
1096 9161877 : rho_set%norm_drho(ia, 1, 1) = drho(ia, 1)
1097 : END DO
1098 22077 : rho_set%owns%norm_drho = .TRUE.
1099 22077 : rho_set%has%norm_drho = .TRUE.
1100 : END IF
1101 : CASE (2)
1102 921 : CPASSERT(.NOT. needs%drho)
1103 921 : CPASSERT(.NOT. needs%drho_spin)
1104 : ! Give the total density
1105 921 : IF (needs%rho) THEN
1106 0 : DO ia = 1, na
1107 0 : rho_set%rho(ia, 1, 1) = rho(ia, 1) + rho(ia, 2)
1108 : END DO
1109 0 : rho_set%owns%rho = .TRUE.
1110 0 : rho_set%has%rho = .TRUE.
1111 : END IF
1112 : ! Give the norm of the total gradient of the density
1113 921 : IF (needs%norm_drho) THEN
1114 365719 : DO ia = 1, na
1115 365719 : rho_set%norm_drho(ia, 1, 1) = drho(ia, 1) + drho(ia, 2)
1116 : END DO
1117 919 : rho_set%owns%norm_drho = .TRUE.
1118 919 : rho_set%has%norm_drho = .TRUE.
1119 : END IF
1120 : ! Give rho_spin
1121 921 : IF (needs%rho_spin) THEN
1122 366521 : DO ia = 1, na
1123 365600 : rho_set%rhoa(ia, 1, 1) = rho(ia, 1)
1124 366521 : rho_set%rhob(ia, 1, 1) = rho(ia, 2)
1125 : END DO
1126 921 : rho_set%owns%rho_spin = .TRUE.
1127 921 : rho_set%has%rho_spin = .TRUE.
1128 : END IF
1129 : ! Give rho_spin to 1/3
1130 921 : IF (needs%rho_spin_1_3) THEN
1131 170024 : DO ia = 1, na
1132 169600 : rho_set%rhoa_1_3(ia, 1, 1) = MAX(rho(ia, 1), 0.0_dp)**f13
1133 170024 : rho_set%rhob_1_3(ia, 1, 1) = MAX(rho(ia, 2), 0.0_dp)**f13
1134 : END DO
1135 424 : rho_set%owns%rho_1_3 = .TRUE.
1136 424 : rho_set%has%rho_1_3 = .TRUE.
1137 : END IF
1138 : ! Give the norm of the gradient of rhoa and of rhob separatedly
1139 24665 : IF (needs%norm_drho_spin) THEN
1140 365719 : DO ia = 1, na
1141 364800 : rho_set%norm_drhoa(ia, 1, 1) = drho(ia, 1)
1142 365719 : rho_set%norm_drhob(ia, 1, 1) = drho(ia, 2)
1143 : END DO
1144 919 : rho_set%owns%norm_drho_spin = .TRUE.
1145 919 : rho_set%has%norm_drho_spin = .TRUE.
1146 : END IF
1147 : !
1148 : END SELECT
1149 :
1150 : ! tau part
1151 23744 : IF (needs%tau) THEN
1152 108 : IF (nspins == 2) THEN
1153 0 : DO ia = 1, na
1154 0 : rho_set%tau(ia, 1, 1) = tau(ia, 1) + tau(ia, 2)
1155 : END DO
1156 0 : rho_set%owns%tau = .TRUE.
1157 0 : rho_set%has%tau = .TRUE.
1158 : ELSE
1159 43308 : DO ia = 1, na
1160 43308 : rho_set%tau(ia, 1, 1) = tau(ia, 1)
1161 : END DO
1162 108 : rho_set%owns%tau = .TRUE.
1163 108 : rho_set%has%tau = .TRUE.
1164 : END IF
1165 : END IF
1166 23744 : IF (needs%tau_spin) THEN
1167 2 : CPASSERT(nspins == 2)
1168 802 : DO ia = 1, na
1169 800 : rho_set%tau_a(ia, 1, 1) = tau(ia, 1)
1170 802 : rho_set%tau_b(ia, 1, 1) = tau(ia, 2)
1171 : END DO
1172 2 : rho_set%owns%tau_spin = .TRUE.
1173 2 : rho_set%has%tau_spin = .TRUE.
1174 : END IF
1175 :
1176 : ! Laplace
1177 23744 : IF (needs%laplace_rho) THEN
1178 0 : IF (nspins == 2) THEN
1179 0 : DO ia = 1, na
1180 0 : rho_set%laplace_rho(ia, 1, 1) = lap(ia, 1) + lap(ia, 2)
1181 : END DO
1182 0 : rho_set%owns%laplace_rho = .TRUE.
1183 0 : rho_set%has%laplace_rho = .TRUE.
1184 : ELSE
1185 0 : DO ia = 1, na
1186 0 : rho_set%laplace_rho(ia, 1, 1) = lap(ia, 1)
1187 : END DO
1188 0 : rho_set%owns%laplace_rho = .TRUE.
1189 0 : rho_set%has%laplace_rho = .TRUE.
1190 : END IF
1191 : END IF
1192 23744 : IF (needs%laplace_rho_spin) THEN
1193 0 : CPASSERT(nspins == 2)
1194 0 : DO ia = 1, na
1195 0 : rho_set%laplace_rhoa(ia, 1, 1) = lap(ia, 1)
1196 0 : rho_set%laplace_rhob(ia, 1, 1) = lap(ia, 2)
1197 : END DO
1198 0 : rho_set%owns%laplace_rho_spin = .TRUE.
1199 0 : rho_set%has%laplace_rho_spin = .TRUE.
1200 : END IF
1201 :
1202 23744 : END SUBROUTINE fill_rho_set
1203 :
1204 : ! **************************************************************************************************
1205 : !> \brief Calculate PADE exchange-correlation (xc) energy functional and potential
1206 : !> in spin-restricted case.
1207 : !> \param rho electron density
1208 : !> \param exc XC energy functional
1209 : !> \param vxc XC potential
1210 : !> \par History
1211 : !> * 12.2008 created [Juerg Hutter]
1212 : ! **************************************************************************************************
1213 44938 : PURE SUBROUTINE lda_pade(rho, exc, vxc)
1214 :
1215 : REAL(dp), DIMENSION(:), INTENT(IN) :: rho
1216 : REAL(dp), DIMENSION(:), INTENT(OUT) :: exc, vxc
1217 :
1218 : REAL(KIND=dp), PARAMETER :: a0 = 0.4581652932831429E+0_dp, a1 = 0.2217058676663745E+1_dp, &
1219 : a2 = 0.7405551735357053E+0_dp, a3 = 0.1968227878617998E-1_dp, &
1220 : b1 = 1.0000000000000000E+0_dp, b2 = 0.4504130959426697E+1_dp, &
1221 : b3 = 0.1110667363742916E+1_dp, b4 = 0.2359291751427506E-1_dp, f13 = (1.0_dp/3.0_dp), &
1222 : rsfac = 0.6203504908994000166680065_dp
1223 :
1224 : INTEGER :: i, n
1225 : REAL(KIND=dp) :: depade, dpv, dq, epade, p, q, rs
1226 :
1227 44938 : n = SIZE(rho)
1228 18042356 : exc(1:n) = 0._dp
1229 18042356 : vxc(1:n) = 0._dp
1230 :
1231 18042356 : DO i = 1, n
1232 18042356 : IF (rho(i) > 1.e-20_dp) THEN
1233 16407846 : rs = rsfac*rho(i)**(-f13)
1234 16407846 : p = a0 + (a1 + (a2 + a3*rs)*rs)*rs
1235 16407846 : q = (b1 + (b2 + (b3 + b4*rs)*rs)*rs)*rs
1236 16407846 : epade = -p/q
1237 :
1238 16407846 : dpv = a1 + (2.0_dp*a2 + 3.0_dp*a3*rs)*rs
1239 16407846 : dq = b1 + (2.0_dp*b2 + (3.0_dp*b3 + 4.0_dp*b4*rs)*rs)*rs
1240 16407846 : depade = f13*rs*(dpv*q - p*dq)/(q*q)
1241 :
1242 16407846 : exc(i) = epade*rho(i)
1243 16407846 : vxc(i) = epade + depade
1244 : END IF
1245 : END DO
1246 :
1247 44938 : END SUBROUTINE lda_pade
1248 :
1249 : ! **************************************************************************************************
1250 : !> \brief Calculate PADE exchange-correlation (xc) energy functional and potential
1251 : !> in spin-polarized case.
1252 : !> \param rhoa spin-alpha electron density
1253 : !> \param rhob spin-beta electron density
1254 : !> \param exc XC energy functional
1255 : !> \param vxca spin-alpha XC potential
1256 : !> \param vxcb spin-beta XC potential
1257 : !> \par History
1258 : !> * 02.2010 created [Juerg Hutter]
1259 : ! **************************************************************************************************
1260 554 : PURE SUBROUTINE lsd_pade(rhoa, rhob, exc, vxca, vxcb)
1261 :
1262 : REAL(dp), DIMENSION(:), INTENT(IN) :: rhoa, rhob
1263 : REAL(dp), DIMENSION(:), INTENT(OUT) :: exc, vxca, vxcb
1264 :
1265 : REAL(KIND=dp), PARAMETER :: a0 = 0.4581652932831429E+0_dp, a1 = 0.2217058676663745E+1_dp, &
1266 : a2 = 0.7405551735357053E+0_dp, a3 = 0.1968227878617998E-1_dp, &
1267 : b1 = 1.0000000000000000E+0_dp, b2 = 0.4504130959426697E+1_dp, &
1268 : b3 = 0.1110667363742916E+1_dp, b4 = 0.2359291751427506E-1_dp, &
1269 : da0 = 0.119086804055547E+0_dp, da1 = 0.6157402568883345E+0_dp, &
1270 : da2 = 0.1574201515892867E+0_dp, da3 = 0.3532336663397157E-2_dp, &
1271 : db1 = 0.0000000000000000E+0_dp, db2 = 0.2673612973836267E+0_dp, &
1272 : db3 = 0.2052004607777787E+0_dp, db4 = 0.4200005045691381E-2_dp, f13 = (1.0_dp/3.0_dp), &
1273 : f43 = (4.0_dp/3.0_dp)
1274 : REAL(KIND=dp), PARAMETER :: fxfac = 1.923661050931536319759455_dp, &
1275 : rsfac = 0.6203504908994000166680065_dp
1276 :
1277 : INTEGER :: i, n
1278 : REAL(KIND=dp) :: dc, dpv, dq, dr, dx, fa0, fa1, fa2, fa3, &
1279 : fb1, fb2, fb3, fb4, fx1, fx2, p, q, &
1280 : rhoab, rs, x, xp, xq
1281 :
1282 : ! 1/(2^(4/3) - 2)
1283 :
1284 554 : n = SIZE(rhoa)
1285 222154 : exc(1:n) = 0._dp
1286 222154 : vxca(1:n) = 0._dp
1287 222154 : vxcb(1:n) = 0._dp
1288 :
1289 222154 : DO i = 1, n
1290 221600 : rhoab = rhoa(i) + rhob(i)
1291 222154 : IF (rhoab > 1.e-20_dp) THEN
1292 202540 : rs = rsfac*rhoab**(-f13)
1293 :
1294 202540 : x = (rhoa(i) - rhob(i))/rhoab
1295 202540 : IF (x < -1.0_dp) THEN
1296 : fx1 = 1.0_dp
1297 : fx2 = -f43*fxfac*2.0_dp**f13
1298 202540 : ELSE IF (x > 1.0_dp) THEN
1299 : fx1 = 1.0_dp
1300 : fx2 = f43*fxfac*2.0_dp**f13
1301 : ELSE
1302 202540 : fx1 = ((1.0_dp + x)**f43 + (1.0_dp - x)**f43 - 2.0_dp)*fxfac
1303 202540 : fx2 = ((1.0_dp + x)**f13 - (1.0_dp - x)**f13)*fxfac*f43
1304 : END IF
1305 :
1306 202540 : fa0 = a0 + fx1*da0
1307 202540 : fa1 = a1 + fx1*da1
1308 202540 : fa2 = a2 + fx1*da2
1309 202540 : fa3 = a3 + fx1*da3
1310 202540 : fb1 = b1 + fx1*db1
1311 202540 : fb2 = b2 + fx1*db2
1312 202540 : fb3 = b3 + fx1*db3
1313 202540 : fb4 = b4 + fx1*db4
1314 :
1315 202540 : p = fa0 + (fa1 + (fa2 + fa3*rs)*rs)*rs
1316 202540 : q = (fb1 + (fb2 + (fb3 + fb4*rs)*rs)*rs)*rs
1317 202540 : dpv = fa1 + (2.0_dp*fa2 + 3.0_dp*fa3*rs)*rs
1318 : dq = fb1 + (2.0_dp*fb2 + (3.0_dp*fb3 + &
1319 202540 : 4.0_dp*fb4*rs)*rs)*rs
1320 202540 : xp = da0 + (da1 + (da2 + da3*rs)*rs)*rs
1321 202540 : xq = (db1 + (db2 + (db3 + db4*rs)*rs)*rs)*rs
1322 :
1323 202540 : dr = (dpv*q - p*dq)/(q*q)
1324 202540 : dx = 2.0_dp*(xp*q - p*xq)/(q*q)*fx2/rhoab
1325 202540 : dc = f13*rs*dr - p/q
1326 :
1327 202540 : exc(i) = -p/q*rhoab
1328 202540 : vxca(i) = dc - dx*rhob(i)
1329 202540 : vxcb(i) = dc + dx*rhoa(i)
1330 : END IF
1331 : END DO
1332 :
1333 554 : END SUBROUTINE lsd_pade
1334 :
1335 : END MODULE atom_xc
|