TABLE OF CONTENTS


ABINIT/pawdfptenergy [ Functions ]

[ Top ] [ Functions ]

NAME

 pawdfptenergy

FUNCTION

 This routine compute the Hartree+XC PAW on-site contributions to a 1st-order or 2nd-order energy.
  These contributions are equal to:
    E_onsite=
       Int{ VHxc[n1_a^(1);nc^(1)].n1_b }
      -Int{ VHxc[tild_n1_a^(j1)+hat_n1_a^(j1);tild_n_c^(j1)].(tild_n1_b+n1_b)^(j2) }
 Some typical uses:
  A-Contribution to non-stationary expression of the 2nd-order total energy:
    In that case, n1_a^(1)[r]=n1^(j1)[r] and n1_b[r]=delta_n1^(j2)[r]
    where j1 and j2 are two given perturbations,
    and delta_n1^(j)[r] is the 1s-order density only due to change of WF overlap.
    See PRB 78, 035105 (2008), Eq.(80)
    E_onsite=
       Int{ VHxc[n1^(j1);nc^(j1)].delta_n1^(j2) }
      -Int{ VHxc[tild_n1^(j1)+hat_n1^(j1);tild_n_c^(j1)].delta_(tild_n1+hat_n1)^(j2) }
  B-Contribution to first-order Fermi energy:
    In that case, n1_a^(1)[r]=n1^(j1)[r] and n1_b[r]=n1[r,EFermi]
    where j1 is the current perturbation, and n1[r,EFermi] is the density at Fermi level.
    E_onsite=
       Int{ VHxc[n1^(j1);nc^(j1)].n1[r,EFermi] }
      -Int{ VHxc[tild_n1^(j1)+hat_n1^(j1);tild_n_c^(j1)].(tild_n1+hat_n1)[r,EFermi] }

COPYRIGHT

 Copyright (C) 1998-2018 ABINIT group (MT)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .
 For the initials of contributors, see ~abinit/doc/developers/contributors.txt.

INPUTS

  ipert1,ipert2=indexes of perturbations (j1) and (j2)
                if ipert2<=0, we compute a first-order energy
                if ipert2> 0, we compute a second-order energy
  ixc= choice of exchange-correlation scheme
  mpi_atmtab(:)=--optional-- indexes of the atoms treated by current proc
  comm_atom=--optional-- MPI communicator over atoms
  my_natom=number of atoms treated by current processor
  natom=total number of atoms in cell
  ntypat=number of types of atoms in unit cell.
  nzlmopt_a= For the n1_a density:
            if -1, compute all LM-moments of the density and use non-zero LM-moments
            if  0, compute all LM-moments of the density and use all LM-moments
            if +1, compute only non-zero LM-moments of the density (stored before)
  nzlmopt_b= For the n1_b density:
            if -1, compute all LM-moments of the density and use non-zero LM-moments
            if  0, compute all LM-moments of the density and use all LM-moments
            if +1, compute only non-zero LM-moments of the density (stored before)
  paw_an0(natom) <type(paw_an_type)>=paw arrays for 0th-order quantities given on angular mesh
  paw_an1(natom) <type(paw_an_type)>=paw arrays for 1st-order quantities given on angular mesh
                                     This corresponds to (j1) perturbation
  paw_ij1(natom) <type(paw_ij_type)>=paw arrays given on (i,j) channels
                                     This corresponds to (j1) perturbation
  pawang <type(pawang_type)>=paw angular mesh and related data
  pawprtvol=control print volume and debugging output for PAW
  pawrad(ntypat) <type(pawrad_type)>=paw radial mesh and related data
  pawrhoij_a(natom) <type(pawrhoij_type)>= paw rhoij 1st-order occupancies for the (j1) perturbation
  pawrhoij_b(natom) <type(pawrhoij_type)>=
    if ipert2> 0: paw rhoij 1st-order occupancies for the (j2) perturbation corrsponding to n1_b^(j2)[r]
    if ipert2<=0: paw rhoij occupancies corresponding to n1_b[r]
  pawtab(ntypat) <type(pawtab_type)>=paw tabulated starting data
  pawxcdev=Choice of XC development (0=no dev. (use of angular mesh) ; 1 or 2=dev. on moments)
  xclevel= XC functional level

OUTPUT

  delta_energy(2)= real and imaginary parts of contributions to non-stationary expression for the
              second derivative of the total energy

SIDE EFFECTS

    ==== if paw_an1(:)%has_vxc<2, compute 1st-order XC potentials
      paw_an1(natom)%vxc1(cplex_a*mesh_size,:,nspden) =AE 1st-order XC potential Vxc^(j1)
      paw_an1(natom)%vxct1(cplex_a*mesh_size,:,nspden)=PS 1st-order XC potential tVxc^(j1)
    ==== if paw_ij1(:)%has_dijhartree<2, compute 1st-order Dij_hartree
      paw_ij1(natom)%dijhartree(cplex_a*lmn2_size)=Hartree contribution to Dij^(j1)

PARENTS

      dfpt_nstpaw,newfermie1

CHILDREN

      free_my_atmtab,get_my_atmtab,pawdensities,pawdijhartree,pawxc_dfpt
      pawxcm_dfpt,timab,xmpi_sum

SOURCE

 89 #if defined HAVE_CONFIG_H
 90 #include "config.h"
 91 #endif
 92 
 93 #include "abi_common.h"
 94 
 95 subroutine pawdfptenergy(delta_energy,ipert1,ipert2,ixc,my_natom,natom,ntypat,nzlmopt_a,nzlmopt_b,&
 96 &                    paw_an0,paw_an1,paw_ij1,pawang,pawprtvol,pawrad,pawrhoij_a,pawrhoij_b,&
 97 &                    pawtab,pawxcdev,xclevel, &
 98 &                    mpi_atmtab,comm_atom) ! optional arguments (parallelism)
 99 
100 
101  use defs_basis
102  use m_profiling_abi
103  use m_errors
104  use m_xmpi, only : xmpi_comm_self,xmpi_sum
105 
106  use m_pawang,     only : pawang_type
107  use m_pawrad,     only : pawrad_type
108  use m_pawtab,     only : pawtab_type
109  use m_paw_an,     only : paw_an_type
110  use m_paw_ij,     only : paw_ij_type
111  use m_pawrhoij,   only : pawrhoij_type
112  use m_pawdij,     only : pawdijhartree
113  use m_pawxc,      only : pawxc_dfpt, pawxcm_dfpt
114  use m_paral_atom, only : get_my_atmtab, free_my_atmtab
115 
116 !This section has been created automatically by the script Abilint (TD).
117 !Do not modify the following lines by hand.
118 #undef ABI_FUNC
119 #define ABI_FUNC 'pawdfptenergy'
120  use interfaces_18_timing
121  use interfaces_65_paw, except_this_one => pawdfptenergy
122 !End of the abilint section
123 
124  implicit none
125 
126 !Arguments ---------------------------------------------
127 !scalars
128  integer,intent(in) :: ipert1,ipert2,ixc,my_natom,natom,ntypat,nzlmopt_a,nzlmopt_b
129  integer,intent(in) :: pawprtvol,pawxcdev,xclevel
130  integer,optional,intent(in) :: comm_atom
131  type(pawang_type),intent(in) :: pawang
132 !arrays
133  integer,optional,target,intent(in) :: mpi_atmtab(:)
134  real(dp),intent(out) :: delta_energy(2)
135  type(paw_an_type),intent(in) :: paw_an0(my_natom)
136  type(paw_an_type),intent(inout) :: paw_an1(my_natom)
137  type(paw_ij_type),intent(inout) :: paw_ij1(my_natom)
138  type(pawrad_type),intent(in) :: pawrad(ntypat)
139  type(pawrhoij_type),intent(in) :: pawrhoij_a(my_natom),pawrhoij_b(my_natom)
140  type(pawtab_type),intent(in) :: pawtab(ntypat)
141 
142 !Local variables ---------------------------------------
143 !scalars
144  integer :: cplex_a,cplex_b,cplex_dijh1,iatom,iatom_tot,ierr,irhoij,ispden,itypat,jrhoij
145  integer :: klmn,lm_size_a,lm_size_b,mesh_size,my_comm_atom,nspden,nspdiag,opt_compch,optexc,optvxc
146  integer :: usecore,usetcore,usexcnhat
147  logical :: my_atmtab_allocated,paral_atom
148  real(dp) :: compch,eexc,eexc_im
149  character(len=500) :: msg
150 !arrays
151  integer,pointer :: my_atmtab(:)
152  logical,allocatable :: lmselect_a(:),lmselect_b(:),lmselect_tmp(:)
153  real(dp) :: dij(2),delta_energy_h(2),delta_energy_xc(2),ro(2),tsec(2)
154  real(dp),allocatable :: kxc_dum(:,:,:),nhat1(:,:,:),rho1(:,:,:),trho1(:,:,:)
155 
156 ! *************************************************************************
157 
158  DBG_ENTER("COLL")
159 
160  call timab(567,1,tsec)
161 
162  if (.not.(ipert1==natom+1.or.ipert1==natom+10.or.ipert1==natom+11 &
163 & .or.ipert2==natom+1.or.ipert2==natom+10.or.ipert2==natom+11)) then
164    if((abs(nzlmopt_a)/=1.and.nzlmopt_a/=0).or.(abs(nzlmopt_b)/=1.and.nzlmopt_b/=0)) then
165      msg='invalid value for nzlmopt !'
166      MSG_BUG(msg)
167    end if
168    if (my_natom>0) then
169      if(paw_ij1(1)%has_dijhartree==0) then
170        msg='dijhartree must be allocated !'
171        MSG_BUG(msg)
172      end if
173      if(paw_an1(1)%has_vxc==0) then
174        msg='vxc1 and vxct1 must be allocated !'
175        MSG_BUG(msg)
176      end if
177      if(paw_an0(1)%has_kxc==0) then
178        msg='kxc1 must be allocated !'
179        MSG_BUG(msg)
180      end if
181      if ((ipert1<=natom.or.ipert1==natom+1.or.ipert1==natom+10.or.ipert1==natom+11).and.paw_an0(1)%has_kxc/=2) then
182        msg='XC kernels for ground state must be in memory !'
183        MSG_BUG(msg)
184      end if
185      if (paw_ij1(1)%cplex/=paw_an1(1)%cplex) then
186        msg='paw_ij1()%cplex and paw_an1()%cplex must be equal !'
187        MSG_BUG(msg)
188      end if
189      if (pawrhoij_a(1)%cplex<paw_an1(1)%cplex.or.pawrhoij_b(1)%cplex<paw_an1(1)%cplex) then
190        msg='pawrhoij()%cplex must be >=paw_an1()%cplex  !'
191        MSG_BUG(msg)
192      end if
193      if (pawrhoij_a(1)%nspden/=pawrhoij_b(1)%nspden) then
194        msg='pawrhoij_a()%nspden must =pawrhoij_b()%nspden  !'
195        MSG_BUG(msg)
196      end if
197    end if
198  end if
199 
200 !Set up parallelism over atoms
201  paral_atom=(present(comm_atom).and.(my_natom/=natom))
202  nullify(my_atmtab);if (present(mpi_atmtab)) my_atmtab => mpi_atmtab
203  my_comm_atom=xmpi_comm_self;if (present(comm_atom)) my_comm_atom=comm_atom
204  call get_my_atmtab(my_comm_atom,my_atmtab,my_atmtab_allocated,paral_atom,natom,my_natom_ref=my_natom)
205 
206 !Init contribution to 1st-order (or 2nd-order) energy
207  delta_energy(1:2)=zero
208 
209 !For some perturbations, nothing else to do
210  if (ipert1==natom+1.or.ipert1==natom+10.or.ipert1==natom+11 .or. &
211 & ipert2==natom+1.or.ipert2==natom+10.or.ipert2==natom+11) return
212 
213 !Various inits
214  opt_compch=0;optvxc=1;optexc=3
215  usecore=0;usetcore=0  ! This is true for phonons and Efield pert.
216  usexcnhat=maxval(pawtab(1:ntypat)%usexcnhat)
217  delta_energy_xc(1:2)=zero;delta_energy_h(1:2)=zero
218  dij(1:2)=zero;ro(1:2)=zero
219 
220 
221 !================ Loop on atomic sites =======================
222  do iatom=1,my_natom
223    iatom_tot=iatom;if (paral_atom) iatom_tot=my_atmtab(iatom)
224 
225    itypat=pawrhoij_a(iatom)%itypat
226    mesh_size=pawtab(itypat)%mesh_size
227    nspden=pawrhoij_a(iatom)%nspden
228    cplex_a=pawrhoij_a(iatom)%cplex
229    cplex_b=pawrhoij_b(iatom)%cplex
230    cplex_dijh1=paw_ij1(iatom)%cplex
231    lm_size_a=paw_an1(iatom)%lm_size
232    if (ipert2<=0) lm_size_b=paw_an0(iatom)%lm_size
233    if (ipert2> 0) lm_size_b=paw_an1(iatom)%lm_size
234 
235 !  If Vxc potentials are not in memory, compute them
236    if (paw_an1(iatom)%has_vxc/=2) then
237      ABI_ALLOCATE(rho1 ,(cplex_a*mesh_size,lm_size_a,nspden))
238      ABI_ALLOCATE(trho1,(cplex_a*mesh_size,lm_size_a,nspden))
239      ABI_ALLOCATE(nhat1,(cplex_a*mesh_size,lm_size_a,nspden*usexcnhat))
240      ABI_ALLOCATE(lmselect_a,(lm_size_a))
241      lmselect_a(:)=paw_an1(iatom)%lmselect(:)
242      ABI_ALLOCATE(lmselect_tmp,(lm_size_a))
243      lmselect_tmp(:)=.true.
244      if (nzlmopt_a==1) lmselect_tmp(:)=lmselect_a(:)
245 !    Compute on-site 1st-order densities
246      call pawdensities(compch,cplex_a,iatom_tot,lmselect_tmp,lmselect_a,&
247 &     lm_size_a,nhat1,nspden,nzlmopt_a,opt_compch,1-usexcnhat,-1,0,pawang,pawprtvol,&
248 &     pawrad(itypat),pawrhoij_a(iatom),pawtab(itypat),rho1,trho1)
249      ABI_DEALLOCATE(lmselect_tmp)
250 !    Compute on-site 1st-order xc potentials
251      if (pawxcdev/=0) then
252        call pawxcm_dfpt(pawtab(itypat)%coredens,cplex_a,cplex_a,eexc,ixc,paw_an0(iatom)%kxc1,&
253 &       lm_size_a,lmselect_a,nhat1,paw_an0(iatom)%nkxc1,mesh_size,nspden,optvxc,&
254 &       pawang,pawrad(itypat),rho1,usecore,0,&
255 &       paw_an1(iatom)%vxc1,xclevel)
256        call pawxcm_dfpt(pawtab(itypat)%tcoredens(:,1),&
257 &       cplex_a,cplex_a,eexc,ixc,paw_an0(iatom)%kxct1,&
258 &       lm_size_a,lmselect_a,nhat1,paw_an0(iatom)%nkxc1,mesh_size,nspden,optvxc,&
259 &       pawang,pawrad(itypat),trho1,usetcore,2*usexcnhat,&
260 &       paw_an1(iatom)%vxct1,xclevel)
261      else
262        call pawxc_dfpt(pawtab(itypat)%coredens,cplex_a,cplex_a,eexc,ixc,paw_an0(iatom)%kxc1,&
263 &       lm_size_a,lmselect_a,nhat1,paw_an0(iatom)%nkxc1,mesh_size,nspden,optvxc,&
264 &       pawang,pawrad(itypat),rho1,usecore,0,&
265 &       paw_an0(iatom)%vxc1,paw_an1(iatom)%vxc1,xclevel)
266        call pawxc_dfpt(pawtab(itypat)%tcoredens(:,1),&
267 &       cplex_a,cplex_a,eexc,ixc,paw_an0(iatom)%kxct1,&
268 &       lm_size_a,lmselect_a,nhat1,paw_an0(iatom)%nkxc1,mesh_size,nspden,optvxc,&
269 &       pawang,pawrad(itypat),trho1,usetcore,2*usexcnhat,&
270 &       paw_an0(iatom)%vxct1,paw_an1(iatom)%vxct1,xclevel)
271      end if
272 
273      paw_an1(iatom)%has_vxc=2
274      ABI_DEALLOCATE(lmselect_a)
275      ABI_DEALLOCATE(rho1)
276      ABI_DEALLOCATE(trho1)
277      ABI_DEALLOCATE(nhat1)
278    end if ! has_vxc
279 
280 !  If Dij_hartree are not in memory, compute them
281    if (paw_ij1(iatom)%has_dijhartree/=2) then
282      call pawdijhartree(cplex_dijh1,paw_ij1(iatom)%dijhartree,paw_ij1(iatom)%nspden,&
283 &     pawrhoij_a(iatom),pawtab(itypat))
284      paw_ij1(iatom)%has_dijhartree=2
285    end if
286 
287 !  Compute contribution to 1st-order (or 2nd-order) energy from 1st-order XC potential
288    ABI_ALLOCATE(rho1 ,(cplex_b*mesh_size,lm_size_b,nspden))
289    ABI_ALLOCATE(trho1,(cplex_b*mesh_size,lm_size_b,nspden))
290    ABI_ALLOCATE(nhat1,(cplex_b*mesh_size,lm_size_b,nspden*usexcnhat))
291    ABI_ALLOCATE(lmselect_b,(lm_size_b))
292    if (ipert2<=0) lmselect_b(:)=paw_an0(iatom)%lmselect(:)
293    if (ipert2> 0) lmselect_b(:)=paw_an1(iatom)%lmselect(:)
294    ABI_ALLOCATE(lmselect_tmp,(lm_size_b))
295    lmselect_tmp(:)=.true.
296    if (nzlmopt_b==1) lmselect_tmp(:)=lmselect_b(:)
297 !  Compute on-site 1st-order densities
298    call pawdensities(compch,cplex_b,iatom_tot,lmselect_tmp,lmselect_b,&
299 &   lm_size_b,nhat1,nspden,nzlmopt_b,opt_compch,1-usexcnhat,-1,0,pawang,pawprtvol,&
300 &   pawrad(itypat),pawrhoij_b(iatom),pawtab(itypat),rho1,trho1)
301    ABI_DEALLOCATE(lmselect_tmp)
302 !  Compute contributions to 1st-order (or 2nd-order) energy
303    if (pawxcdev/=0) then
304      ABI_ALLOCATE(kxc_dum,(mesh_size,pawang%angl_size,0))
305      call pawxcm_dfpt(pawtab(itypat)%coredens,cplex_b,cplex_a,eexc,ixc,kxc_dum,&
306 &     lm_size_b,lmselect_b,nhat1,0,mesh_size,nspden,optexc,pawang,pawrad(itypat),&
307 &     rho1,usecore,0,paw_an1(iatom)%vxc1,xclevel,d2enxc_im=eexc_im)
308 
309      delta_energy_xc(1)=delta_energy_xc(1)+eexc
310      delta_energy_xc(2)=delta_energy_xc(2)+eexc_im
311      call pawxcm_dfpt(pawtab(itypat)%tcoredens(:,1),&
312 &     cplex_b,cplex_a,eexc,ixc,kxc_dum,&
313 &     lm_size_b,lmselect_b,nhat1,0,mesh_size,nspden,optexc,pawang,pawrad(itypat),&
314 &     trho1,usetcore,2*usexcnhat,paw_an1(iatom)%vxct1,xclevel,&
315 &     d2enxc_im=eexc_im)
316      ABI_DEALLOCATE(kxc_dum)
317      delta_energy_xc(1)=delta_energy_xc(1)-eexc
318      delta_energy_xc(2)=delta_energy_xc(2)-eexc_im
319    else
320      ABI_ALLOCATE(kxc_dum,(mesh_size,lm_size_b,0))
321      call pawxc_dfpt(pawtab(itypat)%coredens,cplex_b,cplex_a,eexc,ixc,kxc_dum,&
322 &     lm_size_b,lmselect_b,nhat1,0,mesh_size,nspden,optexc,pawang,pawrad(itypat),&
323 &     rho1,usecore,0,paw_an0(iatom)%vxc1,paw_an1(iatom)%vxc1,xclevel,d2enxc_im=eexc_im)
324      delta_energy_xc(1)=delta_energy_xc(1)+eexc
325      delta_energy_xc(2)=delta_energy_xc(2)+eexc_im
326      call pawxc_dfpt(pawtab(itypat)%tcoredens(:,1),&
327 &     cplex_b,cplex_a,eexc,ixc,kxc_dum,&
328 &     lm_size_b,lmselect_b,nhat1,0,mesh_size,nspden,optexc,pawang,pawrad(itypat),&
329 &     trho1,usetcore,2*usexcnhat,paw_an0(iatom)%vxct1,paw_an1(iatom)%vxct1,xclevel,&
330 &     d2enxc_im=eexc_im)
331      ABI_DEALLOCATE(kxc_dum)
332      delta_energy_xc(1)=delta_energy_xc(1)-eexc
333      delta_energy_xc(2)=delta_energy_xc(2)-eexc_im
334    end if
335    ABI_DEALLOCATE(lmselect_b)
336    ABI_DEALLOCATE(rho1)
337    ABI_DEALLOCATE(trho1)
338    ABI_DEALLOCATE(nhat1)
339 
340 !  Compute contribution to 1st-order(or 2nd-order) energy from 1st-order Hartree potential
341    nspdiag=1;if (nspden==2) nspdiag=2
342    do ispden=1,nspdiag
343      if (cplex_dijh1==1) then
344        jrhoij=1
345        do irhoij=1,pawrhoij_b(iatom)%nrhoijsel
346          klmn=pawrhoij_b(iatom)%rhoijselect(irhoij)
347          dij(1)=paw_ij1(iatom)%dijhartree(klmn)
348          ro(1)=pawrhoij_b(iatom)%rhoijp(jrhoij,ispden)*pawtab(itypat)%dltij(klmn)
349          delta_energy_h(1)=delta_energy_h(1)+ro(1)*dij(1)
350          if (cplex_b==2) then
351            ro(2)=pawrhoij_b(iatom)%rhoijp(jrhoij+1,ispden)*pawtab(itypat)%dltij(klmn)
352            delta_energy_h(2)=delta_energy_h(2)+ro(2)*dij(1)
353          end if
354          jrhoij=jrhoij+cplex_b
355        end do
356      else ! cplex_dijh1==2
357        jrhoij=1
358        do irhoij=1,pawrhoij_b(iatom)%nrhoijsel
359          klmn=pawrhoij_b(iatom)%rhoijselect(irhoij)
360          dij(1:2)=paw_ij1(iatom)%dijhartree(2*klmn-1:2*klmn)
361          ro(1)=pawrhoij_b(iatom)%rhoijp(jrhoij,ispden)*pawtab(itypat)%dltij(klmn)
362          delta_energy_h(1)=delta_energy_h(1)+ro(1)*dij(1)
363          delta_energy_h(2)=delta_energy_h(2)-ro(1)*dij(2)
364          if (cplex_b==2) then
365            ro(2)=pawrhoij_b(iatom)%rhoijp(jrhoij+1,ispden)*pawtab(itypat)%dltij(klmn)
366            delta_energy_h(1)=delta_energy_h(1)+ro(2)*dij(2)
367            delta_energy_h(2)=delta_energy_h(2)+ro(2)*dij(1)
368          end if
369          jrhoij=jrhoij+cplex_b
370        end do
371      end if
372    end do
373 
374 !  ================ End loop oon atomic sites =======================
375  end do
376 
377 !Final building of 1st-order (or 2nd-order) energy
378  delta_energy(1:2)=delta_energy_xc(1:2)+delta_energy_h(1:2)
379 
380 !Reduction in case of parallelism
381  if (paral_atom) then
382    call xmpi_sum(delta_energy,my_comm_atom,ierr)
383  end if
384 
385 !Destroy atom table used for parallelism
386  call free_my_atmtab(my_atmtab,my_atmtab_allocated)
387 
388  call timab(567,2,tsec)
389 
390  DBG_EXIT("COLL")
391 
392 end subroutine pawdfptenergy