LCOV - code coverage report
Current view: top level - vgen - vintcz.f90 (source / functions) Coverage Total Hit
Test: FLEUR test coverage Lines: 73.3 % 86 63
Test Date: 2026-04-29 04:40:47 Functions: 50.0 % 2 1

            Line data    Source code
       1              : MODULE m_vintcz
       2              :   !     *************************************************************
       3              :   !     z-dependent part of Coulomb potential in the interstitial   *
       4              :   !     [-d/2,d/2] region            c.l.fu, r.podloucky            *
       5              :   !     *************************************************************
       6              :   !     modified for thick films to avoid underflows gb`06
       7              :   !---------------------------------------------------------------
       8              : CONTAINS
       9      4303119 :    COMPLEX FUNCTION vintcz(stars,vacuum,cell,input,field,z,nrec2,psq,vnew,rhobar,sig1dh,vz1dh,alphm,vslope,l_dfptvgen)
      10              :       USE m_constants
      11              :       USE m_types
      12              : 
      13              :       IMPLICIT NONE
      14              : 
      15              :       TYPE(t_stars),  INTENT(IN) :: stars
      16              :       TYPE(t_vacuum), INTENT(IN) :: vacuum
      17              :       TYPE(t_cell),   INTENT(IN) :: cell
      18              :       TYPE(t_input),  INTENT(IN) :: input
      19              :       TYPE(t_field),  INTENT(IN) :: field
      20              : 
      21              :       INTEGER,        INTENT(IN) :: nrec2
      22              :       COMPLEX,        INTENT(IN) :: rhobar,vslope
      23              :       COMPLEX,        INTENT(IN) :: sig1dh,vz1dh
      24              :       REAL,           INTENT(IN) :: z
      25              : 
      26              :       COMPLEX,        INTENT(IN) :: psq(stars%ng3),vnew(:,:,:)!,vxy(:,:,:) !(vacuum%nmzxyd,stars%ng2-1,2)
      27              :       COMPLEX,        INTENT(IN) :: alphm(stars%ng2,2)
      28              :       !complex,        intent(in) :: sigma_disc(2)
      29              :       LOGICAL,        INTENT(IN) :: l_dfptvgen !, l_corr
      30              :       !COMPLEX,        INTENT(IN) :: diff_vmz1dh
      31              : 
      32              :       !complex, optional, intent(in) :: sigma_disc2(2)
      33              :       !REAL,           INTENT(IN) :: vz(:,:) !(vacuum%nmzd,2,jspins)
      34              : 
      35              :       COMPLEX                    :: argr,sumrr,vcons1,test,c_ph,phas
      36              :       REAL                       :: bj0,dh,fit,g,g3,q,qdh,vcons2,zf
      37              :       REAL                       :: e_m,e_p,cos_q,sin_q
      38              :       INTEGER                    :: ig3n,im,iq,ivac,k1,k2,nrec2r
      39              :       !COMPLEX                    :: newdp, newdm, newdp2, newdm2
      40              :       
      41      4303119 :       dh = cell%z1
      42      4303119 :       sumrr = (0.,0.)
      43      4303119 :       vintcz = (0.,0.)
      44              : 
      45              :       ! newdp = CMPLX(0.0,0.0)
      46              :       ! newdm = CMPLX(0.0,0.0)
      47              :       ! newdp2 = CMPLX(0.0,0.0)
      48              :       ! newdm2 = CMPLX(0.0,0.0)
      49              :       
      50              :       !--->    if z is in the vacuum, use vacuum representations (m.w.)
      51      4303119 :       IF (ABS(z).GE.cell%z1) THEN
      52      1967916 :          ivac = 1
      53      1967916 :          IF (z.LT.0.0) THEN
      54       972672 :             ivac = 2
      55      1967916 :             IF (vacuum%nvac==1) ivac = 1
      56              :          END IF
      57      1967916 :          zf = (ABS(z)-cell%z1)/vacuum%delz + 1.0
      58      1967916 :          im = zf
      59      1967916 :          q = zf - im
      60              :          ! For q/=0 in DFPT, the is no G+q=0, so all stars are treated in the G/=0 way.
      61      7871664 :          IF (nrec2.EQ.1.AND.((.NOT.l_dfptvgen).OR.norm2(stars%center)<1e-8)) THEN
      62              :             fit = 0.5* (q-1.)* (q-2.)*REAL(vnew(im,1,ivac)) -&
      63              :                &            q* (q-2.)*REAL(vnew(im+1,1,ivac)) +&
      64         8147 :                &        0.5*q* (q-1.)*REAL(vnew(im+2,1,ivac))
      65         8147 :             vintcz = CMPLX(fit,0.0)
      66      1959769 :          ELSE IF (im+2.LE.vacuum%nmzxy) THEN
      67      1959769 :             if (z<0) THEN 
      68       968641 :                call stars%map_2nd_vac(vacuum,nrec2,nrec2r,phas) ! TODO: AN TB; will this work?
      69              :             else
      70       991128 :                nrec2r=nrec2 
      71       991128 :                phas=cmplx(1.0,0.0)
      72              :             end if      
      73              :             vintcz = phas*0.5* (q-1.)* (q-2.)*vnew(im,nrec2r,ivac) -&
      74              :                                     q* (q-2.)*vnew(im+1,nrec2r,ivac) +&
      75      1959769 :                                 0.5*q* (q-1.)*vnew(im+2,nrec2r,ivac)
      76              :          END IF
      77      1967916 :          RETURN
      78              :       END IF
      79              : 
      80              :       ! For q/=0 in DFPT, there is no G+q=0, so all stars are treated in the G/=0 way.
      81      9340812 :       IF (nrec2==1.AND.((.NOT.l_dfptvgen).OR.norm2(stars%center)<1e-8)) THEN    !     ---->    g=0 coefficient
      82              : 
      83              :          ! ! New discontinuity correction
      84              :          ! IF (l_corr) THEN
      85              :          !    newdp = - psq(1) * dh
      86              :          !    newdp2 = -psq(1) * dh**2 
      87              :          ! END IF
      88              : 
      89       517698 :          DO  iq = -stars%mx3,stars%mx3
      90       508076 :             IF (iq.EQ.0) CYCLE
      91       498454 :             ig3n = stars%ig(0,0,iq)
      92              :             !     ----> use only stars within the g_max sphere (oct.97 shz)
      93       508076 :             IF (ig3n.NE.0) THEN
      94       479210 :                q = iq*cell%bmat(3,3)
      95       479210 :                qdh = q*dh
      96       479210 :                bj0 = SIN(qdh)/qdh
      97       479210 :                argr = ImagUnit*q*z
      98       479210 :                sumrr = (EXP(argr)-EXP(ImagUnit*qdh))/ (q*q) + ImagUnit*COS(qdh)* (dh-z)/q + bj0* (z*z-dh*dh)/2.
      99       479210 :                vintcz = vintcz + fpi_const*psq(ig3n)*sumrr
     100              :                
     101              :                ! ! New discontinuity correction
     102              :                ! IF (l_corr) THEN
     103              :                !    newdp = newdp + ImagUnit * psq(ig3n) * cmplx(cos(qdh), sin(qdh)) * dh / qdh
     104              :                !    newdp2 = newdp2 + psq(ig3n) * cmplx(cos(qdh), sin(qdh)) / q**2
     105              :                ! END IF
     106              :             END IF
     107              :          END DO
     108              :          !           -----> v2(z)
     109              :          vintcz = vintcz + vz1dh - fpi_const* (dh-z)*&
     110         9622 :             &              (sig1dh-rhobar/2.* (dh-z))
     111              :          
     112              :          ! ! Discontinuity correction
     113              :          ! vintcz = vintcz - fpi_const * sigma_disc(1)*(dh-z)
     114              :          ! !IF (PRESENT(sigma_disc2)) vintcz = vintcz + fpi_const * sigma_disc2(1)
     115              : 
     116              :          ! ! New discontinuity correction
     117              :          ! IF (l_dfptvgen.AND.l_corr) vintcz = vintcz - fpi_const * newdp * (dh-z) + fpi_const * newdp2
     118              : 
     119              :          ! Correct the interstitial potential by the mismatch we calculated as
     120              :          ! a boundary condition for DFPT q=0.
     121              :          !IF (l_dfptvgen) vintcz = vintcz - diff_vmz1dh*z/(2*dh) + diff_vmz1dh/2
     122              : 
     123         9622 :          IF (field%efield%dirichlet .AND. vslope /= 0.0) THEN
     124            0 :             vintcz = vintcz + vslope * (dh-z)
     125              :          END IF
     126              :          !     ---->    (g.ne.0)  coefficients
     127              :       ELSE
     128      2325581 :          k1 = stars%kv2(1,nrec2)
     129      2325581 :          k2 = stars%kv2(2,nrec2)
     130              : 
     131              :          !newdp = cmplx(0.0,0.0)
     132              :          !newdm = cmplx(0.0,0.0)
     133              :          !newdp2 = cmplx(0.0,0.0)
     134              :          !newdm2 = cmplx(0.0,0.0)
     135              : 
     136    118105238 :          DO  iq = -stars%mx3,stars%mx3
     137    115779657 :             ig3n = stars%ig(k1,k2,iq)
     138              :             !     ----> use only stars within the g_max sphere (oct.97 shz)
     139    118105238 :             IF (ig3n.NE.0) THEN
     140    105476161 :                c_ph = stars%rgphs(k1,k2,iq)
     141              :                !           -----> v3(z)
     142    105476161 :                q = iq*cell%bmat(3,3)
     143    105476161 :                g = stars%sk2(nrec2)
     144    105476161 :                g3 = stars%sk3(ig3n)
     145    105476161 :                vcons1 = fpi_const*psq(ig3n)*c_ph / (g3*g3)
     146    105476161 :                IF (field%efield%dirichlet) THEN
     147            0 :                   e_m = 0.0
     148            0 :                   e_p = 0.0
     149            0 :                   vcons1  = vcons1/(g*SINH(g*2*(dh+field%efield%zsigma)))
     150            0 :                   e_m = e_m - EXP(-ImagUnit*q*dh)*(g*COSH(g*(-field%efield%zsigma))+ImagUnit*q*SINH(g*(-field%efield%zsigma)))
     151            0 :                   e_p = e_p + EXP(ImagUnit*q*dh)*(-g*COSH(g*(-field%efield%zsigma))+ImagUnit*q*SINH(g*(-field%efield%zsigma)))
     152            0 :                   sumrr = EXP(ImagUnit*q*z)
     153            0 :                   e_m = e_m + sumrr*(g*COSH(g*(z+dh+field%efield%zsigma))-ImagUnit*q*SINH(g*(z+dh+field%efield%zsigma)))
     154            0 :                   e_p = e_p + sumrr*(g*COSH(g*(z-dh-field%efield%zsigma))-ImagUnit*q*SINH(g*(z-dh-field%efield%zsigma)))
     155              :                   vintcz = vintcz+ vcons1*(e_m*SINH(g*(field%efield%zsigma+dh-z))&
     156            0 :                                           +e_p*SINH(g*(field%efield%zsigma+dh+z)))
     157              :                ELSE
     158    105476161 :                   sumrr = (0.0,0.0)
     159    105476161 :                   vcons2 = - 1.0 / (2.*g)
     160    210952322 :                   e_m = exp_safe( -g*(z+dh) ) !exp_safe handles overflow
     161    210952322 :                   e_p = exp_safe( g*(z-dh) )
     162              :                   !               --> sum over gz-stars
     163    105476161 :                   cos_q = COS(q*dh)
     164    105476161 :                   sin_q = SIN(q*dh)
     165              :                   sumrr = sumrr + CMPLX(COS(q*z),SIN(q*z)) + vcons2 *&
     166              :                         &                      ( (g + ImagUnit*q) * e_p * (cos_q + ImagUnit*sin_q) +&
     167    105476161 :                         &                        (g - ImagUnit*q) * e_m * (cos_q - ImagUnit*sin_q) )
     168    105476161 :                   vintcz = vintcz + vcons1*sumrr
     169              : 
     170              :                   ! ! New discontinuity correction
     171              :                   ! IF (iq==0.AND.l_corr) newdp = newdp - psq(ig3n) * dh
     172              :                   ! IF (iq/=0.AND.l_corr) newdp = newdp + ImagUnit * psq(ig3n) * cmplx(cos_q, sin_q) * dh / (q*dh)
     173              :                   ! IF (iq==0.AND.l_corr) newdm = newdm - psq(ig3n) * dh
     174              :                   ! IF (iq/=0.AND.l_corr) newdm = newdm - ImagUnit * psq(ig3n) * cmplx(cos_q,-sin_q) * dh / (q*dh)
     175              :                   ! IF (iq==0.AND.l_corr) newdp2 = newdp2 - psq(ig3n) * dh**2
     176              :                   ! IF (iq/=0.AND.l_corr) newdp2 = newdp2 + psq(ig3n) * cmplx(cos_q, sin_q) / q**2
     177              :                   ! IF (iq==0.AND.l_corr) newdm2 = newdm2 + psq(ig3n) * dh**2
     178              :                   ! IF (iq/=0.AND.l_corr) newdm2 = newdm2 - psq(ig3n) * cmplx(cos_q,-sin_q) / q**2
     179              : 
     180              :                END IF ! Neumann (vs. Dirichlet)
     181              :             END IF ! ig3d /= 0
     182              :          END DO
     183              :          !  ----> v4(z)
     184      2325581 :          IF (field%efield%dirichlet) THEN
     185            0 :             e_m = SINH(g*(field%efield%zsigma+dh - z))
     186            0 :             e_p = SINH(g*(field%efield%zsigma+dh + z))
     187            0 :             test = e_m*alphm(nrec2,2) + e_p*alphm(nrec2,1)
     188            0 :             test = fpi_const/(g*SINH(g*2*(field%efield%zsigma+dh))) * test
     189            0 :             IF ( 2.0 * test == test ) test = CMPLX(0.0,0.0)
     190            0 :             vintcz = vintcz + test
     191            0 :             IF (ALLOCATED (field%efield%C1)) THEN
     192            0 :                g = stars%sk2(nrec2)
     193            0 :                e_m = exp_safe (-g*z)
     194            0 :                e_p = exp_safe ( g*z)
     195              :                vintcz = vintcz + field%efield%C1(nrec2-1)*e_m &
     196            0 :                   &            + field%efield%C2(nrec2-1)*e_p
     197              :             END IF
     198              :          ELSE ! Neumann
     199      4651162 :             e_m = exp_safe( -g*z  )
     200      4651162 :             e_p = exp_safe( g*z  )
     201      2325581 :             test = e_m*alphm(nrec2,2) + e_p*alphm(nrec2,1)
     202      2325581 :             IF ( 2.0 * test == test ) test = CMPLX(0.0,0.0)
     203      2325581 :             vintcz = vintcz + tpi_const/g* test
     204              : 
     205              :             ! New discontinuity correction
     206              :             !IF (l_dfptvgen.AND.l_corr.AND.nrec2==1) THEN
     207              :             !   e_m = exp_safe( - g * abs(z-cell%z1) )
     208              :             !   e_p = exp_safe( - g * abs(z+cell%z1) )
     209              :             !   test = e_m * newdp + e_p * newdm
     210              :             !   if ( 2.0 * test == test ) test = cmplx( 0.0, 0.0 )
     211              :             !   vintcz = vintcz + tpi_const/g * test
     212              :             !   !IF (abs(z-cell%z1)<1e-9) e_m = 0.0
     213              :             !   !IF (abs(z+cell%z1)<1e-9) e_p = 0.0
     214              :             !   test = e_m * newdp2 * sign(1.0,z-cell%z1)+ e_p * newdm2 * sign(1.0,z+cell%z1)
     215              :             !   if ( 2.0 * test == test ) test = cmplx( 0.0, 0.0 )
     216              :             !   vintcz = vintcz - tpi_const * test
     217              :             !END IF
     218              : 
     219              :          END IF
     220              :       END IF
     221              :    END FUNCTION vintcz
     222              : 
     223    215603484 :    PURE REAL FUNCTION exp_safe(x)
     224              :       ! replace exp by a function that does not under/overflow dw09
     225              :       IMPLICIT NONE
     226              : 
     227              :       REAL, INTENT(IN) :: x
     228              :       REAL, PARAMETER  :: maxexp = LOG(2.0)*MAXEXPONENT(2.0)
     229              :       REAL, PARAMETER  :: minexp = LOG(2.0)*MINEXPONENT(2.0)
     230              : 
     231    215603484 :       IF ( ABS(x)>minexp .AND. ABS(x)<maxexp ) THEN
     232    215603484 :          exp_safe = EXP(x)
     233              :       ELSE
     234            0 :          IF ( x > 0 ) THEN
     235              :             IF ( x > minexp ) THEN
     236              :                exp_safe = EXP(maxexp)
     237              :             ELSE
     238              :                exp_safe = EXP(minexp)
     239              :             END IF
     240              :          ELSE
     241              :             IF ( -x > minexp ) THEN
     242              :                exp_safe = EXP(-maxexp)
     243              :             ELSE
     244              :                exp_safe = EXP(-minexp)
     245              :             END IF
     246              :          END IF
     247              :       END IF
     248            0 :    END FUNCTION exp_safe
     249              : END MODULE m_vintcz
        

Generated by: LCOV version 2.0-1