LCOV - code coverage report
Current view: top level - src/65_paw - m_paw_yukawa.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 107 0
Test Date: 2026-11-11 19:49:02 Functions: 0.0 % 4 0
Branches: 0.0 % 112 0

             Branch data     Line data    Source code
       1                 :             : !!****m* m_paw_yukawa/m_paw_yukawa
       2                 :             : !! NAME
       3                 :             : !!  m_paw_yukawa
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  This module contains several routines related to the Yukawa parametrization
       7                 :             : !!  of Coulomb interactions in the PAW approach.
       8                 :             : !!
       9                 :             : !! COPYRIGHT
      10                 :             : !! Copyright (C) 2025-2026 ABINIT group
      11                 :             : !! These routines are inspired by K. Haule routines in embedded DMFT.
      12                 :             : !! This file is distributed under the terms of the
      13                 :             : !! GNU General Public License, see ~abinit/COPYING
      14                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      15                 :             : !!
      16                 :             : !! SOURCE
      17                 :             : 
      18                 :             : #if defined HAVE_CONFIG_H
      19                 :             : #include "config.h"
      20                 :             : #endif
      21                 :             : 
      22                 :             : #include "abi_common.h"
      23                 :             : 
      24                 :             : MODULE m_paw_yukawa
      25                 :             : 
      26                 :             :  use defs_basis
      27                 :             :  use m_abicore
      28                 :             :  use m_errors
      29                 :             :  use m_pawrad, only : pawrad_type
      30                 :             : 
      31                 :             :  implicit none
      32                 :             : 
      33                 :             :  private
      34                 :             : 
      35                 :             :  public :: compute_slater
      36                 :             :  public :: get_lambda
      37                 :             : 
      38                 :             : CONTAINS  !========================================================================================
      39                 :             : !!***
      40                 :             : 
      41                 :             : !!****f* m_paw_yukawa/compute_slater
      42                 :             : !! NAME
      43                 :             : !! compute_slater
      44                 :             : !!
      45                 :             : !! FUNCTION
      46                 :             : !!
      47                 :             : !! Compute Slater integrals for a screened Yukawa potential v(r,r') = exp(-lambda*(r-r'))/(epsilon*(r-r'))
      48                 :             : !! This is eq. 36 in the supplementary of Physical review letters, Haule, K. (2015), 115(19), 196403
      49                 :             : !!
      50                 :             : !! INPUTS
      51                 :             : !!  lpawu = angular momentum
      52                 :             : !!  pawrad <type(pawrad_type)>=paw radial mesh and related data:
      53                 :             : !!     %mesh_size=Dimension of radial mesh
      54                 :             : !!     %rad(mesh_size)=The coordinates of all the points of the radial mesh
      55                 :             : !!  proj2 = u(r)**2 where u(r) is the atomic orbital multiplied by r
      56                 :             : !!  meshsz = size of the radial mesh
      57                 :             : !!  lambda, eps = parameters of the Yukawa potential
      58                 :             : !!
      59                 :             : !! OUTPUT
      60                 :             : !!  fk(lpawu+1)= Slater integrals
      61                 :             : !!
      62                 :             : !! SOURCE
      63                 :             : 
      64                 :           0 :  subroutine compute_slater(lpawu,pawrad,proj2,meshsz,lambda,eps,fk)
      65                 :             : 
      66                 :             :  use m_pawrad, only : pawrad_type,simp_gen
      67                 :             :  use m_bessel2, only : bessel_iv,bessel_kv
      68                 :             : 
      69                 :             : !Arguments ------------------------------------
      70                 :             :  integer, intent(in) :: lpawu,meshsz
      71                 :             :  real(dp), intent(in) :: lambda,eps
      72                 :             :  real(dp), intent(in) :: proj2(meshsz)
      73                 :             :  real(dp), intent(inout) :: fk(lpawu+1)
      74                 :             :  type(pawrad_type), intent(in) :: pawrad
      75                 :             : !Local variables ------------------------------
      76                 :             :  integer :: ir,k,mesh_type
      77                 :             :  real(dp) :: dum,r_for_intg,y0
      78                 :           0 :  real(dp), allocatable :: r_k(:),u_inside(:),u_outside(:),y1(:),y2(:)
      79                 :             :  !************************************************************************
      80                 :             : 
      81                 :           0 :  mesh_type  = pawrad%mesh_type
      82                 :           0 :  r_for_intg = pawrad%rad(meshsz)
      83   [ #  #  #  #  :           0 :  ABI_MALLOC(r_k,(meshsz))
          #  #  #  #  #  
                #  #  # ]
      84   [ #  #  #  #  :           0 :  ABI_MALLOC(u_inside,(meshsz))
             #  #  #  # ]
      85   [ #  #  #  #  :           0 :  ABI_MALLOC(u_outside,(meshsz))
             #  #  #  # ]
      86                 :             : 
      87         [ #  # ]:           0 :  if (lambda == zero) then
      88                 :             : 
      89   [ #  #  #  # ]:           0 :    do k=0,2*lpawu+1,2
      90                 :           0 :      u_inside(1) = zero
      91         [ #  # ]:           0 :      r_k(:) = pawrad%rad(1:meshsz)**k
      92         [ #  # ]:           0 :      do ir=2,meshsz
      93         [ #  # ]:           0 :        if (ir == 2) then
      94                 :             :          ! Use a trapezoidal rule
      95                 :             :          u_inside(ir) = half * (proj2(1)*r_k(1)+proj2(2)*r_k(2)) * &
      96                 :           0 :                  & (pawrad%rad(2)-pawrad%rad(1))
      97         [ #  # ]:           0 :        else if (ir == 3 .and. mesh_type == 3) then
      98                 :             :          ! simp_gen doesn't handle this case, so we use a trapezoidal rule instead
      99                 :             :          u_inside(ir) = u_inside(2) + half*(proj2(2)*r_k(2)+proj2(3)*r_k(3))* &
     100                 :           0 :                  & (pawrad%rad(3)-pawrad%rad(2))
     101                 :             :        else
     102                 :             :          ! Use Simpson rule when enough points are available
     103         [ #  # ]:           0 :          call simp_gen(u_inside(ir),proj2(1:ir)*r_k(1:ir),pawrad,r_for_intg=pawrad%rad(ir))
     104                 :             :        end if ! ir=2
     105                 :             :      end do ! ir
     106                 :           0 :      u_outside(1) = zero
     107         [ #  # ]:           0 :      u_outside(2:meshsz) = two * u_inside(2:meshsz) * proj2(2:meshsz) / (pawrad%rad(2:meshsz)*r_k(2:meshsz))
     108                 :           0 :      call simp_gen(fk(k/2+1),u_outside(:),pawrad,r_for_intg=r_for_intg)
     109                 :             :    end do ! k
     110                 :             : 
     111                 :             :  else
     112                 :             : 
     113   [ #  #  #  #  :           0 :    ABI_MALLOC(y1,(meshsz))
             #  #  #  # ]
     114   [ #  #  #  #  :           0 :    ABI_MALLOC(y2,(meshsz))
             #  #  #  # ]
     115                 :             : 
     116         [ #  # ]:           0 :    r_k(:) = sqrt(pawrad%rad(1:meshsz))
     117                 :             : 
     118   [ #  #  #  # ]:           0 :    do k=0,2*lpawu+1,2
     119                 :             : 
     120                 :           0 :      y0 = zero
     121         [ #  # ]:           0 :      if (k == 0) y0 = lambda * sqrt(two/pi)
     122                 :           0 :      y1(1) = y0
     123                 :           0 :      u_inside(1) = zero
     124                 :             : 
     125         [ #  # ]:           0 :      do ir=2,meshsz
     126                 :             : 
     127                 :           0 :        call bessel_iv(half+dble(k),lambda*pawrad%rad(ir),zero,y1(ir),dum)
     128                 :           0 :        y1(ir) = y1(ir) / r_k(ir)
     129                 :             : 
     130         [ #  # ]:           0 :        if (ir == 2) then
     131                 :             :          ! Use a trapezoidal rule
     132                 :             :          u_inside(ir) = half * (proj2(1)*y1(1)+proj2(2)*y1(2)) * &
     133                 :           0 :                  & (pawrad%rad(2)-pawrad%rad(1))
     134         [ #  # ]:           0 :        else if (ir == 3 .and. mesh_type == 3) then
     135                 :             :          ! simp_gen doesn't handle this case, so we use a trapezoidal rule instead
     136                 :             :          u_inside(ir) = u_inside(2) + half*(proj2(2)*y1(2)+proj2(3)*y1(3)) * &
     137                 :           0 :                  & (pawrad%rad(3)-pawrad%rad(2))
     138                 :             :        else
     139                 :             :          ! Use Simpson rule when enough points are available
     140         [ #  # ]:           0 :          call simp_gen(u_inside(ir),proj2(1:ir)*y1(1:ir),pawrad,r_for_intg=pawrad%rad(ir))
     141                 :             :        end if ! ir
     142                 :             : 
     143                 :           0 :        call bessel_kv(half+dble(k),lambda*pawrad%rad(ir),zero,y2(ir),dum)
     144                 :           0 :        y2(ir) = y2(ir) / r_k(ir)
     145                 :             :      end do ! ir
     146                 :             : 
     147                 :           0 :      u_outside(1) = zero
     148         [ #  # ]:           0 :      u_outside(2:meshsz) = two * (two*dble(k)+one)*u_inside(2:meshsz)*proj2(2:meshsz)*y2(2:meshsz)
     149                 :           0 :      call simp_gen(fk(k/2+1),u_outside(:),pawrad,r_for_intg=r_for_intg)
     150                 :             : 
     151                 :             :    end do ! k
     152                 :             : 
     153         [ #  # ]:           0 :    ABI_FREE(y1)
     154         [ #  # ]:           0 :    ABI_FREE(y2)
     155                 :             : 
     156                 :             :  end if ! lambda
     157                 :             : 
     158         [ #  # ]:           0 :  fk(1:lpawu+1) = fk(1:lpawu+1) / eps
     159                 :             : 
     160         [ #  # ]:           0 :  ABI_FREE(r_k)
     161         [ #  # ]:           0 :  ABI_FREE(u_inside)
     162         [ #  # ]:           0 :  ABI_FREE(u_outside)
     163                 :             : 
     164                 :           0 :  end subroutine compute_slater
     165                 :             : !!***
     166                 :             : 
     167                 :             : !----------------------------------------------------------------------
     168                 :             : 
     169                 :             : !!****f* m_paw_yukawa/get_lambda
     170                 :             : !! NAME
     171                 :             : !! get_lambda
     172                 :             : !!
     173                 :             : !! FUNCTION
     174                 :             : !!
     175                 :             : !! Conversion from U,J,f4/f2,f6/f2 parametrization of Slater integrals
     176                 :             : !! to lambda,epsilon parametrization, with lambda and epsilon the parameters
     177                 :             : !! of the screened Yukawa potential v(r,r') = exp(-lambda*(r-r'))/(epsilon*(r-r')).
     178                 :             : !!
     179                 :             : !! CAREFUL: this routine does not handle custom f4/f2 and f6/f2 values, and set them
     180                 :             : !!          to their default values f4/f2=0.625 for l=2 and f4/f2=0.6681, f6/f2=0.4943 for l=3.
     181                 :             : !!
     182                 :             : !! CAREFUL: For l>=2 we lose information since we have more input parameters than output
     183                 :             : !!          parameters. In this case, a compromise has to be made, and you will no longer
     184                 :             : !!          have the exact same Slater integrals as before.
     185                 :             : !!
     186                 :             : !! INPUTS
     187                 :             : !!  lpawu = angular momentum
     188                 :             : !!  pawrad <type(pawrad_type)>=paw radial mesh and related data:
     189                 :             : !!     %mesh_size=Dimension of radial mesh
     190                 :             : !!     %rad(mesh_size)=The coordinates of all the points of the radial mesh
     191                 :             : !!  proj2 = u(r)**2 where u(r) is the atomic orbital multiplied by r
     192                 :             : !!  meshsz = size of the radial mesh
     193                 :             : !!  upawu,jpawu = parameters for Slater integrals
     194                 :             : !!  yukawa_param = if set to 1, search for lambda and epsilon yielding the values closest to u and j
     195                 :             : !!                 if set to 2, search for lambda yielding u, and set epsilon to 1
     196                 :             : !!
     197                 :             : !! OUTPUT
     198                 :             : !!  lambda,epsilon = parameters of the corresponding Yukawa potential
     199                 :             : !!
     200                 :             : !! SOURCE
     201                 :             : 
     202                 :           0 :  subroutine get_lambda(lpawu,pawrad,proj2,meshsz,upawu,jpawu,lambda,eps,yukawa_param)
     203                 :             : 
     204                 :             :  use m_brentq, only : brentq
     205                 :             :  use m_hybrd, only : hybrd
     206                 :             : 
     207                 :             : !Arguments ------------------------------------
     208                 :             :  integer, intent(in) :: lpawu,meshsz,yukawa_param
     209                 :             :  real(dp), intent(in) :: upawu,jpawu
     210                 :             :  real(dp), intent(out) :: lambda,eps
     211                 :             :  real(dp), intent(in) :: proj2(meshsz)
     212                 :             :  type(pawrad_type), intent(in) :: pawrad
     213                 :             : !Local variables ------------------------------
     214                 :             :  integer  :: i,ierr,info,ldfjac,lr,maxfev,ml,mode,mu,n,nfev,nprint
     215                 :             :  real(dp) :: epsfcn,fac,lmb_temp,upbound,xtol
     216                 :           0 :  real(dp) :: diag(2),fjac(2,2),fkk(lpawu+1),fvec(2),lmb_eps(2)
     217                 :             :  real(dp) :: r(3),qtf(2),wa1(2),wa2(2),wa3(2),wa4(2)
     218                 :             :  character(len=500) :: message
     219                 :             :  !************************************************************************
     220                 :             : 
     221                 :             :  ! Find suitable upper bound for brentq routine
     222                 :           0 :  upbound = five
     223         [ #  # ]:           0 :  do i=1,10
     224                 :             : 
     225                 :           0 :    call compute_slater(lpawu,pawrad,proj2(:),meshsz,upbound,one,fkk(:))
     226         [ #  # ]:           0 :    if (fkk(1) < upawu) exit
     227                 :           0 :    upbound = two * upbound
     228                 :             : 
     229                 :             :  end do ! i
     230                 :             : 
     231                 :           0 :  write(message,'(4a)') "An error occurred when trying to find a suitable lambda and ", &
     232                 :           0 :                      & "epsilon for your input values of upawu and jpawu.", ch10, &
     233                 :           0 :                      & "Either try different values or use dmft_yukawa_lambda and dmft_yukawa_epsilon."
     234                 :             : 
     235         [ #  # ]:           0 :  if (fkk(1) > upawu) ABI_ERROR(message)
     236                 :             : 
     237                 :             :  ! First, set epsilon to 1, and find lambda which yields the correct F0=upawu, to have a good starting point
     238                 :           0 :  call brentq(get_coulomb_u,zero,upbound,two*tol12,four*epsilon(one),100,lmb_temp,ierr)
     239                 :             : 
     240         [ #  # ]:           0 :  if (ierr == 0) ABI_ERROR(message)
     241                 :             : 
     242                 :             :  ! Initial values for lambda and epsilon
     243                 :           0 :  lmb_eps(1) = lmb_temp
     244                 :           0 :  lmb_eps(2) = one
     245                 :             : 
     246                 :           0 :  lambda = lmb_temp
     247                 :           0 :  eps    = one
     248                 :             : 
     249         [ #  # ]:           0 :  if (yukawa_param == 2) return
     250                 :             : 
     251         [ #  # ]:           0 :  if (lpawu > 0) then
     252                 :             : 
     253                 :             :    ! Default values from scipy
     254                 :           0 :    epsfcn = epsilon(one) ; fac = dble(100.) ; n = 2
     255                 :           0 :    ldfjac = n ; lr = n * (n+1) / 2
     256                 :           0 :    maxfev = 200 * (n+1) ; ml = n - 1 ; mode = 1
     257                 :           0 :    mu = n - 1 ; nprint = 0 ; xtol = dble(1.49012e-8)
     258                 :             : 
     259                 :             :    ! Now find lambda and epsilon
     260                 :             :    call hybrd(get_coulomb_uj,2,lmb_eps(:),fvec(:),xtol,maxfev,ml,mu,epsfcn,diag(:),mode, &
     261                 :           0 :             & fac,nprint,info,nfev,fjac(:,:),ldfjac,r(:),lr,qtf(:),wa1(:),wa2(:),wa3(:),wa4(:))
     262                 :             : 
     263         [ #  # ]:           0 :    if (info /= 1) ABI_ERROR(message)
     264                 :             : 
     265                 :             :  end if ! lpawu > 0
     266                 :             : 
     267                 :           0 :  lambda = lmb_eps(1)
     268                 :           0 :  eps    = lmb_eps(2)
     269                 :             : 
     270                 :             :  contains
     271                 :             : 
     272                 :           0 :  subroutine get_coulomb_u(lmb,uu)
     273                 :             : 
     274                 :             : !Arguments ------------------------------------
     275                 :             :  real(dp), intent(in) :: lmb
     276                 :             :  real(dp), intent(out) :: uu
     277                 :             : !Local variables ------------------------------
     278                 :           0 :  real(dp) :: fk(lpawu+1)
     279                 :             : !************************************************************************
     280                 :             : 
     281                 :           0 :  call compute_slater(lpawu,pawrad,proj2(:),meshsz,lmb,one,fk(:))
     282                 :           0 :  uu = fk(1) - upawu
     283                 :             : 
     284                 :           0 :  end subroutine get_coulomb_u
     285                 :             : 
     286                 :           0 :  subroutine get_coulomb_uj(n,lmb_eps,uj,iflag)
     287                 :             : 
     288                 :             : !Arguments ------------------------------------
     289                 :             :  integer, intent(in) :: iflag,n
     290                 :             :  real(dp), intent(in) :: lmb_eps(n)
     291                 :             :  real(dp), intent(inout) :: uj(n)
     292                 :             :  !Local variables ------------------------------
     293                 :             :  real(dp) :: eps,f4of2,f6of2,factor,j2,j4,j6,jh,lmb
     294                 :           0 :  real(dp) :: fk(lpawu+1)
     295                 :             :  character(len=500) :: message
     296                 :             : !************************************************************************
     297                 :             : 
     298                 :             :  ABI_UNUSED(iflag)
     299                 :             : 
     300                 :           0 :  lmb = lmb_eps(1)
     301                 :           0 :  eps = lmb_eps(2)
     302                 :           0 :  call compute_slater(lpawu,pawrad,proj2(:),meshsz,lmb,eps,fk(:))
     303                 :           0 :  uj(1) = fk(1) - upawu
     304                 :             : 
     305         [ #  # ]:           0 :  if (lpawu == 1) then
     306                 :           0 :    j2 = fk(2) * fifth
     307                 :           0 :    jh = j2
     308         [ #  # ]:           0 :  else if (lpawu == 2) then
     309                 :           0 :    f4of2  = dble(0.625)
     310                 :           0 :    factor = (one+f4of2) / dble(14)
     311                 :           0 :    j2 = fk(2)
     312                 :           0 :    j4 = fk(3) / f4of2
     313                 :           0 :    jh = (j2+j4) * factor * half
     314         [ #  # ]:           0 :  else if (lpawu == 3) then
     315                 :           0 :    f4of2  = dble(0.6681)
     316                 :           0 :    f6of2  = dble(0.4943)
     317                 :           0 :    factor = (dble(286.)+dble(195.)*f4of2+dble(250.)*f6of2) / dble(6435.)
     318                 :           0 :    j2 = fk(2)
     319                 :           0 :    j4 = fk(3) / f4of2
     320                 :           0 :    j6 = fk(4) / f6of2
     321                 :           0 :    jh = (j2+j4+j6) * factor * third
     322                 :             :  else
     323                 :           0 :    write(message,'(a,i0,2a)') ' lpawu=',lpawu,ch10,' lpawu not equal to 0, 1, 2 or 3 is not allowed'
     324                 :           0 :    ABI_ERROR(message)
     325                 :             :  end if ! lpawu
     326                 :             : 
     327                 :           0 :  uj(2) = jh - jpawu
     328                 :             : 
     329                 :           0 :  end subroutine get_coulomb_uj
     330                 :             : 
     331                 :             :  end subroutine get_lambda
     332                 :             : !!***
     333                 :             : 
     334                 :             : !----------------------------------------------------------------------
     335                 :             : 
     336                 :             : END MODULE m_paw_yukawa
     337                 :             : !!***
        

Generated by: LCOV version 2.3-1