LCOV - code coverage report
Current view: top level - tetra - resWeight.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 0 179 0.0 %
Date: 2024-05-15 04:28:08 Functions: 0 3 0.0 %

          Line data    Source code
       1             : MODULE m_resWeight
       2             : 
       3             :    IMPLICIT NONE
       4             : 
       5             :    PRIVATE
       6             :    PUBLIC   :: resWeight
       7             : 
       8             :    CONTAINS
       9             : 
      10           0 :    PURE FUNCTION resWeight(eMesh,etetra,ind,vol,film) Result(weights)
      11             : 
      12             :       REAL,       INTENT(IN)     :: eMesh(:)
      13             :       REAL,       INTENT(IN)     :: etetra(:)
      14             :       INTEGER,    INTENT(IN)     :: ind
      15             :       REAL,       INTENT(IN)     :: vol
      16             :       LOGICAL,    INTENT(IN)     :: film
      17             : 
      18             :       REAL :: weights(SIZE(eMesh))
      19             :       INTEGER ie
      20             : 
      21           0 :       IF(.not.film) then
      22           0 :          weights = resWeightBulk(eMesh,etetra,ind) * vol
      23             :       ELSE
      24           0 :          DO ie = 1, SIZE(eMesh)
      25           0 :             IF(film) THEN
      26           0 :                weights(ie) = resWeightFilm(eMesh(ie),etetra,ind) * vol
      27             :             ENDIF
      28             :          ENDDO
      29             :       ENDIF
      30             : 
      31           0 :    END FUNCTION resWeight
      32             : 
      33           0 :    PURE FUNCTION resWeightBulk(eMesh,e,ind) Result(weights)
      34             : 
      35             :       !Calculates resolvent weights for point in tetrahedron (Compare PhysRevB.29.3430)
      36             : 
      37             :       REAL,          INTENT(IN)  :: eMesh(:)
      38             :       REAL,          INTENT(IN)  :: e(:)
      39             :       INTEGER,       INTENT(IN)  :: ind
      40             : 
      41             :       REAL :: weights(SIZE(eMesh))
      42             : 
      43             :       REAL, PARAMETER :: tol = 1e-7!tolerance for degeneracy
      44             :       REAL, PARAMETER :: fac = 5.0
      45             :       REAL, PARAMETER :: highEnergyCut = 0.1
      46             : 
      47             :       REAL a,b,cut,min,z,denom(4)
      48             :       REAL eShift
      49             :       REAL eDeg(4)
      50             :       INTEGER lowerCut,upperCut,ie
      51             :       INTEGER ndeg,i,j,k,l,m
      52             :       INTEGER ideg(6,2)
      53             : 
      54           0 :       REAL, ALLOCATABLE :: eMesh_shifted(:)
      55             :       REAL :: eig_shifted(4)
      56             : 
      57           0 :       eShift = 0.0
      58           0 :       if (MAXVAL(eMesh)*MINVAL(eMesh) < 0.0) then
      59             :          !0 is inside the interval
      60             :          !The asymptotic relations for energies far from the
      61             :          !eigenvalues at the corners has a pole for energies at 0
      62             :          !To prevent these we shift everything (eignevalues and energy grid so that zero)
      63             :          !is far away. This does not change the results for all other cases
      64             :          !Since there only energy differences contribute
      65           0 :          eShift = 2.0*MAX(ABS(MINVAL(eMesh)),ABS(MAXVAL(eMesh)))
      66             :       endif
      67             : 
      68           0 :       weights = 0.0
      69             :       cut = 0.0
      70             :       !
      71           0 :       DO i = 1, 3
      72           0 :          DO j=i+1,4
      73           0 :             IF(ABS(e(i)-e(j)).GT.cut) cut = MAX(ABS(e(i)-e(j)),tol)
      74             :          ENDDO
      75             :       ENDDO
      76             :       !Determine the cutoffs
      77           0 :       upperCut = SIZE(eMesh)
      78           0 :       DO
      79           0 :          IF(MINVAL(ABS(eMesh(upperCut)-e)).LT.fac*cut.OR.upperCut.EQ.1) THEN
      80             :             EXIT
      81           0 :          ELSE IF(MAXVAL(eMesh(upperCut)-e) < 0.0) THEN
      82             :             EXIT
      83             :          ELSE
      84           0 :             upperCut = upperCut - 1
      85             :          ENDIF
      86             :       ENDDO
      87             :       lowerCut = 1
      88           0 :       DO
      89           0 :          IF(MINVAL(ABS(eMesh(lowerCut)-e)).LT.fac*cut.OR.lowerCut.EQ.upperCut) THEN
      90             :             EXIT
      91           0 :          ELSE IF(MINVAL(eMesh(lowerCut)-e) > 0.0) THEN
      92             :             EXIT
      93             :          ELSE
      94           0 :             lowerCut = lowerCut + 1
      95             :          ENDIF
      96             :       ENDDO
      97           0 :       eig_shifted = e(:) - eShift
      98             : 
      99           0 :       ALLOCATE(eMesh_shifted,mold=eMesh)
     100           0 :       eMesh_shifted = eMesh(:) - eShift
     101             : 
     102           0 :       ndeg = 0
     103           0 :       ideg = 0
     104             :       !Search for degenerate eigenvalues
     105           0 :       eDeg = eig_shifted
     106           0 :       DO i = 1, 3
     107           0 :          DO j = i+1,4
     108           0 :             IF(ABS(eig_shifted(i)-eig_shifted(j)).LT.tol) THEN
     109           0 :                ndeg = ndeg + 1
     110           0 :                ideg(ndeg,1) = i
     111           0 :                ideg(ndeg,2) = j
     112             :                !Set the two values equal
     113           0 :                eDeg(i) = (eig_shifted(i)+eig_shifted(j))/2.0
     114           0 :                eDeg(j) = eDeg(i)
     115           0 :                DO k = 1, ndeg-1
     116           0 :                   IF(ideg(k,1).EQ.i.OR.ideg(k,1).EQ.j) THEN
     117           0 :                      eDeg(ideg(k,1)) = (eig_shifted(i)+eig_shifted(j)+eig_shifted(ideg(k,1)))/3.0
     118           0 :                      eDeg(j) = eDeg(ideg(k,1))
     119           0 :                      eDeg(i) = eDeg(ideg(k,1))
     120           0 :                   ELSE IF(ideg(k,2).EQ.i.OR.ideg(k,2).EQ.j) THEN
     121           0 :                      eDeg(ideg(k,2)) = (eig_shifted(i)+eig_shifted(j)+eig_shifted(ideg(k,2)))/3.0
     122           0 :                      eDeg(j) = eDeg(ideg(k,2))
     123           0 :                      eDeg(i) = eDeg(ideg(k,2))
     124             :                   ENDIF
     125             :                ENDDO
     126             :             ENDIF
     127             :          ENDDO
     128             :       ENDDO
     129           0 :       ndeg = 0
     130           0 :       ideg = 0
     131           0 :       DO i = 1, 3
     132           0 :          DO j = i+1,4
     133           0 :             IF(ABS(eDeg(i)-eDeg(j)).LT.tol) THEN
     134           0 :                ndeg = ndeg + 1
     135           0 :                ideg(ndeg,1) = i
     136           0 :                ideg(ndeg,2) = j
     137             :             ENDIF
     138             :          ENDDO
     139             :       ENDDO
     140             : 
     141           0 :       IF(MAXVAL(MAXVAL(eMesh)-e)<-highEnergyCut) THEN
     142           0 :          lowerCut=SIZE(eMesh)
     143           0 :          upperCut=SIZE(eMesh)
     144             :       ENDIF
     145             : 
     146           0 :       IF(MINVAL(MINVAL(eMesh)-e)>highEnergyCut) THEN
     147           0 :          lowerCut=1
     148           0 :          upperCut=1
     149             :       ENDIF
     150             : 
     151             :       !asymptotic relation Eqs. 9-11
     152             :       !the formulas below are unstable for big z arguments
     153           0 :       a = (eDeg(ind) + SUM(eDeg(:)))/5.0
     154           0 :       b = 0.0
     155           0 :       DO j = 1, 4
     156           0 :          IF(j.EQ.ind) CYCLE
     157           0 :          b = b + 3*(eDeg(j)-eDeg(ind))**2
     158           0 :          DO k = 1, 4
     159           0 :             IF(k.EQ.j) CYCLE
     160           0 :             b = b + (eDeg(k)-eDeg(j))**2
     161             :          ENDDO
     162             :       ENDDO
     163           0 :       b = b/300.0
     164             : 
     165           0 :       weights(  :lowerCut) = 0.25/(eMesh_shifted(  :lowerCut)-a-b/eMesh_shifted(  :lowerCut))
     166           0 :       weights(upperCut:) = 0.25/(eMesh_shifted(upperCut:)-a-b/eMesh_shifted(upperCut:))
     167             : 
     168           0 :       IF(lowerCut==upperCut) RETURN
     169             : 
     170             :       IF(ndeg.EQ.0) THEN
     171           0 :          denom = 1.0
     172           0 :          DO i = 1, 4
     173           0 :             DO j = 1, 4
     174           0 :                IF(i.EQ.j) CYCLE
     175           0 :                denom(i) = denom(i)*(eDeg(j)-eDeg(i))
     176             :             ENDDO
     177           0 :             IF(i.EQ.ind) CYCLE
     178           0 :             denom(i) = denom(i)*(eDeg(ind)-eDeg(i))
     179             :          ENDDO
     180           0 :          DO ie = lowerCut, upperCut
     181           0 :             z = eMesh_shifted(ie)
     182             :             !all eigenvalues are non degenerate (EQ.7 from the paper)
     183             :             !First term
     184           0 :             weights(ie) = (z-eDeg(ind))**2/denom(ind)
     185           0 :             DO j = 1, 4
     186           0 :                IF(j.EQ.ind) CYCLE
     187           0 :                weights(ie) = weights(ie) + (z-eDeg(j))**3/denom(j)*LOG(ABS((z-eDeg(j)))/ABS((z-eDeg(ind))))
     188             :             ENDDO
     189             :          ENDDO
     190             : 
     191             :       ELSE IF(ndeg.EQ.1) THEN
     192             : 
     193             :          !Two eigenvalues are degenerate (EQs. A1 A2)
     194             : 
     195           0 :          l = ideg(1,1)
     196           0 :          m = ideg(1,2)
     197             : 
     198           0 :          IF(ind.EQ.l.OR.ind.EQ.m) THEN
     199             :             !EQ. A2
     200             : 
     201             :             !Get the two indices different from l,m and ind
     202             :             j = 0
     203           0 :             DO i = 1, 4
     204           0 :                IF(i.EQ.l.OR.i.EQ.m) CYCLE
     205           0 :                j = i
     206             :             ENDDO
     207             :             k = 0
     208           0 :             DO i = 1, 4
     209           0 :                IF(i.EQ.l.OR.i.EQ.m.OR.i.EQ.j) CYCLE
     210           0 :                k = i
     211             :             ENDDO
     212           0 :             DO ie = lowerCut, upperCut
     213           0 :                z = eMesh_shifted(ie)
     214             :                weights(ie) = (z-eDeg(k))**3/((eDeg(k)-eDeg(j))*(eDeg(k)-eDeg(m))**3)*LOG(ABS(z-eDeg(k))) &
     215             :                             +(z-eDeg(j))**3/((eDeg(j)-eDeg(k))*(eDeg(j)-eDeg(m))**3)*LOG(ABS(z-eDeg(j))) &
     216             :                             +(z-eDeg(m))/((eDeg(m)-eDeg(j))*(eDeg(m)-eDeg(k))) * (0.5 + (z-eDeg(j))/(eDeg(m)-eDeg(j))&
     217             :                            +(z-eDeg(k))/(eDeg(m)-eDeg(k)) + ((z-eDeg(j))**2/(eDeg(m)-eDeg(j))**2 &
     218             :                            +(z-eDeg(k))**2/(eDeg(m)-eDeg(k))**2 +(z-eDeg(j))/(eDeg(m)-eDeg(j))*(z-eDeg(k))/(eDeg(m)-eDeg(k))) &
     219           0 :                            *LOG(ABS(z-eDeg(m))))
     220             :             ENDDO
     221             :          ELSE
     222             :             !k is the one site not equal to ind, l or m
     223             :             k = 0
     224           0 :             DO i = 1, 4
     225           0 :                IF(i.EQ.ind.OR.i.EQ.l.OR.i.EQ.m) CYCLE
     226           0 :                k = i
     227             :             ENDDO
     228             :             !EQ. A1
     229           0 :             DO ie = lowerCut, upperCut
     230           0 :                z = eMesh_shifted(ie)
     231             :                weights(ie) = (z-eDeg(ind))**2/((eDeg(ind)-eDeg(m))**2*(eDeg(k)-eDeg(ind))) *&
     232             :                         (1 + (2*(z-eDeg(m))/(eDeg(ind)-eDeg(m))+(z-eDeg(k))/(eDeg(ind)-eDeg(k)))*LOG(ABS(z-eDeg(ind)))) &
     233             :                        +(z-eDeg(m))**2/((eDeg(m)-eDeg(ind))**2*(eDeg(k)-eDeg(m))) *&
     234             :                         (1 + (2*(z-eDeg(ind))/(eDeg(m)-eDeg(ind))+(z-eDeg(k))/(eDeg(m)-eDeg(k)))*LOG(ABS(z-eDeg(m)))) &
     235           0 :                        +(z-eDeg(k))**3/((eDeg(k)-eDeg(ind))**2*(eDeg(k)-eDeg(m))**2)*LOG(ABS(z-eDeg(k)))
     236             :             ENDDO
     237             :          ENDIF
     238             :       ELSE IF(ndeg.EQ.2) THEN
     239             :          !This is the case E1=E2<E3=E4 => A4
     240           0 :          IF(ind.LE.2) THEN
     241           0 :             DO ie = lowerCut, upperCut
     242           0 :                z = eMesh_shifted(ie)
     243             :                weights(ie) = 3.0*(z-eDeg(3))**2*(z-eDeg(2))/(eDeg(3)-eDeg(2))**4*LOG(ABS((z-eDeg(2)))/ABS((z-eDeg(3)))) &
     244           0 :                             - 3.0/2.0*(z-eDeg(2))*(2*(z-eDeg(3))-eDeg(3)+eDeg(2))/(eDeg(3)-eDeg(2))**3-1.0/(eDeg(3)-eDeg(2))
     245             :             ENDDO
     246             :          ELSE
     247           0 :             DO ie = lowerCut, upperCut
     248           0 :                z = eMesh_shifted(ie)
     249             :                weights(ie) = 3.0*(z-eDeg(2))**2*(z-eDeg(3))/(eDeg(3)-eDeg(2))**4*LOG(ABS((z-eDeg(3)))/ABS((z-eDeg(2)))) &
     250           0 :                             + 3.0/2.0*(z-eDeg(3))*(2*(z-eDeg(2))+eDeg(3)-eDeg(2))/(eDeg(3)-eDeg(2))**3+1.0/(eDeg(3)-eDeg(2))
     251             :             ENDDO
     252             :          ENDIF
     253             :       ELSE IF(ndeg.GE.3 .AND. ndeg.LT.6) THEN
     254             :          !EQs A3/A5 (here we explicitly write each weight)
     255           0 :          IF(ALL(ideg(:,:).NE.4)) THEN
     256             :             !A3
     257           0 :             IF(ind.NE.4) THEN
     258           0 :                DO ie = lowerCut, upperCut
     259           0 :                   z = eMesh_shifted(ie)
     260             :                   weights(ie) = (z-eDeg(4))**3/(eDeg(4)-eDeg(3))**4*LOG(ABS((z-eDeg(4))/(z-eDeg(3)))) &
     261           0 :                             + (6*(z-eDeg(4))**2-3*(eDeg(4)-eDeg(3))*(z-eDeg(4))+2*(eDeg(4)-eDeg(3))**2)/(6*(eDeg(4)-eDeg(3))**3)
     262             :                ENDDO
     263             :             ELSE
     264           0 :                DO ie = lowerCut, upperCut
     265           0 :                   z = eMesh_shifted(ie)
     266             :                   weights(ie) = 3.0*(z-eDeg(4))**2*(z-eDeg(3))/(eDeg(4)-eDeg(3))**4*LOG(ABS((z-eDeg(3))/(z-eDeg(4)))) &
     267           0 :                             - 3.0/2.0*(z-eDeg(3))*(2*(z-eDeg(4))-eDeg(4)+eDeg(3))/(eDeg(4)-eDeg(3))**3-1.0/(eDeg(4)-eDeg(3))
     268             :                ENDDO
     269             :             ENDIF
     270           0 :          ELSE IF(ALL(ideg(:,:).NE.1)) THEN
     271             :             !A5
     272           0 :             IF(ind.EQ.1) THEN
     273           0 :                DO ie = lowerCut, upperCut
     274           0 :                   z = eMesh_shifted(ie)
     275             :                   weights(ie) = 3.0*(z-eDeg(1))**2*(z-eDeg(2))/(eDeg(2)-eDeg(1))**4*LOG(ABS((z-eDeg(2))/(z-eDeg(1)))) &
     276           0 :                             + 3.0/2.0*(z-eDeg(2))*(2*(z-eDeg(1))-eDeg(1)+eDeg(2))/(eDeg(2)-eDeg(1))**3+1.0/(eDeg(2)-eDeg(1))
     277             :                ENDDO
     278             :             ELSE
     279           0 :                DO ie = lowerCut, upperCut
     280           0 :                   z = eMesh_shifted(ie)
     281             :                   weights(ie) = (z-eDeg(1))**3/(eDeg(2)-eDeg(1))**4*LOG(ABS((z-eDeg(1))/(z-eDeg(2)))) &
     282           0 :                             - (6*(z-eDeg(1))**2+3*(z-eDeg(1))*(eDeg(2)-eDeg(1))+2*(eDeg(2)-eDeg(1))**2)/(6*(eDeg(2)-eDeg(1))**3)
     283             :                ENDDO
     284             :             ENDIF
     285             :          ENDIF
     286             :       ELSE IF(ndeg.EQ.6) THEN
     287             :          !Eq. A6
     288           0 :          weights(lowerCut:upperCut) = 0.25/(eMesh_shifted(lowerCut:upperCut)-eDeg(1))
     289             :       ENDIF
     290           0 :    END FUNCTION resWeightBulk
     291             : 
     292           0 :    PURE REAL FUNCTION resWeightFilm(z,e,ind)
     293             : 
     294             :       !Calculates resolvent weights for point in triangle (Compare Solid State Phys. 20 (1987) 4823-4831.)
     295             : 
     296             :       REAL,          INTENT(IN)  :: z
     297             :       REAL,          INTENT(IN)  :: e(:)
     298             :       INTEGER,       INTENT(IN)  :: ind
     299             : 
     300             :       REAL, PARAMETER :: tol = 1e-8!tolerance for degeneracy
     301             :       REAL, PARAMETER :: fac = 4.0
     302             : 
     303             :       REAL denom,a,b,cut,min,prod
     304             :       INTEGER ndeg,i,j,k,l,m
     305             :       INTEGER ideg(2,2)
     306             : 
     307           0 :       min = 9e+20
     308           0 :       cut = 0.0
     309           0 :       DO i = 1, 2
     310           0 :          DO j=i+1,3
     311           0 :             IF(ABS(e(i)-e(j)).GT.cut) cut = MAX(ABS(e(i)-e(j)),tol)
     312             :          ENDDO
     313             :       ENDDO
     314             : 
     315           0 :       DO i =1, 3
     316           0 :          IF(ABS(z-e(i)).LT.min) min = ABS(z-e(i))
     317             :       ENDDO
     318           0 :       ndeg = 0
     319           0 :       ideg = 0
     320           0 :       IF(min.GT.fac*cut) THEN
     321             :          !asymptotic relation Eqs. 9-11
     322             :          !the formulas below are unstable for big z arguments
     323           0 :          a = (e(ind) + SUM(e(:)))/4.0
     324           0 :          b = 3*e(ind)**2
     325           0 :          prod = 1.0
     326           0 :          DO j = 1,3
     327           0 :             IF(j.EQ.ind) CYCLE
     328           0 :             b = b + 2*e(ind)*e(j)+e(j)**2
     329           0 :             prod = prod * e(j)
     330             :          ENDDO
     331           0 :          b = (b+prod)/300.0
     332           0 :          resWeightFilm = 1.0/3.0/(z-a-b/z)
     333             :          !The asymptotic relationship has a divergence at z=0
     334             :          !For now we drop the 1/z term in the denominator here
     335           0 :          IF(ABS(z).LT.2e-2) resWeightFilm = 1.0/3.0/(z-a)
     336             :       ELSE
     337             :          !Search for degenerate eigenvalues
     338           0 :          DO i = 1, 2
     339           0 :             DO j = i+1,3
     340           0 :                IF(ABS(e(i)-e(j)).LT.tol) THEN
     341           0 :                   ndeg = ndeg + 1
     342           0 :                   ideg(ndeg,1) = i
     343           0 :                   ideg(ndeg,2) = j
     344             :                ENDIF
     345             :             ENDDO
     346             :          ENDDO
     347           0 :          resWeightFilm = 0.0
     348           0 :          IF(ndeg.EQ.0) THEN
     349             : 
     350             :             !all eigenvalues are non degenerate
     351             :             denom = 1.0
     352           0 :             DO i = 1, 3
     353           0 :                IF(i.EQ.ind) CYCLE
     354           0 :                denom = denom*(e(i)-e(ind))
     355             :             ENDDO
     356             :             !First term
     357           0 :             resWeightFilm = (z-e(ind))/denom
     358           0 :             DO j = 1, 3
     359           0 :                IF(j.EQ.ind) CYCLE
     360             :                denom = 1.0
     361           0 :                DO i = 1, 3
     362           0 :                   IF(i.EQ.j) CYCLE
     363           0 :                   denom = denom*(e(i)-e(j))
     364             :                ENDDO
     365           0 :                resWeightFilm = resWeightFilm + (z-e(j))**2/denom*LOG(ABS((z-e(j))/(z-e(ind))))/(e(ind)-e(j))
     366             :             ENDDO
     367           0 :          ELSE IF(ndeg.EQ.1) THEN
     368             : 
     369           0 :             IF(ALL(ideg(:,:).NE.3)) THEN
     370           0 :                IF(ind.NE.3) THEN
     371             :                   resWeightFilm =  (z-e(3))**2/((e(1)-e(3))**3)*LOG(ABS((z-e(3))/(z-e(1)))) &
     372           0 :                                   -(z-e(1))/(e(3)-e(1))**2+1.5/(e(3)-e(1))
     373             :                ELSE
     374             :                   resWeightFilm =  (z-e(3))/((e(1)-e(3))*(e(2)-e(3))) &
     375             :                                   - 2*(z-e(1))*(z-e(3))/(e(3)-e(1))**3 * LOG(ABS((z-e(1))/(z-e(3)))) &
     376           0 :                                    +(z-e(1))/(e(3)-e(1))**2
     377             :                ENDIF
     378             :             ELSE
     379           0 :                IF(ind.EQ.1) THEN
     380             :                   resWeightFilm =  (z-e(1))/((e(2)-e(1))*(e(3)-e(1))) &
     381             :                                   - 2*(z-e(1))*(z-e(3))/(e(1)-e(3))**3 * LOG(ABS((z-e(3))/(z-e(1)))) &
     382           0 :                                    +(z-e(3))/(e(1)-e(3))**2
     383             :                ELSE
     384             :                   resWeightFilm =  (z-e(1))**2/((e(3)-e(1))**3)*LOG(ABS((z-e(1))/(z-e(3)))) &
     385           0 :                                   -(z-e(1))/(e(1)-e(3))**2+0.5/(e(1)-e(3))
     386             :                ENDIF
     387             :             ENDIF
     388             : 
     389             :          ELSE
     390           0 :             resWeightFilm = 1.0/3.0 * 1/(z-e(1))
     391             :          ENDIF
     392             :       ENDIF
     393             : 
     394           0 :    END FUNCTION resWeightFilm
     395             : 
     396             : END MODULE m_resWeight

Generated by: LCOV version 1.14