LCOV - code coverage report
Current view: top level - vgen - vvacxy.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 53 127 41.7 %
Date: 2024-04-26 04:44:34 Functions: 2 2 100.0 %

          Line data    Source code
       1             : module m_vvacxy
       2             :   !     **********************************************************
       3             :   !     g/=0 coefficient of vacuum coulomb potential           *
       4             :   !     due to warped vacuum charged density                     *
       5             :   !                                 c.l.fu, r.podloucky          *
       6             :   !     **********************************************************
       7             :   !     modified for thick films to avoid underflows gb`06
       8             :   !---------------------------------------------------------------
       9             : 
      10             :    use m_judft
      11             : 
      12             : contains
      13          44 :    subroutine vvacxy( stars, vacuum, cell, sym, input, field, rhtxy, vxy, alphm, l_dfptvgen )
      14             :       use m_types
      15             :       use m_constants
      16             :       use m_intgr, only: intgz1
      17             :       use m_qsf
      18             : 
      19             :       implicit none
      20             : 
      21             :       type(t_input),  intent(in)     :: input
      22             :       type(t_field),  intent(in)     :: field
      23             :       type(t_vacuum), intent(in)     :: vacuum
      24             :       type(t_sym),    intent(in)     :: sym
      25             :       type(t_stars),  intent(in)     :: stars
      26             :       type(t_cell),   intent(in)     :: cell
      27             : 
      28             :       complex,        intent(in)     :: rhtxy(vacuum%nmzxyd,stars%ng2,2)
      29             :       complex,        intent(inout)  :: vxy(vacuum%nmzxyd,stars%ng2,2)
      30             :       complex,        intent(out)    :: alphm(stars%ng2,2)
      31             :       logical,        intent(in)     :: l_dfptvgen
      32             : 
      33             :       complex                        :: alph0, alphaz, betaz, test, phas
      34             :       real                           :: g, vcons, z, e_m, e_p,arg
      35             :       integer                        :: imz, ip, irec2, ivac, ncsh,irec2r, start_star
      36          44 :       real                           :: fra(vacuum%nmzxyd), frb(vacuum%nmzxyd), fia(vacuum%nmzxyd), fib(vacuum%nmzxyd)
      37          44 :       real                           :: alpha(vacuum%nmzxyd,2,2,stars%ng2), beta(vacuum%nmzxyd,2,2,stars%ng2)
      38             : 
      39          44 :       if ( allocated( field%efield%rhoef ) .or. field%efield%dirichlet ) then
      40           0 :          ncsh = field%efield%zsigma / vacuum%delz + 1.01
      41             :          ! if nmzxy < ncsh, the inhomogenous field cannot be represented.
      42             :          ! if nmzxy > ncsh, the boundary condition is wrong - and the
      43             :          ! potential is very wavy - try it yourself, if you don't believe.
      44           0 :          if ( vacuum%nmzxyd < ncsh ) then
      45           0 :             write (oUnit,*) 'error vvacxy.f: vacuum%nmzxyd =', vacuum%nmzxyd, '< ncsh(zsigma) = ', ncsh
      46           0 :             call judft_error( "error: vacuum%nmzxyd < ncsh", calledby="vvacxy" )
      47           0 :          else if ( vacuum%nmzxyd > ncsh ) then
      48           0 :             write (oUnit,*) 'warning vvacxy.f: vacuum%nmzxyd =', vacuum%nmzxyd, '> ncsh(zsigma) = ', ncsh
      49           0 :             write (*,*) 'warning vvacxy.f: vacuum%nmzxyd =', vacuum%nmzxyd, '> ncsh(zsigma) = ', ncsh
      50           0 :             call judft_warn( "nmzxyd > ncsh", calledby="vvacxy" )
      51             :          end if
      52             :       end if
      53             : 
      54          44 :       start_star = 2
      55             :       ! For q/=0 in DFPT, there is no G+q=0, so all stars are treated in the G/=0 way.
      56          44 :       if (l_dfptvgen) then
      57           0 :          if (norm2(stars%center)>1e-8) start_star = 1
      58             :       end if
      59             :       ! 2-dim star loop g/=0
      60          44 :       ip = vacuum%nmzxy + 1
      61             :       !    irec2_loop: do irec2 = 2, stars%ng2
      62             :       !      g = stars%sk2(irec2)
      63             :       !      vcons = tpi_const / g
      64          44 :       if ( field%efield%dirichlet ) then ! Dirichlet
      65           0 :          do irec2 = start_star, stars%ng2
      66           0 :             g = stars%sk2(irec2)
      67           0 :             vcons = tpi_const / g
      68           0 :             if ( allocated( field%efield%rhoef ) ) then
      69           0 :                vxy(ncsh:vacuum%nmzxy,irec2,1) = field%efield%rhoef(irec2-1, 1)
      70           0 :                if ( vacuum%nvac == 2 ) then
      71           0 :                   vxy(ncsh:vacuum%nmzxy,irec2,2) = field%efield%rhoef(irec2-1, 2)
      72             :                end if
      73             :             else
      74           0 :                vxy(ncsh:vacuum%nmzxy,irec2,1:vacuum%nvac) = 0.0
      75             :             end if
      76           0 :             vcons = 2.0 * vcons / sinh( g * 2.0 * ( field%efield%zsigma + cell%z1 ) )
      77           0 :             do ivac = 1, vacuum%nvac
      78           0 :                z = cell%z1
      79           0 :                do imz = 1, ncsh-1
      80             :                   ! as "z" > 0 in this subroutine, the integrand is the same
      81             :                   ! for both ivac -- but the integral bounds are reversed
      82           0 :                   e_m = sinh( g * ( field%efield%zsigma + cell%z1 - z ) )
      83           0 :                   e_p = sinh( g * ( field%efield%zsigma + cell%z1 + z ) )
      84           0 :                   fra(ncsh-imz) = real(  rhtxy(imz,irec2,ivac) ) * e_m
      85           0 :                   fia(ncsh-imz) = aimag( rhtxy(imz,irec2,ivac) ) * e_m
      86           0 :                   frb(imz)      = real(  rhtxy(imz,irec2,ivac) ) * e_p
      87           0 :                   fib(imz)      = aimag( rhtxy(imz,irec2,ivac) ) * e_p
      88           0 :                   z = z + vacuum%delz
      89             :                end do 
      90           0 :                call intgz1( fra, vacuum%delz, ncsh - 1, alpha(1,ivac,1,irec2), .false. )
      91           0 :                call intgz1( fia, vacuum%delz, ncsh - 1, alpha(1,ivac,2,irec2), .false. )
      92           0 :                call qsf( vacuum%delz, frb, beta(1,ivac,1,irec2), ncsh - 1, 1 )
      93           0 :                call qsf( vacuum%delz, fib, beta(1,ivac,2,irec2), ncsh - 1, 1 )
      94             :             end do 
      95             : 
      96           0 :             if ( ivac == 2 ) then
      97             :                ! honour reversed integral bounds
      98           0 :                alpha(:,ivac,:,irec2) = - alpha(:,ivac,:,irec2)
      99           0 :                beta(:,ivac,:,irec2)  = - beta(:,ivac,:,irec2)
     100             :             end if
     101             :          end do
     102           0 :          do irec2 = start_star, stars%ng2
     103           0 :             g = stars%sk2(irec2)
     104           0 :             vcons = tpi_const / g
     105           0 :             alphm(irec2,1) = cmplx( alpha(vacuum%nmzxy,1,1,irec2), alpha(vacuum%nmzxy,1,2,irec2) )
     106           0 :             if ( vacuum%nvac == 1 ) then
     107           0 :                call stars%map_2nd_vac(vacuum,irec2,irec2r,phas)
     108           0 :                alphm(irec2r,2) = phas * cmplx(alpha(vacuum%nmzxy,1,1,irec2),alpha(vacuum%nmzxy,1,2,irec2))
     109             :             else
     110           0 :                alphm(irec2,2) = cmplx( alpha(vacuum%nmzxy,2,1,irec2), alpha(vacuum%nmzxy,2,2,irec2) )
     111             :             end if
     112           0 :             do ivac = 1, vacuum%nvac
     113           0 :                z = cell%z1
     114           0 :                if ( ivac == 1 ) alph0 = alphm(irec2,2)
     115           0 :                if ( ivac == 2 ) alph0 = alphm(irec2,1)
     116           0 :                do imz = 1, ncsh-1
     117           0 :                   betaz  = cmplx( beta(imz,ivac,1,irec2), beta(imz,ivac,2,irec2) )
     118           0 :                   alphaz = cmplx( alpha(ncsh-imz,ivac,1,irec2), alpha(ncsh-imz,ivac,2,irec2) )
     119           0 :                   e_m = sinh( g * ( field%efield%zsigma + cell%z1 - z ) )
     120           0 :                   e_p = sinh( g * ( field%efield%zsigma + cell%z1 + z ) )
     121           0 :                   test = e_m * ( alph0 + betaz ) + e_p * alphaz
     122           0 :                   if ( 2.0 * test == test ) test = cmplx( 0.0, 0.0 )
     123           0 :                   vxy(imz,irec2,ivac) = vxy(imz,irec2,ivac) + vcons * test
     124           0 :                   if ( allocated( field%efield%c1 ) ) then
     125           0 :                      e_m = exp_safe( - g * z )
     126           0 :                      e_p = exp_safe(   g * z )
     127           0 :                      if ( ivac == 1 ) then ! z > 0
     128           0 :                         vxy(imz,irec2,ivac) = vxy(imz,irec2,ivac) + field%efield%c1(irec2-1) * e_p + field%efield%c2(irec2-1) * e_m
     129             :                      else ! z < 0
     130           0 :                         vxy(imz,irec2,ivac) = vxy(imz,irec2,ivac) + field%efield%c1(irec2-1) * e_m + field%efield%c2(irec2-1) * e_p
     131             :                      end if
     132             :                   end if
     133           0 :                   z = z + vacuum%delz
     134             :                end do 
     135             :             end do 
     136             :          end do 
     137             :       else ! Neumann
     138       17377 :          do irec2 = start_star, stars%ng2
     139       17333 :             g = stars%sk2(irec2)
     140       17333 :             vcons = tpi_const / g
     141             :      
     142       36360 :             do ivac = 1, vacuum%nvac
     143       18983 :                z = cell%z1
     144     1917283 :                do imz = 1, vacuum%nmzxy
     145     1898300 :                   e_m = exp_safe( - g * z )
     146     1898300 :                   e_p = exp_safe(   g * z )
     147     1898300 :                   fra(ip-imz) = real(  rhtxy(imz,irec2,ivac) ) * e_m
     148     1898300 :                   fia(ip-imz) = aimag( rhtxy(imz,irec2,ivac) ) * e_m
     149     1898300 :                   frb(imz)    = real(  rhtxy(imz,irec2,ivac) ) * e_p
     150     1898300 :                   fib(imz)    = aimag( rhtxy(imz,irec2,ivac) ) * e_p
     151     1917283 :                   z = z + vacuum%delz
     152             :                end do 
     153             :                ! add external field, if segmented
     154       18983 :                if ( allocated( field%efield%rhoef ) ) then
     155           0 :                   z = cell%z1 + field%efield%zsigma
     156           0 :                   e_m = exp_safe( - g * z )
     157           0 :                   e_p = exp_safe(   g * z )
     158             :                   ! the equation has a minus sign as "rhtxy" contains the electron density
     159             :                   ! (a positive number representing a negative charge) while rhoef
     160             :                   ! specifies the charges in terms of the (positive) elementary charge "e".
     161           0 :                   fra(ip-ncsh) = fra(ip-ncsh) - real(  field%efield%rhoef(irec2-1,ivac) ) * e_m
     162           0 :                   fia(ip-ncsh) = fia(ip-ncsh) - aimag( field%efield%rhoef(irec2-1,ivac) ) * e_m
     163           0 :                   frb(ncsh)    = frb(ncsh)    - real(  field%efield%rhoef(irec2-1,ivac) ) * e_p
     164           0 :                   fib(ncsh)    = fib(ncsh)    - aimag( field%efield%rhoef(irec2-1,ivac) ) * e_p
     165             :                end if
     166       18983 :                call intgz1( fra, vacuum%delz, vacuum%nmzxy, alpha(1,ivac,1,irec2), .true. )
     167       18983 :                call intgz1( fia, vacuum%delz, vacuum%nmzxy, alpha(1,ivac,2,irec2), .true. )
     168       18983 :                call qsf( vacuum%delz, frb, beta(1,ivac,1,irec2), vacuum%nmzxy, 1 )
     169       36316 :                call qsf( vacuum%delz, fib, beta(1,ivac,2,irec2), vacuum%nmzxy, 1 )
     170             :             end do 
     171             :          end do
     172             :        
     173       17377 :          do irec2 = start_star, stars%ng2
     174       17333 :             alphm(irec2,1) = cmplx( alpha(vacuum%nmzxy,1,1,irec2), alpha(vacuum%nmzxy,1,2,irec2) )
     175       17377 :             if ( vacuum%nvac == 1 ) then
     176       15683 :                call stars%map_2nd_vac(vacuum,irec2,irec2r,phas)
     177       15683 :                alphm(irec2r,2) = phas * cmplx(alpha(vacuum%nmzxy,1,1,irec2),alpha(vacuum%nmzxy,1,2,irec2))
     178             :             else
     179        1650 :                alphm(irec2,2) = cmplx( alpha(vacuum%nmzxy,2,1,irec2), alpha(vacuum%nmzxy,2,2,irec2) )
     180             :             end if
     181             :          end do
     182             : 
     183       17377 :          do irec2 = start_star, stars%ng2
     184       17333 :             g = stars%sk2(irec2)
     185       17333 :             vcons = tpi_const / g
     186             :               
     187       36360 :             do ivac = 1, vacuum%nvac
     188       18983 :                z = cell%z1
     189       18983 :                if ( ivac == 1 ) alph0 = alphm(irec2,2)
     190       18983 :                if ( ivac == 2 ) alph0 = alphm(irec2,1)
     191     1934616 :                do imz = 1, vacuum%nmzxy
     192     1898300 :                   betaz  = cmplx( beta(imz,ivac,1,irec2), beta(imz,ivac,2,irec2) )
     193     1898300 :                   alphaz = cmplx( alpha(ip-imz,ivac,1,irec2), alpha(ip-imz,ivac,2,irec2) )
     194     1898300 :                   e_m = exp_safe( - g * z )
     195     1898300 :                   e_p = exp_safe(   g * z )
     196     1898300 :                   test = e_m * ( alph0 + betaz ) + e_p * alphaz
     197     1898300 :                   if ( 2.0 * test == test ) test = cmplx( 0.0, 0.0 )
     198     1898300 :                   vxy(imz,irec2,ivac) = vxy(imz,irec2,ivac) + vcons * test
     199     1917283 :                   z = z + vacuum%delz
     200             :                end do 
     201             :             end do 
     202             :          end do
     203             :       end if
     204          44 :    end subroutine vvacxy
     205             : 
     206     7593200 :    pure real function exp_safe( x )
     207             :       ! replace exp by a function that does not under/overflow
     208             :       implicit none
     209             : 
     210             :       real, intent(in) :: x
     211             :       real, parameter  :: maxexp = log( 2.0 ) * maxexponent( 2.0 )
     212             :       real, parameter  :: minexp = log( 2.0 ) * minexponent( 2.0 )
     213             : 
     214     7593200 :       if ( abs( x ) > minexp .and. abs( x ) < maxexp ) then
     215     7593200 :          exp_safe = exp( x )
     216             :       else
     217           0 :          if ( x > 0 ) then
     218           0 :             if ( x > minexp ) then
     219             :                exp_safe = exp( maxexp )
     220             :             else
     221           0 :                exp_safe = exp( minexp )
     222             :             end if
     223             :          else
     224           0 :             if ( - x > minexp ) then
     225             :                exp_safe = exp( - maxexp )
     226             :             else
     227           0 :                exp_safe = exp( - minexp )
     228             :             end if
     229             :          end if
     230             :       end if
     231     7593200 :    end function exp_safe
     232             : end module m_vvacxy

Generated by: LCOV version 1.14