LCOV - code coverage report
Current view: top level - vgen - vvac.f90 (source / functions) Coverage Total Hit
Test: FLEUR test coverage Lines: 64.5 % 62 40
Test Date: 2026-06-09 05:02:56 Functions: 100.0 % 1 1

            Line data    Source code
       1              : !-------------------------------------------------------------------------------
       2              : ! Copyright (c) 2022 Peter Grünberg Institut, Forschungszentrum Jülich, Germany
       3              : ! This file is part of FLEUR and available as free software under the conditions
       4              : ! of the MIT license as expressed in the LICENSE file in more detail.
       5              : !-------------------------------------------------------------------------------
       6              : 
       7              : module m_vvac
       8              :    ! Legacy comment:
       9              :    ! ****************************************************************
      10              :    ! calculates the g(2-dim)=0 part of the vacuum coulomb potential *
      11              :    ! for general symmetry.          c.l.fu, r.podloucky             *
      12              :    ! ****************************************************************
      13              : contains
      14          266 :    subroutine vvac(vacuum, stars, cell, input, field, psq, rht, vnew, rhobar, sig1dh, vz1dh, vslope, vmz1dh,l_dfptvgen)
      15              :       !! Calculates the \(\boldsymbol{G}_{||}=0\) part of the vacuum Coulomb potential.
      16              :       !! There are two possible cases for Dirichlet and von Neumann boundary conditions, respectively.
      17              :       !! von Neumann case:
      18              :       !! upper vacuum \( z\ge D/2)\):
      19              :       !! $$V^{0}(z)=-4\pi[\int_{z}^{\infty}\sigma_{+}^{0}(z')dz'+(z-z_{\sigma})\sigma_{+}]=: V_{+}^{0}(z)$$
      20              :       !! with
      21              :       !! $$\sigma_{+}^{0}(z):=\int_{z}^{\infty}n_{V}^{0}(z')dz'$$
      22              :       use m_constants
      23              :       use m_qsf
      24              :       use m_types
      25              : 
      26              :       implicit none
      27              : 
      28              :       type(t_vacuum), intent(in)  :: vacuum
      29              :       type(t_stars),  intent(in)  :: stars
      30              :       type(t_cell),   intent(in)  :: cell
      31              :       type(t_input),  intent(in)  :: input
      32              :       type(t_field),  intent(in)  :: field
      33              : 
      34              :       complex,        intent(in)  :: psq(stars%ng3)
      35              :       complex,        intent(in)  :: rht(vacuum%nmzd,2)
      36              : 
      37              :       complex,        intent(out) :: vnew(vacuum%nmzd,2)
      38              :       complex,        intent(out) :: rhobar
      39              :       complex,        intent(out) :: sig1dh, vz1dh
      40              :       complex,        intent(out) :: vslope
      41              :       complex,        intent(out) :: vmz1dh
      42              :       logical,        intent(in)  :: l_dfptvgen
      43              :       !complex,        intent(in)  :: sigma_disc(2)
      44              : 
      45              :       !complex, optional, intent(in) :: sigma_disc2(2)
      46              : 
      47              :       complex                     :: sumq, newdp, newdm, newdp2, newdm2
      48              :       real                        :: bj0, bj1, qzh, sigmaa(2)
      49              :       integer                     :: ig3, imz, ivac, ncsh
      50          266 :       real                        :: f(vacuum%nmzd), sig(vacuum%nmzd), vtemp(vacuum%nmzd)
      51              : 
      52              :       !vmz1dh = cmplx(0.0,0.0)
      53              : 
      54              :       ! newdp =  cmplx(0.0,0.0)
      55              :       ! newdm =  cmplx(0.0,0.0)
      56              :       ! newdp2 =  cmplx(0.0,0.0)
      57              :       ! newdm2 =  cmplx(0.0,0.0)
      58              : 
      59       124260 :       vnew(:,1:vacuum%nvac) = 0.0 ! initialize potential
      60              : 
      61              :       ! obtain mesh point (ncsh) of charge sheet for external electric field
      62          266 :       ncsh = field%efield%zsigma / vacuum%delz + 1.01
      63          266 :       sigmaa = 0.0
      64          266 :       if (.not. l_dfptvgen) then
      65           56 :          sigmaa(1) = ( field%efield%sigma + field%efield%sig_b(1) ) / cell%area
      66           56 :          sigmaa(2) = ( field%efield%sigma + field%efield%sig_b(2) ) / cell%area
      67              :       end if
      68              :       ! g=0 vacuum potential due to neutral charge density
      69              :       ! inside slab and zero charge density outside
      70              : 
      71          266 :       rhobar = - psq(1)
      72          266 :       sumq = 0.0
      73              : 
      74              :       !IF (l_bind) newdp = -psq(1) * cell%z1
      75              :       !IF (l_bind) newdm = -psq(1) * cell%z1
      76              :       !IF (l_bind) newdp2 = -psq(1) * cell%z1 * cell%z1
      77              :       !IF (l_bind) newdm2 =  psq(1) * cell%z1 * cell%z1
      78              : 
      79      1368307 :       do ig3 = 2, stars%ng3
      80      1368307 :          if (stars%ig2(ig3) == 1) then           ! select g_|| = 0
      81        10755 :             qzh = stars%kv3(3,ig3) * cell%bmat(3,3) * cell%z1
      82        10755 :             bj0 = sin(qzh) / qzh
      83        10755 :             rhobar = rhobar - psq(ig3) * bj0 * stars%nstr(ig3)
      84        10755 :             if ( vacuum%nvac==2 ) then
      85        10196 :                bj1 = ( sin(qzh) - qzh * cos(qzh) ) / ( qzh * qzh )
      86        10196 :                sumq = sumq - 2. * fpi_const * ImagUnit * bj1 * psq(ig3) * cell%z1 *cell%z1
      87              : 
      88              :                ! ! New discontinuity correction
      89              :                ! IF (l_bind) newdp = newdp + ImagUnit * psq(ig3) * cmplx(cos(qzh), sin(qzh)) * cell%z1 / qzh
      90              :                ! IF (l_bind) newdm = newdm - ImagUnit * psq(ig3) * cmplx(cos(qzh),-sin(qzh)) * cell%z1 / qzh
      91              :                ! IF (l_bind) newdp2 = newdp2 + psq(ig3) * cmplx(cos(qzh), sin(qzh)) * cell%z1**2 / qzh**2
      92              :                ! IF (l_bind) newdm2 = newdm2 - psq(ig3) * cmplx(cos(qzh),-sin(qzh)) * cell%z1**2 / qzh**2
      93              : 
      94              :             end if
      95              :          end if
      96              :       end do ! --> qzh, bj0, bj1, psq finished; rhobar, sumq passed on and unchanged
      97              : 
      98              :       ! lower (nvac=2) vacuum
      99        57266 :       if ( vacuum%nvac == 2 ) vnew(1:vacuum%nmz,2) =  sumq
     100              : 
     101              :       ! g=0 vacuum potential due to
     102              :       ! negative of rhobar + vacuum (g=0) charge ----> v2(z)
     103              : 
     104          266 :       ivac = 1 ! upper vacuum
     105              : 
     106          266 :       if ( field%efield%dirichlet .and. .not. l_dfptvgen ) then ! Dirichlet
     107            0 :          vnew(ncsh+1:vacuum%nmz,ivac) = field%efield%sig_b(1)
     108            0 :          call qsf( vacuum%delz, REAL(rht(:,ivac)), sig, ncsh, 1 )
     109            0 :          sig(1:ncsh) = sig(ncsh) - sig(1:ncsh)
     110            0 :          call qsf( vacuum%delz, sig, vtemp, ncsh, 1 )
     111            0 :          do imz = 1, ncsh
     112            0 :             vnew(imz,ivac) = - fpi_const * ( vtemp(ncsh) - vtemp(imz) ) + field%efield%sig_b(1)
     113              :          end do
     114            0 :          sig1dh = sig(1)
     115            0 :          vz1dh = vnew(1,ivac)   ! potential on vacuum boundary
     116           38 :          if ( vacuum%nvac == 1 ) return
     117              : 
     118            0 :          ivac = 2     ! lower vacuum
     119            0 :          call qsf( vacuum%delz, REAL(rht(:,ivac)), sig, ncsh, 1 )
     120            0 :          f(1:ncsh) = sig(1:ncsh) - rhobar*vacuum%dvac + sig1dh
     121            0 :          call qsf( vacuum%delz, f, vtemp, ncsh, 1 )
     122            0 :          do imz = 1,ncsh
     123            0 :             vnew(imz,ivac) = - fpi_const * ( vtemp(imz) + sig1dh * vacuum%dvac - rhobar * vacuum%dvac * vacuum%dvac / 2. ) + vnew(imz,ivac) + vz1dh
     124              :          end do
     125              : 
     126              :          ! force matching on the other side
     127            0 :          vslope = ( field%efield%sig_b(2) - vnew(ncsh,1) ) / ( 2 * vacuum%delz * ( ncsh + 1 ) + vacuum%dvac )
     128            0 :          ivac = 1
     129            0 :          do imz = 1, ncsh
     130            0 :             vnew(imz,ivac) = vnew(imz,ivac) + vslope * vacuum%delz * ( ncsh - imz + 1 )
     131              :          end do
     132            0 :          ivac = 2
     133            0 :          do imz = 1, ncsh
     134            0 :             vnew(imz,ivac) = vnew(imz,ivac) + vslope * ( vacuum%dvac + vacuum%delz * imz + vacuum%delz * ncsh )
     135              :          end do
     136            0 :          vnew(ncsh+1:vacuum%nmz,ivac) = field%efield%sig_b(2)
     137              :       else ! Neumann
     138        67032 :          call qsf( vacuum%delz, REAL(rht(:,ivac)), sig, vacuum%nmz, 1 )
     139          266 :          sig1dh = sig(vacuum%nmz) - sigmaa(1)  ! need to include contribution from electric field
     140        66766 :          sig(1:vacuum%nmz) = sig(vacuum%nmz) - sig(1:vacuum%nmz)
     141          266 :          call qsf( vacuum%delz, sig, vtemp, vacuum%nmz, 1 )
     142              :          ! external electric field contribution
     143        27132 :          do imz = 1, ncsh
     144        27132 :             vnew(imz,ivac) = - fpi_const * ( vtemp(vacuum%nmz) - vtemp(imz) ) + vnew(imz,ivac) - fpi_const * ( imz - ncsh ) * vacuum%delz * sigmaa(1)
     145              :          end do
     146        39900 :          do imz = ncsh + 1, vacuum%nmz
     147        39900 :             vnew(imz,ivac) = - fpi_const * ( vtemp(vacuum%nmz) - vtemp(imz) ) + vnew(imz,ivac)
     148              :          end do
     149          266 :          vz1dh = vnew(1,ivac)   ! potential on vacuum boundary
     150          266 :          if ( vacuum%nvac == 1 ) return
     151              : 
     152          228 :          ivac = 2 ! lower vacuum
     153        57228 :          call qsf( vacuum%delz, REAL(rht(:,ivac)), sig, vacuum%nmz, 1 )
     154        57228 :          f(1:vacuum%nmz) = sig(1:vacuum%nmz) - rhobar * vacuum%dvac + sig1dh
     155          228 :          call qsf( vacuum%delz, f, vtemp, vacuum%nmz, 1 )
     156              :          ! external electric field contribution
     157        23256 :          do imz = 1, ncsh
     158        23256 :             vnew(imz,ivac) = - fpi_const * ( vtemp(imz) + sig1dh * vacuum%dvac - rhobar * vacuum%dvac * vacuum%dvac / 2. ) + vz1dh + vnew(imz,ivac) !&
     159              :                            !   - fpi_const * (sigma_disc(1) * ( vacuum%dvac / 2. - (imz-1) * vacuum%delz ) - sigma_disc(2) * ( vacuum%dvac / 2. + (imz-1) * vacuum%delz )) &! Discontinuity correction
     160              :                            !   - fpi_const * (-newdp2-newdm2+newdp * ( vacuum%dvac / 2. - (imz-1) * vacuum%delz ) - newdm * ( vacuum%dvac / 2. + (imz-1) * vacuum%delz ))! New discontinuity correction
     161              :             !if (present(sigma_disc2)) vnew(imz,ivac) = vnew(imz,ivac) - fpi_const * (sigma_disc2(1)+sigma_disc2(2))
     162              :          end do
     163        34200 :          do imz = ncsh + 1, vacuum%nmz
     164              :             vnew(imz,ivac) = - fpi_const * ( vtemp(imz) + sig1dh * vacuum%dvac - rhobar * vacuum%dvac * vacuum%dvac / 2. ) + vz1dh + vnew(imz,ivac) &
     165        34200 :                            + fpi_const * ( imz - ncsh ) * vacuum%delz * sigmaa(2) !& ! Discontinuity correction
     166              :                            ! - fpi_const * (sigma_disc(1) * ( vacuum%dvac / 2. - (imz-1) * vacuum%delz ) - sigma_disc(2) * ( vacuum%dvac / 2. + (imz-1) * vacuum%delz )) &! Discontinuity correction
     167              :                            ! - fpi_const * (-newdp2-newdm2+newdp * ( vacuum%dvac / 2. - (imz-1) * vacuum%delz ) - newdm * ( vacuum%dvac / 2. + (imz-1) * vacuum%delz )) ! New discontinuity correction
     168              :             !if (present(sigma_disc2)) vnew(imz,ivac) = vnew(imz,ivac) - fpi_const * (sigma_disc2(1)+sigma_disc2(2))
     169              :          end do
     170              :          !if (l_bind) then
     171              :          !   ! Fix the potential to 0 at -infinity and save the resulting value at the vacuum border -D/2
     172              :          !   vnew(:,2) = vnew(:,2) - vnew(vacuum%nmz,2)
     173              :          !   vmz1dh = vnew(1,2)
     174              :          !end if
     175              :          ! Discontinuity correction
     176              :          !if (l_bind) then
     177              :             ! Fix the potential to 0 at -infinity and save the resulting value at the vacuum border -D/2
     178              :             !vnew(:,2) = cmplx(0.0,0.0)
     179              :             !vmz1dh = vnew(1,2)
     180              :          !end if
     181              :       end if ! Dirichlet/Neumann
     182              :    end subroutine vvac
     183              : end module m_vvac
        

Generated by: LCOV version 2.0-1