Line data Source code
1 : !!****m* ABINIT/m_special_funcs
2 : !! NAME
3 : !! m_special_funcs
4 : !!
5 : !! FUNCTION
6 : !! This module contains routines and functions used to
7 : !! evaluate special functions frequently needed in Abinit.
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2008-2026 ABINIT group (MG, MT, FB, XG, MVer, FJ, NH, GZ, DRH)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_special_funcs
24 :
25 : use defs_basis
26 : use m_abicore
27 : use m_errors
28 : use m_splines
29 :
30 : use m_fstrings, only : sjoin, ftoa
31 : use m_numeric_tools, only : arth, simpson
32 :
33 : implicit none
34 :
35 : private
36 :
37 : public :: clp ! x-1, if x>1/2, x+1, if x<-1/2
38 : public :: factorial ! Calculates N! returning a real.
39 : public :: permutations ! Returns N!/(N-k) if N>=0 and N-k>0 else 0.
40 : public :: binomcoeff ! Binomial coefficient n!/(n-k)!
41 : public :: laguerre ! Laguerre Polynomial(x,n,a).
42 : public :: RadFnH ! Atomic radial function(r,n,l,Z).
43 : public :: iradfnh ! Norm of atomic radial function(a,b,n,l,Z).
44 : public :: gaussian ! Normalized Gaussian distribution.
45 : public :: lorentzian ! Approximate Dirac Delta with lorentzian
46 : public :: abi_derf ! Evaluates the error function in real(dp).
47 : public :: abi_derfc ! Evaluates the complementary error function in real(dp).
48 : public :: gamma_function ! Computes the gamma function
49 : public :: besjm ! Spherical bessel function of order nn. Handles nn=0,1,2,3,4, or 5 only.
50 : public :: sbf8 ! Computes set of spherical bessel functions using accurate algorithm
51 : public :: k_fermi ! Fermi wave vector corresponding to the local value of the real space density rhor.
52 : public :: k_thfermi ! Thomas-Fermi wave vector corresponding to the local value of the real space density rhor
53 : public :: levi_civita_3 ! Return Levi-Civita tensor of rank 3
54 : public :: fermi_dirac ! Fermi Dirac distribution
55 : public :: bose_einstein ! Bose Einstein distribution
56 : public :: dip12 ! Complete Fermi integral of order 1/2
57 : public :: dip32 ! Complete Fermi integral of order 3/2
58 : public :: djp12 ! Incomplete Fermi integral of order 1/2
59 : public :: djp32 ! Incomplete Fermi integral of order 3/2
60 : public :: tildeAx ! tilde Ax Pade fit and first and second derivatives
61 : public :: tildeBx ! tilde Bx Pade fit and first and second derivatives
62 : public :: tildeBc ! tilde Bc Pade fit and first and second derivatives
63 : !!***
64 :
65 : !!****t* m_special_funcs/jlspline_t
66 : !! NAME
67 : !! jlspline_t
68 : !!
69 : !! FUNCTION
70 : !! Object used to interpolate Bessel functions
71 : !!
72 : !! SOURCE
73 :
74 : type,public :: jlspline_t
75 :
76 : integer :: nx
77 : ! number of points on linear mesh used in spline.
78 :
79 : integer :: mlang
80 : ! mlang= max angular momentum + 1
81 :
82 : real(dp) :: delta
83 : ! Step of linear mesh.
84 :
85 : real(dp) :: maxarg
86 : ! max arg value.
87 :
88 : real(dp),allocatable :: xx(:)
89 : ! xx(nx)
90 : ! coordinates of points belonging to the grid
91 :
92 : real(dp),allocatable :: bess_spl(:,:)
93 : ! bess_spl(nx,mlang)
94 : ! bessel functions computed on the linear mesh
95 :
96 : real(dp),allocatable :: bess_spl_der(:,:)
97 : ! bess_spl_der(nx,mlang)
98 : ! the second derivatives of the cubic spline.
99 :
100 : contains
101 :
102 : procedure :: init => jlspline_init ! Create new object.
103 : procedure :: free => jlspline_free ! Free memory.
104 : procedure :: eval => jlspline_integral ! Compute integral.
105 :
106 : end type jlspline_t
107 : !!***
108 :
109 : !!****t* m_special_funcs/gspline_t
110 : !! NAME
111 : !! gspline_t
112 : !!
113 : !! FUNCTION
114 : !! Object used to interpolate the gaussian approximant and its primitive with cubic spline.
115 : !! Particularly useful if we are computing DOSes with many k-points/bands
116 : !! because one can significantly decrease the number of calls to exponential functions.
117 : !!
118 : !! SOURCE
119 :
120 : type,public :: gspline_t
121 :
122 : integer :: nspline
123 : ! Number of points used in spline table.
124 :
125 : real(dp) :: sigma
126 : ! Broadening parameter.
127 :
128 : real(dp) :: xmin, xmax
129 : ! Min and max x in spline mesh. Only positive xs are stored in memory
130 : ! The values at -x are reconstructed by symmetry.
131 : ! xmin is usually zero, xmax is the point where the gaussian == tol16.
132 : ! g(x) is set to zero if x > xmin.
133 :
134 : real(dp) :: step, stepm1, step2div6
135 : ! Step of the linear mesh used in spline and associated coefficients.
136 :
137 : real(dp),allocatable :: xvals(:)
138 : ! xvals(nspline)
139 : ! The xvalues used in the spline
140 :
141 : real(dp),allocatable :: svals(:,:)
142 : ! svals(nspline,4)
143 : ! Internal tables with spline data.
144 :
145 : contains
146 :
147 : procedure :: init => gspline_init ! Creation method.
148 : procedure :: eval => gspline_eval ! Evaluate interpolant
149 : procedure :: free => gspline_free ! Free memory.
150 : end type gspline_t
151 : !!***
152 :
153 : CONTAINS !===========================================================
154 : !!***
155 :
156 : !!****f* m_special_funcs/clp
157 : !! NAME
158 : !! clp
159 : !!
160 : !! FUNCTION
161 : !! clp(x)= x-1, if x>1/2
162 : !! x+1, if x<-1/2
163 : !!
164 : !! INPUTS
165 : !! x= input variable
166 : !!
167 : !! OUTPUT
168 : !! clp= resulting function
169 : !!
170 : !! SOURCE
171 :
172 0 : pure function clp(x)
173 :
174 : !Arguments ------------------------------------
175 : !scalars
176 : real(dp) :: clp
177 : real(dp),intent(in) :: x
178 : ! **********************************************************************
179 :
180 0 : if(x > half) then
181 0 : clp=x-one
182 0 : elseif(x < -half) then
183 0 : clp=x+one
184 : else
185 : clp=x
186 : end if
187 :
188 0 : end function clp
189 : !!***
190 :
191 : !!****f* m_special_funcs/factorial
192 : !! NAME
193 : !! factorial
194 : !!
195 : !! FUNCTION
196 : !! Calculates N!. Returns a (dp) real.
197 : !!
198 : !! INPUTS
199 : !! nn=number to use
200 : !!
201 : !! OUTPUT
202 : !! factorial= n! (real)
203 : !!
204 : !! SOURCE
205 :
206 47745 : elemental function factorial(nn)
207 :
208 : !Arguments ---------------------------------------------
209 : !scalars
210 : integer,intent(in) :: nn
211 : real(dp) :: factorial
212 :
213 : !Local variables ---------------------------------------
214 : !scalars
215 : integer :: ii
216 : real(dp) :: ff
217 : ! *********************************************************************
218 :
219 47745 : ff=one
220 115523 : do ii=2,nn
221 284483 : ff=ff*ii
222 : end do
223 :
224 47745 : factorial=ff
225 :
226 1665 : end function factorial
227 : !!***
228 :
229 : !!****f* m_special_funcs/permutations
230 : !! NAME
231 : !! permutations
232 : !!
233 : !! FUNCTION
234 : !! Returns N!/(N-k)! if N>=0 and N-k>0
235 : !! otherwise 0 is returned
236 : !! Output is real
237 : !!
238 : !! INPUTS
239 : !! kk=number k to use
240 : !! nn=number N to use
241 : !!
242 : !! OUTPUT
243 : !! permutations= n!/(n-k)! (real)
244 : !!
245 : !! SOURCE
246 :
247 1665 : pure function permutations(nn,kk)
248 :
249 : !Arguments ---------------------------------------------
250 : !scalars
251 : integer,intent(in) :: kk,nn
252 : real(dp) :: permutations
253 :
254 : !Local variables ---------------------------------------
255 : !scalars
256 : integer :: ii
257 : real(dp) :: pp
258 : ! *********************************************************************
259 :
260 1665 : if ((nn>=0).and.((nn-kk)>=0)) then
261 1665 : pp=one
262 9575 : do ii=nn-kk+1,nn
263 9575 : pp=pp*ii
264 : end do
265 : else
266 : pp=zero
267 : end if
268 :
269 1665 : permutations=pp
270 :
271 1665 : end function permutations
272 : !!***
273 :
274 : !----------------------------------------------------------------------
275 :
276 : !!****f* m_special_funcs/binomcoeff
277 : !! NAME
278 : !! factorial
279 : !!
280 : !! FUNCTION
281 : !! Calculates n!/( k!* (n-k)!). Returns a real (dp)
282 : !!
283 : !! INPUTS
284 : !! nn=number to use
285 : !!
286 : !! OUTPUT
287 : !! binomcoeff= n!/( k!* (n-k)!) (real dp)
288 : !!
289 : !! SOURCE
290 :
291 15360 : elemental function binomcoeff(n,k)
292 :
293 : !Arguments ---------------------------------------------
294 : !scalars
295 : integer,intent(in) :: n,k
296 : real(dp) :: binomcoeff
297 : ! *********************************************************************
298 :
299 107520 : binomcoeff=factorial(n)/(factorial(k)*factorial(n-k))
300 :
301 15360 : end function binomcoeff
302 : !!***
303 :
304 : !----------------------------------------------------------------------
305 :
306 : !!****f* m_special_funcs/laguerre
307 : !! NAME
308 : !! laguerre
309 : !!
310 : !! FUNCTION
311 : !! Laguerre(x,n,a). Returns a (dp) real.
312 : !!
313 : !! INPUTS
314 : !! x position
315 : !! n order of laguerre polynomial
316 : !! a
317 : !!
318 : !! OUTPUT
319 : !! Laguerre(x,n,a) (dp)
320 : !!
321 : !! SOURCE
322 :
323 15360 : function laguerre(x,n,a)
324 :
325 : !Arguments ---------------------------------------------
326 : !scalars
327 : integer,intent(in),optional :: n,a
328 : real(dp) :: laguerre
329 : real(dp),intent(in) :: x
330 :
331 : !Local variables ---------------------------------------
332 : !scalars
333 : integer :: ii, nn, aa
334 :
335 : !arrays
336 15360 : real(dp),allocatable :: ff(:)
337 : ! *********************************************************************
338 :
339 15360 : if (present(n)) then
340 15360 : nn=n
341 : else
342 : nn=1
343 : end if
344 :
345 15360 : if (present(a)) then
346 15360 : aa=a
347 : else
348 : aa=0
349 : end if
350 46080 : ABI_MALLOC(ff,(nn+1))
351 30720 : ff=0.0_dp
352 76800 : ff=(/ (binomcoeff(nn+aa,nn-ii)*((-1.0_dp)*x)**ii/factorial(ii) ,ii=0,nn) /)
353 30720 : laguerre=sum(ff)
354 :
355 15360 : ABI_FREE(ff)
356 :
357 15360 : end function laguerre
358 : !!***
359 :
360 : !----------------------------------------------------------------------
361 :
362 : !!****f* m_special_funcs/RadFnH
363 : !! NAME
364 : !! RadFnH
365 : !!
366 : !! FUNCTION
367 : !! RadFnH(r,n,l,Z) radial function of atomic wavefunction with nuclear charge Z.
368 : !! for quantum number n, and l.
369 : !! Default: Fe 3d function. Returns a (dp) real.
370 : !!
371 : !! INPUTS
372 : !! r radius
373 : !! n principal quantum number
374 : !! l quantum number
375 : !!
376 : !! OUTPUT
377 : !! RadFnH(r,n,l,Z) (dp)
378 : !!
379 : !! SOURCE
380 :
381 15360 : function RadFnH(r,n,l,Z)
382 :
383 : !Arguments ---------------------------------------------
384 : !scalars
385 : integer,intent(in),optional :: n,l
386 : real(dp) :: RadFnH
387 : real(dp),intent(in) :: r
388 : real(dp),intent(in),optional :: Z
389 :
390 : !Local variables ---------------------------------------
391 : !scalars
392 : integer :: nn,ll
393 : real(dp) :: ff,rr,ZZ
394 : ! *********************************************************************
395 :
396 15360 : if (present(n)) then
397 15360 : nn=n
398 : else
399 : nn=3
400 : end if
401 :
402 15360 : if (present(l)) then
403 15360 : ll=l
404 : else
405 : ll=2
406 : end if
407 :
408 15360 : if (present(Z)) then
409 15360 : ZZ=Z
410 : else
411 : ZZ=28.0_dp
412 : end if
413 :
414 15360 : rr=ZZ*r/nn
415 15360 : ff=exp(log(ZZ*1.0_dp)*(3.0_dp/2.0_dp))*2/nn**2
416 92160 : ff=ff*sqrt(factorial(nn-ll-1)/factorial(nn+ll))*(2*rr)**ll
417 15360 : RadFnH=ff*exp(-1*rr)*laguerre(2*rr,nn-ll-1,2*ll+1)
418 :
419 15360 : end function RadFnH
420 : !!***
421 :
422 : !----------------------------------------------------------------------
423 :
424 : !!****f* m_special_funcs/IRadFnH
425 : !! NAME
426 : !! IRadFnH
427 : !!
428 : !! FUNCTION
429 : !! IRadFnH(a,b,n,l,Z): Integral of radial function of atomic wavefunction between a and b.
430 : !! recursive programming using simpson's rule
431 : !! iteration depth of m=8 corresponds to relative error of 10^(-12).
432 : !!
433 : !! INPUTS
434 : !! a lower limit for integration
435 : !! b upper limit for integration
436 : !! n principal quantum number
437 : !! l quantum number
438 : ! Z nuclear charge
439 : !!
440 : !! OUTPUT
441 : !! IRadFnH(a,b,n,l,Z) (dp)
442 : !!
443 : !! SOURCE
444 :
445 10220 : recursive function IRadFnH(a,b,n,l,Z,m) result(x)
446 :
447 : !Arguments ---------------------------------------------
448 : !scalars
449 : integer,intent(in),optional :: n,l,m
450 : real(dp),intent(in):: a
451 : real(dp),intent(in),optional :: b,Z
452 :
453 : !Local variables ---------------------------------------
454 : !scalars
455 : integer :: nn,ll,mm
456 : real(dp) :: h,bb,ZZ,x
457 : ! *********************************************************************
458 :
459 10220 : if (present(n)) then
460 10220 : nn=n
461 : else
462 0 : nn=3
463 : end if
464 :
465 10220 : if (present(l)) then
466 10220 : ll=l
467 : else
468 0 : ll=2
469 : end if
470 :
471 10220 : if (present(Z)) then
472 10220 : ZZ=Z
473 : else
474 0 : ZZ=28
475 : end if
476 :
477 10220 : if (present(b)) then
478 10220 : bb=b
479 : else
480 0 : bb=100.0_dp
481 : end if
482 :
483 10220 : if (present(m)) then
484 10200 : mm=m
485 : else
486 : mm=0
487 : end if
488 :
489 10220 : h=(bb-a)/2.0_dp
490 10220 : if (mm<8) then
491 : !h=2*h/exp(1.0_dp)
492 5100 : x=IRadFnH(a,a+h,nn,ll,ZZ,mm+1)+IRadFnH(a+h,bb,nn,ll,ZZ,mm+1)
493 : else
494 5120 : x=RadFnH(a,nn,ll,ZZ)**2*a**2+4.0_dp*RadFnH(a+h,nn,ll,ZZ)**2*(a+h)**2
495 5120 : x=h/3.0_dp*(x+RadFnH(bb,nn,ll,ZZ)**2*bb**2)
496 : end if
497 :
498 10220 : end function IRadFnH
499 : !!***
500 :
501 : !----------------------------------------------------------------------
502 :
503 : !!****f* m_special_funcs/gaussian
504 : !! NAME
505 : !! gaussian
506 : !!
507 : !! FUNCTION
508 : !! Return the values of the normalized Gaussian distribution:
509 : !!
510 : !! Gauss(arg,sigma) = 1/(sigma SQRT(2*pi)) e^{-arg**2/(2*sigma**2)}
511 : !!
512 : !! INPUTS
513 : !! arg=Argument of the Gaussian.
514 : !! sigma=Standard deviation
515 : !!
516 : !! SOURCE
517 :
518 16907114 : elemental function gaussian(arg, sigma)
519 :
520 : !Arguments ---------------------------------------------
521 : !scalars
522 : real(dp),intent(in) :: arg,sigma
523 : real(dp) :: gaussian
524 :
525 : !Local variables ---------------------------------------
526 : real(dp) :: xx
527 : ! *********************************************************************
528 :
529 16907114 : xx = arg / (sqrt2 * sigma)
530 16907114 : gaussian = exp(-xx*xx) / (sigma * sqrt(two_pi))
531 :
532 16907114 : end function gaussian
533 : !!***
534 :
535 : !----------------------------------------------------------------------
536 :
537 : !!****f* m_special_funcs/lorentzian
538 : !! NAME
539 : !! lorentzian
540 : !!
541 : !! FUNCTION
542 : !! Lorentzian function.
543 : !!
544 : !! INPUTS
545 : !! arg=Argument of the lorentzian.
546 : !! sigma=Broadening factor
547 : !!
548 : !! SOURCE
549 :
550 0 : elemental function lorentzian(arg, sigma)
551 :
552 : !Arguments ---------------------------------------------
553 : real(dp),intent(in) :: arg, sigma
554 : real(dp) :: lorentzian
555 : ! *********************************************************************
556 :
557 0 : lorentzian = piinv * sigma / (arg ** 2 + sigma ** 2)
558 :
559 0 : end function lorentzian
560 : !!***
561 :
562 : !----------------------------------------------------------------------
563 :
564 : !!****f* m_special_funcs/abi_derf
565 : !! NAME
566 : !! abi_derf
567 : !!
568 : !! FUNCTION
569 : !! Evaluates the error function in real(dp).
570 : !! Same implementation as imsl.
571 : !! Simple mod of derfc.F90
572 : !!
573 : !! INPUTS
574 : !! yy
575 : !!
576 : !! OUTPUT
577 : !! derf_yy= error function of yy
578 : !!
579 : !! SOURCE
580 :
581 3278 : elemental function abi_derf(yy) result(derf_yy)
582 :
583 : !Arguments ------------------------------------
584 : !scalars
585 : real(dp),intent(in) :: yy
586 : real(dp) :: derf_yy
587 :
588 : !Local variables-------------------------------
589 : integer :: done,ii,isw
590 : ! coefficients for 0.0 <= yy < .477
591 : real(dp), parameter :: &
592 : & pp(5)=(/ 113.8641541510502e0_dp, 377.4852376853020e0_dp, &
593 : & 3209.377589138469e0_dp, .1857777061846032e0_dp, &
594 : & 3.161123743870566e0_dp /)
595 : real(dp), parameter :: &
596 : & qq(4)=(/ 244.0246379344442e0_dp, 1282.616526077372e0_dp, &
597 : & 2844.236833439171e0_dp, 23.60129095234412e0_dp/)
598 : ! coefficients for .477 <= yy <= 4.0
599 : real(dp), parameter :: &
600 : & p1(9)=(/ 8.883149794388376e0_dp, 66.11919063714163e0_dp, &
601 : & 298.6351381974001e0_dp, 881.9522212417691e0_dp, &
602 : & 1712.047612634071e0_dp, 2051.078377826071e0_dp, &
603 : & 1230.339354797997e0_dp, 2.153115354744038e-8_dp, &
604 : & .5641884969886701e0_dp /)
605 : real(dp), parameter :: &
606 : & q1(8)=(/ 117.6939508913125e0_dp, 537.1811018620099e0_dp, &
607 : & 1621.389574566690e0_dp, 3290.799235733460e0_dp, &
608 : & 4362.619090143247e0_dp, 3439.367674143722e0_dp, &
609 : & 1230.339354803749e0_dp, 15.74492611070983e0_dp/)
610 : ! coefficients for 4.0 < y,
611 : real(dp), parameter :: &
612 : & p2(6)=(/ -3.603448999498044e-01_dp, -1.257817261112292e-01_dp, &
613 : & -1.608378514874228e-02_dp, -6.587491615298378e-04_dp, &
614 : & -1.631538713730210e-02_dp, -3.053266349612323e-01_dp/)
615 : real(dp), parameter :: &
616 : & q2(5)=(/ 1.872952849923460e0_dp , 5.279051029514284e-01_dp, &
617 : & 6.051834131244132e-02_dp , 2.335204976268692e-03_dp, &
618 : & 2.568520192289822e0_dp /)
619 : real(dp), parameter :: &
620 : & sqrpi=.5641895835477563e0_dp, xbig=13.3e0_dp, xlarge=6.375e0_dp, xmin=1.0e-10_dp
621 : real(dp) :: res,xden,xi,xnum,xsq,xx
622 : ! ******************************************************************
623 :
624 3278 : xx = yy
625 3278 : isw = 1
626 : !Here change the sign of xx, and keep track of it thanks to isw
627 3278 : if (xx<0.0e0_dp) then
628 0 : isw = -1
629 0 : xx = -xx
630 : end if
631 :
632 3278 : done=0
633 :
634 : !Residual value, if yy < -6.375e0_dp
635 3278 : res=-1.0e0_dp
636 :
637 : !abs(yy) < .477, evaluate approximation for erfc
638 3278 : if (xx<0.477e0_dp) then
639 : ! xmin is a very small number
640 108 : if (xx<xmin) then
641 0 : res = xx*pp(3)/qq(3)
642 : else
643 108 : xsq = xx*xx
644 108 : xnum = pp(4)*xsq+pp(5)
645 108 : xden = xsq+qq(4)
646 432 : do ii = 1,3
647 324 : xnum = xnum*xsq+pp(ii)
648 432 : xden = xden*xsq+qq(ii)
649 : end do
650 108 : res = xx*xnum/xden
651 : end if
652 108 : if (isw==-1) res = -res
653 : done=1
654 : end if
655 :
656 : !.477 < abs(yy) < 4.0 , evaluate approximation for erfc
657 3278 : if (xx<=4.0e0_dp .and. done==0 ) then
658 1280 : xsq = xx*xx
659 1280 : xnum = p1(8)*xx+p1(9)
660 1280 : xden = xx+q1(8)
661 10240 : do ii=1,7
662 8960 : xnum = xnum*xx+p1(ii)
663 10240 : xden = xden*xx+q1(ii)
664 : end do
665 1280 : res = xnum/xden
666 1280 : res = res* exp(-xsq)
667 1280 : if (isw.eq.-1) then
668 0 : res = res-1.0e0_dp
669 : else
670 1280 : res=1.0e0_dp-res
671 : end if
672 1280 : done=1
673 : end if
674 :
675 : !y > 13.3e0_dp
676 3278 : if (isw > 0 .and. xx > xbig .and. done==0 ) then
677 0 : res = 1.0e0_dp
678 0 : done=1
679 : end if
680 :
681 : !4.0 < yy < 13.3e0_dp .or. -6.375e0_dp < yy < -4.0
682 : !evaluate minimax approximation for erfc
683 3278 : if ( ( isw > 0 .or. xx < xlarge ) .and. done==0 ) then
684 1890 : xsq = xx*xx
685 1890 : xi = 1.0e0_dp/xsq
686 1890 : xnum= p2(5)*xi+p2(6)
687 1890 : xden = xi+q2(5)
688 9450 : do ii = 1,4
689 7560 : xnum = xnum*xi+p2(ii)
690 9450 : xden = xden*xi+q2(ii)
691 : end do
692 1890 : res = (sqrpi+xi*xnum/xden)/xx
693 1890 : res = res* exp(-xsq)
694 1890 : if (isw.eq.-1) then
695 0 : res = res-1.0e0_dp
696 : else
697 1890 : res=1.0e0_dp-res
698 : end if
699 : end if
700 :
701 : !All cases have been investigated
702 3278 : derf_yy = res
703 :
704 3278 : end function abi_derf
705 : !!***
706 :
707 : !----------------------------------------------------------------------
708 :
709 : !!****f* m_special_funcs/abi_derfc
710 : !! NAME
711 : !! abi_derfc
712 : !!
713 : !! FUNCTION
714 : !! Evaluates the complementary error function in real(dp).
715 : !! Same implementation as imsl.
716 : !!
717 : !! INPUTS
718 : !! yy
719 : !!
720 : !! OUTPUT
721 : !! derfc_yy=complementary error function of yy
722 : !!
723 : !! SOURCE
724 :
725 1323946680 : elemental function abi_derfc(yy) result(derfc_yy)
726 :
727 : !Arguments ------------------------------------
728 : !scalars
729 : real(dp),intent(in) :: yy
730 : real(dp) :: derfc_yy
731 :
732 : !Local variables-------------------------------
733 : integer :: done,ii,isw
734 : ! coefficients for 0.0 <= yy < .477
735 : real(dp), parameter :: &
736 : & pp(5)=(/ 113.8641541510502e0_dp, 377.4852376853020e0_dp, &
737 : & 3209.377589138469e0_dp, .1857777061846032e0_dp, &
738 : & 3.161123743870566e0_dp /)
739 : real(dp), parameter :: &
740 : & qq(4)=(/ 244.0246379344442e0_dp, 1282.616526077372e0_dp, &
741 : & 2844.236833439171e0_dp, 23.60129095234412e0_dp/)
742 : ! coefficients for .477 <= yy <= 4.0
743 : real(dp), parameter :: &
744 : & p1(9)=(/ 8.883149794388376e0_dp, 66.11919063714163e0_dp, &
745 : & 298.6351381974001e0_dp, 881.9522212417691e0_dp, &
746 : & 1712.047612634071e0_dp, 2051.078377826071e0_dp, &
747 : & 1230.339354797997e0_dp, 2.153115354744038e-8_dp, &
748 : & .5641884969886701e0_dp /)
749 : real(dp), parameter :: &
750 : & q1(8)=(/ 117.6939508913125e0_dp, 537.1811018620099e0_dp, &
751 : & 1621.389574566690e0_dp, 3290.799235733460e0_dp, &
752 : & 4362.619090143247e0_dp, 3439.367674143722e0_dp, &
753 : & 1230.339354803749e0_dp, 15.74492611070983e0_dp/)
754 : ! coefficients for 4.0 < y,
755 : real(dp), parameter :: &
756 : & p2(6)=(/ -3.603448999498044e-01_dp, -1.257817261112292e-01_dp, &
757 : & -1.608378514874228e-02_dp, -6.587491615298378e-04_dp, &
758 : & -1.631538713730210e-02_dp, -3.053266349612323e-01_dp/)
759 : real(dp), parameter :: &
760 : & q2(5)=(/ 1.872952849923460e0_dp , 5.279051029514284e-01_dp, &
761 : & 6.051834131244132e-02_dp , 2.335204976268692e-03_dp, &
762 : & 2.568520192289822e0_dp /)
763 : real(dp), parameter :: &
764 : & sqrpi=.5641895835477563e0_dp, xbig=13.3e0_dp, xlarge=6.375e0_dp, xmin=1.0e-10_dp
765 : real(dp) :: res,xden,xi,xnum,xsq,xx
766 :
767 : !******************************************************************
768 :
769 1323946680 : xx = yy
770 1323946680 : isw = 1
771 : !Here change the sign of xx, and keep track of it thanks to isw
772 1323946680 : if (xx<0.0e0_dp) then
773 159608 : isw = -1
774 159608 : xx = -xx
775 : end if
776 :
777 1323946680 : done=0
778 :
779 : !Residual value, if yy < -6.375e0_dp
780 1323946680 : res=2.0e0_dp
781 :
782 : !abs(yy) < .477, evaluate approximation for erfc
783 1323946680 : if (xx<0.477e0_dp) then
784 : ! xmin is a very small number
785 123440 : if (xx<xmin) then
786 0 : res = xx*pp(3)/qq(3)
787 : else
788 123440 : xsq = xx*xx
789 123440 : xnum = pp(4)*xsq+pp(5)
790 123440 : xden = xsq+qq(4)
791 493760 : do ii = 1,3
792 370320 : xnum = xnum*xsq+pp(ii)
793 493760 : xden = xden*xsq+qq(ii)
794 : end do
795 123440 : res = xx*xnum/xden
796 : end if
797 123440 : if (isw==-1) res = -res
798 123440 : res = 1.0e0_dp-res
799 123440 : done=1
800 : end if
801 :
802 : !.477 < abs(yy) < 4.0 , evaluate approximation for erfc
803 1323946680 : if (xx<=4.0e0_dp .and. done==0 ) then
804 164750336 : xsq = xx*xx
805 164750336 : xnum = p1(8)*xx+p1(9)
806 164750336 : xden = xx+q1(8)
807 1318002688 : do ii=1,7
808 1153252352 : xnum = xnum*xx+p1(ii)
809 1318002688 : xden = xden*xx+q1(ii)
810 : end do
811 164750336 : res = xnum/xden
812 164750336 : res = res* exp(-xsq)
813 164750336 : if (isw.eq.-1) res = 2.0e0_dp-res
814 : done=1
815 : end if
816 :
817 : !y > 13.3e0_dp
818 1323922388 : if (isw > 0 .and. xx > xbig .and. done==0 ) then
819 5379318 : res = 0.0e0_dp
820 5379318 : done=1
821 : end if
822 :
823 : !4.0 < yy < 13.3e0_dp .or. -6.375e0_dp < yy < -4.0
824 : !evaluate minimax approximation for erfc
825 1323946680 : if ( ( isw > 0 .or. xx < xlarge ) .and. done==0 ) then
826 1153578434 : xsq = xx*xx
827 1153578434 : xi = 1.0e0_dp/xsq
828 1153578434 : xnum= p2(5)*xi+p2(6)
829 1153578434 : xden = xi+q2(5)
830 5767892170 : do ii = 1,4
831 4614313736 : xnum = xnum*xi+p2(ii)
832 5767892170 : xden = xden*xi+q2(ii)
833 : end do
834 1153578434 : res = (sqrpi+xi*xnum/xden)/xx
835 1153578434 : res = res* exp(-xsq)
836 1153578434 : if (isw.eq.-1) res = 2.0e0_dp-res
837 : end if
838 :
839 : !All cases have been investigated
840 1323946680 : derfc_yy = res
841 :
842 1323946680 : end function abi_derfc
843 : !!***
844 :
845 : !!****f* ABINIT/GAMMA_FUNCTION
846 : !! NAME
847 : !! GAMMA_FUNCTION
848 : !!
849 : !! FUNCTION
850 : !!
851 : !! INPUTS
852 : !!
853 : !! OUTPUT
854 : !!
855 : !! NOTES
856 : !!
857 : !! SOURCE
858 :
859 36 : subroutine GAMMA_FUNCTION(X,GA)
860 :
861 : ! ====================================================
862 : ! Purpose: This program computes the gamma function
863 : ! Gamma(x) using subroutine GAMMA
864 : ! Examples:
865 : ! x Gamma(x)
866 : ! ----------------------------
867 : ! 1/3 2.678938534708
868 : ! 0.5 1.772453850906
869 : ! -0.5 -3.544907701811
870 : ! -1.5 2.363271801207
871 : ! 5.0 24.000000000000
872 : ! ====================================================
873 : !
874 : ! This routine was downloaded from UIUC:
875 : ! http://jin.ece.uiuc.edu/routines/routines.html
876 : !
877 : ! The programs appear to accompany a book "Computation of Special
878 : ! Functions" (1996) John Wiley and Sons, but are distributed online
879 : ! by the authors. Exact copyright should be checked.
880 : !
881 : ! Authors / copyright:
882 : ! Shanjie Zhang and Jianming Jin
883 : ! Proposed contact is: j-jin1@uiuc.edu
884 : !
885 : ! 20 October 2008:
886 : ! Incorporated into ABINIT by M. Verstraete
887 : !
888 : !
889 : !
890 : ! ==================================================
891 : ! Purpose: Compute the gamma function Gamma(x)
892 : ! Input : x --- Argument of Gamma(x)
893 : ! ( x is not equal to 0,-1,-2, etc )
894 : ! Output: GA --- Gamma(x)
895 : ! ==================================================
896 : !
897 :
898 : ! arguments
899 :
900 : real(dp),intent(in) :: x
901 : real(dp),intent(out) :: ga
902 :
903 : ! local variables
904 : integer :: k,m
905 : real(dp) :: m1,z,r,gr
906 : real(dp) :: G(26)
907 :
908 : ! source code:
909 :
910 : ! initialization of reference data
911 : G=(/1.0D0,0.5772156649015329D0, &
912 : & -0.6558780715202538D0, -0.420026350340952D-1, &
913 : & 0.1665386113822915D0,-.421977345555443D-1, &
914 : & -.96219715278770D-2, .72189432466630D-2, &
915 : & -.11651675918591D-2, -.2152416741149D-3, &
916 : & .1280502823882D-3, -.201348547807D-4, &
917 : & -.12504934821D-5, .11330272320D-5, &
918 : & -.2056338417D-6, .61160950D-8, &
919 : & .50020075D-8, -.11812746D-8, &
920 : & .1043427D-9, .77823D-11, &
921 : & -.36968D-11, .51D-12, &
922 36 : & -.206D-13, -.54D-14, .14D-14, .1D-15/)
923 :
924 :
925 : ! for the integer case, do explicit factorial
926 36 : if (X==int(X)) then
927 0 : if (X > 0.0D0) then
928 0 : GA=1.0D0
929 0 : M1=X-1
930 0 : do K=2,int(M1)
931 0 : GA=GA*K
932 : end do
933 : else
934 0 : GA=1.0D+300
935 : end if
936 : ! for the integer case, do explicit factorial
937 : else
938 36 : if (abs(X) > 1.0D0) then
939 36 : Z=abs(X)
940 36 : M=int(Z)
941 36 : R=1.0D0
942 180 : do K=1,M
943 180 : R=R*(Z-K)
944 : end do
945 36 : Z=Z-M
946 : else
947 : Z=X
948 : end if
949 36 : GR=G(26)
950 936 : do K=25,1,-1
951 936 : GR=GR*Z+G(K)
952 : end do
953 36 : GA=1.0D0/(GR*Z)
954 36 : if (abs(X) > 1.0D0) then
955 36 : GA=GA*R
956 36 : if (X < 0.0D0) GA=-PI/(X*GA*SIN(PI*X))
957 : end if
958 : end if
959 36 : return
960 :
961 : end subroutine GAMMA_FUNCTION
962 : !!***
963 :
964 : !!****f* m_special_funcs/besjm
965 : !! NAME
966 : !! besjm
967 : !!
968 : !! FUNCTION
969 : !! Spherical bessel function of order nn. Handles nn=0,1,2,3,4, or 5 only.
970 : !!
971 : !! INPUTS
972 : !! arg= scaling to be applied to xx(nx)
973 : !! nn=order of spherical bessel function (only 0 through 5 allowed)
974 : !! cosx(1:nx)=cosines of arg*xx(1:nx)
975 : !! xx(1:nx)=set of dimensionless arguments of function
976 : !! nx=number of arguments
977 : !! sinx(1:nx)=sines of arg*xx(1:nx)
978 : !!
979 : !! OUTPUT
980 : !! besjx(1:nx)=returned values
981 : !!
982 : !! NOTES
983 : !! besj(nn,y)=$ j_{nn}(y) =(\frac{\pi}{2y})^{\frac{1}{2}}J(nn+\frac{1}{2},y)$
984 : !! where J=Bessel function of the first kind.
985 : !! besjm compute multiple values, and relies on precomputed values of sin and cos of y.
986 : !! The argument y is arg*xx(ix), for ix from 1 to nx
987 : !! The values of xx must be positive, and ordered by increasing order
988 : !! At small arg, the higher orders have so much cancellation that the
989 : !! analytic expression is very poor computationally. In that case we
990 : !! use a rational polynomial approximation.
991 : !!
992 : !! SOURCE
993 :
994 4807693 : subroutine besjm(arg,besjx,cosx,nn,nx,sinx,xx)
995 :
996 : !Arguments ------------------------------------
997 : !scalars
998 : integer,intent(in) :: nn,nx
999 : real(dp),intent(in) :: arg
1000 : !arrays
1001 : real(dp),intent(in) :: cosx(nx),sinx(nx),xx(nx)
1002 : real(dp),intent(out) :: besjx(nx)
1003 :
1004 : !Local variables-------------------------------
1005 : !scalars
1006 : integer :: ix,switchx
1007 : !Series or rational polynomial coefficients
1008 : real(dp),parameter :: b01=1.d0/6.d0,b02=1.d0/120.d0,b03=1.d0/5040.d0
1009 : real(dp),parameter :: b04=1.d0/362880.d0,b11=0.8331251468724171d-1
1010 : real(dp),parameter :: b12=0.2036961284395412d-2,b13=0.1932970379901801d-4
1011 : real(dp),parameter :: b14=0.6526053169009489d-7,b21=0.5867824627555163d-1
1012 : real(dp),parameter :: b22=0.1152501878595934d-2,b23=0.1011071389414764d-4
1013 : real(dp),parameter :: b24=0.4172322111421287d-7,b25=0.6790616688656543d-10
1014 : real(dp),parameter :: b31=0.439131885807176d-1,b32=0.6813139609887099d-3
1015 : real(dp),parameter :: b33=0.4899103784264755d-5,b34=0.17025590795625d-7
1016 : real(dp),parameter :: b35=0.2382642910613347d-10,b41=0.3587477991030971d-1
1017 : real(dp),parameter :: b42=0.4833719855268907d-3,b43=0.3238388977796242d-5
1018 : real(dp),parameter :: b44=0.1171802513125112d-7,b45=0.223261650431992d-10
1019 : real(dp),parameter :: b46=.1800045587335951d-13,b51=0.295232406376567d-1
1020 : real(dp),parameter :: b52=0.3359864457080573d-3,b53=0.19394750603618d-5
1021 : real(dp),parameter :: b54=0.6143166228216219d-8,b55=0.10378501636108d-10
1022 : real(dp),parameter :: b56=.749975122872713d-14
1023 : real(dp),parameter :: c11=0.1668748531275829d-1,c12=0.1342812442426702d-3
1024 : real(dp),parameter :: c13=0.6378249315355233d-6,c14=0.1573564527360138d-8
1025 : real(dp),parameter :: c21=0.127503251530198d-1,c22=0.7911240539893565d-4
1026 : real(dp),parameter :: c23=0.3044380758068054d-6,c24=0.7439837832363479d-9
1027 : real(dp),parameter :: c25=0.9515065658793124d-12,c31=0.1164236697483795d-1
1028 : real(dp),parameter :: c32=0.654858636312224d-4,c33=0.2265576367562734d-6
1029 : real(dp),parameter :: c34=0.4929905563217352d-9,c35=0.555120465710914d-12
1030 : real(dp),parameter :: c41=0.9579765544235745d-2,c42=0.4468999977536864d-4
1031 : real(dp),parameter :: c43=0.1315634305905896d-6,c44=0.2615492488301639d-9
1032 : real(dp),parameter :: c45=0.3387473312408129d-12,c46=.2280866204624012d-15
1033 : real(dp),parameter :: c51=0.8938297823881763d-2,c52=0.3874149021633025d-4
1034 : real(dp),parameter :: c53=0.1054692715135225d-6,c54=0.192879620987602d-9
1035 : real(dp),parameter :: c55=0.2284469423833734d-12,c56=0.139729234332572d-15
1036 : real(dp),parameter :: ffnth=1.d0/15.d0,o10395=1.d0/10395d0,oo105=1.d0/105.d0
1037 : real(dp),parameter :: oo945=1.d0/945.d0
1038 : real(dp) :: bot,rr,rsq,top
1039 : character(len=500) :: message
1040 : ! *************************************************************************
1041 :
1042 4807693 : if (nn==0) then
1043 :
1044 2370586 : switchx=nx+1
1045 644403935 : do ix=1,nx
1046 644394347 : rr=arg*xx(ix)
1047 644403935 : if (rr<=1.d-1) then
1048 642033349 : rsq=rr*rr
1049 642033349 : besjx(ix)=1.d0-rsq*(b01-rsq*(b02-rsq*(b03-rsq*b04)))
1050 : else
1051 : switchx=ix
1052 : exit
1053 : end if
1054 : end do
1055 :
1056 1321653242 : do ix=switchx,nx
1057 1319282656 : rr=arg*xx(ix)
1058 1321653242 : besjx(ix)=sinx(ix)/rr
1059 : end do
1060 :
1061 : else if (nn==1) then
1062 :
1063 1869755 : switchx=nx+1
1064 782041558 : do ix=1,nx
1065 781972309 : rr=arg*xx(ix)
1066 782041558 : if (rr<=1.d0) then
1067 780171803 : rsq=rr*rr
1068 780171803 : top=1.d0-rsq*(b11-rsq*(b12-rsq*(b13-rsq*b14)))
1069 780171803 : bot=1.d0+rsq*(c11+rsq*(c12+rsq*(c13+rsq*c14)))
1070 780171803 : besjx(ix)=third*rr*top/bot
1071 : else
1072 : switchx=ix
1073 : exit
1074 : end if
1075 : end do
1076 :
1077 783956221 : do ix=switchx,nx
1078 782086466 : rr=arg*xx(ix)
1079 782086466 : rsq=rr*rr
1080 783956221 : besjx(ix)=(sinx(ix)-rr*cosx(ix))/rsq
1081 : end do
1082 :
1083 : else if (nn==2) then
1084 :
1085 555190 : switchx=nx+1
1086 179572647 : do ix=1,nx
1087 179552563 : rr=arg*xx(ix)
1088 179572647 : if (rr<=2.d0) then
1089 179017457 : rsq=rr*rr
1090 179017457 : top=1.d0-rsq*(b21-rsq*(b22-rsq*(b23-rsq*(b24-rsq*b25))))
1091 179017457 : bot=1.d0+rsq*(c21+rsq*(c22+rsq*(c23+rsq*(c24+rsq*c25))))
1092 179017457 : besjx(ix)=ffnth*rsq*top/bot
1093 : else
1094 : switchx=ix
1095 : exit
1096 : end if
1097 : end do
1098 :
1099 263961161 : do ix=switchx,nx
1100 263405971 : rr=arg*xx(ix)
1101 263405971 : rsq=rr*rr
1102 263961161 : besjx(ix)=((3.d0-rsq)*sinx(ix)-3.d0*rr*cosx(ix))/(rr*rsq)
1103 : end do
1104 :
1105 : else if (nn==3) then
1106 :
1107 12081 : switchx=nx+1
1108 8377955 : do ix=1,nx
1109 8377180 : rr=arg*xx(ix)
1110 8377955 : if (rr<=2.d0) then
1111 8365874 : rsq=rr*rr
1112 8365874 : top=1.d0-rsq*(b31-rsq*(b32-rsq*(b33-rsq*(b34-rsq*b35))))
1113 8365874 : bot=1.d0+rsq*(c31+rsq*(c32+rsq*(c33+rsq*(c34+rsq*c35))))
1114 8365874 : besjx(ix)=rr*rsq*oo105*top/bot
1115 : else
1116 : switchx=ix
1117 : exit
1118 : end if
1119 : end do
1120 :
1121 3651507 : do ix=switchx,nx
1122 3639426 : rr=arg*xx(ix)
1123 3639426 : rsq=rr*rr
1124 : besjx(ix)=( (15.d0-6.d0*rsq)*sinx(ix)&
1125 3651507 : & + rr*(rsq-15.d0) *cosx(ix) ) /(rsq*rsq)
1126 : end do
1127 :
1128 : else if (nn==4) then
1129 :
1130 81 : switchx=nx+1
1131 3402 : do ix=1,nx
1132 3402 : rr=arg*xx(ix)
1133 3402 : if (rr<=4.d0) then
1134 3321 : rsq=rr*rr
1135 3321 : top=1.d0-rsq*(b41-rsq*(b42-rsq*(b43-rsq*(b44-rsq*(b45-rsq*b46)))))
1136 3321 : bot=1.d0+rsq*(c41+rsq*(c42+rsq*(c43+rsq*(c44+rsq*(c45+rsq*c46)))))
1137 3321 : besjx(ix)=rsq*rsq*oo945*top/bot
1138 : else
1139 : switchx=ix
1140 : exit
1141 : end if
1142 : end do
1143 :
1144 38060 : do ix=switchx,nx
1145 37979 : rr=arg*xx(ix)
1146 37979 : rsq=rr*rr
1147 : besjx(ix)=( (105.d0-rsq*(45.d0-rsq)) *sinx(ix)&
1148 38060 : & + rr * (10.d0*rsq-105.d0) *cosx(ix) ) /(rsq*rsq*rr)
1149 : end do
1150 :
1151 : else if (nn==5) then
1152 :
1153 0 : switchx=nx+1
1154 0 : do ix=1,nx
1155 0 : rr=arg*xx(ix)
1156 0 : if (rr<=4.d0) then
1157 0 : rsq=rr*rr
1158 0 : top=1.d0-rsq*(b51-rsq*(b52-rsq*(b53-rsq*(b54-rsq*(b55-rsq*b56)))))
1159 0 : bot=1.d0+rsq*(c51+rsq*(c52+rsq*(c53+rsq*(c54+rsq*(c55+rsq*c56)))))
1160 0 : besjx(ix)=rsq*rsq*rr*o10395*top/bot
1161 : else
1162 : switchx=ix
1163 : exit
1164 : end if
1165 : end do
1166 :
1167 0 : do ix=switchx,nx
1168 0 : rr=arg*xx(ix)
1169 0 : rsq=rr*rr
1170 : besjx(ix)=( (945.d0-rsq*(420.d0-rsq*15.d0)) *sinx(ix)&
1171 0 : & + rr * (945.d0-rsq*(105.d0-rsq)) *cosx(ix) ) /(rsq*rsq*rr)
1172 : end do
1173 :
1174 : else
1175 0 : write(message, '(a,i0,a)' )' besjm only defined for nn in [0,5]; input was nn=',nn,'.'
1176 0 : ABI_BUG(message)
1177 : end if
1178 :
1179 4807693 : end subroutine besjm
1180 : !!***
1181 :
1182 : !!****f* m_special_funcs/sbf8
1183 : !! NAME
1184 : !! sbf8
1185 : !!
1186 : !! FUNCTION
1187 : !! Computes set of spherical bessel functions using accurate algorithm
1188 : !! based on downward recursion in order and normalization sum.
1189 : !! Power series used at small arguments.
1190 : !!
1191 : !! INPUTS
1192 : !! nm=maximum angular momentum wanted + one
1193 : !! xx=argument of sbf
1194 : !!
1195 : !! OUTPUT
1196 : !! sb_out(nm)=values of spherical bessel functions for l=0,nm-1
1197 : !!
1198 : !! SOURCE
1199 :
1200 812315248 : subroutine sbf8(nm,xx,sb_out)
1201 :
1202 : !Arguments----------------------------------------------------------
1203 : !scalars
1204 : integer,intent(in) :: nm
1205 : real(dp),intent(in) :: xx
1206 : !arrays
1207 : real(dp),intent(out) :: sb_out(nm)
1208 :
1209 : !Local variables-------------------------------
1210 : !scalars
1211 : integer :: nlim,nn
1212 : real(dp) :: fn,sn,xi,xn,xs
1213 : !arrays
1214 812315248 : real(dp),allocatable :: sb(:)
1215 : ! *************************************************************************
1216 :
1217 812315248 : if(xx<= 1.0e-36_dp) then
1218 : ! zero argument section
1219 7827685 : sb_out(:)=zero
1220 2061565 : sb_out(1)=one
1221 810253683 : else if(xx<1.e-3_dp) then
1222 : ! small argument section
1223 15642225 : xn=one
1224 15642225 : xs=half*xx**2
1225 63748618 : do nn=1,nm
1226 48106393 : sb_out(nn)=xn*(one - xs*(one - xs/(4*nn+6))/(2*nn+1))
1227 63748618 : xn=xx*xn/(2*nn+1)
1228 : end do
1229 : else
1230 : ! recursion method
1231 794611458 : if(xx<one) then
1232 366068511 : nlim=nm+int(15.0e0_dp*xx)+1
1233 : else
1234 428542947 : nlim=nm+int(1.36e0_dp*xx)+15
1235 : end if
1236 2383834374 : ABI_MALLOC(sb,(nlim+1))
1237 794611458 : nn=nlim
1238 794611458 : xi=one/xx
1239 794611458 : sb(nn+1)=zero
1240 794611458 : sb(nn)=1.e-18_dp
1241 794611458 : sn=dble(2*nn-1)*1.e-36_dp
1242 14384210566 : do nn=nlim-1,1,-1
1243 14384210566 : sb(nn)=dble(2*nn+1)*xi*sb(nn+1) - sb(nn+2)
1244 : end do
1245 14384210566 : do nn=1,nlim-1
1246 14384210566 : sn=sn + dble(2*nn-1)*sb(nn)*sb(nn)
1247 : end do
1248 794611458 : fn=1.d0/sqrt(sn)
1249 3103206171 : sb_out(:)=fn*sb(1:nm)
1250 794611458 : ABI_FREE(sb)
1251 : end if
1252 :
1253 812315248 : end subroutine sbf8
1254 : !!***
1255 :
1256 : !----------------------------------------------------------------------
1257 :
1258 : !!****f* m_special_funcs/fermi_dirac
1259 : !! NAME
1260 : !! fermi_dirac
1261 : !!
1262 : !! FUNCTION
1263 : !! Returns the Fermi Dirac distribution for T and energy wrt Fermi level
1264 : !! presumes everything is in Hartree!!!! Not Kelvin for T
1265 : !!
1266 : !! INPUTS
1267 : !! energy = electron energy level
1268 : !! mu = chemical potential
1269 : !! temperature = T
1270 : !!
1271 : !! SOURCE
1272 :
1273 11046015 : function fermi_dirac(energy, mu, temperature)
1274 :
1275 : !Arguments ------------------------------------
1276 : !scalars
1277 : real(dp),intent(in) :: energy, mu, temperature
1278 : real(dp) :: fermi_dirac
1279 :
1280 : !Local variables-------------------------------
1281 : !scalars
1282 : real(dp) :: arg
1283 : ! *************************************************************************
1284 :
1285 11046015 : fermi_dirac = zero
1286 11046015 : if (temperature > tol12) then
1287 11039622 : arg = (energy-mu)/temperature
1288 11039622 : if(arg < -600._dp)then ! far below Ef
1289 : fermi_dirac = one
1290 11039622 : else if (arg < 600._dp)then ! around Ef
1291 11039622 : fermi_dirac = one / (exp(arg) + one)
1292 : end if
1293 : else ! T is too small - just step function
1294 6393 : if (mu-energy > tol12) fermi_dirac = one
1295 : end if
1296 :
1297 11046015 : end function fermi_dirac
1298 : !!***
1299 :
1300 : !----------------------------------------------------------------------
1301 :
1302 : !!****f* m_special_funcs/bose_einstein
1303 : !! NAME
1304 : !! bose_einstein
1305 : !!
1306 : !! FUNCTION
1307 : !! Returns the Bose Einstein distribution for T and energy
1308 : !! presumes everything is in Hartree!!!! Not Kelvin for T
1309 : !!
1310 : !! INPUTS
1311 : !! energy = electron energy level
1312 : !! temperature = T
1313 : !!
1314 : !! SOURCE
1315 :
1316 1247510 : real(dp) function bose_einstein(energy, temperature)
1317 :
1318 : !Arguments ------------------------------------
1319 : !scalars
1320 : real(dp),intent(in) :: energy, temperature
1321 :
1322 : !Local variables-------------------------------
1323 : real(dp) :: arg
1324 : ! *************************************************************************
1325 :
1326 1247510 : bose_einstein = zero
1327 1247510 : if (temperature > tol12) then
1328 1241117 : arg = energy/temperature
1329 1241117 : if(arg > tol12 .and. arg < 600._dp)then
1330 1102913 : bose_einstein = one / (exp(arg) - one)
1331 138204 : else if (arg < tol12) then
1332 138204 : ABI_WARNING('No Bose Einstein for negative energies')
1333 : end if
1334 : else
1335 6393 : ABI_WARNING('No Bose Einstein for negative or 0 T')
1336 : end if
1337 :
1338 :
1339 1247510 : end function bose_einstein
1340 : !!***
1341 :
1342 : !----------------------------------------------------------------------
1343 :
1344 : !!****f* m_special_funcs/dip12
1345 : !! NAME
1346 : !! dip12
1347 : !!
1348 : !! FUNCTION
1349 : !! Returns the complete Fermi integral of order 1/2.
1350 : !! Based on an analytical approximation.
1351 : !!
1352 : !! INPUTS
1353 : !! gamma=complete Fermi integral argument
1354 : !!
1355 : !! OUTPUT
1356 : !! dip12=resulting function
1357 : !!
1358 : !! SOURCE
1359 :
1360 158 : real(dp) function dip12(gamma)
1361 :
1362 : ! Arguments -------------------------------
1363 : ! Scalars
1364 : real(dp),intent(in) :: gamma
1365 :
1366 : ! Local variables -------------------------
1367 : ! Scalars
1368 : real(dp) :: d,dy
1369 : ! *********************************************************************
1370 :
1371 158 : if (gamma.lt.3.) then
1372 79 : dy=exp(gamma)
1373 79 : if (gamma+1.9375.LE.0) then
1374 : dip12=dy*&
1375 : & (1.-dy*(0.35355283-dy*(0.19242767-dy*(0.12456909-dy*&
1376 79 : & (8.5114507E-02-dy*4.551794E-02)))))
1377 : else
1378 0 : d=gamma-0.5
1379 : dip12=dy*(0.677695804-d*(0.187773135+d*(2.16197521E-02-d*&
1380 : & (9.23703807E-03+d*&
1381 : & (1.71735167E-03-d*(6.07913775E-04+d*&
1382 : & (1.1448629E-04-d*&
1383 : & (4.544432E-05+d*(6.4719368E-06-d*(3.794983E-06+d*&
1384 : & (1.7338029E-07-d*&
1385 : & (3.5546516E-07-d*(3.7329191E-08+d*&
1386 : & (3.3097822E-08-d*&
1387 : & (8.3190193E-09+d*(2.2752769E-09-d*(7.836005E-10+d*&
1388 0 : & (7.519551E-11-d*2.960006E-11))))))))))))))))))
1389 : end if
1390 79 : else if (gamma.lt.20.) then
1391 0 : if (gamma.lt.10.) then
1392 0 : d=gamma-6.5
1393 : dip12=12.839811+d*&
1394 : & (2.844774+d*(0.114920926-d*(3.43733039E-03-d*&
1395 : & (2.3980356E-04-d*&
1396 : & (2.0201888E-05-d*(1.5219883E-06-d*&
1397 : & (6.2770524E-08+d*&
1398 : & (4.8830336E-09-d*(2.1031164E-09-d*(5.785753E-10-d*&
1399 0 : & (7.233066E-11-d*1.230727E-12)))))))))))
1400 : else
1401 0 : d=gamma-14.5
1402 : dip12=41.7799227+d*&
1403 : & (4.2881461+d*(7.45407825E-02-d*(8.79243296E-04-d*&
1404 : & (2.38288861E-05-d*&
1405 : & (8.82474867E-07-d*(3.82865217E-08-d*&
1406 0 : & (1.9274292E-09-d*(1.42248669E-10-d*8.17019813E-12))))))))
1407 : end if
1408 : else
1409 79 : d=1./gamma
1410 79 : dy=gamma*dsqrt(gamma)/1.329340388
1411 : dip12=dy*(1.-d*(9.354E-07-d*(1.2338391-d*(6.77931E-03-d*&
1412 79 : & 1.17871643))))
1413 : end if
1414 158 : dip12=dip12*0.88622692
1415 158 : end function dip12
1416 : !!***
1417 :
1418 : !----------------------------------------------------------------------
1419 :
1420 : !!****f* m_special_funcs/dip32
1421 : !! NAME
1422 : !! dip32
1423 : !!
1424 : !! FUNCTION
1425 : !! Returns the complete Fermi integral of order 3/2.
1426 : !! Based on an analytical approximation.
1427 : !!
1428 : !! INPUTS
1429 : !! gamma=complete Fermi integral argument
1430 : !!
1431 : !! OUTPUT
1432 : !! dip32=resulting function
1433 : !!
1434 : !! SOURCE
1435 :
1436 79 : real(dp) function dip32(gamma)
1437 :
1438 : ! Arguments -------------------------------
1439 : real(dp),intent(in) :: gamma
1440 :
1441 : ! Local variables -------------------------
1442 : ! Scalars
1443 : real(dp) :: d,dval
1444 : ! *********************************************************************
1445 :
1446 79 : if (gamma.GT.1.75) then
1447 0 : dval=gamma*gamma*dsqrt(gamma)
1448 0 : if (gamma.LT.4.5) then
1449 0 : d=gamma-3.125
1450 : dip32=(1.27623+0.596065*gamma+0.3*dval)*&
1451 : & (1.0055558385-d*(5.23889494E-03+d*&
1452 : & (3.13523144E-03-d*(3.06124286E-03-d*&
1453 : & (1.3644667E-03-d*&
1454 : & (4.1528384E-04-d*(8.901188E-05-d*(1.079979E-05+d*&
1455 0 : & (2.29058E-06-d*(2.58985E-06-d*7.30909E-07))))))))))
1456 0 : else if (gamma.LT.12.) then
1457 0 : if (gamma.LT.8.) then
1458 0 : d=gamma-6.25
1459 : dip32=(2.01508+0.425775*gamma+0.3*dval)*&
1460 : & (1.000387131-d*(3.93626295E-04+d*&
1461 : & (2.55710115E-04-d*&
1462 : & (1.57383494E-04-d*(5.0286036E-05-d*&
1463 : & (1.2073559865E-05-d*&
1464 : & (2.4909523213E-06-d*(5.244328548E-07-d*&
1465 0 : & 8.0884033896E-08))))))))
1466 : else
1467 0 : d=gamma-10.
1468 : dip32=0.3*dval*&
1469 : & (1.064687247-d*(1.22972303E-02-d*(1.8362121E-03-d*&
1470 : & (2.433558E-04-d*(3.018186E-05-d*(3.5694E-06-d*&
1471 0 : & (4.11212E-07-d*(5.2151E-08-d*5.8424E-09))))))))
1472 : end if
1473 : else
1474 0 : d=1./gamma
1475 : dip32=0.30090111127*dval*&
1476 : & (1.-d*(2.863E-06-d*(6.168876549-d*&
1477 0 : & (1.740553E-02+d*(1.425257+d*2.95887)))))
1478 : end if
1479 79 : else if (gamma+0.75.LE.0) then
1480 79 : d=EXP(gamma)
1481 : dip32=d*&
1482 : & (1.-d*(1.76775246E-01-d*(6.4124584E-02-d*&
1483 : & (3.1027055E-02-d*(1.6797637E-02-d*&
1484 79 : & (8.212636E-03-d*(2.384106E-03)))))))
1485 : else
1486 0 : d=gamma-0.5
1487 : dip32=EXP(gamma)*(0.846691-0.128948*gamma)*&
1488 : & (1.034064158+d*(2.778947E-03-d*&
1489 : & (3.572502805E-02+d*(3.0411645E-03-d*&
1490 : & (1.7380548E-03+d*(2.7756776E-04-d*&
1491 : & (8.08302E-05+d*(1.59606E-05-d*&
1492 0 : & (3.8144E-06+d*7.4446E-07)))))))))
1493 : end if
1494 79 : dip32=dip32*1.32934038
1495 :
1496 79 : end function dip32
1497 : !!***
1498 :
1499 : !----------------------------------------------------------------------
1500 :
1501 : !!****f* m_special_funcs/djp12
1502 : !! NAME
1503 : !! djp12
1504 : !!
1505 : !! FUNCTION
1506 : !! Returns the incomplete Fermi integral of order 1/2.
1507 : !! Based on an analytical approximation.
1508 : !!
1509 : !! INPUTS
1510 : !! xcut=lower bound of the incomplete Fermi integral
1511 : !! gamma=incomplete Fermi integral argument
1512 : !!
1513 : !! OUTPUT
1514 : !! djp12=resulting function
1515 : !!
1516 : !! SOURCE
1517 :
1518 4149 : real(dp) function djp12(xcut, gamma)
1519 :
1520 : ! Arguments -------------------------------
1521 : ! Scalars
1522 : real(dp),intent(in) :: xcut,gamma
1523 :
1524 : ! Local variables -------------------------
1525 : ! Scalars
1526 : real(dp) :: d2h,db,dc,dd,de,df1,df2,df3,dh
1527 : real(dp) :: ds,dt,dv,dw,dxm,dxp
1528 : integer :: i,ind,iq,k,nm,np,nq
1529 : ! Arrays
1530 : real(dp) :: dq(5),df(101),dy(101)
1531 : ! *********************************************************************
1532 :
1533 4149 : dh=0.2D+0
1534 4149 : d2h=0.4D+0
1535 4149 : nm=101
1536 4149 : ind=0
1537 4149 : dq=(/1.D+0,2.828427124D+0,5.196152423D+0,8.D+0,1.118033989D+1/)
1538 :
1539 4149 : djp12=0.D+0
1540 4149 : dxm=gamma-1.5D+1
1541 4149 : if (xcut.gt.dxm) then
1542 : if (ind.eq.0) then
1543 415140 : do i=1,nm
1544 411070 : dy(i)=-1.5D+1+(i-1)*dh
1545 415140 : df(i)=1.D+0+dexp(dy(i))
1546 : end do
1547 4070 : ind=1
1548 : end if
1549 4070 : dxp=gamma+5.D+0
1550 : if (xcut.lt.dxp) then
1551 : dc=dxp
1552 : else
1553 : dc=xcut
1554 : end if
1555 4070 : db=dexp(gamma-dc)
1556 4070 : dt=db
1557 15892 : do iq=1,5
1558 15892 : dd=iq*dc
1559 15892 : ds=dsqrt(dd)
1560 15892 : dw=1.+.3275911*ds
1561 15892 : dw=1.D+0/dw
1562 : dv=dw*(.2258368458D+0+&
1563 : & dw*(-.2521286676D+0+dw*(1.2596951294D+0+&
1564 15892 : & dw*(-1.2878224530D+0+dw*(.9406460699D+0)))))
1565 15892 : dv=dv+ds
1566 15892 : de=dt*dv/dq(iq)
1567 15892 : djp12=djp12+de
1568 15892 : if (dabs(de).lt.(1.D-07*djp12)) exit
1569 15892 : dt=-dt*db
1570 : end do
1571 4070 : if (xcut.ge.dxp) return
1572 3507 : np=(dxp-xcut)/dh
1573 3507 : np=2*(np/2)
1574 3507 : np=nm-np
1575 3507 : nq=(15.-gamma)/dh
1576 3507 : nq=1+2*(nq/2)
1577 3507 : if (np.lt.nq) np=nq
1578 3507 : if (np.le.nm) then
1579 3507 : df3=0.D+0
1580 3507 : dt=dy(np)+gamma
1581 3507 : dv=(dt-xcut)/2.D+0
1582 3507 : df3=0.D0
1583 3507 : if (dt.ge.1.D-13) df3=dsqrt(dt)
1584 3507 : if (dabs(dv).ge.1.D-13) then
1585 3507 : df1=dsqrt(xcut)
1586 3507 : dt=df1+df3
1587 3507 : dw=(dv+dv)/(dt*dt)
1588 3507 : df2=dw*dw
1589 3507 : df2=df2+df2
1590 3507 : db=df2*(df2+7.D+0)+7.D+1
1591 3507 : dc=7.D+0*(1.D+1-df2)
1592 3507 : dc=dc*dw
1593 3507 : dd=-df2*(df2-2.8D+1)+1.4D+2
1594 3507 : dd=dd+dd
1595 : ds=dt*((db-dc)/(1.D+0+dexp(xcut-gamma))+&
1596 3507 : & dd/(1.D+0+dexp(xcut+dv-gamma))+(db+dc)/df(np))
1597 3507 : ds=ds*dv/4.2D+2
1598 3507 : djp12=djp12+ds
1599 : end if
1600 3507 : if (np.ne.nm) then
1601 3507 : ds=0.D+0
1602 3507 : np=np+2
1603 3507 : do k=np,nm,2
1604 7851 : df1=df3
1605 7851 : df3=dsqrt(dy(k)+gamma)
1606 7851 : dt=df1+df3
1607 7851 : dw=d2h/(dt*dt)
1608 7851 : df2=dw*dw
1609 7851 : df2=df2+df2
1610 7851 : db=df2*(df2+7.D+0)+7.D+1
1611 7851 : dc=7.D+0*(1.D+1-df2)
1612 7851 : dc=dc*dw
1613 7851 : dd=-df2*(df2-2.8D+1)+1.4D+2
1614 7851 : dd=dd+dd
1615 7851 : ds=ds+dt*((db-dc)/df(k-2)+dd/df(k-1)+(db+dc)/df(k))
1616 : end do
1617 3507 : ds=ds*dh/4.2D+2
1618 3507 : djp12=djp12+ds
1619 : end if
1620 3507 : if (xcut.ge.dxm) return
1621 : end if
1622 : end if
1623 79 : djp12=dip12(gamma)-xcut*dsqrt(xcut)/1.5D+0
1624 :
1625 79 : end function djp12
1626 : !!***
1627 :
1628 : !----------------------------------------------------------------------
1629 :
1630 : !!****f* m_special_funcs/djp32
1631 : !! NAME
1632 : !! djp32
1633 : !!
1634 : !! FUNCTION
1635 : !! Returns the incomplete Fermi integral of order 3/2.
1636 : !! Based on an analytical approximation.
1637 : !!
1638 : !! INPUTS
1639 : !! xcut=lower bound of the incomplete Fermi integral
1640 : !! gamma=incomplete Fermi integral argument
1641 : !!
1642 : !! OUTPUT
1643 : !! djp32=resulting function
1644 : !!
1645 : !! SOURCE
1646 :
1647 79 : real(dp) function djp32(xcut,gamma)
1648 :
1649 : ! Arguments -------------------------------
1650 : ! Scalars
1651 : real(dp),intent(in) :: xcut,gamma
1652 :
1653 : ! Local variables -------------------------
1654 : ! Scalars
1655 : real(dp) :: d2h,db,dc,dd,de,df1,df2,df3,dh
1656 : real(dp) :: ds,dt,dv,dw,dx1,dx2
1657 : real(dp) :: dx3,dxm,dxp
1658 : integer :: i,ind,iq,k,nm,np,nq
1659 : ! Arrays
1660 : real(dp) :: dq(5),df(101),dy(101)
1661 : ! *********************************************************************
1662 :
1663 79 : dh=0.2D+0
1664 79 : d2h=0.4D+0
1665 79 : nm=101
1666 79 : ind=0
1667 79 : dq=(/1.D+0,5.656854228D+0,1.558845727D+1,3.2D+1,5.590169945D+0/)
1668 :
1669 79 : djp32=0.D+0
1670 79 : dxm=gamma-1.5D+1
1671 79 : if (xcut.GT.dxm) then
1672 : if (ind.EQ.0) then
1673 8058 : do i=1,nm
1674 7979 : dy(i)=-1.5D+1+(i-1)*dh
1675 8058 : df(i)=1.D+0+DEXP(dy(i))
1676 : end do
1677 79 : ind=1
1678 : end if
1679 79 : dxp=gamma+5.D+0
1680 : if (xcut.LT.dxp) then
1681 : dc=dxp
1682 : else
1683 : dc=xcut
1684 : end if
1685 79 : db=DEXP(gamma-dc)
1686 79 : dt=db
1687 309 : do iq=1,5
1688 309 : dd=iq*dc
1689 309 : ds=DSQRT(dd)
1690 309 : dw=1.+.3275911*ds
1691 309 : dw=1.D+0/dw
1692 : dv=dw*(.2258368458D+0+&
1693 : & dw*(-.2521286676D+0+dw*(1.2596951294D+0+&
1694 309 : & dw*(-1.2878224530D+0+dw*(.9406460699D+0)))))
1695 309 : dv=dv+ds
1696 309 : dv=1.5D+0*dv+ds*dd
1697 309 : de=dt*dv/dq(iq)
1698 309 : djp32=djp32+de
1699 309 : if (DABS(de).LT.(1.D-07*djp32)) exit
1700 309 : dt=-dt*db
1701 : end do
1702 79 : if (xcut.GE.dxp) return
1703 72 : np=(dxp-xcut)/dh
1704 72 : np=2*(np/2)
1705 72 : np=nm-np
1706 72 : nq=(15.-gamma)/dh
1707 72 : nq=1+2*(nq/2)
1708 72 : if (np.LT.nq) np=nq
1709 72 : if (np.LE.nm) then
1710 72 : df3=0.D+0
1711 72 : dt=dy(np)+gamma
1712 72 : dv=(dt-xcut)/2.D+0
1713 72 : df3=DSQRT(dt)
1714 72 : dx3=dt
1715 72 : if (DABS(dv).GE.1.D-13) then
1716 72 : df1=DSQRT(xcut)
1717 72 : dt=df1+df3
1718 72 : dw=(dv+dv)/(dt*dt)
1719 72 : df2=dw*dw
1720 72 : df2=df2+df2
1721 72 : db=df2*(df2+7.D+0)+7.D+1
1722 72 : dc=7.D+0*(1.D+1-df2)
1723 72 : dc=dc*dw
1724 72 : dd=-df2*(df2-2.8D+1)+1.4D+2
1725 72 : dd=dd+dd
1726 : ds=dt*((db-dc)*xcut/(1.D+0+DEXP(xcut-gamma))+dd*(xcut+dv)&
1727 72 : & /(1.D+0+DEXP(xcut+dv-gamma))+(db+dc)*(dy(np)+gamma)/df(np))
1728 72 : ds=ds*dv/4.2D+2
1729 72 : djp32=djp32+ds
1730 : end if
1731 72 : if (np.NE.nm) then
1732 72 : ds=0.D+0
1733 72 : np=np+2
1734 72 : do k=np,nm,2
1735 144 : dx1=dx3
1736 144 : df1=df3
1737 144 : dx2=dy(k-1)+gamma
1738 144 : dx3=dy(k)+gamma
1739 144 : df3=DSQRT(dx3)
1740 144 : dt=df1+df3
1741 144 : dw=d2h/(dt*dt)
1742 144 : df2=dw*dw
1743 144 : df2=df2+df2
1744 144 : db=df2*(df2+7.D+0)+7.D+1
1745 144 : dc=7.D+0*(1.D+1-df2)
1746 144 : dc=dc*dw
1747 144 : dd=-df2*(df2-2.8D+1)+1.4D+2
1748 144 : dd=dd+dd
1749 : ds=ds+dt*((db-dc)*dx1/df(k-2)+dd*dx2/df(k-1)&
1750 144 : & +(db+dc)*dx3/df(k))
1751 : end do
1752 72 : ds=ds*dh/4.2D+2
1753 72 : djp32=djp32+ds
1754 : end if
1755 72 : if (xcut.GE.dxm) return
1756 : end if
1757 : end if
1758 0 : djp32=dip32(gamma)-xcut*xcut*DSQRT(xcut)/2.5D+0
1759 :
1760 0 : end function djp32
1761 : !!***
1762 :
1763 : !!****f* m_special_funcs/tildeAx
1764 : !! NAME
1765 : !! tildeAx
1766 : !!
1767 : !! FUNCTION
1768 : !! Returns tilde Ax Pade fit and first and second derivatives
1769 : !! w.r.t. reduced temperature t.
1770 : !!
1771 : !! NOTES
1772 : !! Karasiev-Sjostrom-Dufty-Trickey (KSDT) TLDA xc-functional
1773 : !! V.V. Karasiev, T. Sjostrom, J. Dufty, and S.B. Trickey, PRL 112, 076403 (2014) [[cite:Karasiev2014]]
1774 : !!
1775 : !! INPUTS
1776 : !! t=reduced temperature, t=T/T_F
1777 : !!
1778 : !! OUTPUT
1779 : !! Ax=tilde Ax(t)
1780 : !! dAx=dAx(t)/dt
1781 : !! d2Ax=d^2Ax(t)/dt^2
1782 : !!
1783 : !! SOURCE
1784 :
1785 129516 : subroutine tildeAx(t,Ax,dAx,d2Ax)
1786 :
1787 : !Arguments ------------------------------------
1788 : !scalars
1789 : real(dp),intent(in) :: t
1790 : real(dp),intent(out) :: Ax,dAx,d2Ax
1791 : !Local variables ------------------------------
1792 : !scalars
1793 : real(dp),parameter :: aln= -0.0475410604245741_dp
1794 : real(dp),parameter :: a52= -0.1065378473507800_dp
1795 : real(dp),parameter :: a1 = 0.5823869764908659_dp
1796 : real(dp),parameter :: a2 = -0.0068339509356661_dp
1797 : real(dp),parameter :: a3 = 11.5469239288490009_dp
1798 : real(dp),parameter :: a4 = -0.8465428870889800_dp
1799 : real(dp),parameter :: a5 = -0.1212525366470300_dp
1800 : real(dp),parameter :: a6 = 1.9902818786101000_dp
1801 : real(dp),parameter :: a7 = 0.0000000000000000_dp
1802 : real(dp),parameter :: a8 = 0.0744389046707120_dp
1803 : real(dp),parameter :: b1 = 19.9256144707979992_dp
1804 : real(dp),parameter :: b2 = 5.1663994545590004_dp
1805 : real(dp),parameter :: b3 = 2.0463164858237000_dp
1806 : real(dp),parameter :: b4 = 0.0744389046707120_dp
1807 : real(dp),parameter :: onethird = 1._dp/3._dp
1808 : real(dp),parameter :: twothird = 2._dp/3._dp
1809 : real(dp),parameter :: fourthird = 4._dp/3._dp
1810 : real(dp),parameter :: threehalf = 3._dp/2._dp
1811 : real(dp),parameter :: fivehalf = 5._dp/2._dp
1812 : real(dp),parameter :: sevenhalf = 7._dp/2._dp
1813 : real(dp) :: y,u,du,d2u
1814 : real(dp) :: v,dv,d2v
1815 : real(dp) :: dydt,d2ydt2
1816 : real(dp) :: num,den,fit,dnum,d2num,dden,d2den,dfit,d2fit
1817 : ! *************************************************************************
1818 :
1819 129516 : y = twothird/t**threehalf
1820 129516 : u = y**twothird
1821 129516 : du = twothird/y**onethird
1822 129516 : d2u = -onethird*du/y
1823 :
1824 129516 : v = y**fourthird
1825 129516 : dv = fourthird *y**onethird
1826 129516 : d2v = onethird*dv/y
1827 :
1828 129516 : dydt = -1._dp/t**fivehalf
1829 129516 : d2ydt2 = fivehalf/t**sevenhalf
1830 :
1831 : num = a52*u**fivehalf &
1832 : +a1*u+a2*u**2+a3*u**3+a4*u**4 &
1833 : +a5*u**5+a6*u**6+a7*u**7+a8*u**8 &
1834 129516 : +aln*log(y)*y**4
1835 129516 : den = 1._dp+b1*v+b2*v**2+b3*v**3+b4*v**4
1836 129516 : fit = num/den
1837 : dnum = du*(fivehalf*a52*u**threehalf &
1838 : +a1+2._dp*a2*u+3._dp*a3*u**2+4._dp*a4*u**3 &
1839 : +5._dp*a5*u**4+6._dp*a6*u**5+7._dp*a7*u**6+8._dp*a8*u**7) &
1840 129516 : +aln*y**3+4._dp*aln*log(y)*y**3
1841 : d2num = d2u*(fivehalf*a52*u**threehalf &
1842 : +a1+2._dp*a2*u+3._dp*a3*u**2+4._dp*a4*u**3 &
1843 : +5._dp*a5*u**4+6._dp*a6*u**5+7._dp*a7*u**6+8._dp*a8*u**7) &
1844 : +du*du*(fivehalf*threehalf*a52*u**half &
1845 : +2._dp*a2+2._dp*3._dp*a3*u+3._dp*4._dp*a4*u**2 &
1846 : +4._dp*5._dp*a5*u**3+5._dp*6._dp*a6*u**4 &
1847 : +6._dp*7._dp*a7*u**5+7._dp*8._dp*a8*u**6) &
1848 129516 : +7._dp*aln*y**2+12._dp*aln*log(y)*y**2
1849 129516 : dden = dv*(b1+2._dp*b2*v+3._dp*b3*v**2+4._dp*b4*v**3)
1850 : d2den = d2v*(b1+2._dp*b2*v+3._dp*b3*v**2+4._dp*b4*v**3) &
1851 129516 : +dv*dv*(2._dp*b2+2._dp*3._dp*b3*v+3._dp*4._dp*b4*v**2)
1852 : ! derivatives w.r.t. y
1853 129516 : dfit = dnum/den - (num/den)*(dden/den)
1854 : d2fit = d2num/den - (dnum/den)*(dden/den) &
1855 : - (dnum/den)*(dden/den) + 2._dp*(num/den)*(dden/den)*(dden/den) &
1856 129516 : - (num/den)*(d2den/den)
1857 : ! Ax, and derivatives w.r.t. t
1858 129516 : Ax = fit
1859 129516 : dAx = dfit * dydt
1860 129516 : d2Ax = d2fit*dydt**2 + dfit*d2ydt2
1861 129516 : if(Ax/=Ax) Ax=zero
1862 129516 : if(dAx/=dAx) dAx=zero
1863 129516 : if(d2Ax/=d2Ax) d2Ax=zero
1864 :
1865 129516 : end subroutine tildeAx
1866 : !!***
1867 :
1868 : !!****f* m_special_funcs/tildeBx
1869 : !! NAME
1870 : !! tildeBx
1871 : !!
1872 : !! FUNCTION
1873 : !! Returns tilde Bx Pade fit and first and second derivatives
1874 : !! w.r.t. reduced temperature t.
1875 : !!
1876 : !! NOTES
1877 : !! Karasiev-Dufty-Trickey (KDT16) TGGA xc-functional
1878 : !! V.V. Karasiev, J.W. Dufty, and S.B. Trickey, PRL 120(7), 076401 (2018) [[cite:Karasiev2018]]
1879 : !!
1880 : !! INPUTS
1881 : !! t=reduced temperature, t=T/T_F
1882 : !!
1883 : !! OUTPUT
1884 : !! Bx=tilde Bx(t)
1885 : !! dBx=dBx(t)/dt
1886 : !! d2Bx=d^2Bx(t)/dt^2
1887 : !!
1888 : !! SOURCE
1889 :
1890 64758 : subroutine tildeBx(t,Bx,dBx,d2Bx)
1891 :
1892 : !Arguments ------------------------------------
1893 : !scalars
1894 : real(dp),intent(in) :: t
1895 : real(dp),intent(out) :: Bx,dBx,d2Bx
1896 :
1897 : !Local variables ------------------------------
1898 : !scalars
1899 : real(dp),parameter :: a2 = -3.4341427276599950_dp
1900 : real(dp),parameter :: a3 = -0.9066069544311700_dp
1901 : real(dp),parameter :: a4 = 2.2386316137237001_dp
1902 : real(dp),parameter :: a5 = 2.4232553178542000_dp
1903 : real(dp),parameter :: a6 = -0.1339278564306200_dp
1904 : real(dp),parameter :: a7 = 0.4392739633708200_dp
1905 : real(dp),parameter :: a8 = -0.0497109675177910_dp
1906 : real(dp),parameter :: a9 = 0.0000000000000000_dp
1907 : real(dp),parameter :: a10= 0.0028609701106953_dp
1908 : real(dp),parameter :: b1 = 0.7098198258073800_dp
1909 : real(dp),parameter :: b2 = 4.6311326377185997_dp
1910 : real(dp),parameter :: b3 = -2.9243190977647000_dp
1911 : real(dp),parameter :: b4 = 6.1688157841895004_dp
1912 : real(dp),parameter :: b5 = -1.3435764191535999_dp
1913 : real(dp),parameter :: b6 = 0.1576046383295400_dp
1914 : real(dp),parameter :: b7 = 0.4365792821186800_dp
1915 : real(dp),parameter :: b8 = -0.0620444574606262_dp
1916 : real(dp),parameter :: b9 = 0.0000000000000000_dp
1917 : real(dp),parameter :: b10= 0.0028609701106953_dp
1918 : real(dp),parameter :: onethird = 1._dp/3._dp
1919 : real(dp),parameter :: twothird = 2._dp/3._dp
1920 : real(dp),parameter :: threehalf = 3._dp/2._dp
1921 : real(dp),parameter :: fivehalf = 5._dp/2._dp
1922 : real(dp),parameter :: sevenhalf = 7._dp/2._dp
1923 : real(dp) :: y,u,du,d2u
1924 : real(dp) :: v,dv,d2v
1925 : real(dp) :: dydt,d2ydt2
1926 : real(dp) :: num,den,fit,dnum,d2num,dden,d2den,dfit,d2fit
1927 : ! *************************************************************************
1928 :
1929 64758 : y = twothird/t**threehalf
1930 64758 : u = y**twothird
1931 64758 : du = twothird/y**onethird
1932 64758 : d2u = -onethird*du/y
1933 :
1934 64758 : v = u
1935 64758 : dv = du
1936 64758 : d2v = d2u
1937 :
1938 64758 : dydt = -1._dp/t**fivehalf
1939 64758 : d2ydt2 = fivehalf/t**sevenhalf
1940 :
1941 : num = a2*u**2+a3*u**3+a4*u**4 &
1942 : +a5*u**5+a6*u**6+a7*u**7+a8*u**8 &
1943 64758 : +a9*u**9+a10*u**10
1944 : den = 1._dp+b1*v+b2*v**2+b3*v**3+b4*v**4 &
1945 64758 : +b5*v**5+b6*v**6+b7*v**7+b8*v**8+b9*v**9+b10*v**10
1946 64758 : fit = num/den
1947 :
1948 : dnum = du*(2._dp*a2*u+3._dp*a3*u**2+4._dp*a4*u**3 &
1949 : +5._dp*a5*u**4+6._dp*a6*u**5+7._dp*a7*u**6+8._dp*a8*u**7 &
1950 64758 : +9._dp*a9*u**8+10._dp*a10*u**9)
1951 :
1952 : d2num = d2u*(2._dp*a2*u+3._dp*a3*u**2+4._dp*a4*u**3 &
1953 : +5._dp*a5*u**4+6._dp*a6*u**5+7._dp*a7*u**6+8._dp*a8*u**7 &
1954 : +9._dp*a9*u**8+10._dp*a10*u**9) &
1955 : +du*du*(2._dp*a2+2._dp*3._dp*a3*u+3._dp*4._dp*a4*u**2 &
1956 : +4._dp*5._dp*a5*u**3+5._dp*6._dp*a6*u**4 &
1957 : +6._dp*7._dp*a7*u**5+7._dp*8._dp*a8*u**6 &
1958 64758 : +8._dp*9._dp*a9*u**7+9._dp*10._dp*a10*u**8)
1959 :
1960 : dden = dv*(b1+2._dp*b2*v+3._dp*b3*v**2+4._dp*b4*v**3 &
1961 : +5._dp*b5*v**4+6._dp*b6*v**5+7._dp*b7*v**6+8._dp*b8*v**7 &
1962 64758 : +9._dp*b9*v**8+10._dp*b10*v**9)
1963 :
1964 : d2den = d2v*(b1+2._dp*b2*v+3._dp*b3*v**2+4._dp*b4*v**3 &
1965 : +5._dp*b5*v**4+6._dp*b6*v**5+7._dp*b7*v**6+8._dp*b8*v**7 &
1966 : +9._dp*b9*v**8+10._dp*b10*v**9) &
1967 : + dv*dv*(2._dp*b2+2._dp*3._dp*b3*v+3._dp*4._dp*b4*v**2 &
1968 : +4._dp*5._dp*b5*v**3+5._dp*6._dp*b6*v**4+6._dp*7._dp*b7*v**5+7._dp*8._dp*b8*v**6 &
1969 64758 : +8._dp*9._dp*b9*v**7+9._dp*10._dp*b10*v**8)
1970 :
1971 : ! derivatives w.r.t. y
1972 64758 : dfit = dnum/den - (num/den)*(dden/den)
1973 : d2fit = d2num/den - (dnum/den)*(dden/den) &
1974 : - (dnum/den)*(dden/den) + 2._dp*(num/den)*(dden/den)*(dden/den) &
1975 64758 : - (num/den)*(d2den/den)
1976 :
1977 : ! Bx, and derivatives w.r.t. t
1978 64758 : Bx = fit
1979 64758 : dBx = dfit * dydt
1980 64758 : d2Bx = d2fit*dydt**2 + dfit*d2ydt2
1981 64758 : if(Bx/=Bx) Bx=zero
1982 64758 : if(dBx/=dBx) dBx=zero
1983 64758 : if(d2Bx/=d2Bx) d2Bx=zero
1984 :
1985 64758 : end subroutine tildeBx
1986 : !!***
1987 :
1988 : !!****f* m_special_funcs/tildeBc
1989 : !! NAME
1990 : !! tildeBc
1991 : !!
1992 : !! FUNCTION
1993 : !! Returns tilde Bc Pade fit and first and second derivatives
1994 : !! w.r.t. reduced temperature t.
1995 : !!
1996 : !! NOTES
1997 : !! Karasiev-Dufty-Trickey (KDT16) TGGA xc-functional
1998 : !! V.V. Karasiev, J.W. Dufty, and S.B. Trickey, PRL 120(7), 076401 (2018) [[cite:Karasiev2018]]
1999 : !!
2000 : !! INPUTS
2001 : !! iflag=flag selector integer
2002 : !! rs=Wigner-Seitz radius (bohr)
2003 : !! t=reduced temperature, t=T/T_F
2004 : !!
2005 : !! OUTPUT
2006 : !! Bc=tilde Bc(t)
2007 : !! dBcdrs=dBxc(rs,t)/drs
2008 : !! dBcdt=dBc(rs,t)/dt
2009 : !!
2010 : !! SOURCE
2011 :
2012 64758 : subroutine tildeBc(iflag,rs,t,Bc,dBcdrs,dBcdt)
2013 :
2014 : !Arguments ------------------------------------
2015 : !scalars
2016 : integer,intent(in) :: iflag
2017 : real(dp),intent(in) :: rs,t
2018 : real(dp),intent(out) :: Bc,dBcdrs,dBcdt
2019 :
2020 : !Local variables ------------------------------
2021 : !scalars
2022 : real(dp),parameter :: alpha_n = 0.50000000000000D+00
2023 : real(dp),parameter :: alpha_d = 0.15000000000000D+01
2024 : real(dp),parameter :: alpha_t = 0.32500000000000D+01
2025 : real(dp),parameter :: a1 = 0.30047772904141D+03
2026 : real(dp),parameter :: b1 = -0.11166043894641D+03
2027 : real(dp),parameter :: a2 = -0.38706401119284D+03
2028 : real(dp),parameter :: b2 = -0.45327974938936D+02
2029 : real(dp),parameter :: a3 = 0.25112236519758D+04
2030 : real(dp),parameter :: b3 = -0.14507109325068D+04
2031 : real(dp),parameter :: a4 = 0.52243427453456D+03
2032 : real(dp),parameter :: b4 = -0.30665095324907D+02
2033 : real(dp),parameter :: c1 = 0.11077393333429D+03
2034 : real(dp),parameter :: d1 = 0.12854960224127D+01
2035 : real(dp),parameter :: c2 = 0.32355494275181D+03
2036 : real(dp),parameter :: d2 = 0.13482659120012D+02
2037 : real(dp),parameter :: c3 = 0.45509212104516D+03
2038 : real(dp),parameter :: d3 = 0.23416017878226D+02
2039 : real(dp),parameter :: c4 = 0.10884351801356D+04
2040 : real(dp),parameter :: d4 = 0.24480831491950D+02
2041 : real(dp),parameter :: c5 = 0.36112604933128D+00
2042 : real(dp),parameter :: d5 = 0.32161372287131D-08
2043 : real(dp),parameter :: e1 = 0.32175261286726D+02
2044 : real(dp),parameter :: e2 = 0.61853047558212D+02
2045 : real(dp),parameter :: e3 = 0.33585054134674D+03
2046 : real(dp),parameter :: e4 = 0.12874240529185D+03
2047 : real(dp),parameter :: f1 = 0.41006056761680D-02
2048 : real(dp),parameter :: f2 = 0.18933118065366D-01
2049 : real(dp),parameter :: f3 = 0.24295412676204D-04
2050 : real(dp),parameter :: f4 = 0.18369775992299D-07
2051 : real(dp),parameter :: f5 = 0.69274680951701D-10
2052 : real(dp),parameter :: onethird = 1.d0/3.d0
2053 : real(dp),parameter :: twothird = 2.d0/3.d0
2054 : real(dp),parameter :: threehalf = 3.d0/2.d0
2055 : real(dp),parameter :: fivehalf = 5.d0/2.d0
2056 : real(dp),parameter :: sevenhalf = 7.d0/2.d0
2057 : real(dp) :: rsn,rsd,u,du
2058 : real(dp) :: num,den,dnumdrs,dnumdt,ddendrs,ddendt
2059 : ! *************************************************************************
2060 :
2061 64758 : if(iflag==5.or.iflag==6.or.iflag==7.or.iflag==8) then
2062 : ! Bc(rs,t) = 1
2063 0 : Bc = 1._dp
2064 0 : dBcdrs = 0._dp
2065 0 : dBcdt = 0._dp
2066 64758 : elseif(iflag==1.or.iflag==2.or.iflag==3.or.iflag==4) then
2067 : !
2068 : ! Bc(rs,t) = Pade Fit
2069 : !
2070 64758 : rsn = rs**alpha_n
2071 64758 : rsd = rs**alpha_d
2072 64758 : u = t**alpha_t
2073 64758 : du = alpha_t*t**(alpha_t-1.d0)
2074 : !
2075 64758 : num = 1.d0+(a1+b1*rsn+e1*rsn**2)*u+(a2+b2*rsn+e2*rsn**2)*u**2+(a3+b3*rsn+e3*rsn**2)*u**3+(a4+b4*rsn+e4*rsn**2)*u**4
2076 64758 : dnumdrs = (b1+2.d0*e1*rsn)*u+(b2+2.d0*e2*rsn)*u**2+(b3+2.d0*e3*rsn)*u**3+(b4+2.d0*e4*rsn)*u**4
2077 64758 : dnumdrs = dnumdrs * alpha_n*rs**(alpha_n-1.d0)
2078 64758 : dnumdt = (a1+b1*rsn+e1*rsn**2)+2.d0*(a2+b2*rsn+e2*rsn**2)*u+3.d0*(a3+b3*rsn+e3*rsn**2)*u**2+4.d0*(a4+b4*rsn+e4*rsn**2)*u**3
2079 64758 : dnumdt = dnumdt * du
2080 : !
2081 64758 : den = 1.d0+(c1+d1*rsd+f1*rsd**2)*u+(c2+d2*rsd+f2*rsd**2)*u**2+(c3+d3*rsd+f3*rsd**2)*u**3+(c4+d4*rsd+f4*rsd**2)*u**4+(c5+d5*rsd+f5*rsd**2)*u**5
2082 64758 : ddendrs = (d1+2.d0*f1*rsd)*u+(d2+2.d0*f2*rsd)*u**2+(d3+2.d0*f3*rsd)*u**3+(d4+2.d0*f4*rsd)*u**4+(d5+2.d0*f5*rsd)*u**5
2083 64758 : ddendrs = ddendrs * alpha_d*rs**(alpha_d-1.d0)
2084 64758 : ddendt = (c1+d1*rsd+f1*rsd**2)+2.d0*(c2+d2*rsd+f2*rsd**2)*u+3.d0*(c3+d3*rsd+f3*rsd**2)*u**2+4.d0*(c4+d4*rsd+f4*rsd**2)*u**3+5.d0*(c5+d5*rsd+f5*rsd**2)*u**4
2085 64758 : ddendt = ddendt * du
2086 : !
2087 64758 : Bc = num/den
2088 64758 : dBcdrs = dnumdrs/den - (num/den)*ddendrs/den
2089 64758 : dBcdt = dnumdt/den - (num/den)*ddendt/den
2090 64758 : if(Bc/=Bc) Bc=zero
2091 64758 : if(dBcdrs/=dBcdrs) dBcdrs=zero
2092 64758 : if(dBcdt/=dBcdt) dBcdt=zero
2093 : !
2094 : endif
2095 :
2096 64758 : end subroutine tildeBc
2097 : !!***
2098 :
2099 : !----------------------------------------------------------------------
2100 :
2101 : !!****f* m_special_funcs/k_fermi
2102 : !! NAME
2103 : !! k_fermi
2104 : !!
2105 : !! FUNCTION
2106 : !! Returns the Fermi wave vector corresponding to the local value of the real space density rhor.
2107 : !!
2108 : !! INPUTS
2109 : !! rhor=Local density in real space.
2110 : !!
2111 : !! SOURCE
2112 :
2113 280434564 : elemental function k_fermi(rhor)
2114 :
2115 : !Arguments ------------------------------------
2116 : !scalars
2117 : real(dp),intent(in) :: rhor
2118 : real(dp) :: k_fermi
2119 :
2120 : !Local variables-------------------------------
2121 : !scalars
2122 : real(dp),parameter :: pisq=pi**2
2123 : ! *************************************************************************
2124 :
2125 280434564 : k_fermi = (three*pisq*rhor)**third
2126 :
2127 140216832 : end function k_fermi
2128 : !!***
2129 :
2130 : !----------------------------------------------------------------------
2131 :
2132 : !!****f* m_special_funcs/k_thfermi
2133 : !! NAME
2134 : !! k_thfermi
2135 : !!
2136 : !! FUNCTION
2137 : !! Returns the Thomas-Fermi wave vector corresponding to the local value of the real space density rhor.
2138 : !!
2139 : !! INPUTS
2140 : !! rhor=Local density in real space.
2141 : !!
2142 : !! SOURCE
2143 :
2144 140217732 : elemental function k_thfermi(rhor)
2145 :
2146 : !Arguments ------------------------------------
2147 : !scalars
2148 : real(dp),intent(in) :: rhor
2149 : real(dp) :: k_thfermi
2150 :
2151 : !Local variables-------------------------------
2152 : !scalars
2153 : real(dp),parameter :: pisq=pi**2
2154 : ! *************************************************************************
2155 :
2156 140217732 : k_thfermi = SQRT(four*k_fermi(rhor)*piinv)
2157 :
2158 140217732 : end function k_thfermi
2159 : !!***
2160 :
2161 : !----------------------------------------------------------------------
2162 :
2163 : !!****f* m_special_funcs/levi_civita_3
2164 : !! NAME
2165 : !! levi_civita_3
2166 : !!
2167 : !! FUNCTION
2168 : !! Return Levi-Civita tensor of rank 3
2169 : !!
2170 : !! SOURCE
2171 :
2172 0 : pure function levi_civita_3() result(ee)
2173 :
2174 : !Arguments ------------------------------------
2175 : integer :: ee(3,3,3)
2176 : ! *************************************************************************
2177 :
2178 0 : ee = 0
2179 0 : ee(1,2,3) = 1
2180 0 : ee(2,3,1) = 1
2181 0 : ee(3,1,2) = 1
2182 : !
2183 0 : ee(3,2,1) = -1
2184 0 : ee(1,3,2) = -1
2185 0 : ee(2,1,3) = -1
2186 :
2187 0 : end function levi_civita_3
2188 : !!***
2189 :
2190 : !!****f* m_special_funcs/jlspline_init
2191 : !! NAME
2192 : !! jlspline_init
2193 : !!
2194 : !! FUNCTION
2195 : !! Pre-calculate the j_v(y) for recip_ylm on regular grid
2196 : !! NOTE: spherical Bessel function small j!
2197 : !!
2198 : !! INPUTS
2199 : !! nx = max number of points on grid for integral
2200 : !! delta = space between integral arguments
2201 : !! mlang= max angular momentum
2202 : !!
2203 : !! OUTPUT
2204 : !! bess_spl=array of integrals
2205 : !! bess_spl_der=array of derivatives of integrals
2206 : !! xx=coordinates of points belonging to the grid
2207 : !!
2208 : !! SOURCE
2209 :
2210 81 : subroutine jlspline_init(new, nx, delta, mlang)
2211 :
2212 : !Arguments ------------------------------------
2213 : !scalars
2214 : class(jlspline_t),intent(inout) :: new
2215 : integer,intent(in) :: nx,mlang
2216 : real(dp),intent(in) :: delta
2217 :
2218 : !Local variables -------------------------
2219 : !scalars
2220 : integer :: ix,ll
2221 : real(dp) :: yp1,ypn
2222 : !arrays
2223 81 : real(dp),allocatable :: cosbessx(:),sinbessx(:)
2224 : ! *********************************************************************
2225 :
2226 81 : if (nx < 2) then
2227 0 : ABI_ERROR('need more than one point for the interpolation routines')
2228 : end if
2229 :
2230 81 : new%nx = nx; new%mlang = mlang; new%delta = delta; new%maxarg = (nx-1) * delta
2231 243 : ABI_MALLOC(new%xx, (nx))
2232 324 : ABI_MALLOC(new%bess_spl, (nx, mlang))
2233 243 : ABI_MALLOC(new%bess_spl_der, (nx, mlang))
2234 :
2235 : !-----------------------------------------------------------------
2236 : !Bessel function into array
2237 : !-----------------------------------------------------------------
2238 : ! integration grid is nfiner times finer than the interpolation grid
2239 162 : ABI_MALLOC(sinbessx, (nx))
2240 162 : ABI_MALLOC(cosbessx, (nx))
2241 :
2242 : ! could be done by chain rule for cos sin (is it worth it?) but
2243 : ! precision problems as numerical errors are propagated.
2244 41381 : do ix=1,nx
2245 41300 : new%xx(ix) = (ix-1) * delta
2246 41300 : sinbessx(ix) = sin(new%xx(ix))
2247 41381 : cosbessx(ix) = cos(new%xx(ix))
2248 : end do
2249 :
2250 : ! fill bess_spl array
2251 486 : do ll=0,mlang-1
2252 405 : call besjm(one,new%bess_spl(:,ll+1),cosbessx,ll,nx,sinbessx,new%xx)
2253 :
2254 : ! call spline to get 2nd derivative (reuse in splint later)
2255 405 : yp1 = zero; ypn = zero
2256 486 : call spline(new%xx, new%bess_spl(:,ll+1), nx, yp1, ypn, new%bess_spl_der(:,ll+1))
2257 : end do
2258 :
2259 : !write(std_out,*) ' bess funct 0 1 2 3 4'
2260 : !do ix=1,nx
2261 : !write(std_out,*) xx(ix), (new%bess_spl(ix,ll),ll=1,mlang)
2262 : !end do
2263 :
2264 81 : ABI_FREE(sinbessx)
2265 81 : ABI_FREE(cosbessx)
2266 :
2267 81 : end subroutine jlspline_init
2268 : !!***
2269 :
2270 : !----------------------------------------------------------------------
2271 :
2272 : !!****f* m_special_funcs/jlspline_free
2273 : !! NAME
2274 : !! jlspline_free
2275 : !!
2276 : !! FUNCTION
2277 : !! deallocate memory
2278 : !!
2279 : !! SOURCE
2280 :
2281 81 : subroutine jlspline_free(jlspl)
2282 :
2283 : !Arguments ------------------------------------
2284 : class(jlspline_t),intent(inout) :: jlspl
2285 : ! *********************************************************************
2286 :
2287 81 : ABI_SFREE(jlspl%xx)
2288 81 : ABI_SFREE(jlspl%bess_spl)
2289 81 : ABI_SFREE(jlspl%bess_spl_der)
2290 :
2291 81 : end subroutine jlspline_free
2292 : !!***
2293 :
2294 : !----------------------------------------------------------------------
2295 :
2296 : !!****f* m_special_funcs/jlspline_integral
2297 : !! NAME
2298 : !! jlspline_integral
2299 : !!
2300 : !! INPUTS
2301 : !!
2302 : !! OUTPUT
2303 : !!
2304 : !! FUNCTION
2305 : !!
2306 : !! SOURCE
2307 :
2308 0 : real(dp) function jlspline_integral(jlspl, il, qq, powr, nr, rcut) result(res)
2309 :
2310 : !Arguments ------------------------------------
2311 : class(jlspline_t),intent(in) :: jlspl
2312 : integer,intent(in) :: il,nr,powr
2313 : real(dp),intent(in) :: qq, rcut
2314 :
2315 : !Local variables ---------------------------------------
2316 : integer :: ierr
2317 : real(dp) :: step
2318 : !arrays
2319 0 : real(dp):: xfit(nr),yfit(nr),rr(nr)
2320 : ! *********************************************************************
2321 :
2322 0 : step = rcut / (nr - 1)
2323 0 : rr = arth(zero, step, nr)
2324 0 : xfit = qq * rr
2325 0 : call splint(jlspl%nx, jlspl%xx, jlspl%bess_spl(:,il), jlspl%bess_spl_der(:,il), nr, xfit, yfit, ierr=ierr)
2326 :
2327 0 : if (ierr /= 0) then
2328 0 : write(std_out,*)"qq, rcut, qq*rcut, maxarg", qq, rcut, qq*rcut, jlspl%maxarg
2329 0 : write(std_out,*)"x[0], x[-1]",jlspl%xx(1),jlspl%xx(jlspl%nx)
2330 0 : write(std_out,*)"minval xfit: ",minval(xfit)
2331 0 : write(std_out,*)"maxval xfit: ",maxval(xfit)
2332 0 : ABI_ERROR("splint returned ierr != 0")
2333 : end if
2334 :
2335 0 : if (powr /= 1) yfit = yfit * (rr ** powr)
2336 0 : res = simpson(step, yfit)
2337 :
2338 0 : end function jlspline_integral
2339 : !!***
2340 :
2341 : !!****f* m_special_funcs/gspline_init
2342 : !! NAME
2343 : !! gspline_init
2344 : !!
2345 : !! FUNCTION
2346 : !! Build object to spline the gaussian approximant and its primitive.
2347 : !!
2348 : !! INPUTS
2349 : !! sigma=Broadening parameter.
2350 : !!
2351 : !! SOURCE
2352 :
2353 0 : subroutine gspline_init(new, sigma)
2354 :
2355 : !Arguments ------------------------------------
2356 : !scalars
2357 : class(gspline_t),intent(out) :: new
2358 : real(dp),intent(in) :: sigma
2359 :
2360 : !Local variables ------------------------------
2361 : integer :: ii
2362 : real(dp) :: ybcbeg, ybcend
2363 : ! *************************************************************************
2364 :
2365 0 : new%nspline = 5 * 1024; new%sigma = sigma
2366 0 : ABI_CHECK(sigma > zero, sjoin("invalid sigma:", ftoa(sigma)))
2367 0 : new%xmin = zero
2368 0 : new%xmax = sigma * sqrt(-log(sigma * sqrt(pi) * tol12)) ! gauss(xmax) = tol12
2369 0 : new%step = (new%xmax - new%xmin) / (new%nspline - 1)
2370 0 : new%stepm1 = one / new%step; new%step2div6 = new%step**2 / six
2371 :
2372 0 : ABI_MALLOC(new%xvals, (new%nspline))
2373 0 : do ii=1,new%nspline
2374 0 : new%xvals(ii) = new%xmin + (ii-1) * new%step
2375 : end do
2376 0 : new%xmax = new%xvals(new%nspline)
2377 :
2378 : ! Spline the gaussian approximant.
2379 0 : ABI_MALLOC(new%svals, (new%nspline, 4))
2380 0 : new%svals(:, 1) = gaussian(new%xvals, sigma)
2381 0 : ybcbeg = - (two * new%xmin / sigma**2) * new%svals(1,1)
2382 0 : ybcend = - (two * new%xmax / sigma**2) * new%svals(new%nspline,1)
2383 0 : call spline(new%xvals, new%svals(:,1), new%nspline, ybcbeg, ybcend, new%svals(:,2))
2384 :
2385 : ! Spline the primitive: 1/2 [1 + erf(x/sigma)]
2386 0 : new%svals(:, 3) = half * (one + abi_derf(new%xvals / new%sigma))
2387 0 : call spline(new%xvals, new%svals(:,3), new%nspline, new%svals(1,1), new%svals(new%nspline, 1), new%svals(:,4))
2388 : !do ii=1,new%nspline; write(98,*)new%xvals(ii),new%svals(ii,3),new%svals(ii,4); end do
2389 :
2390 0 : end subroutine gspline_init
2391 : !!***
2392 :
2393 : !!****f* m_special_funcs/gspline_eval
2394 : !! NAME
2395 : !! gspline_eval
2396 : !!
2397 : !! FUNCTION
2398 : !! Evaluate the gaussian approximant and its primitive at (xmesh - x0)
2399 : !!
2400 : !! INPUTS
2401 : !! self<gspline_t>=Object used to spline the gaussian approximant
2402 : !! x0=Shift to be given to xmesh
2403 : !! nx=Number of points in input mesh.
2404 : !! xmesh(nx)=Frequency points (not necessary linear).
2405 : !!
2406 : !! OUTPUT
2407 : !! weights(nx,2)=First slice contains the gaussian approximant on xmesh.
2408 : !! The second slice stores the primitive.
2409 : !!
2410 : !! SOURCE
2411 :
2412 0 : pure subroutine gspline_eval(self, x0, nx, xmesh, weights)
2413 :
2414 : !Arguments ------------------------------------
2415 : !scalars
2416 : class(gspline_t),intent(in) :: self
2417 : integer,intent(in) :: nx
2418 : real(dp),intent(in) :: x0
2419 : !arrays
2420 : real(dp),intent(in) :: xmesh(nx)
2421 : real(dp),intent(out) :: weights(nx,2)
2422 :
2423 : !Local variables ------------------------------
2424 : !scalars
2425 : integer :: ix,jspl
2426 : real(dp) :: xx,absx,aa,bb,cc,dd
2427 : logical :: isneg
2428 : !real(dp) :: int_values(nx)
2429 : ! *************************************************************************
2430 :
2431 0 : do ix=1,nx
2432 0 : xx = xmesh(ix) - x0; absx = abs(xx); isneg = xx < zero
2433 0 : if (absx >= self%xmax) then
2434 : ! Region in which gauss(x) is negligible.
2435 0 : weights(ix,1) = zero
2436 0 : if (isneg) then
2437 0 : weights(ix,2) = zero
2438 : else
2439 0 : weights(ix,2) = one
2440 : end if
2441 : else
2442 : ! Spline functions at |x| and recover the value at x:
2443 : ! g(x) = g(-x); G(-x) = 1 - G(x)
2444 0 : jspl = 1 + int((absx - self%xmin) * self%stepm1); dd = absx - self%xvals(jspl)
2445 0 : bb = dd * self%stepm1
2446 0 : aa = one - bb
2447 0 : cc = aa*(aa**2-one) * self%step2div6
2448 0 : dd = bb*(bb**2-one) * self%step2div6
2449 :
2450 0 : weights(ix,1) = aa*self%svals(jspl,1) + bb*self%svals(jspl+1,1) + cc*self%svals(jspl,2) + dd*self%svals(jspl+1,2)
2451 0 : weights(ix,2) = aa*self%svals(jspl,3) + bb*self%svals(jspl+1,3) + cc*self%svals(jspl,4) + dd*self%svals(jspl+1,4)
2452 0 : if (isneg) weights(ix,2) = one - weights(ix,2)
2453 : end if
2454 : end do
2455 :
2456 : !call simpson_int(nx,xmesh(2) - xmesh(1),weights(:,1),int_values)
2457 : !do ix=1,nx
2458 : ! write(99,*)xmesh(ix), weights(ix,1), gaussian(xx, self%sigma), weights(ix,2), int_values(ix)
2459 : !end do
2460 :
2461 0 : end subroutine gspline_eval
2462 : !!***
2463 :
2464 : !!****f* m_special_funcs/gspline_free
2465 : !! NAME
2466 : !! gspline_free
2467 : !!
2468 : !! FUNCTION
2469 : !! Free dynamic memory
2470 : !!
2471 : !! SOURCE
2472 :
2473 0 : subroutine gspline_free(self)
2474 :
2475 : !Arguments ------------------------------------
2476 : class(gspline_t),intent(inout) :: self
2477 : ! *************************************************************************
2478 :
2479 0 : ABI_SFREE(self%xvals)
2480 0 : ABI_SFREE(self%svals)
2481 :
2482 0 : end subroutine gspline_free
2483 : !!***
2484 :
2485 0 : end module m_special_funcs
2486 : !!***
|