/PP/projwfc.f90
http://github.com/NNemec/quantum-espresso · Fortran Modern · 3396 lines · 2435 code · 88 blank · 873 comment · 76 complexity · c6d124e28c2f01f15117431d03835acc MD5 · raw file
Large files are truncated click here to view the full file
- !
- ! Copyright (C) 2001-2009 Quantum ESPRESSO 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 .
- !
- !-----------------------------------------------------------------------
- PROGRAM projwfc
- !-----------------------------------------------------------------------
- !
- ! projects wavefunctions onto orthogonalized atomic wavefunctions,
- ! calculates Lowdin charges, spilling parameter, projected DOS
- ! or computes the LDOS in a volume given in input as function of energy
- !
- !
- ! Input (namelist &inputpp ... / ): Default value
- !
- ! prefix prefix of input file produced by pw.x 'pwscf'
- ! (wavefunctions are needed)
- ! outdir directory containing the input file ./
- ! ngauss type of gaussian broadening (optional) 0
- ! = 0 Simple Gaussian (default)
- ! = 1 Methfessel-Paxton of order 1
- ! = -1 Marzari-Vanderbilt "cold smearing"
- ! =-99 Fermi-Dirac function
- ! degauss gaussian broadening, Ry (not eV!) 0.0
- ! Emin, Emax min, max energy (eV) for DOS plot band extrema
- ! DeltaE energy grid step (eV) none
- ! lsym if true the projections are symmetrized .true.
- ! filproj file containing the projections none
- ! filpdos prefix for output files containing PDOS(E) prefix
- ! lgww if .true. take energies from previous GWW calculation
- ! (file bands.dat)
- ! kresolveddos if .true. the DOS is written as function .false.
- ! of the k-point (not summed over all of them)
- ! all k-points but results
- ! tdosinboxes if .true., the local DOS in specified .false.
- ! volumes (boxes) is computed
- ! n_proj_boxes number of volumes for the local DOS 0
- ! irmin, irmax first and last point of the FFT grid 1, 0
- ! included in the volume
- ! plotboxes if .true., the volumes are given in output .false.
- !
- !
- ! Output:
- !
- ! Projections are written to standard output,
- ! and also to file filproj if given as input.
- ! The total DOS and the sum of projected DOS are written to file
- ! "filpdos".pdos_tot.
- ! The format for the collinear, spin-unpolarized case and the
- ! non-collinear, spin-orbit case is
- ! E DOS(E) PDOS(E)
- ! The format for the collinear, spin-polarized case is
- ! E DOSup(E) DOSdw(E) PDOSup(E) PDOSdw(E)
- ! The format for the non-collinear, non spin-orbit case is
- ! E DOS(E) PDOSup(E) PDOSdw(E)
- !
- ! In the collinear case and the non-collinear, non spin-orbit case
- ! projected DOS are written to file "filpdos".pdos_atm#N(X)_wfc#M(l),
- ! where N = atom number , X = atom symbol, M = wfc number, l=s,p,d,f
- ! (one file per atomic wavefunction found in the pseudopotential file)
- ! - The format for the collinear, spin-unpolarized case is
- ! E LDOS(E) PDOS_1(E) ... PDOS_2l+1(E)
- ! where LDOS = \sum m=1,2l+1 PDOS_m(E)
- ! and PDOS_m(E) = projected DOS on atomic wfc with component m
- ! - The format for the collinear, spin-polarized case and the
- ! non-collinear, non spin-orbit case is as above with
- ! two components for both LDOS(E) and PDOS_m(E)
- !
- ! In the non-collinear, spin-orbit case (i.e. if there is at least one
- ! fully relativistic pseudopotential) wavefunctions are projected
- ! onto eigenstates of the total angular-momentum.
- ! Projected DOS are written to file "filpdos".pdos_atm#N(X)_wfc#M(l_j),
- ! where N = atom number , X = atom symbol, M = wfc number, l=s,p,d,f
- ! and j is the value of the total angular momentum.
- ! In this case the format is
- ! E LDOS(E) PDOS_1(E) ... PDOS_2j+1(E)
- !
- ! All DOS(E) are in states/eV plotted vs E in eV
- !
- ! If the kresolveddos option is used, the k-point index is prepended
- ! to the formats above, e.g. (collinear, spin-unpolarized case)
- ! ik E DOS(E) PDOS(E)
- !
- ! If the local DOS(E) is computed (tdosinboxes),
- ! projections are written to file "filproj" if given as input.
- ! Volumes are written as xsf files with 3D datagrids, valued 1.0
- ! inside the box volume and 0 outside, named filpdos.box#n.xsf
- ! The local DOS(E) is written to file "filpdos".ldos_boxes, with format
- ! E totDOS(E) SumLDOS(E) LDOS_1(E) ... LDOS_n(E)
- !
- ! Order of m-components for each l in the output:
- !
- ! 1, cos(phi), sin(phi), cos(2*phi), sin(2*phi), .., cos(l*phi), sin(l*phi)
- !
- ! where phi is the polar angle:x=r cos(theta)cos(phi), y=r cos(theta)sin(phi)
- ! This is determined in file flib/ylmr2.f90 that calculates spherical harm.
- ! L=1 :
- ! 1 pz (m=0)
- ! 2 px (real combination of m=+/-1 with cosine)
- ! 3 py (real combination of m=+/-1 with sine)
- ! L=2 :
- ! 1 dz2 (m=0)
- ! 2 dzx (real combination of m=+/-1 with cosine)
- ! 3 dzy (real combination of m=+/-1 with sine)
- ! 4 dx2-y2 (real combination of m=+/-2 with cosine)
- ! 5 dxy (real combination of m=+/-1 with sine)
- !
- ! Important notice:
- !
- ! The tetrahedron method is presently not implemented.
- ! Gaussian broadening is used in all cases:
- ! - if degauss is set to some value in namelist &inputpp, that value
- ! (and the optional value for ngauss) is used
- ! - if degauss is NOT set to any value in namelist &inputpp, the
- ! value of degauss and of ngauss are read from the input data
- ! file (they will be the same used in the pw.x calculations)
- ! - if degauss is NOT set to any value in namelist &inputpp, AND
- ! there is no value of degauss and of ngauss in the input data
- ! file, degauss=DeltaE (in Ry) and ngauss=0 will be used
- ! Obsolete variables, ignored:
- ! io_choice
- ! smoothing
- !
- USE io_global, ONLY : stdout, ionode, ionode_id
- USE constants, ONLY : rytoev
- USE kinds, ONLY : DP
- USE klist, ONLY : degauss, ngauss, lgauss
- USE io_files, ONLY : nd_nmbr, prefix, tmp_dir, trimcheck
- USE noncollin_module, ONLY : noncolin
- USE mp, ONLY : mp_bcast
- USE mp_global, ONLY : mp_startup, nproc_ortho
- USE environment, ONLY : environment_start
- !
- ! for GWW
- USE io_files, ONLY : find_free_unit
- !
- !
- IMPLICIT NONE
- CHARACTER (len=256) :: filpdos, filproj, io_choice, outdir
- REAL (DP) :: Emin, Emax, DeltaE, degauss1, smoothing
- INTEGER :: ngauss1, ios
- LOGICAL :: lsym, kresolveddos, tdosinboxes, plotboxes
- INTEGER, PARAMETER :: N_MAX_BOXES = 999
- INTEGER :: n_proj_boxes, irmin(3,N_MAX_BOXES), irmax(3,N_MAX_BOXES)
- !
- ! for GWW
- INTEGER :: iun, idum
- REAL(DP) :: rdum1,rdum2,rdum3
- LOGICAL :: lex, lgww
- !
- !
- NAMELIST / inputpp / outdir, prefix, ngauss, degauss, lsym, &
- Emin, Emax, DeltaE, io_choice, smoothing, filpdos, filproj, &
- lgww, & !if .true. use GW QP energies from file bands.dat
- kresolveddos, tdosinboxes, n_proj_boxes, irmin, irmax, plotboxes
- !
- ! initialise environment
- !
- #ifdef __PARA
- CALL mp_startup ( )
- #endif
- CALL environment_start ( 'PROJWFC' )
- !
- ! set default values for variables in namelist
- !
- prefix = 'pwscf'
- CALL get_env( 'ESPRESSO_TMPDIR', outdir )
- IF ( trim( outdir ) == ' ' ) outdir = './'
- filproj= ' '
- filpdos= ' '
- Emin =-1000000.d0
- Emax =+1000000.d0
- DeltaE = 0.01d0
- ngauss = 0
- lsym = .true.
- degauss= 0.d0
- lgww = .false.
- kresolveddos = .false.
- tdosinboxes = .false.
- plotboxes = .false.
- n_proj_boxes= 1
- irmin(:,:) = 1
- irmax(:,:) = 0
- !
- ios = 0
- !
- IF ( ionode ) THEN
- !
- CALL input_from_file ( )
- !
- READ (5, inputpp, iostat = ios)
- !
- tmp_dir = trimcheck (outdir)
- ! save the value of degauss and ngauss: they are read from file
- degauss1=degauss
- ngauss1 = ngauss
- !
- ENDIF
- !
- CALL mp_bcast (ios, ionode_id )
- !
- IF (ios /= 0) CALL errore ('projwfc', 'reading inputpp namelist', abs (ios) )
- !
- ! ... Broadcast variables
- !
- CALL mp_bcast( tmp_dir, ionode_id )
- CALL mp_bcast( prefix, ionode_id )
- CALL mp_bcast( filproj, ionode_id )
- CALL mp_bcast( ngauss1, ionode_id )
- CALL mp_bcast( degauss1,ionode_id )
- CALL mp_bcast( DeltaE, ionode_id )
- CALL mp_bcast( lsym, ionode_id )
- CALL mp_bcast( Emin, ionode_id )
- CALL mp_bcast( Emax, ionode_id )
- ! for GWW
- CALL mp_bcast( lgww, ionode_id )
- ! for projection on boxes
- CALL mp_bcast( tdosinboxes, ionode_id )
- CALL mp_bcast( n_proj_boxes, ionode_id )
- CALL mp_bcast( irmin, ionode_id )
- CALL mp_bcast( irmax, ionode_id )
- !
- ! Now allocate space for pwscf variables, read and check them.
- !
- CALL read_file ( )
- !
- CALL openfil_pp ( )
- !
- ! decide Gaussian broadening
- !
- IF (degauss1/=0.d0) THEN
- degauss=degauss1
- ngauss =ngauss1
- WRITE( stdout,'(/5x,"Gaussian broadening (read from input): ",&
- & "ngauss,degauss=",i4,f12.6/)') ngauss,degauss
- lgauss=.true.
- ELSEIF (lgauss) THEN
- WRITE( stdout,'(/5x,"Gaussian broadening (read from file): ",&
- & "ngauss,degauss=",i4,f12.6/)') ngauss,degauss
- ELSE
- degauss=DeltaE/rytoev
- ngauss =0
- WRITE( stdout,'(/5x,"Gaussian broadening (default values): ",&
- & "ngauss,degauss=",i4,f12.6/)') ngauss,degauss
- lgauss=.true.
- ENDIF
- !
- IF ( filpdos == ' ') filpdos = prefix
- !
- IF ( tdosinboxes ) THEN
- IF( nproc_ortho > 1 ) THEN
- CALL errore ('projwfc', 'nproc_ortho > 1 not yet implemented', 1)
- ELSE
- CALL projwave_boxes (filpdos, filproj, n_proj_boxes, irmin, irmax, plotboxes)
- ENDIF
- ELSE
- IF (noncolin) THEN
- CALL projwave_nc(filproj, lsym )
- ELSE
- IF( nproc_ortho > 1 ) THEN
- CALL pprojwave (filproj, lsym)
- ELSE
- CALL projwave (filproj, lsym, lgww)
- ENDIF
- ENDIF
- ENDIF
- !
- IF ( ionode ) THEN
- IF ( tdosinboxes ) THEN
- CALL partialdos_boxes (Emin, Emax, DeltaE, kresolveddos, filpdos, n_proj_boxes)
- ELSE
- IF ( lsym ) THEN
- !
- IF (noncolin) THEN
- CALL partialdos_nc (Emin, Emax, DeltaE, kresolveddos, filpdos)
- ELSE
- CALL partialdos (Emin, Emax, DeltaE, kresolveddos, filpdos)
- ENDIF
- !
- ENDIF
- ENDIF
- ENDIF
- !
- CALL stop_pp
- !
- END PROGRAM projwfc
- !
- MODULE projections
- USE kinds, ONLY : DP
- TYPE wfc_label
- INTEGER na, n, l, m
- END TYPE wfc_label
- TYPE(wfc_label), ALLOCATABLE :: nlmchi(:)
- REAL (DP), ALLOCATABLE :: proj (:,:,:)
- COMPLEX (DP), ALLOCATABLE :: proj_aux (:,:,:)
- END MODULE projections
- !
- MODULE projections_nc
- USE kinds, ONLY : DP
- TYPE wfc_label_nc
- INTEGER na, n, l, m, ind
- REAL (DP) jj
- END TYPE wfc_label_nc
- TYPE(wfc_label_nc), ALLOCATABLE :: nlmchi(:)
- REAL (DP), ALLOCATABLE :: proj (:,:,:)
- COMPLEX (DP), ALLOCATABLE :: proj_aux (:,:,:)
- END MODULE projections_nc
- !
- MODULE projections_ldos
- USE kinds, ONLY : DP
- REAL (DP), ALLOCATABLE :: proj (:,:,:)
- END MODULE projections_ldos
- !
- !-----------------------------------------------------------------------
- SUBROUTINE projwave( filproj, lsym, lgww )
- !-----------------------------------------------------------------------
- !
- USE io_global, ONLY : stdout, ionode
- USE printout_base, ONLY: title
- USE ions_base, ONLY : zv, tau, nat, ntyp => nsp, ityp, atm
- USE basis, ONLY : natomwfc
- USE cell_base
- USE constants, ONLY: rytoev, eps4
- USE gvect
- USE grid_dimensions, ONLY : nr1, nr2, nr3, nr1x, nr2x, nr3x
- USE klist, ONLY: xk, nks, nkstot, nelec
- USE ldaU
- USE lsda_mod, ONLY: nspin, isk, current_spin
- USE symm_base, ONLY: nsym, irt, d1, d2, d3
- USE wvfct
- USE control_flags, ONLY: gamma_only
- USE uspp, ONLY: nkb, vkb
- USE uspp_param, ONLY: upf
- USE becmod, ONLY: bec_type, becp, calbec, allocate_bec_type, deallocate_bec_type
- USE io_files, ONLY: nd_nmbr, prefix, tmp_dir, nwordwfc, iunwfc, find_free_unit
- USE spin_orb, ONLY: lspinorb
- USE wavefunctions_module, ONLY: evc
- !
- USE projections
- !
- IMPLICIT NONE
- !
- CHARACTER (len=*) :: filproj
- INTEGER :: ik, ibnd, i, j, k, na, nb, nt, isym, n, m, m1, l, nwfc,&
- nwfc1, lmax_wfc, is, ios, iunproj
- REAL(DP), ALLOCATABLE :: e (:)
- COMPLEX(DP), ALLOCATABLE :: wfcatom (:,:)
- COMPLEX(DP), ALLOCATABLE :: overlap(:,:), work(:,:),work1(:), proj0(:,:)
- ! Some workspace for k-point calculation ...
- REAL (DP), ALLOCATABLE ::roverlap(:,:), rwork1(:),rproj0(:,:)
- ! ... or for gamma-point.
- REAL(DP), ALLOCATABLE :: charges(:,:,:), proj1 (:)
- REAL(DP) :: psum, totcharge(2)
- INTEGER :: nksinit, nkslast
- CHARACTER(len=256) :: filename
- CHARACTER (len=1) :: l_label(0:3)=(/'s','p','d','f'/)
- INTEGER, ALLOCATABLE :: idx(:)
- LOGICAL :: lsym
- !
- !
- ! for GWW
- INTEGER :: iun, idum
- REAL(DP) :: rdum1,rdum2,rdum3
- LOGICAL :: lex, lgww
- !
- !
- WRITE( stdout, '(/5x,"Calling projwave .... ")')
- IF ( gamma_only ) THEN
- WRITE( stdout, '(5x,"gamma-point specific algorithms are used")')
- ENDIF
- !
- ! initialize D_Sl for l=1, l=2 and l=3, for l=0 D_S0 is 1
- !
- CALL d_matrix (d1, d2, d3)
- !
- ! fill structure nlmchi
- !
- ALLOCATE (nlmchi(natomwfc))
- nwfc=0
- lmax_wfc = 0
- DO na = 1, nat
- nt = ityp (na)
- DO n = 1, upf(nt)%nwfc
- IF (upf(nt)%oc (n) >= 0.d0) THEN
- l = upf(nt)%lchi (n)
- lmax_wfc = max (lmax_wfc, l )
- DO m = 1, 2 * l + 1
- nwfc=nwfc+1
- nlmchi(nwfc)%na = na
- nlmchi(nwfc)%n = n
- nlmchi(nwfc)%l = l
- nlmchi(nwfc)%m = m
- ENDDO
- ENDIF
- ENDDO
- ENDDO
- !
- IF (lmax_wfc > 3) CALL errore ('projwave', 'l > 3 not yet implemented', 1)
- IF (nwfc /= natomwfc) CALL errore ('projwave', 'wrong # of atomic wfcs?', 1)
- !
- ALLOCATE( proj (natomwfc, nbnd, nkstot) )
- ALLOCATE( proj_aux (natomwfc, nbnd, nkstot) )
- proj = 0.d0
- proj_aux = (0.d0, 0.d0)
- !
- IF (.not. lda_plus_u) ALLOCATE(swfcatom (npwx , natomwfc ) )
- ALLOCATE(wfcatom (npwx, natomwfc) )
- ALLOCATE(overlap (natomwfc, natomwfc) )
- overlap= (0.d0,0.d0)
- !
- IF ( gamma_only ) THEN
- ALLOCATE(roverlap (natomwfc, natomwfc) )
- roverlap= 0.d0
- ENDIF
- CALL allocate_bec_type (nkb, natomwfc, becp )
- ALLOCATE(e (natomwfc) )
- !
- ! loop on k points
- !
- CALL init_us_1
- CALL init_at_1
- !
- DO ik = 1, nks
- CALL gk_sort (xk (1, ik), ngm, g, ecutwfc / tpiba2, npw, igk, g2kin)
- CALL davcio (evc, nwordwfc, iunwfc, ik, - 1)
- CALL atomic_wfc (ik, wfcatom)
- CALL init_us_2 (npw, igk, xk (1, ik), vkb)
- CALL calbec ( npw, vkb, wfcatom, becp)
- CALL s_psi (npwx, npw, natomwfc, wfcatom, swfcatom)
- !
- ! wfcatom = |phi_i> , swfcatom = \hat S |phi_i>
- ! calculate overlap matrix O_ij = <phi_i|\hat S|\phi_j>
- !
- IF ( gamma_only ) THEN
- CALL calbec ( npw, wfcatom, swfcatom, roverlap )
- overlap(:,:)=cmplx(roverlap(:,:),0.0_dp, kind=dp)
- ! TEMP: diagonalization routine for real matrix should be used instead
- ELSE
- CALL calbec ( npw, wfcatom, swfcatom, overlap )
- ENDIF
- !
- ! calculate O^{-1/2}
- !
- ALLOCATE(work (natomwfc, natomwfc) )
- CALL cdiagh (natomwfc, overlap, natomwfc, e, work)
- DO i = 1, natomwfc
- e (i) = 1.d0 / dsqrt (e (i) )
- ENDDO
- DO i = 1, natomwfc
- DO j = i, natomwfc
- overlap (i, j) = (0.d0, 0.d0)
- DO k = 1, natomwfc
- overlap (i, j) = overlap (i, j) + e (k) * work (j, k) * conjg (work (i, k) )
- ENDDO
- IF (j /= i) overlap (j, i) = conjg (overlap (i, j))
- ENDDO
- ENDDO
- DEALLOCATE (work)
- !
- ! calculate wfcatom = O^{-1/2} \hat S | phi>
- !
- IF ( gamma_only ) THEN
- roverlap(:,:)=REAL(overlap(:,:),DP)
- ! TEMP: diagonalization routine for real matrix should be used instead
- CALL DGEMM ('n', 't', 2*npw, natomwfc, natomwfc, 1.d0 , &
- swfcatom, 2*npwx, roverlap, natomwfc, 0.d0, wfcatom, 2*npwx)
- ELSE
- CALL ZGEMM ('n', 't', npw, natomwfc, natomwfc, (1.d0, 0.d0) , &
- swfcatom, npwx, overlap, natomwfc, (0.d0, 0.d0), wfcatom, npwx)
- ENDIF
- !
- ! make the projection <psi_i| O^{-1/2} \hat S | phi_j>
- !
- IF ( gamma_only ) THEN
- !
- ALLOCATE(rproj0(natomwfc,nbnd), rwork1 (nbnd) )
- CALL calbec ( npw, wfcatom, evc, rproj0)
- !
- proj_aux(:,:,ik) = cmplx( rproj0(:,:), 0.0_dp, kind=dp )
- !
- ELSE
- !
- ALLOCATE(proj0(natomwfc,nbnd), work1 (nbnd) )
- CALL calbec ( npw, wfcatom, evc, proj0)
- !
- proj_aux(:,:,ik) = proj0(:,:)
- !
- ENDIF
- !
- ! symmetrize the projections
- !
- IF (lsym) THEN
- DO nwfc = 1, natomwfc
- !
- ! atomic wavefunction nwfc is on atom na
- !
- na= nlmchi(nwfc)%na
- n = nlmchi(nwfc)%n
- l = nlmchi(nwfc)%l
- m = nlmchi(nwfc)%m
- !
- DO isym = 1, nsym
- nb = irt (isym, na)
- DO nwfc1 =1, natomwfc
- IF (nlmchi(nwfc1)%na == nb .and. &
- nlmchi(nwfc1)%n == nlmchi(nwfc)%n .and. &
- nlmchi(nwfc1)%l == nlmchi(nwfc)%l .and. &
- nlmchi(nwfc1)%m == 1 ) GOTO 10
- ENDDO
- CALL errore('projwave','cannot symmetrize',1)
- 10 nwfc1=nwfc1-1
- !
- ! nwfc1 is the first rotated atomic wfc corresponding to nwfc
- !
- IF ( gamma_only ) THEN
- IF (l == 0) THEN
- rwork1(:) = rproj0 (nwfc1 + 1,:)
- ELSEIF (l == 1) THEN
- rwork1(:) = 0.d0
- DO m1 = 1, 3
- rwork1(:)=rwork1(:)+d1(m1,m,isym)*rproj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (l == 2) THEN
- rwork1(:) = 0.d0
- DO m1 = 1, 5
- rwork1(:)=rwork1(:)+d2(m1,m,isym)*rproj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (l == 3) THEN
- rwork1(:) = 0.d0
- DO m1 = 1, 7
- rwork1(:)=rwork1(:)+d3(m1,m,isym)*rproj0(nwfc1+m1,:)
- ENDDO
- ENDIF
- DO ibnd = 1, nbnd
- proj (nwfc, ibnd, ik) = proj (nwfc, ibnd, ik) + &
- rwork1(ibnd) * rwork1(ibnd) / nsym
- ENDDO
- ELSE
- IF (l == 0) THEN
- work1(:) = proj0 (nwfc1 + 1,:)
- ELSEIF (l == 1) THEN
- work1(:) = 0.d0
- DO m1 = 1, 3
- work1(:)=work1(:)+d1(m1,m,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (l == 2) THEN
- work1(:) = 0.d0
- DO m1 = 1, 5
- work1(:)=work1(:)+d2(m1,m,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (l == 3) THEN
- work1(:) = 0.d0
- DO m1 = 1, 7
- work1(:)=work1(:)+d3(m1,m,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ENDIF
- DO ibnd = 1, nbnd
- proj (nwfc, ibnd, ik) = proj (nwfc, ibnd, ik) + &
- work1(ibnd) * conjg (work1(ibnd)) / nsym
- ENDDO
- ENDIF
- ENDDO
- ENDDO
- ELSE
- IF ( gamma_only ) THEN
- DO nwfc=1,natomwfc
- DO ibnd=1,nbnd
- proj(nwfc,ibnd,ik)=abs(rproj0(nwfc,ibnd))**2
- ENDDO
- ENDDO
- ELSE
- DO nwfc=1,natomwfc
- DO ibnd=1,nbnd
- proj(nwfc,ibnd,ik)=abs(proj0(nwfc,ibnd))**2
- ENDDO
- ENDDO
- ENDIF
- ENDIF
- IF ( gamma_only ) THEN
- DEALLOCATE (rwork1)
- DEALLOCATE (rproj0)
- ELSE
- DEALLOCATE (work1)
- DEALLOCATE (proj0)
- ENDIF
- ! on k-points
- ENDDO
- !
- DEALLOCATE (e)
- IF ( gamma_only ) THEN
- DEALLOCATE (roverlap)
- ENDIF
- CALL deallocate_bec_type (becp)
- DEALLOCATE (overlap)
- DEALLOCATE (wfcatom)
- IF (.not. lda_plus_u) DEALLOCATE (swfcatom)
- !
- ! vectors et and proj are distributed across the pools
- ! collect data for all k-points to the first pool
- !
- CALL poolrecover (et, nbnd, nkstot, nks)
- CALL poolrecover (proj, nbnd * natomwfc, nkstot, nks)
- CALL poolrecover (proj_aux, 2 * nbnd * natomwfc, nkstot, nks)
- !
- !!!! for GWW
- IF(lgww) THEN
- INQUIRE ( file='bands.dat', EXIST=lex )
- WRITE(stdout,*) 'lex=', lex
- CALL flush_unit(stdout)
- !
- IF(lex) THEN
- WRITE(stdout,*) 'Read the file bands.dat => GWA Eigenvalues used.'
- CALL flush_unit(stdout)
- iun = find_free_unit()
- OPEN(unit=iun, file='bands.dat', status='unknown', form='formatted', IOSTAT=ios)
- READ(iun,*) idum
- DO i=1, nbnd
- READ(iun,*) idum,rdum1,rdum2,et(i,1),rdum3
- ENDDO
- et(:,1)=et(:,1)/rytoev !! because in bands.dat file, the QP energies are in eV
- ELSE
- WRITE(stdout,*) 'The file bands.dat does not exist.'
- WRITE(stdout,*) 'Eigenergies are not modified'
- CALL flush_unit(stdout)
- ENDIF
- !!!! end GWW
- !
- ENDIF
- IF ( ionode ) THEN
- !
- ! write on the file filproj
- !
- IF (filproj/=' ') THEN
- DO is=1,nspin
- IF (nspin==2) THEN
- IF (is==1) filename=trim(filproj)//'.up'
- IF (is==2) filename=trim(filproj)//'.down'
- nksinit=(nkstot/2)*(is-1)+1
- nkslast=(nkstot/2)*is
- ELSE
- filename=trim(filproj)
- nksinit=1
- nkslast=nkstot
- ENDIF
- iunproj=33
- CALL write_io_header(filename, iunproj, title, nr1x, nr2x, nr3x, &
- nr1, nr2, nr3, nat, ntyp, ibrav, celldm, at, gcutm, dual, &
- ecutwfc, nkstot/nspin, nbnd, natomwfc)
- DO nwfc = 1, natomwfc
- WRITE(iunproj,'(2i5,a3,3i5)') &
- nwfc, nlmchi(nwfc)%na, atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n, nlmchi(nwfc)%l, nlmchi(nwfc)%m
- DO ik=nksinit,nkslast
- DO ibnd=1,nbnd
- WRITE(iunproj,'(2i8,f20.10)') ik,ibnd, &
- abs(proj(nwfc,ibnd,ik))
- ENDDO
- ENDDO
- ENDDO
- CLOSE(iunproj)
- ENDDO
- ENDIF
- !
- ! write projections to file using iotk
- !
- CALL write_proj( "atomic_proj.xml", proj_aux )
- !
- ! write on the standard output file
- !
- WRITE( stdout,'(/5x,"Atomic states used for projection")')
- WRITE( stdout,'( 5x,"(read from pseudopotential files):"/)')
- DO nwfc = 1, natomwfc
- WRITE(stdout,1000) &
- nwfc, nlmchi(nwfc)%na, atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n, nlmchi(nwfc)%l, nlmchi(nwfc)%m
- ENDDO
- 1000 FORMAT (5x,"state #",i4,": atom ",i3," (",a3,"), wfc ",i2, &
- " (l=",i1," m=",i2,")")
- !
- ALLOCATE(idx(natomwfc), proj1 (natomwfc) )
- DO ik = 1, nkstot
- WRITE( stdout, '(/" k = ",3f14.10)') (xk (i, ik) , i = 1, 3)
- DO ibnd = 1, nbnd
- WRITE( stdout, '("==== e(",i4,") = ",f11.5," eV ==== ")') &
- ibnd, et (ibnd, ik) * rytoev
- !
- ! sort projections by magnitude, in decreasing order
- !
- DO nwfc = 1, natomwfc
- idx (nwfc) = 0
- proj1 (nwfc) = - proj (nwfc, ibnd, ik)
- ENDDO
- !
- ! projections differing by less than 1.d-4 are considered equal
- !
- CALL hpsort_eps (natomwfc, proj1, idx, eps4)
- !
- ! only projections that are larger than 0.001 are written
- !
- DO nwfc = 1, natomwfc
- proj1 (nwfc) = - proj1(nwfc)
- IF ( abs (proj1(nwfc)) < 0.001d0 ) GOTO 20
- ENDDO
- nwfc = natomwfc + 1
- 20 nwfc = nwfc -1
- !
- ! fancy (?!?) formatting
- !
- WRITE( stdout, '(5x,"psi = ",5(f5.3,"*[#",i4,"]+"))') &
- (proj1 (i), idx(i), i = 1, min(5,nwfc))
- DO j = 1, (nwfc-1)/5
- WRITE( stdout, '(10x,"+",5(f5.3,"*[#",i4,"]+"))') &
- (proj1 (i), idx(i), i = 5*j+1, min(5*(j+1),nwfc))
- ENDDO
- psum = 0.d0
- DO nwfc = 1, natomwfc
- psum = psum + proj (nwfc, ibnd, ik)
- ENDDO
- WRITE( stdout, '(4x,"|psi|^2 = ",f5.3)') psum
- !
- ENDDO
- ENDDO
- DEALLOCATE (idx, proj1)
- !
- ! estimate partial charges (Loewdin) on each atom
- !
- ALLOCATE ( charges (nat, 0:lmax_wfc, nspin ) )
- charges = 0.0d0
- DO ik = 1, nkstot
- IF ( nspin == 1 ) THEN
- current_spin = 1
- ELSEIF ( nspin == 2 ) THEN
- current_spin = isk ( ik )
- ELSE
- CALL errore ('projwfc_nc',' called in the wrong case ',1)
- ENDIF
- DO ibnd = 1, nbnd
- DO nwfc = 1, natomwfc
- na= nlmchi(nwfc)%na
- l = nlmchi(nwfc)%l
- charges(na,l,current_spin) = charges(na,l,current_spin) + &
- wg (ibnd,ik) * proj (nwfc, ibnd, ik)
- ENDDO
- ENDDO
- ENDDO
- !
- WRITE( stdout, '(/"Lowdin Charges: "/)')
- !
- DO na = 1, nat
- DO is = 1, nspin
- totcharge(is) = sum(charges(na,0:lmax_wfc,is))
- ENDDO
- IF ( nspin == 1) THEN
- WRITE( stdout, 2000) na, totcharge(1), &
- ( l_label(l), charges(na,l,1), l= 0,lmax_wfc)
- ELSEIF ( nspin == 2) THEN
- WRITE( stdout, 2000) na, totcharge(1) + totcharge(2), &
- ( l_label(l), charges(na,l,1) + charges(na,l,2), l=0,lmax_wfc)
- WRITE( stdout, 2001) totcharge(1), &
- ( l_label(l), charges(na,l,1), l= 0,lmax_wfc)
- WRITE( stdout, 2002) totcharge(2), &
- ( l_label(l), charges(na,l,2), l= 0,lmax_wfc)
- WRITE( stdout, 2003) totcharge(1) - totcharge(2), &
- ( l_label(l), charges(na,l,1) - charges(na,l,2), l=0,lmax_wfc)
- ENDIF
- ENDDO
- 2000 FORMAT (5x,"Atom # ",i3,": total charge = ",f8.4,4(", ",a1," =",f8.4))
- 2001 FORMAT (15x," spin up = ",f8.4,4(", ",a1," =",f8.4))
- 2002 FORMAT (15x," spin down = ",f8.4,4(", ",a1," =",f8.4))
- 2003 FORMAT (15x," polarization = ",f8.4,4(", ",a1," =",f8.4))
- !
- psum = sum(charges(:,:,:)) / nelec
- WRITE( stdout, '(5x,"Spilling Parameter: ",f8.4)') 1.0d0 - psum
- !
- ! Sanchez-Portal et al., Sol. State Commun. 95, 685 (1995).
- ! The spilling parameter measures the ability of the basis provided by
- ! the pseudo-atomic wfc to represent the PW eigenstates,
- ! by measuring how much of the subspace of the Hamiltonian
- ! eigenstates falls outside the subspace spanned by the atomic basis
- !
- DEALLOCATE (charges)
- !
- ENDIF
- !
- RETURN
- !
- END SUBROUTINE projwave
- !
- !-----------------------------------------------------------------------
- SUBROUTINE projwave_nc(filproj, lsym )
- !-----------------------------------------------------------------------
- !
- USE io_global, ONLY : stdout, ionode
- USE ions_base, ONLY : zv, tau, nat, ntyp => nsp, ityp, atm
- USE basis, ONLY : natomwfc
- USE printout_base, ONLY: title
- USE cell_base
- USE constants, ONLY: rytoev, eps4
- USE gvect
- USE grid_dimensions, ONLY : nr1, nr2, nr3, nr1x, nr2x, nr3x
- USE klist, ONLY: xk, nks, nkstot, nelec
- USE ldaU
- USE lsda_mod, ONLY: nspin
- USE noncollin_module, ONLY: noncolin, npol, angle1, angle2
- USE symm_base, ONLY: nsym, irt, t_rev
- USE wvfct
- USE control_flags, ONLY: gamma_only
- USE uspp, ONLY: nkb, vkb
- USE uspp_param, ONLY: upf
- USE becmod, ONLY: bec_type, becp, calbec, allocate_bec_type, deallocate_bec_type
- USE io_files, ONLY: nd_nmbr, prefix, tmp_dir, nwordwfc, iunwfc
- USE wavefunctions_module, ONLY: evc
- USE mp_global, ONLY : intra_pool_comm
- USE mp, ONLY : mp_sum
- !
- USE spin_orb, ONLY: lspinorb, domag
- USE projections_nc
- !
- IMPLICIT NONE
- !
- CHARACTER(len=*) :: filproj
- LOGICAL :: lsym
- INTEGER :: ik, ibnd, i, j, k, na, nb, nt, isym, ind, n, m, m1, n1, &
- n2, l, nwfc, nwfc1, lmax_wfc, is, nspin0, iunproj, &
- ind0
- REAL(DP) :: jj
- REAL(DP), ALLOCATABLE :: e (:)
- COMPLEX(DP), ALLOCATABLE :: wfcatom (:,:)
- COMPLEX(DP), ALLOCATABLE :: overlap(:,:), work(:,:),work1(:), proj0(:,:)
- ! Some workspace for k-point calculation ...
- REAL(DP), ALLOCATABLE :: charges(:,:,:), proj1 (:)
- REAL(DP) :: psum, totcharge(2), fact(2), spinor, compute_mj
- INTEGER, ALLOCATABLE :: idx(:)
- !
- COMPLEX(DP) :: d12(2, 2, 48), d32(4, 4, 48), d52(6, 6, 48), &
- d72(8, 8, 48)
- COMPLEX(DP) :: d012(2, 2, 48), d112(6, 6, 48), d212(10, 10, 48), &
- d312(14, 14, 48)
- !
- !
- !
- IF (.not.noncolin) CALL errore('projwave_nc','called in the wrong case',1)
- IF (gamma_only) CALL errore('projwave_nc','gamma_only not yet implemented',1)
- WRITE( stdout, '(/5x,"Calling projwave_nc .... ")')
- !
- ! fill structure nlmchi
- !
- ALLOCATE (nlmchi(natomwfc))
- nwfc=0
- lmax_wfc = 0
- DO na = 1, nat
- nt = ityp (na)
- n2 = 0
- DO n = 1, upf(nt)%nwfc
- IF (upf(nt)%oc (n) >= 0.d0) THEN
- l = upf(nt)%lchi (n)
- lmax_wfc = max (lmax_wfc, l )
- IF (lspinorb) THEN
- IF (upf(nt)%has_so) THEN
- jj = upf(nt)%jchi (n)
- ind = 0
- DO m = -l-1, l
- fact(1) = spinor(l,jj,m,1)
- fact(2) = spinor(l,jj,m,2)
- IF (abs(fact(1)) > 1.d-8 .or. abs(fact(2)) > 1.d-8) THEN
- nwfc = nwfc + 1
- ind = ind + 1
- nlmchi(nwfc)%na = na
- nlmchi(nwfc)%n = n
- nlmchi(nwfc)%l = l
- nlmchi(nwfc)%m = m
- nlmchi(nwfc)%ind = ind
- nlmchi(nwfc)%jj = jj
- ENDIF
- ENDDO
- ELSE
- DO n1 = l, l+1
- jj= dble(n1) - 0.5d0
- ind = 0
- IF (jj>0.d0) THEN
- n2 = n2 + 1
- DO m = -l-1, l
- fact(1) = spinor(l,jj,m,1)
- fact(2) = spinor(l,jj,m,2)
- IF (abs(fact(1)) > 1.d-8 .or. abs(fact(2)) > 1.d-8) THEN
- nwfc = nwfc + 1
- ind = ind + 1
- nlmchi(nwfc)%na = na
- nlmchi(nwfc)%n = n2
- nlmchi(nwfc)%l = l
- nlmchi(nwfc)%m = m
- nlmchi(nwfc)%ind = ind
- nlmchi(nwfc)%jj = jj
- ENDIF
- ENDDO
- ENDIF
- ENDDO
- ENDIF
- ELSE
- DO m = 1, 2 * l + 1
- nwfc=nwfc+1
- nlmchi(nwfc)%na = na
- nlmchi(nwfc)%n = n
- nlmchi(nwfc)%l = l
- nlmchi(nwfc)%m = m
- nlmchi(nwfc)%ind = m
- nlmchi(nwfc)%jj = 0.d0
- nlmchi(nwfc+2*l+1)%na = na
- nlmchi(nwfc+2*l+1)%n = n
- nlmchi(nwfc+2*l+1)%l = l
- nlmchi(nwfc+2*l+1)%m = m
- nlmchi(nwfc+2*l+1)%ind = m+2*l+1
- nlmchi(nwfc+2*l+1)%jj = 0.d0
- ENDDO
- nwfc=nwfc+2*l+1
- ENDIF
- ENDIF
- ENDDO
- ENDDO
- !
- IF (lmax_wfc > 3) CALL errore ('projwave_nc', 'l > 3 not yet implemented', 1)
- IF (nwfc /= natomwfc) CALL errore ('projwave_nc','wrong # of atomic wfcs?',1)
- !
- ALLOCATE(wfcatom (npwx*npol,natomwfc) )
- IF (.not. lda_plus_u) ALLOCATE(swfcatom (npwx*npol, natomwfc ) )
- CALL allocate_bec_type (nkb, natomwfc, becp )
- ALLOCATE(e (natomwfc) )
- ALLOCATE(work (natomwfc, natomwfc) )
- !
- ALLOCATE(overlap (natomwfc, natomwfc) )
- ALLOCATE(proj0(natomwfc,nbnd), work1 (nbnd) )
- ALLOCATE(proj (natomwfc, nbnd, nkstot) )
- ALLOCATE(proj_aux (natomwfc, nbnd, nkstot) )
- overlap = (0.d0,0.d0)
- proj0 = (0.d0,0.d0)
- proj = 0.d0
- proj_aux = (0.d0,0.d0)
- !
- ! loop on k points
- !
- CALL init_us_1
- CALL init_at_1
- !
- IF (lspinorb) THEN
- !
- ! initialize D_Sj for j=1/2, j=3/2, j=5/2 and j=7/2
- !
- CALL d_matrix_so (d12, d32, d52, d72)
- !
- ELSE
- !
- ! initialize D_Sl for l=0, l=1, l=2 and l=3
- !
- CALL d_matrix_nc (d012, d112, d212, d312)
- !
- ENDIF
- !
- DO ik = 1, nks
- wfcatom = (0.d0,0.d0)
- swfcatom= (0.d0,0.d0)
- CALL gk_sort (xk (1, ik), ngm, g, ecutwfc / tpiba2, npw, igk, g2kin)
- CALL davcio (evc, nwordwfc, iunwfc, ik, - 1)
- !
- CALL atomic_wfc_nc_proj (ik, wfcatom)
- !
- CALL init_us_2 (npw, igk, xk (1, ik), vkb)
- CALL calbec ( npw, vkb, wfcatom, becp )
- CALL s_psi (npwx, npw, natomwfc, wfcatom, swfcatom)
- !
- ! wfcatom = |phi_i> , swfcatom = \hat S |phi_i>
- ! calculate overlap matrix O_ij = <phi_i|\hat S|\phi_j>
- !
- CALL ZGEMM ('C', 'N', natomwfc, natomwfc, npwx*npol, (1.d0, 0.d0), wfcatom, &
- npwx*npol, swfcatom, npwx*npol, (0.d0, 0.d0), overlap, natomwfc)
- CALL mp_sum ( overlap, intra_pool_comm )
- !
- ! calculate O^{-1/2}
- !
- CALL cdiagh (natomwfc, overlap, natomwfc, e, work)
- DO i = 1, natomwfc
- e (i) = 1.d0 / dsqrt (e (i) )
- ENDDO
- DO i = 1, natomwfc
- DO j = i, natomwfc
- overlap (i, j) = (0.d0, 0.d0)
- DO k = 1, natomwfc
- overlap(i, j) = overlap(i, j) + e(k) * work(j, k) * conjg(work (i, k) )
- ENDDO
- IF (j /= i) overlap (j, i) = conjg (overlap (i, j))
- ENDDO
- ENDDO
- !
- ! calculate wfcatom = O^{-1/2} \hat S | phi>
- !
- CALL ZGEMM ('n', 't', npwx*npol, natomwfc, natomwfc, (1.d0, 0.d0) , &
- swfcatom, npwx*npol, overlap, natomwfc, (0.d0, 0.d0), wfcatom, npwx*npol)
- !
- ! make the projection <psi_i| O^{-1/2} \hat S | phi_j>
- !
- CALL ZGEMM ('C','N',natomwfc, nbnd, npwx*npol, (1.d0, 0.d0), wfcatom, &
- npwx*npol, evc, npwx*npol, (0.d0, 0.d0), proj0, natomwfc)
- CALL mp_sum ( proj0( :, 1:nbnd ), intra_pool_comm )
- !
- proj_aux(:,:,ik) = proj0(:,:)
- !
- IF (lsym) THEN
- DO nwfc = 1, natomwfc
- !
- ! atomic wavefunction nwfc is on atom na
- !
- IF (lspinorb) THEN
- na= nlmchi(nwfc)%na
- n = nlmchi(nwfc)%n
- l = nlmchi(nwfc)%l
- m = nlmchi(nwfc)%m
- ind0 = nlmchi(nwfc)%ind
- jj = nlmchi(nwfc)%jj
- !
- DO isym = 1, nsym
- !-- check for the time reversal
- IF (t_rev(isym) == 1) THEN
- ind = 2*jj + 2 - ind0
- ELSE
- ind = ind0
- ENDIF
- !--
- nb = irt (isym, na)
- DO nwfc1 =1, natomwfc
- IF (nlmchi(nwfc1)%na == nb .and. &
- nlmchi(nwfc1)%n == nlmchi(nwfc)%n .and. &
- nlmchi(nwfc1)%l == nlmchi(nwfc)%l .and. &
- nlmchi(nwfc1)%jj == nlmchi(nwfc)%jj .and. &
- nlmchi(nwfc1)%ind == 1 ) GOTO 10
- ENDDO
- CALL errore('projwave_nc','cannot symmetrize',1)
- 10 nwfc1=nwfc1-1
- !
- ! nwfc1 is the first rotated atomic wfc corresponding to nwfc
- !
- IF (abs(jj-0.5d0)<1.d-8) THEN
- work1(:) = 0.d0
- DO m1 = 1, 2
- work1(:)=work1(:)+d12(m1,ind,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (abs(jj-1.5d0)<1.d-8) THEN
- work1(:) = 0.d0
- DO m1 = 1, 4
- work1(:)=work1(:)+d32(m1,ind,isym)*proj0(nwfc1 + m1,:)
- ENDDO
- ELSEIF (abs(jj-2.5d0)<1.d-8) THEN
- work1(:) = 0.d0
- DO m1 = 1, 6
- work1(:)=work1(:)+d52(m1,ind,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ELSEIF (abs(jj-3.5d0)<1.d-8) THEN
- work1(:) = 0.d0
- DO m1 = 1, 8
- work1(:)=work1(:)+d72(m1,ind,isym)*proj0(nwfc1+m1,:)
- ENDDO
- ENDIF
- DO ibnd = 1, nbnd
- proj (nwfc, ibnd, ik) = proj (nwfc, ibnd, ik) + &
- work1(ibnd) * conjg (work1(ibnd)) / nsym
- ENDDO
- ! on symmetries
- !-- in a nonmagnetic case - another loop with the time reversal
- IF (.not.domag.and.ind==ind0) THEN
- ind = 2*jj + 2 - ind0
- nwfc1 = nwfc1 + 1
- GOTO 10
- ENDIF
- !--
- ENDDO
- !-- in a nonmagnetic case - rescale
- IF (.not.domag) THEN
- DO ibnd = 1, nbnd
- proj(nwfc,ibnd,ik) = 0.5d0*proj(nwfc,ibnd,ik)
- ENDDO
- ENDIF
- !--
- ELSE
- na= nlmchi(nwfc)%na
- n = nlmchi(nwfc)%n
- l = nlmchi(nwfc)%l
- m = nlmchi(nwfc)%m
- ind0 = nlmchi(nwfc)%ind
- !
- DO isym = 1, nsym
- !-- check for the time reversal
- IF (t_rev(isym) == 1) THEN
- ind = 2*m - ind0 + 2*l + 1
- ELSE
- ind = ind0
- ENDIF
- !--
- nb = irt (isym, na)
- DO nwfc1 =1, natomwfc
- IF (nlmchi(nwfc1)%na == nb .and. &
- nlmchi(nwfc1)%n == nlmchi(nwfc)%n .and. &
- nlmchi(nwfc1)%l == nlmchi(nwfc)%l .and. &
- nlmchi(nwfc1)%m == 1 .and. &
- nlmchi(nwfc1)%ind == 1) GOTO 15
- ENDDO
- CALL errore('projwave_nc','cannot symmetrize',1)
- 15 nwfc1=nwfc1-1
- IF (l == 0) THEN
- work1(:) = 0.d0
- DO m1 = 1, 2
- work1(:) = work1(:) + d012 (m1, ind, isym) * &
- proj0 (nwfc1 + m1,:)
- ENDDO
- ELSEIF (l == 1) THEN
- work1(:) = 0.d0
- DO m1 = 1, 6
- work1(:) = work1(:) + d112 (m1, ind, isym) * &
- proj0 (nwfc1 + m1,:)
- ENDDO
- ELSEIF (l == 2) THEN
- work1(:) = 0.d0
- DO m1 = 1, 10
- work1(:) = work1(:) + d212 (m1, ind, isym) * &
- proj0 (nwfc1 + m1,:)
- ENDDO
- ELSEIF (l == 3) THEN
- work1(:) = 0.d0
- DO m1 = 1, 14
- work1(:) = work1(:) + d312 (m1, ind, isym) * &
- proj0 (nwfc1 + m1,:)
- ENDDO
- ENDIF
- DO ibnd = 1, nbnd
- proj (nwfc, ibnd, ik) = proj (nwfc, ibnd, ik) + &
- work1(ibnd) * conjg (work1(ibnd)) / nsym
- ENDDO
- ! on symmetries
- ENDDO
- ENDIF
- ! on atomic wavefunctions
- ENDDO
- ELSE
- DO nwfc=1,natomwfc
- DO ibnd=1,nbnd
- proj(nwfc,ibnd,ik)=abs(proj0(nwfc,ibnd))**2
- ENDDO
- ENDDO
- ENDIF
- ! on k-points
- ENDDO
- !
- DEALLOCATE (work)
- DEALLOCATE (work1)
- DEALLOCATE (proj0)
- DEALLOCATE (e)
- CALL deallocate_bec_type (becp)
- DEALLOCATE (overlap)
- DEALLOCATE (wfcatom)
- IF (.not. lda_plus_u) DEALLOCATE (swfcatom)
- !
- ! vectors et and proj are distributed across the pools
- ! collect data for all k-points to the first pool
- !
- CALL poolrecover (et, nbnd, nkstot, nks)
- CALL poolrecover (proj, nbnd * natomwfc, nkstot, nks)
- CALL poolrecover (proj_aux, 2 * nbnd * natomwfc, nkstot, nks)
- !
- IF ( ionode ) THEN
- !
- ! write on the file filproj
- !
- IF (filproj/=' ') THEN
- iunproj=33
- CALL write_io_header(filproj, iunproj, title, nr1x, nr2x, nr3x, &
- nr1, nr2, nr3, nat, ntyp, ibrav, celldm, at, gcutm, dual, ecutwfc, &
- nkstot,nbnd,natomwfc)
- DO nwfc = 1, natomwfc
- IF (lspinorb) THEN
- WRITE(iunproj,1000) &
- nwfc, nlmchi(nwfc)%na,atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n,nlmchi(nwfc)%jj,nlmchi(nwfc)%l, &
- compute_mj(nlmchi(nwfc)%jj,nlmchi(nwfc)%l,nlmchi(nwfc)%m)
- ELSE
- WRITE(iunproj,1500) &
- nwfc, nlmchi(nwfc)%na, atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n, nlmchi(nwfc)%l, nlmchi(nwfc)%m, &
- 0.5d0-int(nlmchi(nwfc)%ind/(2*nlmchi(nwfc)%l+2))
- ENDIF
- DO ik=1,nkstot
- DO ibnd=1,nbnd
- WRITE(iunproj,'(2i8,f20.10)') ik,ibnd,abs(proj(nwfc,ibnd,ik))
- ENDDO
- ENDDO
- ENDDO
- CLOSE(iunproj)
- ENDIF
- !
- ! write projections to file using iotk
- !
- CALL write_proj( "atomic_proj.xml", proj_aux )
- !
- ! write on the standard output file
- !
- WRITE( stdout,'(/5x,"Atomic states used for projection")')
- WRITE( stdout,'( 5x,"(read from pseudopotential files):"/)')
- IF (lspinorb) THEN
- DO nwfc = 1, natomwfc
- WRITE(stdout,1000) &
- nwfc, nlmchi(nwfc)%na, atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n, nlmchi(nwfc)%jj, nlmchi(nwfc)%l, &
- compute_mj(nlmchi(nwfc)%jj,nlmchi(nwfc)%l,nlmchi(nwfc)%m)
- ENDDO
- 1000 FORMAT (5x,"state #",i3,": atom ",i3," (",a3,"), wfc ",i2, &
- " (j=",f3.1," l=",i1," m_j=",f4.1,")")
- ELSE
- DO nwfc = 1, natomwfc
- WRITE(stdout,1500) &
- nwfc, nlmchi(nwfc)%na, atm(ityp(nlmchi(nwfc)%na)), &
- nlmchi(nwfc)%n, nlmchi(nwfc)%l, nlmchi(nwfc)%m, &
- 0.5d0-int(nlmchi(nwfc)%ind/(2*nlmchi(nwfc)%l+2))
- ENDDO
- 1500 FORMAT (5x,"state #",i3,": atom ",i3," (",a3,"), wfc ",i2, &
- " (l=",i1," m=",i2," s_z=",f4.1,")")
- ENDIF
- !
- ALLOCATE(idx (natomwfc), proj1 (natomwfc) )
- DO ik = 1, nkstot
- WRITE( stdout, '(/" k = ",3f14.10)') (xk (i, ik) , i = 1, 3)
- DO ibnd = 1, nbnd
- WRITE( stdout, '("==== e(",i4,") = ",f11.5," eV ==== ")') &
- ibnd, et (ibnd, ik) * rytoev
- !
- ! sort projections by magnitude, in decreasing order
- !
- DO nwfc = 1, natomwfc
- idx (nwfc) = 0
- proj1 (nwfc) = - proj (nwfc, ibnd, ik)
- ENDDO
- CALL hpsort_eps (natomwfc, proj1, idx, eps4)
- !
- ! only projections that are larger than 0.001 are written
- !
- DO nwfc = 1, natomwfc
- proj1 (nwfc) = - proj1(nwfc)
- IF ( abs (proj1(nwfc)) < 0.001d0 ) GOTO 20
- ENDDO
- nwfc = natomwfc + 1
- 20 nwfc = nwfc -1
- !
- ! fancy (?!?) formatting
- !
- WRITE( stdout, '(5x,"psi = ",5(f5.3,"*[#",i3,"]+"))') &
- (proj1 (i), idx(i), i = 1, min(5,nwfc))
- DO j = 1, (nwfc-1)/5
- WRITE( stdout, '(10x,"+",5(f5.3,"*[#",i3,"]+"))') &
- (proj1 (i), idx(i), i = 5*j+1, min(5*(j+1),nwfc))
- ENDDO
- psum = 0.d0
- DO nwfc = 1, natomwfc
- psum = psum + proj (nwfc, ibnd, ik)
- ENDDO
- WRITE( stdout, '(4x,"|psi|^2 = ",f5.3)') psum
- !
- ENDDO
- ENDDO
- DEALLOCATE (idx, proj1)
- !
- ! estimate partial charges (Loewdin) on each atom
- !
- IF (lspinorb) THEN
- nspin0 = 1
- ELSE
- nspin0 = 2
- ENDIF
- ALLOCATE ( charges (nat, 0:lmax_wfc, nspin0 ) )
- charges = 0.0d0
- IF (lspinorb) THEN
- DO ik = 1, nkstot
- DO ibnd = 1, nbnd
- DO nwfc = 1, natomwfc
- na= nlmchi(nwfc)%na
- l = nlmchi(nwfc)%l
- charges(na,l,1) = charges(na,l,1) + &
- wg (ibnd,ik) * proj (nwfc, ibnd, ik)
- ENDDO
- ENDDO
- ENDDO
- ELSE
- DO ik = 1, nkstot
- DO ibnd = 1, nbnd
- DO nwfc = 1, natomwfc
- na= nlmchi(nwfc)%na
- l = nlmchi(nwfc)%l
- IF ( nlmchi(nwfc)%ind<=(2*l+1)) THEN
- charges(na,l,1) = charges(na,l,1) + &
- wg (ibnd,ik) * proj (nwfc, ibnd, ik)
- ELSE
- charges(na,l,2) = charges(na,l,2) + &
- wg (ibnd,ik) * proj (nwfc, ibnd, ik)
- ENDIF
- ENDDO
- ENDDO
- ENDDO
- ENDIF
- !
- WRITE( stdout, '(/"Lowdin Charges: "/)')
- !
- DO na = 1, nat
- DO is = 1, nspin0
- totcharge(is) = sum(charges(na,0:lmax_wfc,is))
- ENDDO
- IF ( nspin0 == 1) THEN
- WRITE( stdout, 2000) na, totcharge(1), &
- ( charges(na,l,1), l= 0,lmax_wfc)
- ELSEIF ( nspin0 == 2) THEN
- WRITE( stdout, 2000) na, totcharge(1) + totcharge(2), &
- ( charges(na,l,1) + charges(na,l,2), l=0,lmax_wfc)
- WRITE( stdout, 2001) totcharge(1), &
- ( charges(na,l,1), l= 0,lmax_wfc)
- WRITE( stdout, 2002) totcharge(2), &
- ( charges(na,l,2), l= 0,lmax_wfc)
- WRITE( stdout, 2003) totcharge(1) - totcharge(2), &
- ( charges(na,l,1) - charges(na,l,2), l=0,lmax_wfc)
- ENDIF
- ENDDO
- 2000 FORMAT (5x,"Atom # ",i3,": total charge = ",f8.4 ,&
- & ", s, p, d, f = ",4f8.4)
- 2001 FORMAT (15x," spin up = ",f8.4 , &
- & ", s, p, d, f = ",4f8.4)
- 2002 FORMAT (15x," spin down = ",f8.4 , &
- & ", s, p, d, f = ",4f8.4)
- 2003 FORMAT (15x," polarization = ",f8.4 , &
- & ", s, p, d, f = ",4f8.4)
- !
- psum = sum(charges(:,:,:)) / nelec
- WRITE( stdout, '(5x,"Spilling Parameter: ",f8.4)') 1.0d0 - psum
- !
- ! Sanchez-Portal et al., Sol. State Commun. 95, 685 (1995).
- ! The spilling parameter measures the ability of the basis provided by
- ! the pseudo-atomic wfc to represent the PW eigenstates,
- ! by measuring how much of the subspace of the Hamiltonian
- ! eigenstates falls outside the subspace spanned by the atomic basis
- !
- DEALLOCATE (charges)
- !
- ENDIF
- !
- RETURN
- !
- END SUBROUTINE projwave_nc
- !
- !-----------------------------------------------------------------------
- SUBROUTINE partialdos (Emin, Emax, DeltaE, kresolveddos, filpdos)
- !-----------------------------------------------------------------------
- !
- USE io_global, ONLY : stdout
- USE basis, ONLY : natomwfc
- USE ions_base, ONLY : ityp, atm
- USE klist, ONLY: wk, nkstot, degauss, ngauss, lgauss
- USE lsda_mod, ONLY: nspin, isk, current_spin
- USE wvfct, ONLY: et, nbnd
- USE constants, ONLY: rytoev
- !
- USE projections
- !
- IMPLICIT NONE
- CHARACTER (len=256) :: filpdos
- REAL(DP) :: Emin, Emax, DeltaE
- LOGICAL :: kresolveddos
- !
- CHARACTER (len=33) :: filextension
- CHARACTER (len=256):: fileout
- CHARACTER (len=1) :: l_label(0:3)=(/'s','p','d','f'/)
- !
- INTEGER :: ik, ibnd, m, &
- c_tab, nwfc, ne, ie_mid, ie_delta, ie, is, nkseff, ikeff
- REAL(DP) :: etev, delta, Elw, Eup, wkeff
- REAL(DP), ALLOCATABLE :: dostot(:,:,:), pdos(:,:,:,:), pdostot(:,:,:), &
- ldos(:,:,:)
- REAL(DP), EXTERNAL :: w0gauss
- !
- !
- ! find band extrema
- !
- Elw = et (1, 1)
- Eup = et (nbnd, 1)
- DO ik = 2, nkstot
- Elw = min (Elw, et (1, ik) )
- Eup = max (Eup, et (nbnd, ik) )
- ENDDO
- IF (degauss/=0.d0) THEN
- Eup = Eup + 3d0 * degauss
- Elw = Elw - 3d0 * degauss
- ENDIF
- Emin = max (Emin/rytoev, Elw)
- Emax = min (Emax/rytoev, Eup)
- DeltaE = DeltaE/rytoev
- ne = nint ( (Emax - Emin) / DeltaE+0.500001d0)
- !
- IF (kresolveddos) THEN
- IF ( nspin==2 ) THEN
- nkseff=nkstot/2
- ELSE
- nkseff=nkstot
- ENDIF
- ELSE
- nkseff=1
- ENDIF
- !
- ALLOCATE (pdos(0:ne,natomwfc,nspin,nkseff))
- ALLOCATE (dostot(0:ne,nspin,nkseff), pdostot(0:ne,nspin,nkseff), ldos(0:ne,nspin,nkseff) )
- pdos(:,:,:,:) = 0.d0
- dostot(:,:,:) = 0.d0
- pdostot(:,:,:)= 0.d0
- !
- current_spin = 1
- ie_delta = 5 * degauss / DeltaE + 1
- DO ik = 1,nkstot
- !
- IF (kresolveddos) THEN
- ! set equal weight to all k-points
- wkeff=1.D0
- !
- IF (( nspin==2 ).AND.( isk(ik)==2 )) THEN
- ikeff=ik-nkstot/2
- ELSE
- ikeff=ik
- ENDIF
- ELSE
- ! use true weights
- wkeff=wk(ik)
- ! contributions from all k-points are summed in pdos(:,:,:,ikeff)
- ikeff=1
- ENDIF
- !
- IF ( nspin == 2 ) current_spin = isk ( ik )
- DO ibnd = 1, nbnd
- etev = et(ibnd,ik)
- ie_mid = nint( (etev-Emin)/DeltaE )
- DO ie = max(ie_mid-ie_delta, 0), min(ie_mid+ie_delta, ne)
- delta = w0gauss((Emin+DeltaE*ie-etev)/degauss,ngauss) &
- / degauss / rytoev
- !…