TABLE OF CONTENTS


ABINIT/ddb_hybrid [ Functions ]

[ Top ] [ Functions ]

NAME

 ddb_hybrid

FUNCTION

 Modify selected elements in atmfrc, dielt, zeff
 as specified in an input file named: "modifs.ddb"
 If this file does not exist, return immediately

COPYRIGHT

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

INPUTS

 acell = lengths of lattice vectors
 asr = flag to impose the acoustic sum rule
 atmfrc(2,3,natom,3,natom,nrpt)= Analytical part of the
     Interatonmic Force Constants in real space.
 dielt(3,3)=dielectric tensor
 dipdip = flag to include dipole-dipole contribution
 dyew = full Ewald matrix
 dyewq0(3,3,natom)=contraction of the Ewald matrix at q=0
  modifications to the IFCs.
 gmet = reciprocal space metric
 gprim = reciprocal lattice vectors
 iout = unit number for main output file. If -1 we are in a child mpi process which should not write
 natom=number of atom in unit cell
 nrpt = number of points in real space for the FT on the dynamical matrices
 rcan = canonical positions of atoms
 rmet = real-space metric
 rprim = unit cell vectors
 rpt = positions of points in real space for the FT on the dynamical matrices
 ucvol = unit cell volume
 wghatm = wieghts for pairs of atoms, in FT interpolations of dyn mat
 xred = reduced positions of atoms
 zeff(3,3,natom)=effective charge on each atom, versus electric field and atomic displacement.

OUTPUT

 atmfrc(2,3,natom,3,natom,nrpt)= modified
 dielt(3,3)=modified
 zeff(3,3,natom)=modified

PARENTS

CHILDREN

      asrif9,canct9,ewald9,matr3inv,q0dy3_calc

SOURCE

 55 #if defined HAVE_CONFIG_H
 56 #include "config.h"
 57 #endif
 58 
 59 #include "abi_common.h"
 60 
 61 
 62 subroutine ddb_hybrid(acell,asr,atmfrc,dielt,dipdip,dyew,dyewq0,&
 63 & gmet,gprim,iout,natom,nrpt,rcan,rmet,&
 64 & rprim,rpt,ucvol,wghatm,xred,zeff)
 65 
 66  use defs_basis
 67  use m_profiling_abi
 68  use m_errors
 69 
 70  use m_io_tools, only : open_file
 71  use m_dynmat,   only : q0dy3_calc, asrif9, canct9
 72  use m_ewald,    only : ewald9
 73 
 74 !This section has been created automatically by the script Abilint (TD).
 75 !Do not modify the following lines by hand.
 76 #undef ABI_FUNC
 77 #define ABI_FUNC 'ddb_hybrid'
 78  use interfaces_32_util
 79 !End of the abilint section
 80 
 81  implicit none
 82 
 83 !Arguments ------------------------------------
 84 !scalars
 85  integer,intent(in) :: asr,dipdip,iout,natom,nrpt
 86  real(dp),intent(in) :: ucvol
 87 !arrays
 88  real(dp),intent(in) :: acell(3),gmet(3,3),gprim(3,3),rcan(3,natom),rmet(3,3)
 89  real(dp),intent(in) :: rprim(3,3),rpt(3,nrpt),wghatm(natom,natom,nrpt)
 90  real(dp),intent(in) :: xred(3,natom)
 91  real(dp),intent(inout) :: atmfrc(2,3,natom,3,natom,nrpt),dielt(3,3)
 92  real(dp),intent(inout) :: dyew(2,3,natom,3,natom),dyewq0(3,3,natom)
 93  real(dp),intent(inout) :: zeff(3,3,natom)
 94 
 95 !Local variables-------------------------------
 96 !Allocate should be used, instead of these fixed values for msrd and mddd
 97 !scalars
 98  integer,parameter :: hyun=12,mddd=2,msrd=5000
 99  integer :: chk,d1,d2,flgr,genat1,genat2,ia,ib,id1,index,irpt,isrd,jj,kk,mu
100  integer :: nbr,nddd,nsrd,nu,option,sumg0
101  real(dp) :: dd,dd2,detdlt,detdlt2,normr2,rsq,rsq2
102  logical :: ex
103  character(len=500) :: msg
104 !arrays
105  integer :: at1(msrd),at2(msrd),sta(natom,natom,nrpt)
106  real(dp) :: del(3),delta(3),delta2(3),dielt2(3,3),difr(3),dyew2q0(3,3,natom)
107  real(dp) :: ewab(3,3),ewab2(3,3),ewiaf(3,3),ewiaf2(3,3),ifcsr(3,3,msrd)
108  real(dp) :: invdlt(3,3),invdlt2(3,3),qpt(3),ra(3),rb(3)
109  real(dp) :: rpt2(3,msrd),xreda(3),zeff2(3,3,natom)
110 
111 ! ******************************************************************
112 
113 #if defined HAVE_OS_MACOSX
114  return ! macOSX seem to have problem with the inquire statement below
115 #endif
116 
117 !Do the modifications only if the 'modifs.ddb' file exist.
118  inquire(file='modifs.ddb',exist=ex)
119  if(.not.ex)return
120 
121 !PART 1: read input file for modifications
122 !+++++++++++++++++++++++++++++++++++++++++
123 
124  if (iout > 0) then
125    write(iout,*)
126    write(iout,*)
127    write(iout,*)' **WARNING** some interatomic force constants'
128    write(iout,*)'             will be artificially modified'
129  end if
130 
131  if (open_file('modifs.ddb',msg,unit=hyun,status='old',form='formatted') /= 0) then
132    MSG_ERROR(msg)
133  end if
134 
135  read(hyun,*) nsrd
136  if (nsrd<0)then
137    write(std_out,'(a,i8,a)' )&
138 &   'ddb_hybrid : nsrd is',nsrd,', which is lower than 0 => stop'
139    MSG_ERROR("Aborting now")
140  end if
141  if (nsrd>msrd)then
142    write(std_out,'(a,i8,a,a,i8,a)' )&
143 &   ' ddb_hybrid : nsrd is',nsrd,', which is larger than',ch10,&
144 &   msrd,' , the maximum number allowed => stop'
145    MSG_ERROR("Aborting now")
146  end if
147  if (nsrd/=0)then
148    isrd=0
149    do ia=1,natom
150      read(hyun,*) genat1
151      do ib=1,(nsrd/natom)
152        isrd=isrd+1
153        at1(isrd)=genat1
154        read(hyun,*) genat2
155        at2(isrd)=genat2
156        read(hyun,*) rpt2(1:3,isrd)
157        read(hyun,*) ifcsr(1:3,1,isrd)
158        read(hyun,*) ifcsr(1:3,2,isrd)
159        read(hyun,*) ifcsr(1:3,3,isrd)
160      end do
161    end do
162  end if
163 
164  read(hyun,*) nddd
165  if (nddd<0)then
166    write(std_out,'(a,i8,a)' )&
167 &   ' ddb_hybrid : nddd is',nddd,', which is lower than 0 => stop'
168    MSG_ERROR("Aborting now")
169  end if
170  if (nddd>mddd)then
171    write(std_out,'(a,i8,a,a,a)' )&
172 &   ' ddb_hybrid : nddd is',nddd,', which is not',ch10,&
173 &   '  one of the allowed values (0-1-2) => stop'
174    MSG_ERROR("Aborting now")
175  end if
176  if (nddd/=0)then
177    do ia=1,natom
178      do id1=1,3
179        read(hyun,*) zeff2(id1,1:3,ia)
180      end do
181    end do
182    do id1=1,3
183      read(hyun,*) dielt2(id1,1),dielt2(id1,2),dielt2(id1,3)
184    end do
185  end if
186 
187  close(hyun)
188 
189 !PART 2: include modifications in the SR part
190 !++++++++++++++++++++++++++++++++++++++++++++
191 
192  if (nsrd/=0) then
193 
194 !  write(iout,*)' List of SR modifications:'
195 !  write(iout,*)' dir, at, dir, at, R-vec, old-value, new-value'
196 !  write(iout,*)' old-value, new-value, weight'
197 
198    chk=0
199    nbr=0
200 
201    do ia=1,natom
202      do ib=1,natom
203        do irpt=1,nrpt
204          sta(ia,ib,irpt)=0
205          if (wghatm(ia,ib,irpt)/=0) sta(ia,ib,irpt)=1
206        end do
207      end do
208    end do
209 
210 !  BIG loop on the N SR-modifications
211    do isrd=1,nsrd
212 
213 !    identify the R-vector
214      flgr=0
215      do irpt=1,nrpt
216        difr(1:3)= abs(rpt2(1:3,isrd)-rpt(1:3,irpt))
217        if (difr(1)<1.d-4) then
218          if (difr(2)<1.d-4) then
219            if (difr(3)<1.d-4) then
220              flgr=irpt
221            end if
222          end if
223        end if
224      end do
225 
226      if (flgr==0)then
227        write(std_out,'(a,a,a,i8,a)' )&
228 &       ' ddb_hybrid : not able to identify the',ch10,&
229 &       ' R-vector associated to SR-data',isrd,'=> stop'
230        cycle
231      end if
232 
233 !    include the modifications in atmfrc
234      if (wghatm(at1(isrd),at2(isrd),flgr)/=0.0_dp) then
235        do d1=1,3
236          do d2=1,3
237            atmfrc(1,d1,at1(isrd),d2,at2(isrd),flgr) &
238 &           = ifcsr(d1,d2,isrd)/wghatm(at1(isrd),at2(isrd),flgr)
239          end do
240        end do
241        sta(at1(isrd),at2(isrd),flgr)=0
242        nbr=nbr+1
243      end if
244 
245      chk=chk+1
246 
247    end do
248 
249 !  end if nsrd><0
250  end if
251 
252  if (iout > 0) then
253    write(iout,*)' Number of SR modifications:',chk
254    write(iout,*)' Modifications really included:',nbr
255 
256    write(iout,*)' Eventual ifc missing:'
257    write(iout,*)' (ia,ib,irpt -- rpt1,rpt2,rpt3)'
258    chk=0
259    do ia=1,natom
260      do ib=1,natom
261        do irpt=1,nrpt
262          if ((wghatm(ia,ib,irpt)/=0).and.(sta(ia,ib,irpt)==1)) then
263            write(iout,*) ia,ib,irpt
264            write(iout,*) rpt(1,irpt),rpt(2,irpt),rpt(2,irpt)
265            chk=1
266          end if
267        end do
268      end do
269    end do
270    if (chk==0) write(iout,*)' -no problem detected-'
271  end if
272 
273 
274 !PART 3: include modifications in the DD part
275 !++++++++++++++++++++++++++++++++++++++++++++
276 
277  if (nddd/=0) then
278 
279    if (iout > 0) then
280      write(iout,*)' The DD interaction has also been modified:'
281      write(iout,*)' The Born effective chages are now:'
282      do ia=1,natom
283        write(iout,'(a,i4)' )' atom',ia
284        do id1=1,3
285          write(iout,*)zeff2(id1,1:3,ia)
286        end do
287      end do
288      write(iout,*)' The dielectric tensor is now:'
289      do id1=1,3
290        write(iout,*) dielt2(id1,1:3)
291      end do
292    end if
293 
294 !  The former values are replaced by the new ones in part 4
295 
296 !  Modify dyew2q0 accordingly to zeff2 and dielt2 (if dip-dip non-zero)
297    if (dipdip==1) then
298      sumg0=0
299      qpt(1)=0.0_dp
300      qpt(2)=0.0_dp
301      qpt(3)=0.0_dp
302      call ewald9(acell,dielt2,dyew,gmet,gprim,natom,&
303 &     qpt,rmet,rprim,sumg0,ucvol,xred,zeff2)
304      if (asr==1.or.asr==2) then
305        option=asr
306        call q0dy3_calc(natom,dyew2q0,dyew,option)
307      else if (asr==0) then
308        dyew2q0(:,:,:)=0.0_dp
309      end if
310    end if
311 
312 !  end if nddd/=0
313  end if
314 
315 !Eventually keep the total ifc within the box unchanged
316 !This basically corresponds to modify the SR part accordingly
317 !to the change of the DD part within the box...
318 
319  if (nddd==2) then
320 
321 !  Store the interatomic distances
322 !  call dist9(acell,dist,gprim,natom,nrpt,rcan,rprim,rpt)
323 
324 !  calculating the inverse (transpose) of the dielectric tensor
325    call matr3inv(dielt,invdlt)
326    call matr3inv(dielt2,invdlt2)
327 !  calculating the determinant of the dielectric tensor
328    detdlt=dielt(1,1)*dielt(2,2)*dielt(3,3)+dielt(1,3)*dielt(2,1)*&
329 &   dielt(3,2)+dielt(1,2)*dielt(2,3)*dielt(3,1)-dielt(1,3)*&
330 &   dielt(2,2)*dielt(3,1)-dielt(1,1)*dielt(2,3)*dielt(3,2)-&
331 &   dielt(1,2)*dielt(2,1)*dielt(3,3)
332    detdlt2=dielt2(1,1)*dielt2(2,2)*dielt2(3,3)+dielt2(1,3)*&
333 &   dielt2(2,1)*&
334 &   dielt2(3,2)+dielt2(1,2)*dielt2(2,3)*dielt2(3,1)-&
335 &   dielt2(1,3)*&
336 &   dielt2(2,2)*dielt2(3,1)-dielt2(1,1)*dielt2(2,3)*&
337 &   dielt2(3,2)-&
338 &   dielt2(1,2)*dielt2(2,1)*dielt2(3,3)
339 
340 !  Big loop on first atom ia
341    do ia=1,natom
342 
343 !    First transform canonical coordinates to reduced coordinates
344      xreda(:)=gprim(1,:)*rcan(1,ia)+gprim(2,:)*rcan(2,ia)&
345 &     +gprim(3,:)*rcan(3,ia)
346 
347 !    Then to cartesian coordinates
348      ra(:)=xreda(1)*acell(1)*rprim(:,1)+&
349 &     xreda(2)*acell(2)*rprim(:,2)+&
350 &     xreda(3)*acell(3)*rprim(:,3)
351 
352 !    Big intra-loop on the atoms in the box ib
353      do index=1,(natom*nrpt)
354 
355        call canct9(acell,gprim,ib,index,irpt,natom,nrpt,&
356 &       rcan,rb,rprim,rpt)
357 
358        if (wghatm(ia,ib,irpt)/=0)then
359 
360          del(:)=ra(:)-rb(:)
361          rsq=0.0_dp
362          rsq2=0.0_dp
363          delta(:)=0.0_dp
364          delta2(:)=0.0_dp
365          do jj=1,3
366            do kk=1,3
367              ewab(jj,kk)=0.0_dp
368              ewab2(jj,kk)=0
369              rsq=rsq+del(jj)*invdlt(kk,jj)*del(kk)
370              rsq2=rsq2+del(jj)*invdlt2(kk,jj)*del(kk)
371              delta(kk)=delta(kk)+invdlt(kk,jj)*del(jj)
372              delta2(kk)=delta2(kk)+invdlt2(kk,jj)*del(jj)
373            end do
374          end do
375          dd=sqrt(rsq)
376          dd2=sqrt(rsq2)
377 
378 !        Avoid zero denominators in 'term':
379          if (sqrt(rsq)>=1.0d-12) then
380            do mu=1,3
381              do nu=1,3
382                ewab(mu,nu)=(-3*delta(nu)*delta(mu)+invdlt(nu,mu)*dd**2)&
383 &               /dd**5/sqrt(detdlt)
384              end do
385            end do
386          else
387            if (ia/=ib)then
388              write(std_out,*)' ddb_hybrid : interatomic distance vanishes ',&
389 &             ' Check the input for the following atoms :'
390              write(std_out,*)ia,ib
391              MSG_ERROR("Aborting now")
392            end if
393          end if
394 
395 !        Avoid zero denominators in 'term':
396          if (sqrt(rsq)>=1.0d-12) then
397            do mu=1,3
398              do nu=1,3
399                ewab2(mu,nu)=&
400 &               (-3*delta2(nu)*delta2(mu)+invdlt2(nu,mu)*dd2**2)&
401 &               /dd2**5/sqrt(detdlt2)
402              end do
403            end do
404          else
405            if (ia/=ib)then
406              write(std_out,*)' ddb_hybrid : inter-atomic distance vanishes ',&
407 &             ' Check the input for the following atoms :'
408              write(std_out,*)ia,ib
409              MSG_ERROR("Aborting now")
410            end if
411          end if
412 
413 !        Take into account the effective charge tensor
414          normr2=rpt(1,irpt)**2+rpt(2,irpt)**2+rpt(3,irpt)**2
415          do mu=1,3
416            do nu=1,3
417              ewiaf(mu,nu)=0.0_dp
418              ewiaf2(mu,nu)=0.0_dp
419              if((ia==ib).and.(normr2<1.d-7))then
420                ewiaf(mu,nu)=-dyewq0(mu,nu,ia)
421                ewiaf2(mu,nu)=-dyew2q0(mu,nu,ia)
422              end if
423              do jj=1,3
424                do kk=1,3
425                  ewiaf(mu,nu)=ewiaf(mu,nu)&
426 &                 +zeff(jj,mu,ia)*zeff(kk,nu,ib)*&
427 &                 ewab(jj,kk)
428                  ewiaf2(mu,nu)=ewiaf2(mu,nu)&
429 &                 +zeff2(jj,mu,ia)*zeff2(kk,nu,ib)*&
430 &                 ewab2(jj,kk)
431                end do
432              end do
433            end do
434          end do
435 
436 !        add DD(old)-DD(new) to the SR part...
437          do mu=1,3
438            do nu=1,3
439              atmfrc(1,mu,ia,nu,ib,irpt)=atmfrc(1,mu,ia,nu,ib,irpt)&
440 &             +(ewiaf(mu,nu)-ewiaf2(mu,nu))/wghatm(ia,ib,irpt)
441            end do
442          end do
443 
444 !        end if wghatm><0
445        end if
446 
447 !      End loop ia
448      end do
449 
450 !    End loop index
451    end do
452 
453 !  end if nddd=2
454  end if
455 
456 !PART 4: actualize the matrices before exiting
457 !+++++++++++++++++++++++++++++++++++++++++++++
458 
459  if (nddd>0) then
460 
461 !  Update of dielt and zeff
462    zeff(:,:,:)=zeff2(:,:,:)
463    dielt(:,:)=dielt2(:,:)
464 
465 !  Update of dyewq0
466    dyewq0(:,:,:)=dyew2q0(:,:,:)
467 
468  end if
469 
470  if ((nsrd>0).or.(nddd==2)) then
471 !  Reimpose the ASR on the ifc that have been modified...
472    if(asr>0)then
473      write(std_out,*)' ddb_hybrid : enter asrif9 '
474      call asrif9(asr,atmfrc,natom,nrpt,rpt,wghatm)
475      write(std_out,*)' ddb_hybrid : exit asrif9 '
476    end if
477  end if
478 
479 end subroutine ddb_hybrid