Line data Source code
1 : !!****m* ABINIT/m_pred_simple
2 : !! NAME
3 : !! m_pred_simple
4 : !!
5 : !! FUNCTION
6 : !!
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, JCC, SE)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! SOURCE
15 :
16 : #if defined HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #include "abi_common.h"
21 :
22 : module m_pred_simple
23 :
24 : use defs_basis
25 : use m_abicore
26 : use m_abimover
27 : use m_abihist
28 :
29 : use m_geometry, only : fcart2gred, xred2xcart
30 :
31 : implicit none
32 :
33 : private
34 : !!***
35 :
36 : public :: pred_simple
37 : public :: prec_simple
38 : !!***
39 :
40 : contains
41 : !!***
42 :
43 : !!****f* ABINIT/pred_simple
44 : !! NAME
45 : !! pred_simple
46 : !!
47 : !! FUNCTION
48 : !! Ionmov predictors (4 & 5) Internal to scfcv.
49 : !! Actually, this routine does nothing (only copy) as all operations are internal to scfcv ...
50 : !!
51 : !! IONMOV 4:
52 : !! Conjugate gradient algorithm for simultaneous optimization
53 : !! of potential and ionic degrees of freedom. It can be used with
54 : !! iscf=2 and iscf=5 or 6
55 : !!
56 : !! IONMOV 5:
57 : !! Simple relaxation of ionic positions according to (converged)
58 : !! forces. Equivalent to ionmov=1 with zero masses, albeit the
59 : !! relaxation coefficient is not vis, but iprcfc.
60 : !!
61 : !! INPUTS
62 : !! ab_mover <type(abimover)> : Datatype with all the information needed by the preditor
63 : !! zDEBUG : if true print some debugging information
64 : !!
65 : !! OUTPUT
66 : !!
67 : !! SIDE EFFECTS
68 : !! hist <type(abihist)> : History of positions,forces acell, rprimd, stresses
69 : !!
70 : !! SOURCE
71 :
72 35 : subroutine pred_simple(ab_mover,hist,iexit)
73 :
74 : !Arguments ------------------------------------
75 : !scalars
76 : type(abimover),intent(in) :: ab_mover
77 : type(abihist),intent(inout) :: hist
78 : integer,intent(in) :: iexit
79 :
80 : !Local variables-------------------------------
81 : !scalars
82 : integer :: ihist_next,kk
83 :
84 : !***************************************************************************
85 : !Beginning of executable session
86 : !***************************************************************************
87 :
88 35 : if(iexit/=0)then
89 : return
90 : end if
91 :
92 : !All the operations are internal to scfcv.F90
93 :
94 : !XRED, FCART and VEL
95 28 : ihist_next = abihist_findIndex(hist,+1)
96 96 : do kk = 1, ab_mover%natom
97 272 : hist%xred(:, kk, ihist_next) = hist%xred(:, kk, hist%ihist)
98 272 : hist%fcart(:, kk, ihist_next) = hist%fcart(:, kk, hist%ihist)
99 300 : hist%vel(:, kk, ihist_next) = hist%vel(:, kk, hist%ihist)
100 : end do
101 :
102 : !ACELL
103 112 : hist%acell(1:3,ihist_next)=hist%acell(1:3,hist%ihist)
104 :
105 : !RPRIMD
106 112 : do kk=1,3
107 364 : hist%rprimd(1:3,kk,ihist_next)=hist%rprimd(1:3,kk,hist%ihist)
108 : end do
109 :
110 28 : hist%ihist=ihist_next
111 :
112 : end subroutine pred_simple
113 : !!***
114 :
115 : !!****f* ABINIT/prec_simple
116 : !! NAME
117 : !! prec_simple
118 : !!
119 : !! FUNCTION
120 : !! Simple preconditioner, compute the force constant matrix
121 : !! using the Badger's rule:
122 : !!
123 : !! F=A/(r-B)^3
124 : !!
125 : !! INPUTS
126 : !! ab_mover <type(abimover)> : Datatype with all the information needed by the preconditioner
127 : !! zDEBUG : if true print some debugging information
128 : !!
129 : !! OUTPUT
130 : !!
131 : !! SIDE EFFECTS
132 : !! hist <type(abihist)> : History of positions,forces acell, rprimd, stresses
133 : !!
134 : !! SOURCE
135 :
136 440 : subroutine prec_simple(ab_mover,forstr,hist,icycle,itime,iexit)
137 :
138 : use m_linalg_interfaces
139 :
140 : !Arguments ------------------------------------
141 : !scalars
142 : integer,intent(in) :: iexit,itime,icycle
143 : type(abimover),intent(in) :: ab_mover
144 : type(abihist),intent(in) :: hist
145 : type(abiforstr),intent(inout) :: forstr
146 :
147 : !Local variables-------------------------------
148 : !scalars
149 : integer :: period,ii,jj,index,kk,ksub,jsub
150 : integer :: info,lwork,new_order_forces
151 : real(dp) :: Z,badgerfactor,lambda,sigma,val_rms
152 : integer,save :: order_forces
153 : logical :: Compute_Matrix
154 : !arrays
155 440 : type(go_bonds) :: bonds
156 440 : integer,allocatable :: periods(:,:)
157 440 : integer,allocatable :: iatoms(:,:)
158 880 : integer :: ipiv(3*ab_mover%natom)
159 880 : real(dp) :: xcart(3,ab_mover%natom)
160 880 : real(dp) :: fcart(3,ab_mover%natom)
161 440 : real(dp) :: B(3*ab_mover%natom)
162 : real(dp) :: rprimd(3,3)
163 880 : real(dp) :: w(3*ab_mover%natom)
164 440 : real(dp),allocatable :: matrix_tmp(:,:)
165 440 : real(dp),allocatable :: work(:)
166 : real(dp) :: badger(6,6)
167 : real(dp),allocatable,save :: matrix(:,:)
168 : character(len=18) :: fmt
169 :
170 : !***************************************************************************
171 : !Beginning of executable session
172 : !***************************************************************************
173 :
174 440 : if (iexit/=0)then
175 405 : if(allocated(matrix))then
176 6 : ABI_FREE(matrix)
177 : endif
178 405 : return
179 : end if
180 :
181 : !##########################################################
182 : !### 01. Show the Precondition parameters, set the badger
183 : !### matrix.
184 :
185 35 : write(std_out,*) 'Precondition option',ab_mover%goprecon
186 140 : write(std_out,*) 'Precondition parameters',ab_mover%goprecprm
187 35 : lambda=ab_mover%goprecprm(1)
188 :
189 : badger(:,:)=reshape( (/ -0.2573, 0.3401, 0.6937, 0.7126, 0.8335, 0.9491,&
190 : & 0.3401, 0.9652, 1.2843, 1.4725, 1.6549, 1.7190,&
191 : & 0.6937, 1.2843, 1.6925, 1.8238, 2.1164, 2.3185,&
192 : & 0.7126, 1.4725, 1.8238, 2.0203, 2.2137, 2.5206,&
193 : & 0.8335, 1.6549, 2.1164, 2.2137, 2.3718, 2.5110,&
194 35 : & 0.9491, 1.7190, 2.3185, 2.5206, 2.5110, 0.0000 /), (/ 6, 6/) )
195 :
196 35 : write(fmt,'(a1,i4,a5)') '(',3*ab_mover%natom,'f8.3)'
197 :
198 : !##########################################################
199 : !### 02. Take the coordinates and cell parameters from HIST
200 :
201 455 : rprimd(:,:)=hist%rprimd(:,:,hist%ihist)
202 315 : fcart(:,:)=hist%fcart(:,:,hist%ihist)
203 35 : call xred2xcart(ab_mover%natom,rprimd,xcart,hist%xred(:,:,hist%ihist))
204 :
205 : !##########################################################
206 : !### 03. Decide based on kind of preconditioner if
207 : !### a new matrix should be computed
208 :
209 35 : new_order_forces = one ! This to avoid using unitialized variables.
210 :
211 35 : if (ab_mover%goprecon==2)then
212 :
213 0 : val_rms=0.0
214 0 : do kk=1,ab_mover%natom
215 0 : do jj=1,3
216 0 : val_rms=val_rms+fcart(jj,kk)**2
217 : end do
218 : end do
219 0 : val_rms=sqrt(val_rms/dble(ab_mover%natom))
220 0 : new_order_forces=int(log(val_rms)/log(10.0))
221 : end if
222 :
223 35 : if (itime==1.and.icycle==1)then
224 6 : Compute_Matrix=.TRUE.
225 6 : order_forces=new_order_forces
226 6 : if (allocated(matrix)) then
227 0 : ABI_FREE(matrix)
228 : end if
229 :
230 24 : ABI_MALLOC(matrix,(3*ab_mover%natom,3*ab_mover%natom))
231 : else
232 29 : Compute_Matrix=.FALSE.
233 29 : if ((ab_mover%goprecon==2).and.(order_forces.gt.new_order_forces)) then
234 0 : Compute_Matrix=.TRUE.
235 0 : order_forces=new_order_forces
236 : end if
237 29 : if (ab_mover%goprecon==3) Compute_Matrix=.TRUE.
238 : end if
239 :
240 : !##########################################################
241 : !### 04. Compute a new precondition matrix if required
242 :
243 29 : if (Compute_Matrix)then
244 :
245 : ! Fix the tolerance for create a bond
246 6 : bonds%tolerance=1.35
247 6 : bonds%nbonds=1
248 :
249 : ! Allocate the arrays with exactly the rigth nbonds
250 6 : ABI_MALLOC(bonds%bond_vect,(3,bonds%nbonds))
251 6 : ABI_MALLOC(bonds%bond_length,(bonds%nbonds))
252 18 : ABI_MALLOC(bonds%indexi,(ab_mover%natom,bonds%nbonds))
253 18 : ABI_MALLOC(bonds%nbondi,(ab_mover%natom))
254 :
255 : ! Compute the bonds
256 : call make_bonds_new(bonds,ab_mover%natom,ab_mover%ntypat,rprimd,&
257 6 : & ab_mover%typat,xcart,ab_mover%znucl)
258 :
259 384 : write(std_out,'(a,a,63a,a)') ch10,'---PRECONDITIONER',('-',kk=1,63),ch10
260 :
261 : ! For all bonds detect wich atoms are involved
262 : ! and wich period they coprrespond in the periodic table
263 6 : if (bonds%nbonds>0)then
264 :
265 18 : ABI_MALLOC(periods,(2,bonds%nbonds))
266 12 : ABI_MALLOC(iatoms,(2,bonds%nbonds))
267 24 : periods(:,:)=0
268 24 : iatoms(:,:)=0
269 :
270 6 : write(std_out,'(a)') 'Bond of Atom | Bond Number | Index'
271 :
272 18 : do ii=1,ab_mover%natom
273 12 : Z=ab_mover%znucl(ab_mover%typat(ii))
274 12 : if (Z==1)then
275 : period=1
276 0 : elseif ((Z>1).and.(Z<10))then
277 : period=2
278 0 : elseif ((Z>10).and.(Z<18))then
279 : period=3
280 0 : elseif ((Z>18).and.(Z<36))then
281 : period=4
282 0 : elseif ((Z>36).and.(Z<54))then
283 : period=5
284 0 : elseif ((Z>55).and.(Z<86))then
285 : period=6
286 : else
287 : ! Here are the cases for atoms larger than Fr(87) and
288 : ! All the noble gases He-Rn
289 0 : period=-1
290 : end if
291 :
292 30 : do jj=1,bonds%nbondi(ii)
293 12 : index=bonds%indexi(ii,jj)
294 :
295 12 : write(std_out,'(i6,a,i6,a,i4)') ii,' |',jj,' |',index
296 :
297 : ! The first atom should have index=0
298 : ! To make easy fill the matrix using its
299 : ! index
300 :
301 24 : if (index>0)then
302 6 : periods(1,index)=period
303 6 : iatoms(1,index)=ii
304 6 : elseif (index<0) then
305 6 : periods(2,-index)=period
306 6 : iatoms(2,-index)=ii
307 : end if
308 : end do
309 : end do
310 :
311 6 : write(std_out,'(a)') ch10
312 :
313 : end if
314 :
315 : ! For all bonds compute the 3x3 matrix and fill also the big matrix
316 :
317 258 : matrix(:,:)=0.0_dp
318 12 : do ii=1,bonds%nbonds
319 :
320 6 : write(std_out,*) 'Bond number:',ii
321 12 : if (iatoms(1,ii)>0 .and. iatoms(2,ii)>0) then
322 6 : write(std_out,*) 'Between atoms:',iatoms(1,ii),' and ',iatoms(2,ii)
323 6 : badgerfactor=badger(periods(1,ii),periods(2,ii))
324 6 : write(std_out,*) 'Periods of atoms:',periods(1,ii),' and ',periods(2,ii)
325 6 : write(std_out,*) 'Badger factor:',badgerfactor
326 :
327 : ! Compute the diadic product and
328 : ! Insert the matrix into the big one
329 24 : do jj=1,3
330 78 : do kk=1,3
331 : ! The non diagonal elements
332 54 : jsub=3*(iatoms(1,ii)-1)+jj
333 54 : ksub=3*(iatoms(2,ii)-1)+kk
334 : matrix(jsub,ksub)=matrix(jsub,ksub)-&
335 54 : & badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
336 :
337 54 : jsub=3*(iatoms(2,ii)-1)+jj
338 54 : ksub=3*(iatoms(1,ii)-1)+kk
339 : matrix(jsub,ksub)=matrix(jsub,ksub)-&
340 54 : & badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
341 :
342 : ! The diagonal blocks
343 54 : jsub=3*(iatoms(1,ii)-1)+jj
344 54 : ksub=3*(iatoms(1,ii)-1)+kk
345 : matrix(jsub,ksub)=matrix(jsub,ksub)+&
346 54 : & badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
347 :
348 54 : jsub=3*(iatoms(2,ii)-1)+jj
349 54 : ksub=3*(iatoms(2,ii)-1)+kk
350 : matrix(jsub,ksub)=matrix(jsub,ksub)+&
351 72 : & badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
352 :
353 : end do !do kk=1,3
354 : end do !do jj=1,3
355 :
356 : end if
357 :
358 : end do
359 :
360 6 : if (bonds%nbonds>0)then
361 6 : ABI_FREE(periods)
362 6 : ABI_FREE(iatoms)
363 : end if
364 :
365 6 : call bonds_free(bonds)
366 :
367 6 : if (3*ab_mover%natom<100)then
368 : ! Visualize the matrix
369 42 : do jj=1,3*ab_mover%natom
370 42 : write (std_out,fmt) matrix(jj,:)
371 : end do
372 : end if
373 :
374 24 : ABI_MALLOC(matrix_tmp,(3*ab_mover%natom,3*ab_mover%natom))
375 :
376 258 : matrix_tmp(:,:)=matrix(:,:)
377 : !write(*,*)"matrix_tmp",matrix_tmp
378 :
379 6 : ABI_MALLOC(work,(1))
380 6 : lwork=-1
381 6 : call DSYEV('V', 'U', 3*ab_mover%natom, matrix_tmp, 3*ab_mover%natom, w , work, lwork, info )
382 6 : lwork=work(1)
383 6 : write(std_out,*) '[DSYEV] Recommended lwork=',lwork
384 6 : ABI_FREE(work)
385 18 : ABI_MALLOC(work,(lwork))
386 6 : call DSYEV('V', 'U', 3*ab_mover%natom, matrix_tmp, 3*ab_mover%natom, w , work, lwork, info )
387 6 : ABI_FREE(work)
388 6 : ABI_FREE(matrix_tmp)
389 :
390 6 : write(std_out,*) 'DSYEV info=',info
391 6 : write(std_out,*) 'Eigenvalues:'
392 6 : write(std_out,fmt) w(:)
393 :
394 6 : sigma=0
395 42 : do jj=1,3*ab_mover%natom
396 42 : sigma=max(w(jj),sigma)
397 : end do
398 :
399 258 : matrix=lambda*matrix
400 :
401 6 : write(std_out,*) ch10
402 42 : do ii=1,3*ab_mover%natom
403 42 : matrix(ii,ii)=matrix(ii,ii)+(1-lambda)*sigma
404 : end do
405 :
406 : end if ! if (Compute_Matrix)
407 :
408 : !##########################################################
409 : !### 05. Use the precondition matrix to compute new residuals
410 :
411 70 : B=reshape(fcart,(/ 3*ab_mover%natom /))
412 :
413 35 : if (3*ab_mover%natom<100)then
414 : ! Visualize the matrix
415 245 : do jj=1,3*ab_mover%natom
416 245 : write (std_out,fmt) matrix(jj,:)
417 : end do
418 : end if
419 :
420 : !call dsysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work, lwork, info )
421 : !MGNAG FIXME: This call causes a floating point exception if NAG+MKL
422 35 : ABI_MALLOC(work,(1))
423 35 : lwork=-1
424 : call DSYSV( 'U', 3*ab_mover%natom, 1, matrix,&
425 35 : & 3*ab_mover%natom, ipiv, B, 3*ab_mover%natom, work, lwork, info )
426 :
427 35 : lwork=work(1)
428 35 : write(std_out,*) '[DSYSV] Recomended lwork=',lwork
429 35 : ABI_FREE(work)
430 105 : ABI_MALLOC(work,(lwork))
431 : call DSYSV( 'U', 3*ab_mover%natom, 1, matrix,&
432 35 : & 3*ab_mover%natom, ipiv, B, 3*ab_mover%natom, work, lwork, info )
433 35 : ABI_FREE(work)
434 :
435 35 : write(std_out,*) 'DSYSV info=',info
436 35 : write(std_out,*) 'Solution:'
437 35 : write(std_out,fmt) B(:)
438 :
439 420 : forstr%fcart=reshape(B,(/ 3, ab_mover%natom /) )
440 35 : call fcart2gred(forstr%fcart,forstr%gred,rprimd,ab_mover%natom)
441 :
442 440 : end subroutine prec_simple
443 : !!***
444 :
445 : end module m_pred_simple
446 : !!***
|