TABLE OF CONTENTS


ABINIT/m_pawrad [ Modules ]

[ Top ] [ Modules ]

NAME

 m_pawrad

FUNCTION

 Module containing all the functions related to the PAW radial meshes

COPYRIGHT

 Copyright (C) 2013-2024 ABINIT group (MT,FJ,MG)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

NOTES

  * Routines tagged with "@type_name" are strongly connected to the definition of the data type.
    Strongly connected means that the proper functioning of the implementation relies on the
    assumption that the tagged procedure is consistent with the type declaration.
    Every time a developer changes the structure "type_name" adding new entries, he/she has to make sure
    that all the strongly connected routines are changed accordingly to accommodate the modification of the data type
    Typical examples of strongly connected routines are creation, destruction or reset methods.

  * FOR DEVELOPERS: in order to preserve the portability of libPAW library,
    please consult ~abinit/src/??_libpaw/libpaw-coding-rules.txt

SOURCE

27 #include "libpaw.h"
28 
29 MODULE m_pawrad
30 
31  USE_DEFS
32  USE_MSG_HANDLING
33  USE_MPI_WRAPPERS
34  USE_MEMORY_PROFILING
35 
36  use m_paw_numeric, only : paw_derfc
37 
38  implicit none
39 
40  private
41 
42 !public procedures.
43  public :: pawrad_init          ! Main creation method
44  public :: pawrad_free          ! Free the allocated memory
45  public :: pawrad_print         ! Printout of the basic info
46  public :: pawrad_isame         ! Checks whether two meshes are equivalent or have the same equation.
47  public :: pawrad_copy          ! Returns a copy of the mesh.
48  public :: pawrad_ifromr        ! Retrieve the Index FROM a given R value in a radial grid.
49  public :: pawrad_deducer0      ! Extrapolate r=0 value of a function from values near r=0.
50  public :: pawrad_bcast         ! Broadcast pawrad datastructure over a given MPI communicator
51  public :: simp_gen             ! Performs integral on a given (generalized) grid using Simpson rule.
52  public :: nderiv_gen           ! Do corrected first (and 2nd) derivation on a given (generalized) grid.
53  public :: nderiv_lin           ! Do corrected first (and 2nd) derivation on a given linear grid.
54  public :: bound_deriv          ! Computes derivatives at boundaries of the mesh
55  public :: poisson              ! Solves Poisson eq. for angularly dependent charge distribution of angular momentum l
56  public :: screened_coul_kernel ! Kernel used to compute short-range screened Coulomb integrals
57  public :: calc_slatradl        ! Calculates the radial part of Slater integrals.
58 
59  interface pawrad_free
60    module procedure pawrad_free_0D
61    module procedure pawrad_free_1D
62  end interface pawrad_free
63 
64  ! TODO: Might use bit flags, but all radmesh stuff should be encapsulated here!
65  integer,private,parameter :: RMESH_LINEAR = 1
66  integer,private,parameter :: RMESH_LOG1   = 2
67  integer,private,parameter :: RMESH_LOG2   = 3
68  integer,private,parameter :: RMESH_LOG3   = 4
69  integer,private,parameter :: RMESH_NL     = 5

m_pawrad/bound_deriv [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 bound_deriv

FUNCTION

 Computes derivatives of a function a boundaries of interval (first and last derivative)

INPUTS

  func(n)= array containing function
  mesh <type(pawrad_type)>= radial mesh and related data
  nn= size of intervall

OUTPUT

  yp1,ypn= derivatives of func at r(1) and r(n)

SOURCE

1114  subroutine bound_deriv(func,mesh,nn,yp1,ypn)
1115 
1116 !Arguments----------------------
1117  integer, intent(in) :: nn
1118  real(dp), intent(in) :: func(nn)
1119  real(dp), intent(out) :: yp1,ypn
1120  type(pawrad_type),intent(in) :: mesh
1121 
1122 !*************************************************************************
1123 
1124  if (mesh%radfact(1)>zero) then
1125    yp1=1._dp/12._dp/mesh%stepint/mesh%radfact(1) &
1126 &   *(-25._dp*func(1)+48._dp*func(2)-36._dp*func(3)+16._dp*func(4)-3._dp*func(5))
1127  else
1128    yp1=(func(2)-func(1))/(mesh%rad(2)-mesh%rad(1))
1129  end if
1130  ypn=1._dp/12._dp/mesh%stepint &
1131 & *( 3._dp*func(nn-4)-16._dp*func(nn-3)+36._dp*func(nn-2)-48._dp*func(nn-1) &
1132 & +25._dp*func(nn))/mesh%radfact(nn)
1133 
1134 end subroutine bound_deriv

m_pawrad/calc_slatradl [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  calc_slatradl

FUNCTION

  Calculate the radial part of Slater integrals. See below.

INPUTS

  ll= l quantum number in the expansion of the Coulomb term.
  mesh_size=Number of points on the radial mesh.
  ff1(radmesh), ff2(radmesh)= The two functions to be integrated.
  Pawrad <type(pawrad_type)>=Structure containing radial grid information.

OUTPUT

  integral =
   $ \dfrac{4\pi}{2L+1} \int ff1(r1) \dfrac{r_<^L}{r_>^{L+1}} ff2(r2) dr1 dr2 $
  where $r_< = min(r1,r2)$ and $r_> = Max(r1,r2)$.

SOURCE

1702 subroutine calc_slatradl(ll,mesh_size,ff1,ff2,Pawrad,integral)
1703 
1704 !scalars
1705  integer,intent(in) :: mesh_size,ll
1706  real(dp),intent(out) :: integral
1707 !arrays
1708  real(dp),intent(in) :: ff1(mesh_size),ff2(mesh_size)
1709  type(pawrad_type),intent(in) :: Pawrad
1710 
1711 !Local variables ---------------------------------------
1712 !scalars
1713  integer :: int_meshsz
1714  character(len=100) :: msg
1715 !arrays
1716  real(dp),allocatable :: hh(:),gg(:)
1717 
1718 ! *************************************************************************
1719 
1720  if (mesh_size > Pawrad%mesh_size) then
1721    msg='mesh_size > pawrad%mesh_size!'
1722    LIBPAW_BUG(msg)
1723  end if
1724 
1725  LIBPAW_ALLOCATE(hh,(mesh_size))
1726  LIBPAW_ALLOCATE(gg,(mesh_size))
1727  !hh = zero
1728  !gg = zero
1729 
1730  int_meshsz=Pawrad%int_meshsz
1731  !$int_meshsz=Pawrad%mesh_size
1732 
1733  ! the line below requires hh as work array.
1734  hh = ff2
1735 
1736  ! TODO find where int_meshsz is calculated and if it can affects the results.
1737  if (int_meshsz<mesh_size) hh(int_meshsz+1:mesh_size)=zero
1738 
1739  call poisson(hh,ll,Pawrad,gg)
1740 
1741  gg(2:mesh_size) = gg(2:mesh_size)/Pawrad%rad(2:mesh_size)
1742 
1743  hh(1)          = zero
1744  hh(2:mesh_size)= ff1(2:mesh_size) * gg(2:mesh_size)
1745  LIBPAW_DEALLOCATE(gg)
1746 
1747  call simp_gen(integral,hh,Pawrad)
1748  integral = four_pi * integral
1749 
1750  LIBPAW_DEALLOCATE(hh)
1751 
1752 end subroutine calc_slatradl

m_pawrad/nderiv_gen [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 nderiv_gen

FUNCTION

 Do corrected first (and -if requested- second) derivation on a given (generalized) grid.
 This routine interfaces nderiv_lin (derivation on a linear grid).

INPUTS

  func(:)=input function
  radmesh <type(pawrad_type)>=data containing radial grid information

OUTPUT

  der(:)= 1st derivative of input function
  [der2(:)]= -- optional -- 2nd derivative of input function

NOTES

  Possible mesh types (radmesh%mesh_type)
   mesh_type=1 (regular grid): rad(i)=(i-1)*AA
   mesh_type=2 (logari. grid): rad(i)=AA*(exp[BB*(i-1)]-1)
   mesh_type=3 (logari. grid): rad(i>1)=AA*exp[BB*(i-2)] and rad(1)=0
   mesh_type=4 (logari. grid): rad(i)=-AA*ln[1-BB*(i-1)] with BB=1/n

SOURCE

 931 subroutine nderiv_gen(der,func,radmesh,der2)
 932 
 933 !Arguments ------------------------------------
 934 !scalars
 935  type(pawrad_type),intent(in) :: radmesh
 936 !arrays
 937  real(dp),intent(in) :: func(:)
 938  real(dp),intent(out) :: der(:)
 939  real(dp),optional,intent(out) :: der2(:)
 940 
 941 !Local variables-------------------------------
 942 !scalars
 943  integer :: msz
 944  logical :: compute_2der
 945  character(len=500) :: msg
 946 
 947 ! *************************************************************************
 948 
 949  msz=size(func)
 950  if (size(der)/=msz.or.msz>radmesh%mesh_size) then
 951    msg='wrong sizes for in/out arrays!'
 952    LIBPAW_BUG(msg)
 953  end if
 954 
 955  compute_2der=(present(der2))
 956 
 957  if (radmesh%mesh_type==1) then
 958 
 959    call nderiv_lin(radmesh%rstep,func,der,msz,1)
 960    if (compute_2der) then
 961      call nderiv_lin(radmesh%rstep,func,der2,msz,2)
 962    end if
 963 
 964  else if (radmesh%mesh_type==2) then
 965 
 966    call nderiv_lin(radmesh%lstep,func,der,msz,1)
 967    der(1:msz)=der(1:msz)/radmesh%radfact(1:msz)
 968    if (compute_2der)then
 969      call nderiv_lin(radmesh%lstep,func,der2,msz,2)
 970      der2(1:msz)=(der2(1:msz)/radmesh%radfact(1:msz)-der(1:msz))/radmesh%radfact(1:msz)
 971    end if
 972 
 973  else if (radmesh%mesh_type==3) then
 974 
 975    call nderiv_lin(radmesh%lstep,func(2:msz),der(2:msz),msz-1,1)
 976    der(2:msz)=der(2:msz)/radmesh%radfact(2:msz)
 977    call pawrad_deducer0(der,msz,radmesh)
 978    if (compute_2der)then
 979      call nderiv_lin(radmesh%lstep,func(2:msz),der2(2:msz),msz-1,2)
 980      der2(2:msz)=(der2(2:msz)/radmesh%radfact(2:msz)-der(2:msz))/radmesh%radfact(2:msz)
 981      call pawrad_deducer0(der2,msz,radmesh)
 982    end if
 983 
 984  else if (radmesh%mesh_type==4) then
 985 
 986    call nderiv_lin(radmesh%lstep,func,der,msz,1)
 987    der(1:msz)=der(1:msz)/radmesh%radfact(1:msz)
 988    if (compute_2der)then
 989      call nderiv_lin(radmesh%lstep,func,der2,msz,2)
 990      der2(1:msz)=der2(1:msz)/radmesh%radfact(1:msz)**2-der(1:msz)/radmesh%rstep
 991    end if
 992 
 993  else if (radmesh%mesh_type==5) then
 994 
 995    call nderiv_lin(one,func,der,msz,1)
 996    der(1:msz)=der(1:msz)/(radmesh%radfact(1:msz)*radmesh%rstep)
 997    if (compute_2der)then
 998      call nderiv_lin(one,func,der2,msz,2)
 999      der2(1:msz)=der2(1:msz)/(radmesh%radfact(1:msz)*radmesh%rstep)**2-two*der(1:msz)/&
1000 &                            (radmesh%rstep+radmesh%rad(1:msz))
1001    end if
1002  end if
1003 
1004 end subroutine nderiv_gen

m_pawrad/nderiv_lin [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 nderiv_lin

FUNCTION

 Do corrected first (and -if requested- second) derivation on a given LINEAR grid.

INPUTS

  hh= radial step
  ndim= radial mesh size
  yy(ndim)= input function
  norder= order of derivation (1 or 2)

OUTPUT

  zz(ndim)= first or second derivative of y

SOURCE

1027 subroutine nderiv_lin(hh,yy,zz,ndim,norder)
1028 
1029 !Arguments ---------------------------------------------
1030 !scalars
1031  integer,intent(in) :: ndim,norder
1032  real(dp),intent(in) :: hh
1033 !arrays
1034  real(dp),intent(in) :: yy(ndim)
1035  real(dp),intent(out) :: zz(ndim)
1036 
1037 !Local variables ---------------------------------------
1038 !scalars
1039  integer :: ier,ii
1040  real(dp) :: aa,bb,cc,h1,y1
1041 
1042 ! *************************************************************************
1043 
1044 !Initialization (common to 1st and 2nd derivative)
1045  h1=one/(12.d0*hh)
1046  y1=yy(ndim-4)
1047 
1048 !FIRST DERIVATIVE
1049 !================
1050  if (norder==1) then
1051 
1052 !  Prepare differentiation loop
1053    bb=h1*(-25.d0*yy(1)+48.d0*yy(2)-36.d0*yy(3)+16.d0*yy(4)-3.d0*yy(5))
1054    cc=h1*(-3.d0*yy(1)-10.d0*yy(2)+18.d0*yy(3)-6.d0*yy(4)+yy(5))
1055 !  Start differentiation loop
1056    do ii=5,ndim
1057      aa=bb;bb=cc
1058      cc=h1*(yy(ii-4)-yy(ii)+8.d0*(yy(ii-1)-yy(ii-3)))
1059      zz(ii-4)=aa
1060    end do
1061 !  Normal exit
1062    ier=0
1063    aa=h1*(-y1+6.d0*yy(ndim-3)-18.d0*yy(ndim-2)+10.d0*yy(ndim-1)+3.d0*yy(ndim))
1064    zz(ndim)=h1*(3.d0*y1-16.d0*yy(ndim-3)+36.d0*yy(ndim-2) -48.d0*yy(ndim-1)+25.d0*yy(ndim))
1065    zz(ndim-1)=aa
1066    zz(ndim-2)=cc
1067    zz(ndim-3)=bb
1068 
1069 !  SECOND DERIVATIVE
1070 !  =================
1071  else
1072    h1=h1/hh
1073 !  Prepare differentiation loop
1074    bb=h1*(35.d0*yy(1)-104.d0*yy(2)+114.d0*yy(3)-56.d0*yy(4)+11.d0*yy(5))
1075    cc=h1*(11.d0*yy(1)-20.d0*yy(2)+6.d0*yy(3)+4.d0*yy(4)-yy(5))
1076 !  Start differentiation loop
1077    do ii=5,ndim
1078      aa=bb;bb=cc
1079      cc=h1*(-yy(ii-4)-yy(ii)+16.d0*(yy(ii-1)+yy(ii-3))-30.d0*yy(ii-2))
1080      zz(ii-4)=aa
1081    end do
1082 !  Normal exit
1083    ier=0
1084    aa=h1*(-y1+4.d0*yy(ndim-3)+6.d0*yy(ndim-2)-20.d0*yy(ndim-1)+11.d0*yy(ndim))
1085    zz(ndim)=h1*(11.d0*y1-56.d0*yy(ndim-3)+114.d0*yy(ndim-2) -104.d0*yy(ndim-1)+35.d0*yy(ndim))
1086    zz(ndim-1)=aa
1087    zz(ndim-2)=cc
1088    zz(ndim-3)=bb
1089 
1090  end if !norder
1091 
1092 end subroutine nderiv_lin

m_pawrad/pawrad_bcast [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 pawrad_bcast

FUNCTION

 Communicate pawrad data over a given MPI communicator

INPUTS

 comm_mpi= communicator used to broadcast data

SIDE EFFECTS

  pawrad=<type pawrad_type>= a radial mesh datastructure for PAW

SOURCE

648 subroutine pawrad_bcast(pawrad,comm_mpi)
649 
650 !Arguments ------------------------------------
651 !scalars
652  integer,intent(in) :: comm_mpi
653  type(pawrad_type),intent(inout) :: pawrad
654 
655 !Local variables-------------------------------
656 !scalars
657  integer :: ierr,indx,me,nn,isz1
658  integer :: if_rad,if_radfact,if_simfact !flags used to communicate
659  character(len=500) :: msg
660 !arrays
661  integer,allocatable :: list_int(:)
662  real(dp),allocatable :: list_dpr(:)
663 
664 !*************************************************************************
665 
666  me=xmpi_comm_rank(comm_mpi)
667 
668 !Initializations
669  if_rad=0; if_radfact=0; if_simfact=0
670 
671 !calculate the size of the reals
672  if(me==0) then
673    if (allocated(pawrad%rad)) then
674      if_rad=1 !communicate rad
675      isz1=size(pawrad%rad)
676      if(isz1/=pawrad%mesh_size) then
677        msg='rad: sz1 /= pawrad%mesh_size (1)'
678        LIBPAW_BUG(msg)
679      end if
680    end if
681    if (allocated(pawrad%radfact)) then
682      if_radfact=1 !communicate radfact
683      isz1=size(pawrad%radfact)
684      if(isz1/=pawrad%mesh_size) then
685        msg='radfact: sz1 /= pawrad%mesh_size (2)'
686        LIBPAW_BUG(msg)
687      end if
688    end if
689    if (allocated(pawrad%simfact)) then
690      if_simfact=1 !communicate simfact
691      isz1=size(pawrad%simfact)
692      if(isz1/=pawrad%mesh_size) then
693        msg='simfact: sz1 /= pawrad%mesh_size (3)'
694        LIBPAW_BUG(msg)
695      end if
696    end if
697  end if
698 
699 !Brodcast the integers
700  LIBPAW_ALLOCATE(list_int,(6))
701  if(me==0) then
702    list_int(1)=pawrad%int_meshsz
703    list_int(2)=pawrad%mesh_size
704    list_int(3)=pawrad%mesh_type
705    list_int(4)=if_rad
706    list_int(5)=if_radfact
707    list_int(6)=if_simfact
708  end if
709  call xmpi_bcast(list_int,0,comm_mpi,ierr)
710  if(me/=0) then
711    pawrad%int_meshsz =list_int(1)
712    pawrad%mesh_size =list_int(2)
713    pawrad%mesh_type =list_int(3)
714    if_rad=list_int(4)
715    if_radfact=list_int(5)
716    if_simfact=list_int(6)
717  end if
718  LIBPAW_DEALLOCATE(list_int)
719 
720 !Broadcast the reals
721  nn=4+pawrad%mesh_size*(if_rad+if_radfact+if_simfact)
722  LIBPAW_ALLOCATE(list_dpr,(nn))
723  if(me==0) then
724    list_dpr(1)=pawrad%lstep
725    list_dpr(2)=pawrad%rmax
726    list_dpr(3)=pawrad%rstep
727    list_dpr(4)=pawrad%stepint
728    indx=5
729    if (if_rad==1) then
730      isz1=pawrad%mesh_size
731      list_dpr(indx:indx+isz1-1)=pawrad%rad(1:isz1)
732      indx=indx+isz1
733    end if
734    if (if_radfact==1) then
735      isz1=pawrad%mesh_size
736      list_dpr(indx:indx+isz1-1)=pawrad%radfact(1:isz1)
737      indx=indx+isz1
738    end if
739    if (if_simfact==1) then
740      isz1=pawrad%mesh_size
741      list_dpr(indx:indx+isz1-1)=pawrad%simfact(1:isz1)
742      indx=indx+isz1
743    end if
744  end if
745  call xmpi_bcast(list_dpr,0,comm_mpi,ierr)
746  if(me/=0) then
747    pawrad%lstep=list_dpr(1)
748    pawrad%rmax=list_dpr(2)
749    pawrad%rstep=list_dpr(3)
750    pawrad%stepint=list_dpr(4)
751    indx=5
752 !  Deallocate all arrays:
753    if (allocated(pawrad%rad)) then
754      LIBPAW_DEALLOCATE(pawrad%rad)
755    end if
756    if (allocated(pawrad%radfact)) then
757      LIBPAW_DEALLOCATE(pawrad%radfact)
758    end if
759    if (allocated(pawrad%simfact)) then
760      LIBPAW_DEALLOCATE(pawrad%simfact)
761    end if
762 !  Communicate if flag is set to 1:
763    if(if_rad==1) then
764      isz1=pawrad%mesh_size
765      LIBPAW_ALLOCATE(pawrad%rad,(isz1))
766      pawrad%rad(1:isz1)=list_dpr(indx:indx+isz1-1)
767      indx=indx+isz1
768    end if
769    if(if_radfact==1) then
770      isz1=pawrad%mesh_size
771      LIBPAW_ALLOCATE(pawrad%radfact,(isz1))
772      pawrad%radfact(1:isz1)=list_dpr(indx:indx+isz1-1)
773      indx=indx+isz1
774    end if
775    if(if_simfact==1) then
776      isz1=pawrad%mesh_size
777      LIBPAW_ALLOCATE(pawrad%simfact,(isz1))
778      pawrad%simfact(1:isz1)=list_dpr(indx:indx+isz1-1)
779      indx=indx+isz1
780    end if
781  end if
782  LIBPAW_DEALLOCATE(list_dpr)
783 
784 end subroutine pawrad_bcast

m_pawrad/pawrad_copy [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 pawrad_copy

FUNCTION

 Copy one radial mesh (in a generalized format) to another

INPUTS

  mesh1 <type(pawrad_type)>=data containing radial grid information of input mesh

OUTPUT

  mesh2 <type(pawrad_type)>=data containing radial grid information of output mesh

NOTES

  Possible mesh types (mesh%mesh_type)
   mesh_type=1 (regular grid): rad(i)=(i-1)*AA
   mesh_type=2 (logari. grid): rad(i)=AA*(exp[BB*(i-1)]-1)
   mesh_type=3 (logari. grid): rad(i>1)=AA*exp[BB*(i-2)] and rad(1)=0
   mesh_type=4 (logari. grid): rad(i)=-AA*ln[1-BB*(i-1)] with BB=1/n
   mesh_type=5 ( grid): rad(i)=AA*i/(n-i)

SOURCE

559 subroutine pawrad_copy(mesh1,mesh2)
560 
561 !Arguments ------------------------------------
562 !scalars
563  type(pawrad_type),intent(in) :: mesh1
564  type(pawrad_type),intent(out) :: mesh2
565 
566 !Local variables-------------------------------
567 !scalars
568  integer :: ir
569 
570 ! *************************************************************************
571 
572  mesh2%mesh_type =mesh1%mesh_type
573  mesh2%mesh_size =mesh1%mesh_size
574  mesh2%int_meshsz=mesh1%int_meshsz
575  mesh2%lstep     =mesh1%lstep
576  mesh2%rstep     =mesh1%rstep
577  mesh2%stepint   =mesh1%stepint
578  mesh2%rmax      =mesh1%rmax
579 
580  LIBPAW_ALLOCATE(mesh2%rad,(mesh1%mesh_size))
581  LIBPAW_ALLOCATE(mesh2%radfact,(mesh1%mesh_size))
582  LIBPAW_ALLOCATE(mesh2%simfact,(mesh1%mesh_size))
583  do ir=1,mesh1%mesh_size
584    mesh2%rad(ir)    =mesh1%rad(ir)
585    mesh2%radfact(ir)=mesh1%radfact(ir)
586    mesh2%simfact(ir)=mesh1%simfact(ir)
587  end do
588 
589 end subroutine pawrad_copy

m_pawrad/pawrad_deducer0 [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 pawrad_deducer0

FUNCTION

 Extrapolate r=0 value of a function from values near r=0
 using a 3 points formula

INPUTS

  funcsz=size of array func
  radmesh <type(pawrad_type)>=data containing radial grid information

SIDE EFFECTS

  func(funcsz)=array containing values of function to extrapolate

SOURCE

611 subroutine pawrad_deducer0(func,funcsz,radmesh)
612 
613 !Arguments ------------------------------------
614 !scalars
615  integer,intent(in) :: funcsz
616  type(pawrad_type),intent(in) :: radmesh
617 !arrays
618  real(dp),intent(inout) :: func(funcsz)
619 
620 ! *************************************************************************
621 
622  if (radmesh%mesh_type==1.or.radmesh%mesh_type==2.or.radmesh%mesh_type==4.or.radmesh%mesh_type==5) then
623    func(1)=func(4)+3*(func(2)-func(3))
624  else if (radmesh%mesh_type==3) then
625    func(1)=func(4)+exp(two*radmesh%lstep)/(exp(radmesh%lstep)-one)*(func(2)-func(3))
626  end if
627 
628 end subroutine pawrad_deducer0

m_pawrad/pawrad_free_0D [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  pawrad_free_0D

FUNCTION

  Frees all memory allocated in the object

SOURCE

312 subroutine pawrad_free_0D(Rmesh)
313 
314 !Arguments ------------------------------------
315 !arrays
316  type(pawrad_type),intent(inout) :: Rmesh
317 
318 !Local variables-------------------------------
319 
320 ! *************************************************************************
321 
322  !@Pawrad_type
323 
324  if (allocated(Rmesh%rad    ))  then
325    LIBPAW_DEALLOCATE(Rmesh%rad)
326  end if
327  if (allocated(Rmesh%radfact))  then
328    LIBPAW_DEALLOCATE(Rmesh%radfact)
329  end if
330  if (allocated(Rmesh%simfact))  then
331    LIBPAW_DEALLOCATE(Rmesh%simfact)
332  end if
333  Rmesh%int_meshsz=0
334  Rmesh%mesh_size=0
335  Rmesh%mesh_type=-1
336 
337 end subroutine pawrad_free_0D

m_pawrad/pawrad_free_1D [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  pawrad_free_1D

FUNCTION

  Destroy all objects in an array of pawrad data structures

SOURCE

351 subroutine pawrad_free_1D(Rmesh)
352 
353 !Arguments ------------------------------------
354  type(pawrad_type),intent(inout) :: Rmesh(:)
355 
356 !Local variables-------------------------------
357  integer :: ii,nn
358 
359 ! *************************************************************************
360 
361  !@pawrad_type
362 
363  nn=size(Rmesh)
364  if (nn==0) return
365 
366  do ii=1,nn
367    call pawrad_free_0D(Rmesh(ii))
368  end do
369 
370 end subroutine pawrad_free_1D

m_pawrad/pawrad_ifromr [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 pawrad_ifromr

FUNCTION

 Retreive Index FROM a given R value in a radial grid
 Grid can be regular or logarithimc

INPUTS

  rr=given input r value
  radmesh <type(pawrad_type)>=data containing radial grid information

OUTPUT

  pawrad_ifromr=index of rr in radial grid

NOTES

  Possible mesh types (radmesh%mesh_type)
   mesh_type=1 (regular grid): rad(i)=(i-1)*AA
   mesh_type=2 (logari. grid): rad(i)=AA*(exp[BB*(i-1)]-1)
   mesh_type=3 (logari. grid): rad(i>1)=AA*exp[BB*(i-2)] and rad(1)=0
   mesh_type=4 (logari. grid): rad(i)=-AA*ln[1-BB*(i-1)] with BB=1/n
   mesh_type=5 ( grid): rad(i)=AA*i/(n-i)

SOURCE

1406 function pawrad_ifromr(radmesh,rr)
1407 
1408 !Arguments ------------------------------------
1409 !scalars
1410  integer :: pawrad_ifromr
1411  real(dp),intent(in) :: rr
1412  type(pawrad_type),intent(in) :: radmesh
1413 
1414 !Local variables-------------------------------
1415  character(len=500) :: msg
1416 
1417 ! *************************************************************************
1418 
1419  if (radmesh%mesh_type==1) then
1420    pawrad_ifromr=int(tol8+rr/radmesh%rstep)+1
1421  else if (radmesh%mesh_type==2) then
1422    pawrad_ifromr=int(tol8+log(1.d0+rr/radmesh%rstep)/radmesh%lstep)+1
1423  else if (radmesh%mesh_type==3) then
1424    if (rr<radmesh%rstep) then
1425      pawrad_ifromr=1
1426    else
1427      pawrad_ifromr=int(tol8+log(rr/radmesh%rstep)/radmesh%lstep)+2
1428    end if
1429  else if (radmesh%mesh_type==4) then
1430    pawrad_ifromr=int(tol8+(1.d0-exp(-rr/radmesh%rstep))/radmesh%lstep)+1
1431  else if (radmesh%mesh_type==5) then
1432    pawrad_ifromr=int(tol8+(radmesh%lstep*rr)/(radmesh%rstep+rr))+1
1433  else
1434 !  Other values of mesh_type are not allowed (see psp7in.F90)
1435    write(msg,'(a,i0)')" Unknown value of %mesh_type ",radmesh%mesh_type
1436    LIBPAW_ERROR(msg)
1437  end if
1438 
1439 end function pawrad_ifromr

m_pawrad/pawrad_init [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  pawrad_init

FUNCTION

  Creation method for radial meshes.
  Compute all points (and related weights) of a radial mesh.
  Grid can be regular or logarithimc.

INPUTS

  [mesh_size]=Dimension of the radial mesh
              If not present, take mesh%mesh_size
  [mesh_type]=Type of mesh
              If not present, take mesh%mesh_type
  [rstep]=Radial step of the mesh (AA parameter above)
          If not present, take mesh%rstep
  [lstep]=Exponential step of the mesh (BB parameter above)
          If not present, take mesh%lstep
          Needed only if mesh type is logarithmic.
  [r_for_intg]=Mesh size used in integrals computation
               If not present, take mesh%r_for_intg
    Integrals will be computed up to rr(r_for_intg)
    (can be negative for an integration over the whole grid)

OUTPUT

SIDE EFFECTS

  mesh<pawrad_type>=The object completely initialized (containing radial grid information).
  The following quantities are calculated inside the routine:
    %stepint = Radial step used to convert any function from the
               present grid onto a regular grid in order to integrate it using trapeze method
    %rad(mesh_size) = Coordinates of all the points of the mesh.
    %radfact(mesh_size) = Factors used to compute radial integrals.
    %int_meshsz = Integrals will be computed up to r(int_meshsz)
    %simfact(mesh_size) = Factor used to compute radial integrals by the a Simpson scheme
                          Integral[f] = Sum_i [simfact(i)*f(i)]
    %rmax = Max. value of r = rad(mesh_size)

NOTES

  Possible mesh types (mesh%mesh_type)
   mesh_type=1 (regular grid): rad(i)=(i-1)*AA
   mesh_type=2 (logari. grid): rad(i)=AA*(exp[BB*(i-1)]-1)
   mesh_type=3 (logari. grid): rad(i>1)=AA*exp[BB*(i-2)] and rad(1)=0
   mesh_type=4 (logari. grid): rad(i)=-AA*ln[1-BB*(i-1)] with BB=1/n
   mesh_type=5 ( grid): rad(i)=AA*i/(n-i)

SOURCE

190 subroutine pawrad_init(mesh,mesh_size,mesh_type,rstep,lstep,r_for_intg)
191 
192 !Arguments ------------------------------------
193 !scalars
194  integer,intent(in),optional :: mesh_size,mesh_type
195  real(dp),intent(in),optional :: rstep,lstep
196  real(dp),intent(in),optional :: r_for_intg
197  type(pawrad_type),intent(inout) :: mesh
198 
199 !Local variables-------------------------------
200 !scalars
201  integer :: ir,ir_last,isim,mesh_size_,mesh_type_
202  real(dp) :: hh,lstep_,rstep_,r_for_intg_
203  character(len=500) :: msg
204 
205 ! *************************************************************************
206 
207  !@pawrad_type
208 
209 !Retrieve mesh data
210  mesh_size_ = mesh%mesh_size ; if (present(mesh_size)) mesh_size_ = mesh_size
211  mesh_type_ = mesh%mesh_type ; if (present(mesh_type)) mesh_type_ = mesh_type
212  rstep_ = mesh%rstep ; if (present(rstep)) rstep_ = rstep
213  lstep_ = mesh%lstep ; if (present(lstep)) lstep_ = lstep
214 
215  r_for_intg_=-1._dp;if (present(r_for_intg)) r_for_intg_=r_for_intg
216 
217  mesh%mesh_size = mesh_size_
218  mesh%mesh_type = mesh_type_
219  mesh%rstep     = rstep_
220  mesh%lstep     = lstep_
221  LIBPAW_ALLOCATE(mesh%rad    ,(mesh%mesh_size))
222  LIBPAW_ALLOCATE(mesh%radfact,(mesh%mesh_size))
223  LIBPAW_ALLOCATE(mesh%simfact,(mesh%mesh_size))
224  mesh%simfact=zero
225  if (mesh%mesh_type==1) then
226    isim=3
227    mesh%stepint=mesh%rstep
228    mesh%rad(1)=zero;mesh%radfact(1)=one
229    do ir=2,mesh%mesh_size
230      mesh%rad(ir) =mesh%rstep*dble(ir-1)
231      mesh%radfact(ir)=one
232    end do
233  else if (mesh%mesh_type==2) then
234    isim=3
235    mesh%stepint=mesh%lstep
236    mesh%rad(1)=zero;mesh%radfact(1)=mesh%rstep
237    do ir=2,mesh%mesh_size
238      mesh%rad(ir) =mesh%rstep*(exp(mesh%lstep*dble(ir-1))-one)
239      mesh%radfact(ir)=mesh%rad(ir)+mesh%rstep
240    end do
241  else if (mesh%mesh_type==3) then
242    isim=4
243    mesh%stepint=mesh%lstep
244    mesh%rad(1)=zero;mesh%radfact(1)=zero
245    do ir=2,mesh%mesh_size
246      mesh%rad(ir) =mesh%rstep*exp(mesh%lstep*dble(ir-2))
247      mesh%radfact(ir)=mesh%rad(ir)
248    end do
249  else if (mesh%mesh_type==4) then
250    isim=3
251    mesh%lstep=one/dble(mesh%mesh_size)
252    mesh%stepint=mesh%lstep
253    mesh%rad(1)=zero;mesh%radfact(1)=mesh%rstep
254    do ir=2,mesh%mesh_size
255      mesh%rad(ir) =-mesh%rstep*log(one-mesh%lstep*dble(ir-1))
256      mesh%radfact(ir)=mesh%rstep/(one-mesh%lstep*dble(ir-1))
257    end do
258  else if (mesh%mesh_type==5) then
259    isim=3
260    mesh%stepint=mesh%rstep
261    mesh%rad(1)=zero;mesh%radfact(1)=1/mesh%lstep
262    do ir=2,mesh%mesh_size
263      mesh%rad(ir) =mesh%rstep*dble(ir-1)/(mesh%lstep-dble(ir-1))
264      mesh%radfact(ir)=(mesh%rstep+mesh%rad(ir))/(mesh%lstep-dble(ir-1))/mesh%rstep
265    end do
266 
267  else !  Other values of mesh_type are not allowed (see psp7in.F90)
268   write(msg,'(a,i0)')" Unknown value of mesh_type: ",mesh%mesh_type
269   LIBPAW_ERROR(msg)
270  end if
271 
272  mesh%int_meshsz=mesh%mesh_size
273  if (r_for_intg_>0.d0) then
274    ir=min(pawrad_ifromr(mesh,r_for_intg_),mesh%mesh_size)
275    if (ir<mesh%mesh_size) then
276      if (abs(mesh%rad(ir+1)-r_for_intg_)<abs(mesh%rad(ir)-r_for_intg_)) ir=ir+1
277    end if
278    if (ir>1) then
279      if (abs(mesh%rad(ir-1)-r_for_intg_)<abs(mesh%rad(ir)-r_for_intg_)) ir=ir-1
280    end if
281    mesh%int_meshsz=ir
282  end if
283 
284  hh=mesh%stepint/3.d0
285  mesh%simfact(mesh%int_meshsz)=hh*mesh%radfact(mesh%int_meshsz)
286  mesh%simfact(1:isim-2)=zero
287  ir_last=1
288  do ir=mesh%int_meshsz,isim,-2
289    mesh%simfact(ir-1)=4.d0*hh*mesh%radfact(ir-1)
290    mesh%simfact(ir-2)=2.d0*hh*mesh%radfact(ir-2)
291    ir_last=ir-2
292  end do
293  mesh%simfact(ir_last)=half*mesh%simfact(ir_last)
294  if (mesh%int_meshsz<mesh%mesh_size) mesh%simfact(mesh%int_meshsz+1:mesh%mesh_size)=zero
295 
296  mesh%rmax=mesh%rad(mesh%mesh_size)
297 
298 end subroutine pawrad_init

m_pawrad/pawrad_isame [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  pawrad_isame

FUNCTION

  Check two radial meshes, returns a logical flag defining
  whether the meshes have the same equation and an integer
  flag

INPUTS

  Rmesh1,Rmesh2<pawrad_type>=The two radial meshes.

OUTPUT

  hasameq=.true. if the two meshes are defined by the same equation.
  whichdenser=
    * 0 if meshes are not compatible
    * 1 if Rmesh1 is denser than Rmesh2
    * 2 if Rmesh2 is denser than Rmesh1

SOURCE

483 subroutine pawrad_isame(Rmesh1,Rmesh2,hasameq,whichdenser)
484 
485 !Arguments ------------------------------------
486  integer,intent(out) :: whichdenser
487  logical,intent(out) :: hasameq
488  type(pawrad_type),intent(in) :: Rmesh1
489  type(pawrad_type),intent(in) :: Rmesh2
490 
491 !Local variables-------------------------------
492  character(len=50) :: msg
493 
494 ! *************************************************************************
495 
496  !@pawrad_type
497 
498  whichdenser =0 ; hasameq=.FALSE.
499 
500  if (Rmesh1%mesh_type /= Rmesh2%mesh_type) RETURN
501 
502  SELECT CASE (Rmesh1%mesh_type)
503 
504  CASE (RMESH_LINEAR) !check for linear meshes
505    hasameq = (Rmesh1%rstep == Rmesh2%rstep)
506 
507  CASE (RMESH_LOG1,&  !check for logarithmic meshes
508 &      RMESH_LOG2,&
509 &      RMESH_LOG3)
510 
511    hasameq = (    Rmesh1%rstep == Rmesh2%rstep &
512 &            .and.Rmesh1%lstep == Rmesh2%lstep )
513 
514  CASE (RMESH_NL) !check for linear meshes
515    hasameq = (Rmesh1%rstep == Rmesh2%rstep)
516 
517  CASE DEFAULT
518    msg='Unknown mesh type'
519    LIBPAW_ERROR(msg)
520 
521  END SELECT
522 
523  ! === If meshes have same equation, check whether they are equal ===
524  ! * Note that also int_meshsz must be equal
525  if (hasameq) then
526    whichdenser= 1
527    if (Rmesh2%mesh_size  > Rmesh1%mesh_size ) whichdenser = 2
528    !if (Rmesh1%int_meshsz == Rmesh2%int_meshsz) whichdenser = 2
529  end if
530 
531 end subroutine pawrad_isame

m_pawrad/pawrad_print [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

  pawrad_print

FUNCTION

  Reports basic info on the object.

INPUTS

  Rmesh<pawrad_type>=Object defining the radial mesh
  header=String for the header provided by the user.
  [unit]=Unit number for output, defaults to std_out
  [prtvol]=Verbosity level, minimal if not specified.
  [mode_paral]=Either "COLL" or "PERS". Passed to wrtout. Defaults to "COLL"

OUTPUT

  Only writing.

SOURCE

394 subroutine pawrad_print(Rmesh,header,unit,prtvol,mode_paral)
395 
396 !Arguments ------------------------------------
397  integer,intent(in),optional :: prtvol,unit
398  character(len=4),intent(in),optional :: mode_paral
399  character(len=*),intent(in),optional :: header
400  type(pawrad_type),intent(in) :: Rmesh
401 
402 !Local variables-------------------------------
403 !scalars
404  integer :: my_unt,my_prtvol
405  character(len=4) :: my_mode
406  character(len=500) :: msg
407 
408 ! *************************************************************************
409 
410  !@pawrad_type
411  my_unt   =std_out; if (PRESENT(unit      )) my_unt   =unit
412  my_prtvol=0      ; if (PRESENT(prtvol    )) my_prtvol=prtvol
413  my_mode  ='COLL' ; if (PRESENT(mode_paral)) my_mode  =mode_paral
414 
415  msg=ch10//' ==== Info on the Radial Mesh ==== '
416  if (PRESENT(header)) msg=ch10//' ==== '//TRIM(ADJUSTL(header))//' ==== '
417  call wrtout(my_unt,msg,my_mode)
418 
419  SELECT CASE (Rmesh%mesh_type)
420 
421  CASE (RMESH_LINEAR)
422    write(msg,'(a,i4,a,g12.5)')&
423 &    ' - Linear mesh: r(i)=step*(i-1), size=',Rmesh%mesh_size,', step=',Rmesh%rstep
424 
425  CASE (RMESH_LOG1)
426    write(msg,'(a,i4,2(a,g12.5))')&
427 &    ' - Logarithimc mesh: r(i)=AA*[exp(BB*(i-1))-1], size=',Rmesh%mesh_size,', AA=',Rmesh%rstep,' BB=',Rmesh%lstep
428 
429  CASE (RMESH_LOG2)
430    write(msg,'(a,i4,2(a,g12.5))')&
431 &    ' - Logarithimc mesh: r(i)=AA*exp(BB*(i-2)), size=',Rmesh%mesh_size,', AA=',Rmesh%rstep,' BB=',Rmesh%lstep
432 
433  CASE (RMESH_LOG3)
434    write(msg,'(a,i1,a,i4,a,g12.5)')&
435 &    ' - Logarithimc mesh: r(i)=-AA*ln(1-(i-1)/n), n=size=',Rmesh%mesh_size,', AA=',Rmesh%rstep
436 
437  CASE (RMESH_NL)
438    write(msg,'(a,i1,a,i4,a,g12.5)')&
439 &    ' - Non-linear mesh: r(i)=-AA*i/(n-i), n=size=',Rmesh%mesh_size,', AA=',Rmesh%rstep
440 
441  CASE DEFAULT
442    msg = ' Unknown mesh type! Action : check your pseudopotential or input file.'
443    LIBPAW_ERROR(msg)
444  END SELECT
445 
446  call wrtout(my_unt,msg,my_mode)
447 
448  if (my_prtvol>1) then
449    write(msg,'(a,i4)')' Mesh size for integrals = ',Rmesh%int_meshsz
450    call wrtout(my_unt,msg,my_mode)
451    write(msg,'(a,g12.5)')' rmax=rad(mesh_size)     = ',Rmesh%rmax
452    call wrtout(my_unt,msg,my_mode)
453    write(msg,'(a,g12.5)')' Value of stepint        = ',Rmesh%stepint
454    call wrtout(my_unt,msg,my_mode)
455  end if
456 
457 end subroutine pawrad_print

m_pawrad/pawrad_type [ Types ]

[ Top ] [ m_pawrad ] [ Types ]

NAME

 pawrad_type

FUNCTION

 For PAW, RADial mesh discretization and related data

SOURCE

 83  type, public :: pawrad_type
 84 
 85 !Integer scalars
 86 
 87   integer :: int_meshsz=0
 88    ! Mesh size used in integrals computation
 89    ! Integrals will be computed up to r(int_meshsz)
 90 
 91   integer :: mesh_size=0
 92    ! Dimension of radial mesh
 93 
 94   integer :: mesh_type=-1
 95    ! Type of mesh
 96    !     1=regular grid: r(i)=(i-1)*AA
 97    !     2=logarithmic grid: r(i)=AA*(exp[BB*(i-1)]-1)
 98    !     3=logarithmic grid: r(i>1)=AA*exp[BB*(i-1)] and r(1)=0
 99    !     4=logarithmic grid: r(i)=-AA*ln[1-BB*(i-1)] with BB=1/n
100 
101 !Real (real(dp)) scalars
102 
103   real(dp) :: lstep=zero
104    ! Exponential step of the mesh (BB parameter above)
105    ! Defined only if mesh type is logarithmic
106 
107   real(dp) :: rmax=zero
108    ! Max. value of r = rad(mesh_size)
109 
110   real(dp) :: rstep=zero
111    ! Radial step of the mesh (AA parameter above)
112 
113   real(dp) :: stepint=zero
114    ! Radial step used to convert any function from the
115    ! present grid onto a regular grid in order to
116    ! integrate it using trapeze method
117 
118 !Real (real(dp)) arrays
119 
120   real(dp), allocatable :: rad(:)
121    ! rad(mesh_size)
122    ! Coordinates of all the points of the mesh
123 
124   real(dp), allocatable :: radfact(:)
125    ! radfact(mesh_size)
126    ! Factor used to compute radial integrals
127    ! Before being integrated on the present mesh,
128    ! any function is multiplied by this factor
129 
130   real(dp), allocatable :: simfact(:)
131    ! simfact(mesh_size)
132    ! Factor used to compute radial integrals by the a Simpson scheme
133    ! Integral[f] = Sum_i [simfact(i)*f(i)]
134 
135  end type pawrad_type

m_pawrad/poisson [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 poisson

FUNCTION

  Solve poisson equation for angularly dependent charge
  distribution of angular momentum l
  Densities and potentials are given on a (generalized) radial grid

INPUTS

  den(:)= electron density * (4*pi*r**2) appropriate for l
  ll= l quantum number
  radmesh <type(pawrad_type)>=data containing radial grid information
  [screened_sr_separation]= --optional-- separation for screened short-range kernel
                            no screening by default

OUTPUT

  [qq]= --optional-- lth moment of the charge; not compatible with screened Coulomb interaction
  rv(:)= electrostatic potential * r in (Hartree*Bohr) units
          where v(r)=\frac{1}{2l+1}(\frac{int[(r''^(l+2))g(r'')dr'']} {r^(l+1)}
                                   +(r^l) int[r''^(1-l)g(r'')dr''])

SOURCE

1164 subroutine poisson(den,ll,radmesh,rv,screened_sr_separation,qq)
1165 
1166 !Arguments ---------------------------------------------
1167 !scalars
1168  integer,intent(in) :: ll
1169  real(dp),intent(out),optional :: qq
1170  real(dp),intent(in),optional :: screened_sr_separation
1171  type(pawrad_type),intent(in) :: radmesh
1172 !arrays
1173  real(dp),intent(in) :: den(:)
1174  real(dp),intent(out) :: rv(:)
1175 
1176 !Local variables ---------------------------------------
1177 !scalars
1178  integer :: ir,jr,mesh_size,mm,nn
1179  logical :: use_numerov,use_screened
1180  real(dp) :: angm,hh,intg,qq_,ri,rj,rr,sr_omega
1181 !arrays
1182  real(dp) :: ee(4)
1183  real(dp),allocatable :: aa(:),bb(:),cc(:),dd(:),radl(:),radl1(:)
1184 
1185 ! ***************************************************************************
1186 
1187  mesh_size=size(den)
1188  if (size(rv)/=mesh_size.or.mesh_size>radmesh%mesh_size) then
1189    LIBPAW_BUG('wrong sizes!')
1190  end if
1191 
1192  use_numerov=(radmesh%mesh_type==1)
1193 
1194  use_screened=.false.;sr_omega=zero
1195  if (present(screened_sr_separation)) then
1196    sr_omega=screened_sr_separation
1197    use_screened=(sr_omega>tol8)
1198 !  Numerov method not coded for screened Coulomb interaction
1199    if (use_numerov.and.use_screened) use_numerov=.false.
1200  end if
1201 
1202 !==============================================
1203 !UNIFORM GRID - NUMEROV ALGORITHM
1204 !==============================================
1205  if (use_numerov) then
1206    hh=radmesh%rstep
1207    nn=radmesh%int_meshsz-1
1208    LIBPAW_ALLOCATE(aa,(nn))
1209    LIBPAW_ALLOCATE(bb,(nn))
1210    LIBPAW_ALLOCATE(cc,(nn+1))
1211    do ir=1,nn
1212      aa(ir)=two*hh*den(ir+1)/(ir)
1213      bb(ir)=den(ir+1)*((ir*hh)**ll)
1214    end do
1215    cc(1)=zero
1216    cc(2:nn+1)=bb(1:nn)
1217    call simp_gen(qq_,cc,radmesh)
1218    qq_=qq_/dble(2*ll+1)
1219    rv(1)=aa(1)+0.1_dp*aa(2)
1220    do ir=2,nn-1
1221      rv(ir)=aa(ir)+0.1_dp*(aa(ir+1)+aa(ir-1))
1222    end do
1223    rv(nn)=aa(nn)+0.1_dp*aa(nn-1)
1224    angm=dble(ll*(ll+1))
1225    rr=(nn+1)*hh
1226    rv(nn)=rv(nn)+(2.4_dp-0.2_dp*angm/((nn+1)**2))*qq_/(rr**ll)
1227    do ir=1,nn
1228      aa(ir)=angm/(ir*ir)
1229      bb(ir)=2.4_dp+aa(ir)
1230    end do
1231    do ir=1,nn-1
1232      cc(ir)=-1.2_dp+0.1_dp*aa(ir+1)
1233    end do
1234    do ir=nn,2,-1
1235      aa(ir)=-1.2_dp+0.1_dp*aa(ir-1)
1236    end do
1237    if (nn.eq.1) then
1238      rv(2)=rv(1)/bb(1)
1239      rv(1)=zero
1240    else
1241      do ir=2,nn
1242        bb(ir)=bb(ir)-aa(ir)*cc(ir-1)/bb(ir-1)
1243      end do
1244      rv(1)=rv(1)/bb(1)
1245      do ir=2,nn
1246        rv(ir)=(rv(ir)-aa(ir)*rv(ir-1))/bb(ir)
1247      end do
1248      do ir=nn-1,1,-1
1249        rv(ir)=rv(ir)-cc(ir)*rv(ir+1)/bb(ir)
1250      end do
1251      do ir=nn+1,2,-1
1252        rv(ir)=rv(ir-1)
1253      end do
1254      rv(1)=zero
1255      if (nn+1<mesh_size) rv(nn+2:mesh_size)=zero
1256    end if
1257    rv(:)=half*rv(:)
1258    if (present(qq)) qq=qq_
1259    LIBPAW_DEALLOCATE(aa)
1260    LIBPAW_DEALLOCATE(bb)
1261    LIBPAW_DEALLOCATE(cc)
1262 
1263 !  ==============================================
1264 !  ANY OTHER GRID - SIMPSON ALGORITHM
1265 !  ==============================================
1266  else
1267    nn=mesh_size;hh=third*radmesh%stepint
1268    do while (abs(den(nn))<tol16.and.nn>radmesh%int_meshsz)
1269      nn=nn-1
1270    end do
1271    mm=nn;if (radmesh%mesh_type==3) mm=mm-1
1272    LIBPAW_ALLOCATE(aa,(nn))
1273    LIBPAW_ALLOCATE(bb,(nn))
1274    LIBPAW_ALLOCATE(cc,(nn))
1275    LIBPAW_ALLOCATE(dd,(nn))
1276 
1277    if (.not.use_screened) then
1278 
1279 !    Standard Coulomb integral
1280      LIBPAW_ALLOCATE(radl,(nn))
1281      LIBPAW_ALLOCATE(radl1,(nn))
1282      do jr=nn,2,-1
1283        ir=nn-jr+1
1284        radl(jr) =radmesh%rad(jr)**ll
1285        radl1(jr)=radmesh%rad(jr)*radl(jr)
1286        aa(ir)=den(jr)*radmesh%radfact(jr)*radl(jr)
1287        bb(ir)=den(jr)*radmesh%radfact(jr)/radl1(jr)
1288      end do
1289      radl(1)=zero;radl1(1)=zero
1290      ee(2)=aa(nn-1);ee(3)=aa(nn-2);ee(4)=aa(nn-3)
1291      call pawrad_deducer0(ee,4,radmesh)
1292      aa(nn)=ee(1)
1293      ee(2)=bb(nn-1);ee(3)=bb(nn-2);ee(4)=bb(nn-3)
1294      call pawrad_deducer0(ee,4,radmesh)
1295      bb(nn)=ee(1)
1296      cc(1)=zero;dd(1)=zero
1297      do ir=3,mm,2
1298        cc(ir)  =cc(ir-2)+hh*(aa(ir-2)+four*aa(ir-1)+aa(ir))
1299        cc(ir-1)=cc(ir-2)+hh*(1.25_dp*aa(ir-2)+two*aa(ir-1)-quarter*aa(ir))
1300        dd(ir)  =dd(ir-2)+hh*(bb(ir-2)+four*bb(ir-1)+bb(ir))
1301        dd(ir-1)=dd(ir-2)+hh*(1.25_dp*bb(ir-2)+two*bb(ir-1)-quarter*bb(ir))
1302      end do
1303      if (mod(mm,2)==0) then
1304 !      cc(mm)=cc(mm-2)+hh*(aa(mm-2)+four*aa(mm-1)+aa(mm))
1305 !      dd(mm)=dd(mm-2)+hh*(bb(mm-2)+four*bb(mm-1)+bb(mm))
1306        cc(mm)=cc(mm-1)+hh*(1.25_dp*aa(mm-2)+two*aa(mm-1)-quarter*aa(mm))
1307        dd(mm)=dd(mm-1)+hh*(1.25_dp*bb(mm-2)+two*bb(mm-1)-quarter*bb(mm))
1308      end if
1309      if (mm<nn) then
1310        cc(nn)=cc(mm)+half*(aa(mm)+aa(nn))*(radmesh%rad(1+nn-mm)-radmesh%rad(1))
1311        dd(nn)=dd(mm)+half*(bb(mm)+bb(nn))*(radmesh%rad(1+nn-mm)-radmesh%rad(1))
1312      end if
1313      rv(1)=zero
1314      do ir=2,nn
1315        jr=nn-ir+1
1316        rv(ir)=(dd(jr)*radl1(ir)+(cc(nn)-cc(jr))/radl(ir))/(two*ll+one)
1317      end do
1318      if (nn<mesh_size) rv(nn+1:mesh_size)=rv(nn)
1319      if (present(qq)) qq=cc(nn)/(two*ll+one)
1320      LIBPAW_DEALLOCATE(radl)
1321      LIBPAW_DEALLOCATE(radl1)
1322    else
1323 
1324 !    Short-range screened Coulomb integral
1325      rv(1)=zero
1326      do ir=2,nn
1327        ri=sr_omega*radmesh%rad(ir)
1328        do jr=2,nn
1329          rj=sr_omega*radmesh%rad(jr)
1330          aa(jr)=den(jr)*radmesh%radfact(jr)*sr_omega*screened_coul_kernel(ll,ri,rj)
1331        end do
1332        call pawrad_deducer0(aa(1:4),4,radmesh)
1333        intg=zero
1334 !      Compute the integral in 2 parts because the function is not differentiable at r(ir)
1335 !      Integral from zero to r(ir)
1336        if (ir>2) then
1337          do jr=ir-2,1,-2
1338            intg=intg+hh*(aa(jr)+four*aa(jr+1)+aa(jr+2))
1339          end do
1340          if (mod(ir,2)==0) intg=intg+hh*(-quarter*aa(1)+two*aa(2)+1.25_dp*aa(3))
1341        else if (ir==2) then
1342         if (nn >2) intg=intg+hh*(+1.25_dp*aa(1)+two*aa(2)-quarter*aa(3))
1343         if (nn==2) intg=intg+(aa(1)+aa(2))*hh*half
1344        end if
1345        if (mm<nn) intg=intg+half*(aa(1+nn-mm)+aa(nn))*(radmesh%rad(1+nn-mm)-radmesh%rad(1))
1346 !      Integral from r(ir) to rmax
1347        if (ir<nn-2) then
1348          do jr=ir+2,nn,2
1349            intg=intg+hh*(aa(jr-2)+four*aa(jr-1)+aa(jr))
1350          end do
1351          if (mod(nn-ir,2)==1) then
1352            if (ir<=nn-4) then
1353              !Use a high-order formula because points are spaced
1354              intg=intg+hh*(251._dp*aa(nn)+646._dp*aa(nn-1)-264._dp*aa(nn-2) &
1355 &                         +106._dp*aa(nn-3)-19._dp*aa(nn-4))/240._dp
1356            else
1357              intg=intg+hh*(1.25_dp*aa(nn)+two*aa(nn-1)-quarter*aa(nn-2))
1358            endif
1359          end if
1360        else if (ir==nn-1) then
1361          intg=intg+(aa(nn-1)+aa(nn))*hh*half
1362        end if
1363        rv(ir)=intg/(two*ll+one)*radmesh%rad(ir)
1364      end do
1365      if (nn<mesh_size) rv(nn+1:mesh_size)=rv(nn)
1366      if (present(qq)) qq=zero ! Not relevant
1367 
1368    end if
1369    LIBPAW_DEALLOCATE(aa)
1370    LIBPAW_DEALLOCATE(bb)
1371    LIBPAW_DEALLOCATE(cc)
1372    LIBPAW_DEALLOCATE(dd)
1373 
1374  end if
1375 
1376 end subroutine poisson

m_pawrad/screened_coul_kernel [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 screened_coul_kernel

FUNCTION

  Evaluates the kernel function used to compute the integral
  of a screened Coulomb potential (with erfc function)
  See Angyan, Gerber, Marsman, J. Phys. A: Math. Gen. 39, 8613 (2006) [[cite:Angyan2006]]

INPUTS

  [formula]=optional; used to force formula (1=full; 2=dev. near r2=0; 3=dev near r1*r2=0)
  order= order of the function (typically l quantum number)
  r1,r2=input arguments

OUTPUT

  screened_coul_kernel=output radial function

SOURCE

1463 function screened_coul_kernel(order,r1,r2,formula)
1464 
1465 !Arguments ------------------------------------
1466 !scalars
1467  integer,intent(in) :: order
1468  integer,optional :: formula
1469  real(dp),intent(in) :: r1,r2
1470  real(dp) :: screened_coul_kernel
1471 !Local variables-------------------------------
1472  integer :: formula_
1473  real(dp) :: difexp,erfcp,erfcm,f0,f1,f2,f3,f4,f5,f6,hh,sqrtpi,sumexp,xx,xy,yy
1474  character(len=100) :: msg
1475 
1476 !******************************************************************
1477 
1478  if (order>6) then
1479    msg='PAW screened exchange not coded for l>2!'
1480    LIBPAW_ERROR(msg)
1481  end if
1482 
1483 !Use max and min of arguments
1484  xx=max(r1,r2) ; yy=min(r1,r2)
1485 
1486 !Unscreened Coulomb interaction for very small (or negative) arguments
1487  if (xx<tol8) then
1488   screened_coul_kernel=yy**order/xx**(order+1) ; return
1489  end if
1490 
1491 !Choice of formula
1492 !Empirical criterion, inspired by J. Phys. A 39, pp8624 [[cite:Angyan2006]] and adjusted
1493  formula_=1;if (xx<0.25_dp.and.yy<0.25_dp) formula_=2
1494  if (present(formula)) formula_=formula
1495  select case (formula_)
1496 
1497 !Full formula
1498 !J. Phys. A 39, 8613 (2006) - Eq. (21), (22), (24) [[cite:Angyan2006]]
1499 !   Note: typo in the paper: in eq (22), the sum begins at p=0
1500 !------------------------------------------------------------------
1501  case(1)
1502    xy=xx*yy ; sqrtpi=sqrt(pi)
1503    sumexp=exp(-(xx+yy)**2)+exp(-(xx-yy)**2)
1504    difexp=exp(-(xx+yy)**2)-exp(-(xx-yy)**2)
1505    erfcp=paw_derfc(xx+yy) ; erfcm=paw_derfc(xx-yy)
1506    if (order==0) then
1507      f0=-difexp/(two*sqrtpi*xy)
1508      hh=((xx+yy)*erfcp-(xx-yy)*erfcm)/(two*xy)
1509      screened_coul_kernel = hh + f0
1510    else if(order==1) then
1511      f0=-difexp/(two*sqrtpi*xy)
1512      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1513      hh=((xx**3+yy**3)*erfcp-(xx**3-yy**3)*erfcm)/(two*xy**2)
1514      screened_coul_kernel = hh + f1 + f0*(xx**2+yy**2)/xy
1515    else if (order==2) then
1516      f0=-difexp/(two*sqrtpi*xy)
1517      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1518      f2= -((four*xy**2+three)*difexp+6._dp*xy*sumexp)/(sqrtpi*(two*xy)**3)
1519      hh=((xx**5+yy**5)*erfcp-(xx**5-yy**5)*erfcm)/(two*xy**3)
1520      screened_coul_kernel = hh + f2 + f1*(xx**2+yy**2)/xy + f0*(xx**4+yy**4)/xy**2
1521    else if (order==3) then
1522      f0=-difexp/(two*sqrtpi*xy)
1523      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1524      f2= -((four*xy**2+three)*difexp+6._dp*xy*sumexp)/(sqrtpi*(two*xy)**3)
1525      f3=((24._dp*xy**2+15._dp)*difexp+(8._dp*xy**3+30._dp*xy)*sumexp)/(sqrtpi*(two*xy)**4)
1526      hh=((xx**7+yy**7)*erfcp-(xx**7-yy**7)*erfcm)/(two*xy**4)
1527      screened_coul_kernel = hh + f3 + f2*(xx**2+yy**2)/xy    + f1*(xx**4+yy**4)/xy**2 &
1528 &                                   + f0*(xx**6+yy**6)/xy**3
1529    else if (order==4) then
1530      f0=-difexp/(two*sqrtpi*xy)
1531      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1532      f2= -((four*xy**2+three)*difexp+6._dp*xy*sumexp)/(sqrtpi*(two*xy)**3)
1533      f3=((24._dp*xy**2+15._dp)*difexp+(8._dp*xy**3+30._dp*xy)*sumexp)/(sqrtpi*(two*xy)**4)
1534      f4=-((16._dp*xy**4+180._dp*xy**2+105._dp)*difexp &
1535 &        +(80._dp*xy**3+210._dp*xy)*sumexp)/(sqrtpi*(two*xy)**5)
1536      hh=((xx**9+yy**9)*erfcp-(xx**9-yy**9)*erfcm)/(two*xy**5)
1537      screened_coul_kernel = hh + f4 + f3*(xx**2+yy**2)/xy    + f2*(xx**4+yy**4)/xy**2 &
1538 &                                   + f1*(xx**6+yy**6)/xy**3 + f0*(xx**8+yy**8)/xy**4
1539    else if (order==5) then
1540      f0=-difexp/(two*sqrtpi*xy)
1541      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1542      f2= -((four*xy**2+three)*difexp+6._dp*xy*sumexp)/(sqrtpi*(two*xy)**3)
1543      f3=((24._dp*xy**2+15._dp)*difexp+(8._dp*xy**3+30._dp*xy)*sumexp)/(sqrtpi*(two*xy)**4)
1544      f4=-((16._dp*xy**4+180._dp*xy**2+105._dp)*difexp &
1545 &        +(80._dp*xy**3+210._dp*xy)*sumexp)/(sqrtpi*(two*xy)**5)
1546      f5=((240._dp*xy**4+1680._dp*xy**2+945._dp)*difexp &
1547 &       +(32._dp*xy**5+840._dp*xy**3+1890._dp*xy)*sumexp)/(sqrtpi*(two*xy)**6)
1548      hh=((xx**11+yy**11)*erfcp-(xx**11-yy**11)*erfcm)/(two*xy**6)
1549      screened_coul_kernel = hh + f5 + f4*(xx**2+yy**2)  /xy    + f3*(xx**4+yy**4)/xy**2 &
1550 &                                   + f2*(xx**6+yy**6)  /xy**3 + f1*(xx**8+yy**8)/xy**4 &
1551 &                                   + f0*(xx**10+yy**10)/xy**5
1552    else if (order==6) then
1553      f0=-difexp/(two*sqrtpi*xy)
1554      f1=(difexp+two*xy*sumexp)/(sqrtpi*(two*xy)**2)
1555      f2= -((four*xy**2+three)*difexp+6._dp*xy*sumexp)/(sqrtpi*(two*xy)**3)
1556      f3=((24._dp*xy**2+15._dp)*difexp+(8._dp*xy**3+30._dp*xy)*sumexp)/(sqrtpi*(two*xy)**4)
1557      f4=-((16._dp*xy**4+180._dp*xy**2+105._dp)*difexp &
1558 &        +(80._dp*xy**3+210._dp*xy)*sumexp)/(sqrtpi*(two*xy)**5)
1559      f5=((240._dp*xy**4+1680._dp*xy**2+945._dp)*difexp &
1560 &       +(32._dp*xy**5+840._dp*xy**3+1890._dp*xy)*sumexp)/(sqrtpi*(two*xy)**6)
1561      f6=-((64._dp*xy**6+3360._dp*xy**4+18900._dp*xy**2+10395._dp)*difexp+ &
1562 &         (672._dp*xy**5+10080._dp*xy**3+20790._dp*xy)*sumexp)/(sqrtpi*(two*xy)**7)
1563      hh=((xx**13+yy**13)*erfcp-(xx**13-yy**13)*erfcm)/(two*xy**7)
1564      screened_coul_kernel = hh + f6 + f5*(xx**2+yy**2)  /xy    + f4*(xx**4+yy**4)  /xy**2 &
1565 &                                   + f3*(xx**6+yy**6)  /xy**3 + f1*(xx**8+yy**8)  /xy**4 &
1566 &                                   + f1*(xx**10+yy**10)/xy**5 + f0*(xx**12+yy**12)/xy**6
1567    end if
1568 
1569 !Development for yy->0
1570 !J. Phys. A 39, 8613 (2006) - Eq. (28), (29), (30) [[cite:Angyan2006]]
1571 !------------------------------------------------------------------
1572  case(2)
1573    sqrtpi=sqrt(pi)
1574    if (order==0) then
1575      screened_coul_kernel = paw_derfc(xx)/xx + exp(-xx**2)/sqrtpi * &
1576 &            (two/three              *yy**2 &
1577 &           +(two*xx**2-three)/15._dp*yy**4)
1578    else if(order==1) then
1579      screened_coul_kernel = paw_derfc(xx)*yy/xx**2 + exp(-xx**2)/sqrtpi * &
1580 &            (two/xx                         *yy &
1581 &            +four*xx/5._dp                  *yy**3 &
1582 &            +two*xx*(two*xx**2-5._dp)/35._dp*yy**5)
1583    else if (order==2) then
1584      screened_coul_kernel = paw_derfc(xx)*yy**2/xx**3 + exp(-xx**2)/sqrtpi * &
1585 &            (two*(two*xx**2+three)/(three*xx**2) *yy**2 &
1586 &            +8._dp*xx**2/21._dp                  *yy**4 &
1587 &            +four*xx**2*(two*xx**2-7._dp)/189._dp*yy**6)
1588    else if (order==3) then
1589      screened_coul_kernel = paw_derfc(xx)*yy**3/xx**4 + exp(-xx**2)/sqrtpi * &
1590 &            (two*(four*xx**4+10._dp*xx**2+15._dp)/(15._dp*xx**3)*yy**3 &
1591 &            +16._dp*xx**3/135._dp                               *yy**5 &
1592 &            +8._dp*xx**3*(two*xx**2-9._dp)/1485._dp             *yy**7)
1593    else if (order==4) then
1594      screened_coul_kernel = paw_derfc(xx)*yy**4/xx**5 + exp(-xx**2)/sqrtpi * &
1595 &            (two*(8._dp*xx**6+28._dp*xx**4+70._dp*xx**2+105._dp)/(105._dp*xx**4)*yy**4 &
1596 &            +32._dp*xx**4/1155._dp                                              *yy**6 &
1597 &            +16._dp*xx**4*(two*xx**2-11._dp)/15015._dp                          *yy**8)
1598    else if (order==5) then
1599      screened_coul_kernel = paw_derfc(xx)*yy**5/xx**6 + exp(-xx**2)/sqrtpi * &
1600 &            (two*(16._dp*xx**8+72._dp*xx**6+252._dp*xx**4+630._dp*xx**2+945._dp)/(945._dp*xx**5)*yy**5 &
1601 &            +64._dp*xx**5/12285._dp                                                             *yy**7 &
1602 &            +32._dp*xx**5*(two*xx**2-13._dp)/184275._dp                                         *yy**9)
1603    else if (order==6) then
1604      screened_coul_kernel = paw_derfc(xx)*yy**6/xx**7 + exp(-xx**2)/sqrtpi * &
1605 &            (two*(32._dp*xx**10+176._dp*xx**8+792._dp*xx**6+2772._dp*xx**4+6930._dp*xx**2+10395._dp)/(10395._dp*xx**6)*yy**6 &
1606 &            +128._dp*xx**6/155925._dp                                                                                 *yy**8 &
1607 &            +64._dp*xx**6*(two*xx**2-15._dp)/2650725._dp                                                              *yy**10)
1608    end if
1609 
1610 !Development for xx*yy->0
1611 !J. Phys. A 39, 8613 (2006) - Eq. (24), (26) [[cite:Angyan2006]]
1612 !   Note: typo in the paper: (2n+3)! should be (2n+3)!!
1613 !------------------------------------------------------------------
1614  case(3)
1615    xy=xx*yy ; sqrtpi=sqrt(pi)
1616    sumexp=exp(-(xx**2+yy**2))
1617    erfcp=paw_derfc(xx+yy) ; erfcm=paw_derfc(xx-yy)
1618    if (order==0) then
1619      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1620      hh=((xx+yy)*erfcp-(xx-yy)*erfcm)/(two*xy)
1621      screened_coul_kernel = hh + f0
1622    else if(order==1) then
1623      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1624      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1625      hh=((xx**3+yy**3)*erfcp-(xx**3-yy**3)*erfcm)/(two*xy**2)
1626      screened_coul_kernel = hh + f1 + f0*(xx**2+yy**2)/xy
1627    else if (order==2) then
1628      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1629      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1630      f2 = 8._dp  *xy**2*(7._dp +two*xy**2)/(105._dp    *sqrtpi)*sumexp
1631      hh=((xx**5+yy**5)*erfcp-(xx**5-yy**5)*erfcm)/(two*xy**3)
1632      screened_coul_kernel = hh + f2 + f1*(xx**2+yy**2)/xy + f0*(xx**4+yy**4)/xy**2
1633    else if (order==3) then
1634      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1635      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1636      f2 = 8._dp  *xy**2*(7._dp +two*xy**2)/(105._dp    *sqrtpi)*sumexp
1637      f3 = 16._dp *xy**2*(9._dp +two*xy**2)/(945._dp    *sqrtpi)*sumexp
1638      hh=((xx**7+yy**7)*erfcp-(xx**7-yy**7)*erfcm)/(two*xy**4)
1639      screened_coul_kernel = hh + f3 + f2*(xx**2+yy**2)/xy    + f1*(xx**4+yy**4)/xy**2 &
1640 &                                   + f0*(xx**6+yy**6)/xy**3
1641    else if (order==4) then
1642      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1643      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1644      f2 = 8._dp  *xy**2*(7._dp +two*xy**2)/(105._dp    *sqrtpi)*sumexp
1645      f3 = 16._dp *xy**2*(9._dp +two*xy**2)/(945._dp    *sqrtpi)*sumexp
1646      f4 = 32._dp *xy**2*(11._dp+two*xy**2)/(10395._dp  *sqrtpi)*sumexp
1647      hh=((xx**9+yy**9)*erfcp-(xx**9-yy**9)*erfcm)/(two*xy**5)
1648      screened_coul_kernel = hh + f4 + f3*(xx**2+yy**2)/xy    + f2*(xx**4+yy**4)/xy**2 &
1649 &                                   + f1*(xx**6+yy**6)/xy**3 + f0*(xx**8+yy**8)/xy**4
1650    else if (order==5) then
1651      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1652      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1653      f2 = 8._dp  *xy**2*(7._dp +two*xy**2)/(105._dp    *sqrtpi)*sumexp
1654      f3 = 16._dp *xy**2*(9._dp +two*xy**2)/(945._dp    *sqrtpi)*sumexp
1655      f4 = 32._dp *xy**2*(11._dp+two*xy**2)/(10395._dp  *sqrtpi)*sumexp
1656      f5 = 64._dp *xy**2*(13._dp+two*xy**2)/(135135._dp *sqrtpi)*sumexp
1657      hh=((xx**11+yy**11)*erfcp-(xx**11-yy**11)*erfcm)/(two*xy**6)
1658      screened_coul_kernel = hh + f5 + f4*(xx**2+yy**2)  /xy    + f3*(xx**4+yy**4)/xy**2 &
1659 &                                   + f2*(xx**6+yy**6)  /xy**3 + f1*(xx**8+yy**8)/xy**4 &
1660 &                                   + f0*(xx**10+yy**10)/xy**5
1661    else if (order==6) then
1662      f0 = two          *(three +two*xy**2)/(three      *sqrtpi)*sumexp
1663      f1 = four   *xy   *(5._dp +two*xy**2)/(15._dp     *sqrtpi)*sumexp
1664      f2 = 8._dp  *xy**2*(7._dp +two*xy**2)/(105._dp    *sqrtpi)*sumexp
1665      f3 = 16._dp *xy**2*(9._dp +two*xy**2)/(945._dp    *sqrtpi)*sumexp
1666      f4 = 32._dp *xy**2*(11._dp+two*xy**2)/(10395._dp  *sqrtpi)*sumexp
1667      f5 = 64._dp *xy**2*(13._dp+two*xy**2)/(135135._dp *sqrtpi)*sumexp
1668      f6 = 128._dp*xy**2*(15._dp+two*xy**2)/(1027025._dp*sqrtpi)*sumexp
1669      hh=((xx**13+yy**13)*erfcp-(xx**13-yy**13)*erfcm)/(two*xy**7)
1670      screened_coul_kernel = hh + f6 + f5*(xx**2+yy**2)  /xy    + f4*(xx**4+yy**4)  /xy**2 &
1671 &                                   + f3*(xx**6+yy**6)  /xy**3 + f1*(xx**8+yy**8)  /xy**4 &
1672 &                                   + f1*(xx**10+yy**10)/xy**5 + f0*(xx**12+yy**12)/xy**6
1673    end if
1674 
1675  end select
1676 
1677 end function screened_coul_kernel

m_pawrad/simp_gen [ Functions ]

[ Top ] [ m_pawrad ] [ Functions ]

NAME

 simp_gen

FUNCTION

 Do integral on a given (generalized) grid using Simpson rule

INPUTS

  radmesh <type(pawrad_type)>=data containing radial grid information
  func(:)=integrand values
  r_for_intg=upper boundary for (future) integration over the radial grid
            (can be negative for an integration over the whole grid)

OUTPUT

  intg=resulting integral by Simpson rule

NOTES

  Possible mesh types (radmesh%mesh_type)
   mesh_type=1 (regular grid): rad(i)=(i-1)*AA
   mesh_type=2 (logari. grid): rad(i)=AA*(exp[BB*(i-1)]-1)
   mesh_type=3 (logari. grid): rad(i>1)=AA*exp[BB*(i-2)] and rad(1)=0
   mesh_type=4 (logari. grid): rad(i)=-AA*ln[1-BB*(i-1)] with BB=1/n
   mesh_type=5 ( grid): rad(i)=AA*i/(n-i)

SOURCE

815 subroutine simp_gen(intg,func,radmesh,r_for_intg)
816 
817 #if defined HAVE_AVX_SAFE_MODE
818 !DEC$ NOOPTIMIZE
819 #endif
820 
821 !Arguments ------------------------------------
822 !scalars
823  real(dp),intent(out) :: intg
824  real(dp),intent(in),optional :: r_for_intg
825  type(pawrad_type),intent(in) :: radmesh
826 !arrays
827  real(dp),intent(in) :: func(:)
828 
829 !Local variables-------------------------------
830 !scalars
831  integer :: ii,int_meshsz,ir,ir_last,isim,nn
832  real(dp) :: hh,resid,simp
833  real(dp),allocatable :: simfact(:)
834  character(len=500) :: msg
835 
836 ! *************************************************************************
837 
838  if (present(r_for_intg)) then
839    if (r_for_intg>0.d0) then
840      ir=min(pawrad_ifromr(radmesh,r_for_intg),radmesh%mesh_size)
841      if (ir<radmesh%mesh_size) then
842        if (abs(radmesh%rad(ir+1)-r_for_intg)<abs(radmesh%rad(ir)-r_for_intg)) ir=ir+1
843      end if
844      if (ir>1) then
845        if (abs(radmesh%rad(ir-1)-r_for_intg)<abs(radmesh%rad(ir)-r_for_intg)) ir=ir-1
846      end if
847      int_meshsz=ir
848    else
849      int_meshsz=radmesh%mesh_size
850    end if
851    if (int_meshsz>radmesh%mesh_size.or.int_meshsz>size(func)) then
852      write(msg,'(3(a,i4))')"int_meshsz= ",int_meshsz," > mesh_size=",radmesh%mesh_size,&
853 &                          ", size(func)=",size(func)
854      LIBPAW_BUG(msg)
855    end if
856    isim=3; if (radmesh%mesh_type==3)isim=4
857    LIBPAW_ALLOCATE(simfact,(radmesh%mesh_size))
858    hh=radmesh%stepint/3.d0
859    simfact(int_meshsz)=hh*radmesh%radfact(int_meshsz)
860    simfact(1:isim-2)=zero
861    ir_last=1
862    do ir=int_meshsz,isim,-2
863      simfact(ir-1)=4.d0*hh*radmesh%radfact(ir-1)
864      simfact(ir-2)=2.d0*hh*radmesh%radfact(ir-2)
865      ir_last=ir-2
866    end do
867    simfact(ir_last)=half*simfact(ir_last)
868    if (int_meshsz<radmesh%mesh_size) simfact(int_meshsz+1:radmesh%mesh_size)=zero
869 
870    nn=int_meshsz
871    simp=zero
872    do ii=1,nn
873      simp=simp+func(ii)*simfact(ii)
874    end do
875    LIBPAW_DEALLOCATE(simfact)
876 
877  else
878    if (radmesh%int_meshsz>size(func)) then
879      write(msg,'(2(a,i4))')"int_meshsz= ",int_meshsz," > size(func)=",size(func)
880      LIBPAW_BUG(msg)
881    end if
882    nn=radmesh%int_meshsz
883    simp=zero
884    do ii=1,nn
885      simp=simp+func(ii)*radmesh%simfact(ii)
886    end do
887  end if
888 
889  resid=zero
890  if (radmesh%mesh_type==3) then
891    resid=half*(func(2)+func(1))*(radmesh%rad(2)-radmesh%rad(1))
892    if (mod(nn,2)==1) resid=resid+radmesh%stepint/3.d0*(1.25d0*func(2)*radmesh%radfact(2) &
893 &   +2.d0*func(3)*radmesh%radfact(3)-0.25d0*func(4)*radmesh%radfact(4))
894  else if (mod(nn,2)==0) then
895    resid=radmesh%stepint/3.d0*(1.25d0*func(1)*radmesh%radfact(1)+2.d0*func(2)*radmesh%radfact(2) &
896 &   -0.25d0*func(3)*radmesh%radfact(3))
897  end if
898 
899  intg=simp+resid
900 
901 end subroutine simp_gen