atmproj_tools.F Source File




Source Code

!
! Copyright (C) 2012 WanT Group
! Adapted for p2y by DS,DV
!
! This file is distributed under the terms of the
! GNU General Public License. See the file `License\'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
!*********************************************
MODULE atmproj_tools_module
!*********************************************
   !
   USE parameters,          ONLY : nstrx
   !
   IMPLICIT NONE 
   PRIVATE
   SAVE

   !
   ! some default for kinds
   !
   INTEGER,   PARAMETER :: dbl = SELECTED_REAL_KIND( 14, 200 )
   INTEGER,   PARAMETER :: ionode_id=1
   LOGICAL              :: ioneode=.true.

   !
   ! global variables of the module
   !
   CHARACTER(nstrx)   :: savedir
   CHARACTER(nstrx)   :: file_proj
   CHARACTER(nstrx)   :: file_data
   CHARACTER(nstrx)   :: file_fmt
   !
   LOGICAL            :: init = .FALSE.
   !
   ! parameters for the reconstruction 
   ! of the Hamiltonian
   !
   REAL(dbl)          :: atmproj_sh = 10.0d0
   REAL(dbl)          :: atmproj_thr = 0.0d0    ! 0.9d0
   INTEGER            :: atmproj_nbnd = 0
   INTEGER            :: atmproj_nbndmin = 1
   !
   INTEGER, PARAMETER :: nwfcx = 50

   ! contains:
   !
   PUBLIC :: atmproj_read_ext

CONTAINS
!*************************************************
SUBROUTINE atmproj_read_ext ( filein, nbnd, nkpt, nspin, natomwfc, nelec, &
                              efermi, energy_units, vkpt, wk, eig, proj, kovp, ierr )
!*************************************************
   !
   USE iotk_module
   !
   IMPLICIT NONE
   !
   CHARACTER(*),           INTENT(IN)   :: filein
   INTEGER,      OPTIONAL, INTENT(OUT)  :: nbnd, nkpt, nspin, natomwfc
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: nelec, efermi
   CHARACTER(*), OPTIONAL, INTENT(OUT)  :: energy_units
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: vkpt(:,:), wk(:), eig(:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: proj(:,:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: kovp(:,:,:,:)
   INTEGER,                INTENT(OUT)  :: ierr
   !
   !
   CHARACTER(256)    :: attr
   INTEGER           :: iunit
   LOGICAL           :: l_old_atmproj,l_new_atmproj
   !
   INTEGER           :: nbnd_, nkpt_, nspin_, natomwfc_ 
   REAL(dbl)         :: nelec_, efermi_
   CHARACTER(20)     :: energy_units_
   !

   CALL iotk_free_unit( iunit )
   ierr = 0
   CALL iotk_open_read( iunit, FILE=TRIM(filein), IERR=ierr )
   IF ( ierr/=0 ) RETURN

   attr=""
   CALL iotk_scan_empty( iunit, "HEADER", ATTR=attr, IERR=ierr)  
   l_old_atmproj= (ierr/=0)
   l_new_atmproj= (ierr==0)
   
   IF (present(vkpt) .or. present(kovp) ) THEN
     call error(' not coded')
   ENDIF

   IF ( l_old_atmproj ) then
!      WRITE(*,*) "Old atmproj format"
!     CALL atmproj_read_ext_old ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
!                              efermi_, energy_units_, vkpt, wk, eig, proj, kovp, ierr, iunit )
     if (      present(proj) ) CALL atmproj_read_ext_old ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
                              efermi_, energy_units_, proj=proj, ierr=ierr, iunit=iunit )
     if (.not. present(proj) ) CALL atmproj_read_ext_old ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
                              efermi_, energy_units_, ierr=ierr, iunit=iunit )
   ENDIF
                              
   IF ( l_new_atmproj ) THEN
!      WRITE(*,*) "New atmproj format",iunit
!     CALL atmproj_read_ext_new ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
!                              efermi_, energy_units_, vkpt, wk, eig, proj, kovp, ierr, iunit, attr )
     if (      present(proj) ) CALL atmproj_read_ext_new ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
                              efermi_, energy_units_, proj=proj, ierr=ierr, iunit=iunit, attr=attr )
     if (.not. present(proj) ) CALL atmproj_read_ext_new ( filein, nbnd_, nkpt_, nspin_, natomwfc_, nelec_, &
                              efermi_, energy_units_, ierr=ierr, iunit=iunit, attr=attr )
   ENDIF
   
   ! This gives error with new atmproj
   ! if iotk library is compiled with out of bound error check 
   CALL iotk_close_read( iunit, IERR=ierr )
   IF ( ierr/=0 ) RETURN

   IF ( PRESENT( nbnd ) )         nbnd = nbnd_
   IF ( PRESENT( nkpt ) )         nkpt = nkpt_
   IF ( PRESENT( nspin ) )        nspin = nspin_
   IF ( PRESENT( natomwfc ) )     natomwfc = natomwfc_
   IF ( PRESENT( nelec ) )        nelec = nelec_
   IF ( PRESENT( efermi ) )       efermi = efermi_
   IF ( PRESENT( energy_units ) ) energy_units = TRIM(energy_units_)
   !
   RETURN
   !
END SUBROUTINE atmproj_read_ext


!*************************************************
SUBROUTINE atmproj_read_ext_new ( filein, nbnd, nkpt, nspin, natomwfc, nelec, &
                              efermi, energy_units, vkpt, wk, eig, proj, kovp, ierr, iunit, attr )
!*************************************************
   !
   USE iotk_module
   !
   IMPLICIT NONE
   !
   CHARACTER(*),           INTENT(IN)   :: filein
   INTEGER,      OPTIONAL, INTENT(OUT)  :: nbnd, nkpt, nspin, natomwfc
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: nelec, efermi
   CHARACTER(*), OPTIONAL, INTENT(OUT)  :: energy_units
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: vkpt(:,:), wk(:), eig(:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: proj(:,:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: kovp(:,:,:,:)
   INTEGER,                INTENT(OUT)  :: ierr
   INTEGER,                INTENT(IN)   :: iunit
   CHARACTER(256),         INTENT(INOUT):: attr
   !
   CHARACTER(256)    :: str
   INTEGER           :: ik, isp, ias
   !
   INTEGER           :: nbnd_, nkpt_, nspin_, natomwfc_ 
   REAL(dbl)         :: nelec_, efermi_
   CHARACTER(20)     :: energy_units_
   !
   COMPLEX(dbl), ALLOCATABLE :: ztmp(:,:)
   REAL(dbl),    ALLOCATABLE :: rtmp(:,:,:)

     CALL iotk_scan_attr( attr, "NUMBER_OF_BANDS", nbnd_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_attr( attr, "NUMBER_OF_K-POINTS", nkpt_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_attr( attr, "NUMBER_OF_SPIN_COMPONENTS", nspin_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_attr( attr, "NUMBER_OF_ATOMIC_WFC", natomwfc_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_attr( attr, "NUMBER_OF_ELECTRONS", nelec_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
     energy_units_="Rydberg"
     !
     CALL iotk_scan_attr( attr, "FERMI_ENERGY", efermi_, IERR=ierr)
     IF ( ierr/=0 ) RETURN
   !
   ! reading kpoints, weight, energies and proj
!to be generalized with spin > 1
   !
    CALL iotk_scan_begin( iunit, "EIGENSTATES", IERR=ierr)
     IF ( ierr/=0 ) RETURN
!
     DO isp=1,nspin_
       DO ik = 1, nkpt_
         IF ( PRESENT( vkpt ) ) THEN
           CALL iotk_scan_dat( iunit, "K-POINT", vkpt(:,ik), attr=attr, IERR=ierr)
           IF ( ierr/=0 ) RETURN
           call iotk_scan_attr(attr , "Weight", wk(ik), IERR=ierr)
           IF ( ierr/=0 ) RETURN
         ENDIF
         IF ( PRESENT( eig ) ) THEN
            CALL iotk_scan_dat(iunit, "E" , eig(:,ik, isp ), IERR=ierr)    
            IF ( ierr/=0 ) RETURN
         ENDIF
         !
         IF ( PRESENT( proj ) ) THEN
           !
           ALLOCATE( rtmp(2,nbnd_, natomwfc_) )
           ALLOCATE( ztmp(nbnd_, natomwfc_) )
           !
           CALL iotk_scan_begin( iunit, "PROJS", IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
           DO ias = 1, natomwfc_
             !
             str= "ATOMIC_WFC"
             !
             CALL iotk_scan_dat(iunit, TRIM(str) , rtmp( :,:, ias ), IERR=ierr)
             IF ( ierr /= 0 ) RETURN
             !
           ENDDO
           !
           ztmp(1:nbnd_,1:natomwfc_)=cmplx(rtmp(1,1:nbnd_,1:natomwfc_),rtmp(2,1:nbnd_,1:natomwfc_)) 
           proj( 1:natomwfc_, 1:nbnd_, ik, isp ) = TRANSPOSE( ztmp(1:nbnd_,1:natomwfc_) )
           CALL iotk_scan_end( iunit, "PROJS", IERR=ierr )
           IF ( ierr/=0 ) RETURN
           DEALLOCATE( rtmp )
           DEALLOCATE( ztmp )
           !
         ENDIF
       ENDDO
     ENDDO
     
     CALL iotk_scan_end( iunit, "EIGENSTATES", IERR=ierr)
     IF ( ierr/=0 ) RETURN
     
   IF ( PRESENT( nbnd ) )         nbnd = nbnd_
   IF ( PRESENT( nkpt ) )         nkpt = nkpt_
   IF ( PRESENT( nspin ) )        nspin = nspin_
   IF ( PRESENT( natomwfc ) )     natomwfc = natomwfc_
   IF ( PRESENT( nelec ) )        nelec = nelec_
   IF ( PRESENT( efermi ) )       efermi = efermi_
   IF ( PRESENT( energy_units ) ) energy_units = TRIM(energy_units_)


END SUBROUTINE atmproj_read_ext_new


!*************************************************
SUBROUTINE atmproj_read_ext_old ( filein, nbnd, nkpt, nspin, natomwfc, nelec, &
                              efermi, energy_units, vkpt, wk, eig, proj, kovp, ierr, iunit )
!*************************************************
   !
   USE iotk_module
   !
   IMPLICIT NONE
   !
   CHARACTER(*),           INTENT(IN)   :: filein
   INTEGER,      OPTIONAL, INTENT(OUT)  :: nbnd, nkpt, nspin, natomwfc
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: nelec, efermi
   CHARACTER(*), OPTIONAL, INTENT(OUT)  :: energy_units
   REAL(dbl),    OPTIONAL, INTENT(OUT)  :: vkpt(:,:), wk(:), eig(:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: proj(:,:,:,:)
   COMPLEX(dbl), OPTIONAL, INTENT(OUT)  :: kovp(:,:,:,:)
   INTEGER,                INTENT(OUT)  :: ierr
   INTEGER,                INTENT(IN)   :: iunit
   !
   CHARACTER(256)    :: attr, str
   INTEGER           :: ik, isp, ias
   !
   INTEGER           :: nbnd_, nkpt_, nspin_, natomwfc_ 
   REAL(dbl)         :: nelec_, efermi_
   CHARACTER(20)     :: energy_units_
   !
   COMPLEX(dbl), ALLOCATABLE :: ztmp(:,:)
   REAL(dbl),    ALLOCATABLE :: rtmp(:,:,:)


     CALL iotk_scan_begin( iunit, "HEADER", IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_dat( iunit, "NUMBER_OF_BANDS", nbnd_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_dat( iunit, "NUMBER_OF_K-POINTS", nkpt_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_dat( iunit, "NUMBER_OF_SPIN_COMPONENTS", nspin_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_dat( iunit, "NUMBER_OF_ATOMIC_WFC", natomwfc_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_dat( iunit, "NUMBER_OF_ELECTRONS", nelec_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     !
     CALL iotk_scan_empty( iunit, "UNITS_FOR_ENERGY", ATTR=attr, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     CALL iotk_scan_attr( attr, "UNITS", energy_units_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     !
     CALL iotk_scan_dat( iunit, "FERMI_ENERGY", efermi_, IERR=ierr) 
     IF ( ierr/=0 ) RETURN
     !
     CALL iotk_scan_end( iunit, "HEADER", IERR=ierr) 
     IF ( ierr/=0 ) RETURN
   !
   ! reading kpoints and weights 
   ! 
     IF ( PRESENT( vkpt ) ) THEN
       !
       CALL iotk_scan_dat( iunit, "K-POINTS", vkpt(:,:), IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
     ENDIF
   !
     IF ( PRESENT (wk) ) THEN
       !
       CALL iotk_scan_dat( iunit, "WEIGHT_OF_K-POINTS", wk(:), IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
     ENDIF
   
   !
   ! Added by Luis to take spinors into accout
   !
     IF ( nspin_ == 4 ) nspin_ = 1
   
   ! 
   ! reading eigenvalues
   ! 

     IF ( PRESENT( eig ) ) THEN
       ! 
       CALL iotk_scan_begin( iunit, "EIGENVALUES", IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
       DO ik = 1, nkpt_
           !
           CALL iotk_scan_begin( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
           IF ( nspin_ == 1 ) THEN
                !
                isp = 1
                !
                CALL iotk_scan_dat(iunit, "EIG" , eig(:,ik, isp ), IERR=ierr)
                IF ( ierr /= 0 ) RETURN
                !
           ELSE
                !
                DO isp=1,nspin_
                   !
                   str = "EIG"//TRIM(iotk_index(isp))
                   !
                   CALL iotk_scan_dat(iunit, TRIM(str) , eig(:,ik,isp), IERR=ierr)
                   IF ( ierr /= 0 ) RETURN
                   !
                ENDDO
                !
           ENDIF       
           !
           !
           CALL iotk_scan_end( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
       ENDDO
       !
       !
       CALL iotk_scan_end( iunit, "EIGENVALUES", IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
     ENDIF


   ! 
   ! reading projections
   ! 
     IF ( PRESENT( proj ) ) THEN
       !
       ALLOCATE( ztmp(nbnd_, natomwfc_) )
       !
       CALL iotk_scan_begin( iunit, "PROJECTIONS", IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
       !
       DO ik = 1, nkpt_
           !
           !
           CALL iotk_scan_begin( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
           DO isp = 1, nspin_
               !
               IF ( nspin_ == 2 ) THEN
                   !
                   CALL iotk_scan_begin( iunit, "SPIN"//TRIM(iotk_index(isp)), IERR=ierr )
                   IF ( ierr/=0 ) RETURN
                   !
               ENDIF
               !
               DO ias = 1, natomwfc_
                   !
                   str= "ATMWFC"//TRIM( iotk_index( ias ) )
                   !
                   CALL iotk_scan_dat(iunit, TRIM(str) , ztmp( :, ias ), IERR=ierr)
                   IF ( ierr /= 0 ) RETURN
                   !
               ENDDO
               !
               proj( 1:natomwfc_, 1:nbnd_, ik, isp ) = TRANSPOSE( ztmp(1:nbnd_,1:natomwfc_) ) 
               !
               !
               IF ( nspin_ == 2 ) THEN
                   !
                   CALL iotk_scan_end( iunit, "SPIN"//TRIM(iotk_index(isp)), IERR=ierr )
                   IF ( ierr/=0 ) RETURN
                   !
               ENDIF
               !
           ENDDO
           !
           !
           CALL iotk_scan_end( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
           !
       ENDDO
       !
       DEALLOCATE( ztmp )
       !
       CALL iotk_scan_end( iunit, "PROJECTIONS", IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
     ENDIF
   ! 
   ! reading overlaps
   ! 
     IF ( PRESENT( kovp ) ) THEN
       !
       CALL iotk_scan_begin( iunit, "OVERLAPS", IERR=ierr )
       IF ( ierr/=0 ) THEN
           call error(' OVERLAPS data not found in file. Crashing ...')
       ENDIF
       !
       DO ik = 1, nkpt_
           CALL iotk_scan_begin( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
           DO isp = 1, nspin_
               !
               CALL iotk_scan_dat(iunit, "OVERLAP"//TRIM(iotk_index(isp)), kovp( :, :, ik, isp ), IERR=ierr)
               IF ( ierr/=0 ) RETURN
               !
           ENDDO
           !
           CALL iotk_scan_end( iunit, "K-POINT"//TRIM(iotk_index(ik)), IERR=ierr )
           IF ( ierr/=0 ) RETURN
           !
       ENDDO
       !
       CALL iotk_scan_end( iunit, "OVERLAPS", IERR=ierr )
       IF ( ierr/=0 ) RETURN
       !
     ENDIF

   !
   IF ( PRESENT( nbnd ) )         nbnd = nbnd_
   IF ( PRESENT( nkpt ) )         nkpt = nkpt_
   IF ( PRESENT( nspin ) )        nspin = nspin_
   IF ( PRESENT( natomwfc ) )     natomwfc = natomwfc_
   IF ( PRESENT( nelec ) )        nelec = nelec_
   IF ( PRESENT( efermi ) )       efermi = efermi_
   IF ( PRESENT( energy_units ) ) energy_units = TRIM(energy_units_)


END SUBROUTINE atmproj_read_ext_old

END MODULE atmproj_tools_module

📚 Documentation Pages
⏱️ Real-Time
🔗 Code API