TABLE OF CONTENTS


ABINIT/m_mkcore_wvl [ Modules ]

[ Top ] [ Modules ]

NAME

  m_mkcore_wvl

FUNCTION

COPYRIGHT

  Copyright (C) 2016-2024 ABINIT group (MT,TRangel)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

16 #if defined HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19 
20 #include "abi_common.h"
21 
22 module m_mkcore_wvl
23 
24  use defs_basis
25  use m_abicore
26  use m_errors
27  use m_splines
28  use m_xmpi
29  use defs_wvltypes
30 
31  use m_time,        only : timab
32  use m_sort,        only : sort_dp
33  use m_geometry,    only : xcart2xred, xred2xcart, metric, strconv
34  use m_paw_numeric, only : paw_splint, paw_splint_der
35  use m_pawrad,      only : pawrad_type, pawrad_init, pawrad_free
36  use m_pawtab,      only : pawtab_type
37  use m_drivexc,     only : mkdenpos
38 
39  private

ABINIT/mkcore_inner [ Functions ]

[ Top ] [ Functions ]

NAME

  mkcore_inner

FUNCTION

  FIXME: add description.

INPUTS

  argin(sizein)=description

OUTPUT

  argout(sizeout)=description

SIDE EFFECTS

NOTES

SOURCE

 900 subroutine mkcore_inner(corfra,core_mesh,dyfrx2,grxc1,grxc2,grxc3,ifftsph,msz,natom,ncmax,nfft,&
 901 &          nfgd,nfgd_r0,nspden,n3xccc,option,pawtab,rmet,rr,strdia,vxc,xccc3d,&
 902 &          rred) ! optional argument
 903 
 904 !Arguments ------------------------------------
 905 !scalars
 906  integer ,intent(in) :: msz,natom,ncmax,nfft,nfgd,nfgd_r0,nspden,n3xccc,option
 907  real(dp),intent(out) :: grxc1,grxc2,grxc3,strdia
 908 !arrays
 909  integer,intent(in) :: ifftsph(ncmax)
 910  real(dp),intent(in) :: rmet(3,3),rr(ncmax),vxc(nfft,nspden)
 911  real(dp),intent(in),optional :: rred(:,:)
 912  real(dp),intent(inout) :: corfra(3,3),dyfrx2(3,3,natom),xccc3d(n3xccc)
 913  type(pawrad_type),intent(in) :: core_mesh
 914  type(pawtab_type),intent(in) :: pawtab
 915 
 916 !Local variables-------------------------------
 917 !scalars
 918  integer :: iatom,ifgd,ii,jj,mu,nu
 919  character(len=500) :: message
 920  real(dp) :: term,term2
 921 !arrays
 922  integer :: iindex(nfgd)
 923  real(dp) :: tcore(nfgd),dtcore(nfgd),rr_tmp(nfgd)
 924  real(dp),allocatable :: d2tcore(:)
 925 
 926 ! *************************************************************************
 927 
 928 !Checks
 929  if(nspden >1) then
 930    write(message, '(a)')'mkcore_inner: this is not yet generalized to npsden>1'
 931    ABI_ERROR(message)
 932  end if
 933  if (present(rred)) then
 934    if (option>1.and.size(rred)/=3*ncmax) then
 935      write(message, '(a)')'mkcore_inner: incorrect size for rred'
 936      ABI_BUG(message)
 937    end if
 938  else if (option>1) then
 939    write(message, '(a)')'mkcore_inner: rred is not present and option >1'
 940    ABI_BUG(message)
 941  end if
 942 
 943 !Retrieve values of pseudo core density (and derivative)
 944  rr_tmp=rr(1:nfgd)
 945  iindex(1:nfgd)=(/(ii,ii=1,nfgd)/)
 946  call sort_dp(nfgd,rr_tmp,iindex(1:nfgd),tol16)
 947  if (option==1.or.option==3) then
 948    call paw_splint(msz,core_mesh%rad,pawtab%tcoredens(:,1),pawtab%tcoredens(:,3),&
 949 &   nfgd,rr_tmp,tcore)
 950  end if
 951  if (option>=2) then
 952    call paw_splint_der(msz,core_mesh%rad,pawtab%tcoredens(:,1),pawtab%tcoredens(:,3),&
 953 &   nfgd,rr_tmp,dtcore)
 954  end if
 955 
 956 !Accumulate contributions to core density on the entire cell
 957  if (option==1) then
 958    do ifgd=1,nfgd
 959      ii=iindex(ifgd);jj=ifftsph(ii)
 960      xccc3d(jj)=xccc3d(jj)+tcore(ifgd)
 961    end do
 962 
 963 !Accumulate contributions to Exc gradients
 964  else if (option==2) then
 965    do ifgd=1,nfgd
 966      ii=iindex(ifgd);jj=ifftsph(ii)
 967      term=vxc(jj,1)*dtcore(ifgd)/rr_tmp(ifgd)
 968      grxc1=grxc1-rred(1,ii)*term
 969      grxc2=grxc2-rred(2,ii)*term
 970      grxc3=grxc3-rred(3,ii)*term
 971    end do
 972 
 973 !Accumulate contributions to stress tensor
 974  else if (option==3) then
 975 !  Write out the 6 symmetric components
 976    do ifgd=1,nfgd
 977      ii=iindex(ifgd);jj=ifftsph(ii)
 978      term=vxc(jj,1)*dtcore(ifgd)/rr_tmp(ifgd)
 979      corfra(1,1)=corfra(1,1)+term*rred(1,ifgd)**2
 980      corfra(2,2)=corfra(2,2)+term*rred(2,ifgd)**2
 981      corfra(3,3)=corfra(3,3)+term*rred(3,ifgd)**2
 982      corfra(3,2)=corfra(3,2)+term*rred(3,ifgd)*rred(2,ifgd)
 983      corfra(3,1)=corfra(3,1)+term*rred(3,ifgd)*rred(1,ifgd)
 984      corfra(2,1)=corfra(2,1)+term*rred(2,ifgd)*rred(1,ifgd)
 985    end do
 986 !  Also compute diagonal term
 987    do ifgd=1,nfgd
 988      ii=iindex(ifgd);jj=ifftsph(ii)
 989      strdia=strdia+vxc(jj,1)*tcore(ii)
 990    end do
 991 
 992 !Compute frozen-wf contribution to Dynamical matrix
 993  else if (option==4) then
 994    ABI_MALLOC(d2tcore,(nfgd))
 995    if(nfgd>0) then
 996 !    Evaluate spline fit of 2nd der of pseudo core density
 997      call paw_splint(msz,core_mesh%rad,pawtab%tcoredens(:,3),pawtab%tcoredens(:,5),&
 998 &     nfgd,rr_tmp,d2tcore)
 999      do ifgd=1,nfgd
1000        ii=iindex(ifgd);jj=ifftsph(ii)
1001        term=vxc(jj,1)*dtcore(ifgd)/rr_tmp(ifgd)
1002        term2=term*d2tcore(ifgd)/rr_tmp(ifgd)
1003        do mu=1,3
1004          do nu=1,3
1005            dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)&
1006 &           +(term2-term/rr_tmp(iindex(ifgd))**2)&
1007 &           *rred(mu,iatom)*rred(nu,iatom)+term*rmet(mu,nu)
1008          end do
1009        end do
1010      end do
1011    end if
1012 !  Contributions from |r-R|=0
1013    if (nfgd_r0>0) then
1014      rr_tmp(1)=tol10
1015      call paw_splint(msz,core_mesh%rad,pawtab%tcoredens(:,3),pawtab%tcoredens(:,5),&
1016 &     1,rr_tmp,d2tcore(1))
1017      ifgd=1
1018      ii=iindex(ifgd);jj=ifftsph(ii)
1019      term=vxc(jj,1)*d2tcore(ifgd)
1020      do mu=1,3
1021        do nu=1,3
1022          dyfrx2(mu,nu,iatom)=dyfrx2(mu,nu,iatom)+term*rmet(mu,nu)
1023        end do
1024      end do
1025    end if
1026    ABI_FREE(d2tcore)
1027 
1028  end if !option
1029 
1030 end subroutine mkcore_inner

ABINIT/mkcore_wvl [ Functions ]

[ Top ] [ Functions ]

NAME

  mkcore_wvl

FUNCTION

 Optionally compute (in a WVL representation):
  (1) pseudo core electron density throughout unit cell
  (2) pseudo-core contribution to forces
  (3) pseudo-core contribution to stress tensor

INPUTS

  atindx1(natom)=index table for atoms, inverse of atindx
  [mpi_comm_wvl]=MPI communicator (optional)
  mpi_enreg=information about MPI parallelization
  natom=number of atoms in cell
  nattyp(ntypat)=number of atoms of each type
  nfft=dimension of vxc (XC potential)
  nspden=number of spin-density components
  ntypat=number of types of atoms
  n1xccc=dimension of xccc1d ; 0 if no XC core correction is used
  n3xccc=dimension of xccc3d (pseudo core charge)
  option: 1 for computing core charge density
          2 for computing core charge contribution to forces
          3 for computing core charge contribution to stress tensor
          4 for computing contribution to frozen-wf part of dynamical matrix
  pawrad(ntypat*usepaw) <type(pawrad_type)>=paw radial mesh and related data
  pawtab(ntypat*usepaw) <type(pawtab_type)>=paw tabulated starting data
  rprimd(3,3)=dimensional primitive translation vectors (bohr)
  vxc(nfft,nspden)=exchange-correlation potential (hartree)
  xcccrc(ntypat)=XC core correction cutoff radius (bohr) for each atom type
  xccc1d(n1xccc,6,ntypat)=1D core charge function and 5 derivatives for each atom type
  xred(3,natom)=reduced coordinates for atoms in unit cell
  wvl_den=density-potential BigDFT object
  wvl_descr=wavelet BigDFT object

OUTPUT

  === if option==1 ===
  xccc3d(n3xccc)=3D core electron density for XC core correction (bohr^-3)
  === if option==2 ===
  grxc(3,natom)=core charge contribution to forces
  === if option==3 ===
  corstr(6)=core charge contribution to stress tensor

SIDE EFFECTS

  xccc3d(n3xccc)=3D core electron density for XC core correction (bohr^-3)
   (computed and returned when option=1, needed as input when option=3)

NOTES

 Based on mkcore.F90. Adapted to WVL case.

SOURCE

102 subroutine mkcore_wvl(atindx1,corstr,grxc,natom,nattyp,nfft,nspden,ntypat,n1xccc,n3xccc,option,&
103 &                     pawrad,pawtab,rprimd,vxc,xccc1d,xccc3d,xcccrc,xred,wvl_den,wvl_descr,&
104 &                     mpi_comm_wvl) ! optional argument
105 
106 #if defined HAVE_BIGDFT
107  use BigDFT_API, only : PSPCODE_PAW,ind_positions
108 #endif
109 
110 !Arguments ------------------------------------
111 !scalars
112  integer,intent(in) :: natom,nfft,nspden,ntypat,n1xccc,n3xccc,option
113  integer,intent(in),optional :: mpi_comm_wvl
114  type(wvl_denspot_type), intent(inout) :: wvl_den
115  type(wvl_internal_type), intent(in) :: wvl_descr
116 !arrays
117  integer,intent(in) :: atindx1(natom),nattyp(ntypat)
118  real(dp),intent(in) :: rprimd(3,3),xccc1d(n1xccc,6,ntypat),xcccrc(ntypat),xred(3,natom)
119  real(dp),intent(in),target :: vxc(nfft,nspden)
120  real(dp),intent(out) :: corstr(6),grxc(3,natom)
121  real(dp),intent(inout) :: xccc3d(n3xccc)
122  type(pawrad_type),intent(in) :: pawrad(:)
123  type(pawtab_type),intent(in) :: pawtab(:)
124 
125 !Local variables-------------------------------
126 #if defined HAVE_BIGDFT
127 !scalars
128  integer :: iat,iatm,iatom,iex,iey,iez,ind,ioffset,ipts,isx,isy,isz,itypat
129  integer :: iwarn=0,i1,i2,i3,i3s,j1,j2,j3,jj,jpts,me_wvl,nproc_wvl
130  integer :: nbl1,nbr1,nbl2,nbr2,nbl3,nbr3,npts,npts12
131  integer :: ntot,n1,n1i,n2,n2i,n3,n3i,n3pi
132  logical :: perx,pery,perz,gox,goy,goz,USE_PAW
133  real(dp) :: aa,arg,bb,cc,cutoff,dd,delta=0,deltam1=0,delta2div6=0,diff
134  real(dp) :: hxh,hyh,hzh,range,range2,rangem1,rr,rx,ry,rz,r2,strdia
135  real(dp) :: term,ucvol,xx,yy,zz
136  character(len=500) :: msg
137  type(pawrad_type) :: core_mesh
138 !arrays
139  integer,allocatable :: indx(:),ivec(:)
140  real(dp) :: corfra(3,3),corgr(3),gmet(3,3),gprimd(3,3),rmet(3,3),tsec(2),tt(3),xcart(3)
141  real(dp),allocatable :: dtcore(:),d2tcore(:),rnorm(:),tcore(:),vecx(:),vecy(:)
142  real(dp),pointer :: vxc_eff(:)
143 #endif
144 
145 !************************************************************************
146 
147 #if defined HAVE_BIGDFT
148 
149  call timab(12,1,tsec)
150 
151 !Make sure option is acceptable
152  if (option<0.or.option>3) then
153    write(msg,'(a,i2,a)') 'Option= ',option,' is not allowed!'
154    ABI_BUG(MSG)
155  end if
156  if(nfft/=n3xccc)then
157    write(msg,'(a)') 'nfft and n3xccc should be equal!'
158    ABI_BUG(msg)
159  end if
160 
161 !MPI
162  nproc_wvl=1;if (present(mpi_comm_wvl)) nproc_wvl=xmpi_comm_size(mpi_comm_wvl)
163  me_wvl=0;if (present(mpi_comm_wvl)) me_wvl=xmpi_comm_rank(mpi_comm_wvl)
164 
165 !Zero out only the appropriate array according to option
166  if (option==1) then
167    xccc3d(:)=zero
168  else if (option==2) then
169    grxc(:,:)=zero
170  else if (option==3) then
171    corfra(:,:)=zero
172    corstr(:)=zero
173    strdia=zero
174  end if
175 
176 !Nothing to do if no xy plane to handle
177  n3pi=wvl_den%denspot%dpbox%n3pi
178  if (n3pi==0) return
179 
180 !Show how calculation runs
181  if (me_wvl==0) then
182    if (option==1) write(std_out,'(a)',advance='no') ' Compute pseudo core density...'
183    if (option==2) write(std_out,'(a)',advance='no') ' Compute forces due to core density...'
184    if (option==3) write(std_out,'(a)',advance='no') ' Compute stresses due to core density...'
185    if (option==4) write(std_out,'(a)',advance='no') ' Compute dyn. matrix due to core density...'
186  end if
187 
188 !PAW or NCPP ?
189  USE_PAW=any(wvl_descr%atoms%npspcode==PSPCODE_PAW)
190 
191 !Conditions for periodicity in the three directions
192  perx=(wvl_descr%atoms%astruct%geocode /= 'F')
193  pery=(wvl_descr%atoms%astruct%geocode == 'P')
194  perz=(wvl_descr%atoms%astruct%geocode /= 'F')
195  call ext_buffers(perx,nbl1,nbr1)
196  call ext_buffers(pery,nbl2,nbr2)
197  call ext_buffers(perz,nbl3,nbr3)
198 
199  if (option>=2) then
200 !  For spin-polarization, replace vxc by (1/2)*(vxc(up)+vxc(down))
201 !  For non-collinear magnetism, replace vxc by (1/2)*(vxc^{11}+vxc^{22})
202    if (nspden>=2) then
203      ABI_MALLOC(vxc_eff,(nfft))
204      do jj=1,nfft
205        vxc_eff(jj)=half*(vxc(jj,1)+vxc(jj,2))
206      end do
207    else
208      vxc_eff => vxc(1:nfft,1)
209    end if
210  end if
211 
212 !Some constants
213  n1=wvl_descr%Glr%d%n1
214  n2=wvl_descr%Glr%d%n2
215  n3=wvl_descr%Glr%d%n3
216  n1i=wvl_den%denspot%dpbox%ndims(1)
217  n2i=wvl_den%denspot%dpbox%ndims(2)
218  n3i=wvl_den%denspot%dpbox%ndims(3)
219  ntot=n1i*n2i*n3i
220  ioffset=n1i*n2i*wvl_den%denspot%dpbox%i3xcsh
221  i3s=1+wvl_den%denspot%dpbox%nscatterarr(me_wvl,3)-wvl_den%denspot%dpbox%i3xcsh
222  hxh=wvl_den%denspot%dpbox%hgrids(1)
223  hyh=wvl_den%denspot%dpbox%hgrids(2)
224  hzh=wvl_den%denspot%dpbox%hgrids(3)
225  call metric(gmet,gprimd,-1,rmet,rprimd,arg)
226  ucvol=real(ntot,dp)*(hxh*hyh*hzh)
227  if (.not.USE_PAW) then
228    delta=one/(n1xccc-1)
229    deltam1=n1xccc-1
230    delta2div6=delta**2/6.0_dp
231  end if
232 
233 !Loop over atom types
234  iatm=0
235  do itypat=1,ntypat
236 
237 !  Set search range (density cuts off perfectly beyond range)
238    range=xcccrc(itypat);if (USE_PAW) range=pawtab(itypat)%rcore
239    range2=range**2 ; rangem1=one/range
240 
241 !  Skip loop if this type has no core charge
242    if (abs(range)<1.d-16) cycle
243 
244 !  PAW: create mesh for core density
245    if (USE_PAW) then
246      call pawrad_init(core_mesh,mesh_size=pawtab(itypat)%core_mesh_size,&
247 &     mesh_type=pawrad(itypat)%mesh_type,&
248 &     rstep=pawrad(itypat)%rstep,lstep=pawrad(itypat)%lstep)
249    end if
250 
251 !  Loop over atoms of the type
252    do iat=1,nattyp(itypat)
253      iatm=iatm+1;iatom=atindx1(iatm)
254 
255      if (option==2) corgr(:)=zero
256 
257 !    Coordinates of the center
258      call xred2xcart(1,rprimd,xcart,xred(:,iatom))
259      rx=xcart(1) ; ry=xcart(2) ; rz=xcart(3)
260 
261 !    Range of points to explore
262      cutoff=1.1_dp*range
263      isx=floor((rx-cutoff)/hxh)
264      isy=floor((ry-cutoff)/hyh)
265      isz=floor((rz-cutoff)/hzh)
266      iex=ceiling((rx+cutoff)/hxh)
267      iey=ceiling((ry+cutoff)/hyh)
268      iez=ceiling((rz+cutoff)/hzh)
269 
270 !    Allocate temporary memory
271      !npts12=1+int(((range/hh(1))*(range/hh(2))*pi))
272      npts12=(iex-isx+1)*(iey-isy+1)
273      ABI_MALLOC(rnorm,(npts12))
274      ABI_MALLOC(vecx,(npts12))
275      ABI_MALLOC(vecy,(npts12))
276      ABI_MALLOC(ivec,(npts12))
277      ABI_MALLOC(indx,(npts12))
278      if (option==1.or.option==3) then
279        ABI_MALLOC(tcore,(npts12))
280      end if
281      if (option>=2) then
282        ABI_MALLOC(dtcore,(npts12))
283      end if
284      if (option==4) then
285        ABI_MALLOC(d2tcore,(npts12))
286      end if
287 
288 !    Explore range of vectors
289      do i3=isz,iez
290        zz=real(i3,kind=dp)*hzh-rz
291        call ind_positions(perz,i3,n3,j3,goz)
292        j3=j3+nbl3+1
293 
294 !      Select the vectors located around the current atom
295 !        TR: all of the following  could be done inside or
296 !        outside the loops (i2,i1,i3).
297 !        Outside: the memory consumption increases.
298 !        Inside: the time of calculation increases.
299 !        Here, I choose to do it here, somewhere in the middle.
300        npts=0
301        do i2=isy,iey
302          yy=real(i2,kind=dp)*hyh-ry
303          call ind_positions(pery,i2,n2,j2,goy)
304          do i1=isx,iex
305            xx=real(i1,kind=dp)*hxh-rx
306            call ind_positions(perx,i1,n1,j1,gox)
307            r2=xx**2+yy**2+zz**2
308            if ((j3>=i3s.and.j3<=i3s+n3pi-1) .and. (gox.and.goy)) then
309              ind=j1+1+nbl1+(j2+nbl2)*n1i+(j3-i3s+1-1)*n1i*n2i
310 !            Only accept contributions inside defined range
311              if (r2<range2) then
312                npts=npts+1 ; indx(npts)=npts
313                ivec(npts)=ioffset+ind
314                rnorm(npts)=sqrt(r2)
315                vecx(npts)=xx;vecy(npts)=yy
316              end if
317            end if
318          end do
319        end do
320        if (npts==0) cycle
321        if (npts>npts12) then
322          msg='npts>npts12!'
323          ABI_BUG(msg)
324        end if
325 
326 !      Evaluate core density (and derivatives) on the set of selected points
327        if (USE_PAW) then
328 !        PAW: use splint routine
329          call sort_dp(npts,rnorm(1:npts),indx(1:npts),tol16)
330          if (option==1.or.option==3) then
331 !          Evaluate fit of core density
332            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
333 &           pawtab(itypat)%tcoredens(:,1), &
334 &           pawtab(itypat)%tcoredens(:,3),&
335 &           npts,rnorm(1:npts),tcore(1:npts))
336          end if
337          if (option>=2) then
338 !          Evaluate fit of 1-der of core density
339            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
340 &           pawtab(itypat)%tcoredens(:,2), &
341 &           pawtab(itypat)%tcoredens(:,4),&
342 &           npts,rnorm(1:npts),dtcore(1:npts))
343          end if
344          if (option==4) then
345 !          Evaluate fit of 2nd-der of core density
346            call paw_splint(core_mesh%mesh_size,core_mesh%rad, &
347 &           pawtab(itypat)%tcoredens(:,3), &
348 &           pawtab(itypat)%tcoredens(:,5),&
349 &           npts,rnorm(1:npts),d2tcore(1:npts))
350          end if
351        else
352 !        Norm-conserving PP:
353 !          Evaluate spline fit with method from Numerical Recipes
354          do ipts=1,npts
355            rr=rnorm(ipts)*rangem1
356            jj=1+int(rr*(n1xccc-1))
357            diff=rr-(jj-1)*delta
358            bb = diff*deltam1 ; aa = one-bb
359            cc = aa*(aa**2-one)*delta2div6
360            dd = bb*(bb**2-one)*delta2div6
361            if (option==1.or.option==3) then
362              tcore(ipts)=aa*xccc1d(jj,1,itypat)+bb*xccc1d(jj+1,1,itypat) +&
363 &             cc*xccc1d(jj,3,itypat)+dd*xccc1d(jj+1,3,itypat)
364            end if
365            if (option>=2) then
366              dtcore(ipts)=aa*xccc1d(jj,2,itypat)+bb*xccc1d(jj+1,2,itypat) +&
367 &             cc*xccc1d(jj,4,itypat)+dd*xccc1d(jj+1,4,itypat)
368            end if
369            if (option==4) then
370              d2tcore(ipts)=aa*xccc1d(jj,3,itypat)+bb*xccc1d(jj+1,3,itypat) +&
371 &             cc*xccc1d(jj,5,itypat)+dd*xccc1d(jj+1,5,itypat)
372            end if
373          end do
374        end if
375 
376 !      Now, perform the loop over selected grid points
377        do ipts=1,npts
378          rr=rnorm(ipts)
379          xx=vecx(indx(ipts))
380          yy=vecy(indx(ipts))
381          jpts=ivec(indx(ipts))
382 
383 !        === Evaluate charge density
384          if (option==1) then
385            xccc3d(jpts)=xccc3d(jpts)+tcore(ipts)
386 
387 !        === Accumulate contributions to forces
388          else if (option==2) then
389            if (rr>tol10) then
390              term=vxc_eff(jpts)*dtcore(ipts)/rr
391              corgr(1)=corgr(1)+xx*term
392              corgr(2)=corgr(2)+yy*term
393              corgr(3)=corgr(3)+yy*term
394            end if
395 
396 !        === Accumulate contributions to stress tensor (in red. coordinates)
397          else if (option==3) then
398            if (rr>tol10) then
399              term=vxc_eff(jpts)*dtcore(ipts)*rangem1/rr/real(ntot,dp)
400 !            Write out the 6 symmetric components
401              corfra(1,1)=corfra(1,1)+term*xx*xx
402              corfra(2,2)=corfra(2,2)+term*yy*yy
403              corfra(3,3)=corfra(3,3)+term*zz*zz
404              corfra(3,2)=corfra(3,2)+term*zz*yy
405              corfra(3,1)=corfra(3,1)+term*zz*xx
406              corfra(2,1)=corfra(2,1)+term*yy*xx
407 !            (the above still needs to be transformed to cartesian coords)
408            end if
409 !          Also compute a diagonal term
410            strdia=strdia+vxc_eff(jpts)*tcore(ipts)
411 
412          end if ! Choice of option
413 
414        end do ! ipts (i1,i2)
415 
416      end do ! i3
417 
418 !    Release temporary memory
419      ABI_FREE(rnorm)
420      ABI_FREE(vecx)
421      ABI_FREE(vecy)
422      ABI_FREE(ivec)
423      ABI_FREE(indx)
424      if (allocated(tcore)) then
425        ABI_FREE(tcore)
426      end if
427      if (allocated(dtcore)) then
428        ABI_FREE(dtcore)
429      end if
430      if (allocated(d2tcore)) then
431        ABI_FREE(d2tcore)
432      end if
433 
434      if (option==2) then
435        arg=-(ucvol/real(ntot,dp))
436        !arg=-(ucvol/real(ntot,dp))/range  !????
437        grxc(:,iatom)=corgr(:)*arg
438      end if
439 
440 !  End loop on atoms
441    end do
442 
443    if (USE_PAW) then
444      call pawrad_free(core_mesh)
445    end if
446 
447 !End loop over atom types
448  end do
449 
450  if(option>=2.and.nspden>=2)  then
451    ABI_FREE(vxc_eff)
452  end if
453 
454 !Density: make it positive
455  if (option==1) then
456    call mkdenpos(iwarn,n3xccc,nspden,0,xccc3d,tol20)
457  end if
458 
459 !Forces: translate into reduced coordinates
460  if (option==2) then
461    do iatom=1,natom
462      tt(1:3)=grxc(1:3,iatom)
463      grxc(:,iatom)= rprimd(1,:)*tt(1)+rprimd(2,:)*tt(2)+rprimd(3,:)*tt(3)
464     !grxc(:,iatom)=rmet(:,1)*tt(1)+rmet(:,2)*tt(2)+rmet(:,3)*tt(3)
465    end do
466  end if
467 
468 !Stress tensor: symmetrize, translate into cartesian coord., add diagonal part
469  if (option==3) then
470    corstr(1)=corfra(1,1) ; corstr(2)=corfra(2,2)
471    corstr(3)=corfra(3,3) ; corstr(4)=corfra(3,2)
472    corstr(5)=corfra(3,1) ; corstr(6)=corfra(2,1)
473    call strconv(corstr,rprimd,corstr)
474    corstr(1)=corstr(1)+strdia/real(ntot,dp)
475    corstr(2)=corstr(2)+strdia/real(ntot,dp)
476    corstr(3)=corstr(3)+strdia/real(ntot,dp)
477  end if
478 
479 !If needed, sum over MPI processes
480  if(nproc_wvl>1) then
481    call timab(539,1,tsec)
482    if (option==2) then
483      call xmpi_sum(grxc,mpi_comm_wvl,iex)
484    end if
485    if (option==3) then
486      call xmpi_sum(corstr,mpi_comm_wvl,iex)
487    end if
488    call timab(539,2,tsec)
489  end if
490 
491  if (me_wvl==0) write(std_out,'(a)') 'done.'
492 
493  call timab(12,1,tsec)
494 
495 #else
496  BIGDFT_NOTENABLED_ERROR()
497  ABI_UNUSED(xcccrc)
498  if (.false.) write(std_out,*) natom,nfft,nspden,ntypat,n1xccc,n3xccc,option,mpi_comm_wvl,&
499 & wvl_den%symObj,wvl_descr%h(1),atindx1(1),nattyp(1),rprimd(1,1),vxc(1,1),&
500 & xred(1,1),xccc1d(1,1,1),corstr(1),grxc(1,1),xccc3d(1),pawrad(1)%mesh_size,pawtab(1)%lmn_size
501 #endif
502 
503 end subroutine mkcore_wvl

ABINIT/mkcore_wvl_old [ Functions ]

[ Top ] [ Functions ]

NAME

  mkcore_wvl_old

FUNCTION

 Optionally compute
  (1) core electron density throughout unit cell, or
  (2) contribution to Exc gradient wrt xred, or
  (3) contribution to stress tensor, or (response function code)
  (4) contribution to frozen-wavefunction part of
      the dynamical matrix (part 2)

INPUTS

  argin(sizein)=description

OUTPUT

  argout(sizeout)=description

SIDE EFFECTS

NOTES

 Based on mkcore.F90

SOURCE

534 subroutine mkcore_wvl_old(atindx1,corstr,dyfrx2,geocode,grxc,h,natom,&
535 & nattyp,nfft,nscatterarr,nspden,ntypat,n1,n1i,n2,n2i,n3,n3pi,&
536 & n3xccc,option,pawrad,pawtab,psppar,rprimd,ucvol,&
537 & vxc,xccc3d,xred,mpi_comm_wvl)
538 
539 #if defined HAVE_BIGDFT
540   use BigDFT_API, only: ext_buffers,ind_positions
541 #endif
542 
543 !Arguments ---------------------------------------------
544 !scalars
545  integer,intent(in) :: natom,ntypat,nfft,nspden
546  integer,intent(in) ::n1,n2,n3,n1i,n2i,n3pi,n3xccc,option
547  integer,intent(in),optional:: mpi_comm_wvl
548  real(dp),intent(in) :: h(3),ucvol
549  character(1),intent(in)::geocode
550 !arrays
551  integer,intent(in) :: atindx1(natom),nattyp(ntypat)
552  integer,intent(in) :: nscatterarr(4)
553  real(dp),intent(in) :: psppar(0:4,0:6,ntypat),rprimd(3,3)
554  real(dp),intent(in)::xred(3,natom)
555  real(dp),intent(in)::vxc(nfft,nspden)
556  real(dp),intent(out)::xccc3d(n3xccc)
557  real(dp),intent(out) :: corstr(6),dyfrx2(3,3,natom),grxc(3,natom)
558  type(pawtab_type),intent(in) :: pawtab(ntypat)
559  type(pawrad_type),intent(in) :: pawrad(ntypat)
560 
561 !Local variables ------------------------------
562 #if defined HAVE_BIGDFT
563 !scalars
564 !buffer to be added at the end of the last dimension of an array to control bounds_check
565  integer :: i1,i2,i3,iat,iatm,iatom,iatom_tot
566  integer :: itypat,iwarn
567  integer :: nproc_wvl=1
568  integer :: ier,iex,iey,iez,isx,isy,isz,ind,i3s
569  integer :: j1,j2,j3,msz
570  integer :: nbl1,nbr1,nbl2,nbr2,nbl3,nbr3
571  integer :: ncmax,nfgd,nfgd_r0,opt_mkdenpos,shift
572  real(dp) :: cutoff,factor,grxc1,grxc2,grxc3
573  real(dp) :: rloc,rr2,rx,ry,rz
574  real(dp) :: rshp,r2shp,rshpm1,strdia,t1,t2,t3
575  real(dp) :: xx,yy,zz,ucvol_
576  character(len=500) :: message
577  logical :: perx,pery,perz,gox,goy,goz
578  type(pawrad_type)::core_mesh
579 !arrays
580  real(dp) :: hh(3) !fine grid spacing for wavelets
581  real(dp) :: gmet(3,3),gprimd(3,3),rcart(3),rmet(3,3),tsec(2),xcart(3,natom)
582  real(dp) :: corfra(3,3)
583 !allocatable arrays
584  integer,allocatable :: ifftsph_tmp(:)
585  real(dp),allocatable:: rr(:),rred(:,:)
586 #endif
587 
588 ! *************************************************************************
589 
590  DBG_ENTER("COLL")
591 
592 #if defined HAVE_BIGDFT
593 
594  if(nspden >1) then
595    write(message, '(a)')'mkcore_wvl_old: this is not yet generalized to npsden>1'
596    ABI_ERROR(message)
597  end if
598  if(option>4 .or. option<1 )then
599    write(message,'(a,a,a,a,a,a,i6)') ch10,&
600 &   ' mkcore_wvl_old: BUG -',ch10,&
601 &   '  The argument option should be between 1 and 4,',ch10,&
602 &   '  however, option=',option
603    ABI_BUG(message)
604  end if
605  if(nfft .ne. n3xccc)then
606    write(message,'(a,a,a,a,a,a,2i6)') ch10,&
607 &   ' mkcore_wvl_old: BUG -',ch10,&
608 &   '  nfft and n3xccc should be equal,',ch10,&
609 &   '  however, nfft and n3xccc=',nfft,n3xccc
610    ABI_BUG(message)
611  end if
612 
613 !MPI
614  if(present(mpi_comm_wvl)) nproc_wvl=xmpi_comm_size(mpi_comm_wvl)
615  i3s  =nscatterarr(3)+1-nscatterarr(4)
616  shift=n1i*n2i*nscatterarr(4)
617 
618  if (option==1) then
619 !  Zero out array to permit accumulation over atom types below:
620    xccc3d(:)=zero
621  else if (option==2) then
622 !  Zero out gradient of Exc array
623    grxc(:,:)=zero
624  else if (option==3) then
625 !  Zero out locally defined stress array
626    corfra(:,:)=zero
627    strdia=zero
628  else if (option==4) then
629 !  Zero out fr-wf part of the dynamical matrix
630    dyfrx2(:,:,:)=zero
631  else
632    write(message, '(a,a,a,a)' ) ch10,&
633 &   ' mkcore_wvl_old: BUG -',ch10,&
634 &   '  Can''t be here ! (bad option).'
635    ABI_BUG(message)
636  end if
637 
638  write(message,'(a,a)') ch10,&
639 & ' mkcore_wvl_old: Compute core density'
640  call wrtout(std_out,message,'COLL')
641 
642 !Fine grid
643  hh(:)=0.5d0*h(:)
644 
645 !Compute xcart from xred
646  call xred2xcart(natom,rprimd,xcart,xred)
647 
648 !Compute metric tensors and ucvol from rprimd
649  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol_)
650 !correct ucvol for wavelets case is given as an input:
651 !ucvol_local = product(wvl%den%denspot%dpbox%hgrids) * real(product(wvl%den%denspot%dpbox%ndims), dp)
652 !ucvol_local = (half * dtset%wvl_hgrid) ** 3 * ngfft(1)*ngfft(2)*ngfft(3)
653 
654 !Conditions for periodicity in the three directions
655  perx=(geocode /= 'F')
656  pery=(geocode == 'P')
657  perz=(geocode /= 'F')
658 
659 !Compute values of external buffers
660  call ext_buffers(perx,nbl1,nbr1)
661  call ext_buffers(pery,nbl2,nbr2)
662  call ext_buffers(perz,nbl3,nbr3)
663 
664 
665  iatm=0
666 !Big loop on atom types
667  do itypat=1,ntypat
668 
669    rloc=psppar(0,0,itypat)
670    cutoff=10.d0*rloc
671 
672 !  Set radius size:
673    rshp=pawtab(itypat)%rcore
674    r2shp=1.0000001_dp*rshp**2
675    rshpm1=one/rshp
676 
677 !  allocate arrays
678    if (n3pi > 0) then
679 !    ncmax=1+int(1.1_dp*nfft*four_pi/(three*ucvol)*rshp**3)
680 !    ncmax=1+int(1.1_dp*nfft*four_pi/(three*ucvol)*rshp**3)
681 !    1+int(1.1* factors are included just for cautioness
682      ncmax=1+int(1.1d0*((rshp/hh(1))*(rshp/hh(2))*pi))
683    else
684      ncmax=1
685    end if
686 
687    ABI_MALLOC(ifftsph_tmp,(ncmax))
688    ABI_MALLOC(rr,(ncmax))
689    if(option>1) then
690      ABI_MALLOC(rred,(3,ncmax))
691    else
692      ABI_MALLOC(rred,(0,0))
693    end if
694 
695 !  Create mesh_core object
696 !  since core_mesh_size can be bigger than pawrad%mesh_size,
697    msz=pawtab(itypat)%core_mesh_size
698    call pawrad_init(core_mesh,mesh_size=msz,mesh_type=pawrad(itypat)%mesh_type,&
699 &   rstep=pawrad(itypat)%rstep,lstep=pawrad(itypat)%lstep)
700 
701 !  Big loop on atoms
702    do iat=1,nattyp(itypat)
703      iatm=iatm+1;iatom=atindx1(iatm)
704      iatom_tot=iatom
705 
706      if(option==2) then
707        grxc1=zero
708        grxc2=zero
709        grxc3=zero
710      end if
711 
712 !    Define a "box" around each atom
713      rx=xcart(1,iatom_tot)
714      ry=xcart(2,iatom_tot)
715      rz=xcart(3,iatom_tot)
716 
717      isx=floor((rx-cutoff)/hh(1))
718      isy=floor((ry-cutoff)/hh(2))
719      isz=floor((rz-cutoff)/hh(3))
720 
721      iex=ceiling((rx+cutoff)/hh(1))
722      iey=ceiling((ry+cutoff)/hh(2))
723      iez=ceiling((rz+cutoff)/hh(3))
724 
725      do i3=isz,iez
726        zz=real(i3,kind=8)*hh(3)-rz
727        call ind_positions(perz,i3,n3,j3,goz)
728        j3=j3+nbl3+1
729 
730 !      Initialize counters
731        nfgd=0
732        nfgd_r0=0
733 
734        do i2=isy,iey
735          yy=real(i2,kind=8)*hh(2)-ry
736          call ind_positions(pery,i2,n2,j2,goy)
737 
738          do i1=isx,iex
739            xx=real(i1,kind=8)*hh(1)-rx
740            call ind_positions(perx,i1,n1,j1,gox)
741            rr2=xx**2+yy**2+zz**2
742            if (j3 >= i3s .and. j3 <= i3s+n3pi-1  .and. goy  .and. gox ) then
743 
744              if(rr2<=r2shp) then
745                if(rr2>tol5) then
746                  ind=j1+1+nbl1+(j2+nbl2)*n1i+(j3-i3s)*n1i*n2i
747                  nfgd=nfgd+1
748                  rcart(1)=xx; rcart(2)=yy; rcart(3)=zz
749                  rr(nfgd)=(rr2)**0.5
750                  ifftsph_tmp(nfgd)=shift+ind
751                  if(option>1) then
752                    call xcart2xred(1,rprimd,rcart,rred(:,nfgd))
753                  end if
754                else if (option==4) then
755 !                We save r=0 vectors only for option==4:
756 !                for other options this is ignored
757                  ind=j1+1+nbl1+(j2+nbl2)*n1i+(j3-i3s)*n1i*n2i
758 !                We reuse the same variable "ifftshp_tmp",
759 !                but we start from the higher index
760                  nfgd_r0=nfgd_r0+1
761                  ifftsph_tmp(ncmax-nfgd_r0+1)=shift+ind
762 
763                end if !rr2>tol5
764              end if !rr2<r2shp
765            end if !j3..
766          end do !i1
767        end do !i2
768 
769 !      All of the following  could be done inside or outside the loops (i2,i1,i3)
770 !      Outside the loops: the memory consuption increases.
771 !      Inside the inner loop: the time of calculation increases.
772 !      Here, I chose to do it here, somewhere in the middle.
773 
774        if(option .ne.4 ) then
775          if(nfgd==0)      cycle
776        else
777          if(nfgd==0 .and. nfgd_r0==0) cycle
778        end if
779        call mkcore_inner(corfra,core_mesh,dyfrx2,&
780 &       grxc1,grxc2,grxc3,ifftsph_tmp,msz,&
781 &       natom,ncmax,nfft,nfgd,nfgd_r0,nspden,n3xccc,option,pawtab(itypat),&
782 &       rmet,rr,strdia,vxc,xccc3d,rred=rred)
783 
784      end do !i3
785 
786      if(option==2) then
787        factor=(ucvol/real(nfft,dp))/rshp
788        grxc(1,iatom)=grxc1*factor
789        grxc(2,iatom)=grxc2*factor
790        grxc(3,iatom)=grxc3*factor
791 
792        if( nproc_wvl>1 ) then
793          call timab(539,1,tsec)
794          call xmpi_sum(grxc1,mpi_comm_wvl,ier)
795          call xmpi_sum(grxc2,mpi_comm_wvl,ier)
796          call xmpi_sum(grxc3,mpi_comm_wvl,ier)
797          call timab(539,2,tsec)
798        end if
799      end if
800 
801    end do !iat
802 
803 !  Deallocate
804    call pawrad_free(core_mesh)
805    ABI_FREE(ifftsph_tmp)
806    ABI_FREE(rr)
807    ABI_FREE(rred)
808 
809  end do !itypat
810 
811  if (option==2) then
812 !  Apply rmet as needed to get reduced coordinate gradients
813    do iatom=1,natom
814      t1=grxc(1,iatom)
815      t2=grxc(2,iatom)
816      t3=grxc(3,iatom)
817      grxc(:,iatom)=rmet(:,1)*t1+rmet(:,2)*t2+rmet(:,3)*t3
818    end do
819 
820  elseif (option==3) then
821 
822 !  Transform stress tensor from full storage mode to symmetric storage mode
823    corstr(1)=corfra(1,1)
824    corstr(2)=corfra(2,2)
825    corstr(3)=corfra(3,3)
826    corstr(4)=corfra(3,2)
827    corstr(5)=corfra(3,1)
828    corstr(6)=corfra(2,1)
829 
830 !  Transform stress tensor from reduced coordinates to cartesian coordinates
831    call strconv(corstr,rprimd,corstr)
832 
833 !  Compute diagonal contribution to stress tensor (need input xccc3d)
834 !  strdia = (1/N) Sum(r) [mu_xc_avg(r) * rho_core(r)]
835    strdia=zero
836    do i3=1,n3pi
837      do i2=1,n2i
838        do i1=1,n1i
839          ind=i1+(i2-1)*n1i+(i3-1)*n1i*n2i
840          strdia=strdia+vxc(ind,1)*xccc3d(ind)
841 !        write(17,'(3(i6),i12,3(1x,1pe24.17))')i1,i2,i3,ind,potion_corr(ind),pot_ion(ind),maxdiff
842        end do
843      end do
844    end do
845    strdia=strdia/real(nfft,dp)
846 
847 !  Add diagonal term to stress tensor
848    corstr(1)=corstr(1)+strdia
849    corstr(2)=corstr(2)+strdia
850    corstr(3)=corstr(3)+strdia
851  end if
852 
853  if(nproc_wvl > 1) then
854    call timab(539,1,tsec)
855    if(option==3) then
856      call xmpi_sum(corstr,mpi_comm_wvl,ier)
857    end if
858    if(option==2) then
859      call xmpi_sum(grxc,mpi_comm_wvl,ier)
860    end if
861    call timab(539,2,tsec)
862  end if
863 
864 !Make xccc3d positive to avoid numerical instabilities in V_xc
865  iwarn=0 ; opt_mkdenpos=0
866  call mkdenpos(iwarn, n3xccc, nspden, opt_mkdenpos, xccc3d, tol20 )
867 
868 #else
869  BIGDFT_NOTENABLED_ERROR()
870  if (.false.) write(std_out,*) natom,ntypat,nfft,nspden,n1,n2,n3,n1i,n2i,n3pi,n3xccc,option,&
871 & mpi_comm_wvl,h(1),ucvol,geocode,atindx1(1),nattyp(1),nscatterarr(1),psppar(1,1,1),rprimd(1,1),&
872 & xred(1,1),vxc(1,1),xccc3d(1),corstr(1),dyfrx2(1,1,1),grxc(1,1),pawtab(1)%mesh_size,pawrad(1)%mesh_size
873 #endif
874 
875  DBG_EXIT("COLL")
876 
877 end subroutine mkcore_wvl_old