Branch data Line data Source code
1 : : !!****m* ABINIT/m_pred_fire
2 : : !! NAME
3 : : !! m_pred_fire
4 : : !!
5 : : !! FUNCTION
6 : : !! Ionmov predictors (15) FIRE algorithm
7 : : !! The fast inertial relaxation engine (FIRE) method for relaxation.
8 : : !! The method is described in Erik Bitzek, Pekka Koskinen, Franz G"ahler,
9 : : !! Michael Moseler, and Peter Gumbsch, Phys. Rev. Lett. 97, 170201 [[cite:Bitzek2006]]
10 : : !!
11 : : !! COPYRIGHT
12 : : !! Copyright (C) 1998-2026 ABINIT group (hexu)
13 : : !! This file is distributed under the terms of the
14 : : !! GNU General Public License, see ~abinit/COPYING
15 : : !! or http://www.gnu.org/copyleft/gpl.txt .
16 : : !!
17 : : !! SOURCE
18 : :
19 : : #if defined HAVE_CONFIG_H
20 : : #include "config.h"
21 : : #endif
22 : :
23 : : #include "abi_common.h"
24 : :
25 : : module m_pred_fire
26 : : use defs_basis
27 : : use m_abicore
28 : : use m_abimover
29 : : use m_abihist
30 : : use m_xfpack
31 : : use m_geometry, only : mkrdim, fcart2gred, metric, xred2xcart
32 : : use m_errors, only: unused_var
33 : :
34 : : implicit none
35 : :
36 : : private
37 : :
38 : : public :: pred_fire
39 : :
40 : : contains
41 : :
42 : : !!***
43 : :
44 : : !!****f* m_pred_fire/pred_fire
45 : : !! NAME
46 : : !! pred_fire
47 : : !!
48 : : !! FUNCTION
49 : : !!
50 : : !! IONMOV 15:
51 : : !! Given a starting point xred that is a vector of length 3*natom
52 : : !! (reduced nuclei coordinates), a velocity vector (in cartesian
53 : : !! coordinates), and unit cell parameters (acell and rprimd -
54 : : !! without velocities in the present implementation), the Verlet
55 : : !! dynamics is performed, using the gradient of the energy
56 : : !! (atomic forces and stresses) as calculated by the routine scfcv.
57 : : !!
58 : : !! At each step, the dot product of velocity and force is calculated.
59 : : !! If the v.dot.f is positive for min_downhill consecutive steps, the
60 : : !! time step dtion is increased by dtinc until it reaches dtmax. If
61 : : !! v.dot.f is negative, dtion is mulitiplied by dtdec.
62 : : !!
63 : : !! Some atoms can be kept fixed, while the propagation of unit cell
64 : : !! parameters is only performed if optcell/=0.
65 : : !! No more than ab_mover%ntime steps are performed.
66 : : !! The time step is governed by dtion, contained in ab_mover
67 : : !! (coming from dtset).
68 : : !! Returned quantities are xred, and eventually acell and rprimd
69 : : !! (new ones!).
70 : : !!
71 : :
72 : : !! INPUTS
73 : : !! ab_mover <type(abimover)> : Datatype with all the information
74 : : !! needed by the preditor
75 : : !! itime : Index of the present iteration
76 : : !! ntime : Maximal number of iterations
77 : : !! ionmov : (15) FIRE. Not used in function. just to keep the same format as bfgs.
78 : : !! zDEBUG : if true print some debugging information
79 : : !!
80 : : !! OUTPUT
81 : : !!
82 : : !! SIDE EFFECTS
83 : : !! hist <type(abihist)> : History of positions,forces
84 : : !! acell, rprimd, stresses
85 : : !!
86 : : !! SOURCE
87 : 12 : subroutine pred_fire(ab_mover, ab_xfh,forstr,hist,ionmov,itime,zDEBUG,iexit)
88 : :
89 : : !Arguments ------------------------------------
90 : : !scalars
91 : : type(abimover),intent(in) :: ab_mover
92 : : type(ab_xfh_type),intent(inout) :: ab_xfh
93 : : type(abiforstr),intent(in) :: forstr
94 : : type(abihist),intent(inout) :: hist
95 : : integer, intent(in) :: ionmov
96 : : integer,intent(in) :: itime
97 : : integer,intent(in) :: iexit
98 : : logical,intent(in) :: zDEBUG
99 : :
100 : :
101 : : !Local variables-------------------------------
102 : : !scalars
103 : : integer :: ihist,ihist_prev,ndim
104 : : integer, parameter :: min_downhill=4
105 : : integer :: ii,jj,kk
106 : : real(dp),save :: ucvol0
107 : : real(dp) :: ucvol
108 : : real(dp) :: etotal,etotal_prev
109 : : real(dp) :: favg
110 : : ! time step, damping factor initially dtion
111 : : real(dp),save :: dtratio, alpha
112 : : ! dtinc: increment of dtratio
113 : : ! dtdec: decrement of dtratio
114 : : ! dtmax: maximum allowd value of dtratio
115 : : ! alphadec: decrement of alpha
116 : : ! alpha0: initial value of alpha
117 : : ! mixold: if energy goes up, linear mix old and new coordinates. mixold
118 : : real(dp), parameter :: dtinc=1.1, dtdec=0.5, dtmax=10.0
119 : : real(dp), parameter :: alphadec=0.99, alpha0=0.2, mixold=0.3
120 : : ! v.dot.f
121 : : real(dp) :: vf
122 : : ! number of v.dot.f >0
123 : : integer, save :: ndownhill
124 : : ! reset_lattice: whether to reset lattice if energy goes up.
125 : : logical, parameter :: reset_lattice = .true.
126 : :
127 : : !arrays
128 : : real(dp) :: gprimd(3,3)
129 : : real(dp) :: gmet(3,3)
130 : : real(dp) :: rmet(3,3)
131 : 24 : real(dp) :: fcart(3, ab_mover%natom)
132 : : real(dp) :: acell(3),strten(6), acell0(3)
133 : : real(dp) :: rprim(3,3),rprimd(3,3), rprimd0(3,3)
134 : 24 : real(dp) :: xred(3,ab_mover%natom),xcart(3,ab_mover%natom)
135 : : ! velocity are saved
136 : 24 : real(dp) :: vel(3,ab_mover%natom)
137 : 12 : real(dp) :: residual(3,ab_mover%natom),residual_corrected(3,ab_mover%natom)
138 : : real(dp),allocatable, save :: vin(:), vout(:)
139 : : real(dp), allocatable, save:: vin_prev(:)
140 : : ! velocity but correspoing to vin&vout, for ion&cell relaxation
141 : : real(dp),allocatable,save :: vel_ioncell(:)
142 : :
143 : : ABI_UNUSED((/ionmov, ab_xfh%mxfh/))
144 : :
145 : : !***************************************************************************
146 : : !Beginning of executable session
147 : : !***************************************************************************
148 : :
149 [ + + ]: 12 : if(iexit/=0)then
150 [ + - ]: 1 : ABI_SFREE(vin)
151 [ + - ]: 1 : ABI_SFREE(vout)
152 [ + - ]: 1 : ABI_SFREE(vin_prev)
153 [ + - ]: 1 : ABI_SFREE(vel_ioncell)
154 : : return
155 : : end if
156 : :
157 : 11 : write(std_out,*) 'FIRE 01'
158 : : !##########################################################
159 : : !### 01. Compute the dimension of vectors (ndim)
160 : :
161 : 11 : ndim=3*ab_mover%natom
162 [ - + ]: 11 : if(ab_mover%optcell==1) ndim=ndim+1
163 [ - + ]: 11 : if(ab_mover%optcell==2 .or.&
164 : 0 : & ab_mover%optcell==3) ndim=ndim+6
165 [ - + ]: 11 : if(ab_mover%optcell>=4) ndim=ndim+3
166 : :
167 : 11 : write(std_out,*) 'FIRE: ndim=', ndim
168 : 11 : write(std_out,*) 'FIRE 02'
169 : : !##########################################################
170 : : !### 02. Allocate the vectors vin
171 : :
172 : : !Notice that vin, vout, etc could be allocated
173 : : !From a previous dataset with a different ndim
174 [ + + ]: 11 : if(itime==1)then
175 [ - + ]: 1 : ABI_SFREE(vin)
176 [ - + ]: 1 : ABI_SFREE(vout)
177 [ - + ]: 1 : ABI_SFREE(vin_prev)
178 [ - + ]: 1 : ABI_SFREE(vel_ioncell)
179 : :
180 [ - + + - : 3 : ABI_MALLOC(vin,(ndim))
+ - + - -
+ - + -
+ ]
181 [ - + + - : 2 : ABI_MALLOC(vout,(ndim))
- + - + -
+ ]
182 [ - + + - : 2 : ABI_MALLOC(vin_prev,(ndim))
- + - + -
+ ]
183 [ - + + - : 2 : ABI_MALLOC(vel_ioncell,(ndim))
- + - + -
+ ]
184 [ + + ]: 28 : vel_ioncell(:)=0.0
185 : : end if
186 : :
187 : 11 : write(std_out,*) 'FIRE 03'
188 : : !##########################################################
189 : : !### 03. Obtain the present values from the history
190 : :
191 : 11 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
192 : :
193 : 11 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
194 : :
195 [ + + ]: 44 : do ii=1,3
196 [ + + ]: 143 : rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
197 : : end do
198 : :
199 : 11 : ihist = abihist_findIndex(hist, 0)
200 : 11 : ihist_prev = abihist_findIndex(hist,-1)
201 : :
202 : 11 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
203 [ + + + + ]: 407 : fcart(:,:) =hist%fcart(:,:,hist%ihist)
204 [ + + ]: 77 : strten(:) =hist%strten(:,hist%ihist)
205 : 11 : etotal=hist%etot(hist%ihist)
206 : :
207 [ + + ]: 11 : if(itime==1) then
208 : : etotal_prev=0.0
209 : : else
210 : 10 : etotal_prev=hist%etot(ihist_prev)
211 : : endif
212 : :
213 : : !Fill the residual with forces (No preconditioning)
214 : : !Or the preconditioned forces
215 [ + - ]: 11 : if (ab_mover%goprecon==0)then
216 : 11 : call fcart2gred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
217 : : else
218 [ # # # # ]: 0 : residual(:,:)=forstr%gred(:,:)
219 : : end if
220 : :
221 : : !Save initial values
222 [ + + ]: 11 : if (itime==1)then
223 : 1 : acell0(:)=acell(:)
224 : 1 : rprimd0(:,:)=rprimd(:,:)
225 : 1 : ucvol0=ucvol
226 : : end if
227 : :
228 : :
229 [ - + ]: 11 : if(zDEBUG)then
230 : 0 : write (std_out,*) 'fcart:'
231 [ # # ]: 0 : do kk=1,ab_mover%natom
232 : 0 : write (std_out,*) fcart(:,kk)
233 : : end do
234 : 0 : write (std_out,*) 'vel:'
235 [ # # ]: 0 : do kk=1,ab_mover%natom
236 : 0 : write (std_out,*) vel(:,kk)
237 : : end do
238 : 0 : write (std_out,*) 'strten:'
239 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
240 : 0 : write (std_out,*) 'etotal:'
241 : 0 : write (std_out,*) etotal
242 : : end if
243 : :
244 : : !Get rid of mean force on whole unit cell, but only if no
245 : : !generalized constraints are in effect
246 : :
247 [ + + + + ]: 407 : residual_corrected(:,:)=residual(:,:)
248 [ + - ]: 11 : if(ab_mover%nconeq==0)then
249 [ + + ]: 44 : do kk=1,3
250 [ + + + - ]: 44 : if (kk/=3.or.ab_mover%jellslab==0) then
251 [ + + ]: 330 : favg=sum(residual_corrected(kk,:))/dble(ab_mover%natom)
252 [ + + ]: 330 : residual_corrected(kk,:)=residual_corrected(kk,:)-favg
253 : : end if
254 : : end do
255 : : end if
256 : :
257 : 11 : write(std_out,*) 'FIRE 04'
258 : : !##########################################################
259 : : !### 04. Fill the vectors vin and vout
260 : :
261 : : !Initialize input vectors : first vin, then vout
262 : : ! transfer xred, acell, and rprim to vin
263 : : call xfpack_x2vin(acell, ab_mover%natom, ndim,&
264 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
265 [ + - - - : 11 : & ab_mover%symrel, ucvol, ucvol0, vin, xred)
- - - - -
- - + ]
266 : : !end if
267 : :
268 : : !transfer gred and strten to vout.
269 : : !Note: gred is not f in reduced co.
270 : : !but dE/dx
271 : :
272 : : call xfpack_f2vout(residual_corrected, ab_mover%natom, ndim,&
273 : : & ab_mover%optcell, ab_mover%strtarget, strten, ucvol,&
274 [ + - - - : 11 : & vout)
- - - + ]
275 : : ! Now vout -> -dE/dx
276 [ + + ]: 308 : vout(:) = -1.0*vout(:)
277 : :
278 : 11 : write(std_out,*) 'FIRE 05'
279 : : !##########################################################
280 : : !### 05. iniialize FIRE
281 [ + + ]: 11 : if ( itime==1 ) then
282 : 1 : ndownhill=0
283 : 1 : alpha=alpha0
284 [ + - ]: 1 : if (ab_mover%dtion>0)then
285 : 1 : dtratio = 1.0
286 : : end if
287 : : end if
288 : :
289 : 11 : write(std_out,*) 'FIRE 06'
290 : : !##########################################################
291 : : !### 06. update timestep
292 : : ! Note that vin & vout are in reduced coordinates.
293 [ + + ]: 308 : vf=sum(vel_ioncell*vout)
294 [ + + + - ]: 11 : if ( vf >= 0.0_dp .and. (etotal- etotal_prev <0.0_dp) ) then
295 : : !if ( vf >= 0.0_dp ) then
296 : 10 : ndownhill=ndownhill+1
297 : : ! mix v with the v projected on force vector.
298 : : vel_ioncell(:)=(1.0-alpha)*vel_ioncell(:) + alpha* vout * &
299 [ + + + + : 820 : & sqrt(sum(vel_ioncell*vel_ioncell)/sum(vout*vout))
+ + ]
300 [ + + ]: 10 : if ( ndownhill>min_downhill ) then
301 : 2 : dtratio = min(dtratio * dtinc, dtmax)
302 : 2 : alpha = alpha * alphadec
303 : : end if
304 : : else
305 : : ! reset downhill counter, velocity, alpha. decrease dtratio.
306 : 1 : ndownhill=0
307 [ + + ]: 28 : vel_ioncell(:)=0.0
308 : 1 : alpha=alpha0
309 : 1 : dtratio = dtratio*dtdec
310 : : endif
311 : :
312 : 11 : write(std_out,*) 'FIRE 07'
313 : : !##########################################################
314 : : !### 07. MD step. update vel_ioncell
315 : :
316 : : ! Here mass is not used: all masses=1
317 : : !write(std_out,*) 'FIRE vin: ', vin
318 : : ! update v
319 [ - + + + ]: 319 : vel_ioncell = vel_ioncell + dtratio*ab_mover%dtion* vout
320 : : !write(std_out,*) 'FIRE vel: ', vel_ioncell
321 : : !write(std_out,*) 'FIRE delta x',dtratio*ab_mover%dtion* vel_ioncell
322 : : ! update x
323 [ - + + + ]: 319 : vin = vin + dtratio*ab_mover%dtion* vel_ioncell
324 : : !write(std_out,*) 'FIRE vin: ', vin
325 : :
326 : : ! write(std_out,*) 'FIRE vout: ', vout
327 : : ! write(std_out,*) 'FIRE vf: ', vf
328 : : ! write(std_out,*) 'FIRE etotal: ', etotal
329 : : ! write(std_out,*) 'FIRE etotal_prev: ', etotal_prev
330 : : ! write(std_out,*) 'FIRE deltaE: ',etotal-etotal_prev
331 : 11 : write(std_out,*) 'FIRE ndownhill: ', ndownhill
332 : : ! write(std_out,*) 'FIRE dtratio: ', dtratio
333 : : ! write(std_out,*) 'FIRE dtion: ', ab_mover%dtion
334 : :
335 : :
336 : : !Implement fixing of atoms : put back old values for fixed
337 : : !components
338 [ + + ]: 110 : do kk=1,ab_mover%natom
339 [ + + ]: 407 : do jj=1,3
340 : : ! Warning : implemented in reduced coordinates
341 [ - + ]: 396 : if ( ab_mover%iatfix(jj,kk)==1) then
342 : 0 : vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
343 : : end if
344 : : end do
345 : : end do
346 : :
347 : : ! reset_lattice to last step by a ratio if energy is increased.
348 : : ! disabled for debugging
349 [ - + ]: 11 : if ( etotal - etotal_prev >0.0 ) then
350 [ # # # # ]: 0 : vin= vin*(1-mixold)+vin_prev*mixold
351 : : end if
352 : :
353 : : ! only set vin to vin_prev when energy decreased, so it's
354 : : ! possible to go back.
355 : : ! if (etotal - etotal_prev <0.0 ) then
356 [ + + ]: 308 : vin_prev(:)=vin(:)
357 : : ! endif
358 : :
359 : :
360 : :
361 : : !##########################################################
362 : : !### 08. update hist.
363 : :
364 : : !Increase indexes
365 : 11 : hist%ihist = abihist_findIndex(hist,+1)
366 : : !Transfer vin to xred, acell and rprim
367 : : call xfpack_vin2x(acell, acell0, ab_mover%natom, ndim,&
368 : : & ab_mover%nsym, ab_mover%optcell, rprim, rprimd0,&
369 : : & ab_mover%symrel, ucvol, ucvol0,&
370 [ + - - - : 11 : & vin, xred)
- - - - -
- - + ]
371 : :
372 [ - + ]: 11 : if(ab_mover%optcell/=0)then
373 : 0 : call mkrdim(acell,rprim,rprimd)
374 : 0 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
375 : : end if
376 : :
377 : : !Fill the history with the variables
378 : : !xcart, xred, acell, rprimd
379 : 11 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
380 : 11 : ihist_prev = abihist_findIndex(hist,-1)
381 [ + + + + ]: 407 : hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
382 : :
383 [ - + ]: 11 : if(zDEBUG)then
384 : 0 : write (std_out,*) 'residual:'
385 [ # # ]: 0 : do kk=1,ab_mover%natom
386 : 0 : write (std_out,*) residual(:,kk)
387 : : end do
388 : 0 : write (std_out,*) 'strten:'
389 : 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
390 : 0 : write (std_out,*) 'etotal:'
391 : 0 : write (std_out,*) etotal
392 : : end if
393 : :
394 : :
395 : : end subroutine pred_fire
396 : : !!***
397 : :
398 : : end module m_pred_fire
399 : :
|