quantum-espresso/upflib/pseudo_types.f90

335 lines
15 KiB
Fortran

!
! Copyright (C) 2002-2023 Quantum ESPRESSO Foundation
! 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 pseudo_types
! this module contains the definitions of several TYPE structures,
! together with their allocation/deallocation routines
USE upf_kinds, ONLY: DP
IMPLICIT NONE
SAVE
!
! Additional data to make a PAW setup out of an US pseudo,
! they are all stored on a radial grid:
TYPE paw_in_upf
REAL(DP),ALLOCATABLE :: ae_rho_atc(:) ! AE core charge (pseudo ccharge
! is already included in upf)
REAL(DP),ALLOCATABLE :: pfunc(:,:,:),&! Psi_i(r)*Psi_j(r)
pfunc_rel(:,:,:), & ! Psi_i(r)*Psi_j(r) small component
ptfunc(:,:,:), & ! as above, but for pseudo
aewfc_rel(:,:) ! as above, but for pseudo
REAL(DP),ALLOCATABLE :: ae_vloc(:) ! AE local potential (pseudo vloc
! is already included in upf)
REAL(DP),ALLOCATABLE :: oc(:) ! starting occupation used to init becsum
! they differ from US ones because they
! are indexed on BETA functions, non on WFC
REAL(DP),ALLOCATABLE :: augmom(:,:,:) ! multipole AE-pseudo (i,j,l=0:2*lmax)
REAL(DP) :: raug ! augfunction max radius
INTEGER :: iraug ! index on rgrid closer to, and >, raug
INTEGER :: lmax_aug ! max angmom of augmentation functions, it is ==
! to 2* max{l of pseudized wavefunctions}
! note that nqlc of upf also includes the angmom of
! empty virtual channel used to generate local potential
REAL(DP) :: core_energy ! constant to add in order to get all-electron energy
CHARACTER(len=12):: augshape ! shape of augmentation charge
END TYPE paw_in_upf
TYPE pseudo_upf
CHARACTER(LEN=80):: generated=' '! generator software
CHARACTER(LEN=80):: author=' ' ! pseudopotential's author
CHARACTER(LEN=80):: date=' ' ! generation date
CHARACTER(LEN=80):: comment=' ' ! author's comment
CHARACTER(LEN=2) :: psd=' ' ! Element label
CHARACTER(LEN=4) :: typ=' ' ! Pseudo type: NC, SL, US, PAW, 1/r
! NB: many files have USPP instead of US
CHARACTER(len=6) :: rel=' ' ! relativistic: {no|scalar|full}
LOGICAL :: tvanp ! .true. if Ultrasoft
LOGICAL :: tcoulombp ! .true. if Coulomb 1/r potential
LOGICAL :: nlcc ! Non linear core corrections
LOGICAL :: is_gth ! .true. if Goedecker-Teter-Hutter
LOGICAL :: is_multiproj ! .true. if multiple projectors per l
! (for NC PP only; US-PP and PAW are assumed to be multi-projector)
LOGICAL :: with_metagga_info ! true if PP contains meta-GGA data
CHARACTER(LEN=25) :: dft ! Exch-Corr type
REAL(DP) :: zp ! z valence
REAL(DP) :: etotps ! total energy
REAL(DP) :: ecutwfc ! suggested cut-off for wfc
REAL(DP) :: ecutrho ! suggested cut-off for rho
!
CHARACTER(len=11) :: nv ! UPF file three-digit version i.e. 2.0.0
INTEGER :: lmax ! maximum l component in beta
INTEGER :: lmax_rho ! max l component in charge (should be 2*lmax)
REAL(DP), ALLOCATABLE :: vnl(:,:,:) ! vnl(i,l,s) = V(r_i)_{ls}
! (semilocal form) only for single-channel NC PP
! Wavefunctions and projectors
INTEGER :: nwfc ! number of atomic wavefunctions
INTEGER :: nbeta ! number of projectors
INTEGER, ALLOCATABLE :: kbeta(:) ! kbeta(nbeta) see below
INTEGER :: kkbeta ! kkbeta=max(kbeta(:))
! kbeta<=mesh is the number of grid points for each beta function
! beta(r,nb) = 0 for r > r(kbeta(nb))
! kkbeta<=mesh is the largest of such number so that for all beta
! beta(r,nb) = 0 for r > r(kkbeta)
!
INTEGER, ALLOCATABLE :: lll(:) ! lll(nbeta) l of each projector
REAL(DP), ALLOCATABLE :: beta(:,:) ! beta(mesh,nbeta) projectors
!
CHARACTER(LEN=2), ALLOCATABLE :: els(:) ! els(nwfc) label of wfc
CHARACTER(LEN=2), ALLOCATABLE :: els_beta(:) ! els(nbeta) label of beta
INTEGER, ALLOCATABLE :: nchi(:) ! nchi(nwfc) value of pseudo-n for wavefcts
INTEGER, ALLOCATABLE :: lchi(:) ! lchi(nwfc) value of l for wavefcts
REAL(DP), ALLOCATABLE :: oc(:) ! oc(nwfc) occupancies for wavefcts
REAL(DP), ALLOCATABLE :: epseu(:) ! pseudo one-particle energy (nwfc)
REAL(DP), ALLOCATABLE :: rcut_chi(:)! rcut_chi(nwfc) cutoff inner radius
REAL(DP), ALLOCATABLE :: rcutus_chi(:)! rcutus_chi(nwfc) ultrasoft outer radius
! Chi and rho_at are only used for initial density and initial wfcs:
REAL(DP), ALLOCATABLE :: chi(:,:) ! chi(mesh,nwfc) atomic wavefcts
REAL(DP), ALLOCATABLE :: rho_at(:) ! rho_at(mesh) atomic charge
! Minimal radial grid:
INTEGER :: mesh ! number of points in the radial mesh
REAL(DP) :: xmin ! the minimum x of the linear mesh
REAL(DP) :: rmax ! the maximum radius of the mesh
REAL(DP) :: zmesh ! the nuclear charge used for mesh
REAL(DP) :: dx ! the deltax of the linear mesh
REAL(DP), ALLOCATABLE :: r(:) ! r(mesh) radial grid
REAL(DP), ALLOCATABLE :: rab(:) ! rab(mesh) dr(x)/dx (x=linear grid)
! Pseudized core charge
REAL(DP), ALLOCATABLE :: rho_atc(:) ! rho_atc(mesh) atomic core charge
! Local potential
INTEGER :: lloc ! L of channel used to generate local potential
! (if < 0 it was generated by smoothing AE potential)
REAL(DP) :: rcloc ! vloc = v_ae for r > rcloc
REAL(DP), ALLOCATABLE :: vloc(:) ! vloc(mesh) local atomic potential
!
REAL(DP), ALLOCATABLE :: dion(:,:) ! dion(nbeta,nbeta) atomic D_{mu,nu}
! Augmentation
LOGICAL :: q_with_l ! if .true. qfunc is pseudized in
! different ways for different l
INTEGER :: nqf ! number of Q coefficients
INTEGER :: nqlc ! number of angular momenta in Q
REAL(DP):: qqq_eps ! qfunc is null if its norm is .lt. qqq_eps
REAL(DP), ALLOCATABLE :: rinner(:) ! rinner(0:2*lmax) r_L
REAL(DP), ALLOCATABLE :: qqq(:,:) ! qqq(nbeta,nbeta) q_{mu,nu}
! Augmentation without L dependecy
REAL(DP), ALLOCATABLE :: qfunc(:,:) ! qfunc(mesh,nbeta*(nbeta+1)/2)
! Q_{mu,nu}(|r|) function for |r|> r_L
! Augmentation depending on L (optional, compulsory for PAW)
REAL(DP), ALLOCATABLE :: qfuncl(:,:,:)! qfuncl(mesh,nbeta*(nbeta+1)/2,l)
! Q_{mu,nu}(|r|) function for |r|> r_L
! Analitycal coeffs cor small r expansion of qfunc (Vanderbilt's code)
REAL(DP), ALLOCATABLE :: qfcoef(:,:,:,:) ! qfcoef(nqf,0:2*lmax,nbeta,nbeta)
! coefficients for Q for |r|<r_L
!
! META-GGA variables (not yet implemented!)
REAL(DP), ALLOCATABLE :: tau_core(:)
REAL(DP), ALLOCATABLE :: tau_atom(:)
! All electron and pseudo wavefunction, pswfc differ from chi as they are
! one for each beta, not just some choosen for initial conditions
LOGICAL :: has_wfc ! if true, UPF contain AE and PS wfc for each beta
REAL(DP), ALLOCATABLE :: aewfc(:,:) ! wfc(mesh,nbeta) all-electron wfc
REAL(DP), ALLOCATABLE :: pswfc(:,:) ! wfc(mesh,nbeta) pseudo wfc
LOGICAL :: has_so ! if .true. includes spin-orbit
REAL(DP), ALLOCATABLE :: rcut(:) ! cut-off radius(nbeta)
REAL(DP), ALLOCATABLE :: rcutus(:)! ultrasoft cut-off radius (nbeta)
REAL(DP), ALLOCATABLE :: jchi(:) ! jchi(nwfc) j=l+1/2 or l-1/2 of wfc
REAL(DP), ALLOCATABLE :: jjj(:) ! jjj(nbeta) j=l+1/2 or l-1/2 of beta
! PAW:
INTEGER :: paw_data_format ! The version of the format
LOGICAL :: tpawp ! true if atom is PAW, PAW data must be present
TYPE(paw_in_upf) :: paw ! additional data for PAW (see above)
! GIPAW:
LOGICAL :: has_gipaw ! Whether GIPAW data is included
LOGICAL :: paw_as_gipaw !EMINE
INTEGER :: gipaw_data_format ! The version of the format
INTEGER :: gipaw_ncore_orbitals
REAL(DP), ALLOCATABLE :: gipaw_core_orbital_n(:)
REAL(DP), ALLOCATABLE :: gipaw_core_orbital_l(:)
CHARACTER(LEN=2), ALLOCATABLE :: gipaw_core_orbital_el(:)
REAL(DP), ALLOCATABLE :: gipaw_core_orbital(:,:)
REAL(DP), ALLOCATABLE :: gipaw_vlocal_ae(:)
REAL(DP), ALLOCATABLE :: gipaw_vlocal_ps(:)
INTEGER :: gipaw_wfs_nchannels
CHARACTER(LEN=2), ALLOCATABLE :: gipaw_wfs_el(:)
INTEGER, ALLOCATABLE :: gipaw_wfs_ll(:)
REAL(DP), ALLOCATABLE :: gipaw_wfs_ae(:,:)
REAL(DP), ALLOCATABLE :: gipaw_wfs_rcut(:)
REAL(DP), ALLOCATABLE :: gipaw_wfs_rcutus(:)
REAL(DP), ALLOCATABLE :: gipaw_wfs_ps(:,:)
!
! MD5 checksum ... used to verify integrity of the information contained
! in the pseudopotential file w.r.t previous run
!
CHARACTER(len=32) :: MD5_cksum = 'NOT SET'
END TYPE pseudo_upf
TYPE pseudo_config
INTEGER :: nwfs
CHARACTER(len=32) :: pseud
CHARACTER(len=2),ALLOCATABLE :: els(:) ! label
INTEGER,ALLOCATABLE :: nns(:) ! n
INTEGER,ALLOCATABLE :: lls(:) ! l
REAL(DP),ALLOCATABLE :: ocs(:) ! occupation
REAL(DP),ALLOCATABLE :: rcut(:) ! NC cutoff radius
REAL(DP),ALLOCATABLE :: rcutus(:) ! US cutoff radius
REAL(DP),ALLOCATABLE :: enls(:) ! energy
END TYPE pseudo_config
CONTAINS
SUBROUTINE deallocate_paw_in_upf( paw )
TYPE( paw_in_upf ), INTENT(INOUT) :: paw
IF( ALLOCATED( paw%ae_rho_atc ) ) DEALLOCATE ( paw%ae_rho_atc )
IF( ALLOCATED( paw%aewfc_rel ) ) DEALLOCATE (paw%aewfc_rel )
IF( ALLOCATED( paw%pfunc ) ) DEALLOCATE ( paw%pfunc )
IF( ALLOCATED( paw%pfunc_rel ) ) DEALLOCATE ( paw%pfunc_rel )
IF( ALLOCATED( paw%ptfunc ) ) DEALLOCATE ( paw%ptfunc )
IF( ALLOCATED( paw%ae_vloc ) ) DEALLOCATE ( paw%ae_vloc )
IF( ALLOCATED( paw%augmom ) ) DEALLOCATE ( paw%augmom )
IF( ALLOCATED( paw%oc ) ) DEALLOCATE ( paw%oc )
paw%raug = 0.0
paw%core_energy = 0.0
paw%iraug = 0
paw%lmax_aug = 0
paw%augshape = ' '
END SUBROUTINE deallocate_paw_in_upf
!
SUBROUTINE deallocate_gipaw_in_upf ( upf )
TYPE( pseudo_upf ), INTENT(INOUT) :: upf
!
IF ( ALLOCATED ( upf%gipaw_core_orbital_n ) ) &
DEALLOCATE ( upf%gipaw_core_orbital_n )
IF ( ALLOCATED ( upf%gipaw_core_orbital_l ) ) &
DEALLOCATE ( upf%gipaw_core_orbital_l )
IF ( ALLOCATED ( upf%gipaw_core_orbital_el ) ) &
DEALLOCATE ( upf%gipaw_core_orbital_el )
IF ( ALLOCATED ( upf%gipaw_core_orbital ) ) &
DEALLOCATE ( upf%gipaw_core_orbital )
IF ( ALLOCATED ( upf%gipaw_vlocal_ae ) ) &
DEALLOCATE ( upf%gipaw_vlocal_ae )
IF ( ALLOCATED ( upf%gipaw_vlocal_ps ) ) &
DEALLOCATE ( upf%gipaw_vlocal_ps )
IF ( ALLOCATED ( upf%gipaw_wfs_el ) ) &
DEALLOCATE ( upf%gipaw_wfs_el )
IF ( ALLOCATED ( upf%gipaw_wfs_ll ) ) &
DEALLOCATE ( upf%gipaw_wfs_ll )
IF ( ALLOCATED ( upf%gipaw_wfs_ae ) ) &
DEALLOCATE ( upf%gipaw_wfs_ae )
IF ( ALLOCATED ( upf%gipaw_wfs_rcut ) ) &
DEALLOCATE ( upf%gipaw_wfs_rcut )
IF ( ALLOCATED ( upf%gipaw_wfs_rcutus ) ) &
DEALLOCATE ( upf%gipaw_wfs_rcutus )
IF ( ALLOCATED ( upf%gipaw_wfs_ps ) ) &
DEALLOCATE ( upf%gipaw_wfs_ps )
!
END SUBROUTINE deallocate_gipaw_in_upf
!
SUBROUTINE deallocate_pseudo_config(conf)
TYPE(pseudo_config),INTENT(INOUT) :: conf
IF ( ALLOCATED(conf%els) ) DEALLOCATE(conf%els)
IF ( ALLOCATED(conf%nns) ) DEALLOCATE(conf%nns)
IF ( ALLOCATED(conf%lls) ) DEALLOCATE(conf%lls)
IF ( ALLOCATED(conf%ocs) ) DEALLOCATE(conf%ocs)
IF ( ALLOCATED(conf%rcut) ) DEALLOCATE(conf%rcut)
IF ( ALLOCATED(conf%rcutus)) DEALLOCATE(conf%rcutus)
IF ( ALLOCATED(conf%enls) ) DEALLOCATE(conf%enls)
END SUBROUTINE deallocate_pseudo_config
SUBROUTINE deallocate_pseudo_upf( upf )
!
TYPE( pseudo_upf ), INTENT(INOUT) :: upf
!
CALL deallocate_paw_in_upf( upf%paw )
IF( ALLOCATED( upf%els ) ) DEALLOCATE( upf%els )
IF( ALLOCATED( upf%lchi ) ) DEALLOCATE( upf%lchi )
IF( ALLOCATED( upf%nchi ) ) DEALLOCATE( upf%nchi )
IF( ALLOCATED( upf%jchi ) ) DEALLOCATE( upf%jchi )
IF( ALLOCATED( upf%oc ) ) DEALLOCATE( upf%oc )
!
IF( ALLOCATED( upf%r ) ) DEALLOCATE( upf%r )
IF( ALLOCATED( upf%rab ) ) DEALLOCATE( upf%rab )
!
IF( ALLOCATED( upf%els_beta ) )DEALLOCATE( upf%els_beta )
IF( ALLOCATED( upf%rcut_chi ) ) DEALLOCATE( upf%rcut_chi )
IF( ALLOCATED( upf%rcutus_chi ) )DEALLOCATE( upf%rcutus_chi )
IF( ALLOCATED( upf%rcut ) ) DEALLOCATE( upf%rcut )
IF( ALLOCATED( upf%rcutus ) ) DEALLOCATE( upf%rcutus )
IF( ALLOCATED( upf%epseu ) ) DEALLOCATE( upf%epseu )
IF( ALLOCATED( upf%rho_atc ) ) DEALLOCATE( upf%rho_atc )
IF( ALLOCATED( upf%vloc ) ) DEALLOCATE( upf%vloc )
IF( ALLOCATED( upf%lll ) ) DEALLOCATE( upf%lll )
IF( ALLOCATED( upf%jjj ) ) DEALLOCATE( upf%jjj )
IF( ALLOCATED( upf%kbeta ) ) DEALLOCATE( upf%kbeta )
IF( ALLOCATED( upf%beta ) ) DEALLOCATE( upf%beta )
IF( ALLOCATED( upf%vnl ) ) DEALLOCATE( upf%vnl )
IF( ALLOCATED( upf%aewfc ) ) DEALLOCATE( upf%aewfc )
IF( ALLOCATED( upf%pswfc ) ) DEALLOCATE( upf%pswfc )
IF( ALLOCATED( upf%dion ) ) DEALLOCATE( upf%dion )
IF( ALLOCATED( upf%rinner ) ) DEALLOCATE( upf%rinner )
IF( ALLOCATED( upf%qqq ) ) DEALLOCATE( upf%qqq )
IF( ALLOCATED( upf%qfunc ) ) DEALLOCATE( upf%qfunc )
IF( ALLOCATED( upf%qfuncl ) ) DEALLOCATE( upf%qfuncl )
IF( ALLOCATED( upf%qfcoef ) ) DEALLOCATE( upf%qfcoef )
IF( ALLOCATED( upf%chi ) ) DEALLOCATE( upf%chi )
IF( ALLOCATED( upf%rho_at ) ) DEALLOCATE( upf%rho_at )
IF( ALLOCATED( upf%tau_core ) ) DEALLOCATE( upf%tau_core )
IF( ALLOCATED( upf%tau_atom ) ) DEALLOCATE( upf%tau_atom )
!
CALL deallocate_gipaw_in_upf( upf )
!
CALL reset_upf ( upf)
!
END SUBROUTINE deallocate_pseudo_upf
SUBROUTINE reset_upf( upf )
!
TYPE( pseudo_upf ), INTENT(INOUT) :: upf
!
upf%tvanp = .false.
upf%tcoulombp = .false.
upf%nlcc = .false.
upf%dft = ' '
upf%zp = 0.0
upf%etotps = 0.0
upf%ecutwfc = 0.0
upf%ecutrho = 0.0
upf%nv = ' '
upf%lmax = 0
upf%lmax_rho = 0
upf%nwfc = 0
upf%nbeta = 0
upf%kkbeta = 0
upf%mesh = 0
upf%xmin = 0.0
upf%rmax = 0.0
upf%zmesh = 0.0
upf%dx = 0.0
upf%lloc = 0
upf%rcloc = 0.0
upf%q_with_l = .false.
upf%nqf = 0
upf%nqlc = 0
upf%qqq_eps = 0.0
upf%has_wfc = .false.
upf%paw_data_format = 0
upf%tpawp = .false.
upf%has_gipaw = .false.
upf%paw_as_gipaw = .false.
upf%with_metagga_info = .false.
upf%gipaw_data_format = 0
upf%gipaw_ncore_orbitals = 0
upf%gipaw_wfs_nchannels = 0
END SUBROUTINE reset_upf
END MODULE pseudo_types