(git:6344619)
Loading...
Searching...
No Matches
xc_xbr_pbe_lda_hole_t_c_lr.F
Go to the documentation of this file.
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 This functional is a combination of three different exchange hole
10!> models. The ingredients are:
11!>
12!> 1. Becke Roussel exchange hole
13!> 2. PBE exchange hole
14!> 3. LDA exchange hole
15!>
16!> The full functionals is given as follows
17!>
18!> Fx = eps_lr_lda/eps_lr_br
19!> Fcorr = alpha/( exp( (Fx-mu)/N ) + 1)
20!> rhox = Fcorr * eps_lr_pbe + (1-Fcorr)*eps_lr_br
21!> eps = int_{R}^{\infty} rhox*s*ds
22!>
23!> with alpha, mu and N fitting parameters
24!> \par History
25!> 01.2009 created [mguidon]
26!> \author mguidon
27! **************************************************************************************************
28
30
33 USE kinds, ONLY: dp
34 USE mathconstants, ONLY: pi
35 USE xc_derivative_desc, ONLY: &
53#include "../base/base_uses.f90"
54
55 IMPLICIT NONE
56 PRIVATE
57
58 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .true.
59 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc_xbr_pbe_lda_hole_t_c_lr'
60
61 REAL(dp), PARAMETER, PRIVATE :: br_a1 = 1.5255251812009530_dp, &
62 br_a2 = 0.4576575543602858_dp, &
63 br_a3 = 0.4292036732051034_dp, &
64 br_c0 = 0.7566445420735584_dp, &
65 br_c1 = -2.6363977871370960_dp, &
66 br_c2 = 5.4745159964232880_dp, &
67 br_c3 = -12.657308127108290_dp, &
68 br_c4 = 4.1250584725121360_dp, &
69 br_c5 = -30.425133957163840_dp, &
70 br_b0 = 0.4771976183772063_dp, &
71 br_b1 = -1.7799813494556270_dp, &
72 br_b2 = 3.8433841862302150_dp, &
73 br_b3 = -9.5912050880518490_dp, &
74 br_b4 = 2.1730180285916720_dp, &
75 br_b5 = -30.425133851603660_dp, &
76 br_d0 = 0.00004435009886795587_dp, &
77 br_d1 = 0.58128653604457910_dp, &
78 br_d2 = 66.742764515940610_dp, &
79 br_d3 = 434.26780897229770_dp, &
80 br_d4 = 824.7765766052239000_dp, &
81 br_d5 = 1657.9652731582120_dp, &
82 br_e0 = 0.00003347285060926091_dp, &
83 br_e1 = 0.47917931023971350_dp, &
84 br_e2 = 62.392268338574240_dp, &
85 br_e3 = 463.14816427938120_dp, &
86 br_e4 = 785.2360350104029000_dp, &
87 br_e5 = 1657.962968223273000000_dp, &
88 br_bb = 2.085749716493756_dp
89
90 REAL(dp), PARAMETER, PRIVATE :: smax = 8.572844_dp, &
91 scutoff = 8.3_dp, &
92 sconst = 18.79622316_dp, &
93 gcutoff = 0.08_dp
94
95 REAL(dp), PARAMETER, PRIVATE :: alpha = 0.3956891_dp, &
96 n = -0.0009800242_dp, &
97 mu = 0.00118684_dp
98
103CONTAINS
104
105! **************************************************************************************************
106!> \brief return various information on the functional
107!> \param reference string with the reference of the actual functional
108!> \param shortform string with the shortform of the functional name
109!> \param needs the components needed by this functional are set to
110!> true (does not set the unneeded components to false)
111!> \param max_deriv ...
112!> \author mguidon (01.2009)
113! **************************************************************************************************
114 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lda_info(reference, shortform, needs, max_deriv)
115 CHARACTER(LEN=*), INTENT(OUT), OPTIONAL :: reference, shortform
116 TYPE(xc_rho_cflags_type), INTENT(inout), OPTIONAL :: needs
117 INTEGER, INTENT(out), OPTIONAL :: max_deriv
118
119 IF (PRESENT(reference)) THEN
120 reference = "{LDA version}"
121 END IF
122 IF (PRESENT(shortform)) THEN
123 shortform = "{LDA}"
124 END IF
125
126 IF (PRESENT(needs)) THEN
127 needs%rho = .true.
128 needs%norm_drho = .true.
129 needs%tau = .true.
130 needs%laplace_rho = .true.
131 END IF
132
133 IF (PRESENT(max_deriv)) max_deriv = 1
134
136
137! **************************************************************************************************
138!> \brief return various information on the functional
139!> \param reference string with the reference of the actual functional
140!> \param shortform string with the shortform of the functional name
141!> \param needs the components needed by this functional are set to
142!> true (does not set the unneeded components to false)
143!> \param max_deriv ...
144!> \author mguidon (01.2009)
145! **************************************************************************************************
146 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lsd_info(reference, shortform, needs, max_deriv)
147 CHARACTER(LEN=*), INTENT(OUT), OPTIONAL :: reference, shortform
148 TYPE(xc_rho_cflags_type), INTENT(inout), OPTIONAL :: needs
149 INTEGER, INTENT(out), OPTIONAL :: max_deriv
150
151 IF (PRESENT(reference)) THEN
152 reference = "{LDA version}"
153 END IF
154 IF (PRESENT(shortform)) THEN
155 shortform = "{LDA}"
156 END IF
157
158 IF (PRESENT(needs)) THEN
159 needs%rho_spin = .true.
160 needs%norm_drho_spin = .true.
161 needs%tau_spin = .true.
162 needs%laplace_rho_spin = .true.
163 END IF
164 IF (PRESENT(max_deriv)) max_deriv = 1
165
167
168! **************************************************************************************************
169!> \brief Intermediate routine that gets grids, derivatives and some params
170!> \param rho_set the density where you want to evaluate the functional
171!> \param deriv_set place where to store the functional derivatives (they are
172!> added to the derivatives)
173!> \param grad_deriv maximum degree of the derivative that should be evaluated
174!> \param params parameters for functional
175!> \author mguidon (01.2009)
176! **************************************************************************************************
177 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lda_eval(rho_set, deriv_set, grad_deriv, params)
178 TYPE(xc_rho_set_type), INTENT(IN) :: rho_set
179 TYPE(xc_derivative_set_type), INTENT(IN) :: deriv_set
180 INTEGER, INTENT(in) :: grad_deriv
181 TYPE(section_vals_type), POINTER :: params
182
183 CHARACTER(len=*), PARAMETER :: routinen = 'xbr_pbe_lda_hole_tc_lr_lda_eval'
184
185 INTEGER :: handle, npoints
186 INTEGER, DIMENSION(2, 3) :: bo
187 REAL(dp) :: gamma, r, sx
188 REAL(kind=dp) :: epsilon_rho
189 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), &
190 POINTER :: dummy, e_0, e_laplace_rho, e_ndrho, &
191 e_rho, e_tau, laplace_rho, norm_drho, &
192 rho, tau
193 TYPE(xc_derivative_type), POINTER :: deriv
194
195 CALL timeset(routinen, handle)
196
197 CALL xc_rho_set_get(rho_set, rho=rho, norm_drho=norm_drho, &
198 tau=tau, laplace_rho=laplace_rho, local_bounds=bo, &
199 rho_cutoff=epsilon_rho)
200 npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
201
202 dummy => rho
203
204 e_0 => dummy
205 e_rho => dummy
206 e_ndrho => dummy
207 e_tau => dummy
208 e_laplace_rho => dummy
209
210 deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
211 allocate_deriv=.true.)
212 CALL xc_derivative_get(deriv, deriv_data=e_0)
213 IF (grad_deriv >= 1) THEN
214 deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], &
215 allocate_deriv=.true.)
216 CALL xc_derivative_get(deriv, deriv_data=e_rho)
217 deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], &
218 allocate_deriv=.true.)
219 CALL xc_derivative_get(deriv, deriv_data=e_ndrho)
220 deriv => xc_dset_get_derivative(deriv_set, [deriv_tau], &
221 allocate_deriv=.true.)
222 CALL xc_derivative_get(deriv, deriv_data=e_tau)
223 deriv => xc_dset_get_derivative(deriv_set, [deriv_laplace_rho], &
224 allocate_deriv=.true.)
225 CALL xc_derivative_get(deriv, deriv_data=e_laplace_rho)
226 END IF
227 IF (grad_deriv > 1) THEN
228 cpabort("derivatives bigger than 1 not implemented")
229 END IF
230
231 CALL section_vals_val_get(params, "scale_x", r_val=sx)
232 CALL section_vals_val_get(params, "CUTOFF_RADIUS", r_val=r)
233 CALL section_vals_val_get(params, "GAMMA", r_val=gamma)
234
235 IF (r == 0.0_dp) THEN
236 cpabort("Cutoff_Radius 0.0 not implemented")
237 END IF
238
239!$OMP PARALLEL DEFAULT(NONE) &
240!$OMP SHARED(rho, norm_drho, laplace_rho, tau, e_0, e_rho) &
241!$OMP SHARED(e_ndrho, e_tau, e_laplace_rho, grad_deriv) &
242!$OMP SHARED(npoints, epsilon_rho) &
243!$OMP SHARED(sx, r, gamma)
244
245 CALL xbr_pbe_lda_hole_tc_lr_lda_calc(rho=rho, norm_drho=norm_drho, &
246 laplace_rho=laplace_rho, tau=tau, e_0=e_0, e_rho=e_rho, e_ndrho=e_ndrho, &
247 e_tau=e_tau, e_laplace_rho=e_laplace_rho, grad_deriv=grad_deriv, &
248 npoints=npoints, epsilon_rho=epsilon_rho, sx=sx, r=r, gamma=gamma)
249
250!$OMP END PARALLEL
251
252 CALL timestop(handle)
254
255! **************************************************************************************************
256!> \brief Low level routine that calls the three involved holes and puts them
257!> together
258!> \param rho values on the grid
259!> \param norm_drho values on the grid
260!> \param laplace_rho values on the grid
261!> \param tau values on the grid
262!> \param e_0 derivatives on the grid
263!> \param e_rho derivatives on the grid
264!> \param e_ndrho derivatives on the grid
265!> \param e_tau derivatives on the grid
266!> \param e_laplace_rho derivatives on the grid
267!> \param grad_deriv maximum degree of the derivative that should be evaluated
268!> \param npoints number of gridpoints
269!> \param epsilon_rho cutoffs
270!> \param sx parameters for functional
271!> \param R parameters for functional
272!> \param gamma parameters for functional
273!> \author mguidon (01.2009)
274! **************************************************************************************************
275 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lda_calc(rho, norm_drho, laplace_rho, tau, e_0, e_rho, &
276 e_ndrho, e_tau, e_laplace_rho, grad_deriv, npoints, &
277 epsilon_rho, sx, R, gamma)
278
279 INTEGER, INTENT(in) :: npoints, grad_deriv
280 REAL(kind=dp), DIMENSION(1:npoints), INTENT(inout) :: e_laplace_rho, e_tau, e_ndrho, e_rho, e_0
281 REAL(kind=dp), DIMENSION(1:npoints), INTENT(in) :: tau, laplace_rho, norm_drho, rho
282 REAL(kind=dp), INTENT(in) :: epsilon_rho, sx, r, gamma
283
284 INTEGER :: ip
285 REAL(dp) :: dfermi_dlaplace_rho, dfermi_dndrho, dfermi_drho, dfermi_dtau, e_0_br, e_0_lda, &
286 e_0_pbe, e_laplace_rho_br, e_ndrho_br, e_ndrho_pbe, e_rho_br, e_rho_lda, e_rho_pbe, &
287 e_tau_br, fermi, fx, my_laplace_rho, my_ndrho, my_rho, my_tau, ss, ss2, sscale, t1, t15, &
288 t16, t2, t3, t4, t5, t6, t7, t8, t9, yval
289
290!$OMP DO
291
292 DO ip = 1, npoints
293 my_rho = 0.5_dp*max(rho(ip), 0.0_dp)
294 IF (my_rho > epsilon_rho) THEN
295 my_ndrho = 0.5_dp*max(norm_drho(ip), epsilon(0.0_dp)*1.e4_dp)
296 my_tau = 0.5_dp*max(epsilon(0.0_dp)*1.e4_dp, tau(ip))
297 my_laplace_rho = 0.5_dp*laplace_rho(ip)
298
299 ! ** We calculate first the Becke-Roussel part, saving everything in local variables
300 t1 = pi**(0.1e1_dp/0.3e1_dp)
301 t2 = t1**2
302 t3 = my_rho**(0.1e1_dp/0.3e1_dp)
303 t4 = t3**2
304 t5 = t4*my_rho
305 t8 = my_ndrho**2
306 t9 = 0.1e1_dp/my_rho
307 t15 = my_laplace_rho/0.6e1_dp - gamma*(2.0_dp*my_tau - t8*t9/0.4e1_dp)/0.3e1_dp
308 t16 = 0.1e1_dp/t15
309 yval = 0.2e1_dp/0.3e1_dp*t2*t5*t16
310
311 e_0_br = 0.0_dp
312 e_rho_br = 0.0_dp
313 e_ndrho_br = 0.0_dp
314 e_tau_br = 0.0_dp
315 e_laplace_rho_br = 0.0_dp
316
317 IF (r == 0.0_dp) THEN
318 IF (yval <= 0.0_dp) THEN
319 CALL x_br_lsd_y_lte_0(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
320 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
321 sx, gamma, grad_deriv)
322 ! VERY UGLY HACK e_0 has to multiplied by the factor 2
323 e_0_br = 2.0_dp*e_0_br
324 ELSE
325 CALL x_br_lsd_y_gt_0(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
326 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
327 sx, gamma, grad_deriv)
328 ! VERY UGLY HACK e_0 has to multiplied by the factor 2
329 e_0_br = 2.0_dp*e_0_br
330 END IF
331 ELSE
332 IF (yval <= 0.0_dp) THEN
333 CALL x_br_lsd_y_lte_0_cutoff(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
334 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
335 sx, r, gamma, grad_deriv)
336 ! VERY UGLY HACK e_0 has to multiplied by the factor 2
337 e_0_br = 2.0_dp*e_0_br
338 ELSE
339 CALL x_br_lsd_y_gt_0_cutoff(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
340 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
341 sx, r, gamma, grad_deriv)
342 ! VERY UGLY HACK e_0 has to multiplied by the factor 2
343 e_0_br = 2.0_dp*e_0_br
344 END IF
345 END IF
346
347 ! ** Now we calculate the pbe cutoff part
348 ! ** Attention we need to scale rho, ndrho first
349 my_rho = my_rho*2.0_dp
350 my_ndrho = my_ndrho*2.0_dp
351
352 ! ** Do some precalculation in order to catch the correct branch afterwards
353 sscale = 1.0_dp
354 t1 = pi**2
355 t2 = t1*my_rho
356 t3 = t2**(0.1e1_dp/0.3e1_dp)
357 t4 = 0.1e1_dp/t3
358 t6 = my_ndrho*t4
359 t7 = 0.1e1_dp/my_rho
360 t8 = t7*sscale
361 ss = 0.3466806371753173524216762e0_dp*t6*t8
362 IF (ss > scutoff) THEN
363 ss2 = ss*ss
364 sscale = (smax*ss2 - sconst)/(ss2*ss)
365 END IF
366 e_0_pbe = 0.0_dp
367 e_rho_pbe = 0.0_dp
368 e_ndrho_pbe = 0.0_dp
369 IF (ss*sscale > gcutoff) THEN
370 CALL xpbe_hole_t_c_lr_lda_calc_1(e_0_pbe, e_rho_pbe, e_ndrho_pbe, &
371 my_rho, &
372 my_ndrho, sscale, sx, r, grad_deriv)
373 ELSE
374 CALL xpbe_hole_t_c_lr_lda_calc_2(e_0_pbe, e_rho_pbe, e_ndrho_pbe, &
375 my_rho, &
376 my_ndrho, sscale, sx, r, grad_deriv)
377 END IF
378
379 ! ** Finally we get the LDA part
380
381 e_0_lda = 0.0_dp
382 e_rho_lda = 0.0_dp
383 CALL xlda_hole_t_c_lr_lda_calc_0(grad_deriv, my_rho, e_0_lda, e_rho_lda, &
384 sx, r)
385
386 fx = e_0_br/e_0_lda
387
388 fermi = alpha/(exp((fx - mu)/n) + 1.0_dp)
389
390 e_0(ip) = e_0(ip) + (fermi*e_0_pbe + (1.0_dp - fermi)*e_0_br)*sx
391
392 IF (grad_deriv >= 1) THEN
393
394 dfermi_drho = -fermi**2/alpha/n*(e_rho_br/e_0_lda - e_0_br*e_rho_lda/e_0_lda**2)*exp((fx - mu)/n)
395 dfermi_dndrho = -fermi**2/alpha/n*(e_ndrho_br/e_0_lda)*exp((fx - mu)/n)
396 dfermi_dtau = -fermi**2/alpha/n*(e_tau_br/e_0_lda)*exp((fx - mu)/n)
397 dfermi_dlaplace_rho = -fermi**2/alpha/n*(e_laplace_rho_br/e_0_lda)*exp((fx - mu)/n)
398
399 e_rho(ip) = e_rho(ip) + (fermi*e_rho_pbe + dfermi_drho*e_0_pbe + &
400 (1.0_dp - fermi)*e_rho_br - dfermi_drho*e_0_br)*sx
401
402 e_ndrho(ip) = e_ndrho(ip) + (fermi*e_ndrho_pbe + dfermi_dndrho*e_0_pbe + &
403 (1.0_dp - fermi)*e_ndrho_br - dfermi_dndrho*e_0_br)*sx
404
405 e_tau(ip) = e_tau(ip) + (dfermi_dtau*e_0_pbe + &
406 (1.0_dp - fermi)*e_tau_br - dfermi_dtau*e_0_br)*sx
407
408 e_laplace_rho(ip) = e_laplace_rho(ip) + (dfermi_dlaplace_rho*e_0_pbe + &
409 (1.0_dp - fermi)*e_laplace_rho_br - dfermi_dlaplace_rho*e_0_br)*sx
410 END IF
411
412 END IF
413 END DO
414
415!$OMP END DO
416
417 END SUBROUTINE xbr_pbe_lda_hole_tc_lr_lda_calc
418
419! **************************************************************************************************
420!> \brief Intermediate routine that gets grids, derivatives and some params
421!> \param rho_set the density where you want to evaluate the functional
422!> \param deriv_set place where to store the functional derivatives (they are
423!> added to the derivatives)
424!> \param grad_deriv maximum degree of the derivative that should be evaluated
425!> \param params parameters for functional
426!> \author mguidon (01.2009)
427! **************************************************************************************************
428 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lsd_eval(rho_set, deriv_set, grad_deriv, params)
429 TYPE(xc_rho_set_type), INTENT(IN) :: rho_set
430 TYPE(xc_derivative_set_type), INTENT(IN) :: deriv_set
431 INTEGER, INTENT(in) :: grad_deriv
432 TYPE(section_vals_type), POINTER :: params
433
434 CHARACTER(len=*), PARAMETER :: routinen = 'xbr_pbe_lda_hole_tc_lr_lsd_eval'
435
436 INTEGER :: handle, npoints
437 INTEGER, DIMENSION(2, 3) :: bo
438 REAL(dp) :: gamma, r, sx
439 REAL(kind=dp) :: epsilon_rho
440 REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :, :), POINTER :: dummy, e_0, e_laplace_rhoa, &
441 e_laplace_rhob, e_ndrhoa, e_ndrhob, e_rhoa, e_rhob, e_tau_a, e_tau_b, laplace_rhoa, &
442 laplace_rhob, norm_drhoa, norm_drhob, rhoa, rhob, tau_a, tau_b
443 TYPE(xc_derivative_type), POINTER :: deriv
444
445 CALL timeset(routinen, handle)
446
447 CALL xc_rho_set_get(rho_set, rhoa=rhoa, rhob=rhob, norm_drhoa=norm_drhoa, &
448 norm_drhob=norm_drhob, tau_a=tau_a, tau_b=tau_b, laplace_rhoa=laplace_rhoa, &
449 laplace_rhob=laplace_rhob, local_bounds=bo, &
450 rho_cutoff=epsilon_rho)
451 npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
452
453 dummy => rhoa
454
455 e_0 => dummy
456 e_rhoa => dummy
457 e_rhob => dummy
458 e_ndrhoa => dummy
459 e_ndrhob => dummy
460 e_tau_a => dummy
461 e_tau_b => dummy
462 e_laplace_rhoa => dummy
463 e_laplace_rhob => dummy
464
465 deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], &
466 allocate_deriv=.true.)
467 CALL xc_derivative_get(deriv, deriv_data=e_0)
468 IF (grad_deriv >= 1) THEN
469 deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], &
470 allocate_deriv=.true.)
471 CALL xc_derivative_get(deriv, deriv_data=e_rhoa)
472 deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], &
473 allocate_deriv=.true.)
474 CALL xc_derivative_get(deriv, deriv_data=e_rhob)
475
476 deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], &
477 allocate_deriv=.true.)
478 CALL xc_derivative_get(deriv, deriv_data=e_ndrhoa)
479 deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], &
480 allocate_deriv=.true.)
481 CALL xc_derivative_get(deriv, deriv_data=e_ndrhob)
482
483 deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_a], &
484 allocate_deriv=.true.)
485 CALL xc_derivative_get(deriv, deriv_data=e_tau_a)
486 deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_b], &
487 allocate_deriv=.true.)
488 CALL xc_derivative_get(deriv, deriv_data=e_tau_b)
489
490 deriv => xc_dset_get_derivative(deriv_set, [deriv_laplace_rhoa], &
491 allocate_deriv=.true.)
492 CALL xc_derivative_get(deriv, deriv_data=e_laplace_rhoa)
493 deriv => xc_dset_get_derivative(deriv_set, [deriv_laplace_rhob], &
494 allocate_deriv=.true.)
495 CALL xc_derivative_get(deriv, deriv_data=e_laplace_rhob)
496 END IF
497 IF (grad_deriv > 1) THEN
498 cpabort("derivatives bigger than 1 not implemented")
499 END IF
500
501 CALL section_vals_val_get(params, "scale_x", r_val=sx)
502 CALL section_vals_val_get(params, "CUTOFF_RADIUS", r_val=r)
503 CALL section_vals_val_get(params, "GAMMA", r_val=gamma)
504
505 IF (r == 0.0_dp) THEN
506 cpabort("Cutoff_Radius 0.0 not implemented")
507 END IF
508
509!$OMP PARALLEL DEFAULT(NONE) &
510!$OMP SHARED(rhoa, norm_drhoa, laplace_rhoa, tau_a, e_0) &
511!$OMP SHARED(e_rhoa, e_ndrhoa, e_tau_a, e_laplace_rhoa) &
512!$OMP SHARED(grad_deriv, npoints, epsilon_rho) &
513!$OMP SHARED(sx, r, gamma) &
514!$OMP SHARED(rhob, norm_drhob, laplace_rhob, tau_b, e_rhob) &
515!$OMP SHARED(e_ndrhob, e_tau_b, e_laplace_rhob)
516
517 CALL xbr_pbe_lda_hole_tc_lr_lsd_calc(rho=rhoa, norm_drho=norm_drhoa, &
518 laplace_rho=laplace_rhoa, tau=tau_a, e_0=e_0, e_rho=e_rhoa, e_ndrho=e_ndrhoa, &
519 e_tau=e_tau_a, e_laplace_rho=e_laplace_rhoa, grad_deriv=grad_deriv, &
520 npoints=npoints, epsilon_rho=epsilon_rho, &
521 sx=sx, r=r, gamma=gamma)
522
523 CALL xbr_pbe_lda_hole_tc_lr_lsd_calc(rho=rhob, norm_drho=norm_drhob, &
524 laplace_rho=laplace_rhob, tau=tau_b, e_0=e_0, e_rho=e_rhob, e_ndrho=e_ndrhob, &
525 e_tau=e_tau_b, e_laplace_rho=e_laplace_rhob, grad_deriv=grad_deriv, &
526 npoints=npoints, epsilon_rho=epsilon_rho, &
527 sx=sx, r=r, gamma=gamma)
528
529!$OMP END PARALLEL
530
531 CALL timestop(handle)
533! **************************************************************************************************
534!> \brief Low level routine that calls the three involved holes and puts them
535!> together
536!> \param rho values on the grid
537!> \param norm_drho values on the grid
538!> \param laplace_rho values on the grid
539!> \param tau values on the grid
540!> \param e_0 derivatives on the grid
541!> \param e_rho derivatives on the grid
542!> \param e_ndrho derivatives on the grid
543!> \param e_tau derivatives on the grid
544!> \param e_laplace_rho derivatives on the grid
545!> \param grad_deriv maximum degree of the derivative that should be evaluated
546!> \param npoints number of gridpoints
547!> \param epsilon_rho cutoffs
548!> \param sx parameters for functional
549!> \param R parameters for functional
550!> \param gamma parameters for functional
551!> \author mguidon (01.2009)
552! **************************************************************************************************
553 SUBROUTINE xbr_pbe_lda_hole_tc_lr_lsd_calc(rho, norm_drho, laplace_rho, tau, e_0, e_rho, &
554 e_ndrho, e_tau, e_laplace_rho, grad_deriv, npoints, &
555 epsilon_rho, sx, R, gamma)
556
557 INTEGER, INTENT(in) :: npoints, grad_deriv
558 REAL(kind=dp), DIMENSION(1:npoints), INTENT(inout) :: e_laplace_rho, e_tau, e_ndrho, e_rho, e_0
559 REAL(kind=dp), DIMENSION(1:npoints), INTENT(in) :: tau, laplace_rho, norm_drho, rho
560 REAL(kind=dp), INTENT(in) :: epsilon_rho, sx, r, gamma
561
562 INTEGER :: ip
563 REAL(dp) :: dfermi_dlaplace_rho, dfermi_dndrho, dfermi_drho, dfermi_dtau, e_0_br, e_0_lda, &
564 e_0_pbe, e_laplace_rho_br, e_ndrho_br, e_ndrho_pbe, e_rho_br, e_rho_lda, e_rho_pbe, &
565 e_tau_br, fermi, fx, my_laplace_rho, my_ndrho, my_rho, my_tau, ss, ss2, sscale, t1, t15, &
566 t16, t2, t3, t4, t5, t6, t7, t8, t9, yval
567
568!$OMP DO
569
570 DO ip = 1, npoints
571 my_rho = max(rho(ip), 0.0_dp)
572 IF (my_rho > epsilon_rho) THEN
573 my_ndrho = max(norm_drho(ip), epsilon(0.0_dp)*1.e4_dp)
574 my_tau = 1.0_dp*max(epsilon(0.0_dp)*1.e4_dp, tau(ip))
575 my_laplace_rho = 1.0_dp*laplace_rho(ip)
576
577 t1 = pi**(0.1e1_dp/0.3e1_dp)
578 t2 = t1**2
579 t3 = my_rho**(0.1e1_dp/0.3e1_dp)
580 t4 = t3**2
581 t5 = t4*my_rho
582 t8 = my_ndrho**2
583 t9 = 0.1e1_dp/my_rho
584 t15 = my_laplace_rho/0.6e1_dp - gamma*(2.0_dp*my_tau - t8*t9/0.4e1_dp)/0.3e1_dp
585 t16 = 0.1e1_dp/t15
586 yval = 0.2e1_dp/0.3e1_dp*t2*t5*t16
587
588 e_0_br = 0.0_dp
589 e_rho_br = 0.0_dp
590 e_ndrho_br = 0.0_dp
591 e_tau_br = 0.0_dp
592 e_laplace_rho_br = 0.0_dp
593
594 IF (r == 0.0_dp) THEN
595 IF (yval <= 0.0_dp) THEN
596 CALL x_br_lsd_y_lte_0(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
597 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
598 sx, gamma, grad_deriv)
599 ELSE
600 CALL x_br_lsd_y_gt_0(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
601 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
602 sx, gamma, grad_deriv)
603 END IF
604 ELSE
605 IF (yval <= 0.0_dp) THEN
606 CALL x_br_lsd_y_lte_0_cutoff(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
607 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
608 sx, r, gamma, grad_deriv)
609 ELSE
610 CALL x_br_lsd_y_gt_0_cutoff(my_rho, my_ndrho, my_tau, my_laplace_rho, e_0_br, &
611 e_rho_br, e_ndrho_br, e_tau_br, e_laplace_rho_br, &
612 sx, r, gamma, grad_deriv)
613 END IF
614 END IF
615
616 ! ** Now we calculate the pbe cutoff part
617 ! ** Attention we need to scale rho, ndrho first
618 my_rho = my_rho*2.0_dp
619 my_ndrho = my_ndrho*2.0_dp
620
621 ! ** Do some precalculation in order to catch the correct branch afterwards
622 sscale = 1.0_dp
623 t1 = pi**2
624 t2 = t1*my_rho
625 t3 = t2**(0.1e1_dp/0.3e1_dp)
626 t4 = 0.1e1_dp/t3
627 t6 = my_ndrho*t4
628 t7 = 0.1e1_dp/my_rho
629 t8 = t7*sscale
630 ss = 0.3466806371753173524216762e0_dp*t6*t8
631 IF (ss > scutoff) THEN
632 ss2 = ss*ss
633 sscale = (smax*ss2 - sconst)/(ss2*ss)
634 END IF
635 e_0_pbe = 0.0_dp
636 e_rho_pbe = 0.0_dp
637 e_ndrho_pbe = 0.0_dp
638 IF (ss*sscale > gcutoff) THEN
639 CALL xpbe_hole_t_c_lr_lda_calc_1(e_0_pbe, e_rho_pbe, e_ndrho_pbe, &
640 my_rho, &
641 my_ndrho, sscale, sx, r, grad_deriv)
642 ELSE
643 CALL xpbe_hole_t_c_lr_lda_calc_2(e_0_pbe, e_rho_pbe, e_ndrho_pbe, &
644 my_rho, &
645 my_ndrho, sscale, sx, r, grad_deriv)
646 END IF
647
648 e_0_pbe = 0.5_dp*e_0_pbe
649
650 ! ** Finally we get the LDA part
651
652 e_0_lda = 0.0_dp
653 e_rho_lda = 0.0_dp
654 CALL xlda_hole_t_c_lr_lda_calc_0(grad_deriv, my_rho, e_0_lda, e_rho_lda, &
655 sx, r)
656 e_0_lda = 0.5_dp*e_0_lda
657
658 fx = e_0_br/e_0_lda
659
660 fermi = alpha/(exp((fx - mu)/n) + 1.0_dp)
661
662 e_0(ip) = e_0(ip) + (fermi*e_0_pbe + (1.0_dp - fermi)*e_0_br)*sx
663
664 IF (grad_deriv >= 1) THEN
665
666 dfermi_drho = -fermi**2/alpha/n*(e_rho_br/e_0_lda - e_0_br*e_rho_lda/e_0_lda**2)*exp((fx - mu)/n)
667 dfermi_dndrho = -fermi**2/alpha/n*(e_ndrho_br/e_0_lda)*exp((fx - mu)/n)
668 dfermi_dtau = -fermi**2/alpha/n*(e_tau_br/e_0_lda)*exp((fx - mu)/n)
669 dfermi_dlaplace_rho = -fermi**2/alpha/n*(e_laplace_rho_br/e_0_lda)*exp((fx - mu)/n)
670
671 e_rho(ip) = e_rho(ip) + (fermi*e_rho_pbe + dfermi_drho*e_0_pbe + &
672 (1.0_dp - fermi)*e_rho_br - dfermi_drho*e_0_br)*sx
673
674 e_ndrho(ip) = e_ndrho(ip) + (fermi*e_ndrho_pbe + dfermi_dndrho*e_0_pbe + &
675 (1.0_dp - fermi)*e_ndrho_br - dfermi_dndrho*e_0_br)*sx
676
677 e_tau(ip) = e_tau(ip) + (dfermi_dtau*e_0_pbe + &
678 (1.0_dp - fermi)*e_tau_br - dfermi_dtau*e_0_br)*sx
679
680 e_laplace_rho(ip) = e_laplace_rho(ip) + (dfermi_dlaplace_rho*e_0_pbe + &
681 (1.0_dp - fermi)*e_laplace_rho_br - dfermi_dlaplace_rho*e_0_br)*sx
682 END IF
683
684 END IF
685 END DO
686
687!$OMP END DO
688
689 END SUBROUTINE xbr_pbe_lda_hole_tc_lr_lsd_calc
690
Calculation of the incomplete Gamma function F_n(t) for multi-center integrals over Cartesian Gaussia...
Definition gamma.F:15
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Module with functions to handle derivative descriptors. derivative description are strings have the f...
integer, parameter, public deriv_norm_drho
integer, parameter, public deriv_laplace_rhob
integer, parameter, public deriv_norm_drhoa
integer, parameter, public deriv_rhob
integer, parameter, public deriv_rhoa
integer, parameter, public deriv_tau
integer, parameter, public deriv_tau_b
integer, parameter, public deriv_tau_a
integer, parameter, public deriv_laplace_rhoa
integer, parameter, public deriv_rho
integer, parameter, public deriv_norm_drhob
integer, parameter, public deriv_laplace_rho
represent a group ofunctional derivatives
type(xc_derivative_type) function, pointer, public xc_dset_get_derivative(derivative_set, description, allocate_deriv)
returns the requested xc_derivative
Provides types for the management of the xc-functionals and their derivatives.
subroutine, public xc_derivative_get(deriv, split_desc, order, deriv_data, accept_null_data)
returns various information on the given derivative
contains the structure
contains the structure
subroutine, public xc_rho_set_get(rho_set, can_return_null, rho, drho, norm_drho, rhoa, rhob, norm_drhoa, norm_drhob, rho_1_3, rhoa_1_3, rhob_1_3, laplace_rho, laplace_rhoa, laplace_rhob, drhoa, drhob, rho_cutoff, drho_cutoff, tau_cutoff, tau, tau_a, tau_b, local_bounds)
returns the various attributes of rho_set
Calculates the exchange energy based on the Becke-Roussel exchange hole. Takes advantage of an analyt...
subroutine, public x_br_lsd_y_gt_0(rho, ndrho, tau, laplace_rho, e_0, e_rho, e_ndrho, e_tau, e_laplace_rho, sx, gamma, grad_deriv)
Full range evaluation for y > 0.
subroutine, public x_br_lsd_y_gt_0_cutoff(rho, ndrho, tau, laplace_rho, e_0, e_rho, e_ndrho, e_tau, e_laplace_rho, sx, r, gamma, grad_deriv)
Truncated long range part for y > 0.
subroutine, public x_br_lsd_y_lte_0_cutoff(rho, ndrho, tau, laplace_rho, e_0, e_rho, e_ndrho, e_tau, e_laplace_rho, sx, r, gamma, grad_deriv)
Truncated long range part for y <= 0.
subroutine, public x_br_lsd_y_lte_0(rho, ndrho, tau, laplace_rho, e_0, e_rho, e_ndrho, e_tau, e_laplace_rho, sx, gamma, grad_deriv)
full range evaluation for y <= 0
This functional is a combination of three different exchange hole models. The ingredients are:
subroutine, public xbr_pbe_lda_hole_tc_lr_lsd_eval(rho_set, deriv_set, grad_deriv, params)
Intermediate routine that gets grids, derivatives and some params.
subroutine, public xbr_pbe_lda_hole_tc_lr_lda_eval(rho_set, deriv_set, grad_deriv, params)
Intermediate routine that gets grids, derivatives and some params.
subroutine, public xbr_pbe_lda_hole_tc_lr_lda_info(reference, shortform, needs, max_deriv)
return various information on the functional
subroutine, public xbr_pbe_lda_hole_tc_lr_lsd_info(reference, shortform, needs, max_deriv)
return various information on the functional
Calculates the lda exchange hole in a truncated coulomb potential. Can be used as longrange correctio...
subroutine, public xlda_hole_t_c_lr_lda_calc_0(order, rho, e_0, e_rho, sx, r)
low level routine
Calculates the exchange energy for the pbe hole model in a truncated coulomb potential,...
elemental subroutine, public xpbe_hole_t_c_lr_lda_calc_1(e_0, e_rho, e_ndrho, rho, ndrho, sscale, sx, r, order)
low level routine that calculates the energy derivatives in one point
elemental subroutine, public xpbe_hole_t_c_lr_lda_calc_2(e_0, e_rho, e_ndrho, rho, ndrho, sscale, sx, r, order)
low level routine that calculates the energy derivatives in one point
A derivative set contains the different derivatives of a xc-functional in form of a linked list.
represent a derivative of a functional
contains a flag for each component of xc_rho_set, so that you can use it to tell which components you...
represent a density, with all the representation and data needed to perform a functional evaluation