LCOV - code coverage report
Current view: top level - fermi - fertri.f90 (source / functions) Hit Total Coverage
Test: FLEUR test coverage Lines: 52 91 57.1 %
Date: 2024-04-28 04:28:00 Functions: 1 1 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------
       2             : ! Copyright (c) 2016 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             : MODULE m_fertri
       7             :    !
       8             :    !     calculates fermi energy and weights using triangular (tetrahedron) method
       9             :    !
      10             :    USE m_juDFT
      11             :    USE m_types
      12             :    USE m_constants
      13             :    USE m_tetraef
      14             :    USE m_dosef
      15             :    USE m_dosint
      16             :    USE m_doswt
      17             :    USE m_xmlOutput
      18             : 
      19             :    IMPLICIT NONE
      20             : 
      21             :    CONTAINS
      22             : 
      23           2 :    SUBROUTINE fertri(input,noco,kpts,irank,ne,jspins,zc,eig,sfac,&
      24           2 :                      ef,seigv,w,l_output)
      25             : 
      26             :       TYPE(t_input), INTENT(IN)    :: input
      27             :       TYPE(t_noco),    INTENT(IN)    :: noco
      28             :       TYPE(t_kpts),  INTENT(IN)    :: kpts
      29             :       INTEGER,       INTENT(IN)    :: jspins,irank
      30             :       REAL,          INTENT(IN)    :: zc,sfac
      31             :       INTEGER,       INTENT(IN)    :: ne(:,:)!(nkpt,jspins)
      32             :       REAL,          INTENT(OUT)   :: seigv
      33             :       REAL,          INTENT(INOUT) :: ef
      34             :       REAL,          INTENT(OUT)   :: w(:,:,:) !(neig,nkpt,jspins)
      35             :       REAL,          INTENT(INOUT) :: eig(:,:,:)!(neig,nkpt,jspins)
      36             :       LOGICAL,       INTENT(IN)    :: l_output
      37             : 
      38             :       REAL    :: chmom,ct,del,dez,ei,emax,emin,s,s1,workf
      39             :       REAL    :: lb,ub,e_set,seigvTemp
      40             :       INTEGER :: i,ic,j,jsp,k,neig,jj
      41             :       INTEGER :: nemax(2)
      42             :       CHARACTER(LEN=20)    :: attributes(2)
      43             :       REAL, PARAMETER :: de = 5.0e-3 !Step for initial search
      44             : 
      45           2 :       IF (irank == 0 .and. l_output) THEN
      46           2 :          WRITE (oUnit,FMT=8000)
      47             : 8000     FORMAT (/,/,10x,'linear triangular method')
      48             :       END IF
      49         764 :       w=0.0
      50             :       !
      51             :       !--->   clear w and set eig=-9999.9
      52           2 :       e_set = -9999.9
      53           2 :       IF (.NOT.input%film) e_set = 1.0e10
      54           4 :       DO jsp = 1,jspins
      55           2 :          nemax(jsp) = 0.0
      56          44 :          DO k = 1,kpts%nkpt
      57          40 :             nemax(jsp) = max0(nemax(jsp),ne(k,jsp))
      58         760 :             DO i = 1,ne(k,jsp)
      59         760 :                w(i,k,jsp) = 0.
      60             :             ENDDO
      61          42 :             DO i = ne(k,jsp)+1,size(w,1)
      62           0 :                w(i,k,jsp) = 0.
      63          40 :                eig(i,k,jsp) = e_set
      64             :             ENDDO
      65             :          ENDDO
      66             :       ENDDO
      67             :       !
      68             :       !      sfac = 2.0/real(jspins)
      69             : 
      70           2 :       IF(.not.input%film) THEN
      71         764 :          lb = MINVAL(eig) - 0.01
      72           2 :          ub = ef + 0.2
      73           2 :          CALL tetra_ef(kpts,jspins,lb,ub,eig,zc,sfac,ef,w,l_output)
      74             :       ELSE
      75           0 :          IF (irank == 0) THEN
      76           0 :             WRITE (oUnit,FMT=*) 'ef_hist=',ef
      77             :          END IF
      78             : 
      79           0 :          ei = ef
      80             : !jr      emin = -9999.9
      81           0 :          emin = +9999.9
      82           0 :          emax = -emin
      83             :          !Find initial boundaries for the bisection method
      84           0 :          ic = 1
      85           0 :          DO WHILE (emin.GT.emax)
      86           0 :             ic = ic + 1
      87             : 
      88           0 :             CALL dosint(ei,nemax,jspins,kpts,sfac,eig,ct)
      89             : 
      90           0 :             IF (irank == 0 .and. l_output) WRITE (oUnit,FMT=*) 'ct=',ct
      91             : 
      92           0 :             IF (ct.LT.zc) THEN ! ei < ef
      93           0 :                emin = ei
      94           0 :                ei = ei + de
      95           0 :             ELSEIF (ct.GT.zc) THEN ! ei > ef
      96           0 :                emax = ei
      97           0 :                ei = ei - de
      98             :             ENDIF
      99             : 
     100           0 :             IF (irank==0 .AND. ic.GT.100) THEN
     101           0 :                WRITE (oUnit,FMT=8050) ei,ef,emin,emax,ct,zc
     102             : 8050           FORMAT (/,/,10x,'error fertri: initial guess of ef off by 25 mry',&
     103             :                         ' ei,ef,emin,emax,ct,zc',/,10x,6e16.7,/,10x,&
     104             :                         'check number of bands')
     105           0 :                CALL juDFT_error("initial guess of ef off by 25 mry",calledby="fertri")
     106             :             END IF
     107             : 
     108             :          ENDDO
     109             : 
     110           0 :          IF (ct.NE.zc) THEN
     111           0 :             IF (irank == 0 .and. l_output) WRITE (oUnit,FMT=*) '2nd dosint'
     112             :             !---> refine ef to a value of 5 mry * (2**-20)
     113           0 :             iterate : DO i = 1, 40
     114           0 :                ei = 0.5* (emin+emax)
     115             : 
     116           0 :                CALL dosint(ei,nemax,jspins,kpts,sfac,eig,ct)
     117             : 
     118           0 :                IF (irank == 0) WRITE (oUnit,FMT=*) 'i=',i,', ct=',ct
     119           0 :                IF ( ct == zc ) THEN
     120             :                   EXIT iterate
     121           0 :                ELSEIF ( ct > zc ) THEN
     122           0 :                   emax = ei
     123             :                ELSE
     124           0 :                   emin = ei
     125             :                ENDIF
     126             :             ENDDO iterate
     127             :          ENDIF
     128           0 :          ef = ei
     129           0 :          del = emax - emin
     130           0 :          dez = zc - ct
     131           0 :          workf = -hartree_to_ev_const*ef
     132           0 :          IF (irank == 0 .and. l_output) THEN
     133           0 :             WRITE (oUnit,FMT=8030) ef,workf,del,dez
     134             : 8030        FORMAT(/,10x,'fermi energy=',f10.5,' har',/,10x,'work function='&
     135             :                     ,f10.5,' ev',/,10x,'uncertainity in energy and weights=',&
     136             :                      2e16.6)
     137             :          END IF
     138             :          !
     139             :          !--->   obtain dos at ef
     140             :          !
     141           0 :          CALL dosef(ei,nemax,jspins,kpts,sfac,eig,l_output)
     142             :          !
     143             :          !--->   obtain weights needed for integration
     144             :          !
     145           0 :          CALL doswt(ei,nemax,jspins,kpts,eig,w)
     146             : 
     147             :       ENDIF ! .NOT.input%film
     148             : 
     149             :       !
     150             :       !--->   write weights
     151             :       !
     152             : !     DO jsp = 1,jspins
     153             : !        neig = nemax(jsp)
     154             : !        DO i = 1,neig
     155             : !           DO k = 1,kpts%nkpt
     156             : !              WRITE (oUnit,FMT=*) 'w(',i,',',k,',',jsp,')=',w(i,k,jsp)
     157             : !           ENDDO
     158             : !        ENDDO
     159             : !     ENDDO
     160             : 
     161             :       !find degenerate states
     162           4 :      DO jsp=1,jspins
     163          44 :          DO k=1,kpts%nkpt
     164          40 :             i=1   
     165         546 :             DO while(i<nemax(jsp))
     166             :                j=1
     167         680 :                do while (abs(eig(i,k,jsp)-eig(i+j,k,jsp))<1E-9)
     168         196 :                   j=j+1
     169         680 :                   if (i+j>nemax(jsp)) exit
     170             :                ENDDO
     171         504 :                if (j>1) THEN
     172         176 :                   j=j-1
     173             :                   !Make sure all weights are equal
     174         920 :                   w(i:i+j,k,jsp)=sum(w(i:i+j,k,jsp))/(j+1)
     175         176 :                   i=i+j
     176             :                endif
     177         504 :                i=i+1   
     178             :             enddo      
     179             :          enddo
     180             :       enddo
     181             :       !
     182             :       !--->   obtain sum of weights and valence eigenvalues
     183             :       !
     184             :       
     185           2 :       s1 = 0.
     186           2 :       seigv = 0.
     187           4 :       DO jsp = 1,jspins
     188           2 :          s = 0.
     189           2 :          neig = nemax(jsp)
     190          38 :          DO i = 1,neig
     191         758 :             DO k = 1,kpts%nkpt
     192         720 :                s = s + w(i,k,jsp)
     193         756 :                seigv = seigv + w(i,k,jsp)*eig(i,k,jsp)
     194             :             ENDDO
     195             :          ENDDO
     196           4 :          s1 = s1 + s
     197             :       ENDDO
     198           2 :       seigv = sfac*seigv
     199           2 :       chmom = s1 - jspins*s
     200             : 
     201           2 :       seigvTemp = seigv
     202           2 :       IF (noco%l_soc .AND. (.NOT. noco%l_noco)) THEN
     203           0 :          seigvTemp = seigvTemp / 2.0
     204             :       END IF
     205             : 
     206           2 :       IF (irank == 0 .and. l_output) THEN
     207           6 :          attributes = ''
     208           2 :          WRITE(attributes(1),'(f20.10)') seigvTemp
     209           2 :          WRITE(attributes(2),'(a)') 'Htr'
     210           6 :          CALL writeXMLElement('sumValenceSingleParticleEnergies',(/'value','units'/),attributes)
     211           2 :          WRITE (oUnit,FMT=8040) seigvTemp,s1,chmom
     212             : 8040     FORMAT (/,10x,'sum of valence eigenvalues=',f20.10,5x,&
     213             :                   'sum of weights=',f10.6,/,10x,'moment=',f12.6)
     214             :       END IF
     215             : 
     216           2 :    END SUBROUTINE fertri
     217             : END MODULE m_fertri

Generated by: LCOV version 1.14