TABLE OF CONTENTS


ABINIT/pred_lbfgs [ Functions ]

[ Top ] [ Functions ]

NAME

 pred_lbfgs

FUNCTION

 Ionmov predictors (22) Limited-memory Broyden-Fletcher-Goldfarb-Shanno

 IONMOV 22:
 Given a starting point xred that is a vector of length 3*natom
 (reduced nuclei coordinates), and unit cell parameters
 (acell and rprim) the L-Broyden-Fletcher-Goldfarb-Shanno
 minimization is performed on the total energy function, using
 its gradient (atomic forces and stress : fred or fcart and
 stress) as calculated by the routine scfcv. Some atoms can be
 kept fixed, while the optimization of unit cell parameters is
 only performed if optcell/=0. The convergence requirement on
 the atomic forces, dtset%tolmxf,  allows an early exit.
 Otherwise no more than dtset%ntime steps are performed.
 Returned quantities are xred, and eventually acell and rprim
 (new ones!).
 Could see MinPack on netlib.org

COPYRIGHT

 Copyright (C) 1998-2018 ABINIT group (DCA, XG, GMR, JCC, SE, FB)
 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

 ab_mover <type(abimover)> : Datatype with all the information
                                needed by the preditor
 itime  : Index of the present iteration
 ntime  : Maximal number of iterations
 ionmov : (22) Specific kind of BFGS
 zDEBUG : if true print some debugging information

OUTPUT

SIDE EFFECTS

 hist <type(abihist)> : History of positions,forces
                               acell, rprimd, stresses

PARENTS

      mover

CHILDREN

      fcart2fred,hist2var,lbfgs_destroy,lbfgs_init,metric,mkrdim,var2hist
      xfh_recover_new,xfpack_f2vout,xfpack_vin2x,xfpack_x2vin

SOURCE

 55 #if defined HAVE_CONFIG_H
 56 #include "config.h"
 57 #endif
 58 
 59 #include "abi_common.h"
 60 
 61 subroutine pred_lbfgs(ab_mover,ab_xfh,forstr,hist,ionmov,itime,zDEBUG,iexit)
 62 
 63  use defs_basis
 64  use m_profiling_abi
 65  use m_abimover
 66  use m_abihist
 67  use m_lbfgs
 68 
 69  use m_geometry,       only : mkrdim, fcart2fred, metric
 70 
 71 !This section has been created automatically by the script Abilint (TD).
 72 !Do not modify the following lines by hand.
 73 #undef ABI_FUNC
 74 #define ABI_FUNC 'pred_lbfgs'
 75  use interfaces_45_geomoptim, except_this_one => pred_lbfgs
 76 !End of the abilint section
 77 
 78 implicit none
 79 
 80 !Arguments ------------------------------------
 81 !scalars
 82 type(abimover),intent(in)       :: ab_mover
 83 type(ab_xfh_type),intent(inout)    :: ab_xfh
 84 type(abihist),intent(inout) :: hist
 85 type(abiforstr),intent(in) :: forstr
 86 integer,intent(in) :: itime
 87 integer,intent(in) :: ionmov
 88 integer,intent(in) :: iexit
 89 logical,intent(in) :: zDEBUG
 90 
 91 !Local variables-------------------------------
 92 !scalars
 93 integer :: info,ihist_prev
 94 integer  :: ndim,cycl_main
 95 integer, parameter :: npul=0
 96 integer  :: ii,jj,kk
 97 real(dp),save :: ucvol0
 98 real(dp) :: ucvol
 99 real(dp) :: etotal
100 real(dp) :: favg
101 
102 !arrays
103 real(dp),allocatable :: diag(:)
104 real(dp),allocatable,save :: hessin(:,:),vin(:),vin_prev(:)
105 real(dp),allocatable,save :: vout(:),vout_prev(:)
106 real(dp),allocatable,save ::vinres(:,:),vin1(:,:)
107 real(dp),save :: acell0(3) ! Initial acell
108 real(dp),save :: rprimd0(3,3) ! Initial rprimd
109 real(dp) :: acell(3)
110 real(dp) :: rprimd(3,3),rprim(3,3)
111 real(dp) :: gprimd(3,3)
112 real(dp) :: gmet(3,3)
113 real(dp) :: rmet(3,3)
114 real(dp) :: residual(3,ab_mover%natom),residual_corrected(3,ab_mover%natom)
115 real(dp) :: xred(3,ab_mover%natom)
116 real(dp) :: strten(6)
117 
118 !***************************************************************************
119 !Beginning of executable session
120 !***************************************************************************
121 
122  if(iexit/=0)then
123    call lbfgs_destroy()
124 
125    if (allocated(vin))        then
126      ABI_DEALLOCATE(vin)
127    end if
128    if (allocated(vout))       then
129      ABI_DEALLOCATE(vout)
130    end if
131    if (allocated(vin_prev))   then
132      ABI_DEALLOCATE(vin_prev)
133    end if
134    if (allocated(vout_prev))  then
135      ABI_DEALLOCATE(vout_prev)
136    end if
137    if (allocated(vinres))  then
138      ABI_DEALLOCATE(vinres)
139    end if
140    if (allocated(vin1))  then
141      ABI_DEALLOCATE(vin1)
142    end if
143    if (allocated(hessin))     then
144      ABI_DEALLOCATE(hessin)
145    end if
146    return
147  end if
148 
149 !write(std_out,*) 'bfgs 01'
150 !##########################################################
151 !### 01. Debugging and Verbose
152 
153  if(zDEBUG)then
154    write(std_out,'(a,3a,35a,42a)') ch10,('-',kk=1,3),&
155 &   'Debugging and Verbose for pred_bfgs',('-',kk=1,42)
156    write(std_out,*) 'ionmov: ',ionmov
157    write(std_out,*) 'itime:  ',itime
158  end if
159 
160 !write(std_out,*) 'bfgs 02'
161 !##########################################################
162 !### 02. Compute the dimension of vectors (ndim)
163 
164  ndim=3*ab_mover%natom
165  if(ab_mover%optcell==1 .or.&
166 & ab_mover%optcell==4 .or.&
167 & ab_mover%optcell==5 .or.&
168 & ab_mover%optcell==6) ndim=ndim+1
169  if(ab_mover%optcell==2 .or.&
170 & ab_mover%optcell==3) ndim=ndim+6
171  if(ab_mover%optcell==7 .or.&
172 & ab_mover%optcell==8 .or.&
173 & ab_mover%optcell==9) ndim=ndim+3
174 
175  if(zDEBUG) write(std_out,*) 'Dimension of vin, vout and hessian (ndim): ',ndim
176 
177 !write(std_out,*) 'bfgs 03'
178 !##########################################################
179 !### 03. Allocate the vectors vin, vout and hessian matrix
180 
181 !Notice that vin, vout, etc could be allocated
182 !From a previous dataset with a different ndim
183  if(itime==1)then
184    if (allocated(vin))        then
185      ABI_DEALLOCATE(vin)
186    end if
187    if (allocated(vout))       then
188      ABI_DEALLOCATE(vout)
189    end if
190    if (allocated(vin_prev))   then
191      ABI_DEALLOCATE(vin_prev)
192    end if
193    if (allocated(vout_prev))  then
194      ABI_DEALLOCATE(vout_prev)
195    end if
196    if (allocated(vinres))  then
197      ABI_DEALLOCATE(vinres)
198    end if
199    if (allocated(vin1))  then
200      ABI_DEALLOCATE(vin1)
201    end if
202    if (allocated(hessin))     then
203      ABI_DEALLOCATE(hessin)
204    end if
205    if(npul>1) then
206      ABI_ALLOCATE(vinres,(npul+1,ndim))
207      ABI_ALLOCATE(vin1,(npul+1,ndim))
208    end if
209    ABI_ALLOCATE(vin,(ndim))
210    ABI_ALLOCATE(vout,(ndim))
211    ABI_ALLOCATE(vin_prev,(ndim))
212    ABI_ALLOCATE(vout_prev,(ndim))
213    ABI_ALLOCATE(hessin,(ndim,ndim))
214  end if
215 
216 !write(std_out,*) 'bfgs 04'
217 !##########################################################
218 !### 04. Obtain the present values from the history
219 
220  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
221  do ii=1,3
222    rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
223  end do
224 
225  strten(:)=hist%strten(:,hist%ihist)
226  etotal   =hist%etot(hist%ihist)
227 
228 !Fill the residual with forces (No preconditioning)
229 !Or the preconditioned forces
230  if (ab_mover%goprecon==0)then
231    call fcart2fred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
232  else
233    residual(:,:)= forstr%fred(:,:)
234  end if
235 
236  if(zDEBUG)then
237    write (std_out,*) 'residual:'
238    do kk=1,ab_mover%natom
239      write (std_out,*) residual(:,kk)
240    end do
241    write (std_out,*) 'strten:'
242    write (std_out,*) strten(1:3),ch10,strten(4:6)
243    write (std_out,*) 'etotal:'
244    write (std_out,*) etotal
245  end if
246 
247  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
248 
249 !Save initial values
250  if (itime==1)then
251    acell0(:)=acell(:)
252    rprimd0(:,:)=rprimd(:,:)
253    ucvol0=ucvol
254  end if
255 
256 !zDEBUG (UCVOL)
257  if(zDEBUG)then
258    write(std_out,*) 'Volume of cell (ucvol):',ucvol
259  end if
260 
261 !Get rid of mean force on whole unit cell, but only if no
262 !generalized constraints are in effect
263  residual_corrected(:,:)=residual(:,:)
264  if(ab_mover%nconeq==0)then
265    do ii=1,3
266      if (ii/=3.or.ab_mover%jellslab==0) then
267        favg=sum(residual_corrected(ii,:))/dble(ab_mover%natom)
268        residual_corrected(ii,:)=residual_corrected(ii,:)-favg
269      end if
270    end do
271  end if
272 
273 !write(std_out,*) 'bfgs 05'
274 !##########################################################
275 !### 05. Fill the vectors vin and vout
276 
277 !Initialize input vectors : first vin, then vout
278 !The values of vin from the previous iteration
279 !should be the same
280 !if (itime==1)then
281  call xfpack_x2vin(acell, acell0, ab_mover%natom, ndim,&
282 & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
283 & ab_mover%symrel, ucvol, ucvol0, vin, xred)
284 !end if
285 
286  call xfpack_f2vout(residual_corrected, ab_mover%natom, ndim,&
287 & ab_mover%optcell, ab_mover%strtarget, strten, ucvol,&
288 & vout)
289 
290 !write(std_out,*) 'bfgs 06'
291 !##########################################################
292 !### 06. Initialize or update the hessian matrix
293 
294 !Initialise the Hessian matrix using gmet
295  if (itime==1)then
296 
297    ABI_ALLOCATE(diag,(ndim))
298    do ii=1,3*ab_mover%natom
299 !      diag(ii) = 1.00_dp / rprimd(MODULO(ii-1,3)+1,MODULO(ii-1,3)+1)**2
300      diag(ii) = gmet(MODULO(ii-1,3)+1,MODULO(ii-1,3)+1)
301    end do
302    if(ab_mover%optcell/=0)then
303 !     These values might lead to too large changes in some cases ...
304      do ii=3*ab_mover%natom+1,ndim
305        diag(ii) = ab_mover%strprecon*30.0_dp/ucvol
306        if(ab_mover%optcell==1) diag(ii) = diag(ii) / three
307      end do
308    end if
309 
310    call lbfgs_init(ndim,5,diag)
311    ABI_DEALLOCATE(diag)
312 
313    if (ab_mover%restartxf/=0) then
314 
315      call xfh_recover_new(ab_xfh,ab_mover,acell,acell0,cycl_main,residual,&
316 &     hessin,ndim,rprim,rprimd0,strten,ucvol,ucvol0,vin,&
317 &     vin_prev,vout,vout_prev,xred)
318 
319    end if
320 
321  end if
322 
323 !zDEBUG (vin,vout and hessin before prediction)
324  if(zDEBUG)then
325    write(std_out,*) 'Vectors vin and vout and inverse of Hessian (hessin) [before]'
326    write(std_out,*) 'vin:'
327    do ii=1,ndim,3
328      if (ii+2<=ndim)then
329        write(std_out,*) ii,vin(ii:ii+2)
330      else
331        write(std_out,*) ii,vin(ii:ndim)
332      end if
333    end do
334    write(std_out,*) 'vout:'
335    do ii=1,ndim,3
336      if (ii+2<=ndim)then
337        write(std_out,*) ii,vout(ii:ii+2)
338      else
339        write(std_out,*) ii,vout(ii:ndim)
340      end if
341    end do
342    write(std_out,*) 'Inverse Hessian (hessin): ',ndim,'x',ndim
343    do kk=1,ndim
344      do jj=1,ndim,3
345        if (jj+2<=ndim)then
346          write(std_out,*) jj,hessin(jj:jj+2,kk)
347        else
348          write(std_out,*) jj,hessin(jj:ndim,kk)
349        end if
350      end do
351    end do
352  end if
353 
354 !write(std_out,*) 'bfgs 07'
355 !##########################################################
356 !### 07. Compute the next values
357 
358  vin_prev(:) = vin
359  vout_prev(:) = vout
360  info = lbfgs_execute(vin,etotal,vout)
361 
362 !zDEBUG (vin,vout after prediction)
363  if(zDEBUG)then
364    write(std_out,*) 'Vectors vin and vout [after prediction]'
365    write(std_out,*) 'vin_prev:'
366    do ii=1,ndim,3
367      if (ii+2<=ndim)then
368        write(std_out,*) ii,vin_prev(ii:ii+2)
369      else
370        write(std_out,*) ii,vin_prev(ii:ndim)
371      end if
372    end do
373    write(std_out,*) 'vin:'
374    do ii=1,ndim,3
375      if (ii+2<=ndim)then
376        write(std_out,*) ii,vin(ii:ii+2)
377      else
378        write(std_out,*) ii,vin(ii:ndim)
379      end if
380    end do
381    write(std_out,*) 'vout:'
382    do ii=1,ndim,3
383      if (ii+2<=ndim)then
384        write(std_out,*) ii,vout(ii:ii+2)
385      else
386        write(std_out,*) ii,vout(ii:ndim)
387      end if
388    end do
389  end if
390 
391 
392 !Implement fixing of atoms : put back old values for fixed
393 !components
394  do kk=1,ab_mover%natom
395    do jj=1,3
396 !    Warning : implemented in reduced coordinates
397      if ( ab_mover%iatfix(jj,kk)==1) then
398        vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
399      end if
400    end do
401  end do
402 
403 
404 !write(std_out,*) 'bfgs 08'
405 !##########################################################
406 !### 08. Update the history with the prediction
407 
408 !Increase indexes
409  hist%ihist = abihist_findIndex(hist,+1)
410 
411 !Transfer vin  to xred, acell and rprim
412  call xfpack_vin2x(acell, acell0, ab_mover%natom, ndim,&
413 & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
414 & ab_mover%symrel, ucvol, ucvol0,&
415 & vin, xred)
416 
417  if(ab_mover%optcell/=0)then
418    call mkrdim(acell,rprim,rprimd)
419    call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
420  end if
421 
422 !Fill the history with the variables
423 !xcart, xred, acell, rprimd
424  call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
425  ihist_prev = abihist_findIndex(hist,-1)
426  hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
427 
428  if(zDEBUG)then
429    write (std_out,*) 'residual:'
430    do kk=1,ab_mover%natom
431      write (std_out,*) residual(:,kk)
432    end do
433    write (std_out,*) 'strten:'
434    write (std_out,*) strten(1:3),ch10,strten(4:6)
435    write (std_out,*) 'etotal:'
436    write (std_out,*) etotal
437  end if
438 
439 end subroutine pred_lbfgs