eplf/src/eplf_function.irp.f

428 lines
11 KiB
Fortran

BEGIN_PROVIDER [ real, eplf_gamma ]
implicit none
BEGIN_DOC
! Value of the gaussian for the EPLF
END_DOC
include 'constants.F'
real :: eps, N
! N = 0.1
! eps = -real(dlog(tiny(1.d0)))
! eplf_gamma = (4./3.*pi*density_value_p/N)**(2./3.) * eps
N=0.001
eps = 50.
eplf_gamma = eps**2 *0.5d0*(4./9.*pi*density_value_p * N**(-1./3.))**(2./3.)
!eplf_gamma = 1.e10
!eplf_gamma = 1.e5
END_PROVIDER
BEGIN_PROVIDER [ double precision, ao_eplf_integral_matrix, (ao_num,ao_num) ]
implicit none
BEGIN_DOC
! Array of all the <chi_i chi_j | exp(-gamma r^2)> for EPLF
END_DOC
integer :: i, j
double precision :: ao_eplf_integral
do i=1,ao_num
do j=i,ao_num
ao_eplf_integral_matrix(j,i) = ao_eplf_integral(j,i,dble(eplf_gamma),point)
ao_eplf_integral_matrix(i,j) = ao_eplf_integral_matrix(j,i)
enddo
enddo
END_PROVIDER
BEGIN_PROVIDER [ integer, ao_eplf_integral_matrix_non_zero_idx, (0:ao_num,ao_num) ]
implicit none
BEGIN_DOC
! Non zero indices of the ao_eplf_integral_matrix
END_DOC
integer :: i, j
integer :: idx
do j=1,ao_num
idx = 0
do i=1,ao_num
if (abs(ao_eplf_integral_matrix(i,j)) > 1.e-16) then
idx +=1
ao_eplf_integral_matrix_non_zero_idx(idx,j) = i
endif
enddo
ao_eplf_integral_matrix_non_zero_idx(0,j) = idx
enddo
END_PROVIDER
BEGIN_PROVIDER [ double precision, mo_eplf_integral_matrix, (mo_num,mo_num) ]
implicit none
BEGIN_DOC
! Array of all the <phi_i phi_j | exp(-gamma r^2)> for EPLF
END_DOC
integer :: i, j, k, l, kmo, kao
double precision :: t, moki
!DEC$ VECTOR ALIGNED
mo_eplf_integral_matrix = 0.d0
do k=1,ao_num
do kmo=1,mo_coef_transp_non_zero_idx(0,k)
i = mo_coef_transp_non_zero_idx(kmo,k)
moki = mo_coef_transp(i,k)
do kao = 1,ao_eplf_integral_matrix_non_zero_idx(0,k)
l = ao_eplf_integral_matrix_non_zero_idx(kao,k)
t = moki*ao_eplf_integral_matrix(l,k)
do j=i,mo_num
mo_eplf_integral_matrix(j,i) += t*mo_coef_transp(j,l)
enddo
enddo
enddo
enddo
!do j=1,mo_num
! do i=1,j-1
! mo_eplf_integral_matrix(i,j) = mo_eplf_integral_matrix(j,i)
! enddo
!enddo
integer :: momax
momax = mo_num - mod(mo_num,4)
do j=1,momax,4
do i=1,j-1
mo_eplf_integral_matrix(i,j ) = mo_eplf_integral_matrix(j ,i)
mo_eplf_integral_matrix(i,j+1) = mo_eplf_integral_matrix(j+1,i)
mo_eplf_integral_matrix(i,j+2) = mo_eplf_integral_matrix(j+2,i)
mo_eplf_integral_matrix(i,j+3) = mo_eplf_integral_matrix(j+3,i)
enddo
mo_eplf_integral_matrix(j ,j+1) = mo_eplf_integral_matrix(j+1,j)
mo_eplf_integral_matrix(j ,j+2) = mo_eplf_integral_matrix(j+2,j)
mo_eplf_integral_matrix(j ,j+3) = mo_eplf_integral_matrix(j+3,j)
mo_eplf_integral_matrix(j+1,j+2) = mo_eplf_integral_matrix(j+2,j+1)
mo_eplf_integral_matrix(j+1,j+3) = mo_eplf_integral_matrix(j+3,j+1)
mo_eplf_integral_matrix(j+2,j+3) = mo_eplf_integral_matrix(j+3,j+2)
enddo
do j=momax+1,mo_num
do i=1,j-1
mo_eplf_integral_matrix(i,j) = mo_eplf_integral_matrix(j,i)
enddo
enddo
END_PROVIDER
BEGIN_PROVIDER [ double precision, eplf_up_up ]
&BEGIN_PROVIDER [ double precision, eplf_up_dn ]
implicit none
BEGIN_DOC
! Value of the d_upup and d_updn quantities needed for EPLF
END_DOC
integer :: i, j
eplf_up_up = 0.d0
eplf_up_dn = 0.d0
PROVIDE mo_coef_transp
do i=1,mo_closed_num
do j=1,mo_closed_num
double precision :: temp
temp = mo_value_prod_p(i,i)*mo_eplf_integral_matrix(j,j)
eplf_up_up += temp - mo_value_prod_p(j,i)*mo_eplf_integral_matrix(j,i)
eplf_up_dn += temp
enddo
enddo
eplf_up_up *= 2.d0
eplf_up_dn *= 2.d0
integer :: k,l,m
do m=1,two_e_density_num
i=two_e_density_indice(1,m)
j=two_e_density_indice(2,m)
k=two_e_density_indice(3,m)
l=two_e_density_indice(4,m)
temp = mo_value_prod_p(i,j)*mo_eplf_integral_matrix(k,l)
eplf_up_up += two_e_density_value(1,m)*temp
eplf_up_dn += two_e_density_value(2,m)*temp
enddo
END_PROVIDER
BEGIN_PROVIDER [ real, eplf_value_p ]
implicit none
BEGIN_DOC
! Value of the EPLF at the current point.
END_DOC
double precision :: aa, ab
double precision, parameter :: eps = tiny(1.d0)
aa = eplf_up_up
ab = eplf_up_dn
if ( (aa > 0.d0).and.(ab > 0.d0) ) then
aa = min(1.d0,aa)
ab = min(1.d0,ab)
aa = -dlog(aa)
aa = dsqrt(aa)
ab = -dlog(ab)
ab = dsqrt(ab)
eplf_value_p = (aa-ab)/(aa+ab+eps)
else
eplf_value_p = 0.d0
endif
END_PROVIDER
!double precision function ao_eplf_integral_primitive_oneD_numeric(a,xa,i,b,xb,j,gmma,xr)
! implicit none
! include 'constants.F'
!
! real, intent(in) :: a,b,gmma ! Exponents
! real, intent(in) :: xa,xb,xr ! Centers
! integer, intent(in) :: i,j ! Powers of xa and xb
! integer,parameter :: Npoints=10000
! real :: x, xmin, xmax, dx
!
! ASSERT (a>0.)
! ASSERT (b>0.)
! ASSERT (i>=0)
! ASSERT (j>=0)
!
! xmin = min(xa,xb)
! xmax = max(xa,xb)
! xmin = min(xmin,xr) - 10.
! xmax = max(xmax,xr) + 10.
! dx = (xmax-xmin)/real(Npoints)
!
! real :: dtemp
! dtemp = 0.
! x = xmin
! integer :: k
! do k=1,Npoints
! dtemp += &
! (x-xa)**i * (x-xb)**j * exp(-(a*(x-xa)**2+b*(x-xb)**2+gmma*(x-xr)**2))
! x = x+dx
! enddo
! ao_eplf_integral_primitive_oneD_numeric = dtemp*dx
!
!end function
!
!double precision function ao_eplf_integral_numeric(i,j,gmma,center)
! implicit none
! integer, intent(in) :: i, j
! integer :: p,q,k
! double precision :: integral
! double precision :: ao_eplf_integral_primitive_oneD_numeric
! real :: gmma, center(3), c
!
!
! ao_eplf_integral_numeric = 0.d0
! do q=1,ao_prim_num(j)
! do p=1,ao_prim_num(i)
! c = ao_coef(p,i)*ao_coef(q,j)
! integral = &
! ao_eplf_integral_primitive_oneD_numeric( &
! ao_expo(p,i), &
! nucl_coord(ao_nucl(i),1), &
! ao_power(i,1), &
! ao_expo(q,j), &
! nucl_coord(ao_nucl(j),1), &
! ao_power(j,1), &
! gmma, &
! center(1)) * &
! ao_eplf_integral_primitive_oneD_numeric( &
! ao_expo(p,i), &
! nucl_coord(ao_nucl(i),2), &
! ao_power(i,2), &
! ao_expo(q,j), &
! nucl_coord(ao_nucl(j),2), &
! ao_power(j,2), &
! gmma, &
! center(2)) * &
! ao_eplf_integral_primitive_oneD_numeric( &
! ao_expo(p,i), &
! nucl_coord(ao_nucl(i),3), &
! ao_power(i,3), &
! ao_expo(q,j), &
! nucl_coord(ao_nucl(j),3), &
! ao_power(j,3), &
! gmma, &
! center(3))
! ao_eplf_integral_numeric = ao_eplf_integral_numeric + c*integral
! enddo
! enddo
!
!end function
double precision function ao_eplf_integral_primitive_oneD(a,xa,i,b,xb,j,gmma,xr)
implicit none
include 'constants.F'
real, intent(in) :: a,b ! Exponents
double precision , intent(in) :: gmma ! eplf_gamma
real, intent(in) :: xa,xb,xr ! Centers
integer, intent(in) :: i,j ! Powers of xa and xb
integer :: ii, jj, kk
integer, save :: ifirst=0
double precision, save :: f2(32)
if (ifirst == 0) then
ifirst = 1
do ii=1,32
f2(ii) = 2.d0**(-ii/2) * fact2(ii-1)
enddo
endif
ASSERT (a>0.)
ASSERT (b>0.)
ASSERT (i>=0)
ASSERT (j>=0)
double precision :: alpha, beta, delta, c, beta_inv
double precision :: db_inv
beta = a + b + gmma
beta_inv = 1.d0/beta
delta = a*xa + b*xb + gmma*xr
db_inv = delta*beta_inv
alpha = a*xa*xa + b*xb*xb + gmma*xr*xr
c = alpha-delta*db_inv
if ( c > 20.d0 ) then ! Cut-off on exp(-32)
ao_eplf_integral_primitive_oneD = 0.d0
return
endif
double precision :: u,v,w
c = exp(-c)
w = sqrt(beta_inv)
u=db_inv-xa
v=db_inv-xb
double precision :: fact2, binom, f, ac
double precision :: ui(-1:i), vj(-1:j), wij(-1:i+j+3)
!DEC$ ATTRIBUTES ALIGN : 32 :: ui, vj, wij
ui(i) = 1.d0
ui(i-1) = u
do ii=i-2,0,-1
ui(ii) = ui(ii+1) * u
enddo
vj(j) = 1.d0
vj(j-1) = v
do jj=j-2,0,-1
vj(jj) = vj(jj+1) * v
enddo
wij(0) = 1.d0
wij(1) = w
wij(2) = w*w
do ii=3,i+j
wij(ii) = wij(ii-1) * w
enddo
do ii=2,i+j
wij(ii) *= f2(ii)
enddo
ac = 0.d0
integer :: istart(0:1)
istart(0) = 0
istart(1) = 1
do ii=0,i
if (istart(mod(ii,2))<=j) then
f=ui(ii)*binom(ii,i)
do jj=istart(mod(ii,2)),j,2
ac += vj(jj) * wij(ii+jj) * f *binom(jj,j)
enddo
endif
enddo
ao_eplf_integral_primitive_oneD = dsqrt_pi*w*c*ac
end function
double precision function ao_eplf_integral(i,j,gmma,center)
implicit none
integer, intent(in) :: i, j
real, intent(in) :: center(3)
double precision, intent(in) :: gmma
integer :: p,q,k
double precision :: integral
double precision :: ao_eplf_integral_primitive_oneD
ASSERT(i>0)
ASSERT(j>0)
ASSERT(ao_prim_num_max < 100)
ASSERT(i<=ao_num)
ASSERT(j<=ao_num)
ao_eplf_integral = 0.d0
do q=1,ao_prim_num(j)
do p=1,ao_prim_num(i)
if (abs(ao_coef(q,j)*ao_coef(p,i)) < 1.e-9) then
cycle
endif
integral = &
ao_eplf_integral_primitive_oneD( &
ao_expo(p,i), &
nucl_coord(ao_nucl(i),1), &
ao_power(i,1), &
ao_expo(q,j), &
nucl_coord(ao_nucl(j),1), &
ao_power(j,1), &
gmma, &
center(1))
if (dabs(integral) > 1.d-15) then
integral *= &
ao_eplf_integral_primitive_oneD( &
ao_expo(p,i), &
nucl_coord(ao_nucl(i),2), &
ao_power(i,2), &
ao_expo(q,j), &
nucl_coord(ao_nucl(j),2), &
ao_power(j,2), &
gmma, &
center(2))
if (dabs(integral) > 1.d-15) then
integral *= &
ao_eplf_integral_primitive_oneD( &
ao_expo(p,i), &
nucl_coord(ao_nucl(i),3), &
ao_power(i,3), &
ao_expo(q,j), &
nucl_coord(ao_nucl(j),3), &
ao_power(j,3), &
gmma, &
center(3))
ao_eplf_integral += integral*ao_coef(p,i)*ao_coef(q,j)
endif
endif
enddo
enddo
end function
double precision function mo_eplf_integral(i,j)
implicit none
integer :: i, j, k, l
PROVIDE ao_eplf_integral_matrix
PROVIDE mo_coef
mo_eplf_integral = 0.d0
do k=1,ao_num
if (mo_coef(k,i) /= 0.) then
do l=1,ao_num
mo_eplf_integral += &
mo_coef(k,i)*mo_coef(l,j)*ao_eplf_integral_matrix(l,k)
enddo
endif
enddo
end function