Branch data Line data Source code
1 : : !!****m* ABINIT/m_pred_bfgs
2 : : !! NAME
3 : : !! m_pred_bfgs
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, JCC, SE, FB)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! SOURCE
14 : :
15 : : #if defined HAVE_CONFIG_H
16 : : #include "config.h"
17 : : #endif
18 : :
19 : : #include "abi_common.h"
20 : :
21 : : module m_pred_bfgs
22 : :
23 : : use defs_basis
24 : : use m_abicore
25 : : use m_abimover
26 : : use m_abihist
27 : : use m_xfpack
28 : : use m_lbfgs
29 : : use m_errors
30 : :
31 : : use m_geometry, only : mkrdim, fcart2gred, metric
32 : : use m_bfgs, only : hessinit, hessupdt, brdene
33 : :
34 : : implicit none
35 : :
36 : : private
37 : : !!***
38 : :
39 : : public :: pred_bfgs
40 : : public :: pred_lbfgs
41 : : !!***
42 : :
43 : : contains
44 : : !!***
45 : :
46 : : !!****f* ABINIT/pred_bfgs
47 : : !! NAME
48 : : !! pred_bfgs
49 : : !!
50 : : !! FUNCTION
51 : : !! Ionmov predictors (2 & 3) Broyden-Fletcher-Goldfarb-Shanno
52 : : !!
53 : : !! IONMOV 2:
54 : : !! Given a starting point xred that is a vector of length 3*natom
55 : : !! (reduced nuclei coordinates), and unit cell parameters
56 : : !! (acell and rprimd) the Broyden-Fletcher-Goldfarb-Shanno
57 : : !! minimization is performed on the total energy function, using
58 : : !! its gradient (atomic forces and stresse) as calculated
59 : : !! by the routine scfcv. Some atoms can be kept fixed,
60 : : !! while the optimization of unit cell parameters is
61 : : !! only performed if optcell/=0. The convergence requirement on
62 : : !! the atomic forces, dtset%tolmxf, allows an early exit.
63 : : !! Otherwise no more than dtset%ntime steps are performed.
64 : : !! Returned quantities are xred, and eventually acell and rprim (new ones!).
65 : : !! Could see Numerical Recipes (Fortran), 1986, page 307.
66 : : !!
67 : : !! IONMOV 3:
68 : : !! Conduct structural optimization using the Broyden-Fletcher-
69 : : !! Goldfarb-Shanno minimization (BFGS), modified to take into
70 : : !! account the total energy as well as the gradients (as in usual
71 : : !! BFGS). See the paper by Schlegel, J. Comp. Chem. 3, 214 (1982) [[cite:Schlegel1982]].
72 : : !! Might be better than ionmov=2 for few degrees of freedom (less than 3 or 4)
73 : : !!
74 : : !! INPUTS
75 : : !! ab_mover <type(abimover)> : Datatype with all the information
76 : : !! needed by the preditor
77 : : !! itime : Index of the present iteration
78 : : !! ntime : Maximal number of iterations
79 : : !! ionmov : (2 or 3) Specific kind of BFGS
80 : : !! zDEBUG : if true print some debugging information
81 : : !!
82 : : !! OUTPUT
83 : : !!
84 : : !! SIDE EFFECTS
85 : : !! hist <type(abihist)> : History of positions,forces acell, rprimd, stresses
86 : : !!
87 : : !! SOURCE
88 : :
89 : 1244 : subroutine pred_bfgs(ab_mover,ab_xfh,forstr,hist,ionmov,itime,zDEBUG,iexit)
90 : :
91 : : !Arguments ------------------------------------
92 : : !scalars
93 : : type(abimover),intent(in) :: ab_mover
94 : : type(ab_xfh_type),intent(inout) :: ab_xfh
95 : : type(abihist),intent(inout) :: hist
96 : : type(abiforstr),intent(in) :: forstr
97 : : integer,intent(in) :: itime
98 : : integer,intent(in) :: ionmov
99 : : integer,intent(in) :: iexit
100 : : logical,intent(in) :: zDEBUG
101 : :
102 : : !Local variables-------------------------------
103 : : !scalars
104 : : integer :: ihist_prev,ndim,cycl_main
105 : : integer, parameter :: npul=0
106 : : integer :: ierr,ii,jj,kk,nitpul
107 : : real(dp),save :: ucvol0
108 : : real(dp) :: ucvol,det
109 : : real(dp) :: etotal,etotal_prev
110 : : real(dp) :: favg,alpha0
111 : :
112 : : !arrays
113 : 1244 : integer,allocatable :: ipiv(:)
114 : : real(dp),allocatable,save :: hessin(:,:),vin(:),vin_prev(:)
115 : : real(dp),allocatable,save :: vout(:),vout_prev(:)
116 : : real(dp),allocatable,save ::vinres(:,:),vin1(:,:)
117 : 1244 : real(dp),allocatable :: amat(:,:),amatinv(:,:),alpha(:,:)
118 : 1244 : real(dp),allocatable :: rwork(:)
119 : : real(dp),save :: acell0(3) ! Initial acell
120 : : real(dp),save :: rprimd0(3,3) ! Initial rprimd
121 : : real(dp) :: acell(3)
122 : : real(dp) :: rprimd(3,3),rprim(3,3)
123 : : real(dp) :: gprimd(3,3)
124 : : real(dp) :: gmet(3,3)
125 : : real(dp) :: rmet(3,3)
126 : 2488 : real(dp) :: residual(3,ab_mover%natom),residual_corrected(3,ab_mover%natom)
127 : 1244 : real(dp) :: xred(3,ab_mover%natom),strten(6)
128 : :
129 : : !***************************************************************************
130 : : !Beginning of executable session
131 : : !***************************************************************************
132 : :
133 [ + + ]: 1244 : if(iexit/=0)then
134 [ + + ]: 306 : ABI_SFREE(vin)
135 [ + + ]: 306 : ABI_SFREE(vout)
136 [ + + ]: 306 : ABI_SFREE(vin_prev)
137 [ + + ]: 306 : ABI_SFREE(vout_prev)
138 [ - + ]: 306 : ABI_SFREE(vinres)
139 [ - + ]: 306 : ABI_SFREE(vin1)
140 [ + + ]: 306 : ABI_SFREE(hessin)
141 : : return
142 : : end if
143 : :
144 : : !write(std_out,*) 'bfgs 01'
145 : : !##########################################################
146 : : !### 01. Debugging and Verbose
147 : :
148 [ - + ]: 938 : if(zDEBUG)then
149 [ # # # # : 0 : write(std_out,'(a,3a,35a,42a)') ch10,('-',kk=1,3),'Debugging and Verbose for pred_bfgs',('-',kk=1,42)
# # # # ]
150 : 0 : write(std_out,*) 'ionmov: ',ionmov
151 : 0 : write(std_out,*) 'itime: ',itime
152 : : end if
153 : :
154 : : !write(std_out,*) 'bfgs 02'
155 : : !##########################################################
156 : : !### 02. Compute the dimension of vectors (ndim)
157 : :
158 : 938 : ndim=3*ab_mover%natom
159 [ + + ]: 938 : if(ab_mover%optcell==1) ndim=ndim+1
160 [ + + ]: 938 : if(ab_mover%optcell==2 .or.&
161 : 129 : & ab_mover%optcell==3) ndim=ndim+6
162 [ + + ]: 938 : if(ab_mover%optcell>=4) ndim=ndim+3
163 : :
164 [ - + ]: 938 : if(zDEBUG) write(std_out,*) 'Dimension of vin, vout and hessian (ndim): ',ndim
165 : :
166 : : !write(std_out,*) 'bfgs 03'
167 : : !##########################################################
168 : : !### 03. Allocate the vectors vin, vout and hessian matrix
169 : :
170 : : !Notice that vin, vout, etc could be allocated
171 : : !From a previous dataset with a different ndim
172 [ + + ]: 938 : if(itime==1)then
173 [ - + ]: 286 : ABI_SFREE(vin)
174 [ - + ]: 286 : ABI_SFREE(vout)
175 [ - + ]: 286 : ABI_SFREE(vin_prev)
176 [ - + ]: 286 : ABI_SFREE(vout_prev)
177 [ - + ]: 286 : ABI_SFREE(vinres)
178 [ - + ]: 286 : ABI_SFREE(vin1)
179 [ - + ]: 286 : ABI_SFREE(hessin)
180 : : if(npul>1) then
181 : : ABI_MALLOC(vinres,(npul+1,ndim))
182 : : ABI_MALLOC(vin1,(npul+1,ndim))
183 : : end if
184 [ - + + - : 858 : ABI_MALLOC(vin,(ndim))
+ - + - -
+ - + -
+ ]
185 [ - + + - : 572 : ABI_MALLOC(vout,(ndim))
- + - + -
+ ]
186 [ - + + - : 572 : ABI_MALLOC(vin_prev,(ndim))
- + - + -
+ ]
187 [ - + + - : 572 : ABI_MALLOC(vout_prev,(ndim))
- + - + -
+ ]
188 [ - + + - : 1144 : ABI_MALLOC(hessin,(ndim,ndim))
- + + - +
- + - - +
- + - + ]
189 : : end if
190 : :
191 : : !write(std_out,*) 'bfgs 04'
192 : : !##########################################################
193 : : !### 04. Obtain the present values from the history
194 : :
195 : 938 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
196 [ + + ]: 3752 : do ii=1,3
197 [ + + ]: 12194 : rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
198 : : end do
199 : :
200 [ + + ]: 6566 : strten(:)=hist%strten(:,hist%ihist)
201 : 938 : etotal =hist%etot(hist%ihist)
202 : :
203 : : !Fill the residual with forces (No preconditioning)
204 : : !Or the preconditioned forces
205 [ + + ]: 938 : if (ab_mover%goprecon==0)then
206 : 933 : call fcart2gred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
207 : : else
208 [ + + + + ]: 45 : residual(:,:)=forstr%gred(:,:)
209 : : end if
210 : :
211 [ - + ]: 938 : if(zDEBUG)then
212 : 0 : write (std_out,*) 'residual:'
213 [ # # ]: 0 : do kk=1,ab_mover%natom
214 : 0 : write (std_out,*) residual(:,kk)
215 : : end do
216 : 0 : write (std_out,*) 'strten:'
217 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
218 : 0 : write (std_out,*) 'etotal:'
219 : 0 : write (std_out,*) etotal
220 : : end if
221 : :
222 : 938 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
223 : :
224 : : !Save initial values
225 [ + + ]: 938 : if (itime==1)then
226 : 286 : acell0(:)=acell(:)
227 : 286 : rprimd0(:,:)=rprimd(:,:)
228 : 286 : ucvol0=ucvol
229 : : end if
230 : :
231 : : !zDEBUG (UCVOL)
232 [ - + ]: 938 : if(zDEBUG)then
233 : 0 : write(std_out,*) 'Volume of cell (ucvol):',ucvol
234 : : end if
235 : :
236 : : !Get rid of mean force on whole unit cell, but only if no
237 : : !generalized constraints are in effect
238 [ + + + + ]: 12182 : residual_corrected(:,:)=residual(:,:)
239 [ + + ]: 938 : if(ab_mover%nconeq==0)then
240 [ + + ]: 3580 : do ii=1,3
241 [ + + + - ]: 3580 : if (ii/=3.or.ab_mover%jellslab==0) then
242 [ + + ]: 10860 : favg=sum(residual_corrected(ii,:))/dble(ab_mover%natom)
243 [ + + ]: 10860 : residual_corrected(ii,:)=residual_corrected(ii,:)-favg
244 : : end if
245 : : end do
246 : : end if
247 : :
248 : : !write(std_out,*) 'bfgs 05'
249 : : !##########################################################
250 : : !### 05. Fill the vectors vin and vout
251 : :
252 : : !Initialize input vectors : first vin, then vout
253 : : !The values of vin from the previous iteration
254 : : !should be the same
255 : : !if (itime==1)then
256 : : call xfpack_x2vin(acell, ab_mover%natom, ndim,&
257 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
258 [ + - - - : 938 : & ab_mover%symrel, ucvol, ucvol0, vin, xred)
- - - - -
- - + ]
259 : : !end if
260 : :
261 : : call xfpack_f2vout(residual_corrected, ab_mover%natom, ndim,&
262 : : & ab_mover%optcell, ab_mover%strtarget, strten, ucvol,&
263 [ + - - - : 938 : & vout)
- - - + ]
264 : :
265 : : !write(std_out,*) 'bfgs 06'
266 : : !##########################################################
267 : : !### 06. Initialize or update the hessian matrix
268 : :
269 : : !Initialise the Hessian matrix using gmet
270 [ + + ]: 938 : if (itime==1)then
271 : :
272 : 286 : call hessinit(ab_mover, hessin, gmet, ndim, ucvol)
273 : :
274 : : ! ! Initialize inverse hessian with identity matrix
275 : : ! ! in cartesian coordinates, which makes use of metric tensor gmet
276 : : ! ! in reduced coordinates.
277 : : ! hessin(:,:)=zero
278 : : ! do ii=1,ab_mover%natom
279 : : ! do kk=1,3
280 : : ! do jj=1,3
281 : : ! ! Warning : implemented in reduced coordinates
282 : : ! if (ab_mover%iatfix(kk,ii)==0 .and.&
283 : : ! & ab_mover%iatfix(jj,ii)==0 )then
284 : : ! hessin(kk+3*(ii-1),jj+3*(ii-1))=gmet(kk,jj)
285 : : ! end if
286 : : ! end do
287 : : ! end do
288 : : ! end do
289 : : ! if(ab_mover%optcell/=0)then
290 : : ! ! These values might lead to too large changes in some cases
291 : : ! diag=ab_mover%strprecon*30.0_dp/ucvol
292 : : ! if(ab_mover%optcell==1) diag=diag/three
293 : : ! do ii=3*ab_mover%natom+1,ndim
294 : : ! hessin(ii,ii)=diag
295 : : ! end do
296 : : ! end if
297 : :
298 [ + + ]: 286 : if (ab_mover%restartxf/=0) then
299 : :
300 : : call xfh_recover_new(ab_xfh,ab_mover,acell,cycl_main,residual,&
301 : : & hessin,ndim,rprim,rprimd0,strten,ucvol,ucvol0,vin,&
302 : 7 : & vin_prev,vout,vout_prev,xred)
303 : :
304 : : end if
305 : :
306 : : end if
307 : :
308 [ + + ]: 938 : if(itime>1)then
309 : : ! Update the hessian matrix, by taking into account the
310 : : ! current pair (x,f) and the previous one.
311 : : call hessupdt(hessin,ab_mover%iatfix,ab_mover%natom,ndim,vin,&
312 [ + - - - : 652 : & vin_prev,vout,vout_prev)
- - - - -
+ ]
313 : :
314 : : end if
315 : :
316 : : !zDEBUG (vin,vout and hessin before prediction)
317 [ - + ]: 938 : if(zDEBUG)then
318 : 0 : write(std_out,*) 'Vectors vin and vout and inverse of Hessian (hessin) [before]'
319 : 0 : write(std_out,*) 'vin:'
320 [ # # # # ]: 0 : do ii=1,ndim,3
321 [ # # ]: 0 : if (ii+2<=ndim)then
322 : 0 : write(std_out,*) ii,vin(ii:ii+2)
323 : : else
324 : 0 : write(std_out,*) ii,vin(ii:ndim)
325 : : end if
326 : : end do
327 : 0 : write(std_out,*) 'vout:'
328 [ # # # # ]: 0 : do ii=1,ndim,3
329 [ # # ]: 0 : if (ii+2<=ndim)then
330 : 0 : write(std_out,*) ii,vout(ii:ii+2)
331 : : else
332 : 0 : write(std_out,*) ii,vout(ii:ndim)
333 : : end if
334 : : end do
335 : 0 : write(std_out,*) 'Inverse Hessian (hessin): ',ndim,'x',ndim
336 [ # # ]: 0 : do kk=1,ndim
337 [ # # # # ]: 0 : do jj=1,ndim,3
338 [ # # ]: 0 : if (jj+2<=ndim)then
339 : 0 : write(std_out,*) jj,hessin(jj:jj+2,kk)
340 : : else
341 : 0 : write(std_out,*) jj,hessin(jj:ndim,kk)
342 : : end if
343 : : end do
344 : : end do
345 : : end if
346 : :
347 : : !write(std_out,*) 'bfgs 07'
348 : : !##########################################################
349 : : !### 07. Compute the next values
350 : :
351 [ + + + + ]: 938 : if(ionmov==2 .or. itime==1)then
352 : :
353 : : ! Previous cartesian coordinates
354 [ + + ]: 8646 : vin_prev(:)=vin(:)
355 : :
356 : : ! New atomic cartesian coordinates are obtained from vin, hessin
357 : : ! and vout
358 : :
359 [ + - + - : 729987 : vin(:) = vin(:) - matmul(hessin(:,:), vout(:))
+ - - + -
+ + + + +
+ + + - +
- + - + +
+ - ]
360 : :
361 : : !Pulay mixing for vin
362 : 691 : nitpul=0
363 : : if (npul>1) then
364 : : alpha0=1.0_dp
365 : : nitpul=min(itime, npul)
366 : : if (itime>npul) then
367 : : do jj=1,npul-1
368 : : vinres(jj,:)=vinres(jj+1,:)
369 : : vin1(jj,:)=vin1(jj+1,:)
370 : : end do
371 : : end if
372 : : vinres(nitpul,:)=vin(:)-vin_prev(:)
373 : : vin1(nitpul,:)=vin_prev(:)
374 : : end if
375 : :
376 : : if (nitpul>1) then
377 : : ABI_MALLOC(alpha,(nitpul,ndim))
378 : : alpha=zero
379 : : do kk=1,ndim
380 : : ABI_MALLOC(amat,(nitpul,nitpul))
381 : : ABI_MALLOC(amatinv,(nitpul,nitpul))
382 : : amat=zero;amatinv=zero
383 : : do ii=1,nitpul
384 : : do jj=ii,nitpul
385 : : amat(ii,jj)=vinres(jj,kk)*vinres(ii,kk)
386 : : amat(jj,ii)=amat(ii,jj)
387 : : end do
388 : : end do
389 : : amatinv=amat
390 : : if (abs(vin(kk)-vin_prev(kk))<tol10) then
391 : : alpha(:,kk)=zero
392 : : else
393 : : ABI_MALLOC(ipiv,(nitpul))
394 : : ABI_MALLOC(rwork,(nitpul))
395 : : ! amatinv=1.d5*amatinv
396 : : call dgetrf(nitpul,nitpul,amatinv,nitpul,ipiv,ierr)
397 : : call dgetri(nitpul,amatinv,nitpul,ipiv,rwork,nitpul,ierr)
398 : : ! amatinv=1.d5*amatinv
399 : : ABI_FREE(ipiv)
400 : : ABI_FREE(rwork)
401 : : det=zero
402 : : do ii=1,nitpul
403 : : do jj=1,nitpul
404 : : alpha(ii,kk)=alpha(ii,kk)+amatinv(jj,ii)
405 : : det=det+amatinv(jj,ii)
406 : : end do
407 : : end do
408 : : alpha(:,kk)=alpha(:,kk)/det
409 : : end if
410 : : end do
411 : : ABI_FREE(amat)
412 : : ABI_FREE(amatinv)
413 : : vin(:)=vin1(nitpul,:)+alpha0*(vin1(nitpul+1,:)-vin1(nitpul,:))
414 : : vin=zero
415 : : do ii=1,nitpul
416 : : vin(:)=vin(:)+ alpha(ii,:)*(vin1(ii,:))
417 : : end do
418 : : ABI_FREE(alpha)
419 : : end if
420 : :
421 : :
422 : : ! Previous atomic forces
423 [ + + ]: 8646 : vout_prev(:)=vout(:)
424 : :
425 : : else
426 [ + - ]: 247 : if(ionmov==3)then
427 : 247 : ihist_prev = abihist_findIndex(hist,-1)
428 : 247 : etotal_prev=hist%etot(ihist_prev)
429 : : ! Here the BFGS algorithm, modified to take into account the energy
430 : 247 : call brdene(etotal,etotal_prev,hessin,ndim,vin,vin_prev,vout,vout_prev)
431 : : end if
432 : :
433 : : ! zDEBUG (vin,vout and hessin after prediction)
434 [ - + ]: 247 : if(zDEBUG)then
435 : 0 : write(std_out,*) 'Vectors vin and vout [after prediction]'
436 : 0 : write(std_out,*) 'vin:'
437 [ # # # # ]: 0 : do ii=1,ndim,3
438 [ # # ]: 0 : if (ii+2<=ndim)then
439 : 0 : write(std_out,*) ii,vin(ii:ii+2)
440 : : else
441 : 0 : write(std_out,*) ii,vin(ii:ndim)
442 : : end if
443 : : end do
444 : 0 : write(std_out,*) 'vout:'
445 [ # # # # ]: 0 : do ii=1,ndim,3
446 [ # # ]: 0 : if (ii+2<=ndim)then
447 : 0 : write(std_out,*) ii,vout(ii:ii+2)
448 : : else
449 : 0 : write(std_out,*) ii,vout(ii:ndim)
450 : : end if
451 : : end do
452 : : end if
453 : :
454 : :
455 : : ! FIXME: this should be outside the if clause on ionmov!
456 : : ! Implement fixing of atoms : put back old values for fixed
457 : : ! components
458 [ + + ]: 731 : do kk=1,ab_mover%natom
459 [ + + ]: 2183 : do jj=1,3
460 : : ! Warning : implemented in reduced coordinates
461 [ + + ]: 1936 : if ( ab_mover%iatfix(jj,kk)==1) then
462 : 234 : vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
463 : : end if
464 : : end do
465 : : end do
466 : : end if
467 : :
468 : : !write(std_out,*) 'bfgs 08'
469 : : !##########################################################
470 : : !### 08. Update the history with the prediction
471 : :
472 : : !Increase indexes
473 : 938 : hist%ihist = abihist_findIndex(hist,+1)
474 : :
475 : : !Transfer vin to xred, acell and rprim
476 : : call xfpack_vin2x(acell, acell0, ab_mover%natom, ndim,&
477 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
478 : : & ab_mover%symrel, ucvol, ucvol0,&
479 [ + - - - : 938 : & vin, xred)
- - - - -
- - + ]
480 : :
481 [ + + ]: 938 : if(ab_mover%optcell/=0)then
482 : 318 : call mkrdim(acell,rprim,rprimd)
483 : 318 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
484 : : end if
485 : :
486 : : !Fill the history with the variables
487 : : !xred, acell, rprimd, vel
488 : 938 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
489 : 938 : ihist_prev = abihist_findIndex(hist,-1)
490 [ + + + + ]: 12182 : hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
491 : :
492 [ - + ]: 938 : if(zDEBUG)then
493 : 0 : write (std_out,*) 'residual:'
494 [ # # ]: 0 : do kk=1,ab_mover%natom
495 : 0 : write (std_out,*) residual(:,kk)
496 : : end do
497 : 0 : write (std_out,*) 'strten:'
498 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
499 : 0 : write (std_out,*) 'etotal:'
500 : 0 : write (std_out,*) etotal
501 : : end if
502 : :
503 : : end subroutine pred_bfgs
504 : : !!***
505 : :
506 : : !!****f* ABINIT/pred_lbfgs
507 : : !! NAME
508 : : !! pred_lbfgs
509 : : !!
510 : : !! FUNCTION
511 : : !! Ionmov predictors (22) Limited-memory Broyden-Fletcher-Goldfarb-Shanno
512 : : !!
513 : : !! IONMOV 22:
514 : : !! Given a starting point xred that is a vector of length 3*natom
515 : : !! (reduced nuclei coordinates), and unit cell parameters
516 : : !! (acell and rprim) the L-Broyden-Fletcher-Goldfarb-Shanno
517 : : !! minimization is performed on the total energy function, using
518 : : !! its gradient (atomic forces and stress : gred or fcart and
519 : : !! stress) as calculated by the routine scfcv. Some atoms can be
520 : : !! kept fixed, while the optimization of unit cell parameters is
521 : : !! only performed if optcell/=0. The convergence requirement on
522 : : !! the atomic forces, dtset%tolmxf, allows an early exit.
523 : : !! Otherwise no more than dtset%ntime steps are performed.
524 : : !! Returned quantities are xred, and eventually acell and rprim (new ones!).
525 : : !! Could see MinPack on netlib.org
526 : : !!
527 : : !! INPUTS
528 : : !! ab_mover <type(abimover)> : Datatype with all the information needed by the preditor
529 : : !! itime : Index of the present iteration
530 : : !! ntime : Maximal number of iterations
531 : : !! ionmov : (22) Specific kind of BFGS
532 : : !! zDEBUG : if true print some debugging information
533 : : !!
534 : : !! OUTPUT
535 : : !!
536 : : !! SIDE EFFECTS
537 : : !! hist <type(abihist)> : History of positions,forces acell, rprimd, stresses
538 : : !!
539 : : !! SOURCE
540 : :
541 : 12 : subroutine pred_lbfgs(ab_mover,ab_xfh,forstr,hist,ionmov,itime,zDEBUG,iexit)
542 : :
543 : : !Arguments ------------------------------------
544 : : !scalars
545 : : type(abimover),intent(in) :: ab_mover
546 : : type(ab_xfh_type),intent(inout) :: ab_xfh
547 : : type(abihist),intent(inout) :: hist
548 : : type(abiforstr),intent(in) :: forstr
549 : : integer,intent(in) :: itime
550 : : integer,intent(in) :: ionmov
551 : : integer,intent(in) :: iexit
552 : : logical,intent(in) :: zDEBUG
553 : : character(len=500) :: ionmov22_errmsg
554 : :
555 : : !Local variables-------------------------------
556 : : !scalars
557 : : integer :: info,ihist_prev
558 : : integer :: ndim,cycl_main
559 : : integer, parameter :: npul=0
560 : : integer :: ii,jj,kk
561 : : real(dp),save :: ucvol0
562 : : real(dp) :: ucvol
563 : : real(dp) :: etotal
564 : : real(dp) :: favg
565 : :
566 : : !arrays
567 : 12 : real(dp),allocatable :: diag(:)
568 : : real(dp),allocatable,save :: hessin(:,:),vin(:),vin_prev(:)
569 : : real(dp),allocatable,save :: vout(:),vout_prev(:)
570 : : real(dp),allocatable,save ::vinres(:,:),vin1(:,:)
571 : : real(dp),save :: acell0(3) ! Initial acell
572 : : real(dp),save :: rprimd0(3,3) ! Initial rprimd
573 : : real(dp) :: acell(3)
574 : : real(dp) :: rprimd(3,3),rprim(3,3)
575 : : real(dp) :: gprimd(3,3)
576 : : real(dp) :: gmet(3,3)
577 : : real(dp) :: rmet(3,3)
578 : 24 : real(dp) :: residual(3,ab_mover%natom),residual_corrected(3,ab_mover%natom)
579 : 12 : real(dp) :: xred(3,ab_mover%natom)
580 : : real(dp) :: strten(6)
581 : :
582 : : !***************************************************************************
583 : : !Beginning of executable session
584 : : !***************************************************************************
585 : :
586 [ + + ]: 12 : if(iexit/=0)then
587 : 1 : call lbfgs_destroy()
588 [ + - ]: 1 : ABI_SFREE(vin)
589 [ + - ]: 1 : ABI_SFREE(vout)
590 [ + - ]: 1 : ABI_SFREE(vin_prev)
591 [ + - ]: 1 : ABI_SFREE(vout_prev)
592 [ - + ]: 1 : ABI_SFREE(vinres)
593 [ - + ]: 1 : ABI_SFREE(vin1)
594 [ + - ]: 1 : ABI_SFREE(hessin)
595 : : return
596 : : end if
597 : :
598 : : !write(std_out,*) 'bfgs 01'
599 : : !##########################################################
600 : : !### 01. Debugging and Verbose
601 : :
602 [ - + ]: 11 : if(zDEBUG)then
603 [ # # # # : 0 : write(std_out,'(a,3a,35a,42a)') ch10,('-',kk=1,3),'Debugging and Verbose for pred_bfgs',('-',kk=1,42)
# # # # ]
604 : 0 : write(std_out,*) 'ionmov: ',ionmov
605 : 0 : write(std_out,*) 'itime: ',itime
606 : : end if
607 : :
608 : : !write(std_out,*) 'bfgs 02'
609 : : !##########################################################
610 : : !### 02. Compute the dimension of vectors (ndim)
611 : :
612 : 11 : ndim=3*ab_mover%natom
613 [ - + ]: 11 : if(ab_mover%optcell==1) ndim=ndim+1
614 [ - + ]: 11 : if(ab_mover%optcell==2 .or.&
615 : 0 : & ab_mover%optcell==3) ndim=ndim+6
616 [ - + ]: 11 : if(ab_mover%optcell>=4) ndim=ndim+3
617 : :
618 [ - + ]: 11 : if(zDEBUG) write(std_out,*) 'Dimension of vin, vout and hessian (ndim): ',ndim
619 : :
620 : : !write(std_out,*) 'bfgs 03'
621 : : !##########################################################
622 : : !### 03. Allocate the vectors vin, vout and hessian matrix
623 : :
624 : : !Notice that vin, vout, etc could be allocated
625 : : !From a previous dataset with a different ndim
626 [ + + ]: 11 : if(itime==1)then
627 [ - + ]: 1 : ABI_SFREE(vin)
628 [ - + ]: 1 : ABI_SFREE(vout)
629 [ - + ]: 1 : ABI_SFREE(vin_prev)
630 [ - + ]: 1 : ABI_SFREE(vout_prev)
631 [ - + ]: 1 : ABI_SFREE(vinres)
632 [ - + ]: 1 : ABI_SFREE(vin1)
633 [ - + ]: 1 : ABI_SFREE(hessin)
634 : : if(npul>1) then
635 : : ABI_MALLOC(vinres,(npul+1,ndim))
636 : : ABI_MALLOC(vin1,(npul+1,ndim))
637 : : end if
638 [ - + + - : 3 : ABI_MALLOC(vin,(ndim))
+ - + - -
+ - + -
+ ]
639 [ - + + - : 2 : ABI_MALLOC(vout,(ndim))
- + - + -
+ ]
640 [ - + + - : 2 : ABI_MALLOC(vin_prev,(ndim))
- + - + -
+ ]
641 [ - + + - : 2 : ABI_MALLOC(vout_prev,(ndim))
- + - + -
+ ]
642 [ - + + - : 4 : ABI_MALLOC(hessin,(ndim,ndim))
- + + - +
- + - - +
- + - + ]
643 : : end if
644 : :
645 : : !write(std_out,*) 'bfgs 04'
646 : : !##########################################################
647 : : !### 04. Obtain the present values from the history
648 : :
649 : 11 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
650 [ + + ]: 44 : do ii=1,3
651 [ + + ]: 143 : rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
652 : : end do
653 : :
654 [ + + ]: 77 : strten(:)=hist%strten(:,hist%ihist)
655 : 11 : etotal =hist%etot(hist%ihist)
656 : :
657 : : !Fill the residual with forces (No preconditioning)
658 : : !Or the preconditioned forces
659 [ + - ]: 11 : if (ab_mover%goprecon==0)then
660 : 11 : call fcart2gred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
661 : : else
662 [ # # # # ]: 0 : residual(:,:)= forstr%gred(:,:)
663 : : end if
664 : :
665 [ - + ]: 11 : if(zDEBUG)then
666 : 0 : write (std_out,*) 'residual:'
667 [ # # ]: 0 : do kk=1,ab_mover%natom
668 : 0 : write (std_out,*) residual(:,kk)
669 : : end do
670 : 0 : write (std_out,*) 'strten:'
671 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
672 : 0 : write (std_out,*) 'etotal:'
673 : 0 : write (std_out,*) etotal
674 : : end if
675 : :
676 : 11 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
677 : :
678 : : !Save initial values
679 [ + + ]: 11 : if (itime==1)then
680 : 1 : acell0(:)=acell(:)
681 : 1 : rprimd0(:,:)=rprimd(:,:)
682 : 1 : ucvol0=ucvol
683 : : end if
684 : :
685 : : !zDEBUG (UCVOL)
686 [ - + ]: 11 : if(zDEBUG)then
687 : 0 : write(std_out,*) 'Volume of cell (ucvol):',ucvol
688 : : end if
689 : :
690 : : !Get rid of mean force on whole unit cell, but only if no
691 : : !generalized constraints are in effect
692 [ + + + + ]: 407 : residual_corrected(:,:)=residual(:,:)
693 [ + - ]: 11 : if(ab_mover%nconeq==0)then
694 [ + + ]: 44 : do ii=1,3
695 [ + + + - ]: 44 : if (ii/=3.or.ab_mover%jellslab==0) then
696 [ + + ]: 330 : favg=sum(residual_corrected(ii,:))/dble(ab_mover%natom)
697 [ + + ]: 330 : residual_corrected(ii,:)=residual_corrected(ii,:)-favg
698 : : end if
699 : : end do
700 : : end if
701 : :
702 : : !write(std_out,*) 'bfgs 05'
703 : : !##########################################################
704 : : !### 05. Fill the vectors vin and vout
705 : :
706 : : !Initialize input vectors : first vin, then vout
707 : : !The values of vin from the previous iteration
708 : : !should be the same
709 : : !if (itime==1)then
710 : : call xfpack_x2vin(acell, ab_mover%natom, ndim,&
711 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
712 [ + - - - : 11 : & ab_mover%symrel, ucvol, ucvol0, vin, xred)
- - - - -
- - + ]
713 : : !end if
714 : :
715 : : call xfpack_f2vout(residual_corrected, ab_mover%natom, ndim,&
716 : : & ab_mover%optcell, ab_mover%strtarget, strten, ucvol,&
717 [ + - - - : 11 : & vout)
- - - + ]
718 : :
719 : : !write(std_out,*) 'bfgs 06'
720 : : !##########################################################
721 : : !### 06. Initialize or update the hessian matrix
722 : :
723 : : !Initialise the Hessian matrix using gmet
724 [ + + ]: 11 : if (itime==1)then
725 : :
726 [ - + + - : 3 : ABI_MALLOC(diag,(ndim))
+ - + - -
+ - + ]
727 [ + + ]: 28 : do ii=1,3*ab_mover%natom
728 : : !diag(ii) = 1.00_dp / rprimd(MODULO(ii-1,3)+1,MODULO(ii-1,3)+1)**2
729 : 28 : diag(ii) = gmet(MODULO(ii-1,3)+1,MODULO(ii-1,3)+1)
730 : : end do
731 [ - + ]: 1 : if(ab_mover%optcell/=0)then
732 : : ! These values might lead to too large changes in some cases ...
733 [ # # ]: 0 : do ii=3*ab_mover%natom+1,ndim
734 : 0 : diag(ii) = ab_mover%strprecon*30.0_dp/ucvol
735 [ # # ]: 0 : if(ab_mover%optcell==1) diag(ii) = diag(ii) / three
736 : : end do
737 : : end if
738 : :
739 : : !call lbfgs_destroy()
740 : 1 : call lbfgs_init(ndim,5,diag)
741 [ - + ]: 1 : ABI_FREE(diag)
742 : :
743 [ - + ]: 1 : if (ab_mover%restartxf/=0) then
744 : :
745 : : call xfh_recover_new(ab_xfh,ab_mover,acell,cycl_main,residual,&
746 : : hessin,ndim,rprim,rprimd0,strten,ucvol,ucvol0,vin,&
747 : 0 : vin_prev,vout,vout_prev,xred)
748 : :
749 : : end if
750 : :
751 : : end if
752 : :
753 : : !zDEBUG (vin,vout and hessin before prediction)
754 [ - + ]: 11 : if(zDEBUG)then
755 : 0 : write(std_out,*) 'Vectors vin and vout and inverse of Hessian (hessin) [before]'
756 : 0 : write(std_out,*) 'vin:'
757 [ # # # # ]: 0 : do ii=1,ndim,3
758 [ # # ]: 0 : if (ii+2<=ndim)then
759 : 0 : write(std_out,*) ii,vin(ii:ii+2)
760 : : else
761 : 0 : write(std_out,*) ii,vin(ii:ndim)
762 : : end if
763 : : end do
764 : 0 : write(std_out,*) 'vout:'
765 [ # # # # ]: 0 : do ii=1,ndim,3
766 [ # # ]: 0 : if (ii+2<=ndim)then
767 : 0 : write(std_out,*) ii,vout(ii:ii+2)
768 : : else
769 : 0 : write(std_out,*) ii,vout(ii:ndim)
770 : : end if
771 : : end do
772 : 0 : write(std_out,*) 'Inverse Hessian (hessin): ',ndim,'x',ndim
773 [ # # ]: 0 : do kk=1,ndim
774 [ # # # # ]: 0 : do jj=1,ndim,3
775 [ # # ]: 0 : if (jj+2<=ndim)then
776 : 0 : write(std_out,*) jj,hessin(jj:jj+2,kk)
777 : : else
778 : 0 : write(std_out,*) jj,hessin(jj:ndim,kk)
779 : : end if
780 : : end do
781 : : end do
782 : : end if
783 : :
784 : : !write(std_out,*) 'bfgs 07'
785 : : !##########################################################
786 : : !### 07. Compute the next values
787 : :
788 [ + + ]: 308 : vin_prev(:) = vin
789 [ + + ]: 308 : vout_prev(:) = vout
790 : 11 : info = lbfgs_execute(vin,etotal,vout)
791 : :
792 [ - + ]: 11 : if (info /= -1) then
793 : : write (ionmov22_errmsg, '(a,i0,3a)') &
794 : 0 : 'Lbfgs routine failed. Returned value: ', info,ch10, &
795 : 0 : 'Restart your calculation from last step or try a different ionmov'
796 : 0 : ABI_ERROR_CLASS(ionmov22_errmsg, "Ionmov22Error")
797 : : end if
798 : :
799 : : !zDEBUG (vin,vout after prediction)
800 [ - + ]: 11 : if(zDEBUG)then
801 : 0 : write(std_out,*) 'Vectors vin and vout [after prediction]'
802 : 0 : write(std_out,*) 'vin_prev:'
803 [ # # # # ]: 0 : do ii=1,ndim,3
804 [ # # ]: 0 : if (ii+2<=ndim)then
805 : 0 : write(std_out,*) ii,vin_prev(ii:ii+2)
806 : : else
807 : 0 : write(std_out,*) ii,vin_prev(ii:ndim)
808 : : end if
809 : : end do
810 : 0 : write(std_out,*) 'vin:'
811 [ # # # # ]: 0 : do ii=1,ndim,3
812 [ # # ]: 0 : if (ii+2<=ndim)then
813 : 0 : write(std_out,*) ii,vin(ii:ii+2)
814 : : else
815 : 0 : write(std_out,*) ii,vin(ii:ndim)
816 : : end if
817 : : end do
818 : 0 : write(std_out,*) 'vout:'
819 [ # # # # ]: 0 : do ii=1,ndim,3
820 [ # # ]: 0 : if (ii+2<=ndim)then
821 : 0 : write(std_out,*) ii,vout(ii:ii+2)
822 : : else
823 : 0 : write(std_out,*) ii,vout(ii:ndim)
824 : : end if
825 : : end do
826 : : end if
827 : :
828 : :
829 : : !Implement fixing of atoms : put back old values for fixed
830 : : !components
831 [ + + ]: 110 : do kk=1,ab_mover%natom
832 [ + + ]: 407 : do jj=1,3
833 : : ! Warning : implemented in reduced coordinates
834 [ - + ]: 396 : if ( ab_mover%iatfix(jj,kk)==1) then
835 : 0 : vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
836 : : end if
837 : : end do
838 : : end do
839 : :
840 : :
841 : : !write(std_out,*) 'bfgs 08'
842 : : !##########################################################
843 : : !### 08. Update the history with the prediction
844 : :
845 : : !Increase indexes
846 : 11 : hist%ihist = abihist_findIndex(hist,+1)
847 : :
848 : : !Transfer vin to xred, acell and rprim
849 : : call xfpack_vin2x(acell, acell0, ab_mover%natom, ndim,&
850 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
851 : : & ab_mover%symrel, ucvol, ucvol0,&
852 [ + - - - : 11 : & vin, xred)
- - - - -
- - + ]
853 : :
854 [ - + ]: 11 : if(ab_mover%optcell/=0)then
855 : 0 : call mkrdim(acell,rprim,rprimd)
856 : 0 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
857 : : end if
858 : :
859 : : !Fill the history with the variables
860 : : !xcart, xred, acell, rprimd
861 : 11 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
862 : 11 : ihist_prev = abihist_findIndex(hist,-1)
863 [ + + + + ]: 407 : hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
864 : :
865 [ - + ]: 11 : if(zDEBUG)then
866 : 0 : write (std_out,*) 'residual:'
867 [ # # ]: 0 : do kk=1,ab_mover%natom
868 : 0 : write (std_out,*) residual(:,kk)
869 : : end do
870 : 0 : write (std_out,*) 'strten:'
871 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
872 : 0 : write (std_out,*) 'etotal:'
873 : 0 : write (std_out,*) etotal
874 : : end if
875 : :
876 : : end subroutine pred_lbfgs
877 : : !!***
878 : :
879 [ - + ]: 691 : end module m_pred_bfgs
880 : : !!***
|