LCOV - code coverage report
Current view: top level - src/62_poisson - m_cutoff_cylinder.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.6 % 126 94
Test Date: 2026-09-21 13:49:52 Functions: 87.5 % 8 7

            Line data    Source code
       1              : !!****m* ABINIT/m_cutoff_cylinder
       2              : !! NAME
       3              : !!  m_cutoff_cylinder
       4              : !!
       5              : !! FUNCTION
       6              : !!
       7              : !! SOURCE
       8              : 
       9              : #if defined HAVE_CONFIG_H
      10              : #include "config.h"
      11              : #endif
      12              : 
      13              : #include "abi_common.h"
      14              : 
      15              : module m_cutoff_cylinder
      16              : 
      17              :  use defs_basis
      18              :  use m_abicore
      19              :  use m_errors
      20              :  use m_xmpi
      21              :  use m_splines
      22              :  use m_sort
      23              : 
      24              :  use m_fstrings,        only : sjoin, itoa
      25              :  use m_geometry,        only : normv, metric
      26              :  use m_bessel,          only : CALJY0, CALJY1, CALCK0, CALCK1
      27              :  use m_numeric_tools,   only : OPERATOR(.x.), quadrature
      28              :  use m_paw_numeric,     only : paw_jbessel
      29              : 
      30              :  implicit none
      31              : 
      32              :  private
      33              : !!***
      34              : 
      35              :  public :: cutoff_cylinder, K0cos
      36              : 
      37              :  !integer,public,parameter :: CYLINDER_BEIGI = 1
      38              :  !integer,public,parameter :: CYLINDER_ROZZI = 2
      39              : !!***
      40              : 
      41              : ! private variables used for the integration needed by the cylindrical case.
      42              :  integer,save :: npts_,ntrial_,qopt_
      43              :  real(dp),save :: ha_,hb_,r0_
      44              :  real(dp),save :: qpg_perp_,qpg_para_,qpgx_,qpgy_
      45              :  real(dp),save :: zz_,xx_, rho_
      46              :  real(dp),save :: hcyl_,rcut_,accuracy_
      47              : 
      48              : CONTAINS
      49              : !!***
      50              : 
      51              : !----------------------------------------------------------------------
      52              : 
      53              : !!****f* ABINIT/cutoff_cylinder
      54              : !! NAME
      55              : !! cutoff_cylinder
      56              : !!
      57              : !! FUNCTION
      58              : !!  Calculate the Fourier components of an effective Coulomb interaction
      59              : !!  zeroed outside a finite cylindrical region. Two methods are implemented:
      60              : !!
      61              : !!   method==1: The interaction in the (say) x-y plane is truncated outside the Wigner-Seitz
      62              : !!              cell centered on the wire in the x-y plane. The interaction has infinite
      63              : !!              extent along the z axis and the Fourier transform is singular only at the Gamma point.
      64              : !!              Only orthorombic Bravais lattices are supported.
      65              : !!   method==2: The interaction is truncated outside a cylinder of radius rcut. The cylinder has finite
      66              : !!              extent along z. No singularity occurs.
      67              : !!
      68              : !! INPUTS
      69              : !!  boxcenter(3)= center of the wire in the x-y axis
      70              : !!  qpt(3)= q-point
      71              : !!  ng=number of G vectors
      72              : !!  gvec(3,ng)=G vectors in reduced coordinates
      73              : !!  rprimd(3,3)=dimensional real space primitive translations (bohr)
      74              : !!  method=1 for Beigi approach (infinite cylinder with interaction truncated outside the W-S cell)
      75              : !!         2 for Rozzi method (finite cylinder)
      76              : !!  comm=MPI communicator.
      77              : !!
      78              : !! OUTPUT
      79              : !!  vc_cut(ng)= Fourier components of the effective Coulomb interaction
      80              : !!
      81              : !! SOURCE
      82              : 
      83          112 : subroutine cutoff_cylinder(qpt, ng, gvec, rcut, hcyl, pdir, boxcenter, rprimd, vc_cut, method, comm)
      84              : 
      85              : !Arguments ------------------------------------
      86              : !scalars
      87              :  integer,intent(in) :: ng,method,comm
      88              :  real(dp),intent(in) :: rcut,hcyl
      89              : !arrays
      90              :  integer,intent(in) :: gvec(3,ng),pdir(3)
      91              :  real(dp),intent(in) :: boxcenter(3),qpt(3),rprimd(3,3)
      92              :  real(dp),intent(out) :: vc_cut(ng)
      93              : 
      94              : !Local variables-------------------------------
      95              : !scalars
      96              :  integer,parameter :: N0=1000
      97              :  integer :: ig,igs,ierr, my_rank, nproc
      98              :  real(dp) :: j0,j1,k0,k1,qpg2,qpg_xy,tmp
      99              :  real(dp) :: qpg_z,quad,rcut2,hcyl2,c1,c2,ucvol,SMALL
     100              :  logical :: q_is_zero
     101              :  character(len=500) :: msg
     102              : !arrays
     103              :  real(dp) :: qpg(3),b1(3),b2(3),b3(3),gmet(3,3),rmet(3,3),gprimd(3,3),qc(3),gcart(3)
     104              : !************************************************************************
     105              : 
     106              :  ABI_UNUSED(pdir)
     107              :  ABI_UNUSED(boxcenter)
     108              : 
     109              :  ! ===================================================
     110              :  ! === Setup for the quadrature of matrix elements ===
     111              :  ! ===================================================
     112          112 :  qopt_    =6         ! Quadrature method, see quadrature routine.
     113          112 :  ntrial_  =30        ! Max number of attempts.
     114          112 :  accuracy_=0.001     ! Fractional accuracy required.
     115          112 :  npts_    =6         ! Initial number of point (only for Gauss-Legendre method).
     116          112 :  SMALL    =tol4      ! Below this value (q+G)_i is treated as zero.
     117          112 :  rcut_    =rcut      ! Radial cutoff, used only if method==2
     118          112 :  hcyl_    =hcyl      ! Lenght of cylinder along z, only if method==2
     119              : 
     120              :  !write(msg,'(3a,2(a,i5,a),a,f8.5)')ch10,&
     121              :  ! ' cutoff_cylinder: Info on the quadrature method : ',ch10,&
     122              :  ! '  Quadrature scheme      = ',qopt_,ch10,&
     123              :  ! '  Max number of attempts = ',ntrial_,ch10,&
     124              :  ! '  Fractional accuracy    = ',accuracy_
     125              :  !call wrtout(std_out, msg)
     126              : 
     127              :  ! From reduced to Cartesian coordinates.
     128          112 :  call metric(gmet, gprimd, -1, rmet, rprimd, ucvol)
     129          448 :  b1(:) =two_pi*gprimd(:,1)
     130          448 :  b2(:) =two_pi*gprimd(:,2)
     131          448 :  b3(:) =two_pi*gprimd(:,3)
     132              : 
     133          448 :  qc = b1(:)*qpt(1) + b2(:)*qpt(2) + b3(:)*qpt(3)
     134              : 
     135          112 :  my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
     136              : 
     137              :  ! ================================================
     138              :  ! === Different approaches according to method ===
     139              :  ! ================================================
     140         1640 :  vc_cut = zero
     141              : 
     142          112 :  select case (method)
     143              : 
     144              :  case (1)
     145              :    ! Infinite cylinder, interaction is zeroed outside the Wigner-Seitz cell.
     146              :    ! NB: Beigi's expression holds only if the BZ is sampled only along z.
     147              :    !call wrtout(std_out, 'cutoff_cylinder: Using Beigi''s Infinite cylinder')
     148              : 
     149          318 :    if (ANY(qc(1:2) > SMALL)) then
     150              :      write(msg,'(5a)')&
     151            0 :       ' found q-points with non zero components in the X-Y plane. ',ch10,&
     152            0 :       ' This is not allowed, see Notes in cutoff_cylinder.F90. ',ch10,&
     153            0 :       ' ACTION: Modify the q-point sampling. '
     154            0 :      ABI_ERROR(msg)
     155              :    end if
     156              : 
     157              :    ! Check if Bravais lattice is orthorombic and parallel to the Cartesian versors.
     158              :    ! In this case the intersection of the WS cell with the x-y plane is a rectangle with -ha_<=x<=ha_ and -hb_<=y<=hb_
     159              :    if ((ANY(ABS(rprimd(2:3,  1)) > tol6)) .or. &
     160          954 :        (ANY(ABS(rprimd(1:3:2,2)) > tol6)) .or. &
     161              :        (ANY(ABS(rprimd(1:2,  3)) > tol6))) then
     162            0 :      ABI_ERROR('Bravais lattice should be orthorombic and parallel to the Cartesian versors')
     163              :    end if
     164              : 
     165          424 :    ha_ = half*NORM2(rprimd(:,1))
     166          424 :    hb_ = half*NORM2(rprimd(:,2))
     167          106 :    r0_ = MIN(ha_,hb_)/N0
     168              : 
     169              :    ! For each (q,G) pair evaluate the integral defining the Coulomb cutoff.
     170              :    ! NB: the code assumes that all q-vectors are non zero and q_xy/=0.
     171          106 :    igs=1
     172              :    ! Skip singularity at Gamma, it will be treated "by hand" in csigme.
     173          106 :    q_is_zero = (normv(qpt, gmet, 'G') < tol4)
     174              : 
     175          920 :    do ig=igs,ng
     176          814 :      if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
     177              : 
     178         3256 :      gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
     179         3256 :      qpg(:)=qc(:)+gcart(:)
     180          814 :      qpgx_=qpg(1); qpgy_=qpg(2); qpg_para_=ABS(qpg(3))
     181              :      !write(std_out,*)"qpgx_=",qpgx_, "qpgy_=",qpgy_, "qpg_para=",qpg_para_
     182              : 
     183              :      ! Avoid singularity in K_0{qpg_para_\rho) by using a small q along the periodic dimension.
     184          814 :      if (q_is_zero .and. qpg_para_ < tol6) qpg_para_ = tol6
     185              : 
     186              :      ! Calculate $ 2\int_{WS} dxdy K_0{qpg_para_\rho) cos(x.qpg_x + y.qpg_y) $
     187              :      ! where WS is the Wigner-Seitz cell.
     188          814 :      tmp=zero
     189              : 
     190              :      ! Difficult part, integrate on a small cirle of radius r0 using spherical coordinates
     191              :      !call quadrature(K0cos_dth_r0,zero,r0_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     192              :      !ABI_CHECK(ierr == 0, "Accuracy not reached")
     193              :      !write(std_out,'(i8,a,es14.6)')ig,' 1 ',quad
     194              :      !tmp=tmp+quad
     195              :      ! Add region with 0<=x<=r0 and y>=+-(SQRT(r0^2-x^2))since WS is rectangular
     196              :      !call quadrature(K0cos_dy_r0,zero,r0_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     197              :      !ABI_CHECK(ierr == 0, "Accuracy not reached")
     198              :      !write(std_out,'(i8,a,es14.6)')ig,' 2 ',quad
     199              :      !tmp=tmp+quad
     200              :      ! Get the in integral in the rectangle with x>=r0, should be the easiest but sometimes has problems to converge
     201              :      !call quadrature(K0cos_dy,r0_,ha_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     202              :      !ABI_CHECK(ierr == 0, "Accuracy not reached")
     203              :      !write(std_out,'(i8,a,es14.6)')ig,' 3 ',quad
     204              :      !
     205              :      ! More stable method: midpoint integration with Romberg extrapolation ===
     206          814 :      call quadrature(K0cos_dy,zero,ha_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     207              :      !write(std_out,'(i8,a,es14.6)')ig,' 3 ',quad
     208          814 :      ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature!")
     209              : 
     210              :      ! Store final result
     211              :      ! Factor two comes from the replacement WS -> (1,4) quadrant thanks to symmetries of the integrad.
     212          814 :      tmp = tmp+quad
     213          920 :      vc_cut(ig) = two*(tmp*two)
     214              :    end do ! ig
     215              : 
     216              :  case (2)
     217              :    ! Finite cylinder of length hcyl from Rozzi et al.
     218              :    ! TODO add check on hcyl value that should be smaller that 1/deltaq
     219            6 :    if (hcyl_ < zero) then
     220            0 :      write(msg,'(a,f8.4)')' Negative value for cylinder length hcyl_=',hcyl_
     221            0 :      ABI_BUG(msg)
     222              :    end if
     223              : 
     224            6 :    if (ABS(hcyl_) > tol12) then
     225              :      !write(std_out,'(2(a,f8.4))')' cutoff_cylinder: using finite cylinder of length= ',hcyl_,' rcut= ',rcut_
     226            6 :      hcyl2=hcyl_**2
     227            6 :      rcut2=rcut_**2
     228              : 
     229              :      ! No singularity occurs in finite cylinder, thus start from 1.
     230          720 :      do ig=1,ng
     231          714 :        if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
     232              : 
     233         2856 :        gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
     234         2856 :        qpg(:)=qc(:)+gcart(:)
     235          714 :        qpg_para_=ABS(qpg(3)) ; qpg_perp_=SQRT(qpg(1)**2+qpg(2)**2)
     236              : 
     237          720 :        if (qpg_perp_ /= zero .and. qpg_para_ /= zero) then
     238              :          ! $ 4\pi\int_0^{R_c} d\rho\rho j_o(qpg_perp_.\rho)\int_0^hcyl dz\cos(qpg_para_*z)/sqrt(\rho^2+z^2) $
     239          655 :          call quadrature(F2,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     240          655 :          ABI_CHECK(ierr == 0, "Accuracy not reached")
     241          655 :          vc_cut(ig) = four_pi*quad
     242              : 
     243           59 :        else if (qpg_perp_ == zero .and. qpg_para_ /= zero) then
     244              :          ! $ \int_0^h sin(qpg_para_.z)/\sqrt(rcut^2+z^2)dz $
     245           14 :          call quadrature(F3,zero,hcyl_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     246           14 :          ABI_CHECK(ierr == 0, "Accuracy not reached")
     247              : 
     248           14 :          c1=one/qpg_para_**2-COS(qpg_para_*hcyl_)/qpg_para_**2-hcyl_*SIN(qpg_para_*hcyl_)/qpg_para_
     249           14 :          c2=SIN(qpg_para_*hcyl_)*SQRT(hcyl2+rcut2)
     250           14 :          vc_cut(ig) = four_pi*c1+four_pi*(c2-quad)/qpg_para_
     251              : 
     252           45 :        else if (qpg_perp_ /= zero .and. qpg_para_ == zero) then
     253              :          ! $ 4pi\int_0^rcut d\rho \rho J_o(qpg_perp_.\rho) ln((h+\sqrt(h^2+\rho^2))/\rho) $
     254           44 :          call quadrature(F4,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     255           44 :          ABI_CHECK(ierr == 0, "Accuracy not reached")
     256           44 :          vc_cut(ig) = four_pi*quad
     257              : 
     258            1 :        else if (qpg_perp_ == zero .and. qpg_para_ == zero) then
     259              :          ! Use lim q+G --> 0
     260            1 :          vc_cut(ig) = two_pi*(-hcyl2+hcyl_*SQRT(hcyl2+rcut2)+rcut2*LOG((hcyl_+SQRT(hcyl_+SQRT(hcyl2+rcut2)))/rcut_))
     261              : 
     262              :        else
     263            0 :          ABI_BUG('You should not be here!')
     264              :        end if
     265              : 
     266              :      end do !ig
     267              : 
     268              :    else
     269              :      ! Infinite cylinder.
     270              :      !call wrtout(std_out, ' cutoff_cylinder: using Rozzi''s method with infinite cylinder ')
     271              : 
     272            0 :      do ig=1,ng
     273            0 :        if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
     274              : 
     275            0 :        gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
     276            0 :        qpg(:)=qc(:)+gcart(:)
     277            0 :        qpg2  =DOT_PRODUCT(qpg,qpg)
     278            0 :        qpg_z =ABS(qpg(3)) ; qpg_xy=SQRT(qpg(1)**2+qpg(2)**2)
     279              : 
     280            0 :        if (qpg_z > SMALL) then
     281              :          ! Analytic expression.
     282            0 :          call CALCK0(qpg_z *rcut_, k0, 1)
     283            0 :          call CALJY1(qpg_xy*rcut_, j1, 0)
     284            0 :          call CALJY0(qpg_xy*rcut_, j0, 0)
     285            0 :          call CALCK1(qpg_z *rcut_, k1, 1)
     286            0 :          vc_cut(ig) = (four_pi/qpg2)*(one+rcut_*qpg_xy*j1*k0-qpg_z*rcut_*j0*k1)
     287              :        else
     288            0 :          if (qpg_xy > SMALL) then
     289              :            ! Integrate r*Jo(G_xy r)log(r) from 0 up to rcut_
     290            0 :            call quadrature(F5,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     291            0 :            ABI_CHECK(ierr == 0, "Accuracy not reached")
     292            0 :            vc_cut(ig)=-four_pi*quad
     293              :          else
     294              :            ! Analytic expression
     295            0 :            vc_cut(ig)=-pi*rcut_**2*(two*LOG(rcut_)-one)
     296              :          end if
     297              :        end if
     298              :      end do ! ig
     299              :    end if !finite/infinite
     300              : 
     301              :  case default
     302          112 :    ABI_BUG(sjoin('Wrong value for method:',itoa(method)))
     303              :  end select
     304              : 
     305              :  ! Collect vc_cut on each core
     306          112 :  call xmpi_sum(vc_cut, comm, ierr)
     307              : 
     308          112 : end subroutine cutoff_cylinder
     309              : !!***
     310              : 
     311              : !----------------------------------------------------------------------
     312              : 
     313      4297455 : real(dp) function F1(rho)
     314              : 
     315              :  real(dp),intent(in) :: rho
     316              : 
     317              : !Local variables-------------------------------
     318              :  integer,parameter :: order=0,ll=0
     319              :  real(dp) :: arg,bes,besp,bespp
     320              : !************************************************************************
     321              : 
     322              :  ! F1(\rho;z)= \rho*j_o(qpg_perp_*\rho)/sqrt(\rho**2+z**2)
     323      4297455 :  arg=rho*qpg_perp_
     324      4297455 :  call paw_jbessel(bes,besp,bespp,ll,order,arg)
     325              : 
     326      4297455 :  if (zz_==zero) then
     327            0 :    F1=bes
     328              :  else
     329      4297455 :    F1=bes*rho/SQRT(rho**2+zz_**2)
     330              :  end if
     331              : 
     332      4297455 : end function F1
     333              : !!***
     334              : 
     335              : !----------------------------------------------------------------------
     336              : 
     337        53055 : function F2(xx)
     338              : 
     339              :  real(dp),intent(in) :: xx
     340              :  real(dp) :: F2
     341              : 
     342              : !Local variables-------------------------------
     343              : !scalars
     344              :  integer :: ierr
     345              :  real(dp) :: intr
     346              : !************************************************************************
     347              : 
     348        53055 :  zz_=xx
     349        53055 :  call quadrature(F1,zero,rcut_,qopt_,intr,ierr,ntrial_,accuracy_,npts_)
     350        53055 :  ABI_CHECK(ierr == 0, "Accuracy not reached")
     351              : 
     352        53055 :  F2=intr*COS(qpg_para_*xx)
     353              : 
     354        53055 : end function F2
     355              : !!***
     356              : 
     357              : !----------------------------------------------------------------------
     358              : 
     359         1134 : real(dp) pure function F3(xx)
     360              : 
     361              :  real(dp),intent(in) :: xx
     362              : 
     363              : !************************************************************************
     364              : 
     365              :  ! F3(z)=z*\sin(qpg_para_*z)/\sqrt(rcut^2+z^2)
     366         1134 :  F3=xx*SIN(qpg_para_*xx)/SQRT(rcut_**2+xx**2)
     367              : 
     368         1134 : end function F3
     369              : !!***
     370              : 
     371              : !----------------------------------------------------------------------
     372              : 
     373         3564 : real(dp) function F4(rho)
     374              : 
     375              :  real(dp),intent(in) :: rho
     376              : 
     377              : !Local variables-------------------------------
     378              :  integer,parameter :: order=0,ll=0
     379              :  real(dp) :: arg,bes,besp,bespp
     380              : !************************************************************************
     381              : 
     382              :  ! $F4(rho)=\rho*j_o(qpg_perp_.\rho) \ln((hcyl+\sqrt(rho^2+hcyl^2))/\rho)$
     383         3564 :  if (ABS(rho)<tol12) then
     384              :    F4=zero
     385              :  else
     386         3564 :    arg=rho*qpg_perp_
     387         3564 :    call paw_jbessel(bes,besp,bespp,ll,order,arg)
     388         3564 :    F4=bes*rho*LOG((hcyl_+SQRT(rho**2+hcyl_**2))/rho)
     389              :  end if
     390              : 
     391         3564 : end function F4
     392              : !!***
     393              : 
     394              : !----------------------------------------------------------------------
     395              : 
     396            0 : real(dp) function F5(rho)
     397              : 
     398              :  real(dp),intent(in) :: rho
     399              : 
     400              : !Local variables-------------------------------
     401              :  integer,parameter :: order = 0, ll = 0
     402              :  real(dp) :: arg,bes,besp,bespp
     403              : !************************************************************************
     404              : 
     405              :  ! $F5(\rho)=\rho*j_o(G_perp\rho)log(\rho)$
     406            0 :  if (rho==0) then
     407              :    F5=zero
     408              :  else
     409            0 :    arg=rho*qpg_perp_
     410            0 :    call paw_jbessel(bes,besp,bespp,ll,order,arg)
     411            0 :    F5=bes*rho*LOG(rho)
     412              :  end if
     413              : 
     414            0 : end function F5
     415              : !!***
     416              : 
     417              : !----------------------------------------------------------------------
     418              : 
     419      5345190 : real(dp) function K0cos(yy)
     420              : 
     421              :  real(dp),intent(in) :: yy
     422              : 
     423              : !Local variables-------------------------------
     424              :  real(dp) :: k0,rho,arg
     425              : !************************************************************************
     426              : 
     427              :  ! K0cos(y)=K0(\rho*|qpg_z|)*COS(x.qpg_x+y*qpg_y)
     428      5345190 :  rho=SQRT(xx_**2+yy**2) ; arg=qpg_para_*rho
     429      5345190 :  call CALCK0(arg,k0,1)
     430      5345190 :  K0cos=k0*COS(qpgx_*xx_+qpgy_*yy)
     431              : 
     432      5345190 : end function K0cos
     433              : !!***
     434              : 
     435              : !----------------------------------------------------------------------
     436              : 
     437        65934 : real(dp) function K0cos_dy(xx)
     438              : 
     439              :  real(dp),intent(in) :: xx
     440              : 
     441              : !Local variables-------------------------------
     442              :  integer :: ierr
     443              :  real(dp) :: quad
     444              : !************************************************************************
     445              : 
     446              :  !! K0cos_dy(x)=\int_{-b/2}^{b/2} K0(|qpg_z|\rho)cos(x.qpg_x+y.qpg_y)dy$
     447        65934 :  xx_=xx
     448        65934 :  call quadrature(K0cos,-hb_,+hb_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     449        65934 :  ABI_CHECK(ierr == 0, "Accuracy not reached")
     450              : 
     451        65934 :  K0cos_dy=quad
     452              : 
     453        65934 : end function K0cos_dy
     454              : !!***
     455              : 
     456              : 
     457              : 
     458              : 
     459              : !----------------------------------------------------------------------
     460              : 
     461              : real(dp) function K0cos_dy_r0(xx)
     462              : 
     463              :  real(dp),intent(in) :: xx
     464              : 
     465              : !Local variables-------------------------------
     466              : !scalars
     467              :  integer :: ierr
     468              :  real(dp) :: quad,yx
     469              : !************************************************************************
     470              : 
     471              :  ! $ K0cos_dy_r0(x)= \int_{-b/2}^{-y(x)} K0(|qpg_z|\rho) cos(x.qpg_x+y.qpg_y)dy
     472              :  !                  +\int_{y(x)}^{b/2} K0(|qpg_z|\rho)cos(x.qpg_x+y.qpg_y)dy$
     473              :  ! where y(x)=SQRT(r0^2-x^2) and x<=r0
     474              :  !
     475              :  xx_=xx; yx=SQRT(r0_**2-xx**2)
     476              :  call quadrature(K0cos,-hb_,-yx,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     477              :  ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
     478              :  K0cos_dy_r0=quad
     479              : 
     480              :  call quadrature(K0cos,+yx,+hb_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     481              :  ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
     482              : 
     483              :  K0cos_dy_r0=quad+K0cos_dy_r0
     484              : 
     485              : end function K0cos_dy_r0
     486              : !!***
     487              : 
     488              : !----------------------------------------------------------------------
     489              : 
     490              : real(dp) function K0cos_dth_r0(rho)
     491              : 
     492              :  real(dp),intent(in) :: rho
     493              : 
     494              : !Local variables-------------------------------
     495              : !scalars
     496              :  integer :: ierr
     497              :  real(dp) :: quad,arg,k0,tmp
     498              : 
     499              : !************************************************************************
     500              : 
     501              :  ! $ K0cos_dth_r0(\rho)=
     502              :  ! \int_{0}^{2pi)} K0(|qpg_z|\rho)cos(\rho.cos(\theta).qpg_x+\rho.sin(\theta).qpg_y) d\theta $
     503              :  !
     504              :  ! where y(x)=SQRT(r0^2-x^2) and x<=r0
     505              :  !
     506              :  rho_=rho
     507              :  call quadrature(Fcos_th,zero,two_pi,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
     508              :  ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
     509              : 
     510              :  arg=qpg_para_*rho_
     511              :  tmp=zero
     512              :  if (arg>tol6) then
     513              :    call CALCK0(arg,k0,1)
     514              :    tmp=k0*rho_
     515              :  end if
     516              :  K0cos_dth_r0=quad*tmp
     517              : 
     518              : end function K0cos_dth_r0
     519              : !!***
     520              : 
     521              : !----------------------------------------------------------------------
     522              : 
     523              : pure real(dp) function Fcos_th(theta)
     524              : 
     525              :  real(dp),intent(in) :: theta
     526              : 
     527              : !************************************************************************
     528              : 
     529              :  ! $ Fcos_th(\theta)=rho*K0(\rho*|qpg_z|)*COS(\rho.COS(\theta).qpg_x+\rho.SIN/(\theta)*qpg_y) $
     530              : 
     531              :  !arg=qpg_para_*rho_
     532              :  !call CALCK0(arg,k0,1)
     533              :  !tmp=k0*rho_
     534              :  Fcos_th=COS(rho_*COS(theta)*qpgx_+rho_*SIN(theta)*qpgy_)
     535              : 
     536              : end function Fcos_th
     537              : !!***
     538              : 
     539              : !----------------------------------------------------------------------
     540              : 
     541              : !the following functions should be used to deal with the singularity in the Cylindrical cutoff
     542              : !TODO Not yet used and indeed are still private
     543              : 
     544              : function K0fit(mq,nn) result(vals)
     545              : 
     546              :  integer,intent(in) :: nn
     547              :  real(dp),intent(in) :: mq
     548              :  real(dp) :: vals(nn)
     549              : 
     550              : !Local variables-------------------------------
     551              : !scalars
     552              :  integer :: ii
     553              :  real(dp) :: mqh
     554              : !arrays
     555              :  real(dp),parameter :: cc(7)=(/-0.57721566,0.42278420,0.23069756, &
     556              :                                 0.03488590,0.00262698,0.00010750,0.00000740/)
     557              :  ! *************************************************************************
     558              : 
     559              :  if (nn>8.or.nn<1) then
     560              :    ABI_ERROR("nn>8.or.nn<1 not implemented")
     561              :  end if
     562              : 
     563              :  ! === Eq 9.8.5 in Abramovitz ===
     564              :  vals(1)=-LOG(mq*half)*I0(mq)
     565              :  mqh=mq*half
     566              :  do ii=2,nn
     567              :    vals(ii)=cc(ii-1)*mqh**(2*(ii-2))
     568              :  end do
     569              : 
     570              : end function K0fit
     571              : 
     572              : real(dp) function K0fit_int(mq,par,nn) result(integ)
     573              : 
     574              :  integer,intent(in) :: nn
     575              :  real(dp),intent(in) :: mq
     576              :  real(dp),intent(in) :: par(nn)
     577              : 
     578              : !Local variables-------------------------------
     579              : !scalars
     580              :  integer :: ii,aa
     581              :  real(dp) :: mqh
     582              : !arrays
     583              :  real(dp),parameter :: cc(7)=(/-0.57721566,0.42278420,0.23069756,&
     584              : &                               0.03488590,0.00262698,0.00010750,0.00000740/)
     585              :  ! *************************************************************************
     586              : 
     587              :  if (nn>8.or.nn<1) then
     588              :    ABI_ERROR("nn>8.or.nn<1 not implemented")
     589              :  end if
     590              : 
     591              :  mqh=mq*half
     592              :  integ=-par(1)*int_I0ln(mqh)
     593              :  ! primitive of polynomial \sum_0^{N/2} cc_{2i} (x/2)^{2*i}
     594              :  do ii=2,nn
     595              :   aa=(2*(ii-1)+1)
     596              :   integ=integ+par(ii)*two*cc(ii-1)*(mqh**aa)/aa
     597              :  end do
     598              : 
     599              : end function K0fit_int
     600              : 
     601              : real(dp) function I0(xx)
     602              : 
     603              :  real(dp),intent(in) :: xx
     604              : 
     605              : !Local variables-------------------------------
     606              :  real(dp) :: tt
     607              : 
     608              : ! *************************************************************************
     609              : 
     610              :  ! Eq 9.8.1 of Abramovitz, entering the expansion of K0 -->0
     611              :  ! Expansion holds for |x|<3.75, Error<1.6*10D-07
     612              :  tt=xx/3.75
     613              :  I0=one+3.5156229*tt**2+3.0899424*tt**4 +1.2067492*tt**6 &
     614              :        +0.2659732*tt**8+0.0360768*tt**10+0.0045813*tt**12
     615              : end function I0
     616              : 
     617              : ! Primitive of x^m Ln(x) for m/=-1
     618              : real(dp) function int_xmln(xx,mm)  result(res)
     619              : 
     620              :  integer,intent(in) :: mm
     621              :  real(dp),intent(in) :: xx
     622              : 
     623              : ! *********************************************************************
     624              : 
     625              :  if (mm==-1) then
     626              :    ABI_BUG('invalid value for mm')
     627              :  end if
     628              : 
     629              :  if (xx<=zero) then
     630              :    ABI_BUG(' invalid value for xx')
     631              :  end if
     632              : 
     633              :  res= (xx**(mm+1))/(mm+1) * (LOG(xx) - one/(mm+1))
     634              : 
     635              : end function int_xmln
     636              : 
     637              : ! Primitive function of ln(x/2)*I0(x) = sum_0^{N/2} 2^{2s+1} c_{2s} T(x/2,2s)
     638              : ! where T(x,s)=\int x^s ln(x)dx
     639              : real(dp) function int_I0ln(xx) result(res)
     640              : 
     641              : !Arguments ------------------------------------
     642              :  real(dp),intent(in) :: xx
     643              : 
     644              : !Local variables-------------------------------
     645              :  real(dp) :: yy
     646              : ! *********************************************************************
     647              : 
     648              :  yy=xx*half
     649              :  res =  (       one*2    *int_xmln(yy,0)  &
     650              : &        +3.5156229*2**3 *int_xmln(yy,2)  &
     651              : &        +3.0899424*2**5 *int_xmln(yy,4)  &
     652              : &        +1.2067492*2**7 *int_xmln(yy,6)  &
     653              : &        +0.2659732*2**9 *int_xmln(yy,8)  &
     654              : &        +0.0360768*2**11*int_xmln(yy,10) &
     655              : &        +0.0045813*2**13*int_xmln(yy,12) &
     656              : &       )
     657              : 
     658              : end function int_I0ln
     659              : !!***
     660              : 
     661              : end module m_cutoff_cylinder
     662              : !!***
        

Generated by: LCOV version 2.3-1