!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! This module contains the following active subroutines: ! SCFatom_Init,SCFatom,Orbit_Init,NC_Init,SC_Init,FC_Init,Potential_Init, ! Set_Valence ! The following subroutines need revision to be useful: ! dump_aeatom,load_aeatom !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #if defined HAVE_CONFIG_H #include "config.h" #endif MODULE AEatom USE io_tools USE atomdata USE excor USE exx_mod USE general_mod USE globalmath USE gridmod USE hf_mod USE ldagga_mod USE input_dataset_mod IMPLICIT NONE REAL(8), PARAMETER, PRIVATE :: linh=0.0025d0,logh=0.020d0,lor00=1.d-5 REAL(8), PARAMETER, PRIVATE :: small0=1.d-13,rimix=0.5d0,worst=1.d-8 INTEGER, PARAMETER, PRIVATE :: niter=1000,mxloop=500 REAL(8), PARAMETER, PRIVATE :: conv1=4.d13,conv2=3.d13,conv3=2.d13,conv4=1.d13 REAL(8), PRIVATE :: electrons TYPE (PotentialInfo) ,TARGET :: AEPot TYPE (OrbitInfo) ,TARGET :: AEOrbit TYPE (SCFInfo) ,TARGET :: AESCF TYPE (PotentialInfo) ,TARGET :: FCPot TYPE (OrbitInfo) ,TARGET :: FCOrbit TYPE (SCFInfo) ,TARGET :: FCSCF TYPE(FCInfo),TARGET :: FC TYPE (Gridinfo) ,TARGET :: Grid TYPE (PotentialInfo) ,PRIVATE, POINTER :: PotPtr TYPE (OrbitInfo) ,PRIVATE, POINTER :: OrbitPtr TYPE (SCFInfo) ,PRIVATE, POINTER :: SCFPtr CONTAINS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! SCFatom_Init !!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SUBROUTINE SCFatom_Init() ! program to calculate the self-consistent density functional ! atom ground state for atom with atomic number nz ! for self-consistent potential rv REAL(8) :: xocc,qf,small,zeff,hval REAL(8) :: qcal,rescale,nzeff,h,r0 INTEGER :: icount,i,j,k,it,start,np,ierr INTEGER :: is,ip,id,jf,ig,io,l,nfix,ir,kappa INTEGER :: nps,npp,npd,npf,npg INTEGER, ALLOCATABLE :: nl(:,:) ! Various initializations AEPot%v0=0.d0;AEPot%v0p=0.d0;AEPot%Nv0=0;AEPot%Nv0p=0 frozencorecalculation=.FALSE.;setupfrozencore=.false. gaussianshapefunction=.FALSE.;besselshapefunction=.FALSE. ! Atomic symbol and atomic number (from input dataset) AEPot%sym=input_dataset%atomic_symbol AEPot%nz=input_dataset%atomic_charge AEPot%zz=AEPot%nz ! Relativistic, point-nucleus, HF data (from input dataset) scalarrelativistic=input_dataset%scalarrelativistic diracrelativistic=input_dataset%diracrelativistic HFpostprocess=input_dataset%HFpostprocess finitenucleus=input_dataset%finitenucleus AEPot%finitenucleusmodel=input_dataset%finitenucleusmodel ! Grid data (from input dataset) IF (TRIM(input_dataset%gridkey)=='LINEAR') THEN hval=input_dataset%gridmatch/(input_dataset%gridpoints-1) CALL InitGrid(Grid,hval,input_dataset%gridrange) ELSEIF (TRIM(input_dataset%gridkey)=='LOGGRID') THEN hval=logh CALL findh(AEPot%zz,input_dataset%gridmatch,input_dataset%gridpoints,hval,r0) CALL InitGrid(Grid,hval,input_dataset%gridrange,r0=r0) ELSEIF (TRIM(input_dataset%gridkey)=='LOGGRID4') THEN hval=logh CALL findh_given_r0(AEPot%zz,input_dataset%gridmatch,lor00,& & input_dataset%gridpoints,hval) CALL InitGrid(Grid,hval,input_dataset%gridrange,r0=lor00/AEPot%zz) ENDIF CALL InitPot(AEPot,Grid%n) CALL Get_Nuclearpotential(Grid,AEPot) ! Logderiv data minlogderiv=input_dataset%minlogderiv maxlogderiv=input_dataset%maxlogderiv nlogderiv=input_dataset%nlogderiv ! Bound state solver BDsolve=input_dataset%BDsolve ! Exchange-correlation/HF keyword (from input dataset) exctype=input_dataset%exctype localizedcoreexchange=input_dataset%localizedcoreexchange ColleSalvetti=.FALSE. IF (TRIM(input_dataset%exctype)=='EXX'.or.& & TRIM(input_dataset%exctype)=='EXXKLI'.or.& & TRIM(input_dataset%exctype)=='EXXOCC') THEN CALL EXX_Input_Settings(input_dataset%fixed_zero,input_dataset%fixed_zero_index) ELSE IF (TRIM(input_dataset%exctype)=='EXXCS') THEN CALL EXX_Input_Settings(input_dataset%fixed_zero,input_dataset%fixed_zero_index) ColleSalvetti=.TRUE. ELSE IF (TRIM(input_dataset%exctype)=='HF'.or.& & TRIM(input_dataset%exctype)=='HFV') THEN ELSE CALL initexch ENDIF ! Electronic configuration of atom WRITE(STD_OUT,'(a,f6.2)') ' Calculation for atomic number = ',AEPot%zz call flush_unit(std_out) nps=input_dataset%np(1) npp=input_dataset%np(2) npd=input_dataset%np(3) npf=input_dataset%np(4) npg=input_dataset%np(5) WRITE(STD_OUT,'(5i4)') nps,npp,npd,npf,npg i=MAX(nps,npp,npd,npf,npg) j=nps IF(npp>0) j=j+npp-1 IF(npd>0) j=j+npd-2 IF(npf>0) j=j+npf-3 IF(npg>0) j=j+npg-4 IF (diracrelativistic) j=j+j ! need more orbitals CALL InitOrbit(AEOrbit,j,Grid%n,exctype) AEOrbit%nps=nps;AEOrbit%npp=npp;AEOrbit%npd=npd AEOrbit%npf=npf;AEOrbit%npg=npg ALLOCATE(nl(i,j));nl=0 icount=0 IF (.not.diracrelativistic) THEN IF (nps.GT.0) THEN DO is=1,nps icount=icount+1 nl(is,1)=icount AEOrbit%occ(icount)=2.d0 AEOrbit%np(icount)=is AEOrbit%l(icount)=0 ENDDO ENDIF IF (npp.GT.1) THEN DO ip=2,npp icount=icount+1 nl(ip,2)=icount AEOrbit%occ(icount)=6.d0 AEOrbit%np(icount)=ip AEOrbit%l(icount)=1 ENDDO ENDIF IF (npd.GT.2) THEN DO id=3,npd icount=icount+1 nl(id,3)=icount AEOrbit%occ(icount)=10.d0 AEOrbit%np(icount)=id AEOrbit%l(icount)=2 ENDDO ENDIF IF (npf.GT.3) THEN DO jf=4,npf icount=icount+1 nl(jf,4)=icount AEOrbit%occ(icount)=14.d0 AEOrbit%np(icount)=jf AEOrbit%l(icount)=3 ENDDO ENDIF IF(npg.GT.4) THEN DO ig=5,npg icount=icount+1 nl(ig,5)=icount AEOrbit%occ(icount)=18.d0 AEOrbit%np(icount)=ig AEOrbit%l(icount)=4 ENDDO ENDIF AEOrbit%norbit=icount AEOrbit%nps=nps AEOrbit%npp=npp AEOrbit%npd=npd AEOrbit%npf=npf AEOrbit%npg=npg IF (AEOrbit%norbit/=input_dataset%norbit) STOP 'Inconsistent number of orbitals!' WRITE(STD_OUT,*) AEOrbit%norbit, ' orbitals will be calculated' WRITE(STD_OUT,*)' Below are listed the default occupations ' WRITE(STD_OUT,"(' n l occupancy')") DO io=1,AEOrbit%norbit WRITE(STD_OUT,'(i2,1x,i2,4x,1p,1e15.7)') & & AEOrbit%np(io),AEOrbit%l(io),AEOrbit%occ(io) ENDDO !Corrected occupations (from input dataset) DO io=1,input_dataset%norbit_mod l=input_dataset%orbit_mod_l(io) ip=input_dataset%orbit_mod_n(io) xocc=input_dataset%orbit_mod_occ(io) nfix=nl(ip,l+1) IF (nfix<=0.OR.nfix>AEOrbit%norbit) THEN WRITE(STD_OUT,*) 'error in occupations -- ip,l,xocc: ',ip,l,xocc,nfix,AEOrbit%norbit STOP ENDIF AEOrbit%occ(nfix)=xocc END DO WRITE(STD_OUT,*) ' Corrected occupations are: ' WRITE(STD_OUT,"(' n l occupancy')") electrons=0.d0 DO io=1,AEOrbit%norbit WRITE(STD_OUT,'(i2,1x,i2,4x,1p,1e15.7)') & & AEOrbit%np(io),AEOrbit%l(io),AEOrbit%occ(io) electrons=electrons+AEOrbit%occ(io) ENDDO ENDIF ! scalarrelativistic IF (diracrelativistic) THEN icount=0 deallocate(nl) i=MAX(nps,npp,npd,npf,npg) allocate(nl(i,-5:5)) nl=0 IF (nps.GT.0) THEN DO is=1,nps icount=icount+1 nl(is,-1)=icount AEOrbit%occ(icount)=2.d0 AEOrbit%np(icount)=is AEOrbit%l(icount)=0 AEOrbit%kappa(icount)=-1 ENDDO ENDIF IF (npp.GT.1) THEN DO ip=2,npp icount=icount+1 nl(ip,1)=icount AEOrbit%occ(icount)=2.d0 AEOrbit%np(icount)=ip AEOrbit%l(icount)=1 AEOrbit%kappa(icount)=1 ENDDO DO ip=2,npp icount=icount+1 nl(ip,-2)=icount AEOrbit%occ(icount)=4.d0 AEOrbit%np(icount)=ip AEOrbit%l(icount)=1 AEOrbit%kappa(icount)=-2 ENDDO ENDIF IF (npd.GT.2) THEN DO id=3,npd icount=icount+1 nl(id,2)=icount AEOrbit%occ(icount)=4.d0 AEOrbit%np(icount)=id AEOrbit%l(icount)=2 AEOrbit%kappa(icount)=2 ENDDO DO id=3,npd icount=icount+1 nl(id,-3)=icount AEOrbit%occ(icount)=6.d0 AEOrbit%np(icount)=id AEOrbit%l(icount)=2 AEOrbit%kappa(icount)=-3 ENDDO ENDIF IF (npf.GT.3) THEN DO jf=4,npf icount=icount+1 nl(jf,3)=icount AEOrbit%occ(icount)=6.d0 AEOrbit%np(icount)=jf AEOrbit%l(icount)=3 AEOrbit%kappa(icount)=3 ENDDO DO jf=4,npf icount=icount+1 nl(jf,-4)=icount AEOrbit%occ(icount)=8.d0 AEOrbit%np(icount)=jf AEOrbit%l(icount)=3 AEOrbit%kappa(icount)=-4 ENDDO ENDIF IF(npg.GT.4) THEN DO ig=5,npg icount=icount+1 nl(ig,4)=icount AEOrbit%occ(icount)=8.d0 AEOrbit%np(icount)=ig AEOrbit%l(icount)=4 AEOrbit%kappa(icount)=4 ENDDO DO ig=5,npg icount=icount+1 nl(ig,-5)=icount AEOrbit%occ(icount)=10.d0 AEOrbit%np(icount)=ig AEOrbit%l(icount)=4 AEOrbit%kappa(icount)=-5 ENDDO ENDIF AEOrbit%norbit=icount AEOrbit%nps=nps AEOrbit%npp=npp AEOrbit%npd=npd AEOrbit%npf=npf AEOrbit%npg=npg IF (AEOrbit%norbit/=input_dataset%norbit) STOP 'Inconsistent number of orbitals!' WRITE(STD_OUT,*) AEOrbit%norbit, ' orbitals will be calculated' WRITE(STD_OUT,*)' Below are listed the default occupations ' WRITE(STD_OUT,"(' n l kappa occupancy')") DO io=1,AEOrbit%norbit WRITE(STD_OUT,'(i2,1x,i2,3x,i2,4x,1p,1e15.7)') & & AEOrbit%np(io),AEOrbit%l(io),AEOrbit%kappa(io),AEOrbit%occ(io) ENDDO !Corrected occupations (from input dataset) DO io=1,input_dataset%norbit_mod l=input_dataset%orbit_mod_l(io) ip=input_dataset%orbit_mod_n(io) kappa=input_dataset%orbit_mod_k(io) xocc=input_dataset%orbit_mod_occ(io) nfix=nl(ip,kappa) IF (nfix<=0.OR.nfix>AEOrbit%norbit) THEN WRITE(STD_OUT,*) 'error in occupations -- ip,l,kappa,xocc: ',ip,l,kappa,xocc,nfix,AEOrbit%norbit STOP ENDIF AEOrbit%occ(nfix)=xocc END DO WRITE(STD_OUT,*) ' Corrected occupations are: ' WRITE(STD_OUT,"(' n l kappa occupancy')") electrons=0.d0 DO io=1,AEOrbit%norbit WRITE(STD_OUT,'(i2,1x,i2,3x,i2,4x,1p,1e15.7)') & & AEOrbit%np(io),AEOrbit%l(io),AEOrbit%kappa(io),AEOrbit%occ(io) electrons=electrons+AEOrbit%occ(io) ENDDO ENDIF ! diracrelativistic AEPot%q=electrons qf=AEPot%nz-electrons WRITE(STD_OUT,*) WRITE(STD_OUT,*) 'nuclear charge = ', AEPot%nz WRITE(STD_OUT,*) 'electronic charge = ', electrons WRITE(STD_OUT,*) 'net charge = ', qf CALL InitSCF(AESCF) IF (scalarrelativistic) CALL Allocate_Scalar_Relativistic(Grid) IF (diracrelativistic) CALL Allocate_Dirac_Relativistic(Grid) write(std_out,*) 'Finish SCFatom_Init' ; call flush_unit(std_out) DEALLOCATE(nl) END SUBROUTINE SCFatom_Init !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! SCFatom !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SUBROUTINE SCFatom(scftype,lotsofoutput,skip_reading) IMPLICIT NONE CHARACTER(2),INTENT(IN)::scftype LOGICAL,INTENT(IN) :: lotsofoutput LOGICAL,INTENT(IN),OPTIONAL :: skip_reading TYPE(SCFInfo) :: SCFPP ! program to perform self-consistency loop IF(scftype=='AE') THEN !------------AE calculation-------------- frozencorecalculation=.FALSE. setupfrozencore=.FALSE. PotPtr=>AEPot OrbitPtr=>AEOrbit SCFPtr=>AESCF CALL Orbit_Init(OrbitPtr,PotPtr) CALL Potential_Init(OrbitPtr,PotPtr) ELSEIF(scftype=='NC') THEN !------------New Configuration Calculation--------- frozencorecalculation=.FALSE. setupfrozencore=.FALSE. PotPtr=>AEPot OrbitPtr=>AEOrbit SCFPtr=>AESCF IF (PRESENT(skip_reading)) THEN CALL NC_Init(OrbitPtr,PotPtr,skip_reading=skip_reading) ELSE CALL NC_Init(OrbitPtr,PotPtr) ENDIF CALL Potential_Init(OrbitPtr,PotPtr) ELSEIF(scftype=='SC') THEN !------------Set Core and Valence in current config.--------- frozencorecalculation=.TRUE. setupfrozencore=.TRUE. CALL CopyPot(AEPot,FCPot) CALL CopyOrbit(AEOrbit,FCOrbit) CALL CopySCF(AESCF,FCSCF) PotPtr=>FCPot OrbitPtr=>FCOrbit SCFPtr=>FCSCF CALL SC_Init(OrbitPtr,PotPtr,SCFPtr) ELSEIF(scftype=='FC') THEN !------------Frozen Core Calculation--------- frozencorecalculation=.TRUE. setupfrozencore=.FALSE. PotPtr=>FCPot OrbitPtr=>FCOrbit SCFPtr=>FCSCF CALL FC_Init(OrbitPtr,PotPtr) CALL Potential_Init(OrbitPtr,PotPtr) ENDIF IF (TRIM(OrbitPtr%exctype)=='EXX'.OR. & & TRIM(OrbitPtr%exctype)=='EXXKLI'.OR. & TRIM(OrbitPtr%exctype)=='EXXCS') THEN CALL EXX_SCF(scftype,lotsofoutput,Grid,OrbitPtr,PotPtr,FC,SCFPtr) ELSE IF (TRIM(OrbitPtr%exctype)=='EXXOCC') THEN CALL EXXOCC_SCF(scftype,lotsofoutput,Grid,OrbitPtr,PotPtr,FC,SCFPtr) ELSE IF (TRIM(OrbitPtr%exctype)=='HF'.or.TRIM(OrbitPtr%exctype)=='HFV') THEN write(std_out,*) 'Just before HF_SCF'; call flush_unit(std_out) CALL HF_SCF(scftype,lotsofoutput,Grid,OrbitPtr,PotPtr,FC,SCFPtr) write(std_out,*) 'Just after HF_SCF'; call flush_unit(std_out) ELSE !LDA or GGA CALL LDAGGA_SCF(scftype,lotsofoutput,Grid,OrbitPtr,PotPtr,FC,SCFPtr) ENDIF If (HFpostprocess) then write(std_out,*) "******PostProcessing HF*********" CALL InitSCF(SCFPP) call hf_energy_only(Grid,OrbitPtr,PotPtr,SCFPP) endif END SUBROUTINE SCFatom !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! Orbit_Init !! From nuclear charge -- generate hydrogenic-like initial wfns !! and densities -- !! fill AEOrbit%wfn, AEOrbit%eig, and AEOrbit%den and AEOrbit%q !! also AEOrbit%otau and AEOrbit%tau !! Note that both den and tau need to be divided by 4 \pi r^2 !! Note that tau is only correct for non-relativistic case !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SUBROUTINE Orbit_Init(Orbit,Pot) IMPLICIT NONE TYPE(PotentialInfo),INTENT(INOUT) :: Pot TYPE(OrbitInfo),INTENT(INOUT) :: Orbit INTEGER :: i,io,ir,ip,l,nfix,np,kappa REAL(8) :: en0,qcal,qf,rescale,z,small,zeff,xocc,fac REAL(8),allocatable :: dpdr(:),pbr(:) INTEGER :: initialconfig=0 IF (initialconfig/=0) STOP 'Error in aeatom -- Orbit_Init already called' ! calculate initial charge density from hydrogen-like functions ! also initial energies zeff=Pot%nz If (.not.diracrelativistic) then DO io=1,Orbit%norbit np=Orbit%np(io) l=Orbit%l(io) xocc=Orbit%occ(io) Orbit%eig(io)=-(zeff/(np))**2 WRITE(STD_OUT,*) io,np,l,xocc,Orbit%eig(io) DO ir=1,Grid%n Orbit%wfn(ir,io)=hwfn(zeff,np,l,Grid%r(ir)) IF (ABS(Orbit%wfn(ir,io))