TABLE OF CONTENTS


ABINIT/m_pred_simple [ Modules ]

[ Top ] [ Modules ]

NAME

  m_pred_simple

FUNCTION

COPYRIGHT

  Copyright (C) 1998-2024 ABINIT group (DCA, XG, GMR, JCC, SE)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

SOURCE

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

ABINIT/prec_simple [ Functions ]

[ Top ] [ Functions ]

NAME

 prec_simple

FUNCTION

 Simple preconditioner, compute the force constant matrix
 using the Badger's rule:

                F=A/(r-B)^3

INPUTS

 ab_mover <type(abimover)> : Datatype with all the information needed by the preconditioner
 zDEBUG : if true print some debugging information

OUTPUT

SIDE EFFECTS

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

SOURCE

142 subroutine prec_simple(ab_mover,forstr,hist,icycle,itime,iexit)
143 
144  use m_linalg_interfaces
145 
146 !Arguments ------------------------------------
147 !scalars
148  integer,intent(in) :: iexit,itime,icycle
149  type(abimover),intent(in) :: ab_mover
150  type(abihist),intent(in) :: hist
151  type(abiforstr),intent(inout) :: forstr
152 
153 !Local variables-------------------------------
154 !scalars
155  integer :: period,ii,jj,index,kk,ksub,jsub
156  integer :: info,lwork,new_order_forces
157  real(dp) :: Z,badgerfactor,lambda,sigma,val_rms
158  integer,save :: order_forces
159  logical :: Compute_Matrix
160 !arrays
161  type(go_bonds) :: bonds
162  integer,allocatable :: periods(:,:)
163  integer,allocatable :: iatoms(:,:)
164  integer  :: ipiv(3*ab_mover%natom)
165  real(dp) :: xcart(3,ab_mover%natom)
166  real(dp) :: fcart(3,ab_mover%natom)
167  real(dp) :: B(3*ab_mover%natom)
168  real(dp) :: rprimd(3,3)
169  real(dp) :: w(3*ab_mover%natom)
170  real(dp),allocatable :: matrix_tmp(:,:)
171  real(dp),allocatable :: work(:)
172  real(dp) :: badger(6,6)
173  real(dp),allocatable,save :: matrix(:,:)
174  character(len=18)   :: fmt
175 
176 !***************************************************************************
177 !Beginning of executable session
178 !***************************************************************************
179 
180  if (iexit/=0)then
181    if(allocated(matrix))then
182      ABI_FREE(matrix)
183    endif
184    return
185  end if
186 
187 !##########################################################
188 !### 01. Show the Precondition parameters, set the badger
189 !###     matrix.
190 
191  write(std_out,*) 'Precondition option',ab_mover%goprecon
192  write(std_out,*) 'Precondition parameters',ab_mover%goprecprm
193  lambda=ab_mover%goprecprm(1)
194 
195  badger(:,:)=reshape( (/ -0.2573, 0.3401, 0.6937, 0.7126, 0.8335, 0.9491,&
196 & 0.3401, 0.9652, 1.2843, 1.4725, 1.6549, 1.7190,&
197 & 0.6937, 1.2843, 1.6925, 1.8238, 2.1164, 2.3185,&
198 & 0.7126, 1.4725, 1.8238, 2.0203, 2.2137, 2.5206,&
199 & 0.8335, 1.6549, 2.1164, 2.2137, 2.3718, 2.5110,&
200 & 0.9491, 1.7190, 2.3185, 2.5206, 2.5110, 0.0000 /), (/ 6, 6/) )
201 
202  write(fmt,'(a1,i4,a5)') '(',3*ab_mover%natom,'f8.3)'
203 
204 !##########################################################
205 !### 02. Take the coordinates and cell parameters from HIST
206 
207  rprimd(:,:)=hist%rprimd(:,:,hist%ihist)
208  fcart(:,:)=hist%fcart(:,:,hist%ihist)
209  call xred2xcart(ab_mover%natom,rprimd,xcart,hist%xred(:,:,hist%ihist))
210 
211 !##########################################################
212 !### 03. Decide based on kind of preconditioner if
213 !###     a new matrix should be computed
214 
215  new_order_forces = one  ! This to avoid using unitialized variables.
216 
217  if (ab_mover%goprecon==2)then
218 
219    val_rms=0.0
220    do kk=1,ab_mover%natom
221      do jj=1,3
222        val_rms=val_rms+fcart(jj,kk)**2
223      end do
224    end do
225    val_rms=sqrt(val_rms/dble(ab_mover%natom))
226    new_order_forces=int(log(val_rms)/log(10.0))
227  end if
228 
229  if (itime==1.and.icycle==1)then
230    Compute_Matrix=.TRUE.
231    order_forces=new_order_forces
232    if (allocated(matrix))  then
233      ABI_FREE(matrix)
234    end if
235 
236    ABI_MALLOC(matrix,(3*ab_mover%natom,3*ab_mover%natom))
237  else
238    Compute_Matrix=.FALSE.
239    if ((ab_mover%goprecon==2).and.(order_forces.gt.new_order_forces)) then
240      Compute_Matrix=.TRUE.
241      order_forces=new_order_forces
242    end if
243    if (ab_mover%goprecon==3) Compute_Matrix=.TRUE.
244  end if
245 
246 !##########################################################
247 !### 04. Compute a new precondition matrix if required
248 
249  if (Compute_Matrix)then
250 
251 !  Fix the tolerance for create a bond
252    bonds%tolerance=1.35
253    bonds%nbonds=1
254 
255 !  Allocate the arrays with exactly the rigth nbonds
256    ABI_MALLOC(bonds%bond_vect,(3,bonds%nbonds))
257    ABI_MALLOC(bonds%bond_length,(bonds%nbonds))
258    ABI_MALLOC(bonds%indexi,(ab_mover%natom,bonds%nbonds))
259    ABI_MALLOC(bonds%nbondi,(ab_mover%natom))
260 
261 !  Compute the bonds
262    call make_bonds_new(bonds,ab_mover%natom,ab_mover%ntypat,rprimd,&
263 &   ab_mover%typat,xcart,ab_mover%znucl)
264 
265    write(std_out,'(a,a,63a,a)') ch10,'---PRECONDITIONER',('-',kk=1,63),ch10
266 
267 !  For all bonds detect wich atoms are involved
268 !  and wich period they coprrespond in the periodic table
269    if (bonds%nbonds>0)then
270 
271      ABI_MALLOC(periods,(2,bonds%nbonds))
272      ABI_MALLOC(iatoms,(2,bonds%nbonds))
273      periods(:,:)=0
274      iatoms(:,:)=0
275 
276      write(std_out,'(a)') 'Bond of Atom | Bond Number | Index'
277 
278      do ii=1,ab_mover%natom
279        Z=ab_mover%znucl(ab_mover%typat(ii))
280        if (Z==1)then
281          period=1
282        elseif ((Z>1).and.(Z<10))then
283          period=2
284        elseif ((Z>10).and.(Z<18))then
285          period=3
286        elseif ((Z>18).and.(Z<36))then
287          period=4
288        elseif ((Z>36).and.(Z<54))then
289          period=5
290        elseif ((Z>55).and.(Z<86))then
291          period=6
292        else
293 !        Here are the cases for atoms larger than Fr(87) and
294 !        All the noble gases He-Rn
295          period=-1
296        end if
297 
298        do jj=1,bonds%nbondi(ii)
299          index=bonds%indexi(ii,jj)
300 
301          write(std_out,'(i6,a,i6,a,i4)') ii,'       |',jj,'       |',index
302 
303 !        The first atom should have index=0
304 !        To make easy fill the matrix using its
305 !        index
306 
307          if (index>0)then
308            periods(1,index)=period
309            iatoms(1,index)=ii
310          elseif (index<0) then
311            periods(2,-index)=period
312            iatoms(2,-index)=ii
313          end if
314        end do
315      end do
316 
317      write(std_out,'(a)') ch10
318 
319    end if
320 
321 !  For all bonds compute the 3x3 matrix and fill also the big matrix
322 
323    matrix(:,:)=0.0_dp
324    do ii=1,bonds%nbonds
325 
326      write(std_out,*) 'Bond number:',ii
327      if (iatoms(1,ii)>0 .and. iatoms(2,ii)>0) then
328        write(std_out,*) 'Between atoms:',iatoms(1,ii),' and ',iatoms(2,ii)
329        badgerfactor=badger(periods(1,ii),periods(2,ii))
330        write(std_out,*) 'Periods of atoms:',periods(1,ii),' and ',periods(2,ii)
331        write(std_out,*) 'Badger factor:',badgerfactor
332 
333 !      Compute the diadic product and
334 !      Insert the matrix into the big one
335        do jj=1,3
336          do kk=1,3
337 !          The non diagonal elements
338            jsub=3*(iatoms(1,ii)-1)+jj
339            ksub=3*(iatoms(2,ii)-1)+kk
340            matrix(jsub,ksub)=matrix(jsub,ksub)-&
341 &           badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
342 
343            jsub=3*(iatoms(2,ii)-1)+jj
344            ksub=3*(iatoms(1,ii)-1)+kk
345            matrix(jsub,ksub)=matrix(jsub,ksub)-&
346 &           badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
347 
348 !          The diagonal blocks
349            jsub=3*(iatoms(1,ii)-1)+jj
350            ksub=3*(iatoms(1,ii)-1)+kk
351            matrix(jsub,ksub)=matrix(jsub,ksub)+&
352 &           badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
353 
354            jsub=3*(iatoms(2,ii)-1)+jj
355            ksub=3*(iatoms(2,ii)-1)+kk
356            matrix(jsub,ksub)=matrix(jsub,ksub)+&
357 &           badgerfactor*bonds%bond_vect(jj,ii)*bonds%bond_vect(kk,ii)
358 
359          end do !do kk=1,3
360        end do !do jj=1,3
361 
362      end if
363 
364    end do
365 
366    if (bonds%nbonds>0)then
367      ABI_FREE(periods)
368      ABI_FREE(iatoms)
369    end if
370 
371    call bonds_free(bonds)
372 
373    if (3*ab_mover%natom<100)then
374 !    Visualize the matrix
375      do jj=1,3*ab_mover%natom
376        write (std_out,fmt) matrix(jj,:)
377      end do
378    end if
379 
380    ABI_MALLOC(matrix_tmp,(3*ab_mover%natom,3*ab_mover%natom))
381 
382    matrix_tmp(:,:)=matrix(:,:)
383    !write(*,*)"matrix_tmp",matrix_tmp
384 
385    ABI_MALLOC(work,(1))
386    lwork=-1
387    call DSYEV('V', 'U', 3*ab_mover%natom, matrix_tmp, 3*ab_mover%natom, w , work, lwork, info )
388    lwork=work(1)
389    write(std_out,*) '[DSYEV] Recommended lwork=',lwork
390    ABI_FREE(work)
391    ABI_MALLOC(work,(lwork))
392    call DSYEV('V', 'U', 3*ab_mover%natom, matrix_tmp, 3*ab_mover%natom, w , work, lwork, info )
393    ABI_FREE(work)
394    ABI_FREE(matrix_tmp)
395 
396    write(std_out,*) 'DSYEV info=',info
397    write(std_out,*) 'Eigenvalues:'
398    write(std_out,fmt) w(:)
399 
400    sigma=0
401    do jj=1,3*ab_mover%natom
402      sigma=max(w(jj),sigma)
403    end do
404 
405    matrix=lambda*matrix
406 
407    write(std_out,*) ch10
408    do ii=1,3*ab_mover%natom
409      matrix(ii,ii)=matrix(ii,ii)+(1-lambda)*sigma
410    end do
411 
412  end if ! if (Compute_Matrix)
413 
414 !##########################################################
415 !### 05. Use the precondition matrix to compute new residuals
416 
417  B=reshape(fcart,(/ 3*ab_mover%natom /))
418 
419  if (3*ab_mover%natom<100)then
420 !  Visualize the matrix
421    do jj=1,3*ab_mover%natom
422      write (std_out,fmt) matrix(jj,:)
423    end do
424  end if
425 
426 !call dsysv( uplo, n, nrhs, a, lda, ipiv, b, ldb, work, lwork, info )
427 !MGNAG FIXME: This call causes a floating point exception if NAG+MKL
428  ABI_MALLOC(work,(1))
429  lwork=-1
430  call DSYSV( 'U', 3*ab_mover%natom, 1, matrix,&
431 & 3*ab_mover%natom, ipiv, B, 3*ab_mover%natom, work, lwork, info )
432 
433  lwork=work(1)
434  write(std_out,*) '[DSYSV] Recomended lwork=',lwork
435  ABI_FREE(work)
436  ABI_MALLOC(work,(lwork))
437  call DSYSV( 'U', 3*ab_mover%natom, 1, matrix,&
438 & 3*ab_mover%natom, ipiv, B, 3*ab_mover%natom, work, lwork, info )
439  ABI_FREE(work)
440 
441  write(std_out,*) 'DSYSV info=',info
442  write(std_out,*) 'Solution:'
443  write(std_out,fmt) B(:)
444 
445  forstr%fcart=reshape(B,(/ 3, ab_mover%natom /) )
446  call fcart2gred(forstr%fcart,forstr%gred,rprimd,ab_mover%natom)
447 
448 end subroutine prec_simple

ABINIT/pred_simple [ Functions ]

[ Top ] [ Functions ]

NAME

 pred_simple

FUNCTION

 Ionmov predictors (4 & 5) Internal to scfcv.
 Actually, this routine does nothing (only copy) as all operations are internal to scfcv ...

 IONMOV 4:
 Conjugate gradient algorithm for simultaneous optimization
 of potential and ionic degrees of freedom. It can be used with
 iscf=2 and iscf=5 or 6

 IONMOV 5:
 Simple relaxation of ionic positions according to (converged)
 forces. Equivalent to ionmov=1 with zero masses, albeit the
 relaxation coefficient is not vis, but iprcfc.

INPUTS

 ab_mover <type(abimover)> : Datatype with all the information needed by the preditor
 zDEBUG : if true print some debugging information

OUTPUT

SIDE EFFECTS

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

SOURCE

 72 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,jj
 83 
 84 !***************************************************************************
 85 !Beginning of executable session
 86 !***************************************************************************
 87 
 88  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  ihist_next = abihist_findIndex(hist,+1)
 96  do kk=1,ab_mover%natom
 97    do jj=1,3
 98      hist%xred(jj,kk, ihist_next)=hist%xred (jj,kk,hist%ihist)
 99      hist%fcart(jj,kk,ihist_next)=hist%fcart(jj,kk,hist%ihist)
100      hist%vel(jj,kk,ihist_next)=hist%vel(jj,kk,hist%ihist)
101    end do
102  end do
103 
104 !ACELL
105  do jj=1,3
106    hist%acell(jj,ihist_next)=hist%acell(jj,hist%ihist)
107  end do
108 
109 !RPRIMD
110  do kk=1,3
111    do jj=1,3
112      hist%rprimd(jj,kk,ihist_next)=hist%rprimd(jj,kk,hist%ihist)
113    end do
114  end do
115 
116  hist%ihist=ihist_next
117 
118 end subroutine pred_simple