quantum-espresso/upftools/fhi2upf.f90

290 lines
7.6 KiB
Fortran

!
! Copyright (C) 2001 PWSCF group
! 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 .
!
!
#include "f_defs.h"
!---------------------------------------------------------------------
program fhi2upf
!---------------------------------------------------------------------
!
! Convert a pseudopotential written in the Fritz-Haber format
! (numerical format) to unified pseudopotential format
! Restrictions:
! - no semicore states
! Adapted from the converter written by Andrea Ferretti
!
implicit none
character(len=256) filein, fileout
!
!
call get_file ( filein )
open (unit = 1, file = filein, status = 'old', form = 'formatted')
call read_fhi(1)
close (1)
! convert variables read from FHI format into those needed
! by the upf format - add missing quantities
call convert_fhi
fileout=trim(filein)//'.UPF'
print '(''Output PP file in UPF format : '',a)', fileout
open(unit=2,file=fileout,status='unknown',form='formatted')
call write_upf(2)
close (unit=2)
stop
20 write (6,'("fhi2upf: error reading pseudopotential file name")')
stop
end program fhi2upf
module fhi
!
! All variables read from FHI file format
!
type angular_comp
real(8), pointer :: pot(:)
real(8), pointer :: wfc(:)
real(8), pointer :: grid(:)
real(8) :: amesh
integer :: nmesh
integer :: lcomp
end type angular_comp
!------------------------------
real(8) :: Zval ! valence charge
integer :: lmax_ ! max l-component used
logical :: nlcc_
real(8), allocatable :: rho_atc_(:) ! core charge
type (angular_comp), pointer :: comp(:) ! PP numerical info
! (wfc, grid, potentials...)
!------------------------------
end module fhi
!
! ----------------------------------------------------------
subroutine read_fhi(iunps)
! ----------------------------------------------------------
!
use fhi
implicit none
integer, parameter :: Nl=7 ! max number of l-components
integer :: iunps
real(8) :: r, rhoc, drhoc, d2rhoc
!
integer :: l, i, idum, mesh
! Starting file reading
read(iunps,*) Zval, lmax_
lmax_ = lmax_ - 1
if (lmax_+1 > Nl) then
write (6,'("read_fhi: too many l-components...stopping")')
stop
end if
do i=1,10
read(iunps,*) ! skipping 11 lines
end do
allocate( comp(0:lmax_) )
do l=0,lmax_
comp(l)%lcomp = l
read(iunps,*) comp(l)%nmesh, comp(l)%amesh
if ( l > 0) then
if (comp(l)%nmesh /= comp(0)%nmesh .or. &
comp(l)%amesh /= comp(0)%amesh ) then
write(6,'("read_fhi: different radial grids not allowed...stopping")')
stop
end if
end if
mesh = comp(l)%nmesh
allocate( comp(l)%wfc(mesh), & ! wave-functions
comp(l)%pot(mesh), & ! potentials
comp(l)%grid(mesh) ) ! real space radial grid
! read the above quantities
do i=1,mesh
read(iunps,*) idum, comp(l)%grid(i), &
comp(l)%wfc(i), &
comp(l)%pot(i)
end do
end do
nlcc_ =.false.
allocate(rho_atc_(comp(0)%nmesh))
mesh = comp(0)%nmesh
do i=1,mesh
read(iunps,*,end=10, err=20) r, rho_atc_(i), drhoc, d2rhoc
if ( abs( r - comp(0)%grid(i) ) > 1.d-6 ) then
write(6,'("read_fhi: radial grid for core charge? stopping")')
stop
end if
end do
nlcc_ = .true.
! ----------------------------------------------------------
write (6,'(a)') 'Pseudopotential with NLCC successfully read'
! ----------------------------------------------------------
return
10 continue
! ----------------------------------------------------------
write (6,'(a)') 'Pseudopotential without NLCC successfully read'
! ----------------------------------------------------------
return
!
20 write(6,'("read_fhi: error reading core charge")')
stop
!
100 write(6,'("read_fhi: error reading pseudopotential file")')
stop
end subroutine read_fhi
! ----------------------------------------------------------
subroutine convert_fhi
! ----------------------------------------------------------
!
use fhi
use upf
use funct, ONLY : set_dft_from_name, get_iexch, get_icorr, get_igcx, get_igcc
implicit none
real(8), parameter :: rmax = 10.0
real(8), allocatable :: aux(:)
real(8) :: vll
character (len=20):: dft
integer :: lloc, kkbeta
integer :: l, i, ir, iv
!
print '("Atom name > ",$)'
read (5,'(a)') psd
print '("l local (max: ",i1,") > ",$)', lmax_
read (5,*) lloc
print '("DFT > ",$)'
read (5,'(a)') dft
write(generated, '("Generated using Fritz-Haber code")')
write(date_author,'("Author: unknown Generation date: as well")')
comment = 'Info: automatically converted from FHI format'
! reasonable assumption
rel = 1
rcloc = 0.0
nwfs = lmax_+1
allocate( els(nwfs), oc(nwfs), epseu(nwfs))
allocate(lchi(nwfs), nns(nwfs) )
allocate(rcut (nwfs), rcutus (nwfs))
do i=1, nwfs
print '("Wavefunction # ",i1,": label, occupancy > ",$)', i
read (5,*) els(i), oc(i)
nns (i) = 0
lchi(i) = i-1
rcut(i) = 0.0
rcutus(i)= 0.0
epseu(i) = 0.0
end do
pseudotype = 'NC'
nlcc = nlcc_
zp = Zval
etotps = 0.0
ecutrho=0.0
ecutwfc=0.0
if ( lmax_ == lloc) then
lmax = lmax_-1
else
lmax = lmax_
end if
nbeta= lmax_
mesh = comp(0)%nmesh
ntwfc= nwfs
allocate( elsw(ntwfc), ocw(ntwfc), lchiw(ntwfc) )
do i=1, nwfs
lchiw(i) = lchi(i)
ocw(i) = oc(i)
elsw(i) = els(i)
end do
call set_dft_from_name(dft)
iexch = get_iexch()
icorr = get_icorr()
igcx = get_igcx()
igcc = get_igcc()
allocate(rab(mesh))
allocate( r(mesh))
r = comp(0)%grid
rab = r * log( comp(0)%amesh )
if (nlcc) then
allocate (rho_atc(mesh))
rho_atc(:) = rho_atc_(:) / (4.d0*3.141592653589793d0)
end if
allocate (vloc0(mesh))
! the factor 2 converts from Hartree to Rydberg
vloc0 = 2.d0*comp(lloc)%pot
if (nbeta > 0) then
allocate(ikk2(nbeta), lll(nbeta))
kkbeta=mesh
do ir = 1,mesh
if ( r(ir) > rmax ) then
kkbeta=ir
exit
end if
end do
ikk2(:) = kkbeta
allocate(aux(kkbeta))
allocate(betar(mesh,nbeta))
allocate(qfunc(mesh,nbeta,nbeta))
allocate(dion(nbeta,nbeta))
allocate(qqq (nbeta,nbeta))
qfunc(:,:,:)=0.0d0
dion(:,:) =0.d0
qqq(:,:) =0.d0
iv=0
do i=1,nwfs
l=lchi(i)
if (l.ne.lloc) then
iv=iv+1
lll(iv)=l
do ir=1,kkbeta
! FHI potentials are in Hartree
betar(ir,iv) = 2.d0 * comp(l)%wfc(ir) * &
( comp(l)%pot(ir) - comp(lloc)%pot(ir) )
aux(ir) = comp(l)%wfc(ir) * betar(ir,iv)
end do
call simpson(kkbeta,aux,rab,vll)
dion(iv,iv) = 1.0d0/vll
end if
enddo
end if
allocate (rho_at(mesh))
rho_at = 0.d0
do i=1,nwfs
l=lchi(i)
rho_at = rho_at + ocw(i) * comp(l)%wfc ** 2
end do
allocate (chi(mesh,ntwfc))
do i=1,ntwfc
chi(:,i) = comp(i-1)%wfc(:)
end do
! ----------------------------------------------------------
write (6,'(a)') 'Pseudopotential successfully converted'
! ----------------------------------------------------------
return
end subroutine convert_fhi