Line data Source code
1 : !!****m* ABINIT/m_pred_delocint
2 : !! NAME
3 : !! m_pred_delocint
4 : !!
5 : !! FUNCTION
6 : !!
7 : !! COPYRIGHT
8 : !! Copyright (C) 1998-2026 ABINIT group (MVer, DCA, XG, GMR, JCC, SE)
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_delocint
22 :
23 : use defs_basis
24 : use m_errors
25 : use m_abicore
26 : use m_abimover
27 : use m_abihist
28 : use m_xfpack
29 : use m_linalg_interfaces
30 :
31 : use m_geometry, only : fcart2gred, xcart2xred, xred2xcart, metric, acrossb
32 : use m_bfgs, only : hessinit, hessupdt, brdene
33 : use m_results_gs, only : results_gs_type
34 :
35 : implicit none
36 :
37 : private
38 : !!***
39 :
40 : public :: pred_delocint
41 :
42 : contains
43 : !!***
44 :
45 : !!****f* ABINIT/pred_delocint
46 : !! NAME
47 : !! pred_delocint
48 : !!
49 : !! FUNCTION
50 : !! Ionmov predictors (10) BFGS with delocalized internal coordinates
51 : !!
52 : !! IONMOV 10:
53 : !! Given a starting point xred that is a vector of length 3*(natom-1)
54 : !! (reduced nuclei coordinates),
55 : !! and unit cell parameters (acell and rprimd) the
56 : !! Broyden-Fletcher-Goldfarb-Shanno minimization is performed on the
57 : !! total energy function, using its gradient (atomic forces and stresses)
58 : ! as calculated by the routine scfcv. Some atoms can be kept fixed,
59 : !! while the optimization of unit cell
60 : !! parameters is only performed if optcell/=0.
61 : !! The convergence requirement on
62 : !! the atomic forces, 'tolmxf', allows an early exit.
63 : !! Otherwise no more than 'ntime' steps are performed.
64 : !! Returned quantities are xred, and eventually acell and rprimd (new ones!).
65 : !! Could see Numerical Recipes (Fortran), 1986, page 307.
66 : !!
67 : !! Implements the delocalized internal coordinate scheme
68 : !! of Andzelm et al. in CPL .335. 321 (2001) \
69 : !! and Baker et al. JCP .105. 192 (1996)
70 : !!
71 : !! B matrix is derivative of delocalized internals wrt cartesian coordinates
72 : !! U matrix is eigenvectors of G = B*B^{T}
73 : !! S matrix is eigenvectors of F = B^{T}B
74 : !!
75 : !! INPUTS
76 : !! ab_mover <type(abimover)> : Datatype with all the information needed by the preditor
77 : !! itime : Index of the present iteration
78 : !! ntime : Maximal number of iterations
79 : !! ionmov : (10 or 11) 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 2 : subroutine pred_delocint(ab_mover,ab_xfh,deloc,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 : type(delocint),intent(inout) :: deloc
98 : integer,intent(in) :: itime
99 : integer,intent(in) :: ionmov
100 : integer,intent(in) :: iexit
101 : logical,intent(in) :: zDEBUG
102 :
103 : !Local variables-------------------------------
104 : !scalars
105 : integer :: ndim,cycl_main
106 : integer :: ihist_prev,ii,jj,kk
107 : real(dp),save :: ucvol0
108 : real(dp) :: ucvol
109 : real(dp) :: etotal,etotal_prev
110 : logical :: DEBUG=.TRUE.
111 : !integer,save :: icenter,irshift ! DELOCINT indexes
112 : integer,save :: ndeloc ! DELOCINT number of
113 : character(len=500) :: message
114 :
115 : !arrays
116 : real(dp),allocatable,save :: hessin(:,:),vin(:),vin_prev(:)
117 : real(dp),allocatable,save :: vout(:),vout_prev(:)
118 : real(dp),save :: acell0(3) ! Initial acell
119 : real(dp),save :: rprimd0(3,3) ! Initial rprimd
120 2 : real(dp),allocatable :: prim_int(:)
121 : real(dp),allocatable,save :: u_matrix(:,:) ! DELOCINT this may need to be added to type inside ab_mover
122 : real(dp) :: acell(3)
123 : real(dp) :: rprimd(3,3)
124 : real(dp) :: gprimd(3,3)
125 : real(dp) :: gmet(3,3)
126 : real(dp) :: rmet(3,3)
127 4 : real(dp) :: residual(3,ab_mover%natom)
128 : !real(dp) :: residual_corrected(3,ab_mover%natom)
129 4 : real(dp) :: xred(3,ab_mover%natom),xcart(3,ab_mover%natom)
130 : real(dp) :: strten(6)
131 4 : real(dp) :: deloc_gred(3*(ab_mover%natom-1))
132 4 : real(dp) :: deloc_int(3*(ab_mover%natom-1))
133 2 : real(dp) :: bt_inv_matrix(3*(ab_mover%natom-1),3*ab_mover%natom)
134 :
135 : !***************************************************************************
136 : !Beginning of executable session
137 : !***************************************************************************
138 :
139 2 : if(iexit/=0)then
140 1 : ABI_SFREE(vin)
141 1 : ABI_SFREE(vout)
142 1 : ABI_SFREE(vin_prev)
143 1 : ABI_SFREE(vout_prev)
144 1 : ABI_SFREE(hessin)
145 1 : ABI_SFREE(u_matrix)
146 : return
147 : end if
148 :
149 : !write(std_out,*) 'delocint 01'
150 : !##########################################################
151 : !### 01. Debugging and Verbose
152 :
153 1 : if(DEBUG)then
154 43 : write(std_out,'(a,3a,38a,39a)') ch10,('-',kk=1,3),'Debugging and Verbose for pred_deloint',('-',kk=1,39)
155 1 : write(std_out,*) 'ionmov: ',ionmov
156 1 : write(std_out,*) 'itime: ',itime
157 : end if
158 :
159 : !write(std_out,*) 'delocint 02'
160 : !##########################################################
161 : !### 02. Compute the dimension of vectors (ndim)
162 :
163 : !With internal we have 1 coordinate less
164 1 : ndeloc = 3*(ab_mover%natom-1)
165 1 : ndim=ndeloc
166 4 : deloc_int(:)=zero
167 4 : deloc_gred(:)=zero
168 1 : if(ab_mover%optcell==1) ndim=ndim+1
169 1 : if(ab_mover%optcell==2 .or.&
170 0 : & ab_mover%optcell==3) ndim=ndim+6
171 1 : if(ab_mover%optcell>=4) ndim=ndim+3
172 :
173 1 : if(DEBUG) write(std_out,*) 'Dimension of vin, vout and hessian (ndim): ',ndim
174 :
175 : !write(std_out,*) 'delocint 03'
176 : !##########################################################
177 : !### 03. Allocate the vectors vin, vout and hessian matrix
178 :
179 : !Notice thqt vin, vout, etc could be allocated
180 : !From a previous dataset with a different ndim
181 1 : if(itime==1)then
182 1 : ABI_SFREE(vin)
183 1 : ABI_SFREE(vout)
184 1 : ABI_SFREE(vin_prev)
185 1 : ABI_SFREE(vout_prev)
186 1 : ABI_SFREE(hessin)
187 :
188 3 : ABI_MALLOC(vin,(ndim))
189 2 : ABI_MALLOC(vout,(ndim))
190 2 : ABI_MALLOC(vin_prev,(ndim))
191 2 : ABI_MALLOC(vout_prev,(ndim))
192 4 : ABI_MALLOC(hessin,(ndim,ndim))
193 : end if
194 :
195 :
196 : !write(std_out,*) 'delocint 04'
197 : !##########################################################
198 : !### 04. Obtain the present values from the history
199 :
200 1 : call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
201 1 : call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
202 :
203 7 : strten(:)=hist%strten(:,hist%ihist)
204 1 : etotal =hist%etot(hist%ihist)
205 :
206 : !Fill the residual with forces (No preconditioning)
207 : !Or the preconditioned forces
208 1 : if (ab_mover%goprecon==0)then
209 1 : call fcart2gred(hist%fcart(:,:,hist%ihist),residual,rprimd,ab_mover%natom)
210 : else
211 0 : residual(:,:)= forstr%gred(:,:)
212 : end if
213 :
214 1 : if(zDEBUG)then
215 0 : write (std_out,*) 'residual:'
216 0 : do kk=1,ab_mover%natom
217 0 : write (std_out,*) residual(:,kk)
218 : end do
219 0 : write (std_out,*) 'strten:'
220 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
221 0 : write (std_out,*) 'etotal:'
222 0 : write (std_out,*) etotal
223 : end if
224 :
225 1 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
226 :
227 : !Save initial values
228 1 : if (itime==1)then
229 1 : acell0(:)=acell(:)
230 1 : rprimd0(:,:)=rprimd(:,:)
231 1 : ucvol0=ucvol
232 : end if
233 :
234 : !DEBUG (UCVOL)
235 1 : if(DEBUG)then
236 1 : write(std_out,*) 'Volume of cell (ucvol):',ucvol
237 : end if
238 :
239 : !Get rid of mean force on whole unit cell, but only if no
240 : !generalized constraints are in effect
241 : ! residual_corrected(:,:)=residual(:,:)
242 : ! if(ab_mover%nconeq==0)then
243 : ! do ii=1,3
244 : ! if (ii/=3.or.ab_mover%jellslab==0) then
245 : ! favg=sum(residual_corrected(ii,:))/dble(ab_mover%natom)
246 : ! residual_corrected(ii,:)=residual_corrected(ii,:)-favg
247 : ! end if
248 : ! end do
249 : ! end if
250 :
251 : !write(std_out,*) 'delocint 05'
252 : !##########################################################
253 : !### 05. Compute internals for first time
254 :
255 1 : if (itime==1)then
256 : call make_prim_internals(deloc,ab_mover%natom,&
257 1 : & ab_mover%ntypat,rprimd,ab_mover%typat,xcart,ab_mover%znucl)
258 :
259 3 : ABI_MALLOC(prim_int,(deloc%ninternal))
260 :
261 1 : if(DEBUG)then
262 1 : write (message,'(a,i6)') 'Number of primitive internal coordinates (ninternal): ',deloc%ninternal
263 1 : call wrtout(std_out, message,'COLL')
264 : end if
265 :
266 1 : if (allocated(u_matrix)) then
267 0 : ABI_FREE(u_matrix)
268 : end if
269 4 : ABI_MALLOC(u_matrix,(deloc%ninternal,ndeloc))
270 :
271 1 : call calc_prim_int(deloc,ab_mover%natom,rprimd,xcart,prim_int)
272 :
273 1 : if(DEBUG)then
274 1 : write (message,'(a)') 'Primitive internal coordinate values:'
275 1 : call wrtout(std_out, message,'COLL')
276 1 : write (message,'(a)') ' Bonds:'
277 1 : call wrtout(std_out, message,'COLL')
278 5 : do ii = 1, deloc%nbond
279 4 : write (message,'(i6,E20.10)') ii, prim_int(ii)
280 5 : call wrtout(std_out, message,'COLL')
281 : end do
282 :
283 1 : write (message,'(a)') ' Angles:'
284 1 : call wrtout(std_out, message,'COLL')
285 13 : do ii = deloc%nbond+1, deloc%nbond+deloc%nang
286 12 : write (message,'(i6,2(E20.10,2x))') ii, prim_int(ii), prim_int(ii)/pi*180.0_dp
287 13 : call wrtout(std_out, message,'COLL')
288 : end do
289 :
290 1 : write (message,'(a)') ' Dihedrals:'
291 1 : call wrtout(std_out, message,'COLL')
292 37 : do ii = deloc%nbond+deloc%nang+1, deloc%nbond+deloc%nang+deloc%ndihed
293 36 : write (message,'(i6,2(E20.10,2x))') ii, prim_int(ii), prim_int(ii)/pi*180.0_dp
294 37 : call wrtout(std_out, message,'COLL')
295 : end do
296 :
297 1 : write (message,'(a)') ' Cartesian auxiliary coordinates for constraints:'
298 1 : call wrtout(std_out, message,'COLL')
299 1 : do ii = deloc%nbond+deloc%nang+deloc%ndihed+1, deloc%ninternal
300 0 : write (message,'(i6,E20.10)') ii, prim_int(ii)
301 1 : call wrtout(std_out, message,'COLL')
302 : end do
303 : end if
304 :
305 1 : ABI_FREE(prim_int)
306 :
307 : ! equal weight on all internal coordinates as a starting point.
308 160 : u_matrix(:,:) = one / dble (ndeloc)
309 :
310 : ! Zero the arrays before first use
311 4 : deloc_gred(:) = zero
312 :
313 : end if
314 :
315 3 : ABI_MALLOC(prim_int,(deloc%ninternal))
316 :
317 : !write(std_out,*) 'delocint 06'
318 : !##########################################################
319 : !### 06. Compute delocalized coordinates and forces
320 :
321 : !xcart ---> deloc_int
322 :
323 : !Convert positions to delocalized coordinates for next step
324 : call xcart2deloc(deloc,ab_mover%natom,rprimd,xcart,&
325 1 : & bt_inv_matrix,u_matrix,deloc_int,prim_int)
326 :
327 : !gred ---> deloc_gred
328 :
329 : !Convert gradients to delocalized coordinates for next step
330 1 : call gred2gdeloc(bt_inv_matrix,deloc_gred,residual,ab_mover%natom,gprimd)
331 :
332 : !write(std_out,*) 'delocint 07'
333 : !##########################################################
334 : !### 07. Fill the vectors vin and vout
335 :
336 : !DEBUG deloc_int and deloc_gred before pack
337 1 : if(DEBUG)then
338 1 : write (std_out,*) 'Delocalized internals and forces (ndeloc):',ndeloc
339 1 : write(std_out,*) 'deloc_int'
340 2 : do ii=1,ndeloc,3
341 2 : if (ii+2<=ndeloc)then
342 1 : write(std_out,*) ii,deloc_int(ii:ii+2)
343 : else
344 0 : write(std_out,*) ii,deloc_int(ii:ndeloc)
345 : end if
346 : end do
347 1 : write(std_out,*) 'deloc_gred'
348 2 : do ii=1,ndeloc,3
349 2 : if (ii+2<=ndeloc)then
350 1 : write(std_out,*) ii,deloc_gred(ii:ii+2)
351 : else
352 0 : write(std_out,*) ii,deloc_gred(ii:ndeloc)
353 : end if
354 : end do
355 : end if
356 :
357 : !DELOCINT
358 : !Instead of gred_corrected we use deloc_gred
359 : !Instead of xred e use deloc_int
360 : !
361 : !Initialize input vectors : first vin, then vout
362 : !The values of vin from the previous iteration
363 : !should be the same
364 : call xfpack_x2vin(acell, ab_mover%natom-1, ndim,&
365 : & ab_mover%nsym, ab_mover%optcell, rprimd, rprimd0,&
366 1 : & ab_mover%symrel, ucvol, ucvol0, vin, deloc_int)
367 : !end if
368 :
369 : call xfpack_f2vout(deloc_gred, ab_mover%natom-1, ndim,&
370 : & ab_mover%optcell, ab_mover%strtarget, strten, ucvol, &
371 1 : & vout)
372 :
373 : !write(std_out,*) 'delocint 08'
374 : !##########################################################
375 : !### 08. Initialize or update the hessian matrix
376 :
377 : !Initialise the Hessian matrix using gmet
378 1 : if (itime==1)then
379 :
380 : ! Initialise the Hessian matrix with ab_mover%userrc.
381 : ! this has become unusable because it imposes ndim >= 3 natom
382 : ! ident = 3x3 identity matrix
383 : ! call hessinit(ab_mover, hessin, gmet, ndim, ucvol)
384 13 : hessin = zero
385 4 : do ii=1, ndim
386 4 : hessin (ii,ii) = one
387 : end do
388 :
389 : ! ! Initialize inverse hessian with identity matrix
390 : ! ! in cartesian coordinates, which makes use of metric tensor gmet
391 : ! ! in reduced coordinates.
392 : ! hessin(:,:)=zero
393 : ! do ii=1,ab_mover%natom
394 : ! do kk=1,3
395 : ! do jj=1,3
396 : ! ! Warning : implemented in reduced coordinates
397 : ! if (ab_mover%iatfix(kk,ii)==0 .and.&
398 : ! & ab_mover%iatfix(jj,ii)==0 )then
399 : ! hessin(kk+3*(ii-1),jj+3*(ii-1))=gmet(kk,jj)
400 : ! end if
401 : ! end do
402 : ! end do
403 : ! end do
404 : ! if(ab_mover%optcell/=0)then
405 : ! ! These values might lead to too large changes in some cases
406 : ! diag=ab_mover%strprecon*30.0_dp/ucvol
407 : ! if(ab_mover%optcell==1) diag=diag/three
408 : ! do ii=3*ab_mover%natom+1,ndim
409 : ! hessin(ii,ii)=diag
410 : ! end do
411 : ! end if
412 :
413 1 : if (ab_mover%restartxf/=0) then
414 :
415 : call xfh_recover_deloc(ab_xfh,ab_mover,acell,cycl_main,&
416 : & residual,hessin,ndim,rprimd,rprimd0,strten,ucvol,ucvol0,vin,vin_prev,&
417 : & vout,vout_prev,xred,deloc,deloc_int,deloc_gred,bt_inv_matrix,gprimd,prim_int,&
418 0 : & u_matrix)
419 :
420 : end if
421 :
422 : end if
423 :
424 1 : ABI_FREE(prim_int)
425 :
426 1 : if(itime>1)then
427 : ! Update the hessian matrix, by taking into account the
428 : ! current pair (x,f) and the previous one.
429 : call hessupdt(hessin,ab_mover%iatfix,ab_mover%natom,ndim,vin,&
430 0 : & vin_prev,vout,vout_prev)
431 :
432 : end if
433 :
434 : !DEBUG (vin,vout and hessin before prediction)
435 1 : if(DEBUG)then
436 1 : write(std_out,*) 'Vectors vin and vout and inverse of Hessian (hessin) [before]'
437 1 : write(std_out,*) 'vin:'
438 2 : do ii=1,ndim,3
439 2 : if (ii+2<=ndim)then
440 1 : write(std_out,*) ii,vin(ii:ii+2)
441 : else
442 0 : write(std_out,*) ii,vin(ii:ndim)
443 : end if
444 : end do
445 1 : write(std_out,*) 'vout:'
446 2 : do ii=1,ndim,3
447 2 : if (ii+2<=ndim)then
448 1 : write(std_out,*) ii,vout(ii:ii+2)
449 : else
450 0 : write(std_out,*) ii,vout(ii:ndim)
451 : end if
452 : end do
453 1 : write(std_out,*) 'Inverse Hessian (hessin): ',ndim,'x',ndim
454 4 : do kk=1,ndim
455 7 : do jj=1,ndim,3
456 6 : if (jj+2<=ndim)then
457 3 : write(std_out,*) jj,hessin(jj:jj+2,kk)
458 : else
459 0 : write(std_out,*) jj,hessin(jj:ndim,kk)
460 : end if
461 : end do
462 : end do
463 : end if
464 :
465 : !write(std_out,*) 'delocint 09'
466 : !##########################################################
467 : !### 09. Compute the next values
468 :
469 1 : if(ionmov==10 .or. itime==1)then
470 :
471 : ! Previous cartesian coordinates
472 4 : vin_prev(:)=vin(:)
473 :
474 : ! New atomic cartesian coordinates are obtained from vin, hessin
475 : ! and vout
476 40 : vin = vin - matmul(hessin, vout)
477 : ! Previous atomic forces
478 4 : vout_prev(:)=vout(:)
479 :
480 : else
481 0 : if(ionmov==11)then
482 0 : ihist_prev = abihist_findIndex(hist,-1)
483 0 : etotal_prev=hist%etot(ihist_prev)
484 : ! Here the BFGS algorithm, modified to take into account the
485 : ! energy
486 : call brdene(etotal,etotal_prev,hessin,&
487 0 : & ndim,vin,vin_prev,vout,vout_prev)
488 :
489 : end if
490 :
491 : ! DEBUG (vin,vout and hessin after prediction)
492 0 : if(DEBUG)then
493 0 : write(std_out,*) 'Vectors vin and vout [after prediction]'
494 0 : write(std_out,*) 'vin:'
495 0 : do ii=1,ndim,3
496 0 : if (ii+2<=ndim)then
497 0 : write(std_out,*) ii,vin(ii:ii+2)
498 : else
499 0 : write(std_out,*) ii,vin(ii:ndim)
500 : end if
501 : end do
502 0 : write(std_out,*) 'vout:'
503 0 : do ii=1,ndim,3
504 0 : if (ii+2<=ndim)then
505 0 : write(std_out,*) ii,vout(ii:ii+2)
506 : else
507 0 : write(std_out,*) ii,vout(ii:ndim)
508 : end if
509 : end do
510 : end if
511 :
512 : ! Implement fixing of atoms : put back old values for fixed
513 : ! components
514 0 : do kk=1,ab_mover%natom
515 0 : do jj=1,3
516 : ! Warning : implemented in reduced coordinates
517 0 : if ( ab_mover%iatfix(jj,kk)==1) then
518 0 : vin(jj+(kk-1)*3)=vin_prev(jj+(kk-1)*3)
519 : end if
520 : end do
521 : end do
522 : end if
523 :
524 : !write(std_out,*) 'delocint 10'
525 : !##########################################################
526 : !### 10. Convert from delocalized to xcart and xred
527 :
528 : !Transfer vin to deloc_int, acell and rprimd
529 : call xfpack_vin2x(acell, acell0, ab_mover%natom-1, ndim,&
530 : & ab_mover%nsym, ab_mover%optcell, rprimd, rprimd0,&
531 : & ab_mover%symrel, ucvol, ucvol0,&
532 1 : & vin, deloc_int)
533 :
534 1 : if(DEBUG)then
535 1 : write (std_out,*) 'Delocalized internals (deloc_int) [after prediction]:'
536 1 : write(std_out,*) 'deloc_int:'
537 2 : do ii=1,ndeloc,3
538 2 : if (ii+2<=ndeloc)then
539 1 : write(std_out,*) ii,deloc_int(ii:ii+2)
540 : else
541 0 : write(std_out,*) ii,deloc_int(ii:ndeloc)
542 : end if
543 : end do
544 1 : write(std_out,*) 'BT Inverse Matrix:'
545 7 : do ii=1,3*ab_mover%natom
546 7 : write(std_out,*) bt_inv_matrix(:,ii)
547 : end do
548 1 : write (std_out,*) 'xcart (before deloc2xcart):'
549 3 : do ii=1,ab_mover%natom
550 3 : write (std_out,*) xcart(:,ii)
551 : end do
552 : end if
553 :
554 : !this routine contains an iterative scheme to find xcart
555 : !from the non-linear relations between deloc and xcart
556 : !SIGNIFICANTLY DIFFERENT FROM xcart2deloc
557 : call deloc2xcart(deloc,ab_mover%natom,rprimd,xcart,&
558 1 : & deloc_int,bt_inv_matrix,u_matrix)
559 :
560 : !Convert new xcart (cartesian) to xred (reduced coordinates)
561 1 : call xcart2xred(ab_mover%natom,rprimd,xcart,xred)
562 :
563 :
564 : !write(std_out,*) 'delocint 11'
565 : !##########################################################
566 : !### 11. Update the history with the prediction
567 :
568 : !Increase indexes
569 1 : hist%ihist = abihist_findIndex(hist,+1)
570 :
571 1 : if(ab_mover%optcell/=0)then
572 0 : call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
573 : end if
574 :
575 : !Fill the history with the variables
576 : !xred, acell, rprimd, vel
577 1 : call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
578 1 : ihist_prev = abihist_findIndex(hist,-1)
579 9 : hist%vel(:,:,hist%ihist)=hist%vel(:,:,ihist_prev)
580 :
581 1 : if(zDEBUG)then
582 0 : write (std_out,*) 'residual:'
583 0 : do kk=1,ab_mover%natom
584 0 : write (std_out,*) residual(:,kk)
585 : end do
586 0 : write (std_out,*) 'strten:'
587 0 : write (std_out,*) strten(1:3),ch10,strten(4:6)
588 0 : write (std_out,*) 'etotal:'
589 0 : write (std_out,*) etotal
590 : end if
591 :
592 : end subroutine pred_delocint
593 : !!***
594 :
595 : !!****f* ABINIT/deloc2xcart
596 : !! NAME
597 : !! deloc2xcart
598 : !!
599 : !! FUNCTION
600 : !! Determine the cartesian coordinates which correspond to the
601 : !! given values of the delocalized coordinates. The relationship
602 : !! is non-linear, so use an iterative scheme, as in Baker
603 : !! JCP .105. 192 (1996).
604 : !! Older reference: Pulay and co. JACS 101 2550 (1979)
605 : !!
606 : !! INPUTS
607 : !! deloc <type(delocint)>=Important variables for
608 : !! | pred_delocint
609 : !! |
610 : !! | nang = Number of angles
611 : !! | nbond = Number of bonds
612 : !! | ncart = Number of cartesian directions
613 : !! | (used for constraints)
614 : !! | ndihed = Number of dihedrals
615 : !! | nrshift = Dimension of rshift
616 : !! | ninternal= Number of internal coordinates
617 : !! | ninternal=nbond+nang+ndihed+ncart
618 : !! |
619 : !! | angs(2,3,nang) = Indexes to characterize angles
620 : !! | bonds(2,2,nbond)= For a bond between iatom and jatom
621 : !! | bonds(1,1,nbond) = iatom
622 : !! | bonds(2,1,nbond) = icenter
623 : !! | bonds(1,2,nbond) = jatom
624 : !! | bonds(2,2,nbond) = irshift
625 : !! | carts(2,ncart) = Index of total primitive internal,
626 : !! | and atom (carts(2,:))
627 : !! | dihedrals(2,4,ndihed)= Indexes to characterize dihedrals
628 : !! |
629 : !! | rshift(3,nrshift)= Shift in xred that must be done to find
630 : !! | all neighbors of a given atom within a
631 : !! | given number of neighboring shells
632 : !! natom = Number of atoms (dtset%natom)
633 : !! rprimd(3,3)=dimensional real space primitive translations (bohr)
634 : !!
635 : !! OUTPUT
636 : !! bt_inv_matrix(3*(natom-1),3*natom)=inverse of transpose of B matrix
637 : !!
638 : !! SIDE EFFECTS
639 : !! u_matrix(ninternal,3*(natom-1))=eigenvectors of G = BB^T matrix
640 : !! xcart(3,natom)=cartesian coordinates of atoms (bohr)
641 : !!
642 : !! NOTES
643 : !!
644 : !! SOURCE
645 :
646 1 : subroutine deloc2xcart(deloc,natom,rprimd,xcart,deloc_int,btinv,u_matrix)
647 :
648 : !Arguments ------------------------------------
649 : !scalars
650 : integer,intent(in) :: natom
651 : type(delocint),intent(in) :: deloc
652 : !arrays
653 : real(dp),intent(in) :: deloc_int(3*(natom-1)),rprimd(3,3)
654 : real(dp),intent(inout) :: u_matrix(deloc%ninternal,3*(natom-1))
655 : real(dp),intent(inout) :: xcart(3,natom)
656 : real(dp),intent(out) :: btinv(3*(natom-1),3*natom)
657 :
658 : !Local variables-------------------------------
659 : !scalars
660 : integer :: iiter,iprim,niter
661 : integer :: ii
662 : real(dp) :: minmix, maxmix
663 : real(dp) :: mix,tot_diff, toldeloc
664 : real(dp) :: lntoldeloc
665 : logical :: DEBUG=.FALSE.
666 : !arrays
667 2 : real(dp) :: btinv_tmp(3*(natom-1),3*natom)
668 2 : real(dp) :: cgrad(3*natom),cgrad_old(3*natom)
669 2 : real(dp) :: deloc_int_now(3*(natom-1)),prim_int(deloc%ninternal)
670 2 : real(dp) :: tmpxcart(3*natom)
671 2 : real(dp) :: xdeloc_diff(3*(natom-1))
672 :
673 : character(len=500) :: message
674 :
675 : ! ******************************************************************
676 :
677 1 : if (DEBUG) then
678 0 : write(ab_out,*) 'ENTERING DELOC2XCART'
679 :
680 0 : write (message,*) 'BONDS=',deloc%nbond
681 0 : call wrtout(ab_out,message,'COLL')
682 0 : do ii = 1, deloc%nbond
683 0 : write (message,*) ii, deloc%bonds(:,:,ii)
684 0 : call wrtout(ab_out,message,'COLL')
685 : end do
686 :
687 0 : write (message,*) 'ANGS=',deloc%nang
688 0 : call wrtout(ab_out,message,'COLL')
689 0 : do ii = 1, deloc%nang
690 0 : write (message,*) ii, deloc%angs(:,:,ii)
691 0 : call wrtout(ab_out,message,'COLL')
692 : end do
693 :
694 0 : write (message,*) 'DIHEDRALS=',deloc%ndihed
695 0 : call wrtout(ab_out,message,'COLL')
696 0 : do ii = 1, deloc%ndihed
697 0 : write (message,*) ii, deloc%dihedrals(:,:,ii)
698 0 : call wrtout(ab_out,message,'COLL')
699 : end do
700 :
701 0 : write (message,*) 'CARTS=',deloc%ncart
702 0 : call wrtout(ab_out,message,'COLL')
703 0 : do ii = 1, deloc%ncart
704 0 : write (message,*) ii, deloc%carts(:,ii)
705 0 : call wrtout(ab_out,message,'COLL')
706 : end do
707 :
708 0 : write (ab_out,*) 'xcart (input)'
709 0 : do ii=1,natom
710 0 : write (ab_out,*) xcart(:,ii)
711 : end do
712 :
713 : end if
714 :
715 1 : niter = 200
716 2 : tmpxcart = reshape(xcart,(/3*natom/))
717 :
718 7 : cgrad_old(:) = zero
719 7 : cgrad(:) = zero
720 : maxmix = 0.9_dp
721 : minmix = 0.2_dp
722 : toldeloc = tol10
723 : lntoldeloc = log(toldeloc)
724 :
725 62 : do iiter=1,niter
726 62 : if (iiter==1) then
727 : mix= minmix
728 : else
729 61 : mix = minmix + (maxmix-minmix)*(log(tot_diff)-lntoldeloc) / lntoldeloc
730 : end if
731 61 : if (mix < minmix) mix = minmix
732 : if (mix > maxmix) mix = maxmix
733 :
734 434 : tmpxcart(:) = tmpxcart(:) + mix*cgrad(:)
735 186 : xcart = reshape(tmpxcart,(/3,natom/))
736 : call xcart2deloc(deloc,natom,rprimd,xcart,&
737 62 : & btinv_tmp,u_matrix,deloc_int_now,prim_int)
738 : ! update the BT^{-1} matrix?
739 1550 : btinv(:,:) = btinv_tmp(:,:)
740 :
741 248 : xdeloc_diff(:) = deloc_int(:) - deloc_int_now(:)
742 :
743 248 : tot_diff = sum(abs(xdeloc_diff))
744 62 : if (tot_diff < toldeloc) exit
745 :
746 427 : cgrad_old(:) = cgrad(:)
747 :
748 : ! gradient vector = btinv^{T} * xdeloc_diff
749 : call dgemv('T',3*(natom-1),3*natom,one,&
750 62 : & btinv,3*(natom-1),xdeloc_diff,1,zero,cgrad,1)
751 : end do
752 : !end iiter do
753 :
754 : call xcart2deloc(deloc,natom,rprimd,xcart,&
755 1 : & btinv,u_matrix,deloc_int_now,prim_int)
756 1 : write (message,'(3a)') 'delocalized internals, after convergence of xcart = ', ch10
757 1 : call wrtout(std_out,message,'COLL')
758 4 : do ii = 1, 3*(natom-1)
759 3 : write (message,'(I6,E20.10,2x)') ii, deloc_int_now(ii)
760 4 : call wrtout(std_out,message,'COLL')
761 : end do
762 :
763 4 : xdeloc_diff(:) = deloc_int(:) - deloc_int_now(:)
764 :
765 1 : write (message,'(a)') 'Primitive internal coordinate values:'
766 1 : call wrtout(std_out,message,'COLL')
767 5 : do iprim = 1, deloc%nbond
768 4 : write (message,'(i6,E20.10)') iprim, prim_int(iprim)
769 5 : call wrtout(std_out,message,'COLL')
770 : end do
771 49 : do iprim = deloc%nbond+1, deloc%nbond+deloc%nang+deloc%ndihed
772 48 : write (message,'(i6,2E20.10)') iprim, prim_int(iprim), prim_int(iprim)/pi*180.0_dp
773 49 : call wrtout(std_out,message,'COLL')
774 : end do
775 1 : do iprim = deloc%nbond+deloc%nang+deloc%ndihed+1, deloc%ninternal
776 0 : write (message,'(i6,E20.10)') iprim, prim_int(iprim)
777 1 : call wrtout(std_out,message,'COLL')
778 : end do
779 :
780 1 : if (iiter == niter+1) then
781 0 : write (message,'(a,i6,a,E20.10)') 'deloc2xcart : Error, xcart not converged in ', niter, 'iterations ', tot_diff
782 0 : ABI_ERROR(message)
783 : end if
784 :
785 1 : if(DEBUG)then
786 0 : write (ab_out,*) 'xcart (output)'
787 0 : do ii=1,natom
788 0 : write (ab_out,*) xcart(:,ii)
789 : end do
790 0 : write(ab_out,*) 'EXITING DELOC2XCART'
791 : end if
792 :
793 1 : end subroutine deloc2xcart
794 : !!***
795 :
796 : !!****f* ABINIT/gred2gdeloc
797 : !! NAME
798 : !! gred2gdeloc
799 : !!
800 : !! FUNCTION
801 : !! calculate delocalized forces from reduced coordinate ones
802 : !!
803 : !! INPUTS
804 : !! btinv(3*(natom-1),3*natom)= inverse transpose of B matrix (see delocint)
805 : !! natom = number of atoms
806 : !! gprimd(3,3)=dimensional translations in reciprocal space (bohr-1)
807 : !!
808 : !! OUTPUT
809 : !! deloc_gred(3*(natom-1))=delocalized gradients from reduced coordinate ones
810 : !! gred(3,natom)=delocalized gradients in reduced coordinates
811 : !!
812 : !! SOURCE
813 :
814 1 : subroutine gred2gdeloc(btinv,deloc_gred,gred,natom,gprimd)
815 :
816 : !Arguments ------------------------------------
817 : !scalars
818 : integer, intent(in) :: natom
819 : !arrays
820 : real(dp),intent(in) :: btinv(3*(natom-1),3*natom),gprimd(3,3),gred(3,natom)
821 : real(dp),intent(out) :: deloc_gred(3*(natom-1))
822 :
823 : !Local variables-------------------------------
824 : integer :: ii
825 : !arrays
826 2 : real(dp) :: fcart(3,natom)
827 : character(len=500) :: message
828 :
829 : ! ******************************************************************
830 :
831 : !make cartesian forces
832 :
833 : call dgemm('N','N',3,natom,3,one,&
834 1 : & gprimd,3,gred,3,zero,fcart,3)
835 :
836 : !turn cartesian to delocalized forces
837 : call dgemv('N',3*(natom-1),3*natom,one,&
838 1 : & btinv,3*(natom-1),fcart,1,zero,deloc_gred,1)
839 :
840 1 : write (message,'(a)') 'gred2gdeloc : deloc_gred = '
841 1 : call wrtout(std_out,message,'COLL')
842 :
843 4 : do ii = 1, 3*(natom-1)
844 3 : write (message,'(I6,E16.6)') ii, deloc_gred(ii)
845 4 : call wrtout(std_out,message,'COLL')
846 : end do
847 :
848 1 : end subroutine gred2gdeloc
849 : !!***
850 :
851 : !!****f* ABINIT/calc_b_matrix
852 : !! NAME
853 : !! calc_b_matrix
854 : !!
855 : !! FUNCTION
856 : !! calculate values of derivatives of internal coordinates as a function of
857 : !! cartesian ones = B matrix
858 : !!
859 : !! INPUTS
860 : !! angs= number of angles
861 : !! bonds(2,2,nbond)=for a bond between iatom and jatom
862 : !! bonds(1,1,nbond) = iatom
863 : !! bonds(2,1,nbond) = icenter
864 : !! bonds(1,2,nbond) = jatom
865 : !! bonds(2,2,nbond) = irshift
866 : !! carts(2,ncart)= index of total primitive internal, and atom (carts(2,:))
867 : !! dihedrals(2,4,ndihed)=indexes to characterize dihedrals
868 : !! nang(2,3,nang)=indexes to characterize angles
869 : !! nbond=number of bonds
870 : !! ncart=number of auxiliary cartesian atom coordinates (used for constraints)
871 : !! ndihed= number of dihedrals
872 : !! ninternal=nbond+nang+ndihed+ncart: number of internal coordinates
873 : !! nrshift= dimension of rshift
874 : !! rprimd(3,3)=dimensional real space primitive translations (bohr)
875 : !! rshift(3,nrshift)=shift in xred that must be done to find all neighbors of
876 : !! a given atom within a given number of neighboring shells
877 : !! xcart(3,natom)=cartesian coordinates of atoms (bohr)
878 : !!
879 : !! OUTPUT
880 : !! b_matrix(ninternal,3*natom)=matrix of derivatives of internal coordinates
881 : !! wrt cartesians
882 : !!
883 : !! SOURCE
884 :
885 64 : subroutine calc_b_matrix(deloc,natom,rprimd,xcart,b_matrix)
886 :
887 : !Arguments ------------------------------------
888 : !scalars
889 : integer,intent(in) :: natom
890 : type(delocint),intent(in) :: deloc
891 :
892 : !arrays
893 : real(dp),intent(in) :: rprimd(3,3),xcart(3,natom)
894 : real(dp),intent(out) :: b_matrix(deloc%ninternal,3*natom)
895 :
896 : !Local variables-------------------------------
897 : !scalars
898 : integer :: i1,i2,i3,i4,iang,ibond,icart,idihed,iprim,s1,s2,s3,s4
899 : !arrays
900 : real(dp) :: bb(3),r1(3),r2(3),r3(3),r4(3)
901 :
902 : ! *************************************************************************
903 :
904 64 : iprim=0
905 20416 : b_matrix(:,:) = zero
906 :
907 320 : do ibond=1,deloc%nbond
908 256 : i1 = deloc%bonds(1,1,ibond)
909 256 : s1 = deloc%bonds(2,1,ibond)
910 : r1(:) = xcart(:,i1)+deloc%rshift(1,s1)*rprimd(:,1)&
911 : & +deloc%rshift(2,s1)*rprimd(:,2)&
912 1024 : & +deloc%rshift(3,s1)*rprimd(:,3)
913 256 : i2 = deloc%bonds(1,2,ibond)
914 256 : s2 = deloc%bonds(2,2,ibond)
915 : r2(:) = xcart(:,i2)+deloc%rshift(1,s2)*rprimd(:,1)&
916 : & +deloc%rshift(2,s2)*rprimd(:,2)&
917 1024 : & +deloc%rshift(3,s2)*rprimd(:,3)
918 256 : iprim=iprim+1
919 256 : call dbond_length_d1(r1,r2,bb)
920 1024 : b_matrix(iprim,3*(i1-1)+1:3*i1) = b_matrix(iprim,3*(i1-1)+1:3*i1) + bb(:)
921 256 : call dbond_length_d1(r2,r1,bb)
922 1088 : b_matrix(iprim,3*(i2-1)+1:3*i2) = b_matrix(iprim,3*(i2-1)+1:3*i2) + bb(:)
923 : end do
924 :
925 : !second: angle values (ang)
926 832 : do iang=1,deloc%nang
927 768 : i1 = deloc%angs(1,1,iang)
928 768 : s1 = deloc%angs(2,1,iang)
929 : r1(:) = xcart(:,i1)+deloc%rshift(1,s1)*rprimd(:,1)&
930 : & +deloc%rshift(2,s1)*rprimd(:,2)&
931 3072 : & +deloc%rshift(3,s1)*rprimd(:,3)
932 768 : i2 = deloc%angs(1,2,iang)
933 768 : s2 = deloc%angs(2,2,iang)
934 : r2(:) = xcart(:,i2)+deloc%rshift(1,s2)*rprimd(:,1)&
935 : & +deloc%rshift(2,s2)*rprimd(:,2)&
936 3072 : & +deloc%rshift(3,s2)*rprimd(:,3)
937 768 : i3 = deloc%angs(1,3,iang)
938 768 : s3 = deloc%angs(2,3,iang)
939 : r3(:) = xcart(:,i3)+deloc%rshift(1,s3)*rprimd(:,1)&
940 : & +deloc%rshift(2,s3)*rprimd(:,2)&
941 3072 : & +deloc%rshift(3,s3)*rprimd(:,3)
942 768 : iprim=iprim+1
943 768 : call dang_d1(r1,r2,r3,bb)
944 3072 : b_matrix(iprim,3*(i1-1)+1:3*i1) = b_matrix(iprim,3*(i1-1)+1:3*i1) + bb(:)
945 768 : call dang_d2(r1,r2,r3,bb)
946 3072 : b_matrix(iprim,3*(i2-1)+1:3*i2) = b_matrix(iprim,3*(i2-1)+1:3*i2) + bb(:)
947 768 : call dang_d1(r3,r2,r1,bb)
948 3136 : b_matrix(iprim,3*(i3-1)+1:3*i3) = b_matrix(iprim,3*(i3-1)+1:3*i3) + bb(:)
949 : end do
950 :
951 : !third: dihedral values
952 2368 : do idihed=1,deloc%ndihed
953 2304 : i1 = deloc%dihedrals(1,1,idihed)
954 2304 : s1 = deloc%dihedrals(2,1,idihed)
955 : r1(:) = xcart(:,i1)+deloc%rshift(1,s1)*rprimd(:,1)&
956 : & +deloc%rshift(2,s1)*rprimd(:,2)&
957 9216 : & +deloc%rshift(3,s1)*rprimd(:,3)
958 2304 : i2 = deloc%dihedrals(1,2,idihed)
959 2304 : s2 = deloc%dihedrals(2,2,idihed)
960 : r2(:) = xcart(:,i2)+deloc%rshift(1,s2)*rprimd(:,1)&
961 : & +deloc%rshift(2,s2)*rprimd(:,2)&
962 9216 : & +deloc%rshift(3,s2)*rprimd(:,3)
963 2304 : i3 = deloc%dihedrals(1,3,idihed)
964 2304 : s3 = deloc%dihedrals(2,3,idihed)
965 : r3(:) = xcart(:,i3)+deloc%rshift(1,s3)*rprimd(:,1)&
966 : & +deloc%rshift(2,s3)*rprimd(:,2)&
967 9216 : & +deloc%rshift(3,s3)*rprimd(:,3)
968 2304 : i4 = deloc%dihedrals(1,4,idihed)
969 2304 : s4 = deloc%dihedrals(2,4,idihed)
970 : r4(:) = xcart(:,i4)+deloc%rshift(1,s4)*rprimd(:,1)&
971 : & +deloc%rshift(2,s4)*rprimd(:,2)&
972 9216 : & +deloc%rshift(3,s4)*rprimd(:,3)
973 : ! write(std_out,*) 'dihed ',idihed
974 : ! write(std_out,*) r1
975 : ! write(std_out,*) r2
976 : ! write(std_out,*) r3
977 : ! write(std_out,*) r4
978 :
979 2304 : iprim=iprim+1
980 2304 : call ddihedral_d1(r1,r2,r3,r4,bb)
981 9216 : b_matrix(iprim,3*(i1-1)+1:3*i1) = b_matrix(iprim,3*(i1-1)+1:3*i1) + bb(:)
982 2304 : call ddihedral_d2(r1,r2,r3,r4,bb)
983 9216 : b_matrix(iprim,3*(i2-1)+1:3*i2) = b_matrix(iprim,3*(i2-1)+1:3*i2) + bb(:)
984 2304 : call ddihedral_d2(r4,r3,r2,r1,bb)
985 9216 : b_matrix(iprim,3*(i3-1)+1:3*i3) = b_matrix(iprim,3*(i3-1)+1:3*i3) + bb(:)
986 2304 : call ddihedral_d1(r4,r3,r2,r1,bb)
987 9280 : b_matrix(iprim,3*(i4-1)+1:3*i4) = b_matrix(iprim,3*(i4-1)+1:3*i4) + bb(:)
988 : end do
989 :
990 64 : do icart=1,deloc%ncart
991 0 : iprim=iprim+1
992 : b_matrix(iprim,3*(deloc%carts(2,icart)-1)+deloc%carts(1,icart)) = &
993 64 : & b_matrix(iprim,3*(deloc%carts(2,icart)-1)+deloc%carts(1,icart)) + one
994 : end do
995 :
996 : !DEBUG
997 : ! write (200,*) 'calc_b_matrix : b_matrix = '
998 : ! do iprim=1,deloc%ninternal
999 : ! do i1=1, 3*natom
1000 : ! write (200,'(E16.6,2x)',ADVANCE='NO') b_matrix(iprim,i1)
1001 : ! end do
1002 : ! write (200,*)
1003 : ! end do
1004 : !ENDDEBUG
1005 :
1006 64 : end subroutine calc_b_matrix
1007 : !!***
1008 :
1009 : !!****f* ABINIT/dbond_length_d1
1010 : !! NAME
1011 : !! dbond_length_d1
1012 : !!
1013 : !! FUNCTION
1014 : !!
1015 : !! SOURCE
1016 : !!
1017 :
1018 512 : subroutine dbond_length_d1(r1,r2,bb)
1019 :
1020 : !Arguments ------------------------------------
1021 : !arrays
1022 : real(dp),intent(in) :: r1(3),r2(3)
1023 : real(dp),intent(out) :: bb(3)
1024 :
1025 : !Local variables ------------------------------
1026 : !arrays
1027 : real(dp) :: rpt(3)
1028 :
1029 : !************************************************************************
1030 2048 : rpt(:) = r1(:)-r2(:)
1031 2048 : bb(:) = rpt(:)/bond_length(r1,r2)
1032 :
1033 512 : end subroutine dbond_length_d1
1034 : !!***
1035 :
1036 :
1037 : !!****f* ABINIT/dang_d1
1038 : !! NAME
1039 : !! dang_d1
1040 : !!
1041 : !! FUNCTION
1042 : !!
1043 : !! SOURCE
1044 : !!
1045 :
1046 1536 : subroutine dang_d1(r1,r2,r3,bb)
1047 :
1048 : !Arguments ------------------------------------
1049 : !arrays
1050 : real(dp),intent(in) :: r1(3),r2(3),r3(3)
1051 : real(dp),intent(out) :: bb(3)
1052 :
1053 : !Local variables ------------------------------
1054 : !scalars
1055 : real(dp) :: cos_ang,n1,n1232,n2,tmp
1056 : !arrays
1057 : real(dp) :: cp1232(3),rpt(3),rpt12(3),rpt32(3)
1058 :
1059 : !************************************************************************
1060 1536 : n1=bond_length(r1,r2)
1061 1536 : n2=bond_length(r3,r2)
1062 :
1063 6144 : rpt12(:) = r1(:)-r2(:)
1064 6144 : rpt32(:) = r3(:)-r2(:)
1065 :
1066 6144 : cos_ang = dot_product(rpt12,rpt32)/n1/n2
1067 1536 : if (cos_ang > one - epsilon(one)*two) then
1068 : cos_ang = one
1069 1536 : else if(cos_ang < -one + epsilon(one)*two) then
1070 0 : cos_ang = -one
1071 : end if
1072 :
1073 6144 : rpt(:) = rpt32(:)/n1/n2 - rpt12(:)*cos_ang/n1/n1
1074 :
1075 1536 : tmp = sqrt(one-cos_ang**2)
1076 1536 : bb(:) = zero
1077 1536 : if (tmp > epsilon(one)) then
1078 6144 : bb(:) = rpt(:) * (-one)/tmp
1079 : end if
1080 :
1081 : !TEST: version from MOLECULAR VIBRATIONS EB Wilson
1082 1536 : call acrossb(rpt12,rpt32,cp1232)
1083 6144 : n1232 = norm2(cp1232)
1084 6144 : rpt(:) = (cos_ang*rpt12(:)*n2/n1 - rpt32(:))/n1232
1085 1536 : if (abs(bb(1)-rpt(1))+abs(bb(2)-rpt(2))+abs(bb(3)-rpt(3)) > tol10) then
1086 0 : write(std_out,*) 'Compare bb ang 1 : '
1087 0 : write(std_out,*) bb(:), rpt(:), bb(:)-rpt(:)
1088 : end if
1089 1536 : bb(:) = rpt(:)
1090 :
1091 1536 : end subroutine dang_d1
1092 : !!***
1093 :
1094 :
1095 : !!****f* ABINIT/dang_d2
1096 : !! NAME
1097 : !! dang_d2
1098 : !!
1099 : !! FUNCTION
1100 : !!
1101 : !! SOURCE
1102 : !!
1103 :
1104 768 : subroutine dang_d2(r1,r2,r3,bb)
1105 :
1106 : !Arguments ------------------------------------
1107 : !arrays
1108 : real(dp),intent(in) :: r1(3),r2(3),r3(3)
1109 : real(dp),intent(out) :: bb(3)
1110 :
1111 : !Local variables ------------------------------
1112 : !scalars
1113 : real(dp) :: cos_ang,n1,n1232,n2,tmp
1114 : !arrays
1115 : real(dp) :: cp1232(3),rpt(3),rpt12(3),rpt32(3)
1116 :
1117 : !************************************************************************
1118 768 : n1=bond_length(r1,r2)
1119 768 : n2=bond_length(r3,r2)
1120 :
1121 3072 : rpt12(:) = r1(:)-r2(:)
1122 3072 : rpt32(:) = r3(:)-r2(:)
1123 :
1124 3072 : cos_ang = dot_product(rpt12,rpt32)/n1/n2
1125 768 : if (cos_ang > one - epsilon(one)*two) then
1126 : cos_ang = one
1127 768 : else if(cos_ang < -one + epsilon(one)*two) then
1128 0 : cos_ang = -one
1129 : end if
1130 :
1131 : rpt(:) = -rpt32(:)/n1/n2 - rpt12(:)/n1/n2 &
1132 3072 : & + rpt12(:)*cos_ang/n1/n1 + rpt32(:)*cos_ang/n2/n2
1133 :
1134 768 : tmp = sqrt(one-cos_ang**2)
1135 768 : bb(:) = zero
1136 768 : if (tmp > tol12) then
1137 3072 : bb(:) = rpt(:) * (-one)/tmp
1138 : end if
1139 :
1140 : !TEST: version from MOLECULAR VIBRATIONS EB Wilson
1141 768 : call acrossb(rpt12,rpt32,cp1232)
1142 3072 : n1232 = norm2(cp1232)
1143 3072 : rpt(:) = ((n1-n2*cos_ang)*rpt12(:)/n1 + (n2-n1*cos_ang)*rpt32(:)/n2) / n1232
1144 768 : if (abs(bb(1)-rpt(1))+abs(bb(2)-rpt(2))+abs(bb(3)-rpt(3)) > tol10) then
1145 0 : write(std_out,*) 'Compare bb ang 2 : '
1146 0 : write(std_out,*) bb(:), rpt(:), bb(:)-rpt(:)
1147 : end if
1148 768 : bb(:) = rpt(:)
1149 :
1150 768 : end subroutine dang_d2
1151 : !!***
1152 :
1153 : !!****f* ABINIT/ddihedral_d1
1154 : !! NAME
1155 : !! ddihedral_d1
1156 : !!
1157 : !! FUNCTION
1158 : !!
1159 : !! SOURCE
1160 : !!
1161 :
1162 4608 : subroutine ddihedral_d1(r1,r2,r3,r4,bb)
1163 :
1164 : !Arguments ------------------------------------
1165 : !arrays
1166 : real(dp),intent(in) :: r1(3),r2(3),r3(3),r4(3)
1167 : real(dp),intent(out) :: bb(3)
1168 :
1169 : !Local variables ------------------------------------
1170 : !scalars
1171 : real(dp) :: cos_dihedral,dih_sign,n1,n2,n23,sin_dihedral,tmp
1172 : !arrays
1173 : real(dp) :: cp1232(3),cp32_1232(3),cp32_3432(3),cp3432(3),cpcp(3),rpt(3)
1174 : real(dp) :: rpt12(3),rpt32(3),rpt34(3)
1175 :
1176 : !******************************************************************
1177 18432 : rpt12(:) = r1(:)-r2(:)
1178 18432 : rpt32(:) = r3(:)-r2(:)
1179 18432 : rpt34(:) = r3(:)-r4(:)
1180 :
1181 4608 : call acrossb(rpt12,rpt32,cp1232)
1182 4608 : call acrossb(rpt34,rpt32,cp3432)
1183 :
1184 : !DEBUG
1185 : !write(std_out,*) ' cos_dihedral : cp1232 = ', cp1232
1186 : !write(std_out,*) ' cos_dihedral : cp3432 = ', cp3432
1187 : !ENDDEBUG
1188 :
1189 18432 : n1 = norm2(cp1232)
1190 18432 : n2 = norm2(cp3432)
1191 :
1192 18432 : cos_dihedral = dot_product(cp1232,cp3432)/n1/n2
1193 4608 : if (cos_dihedral > one - epsilon(one)*two) then
1194 : cos_dihedral = one
1195 3112 : else if(cos_dihedral < -one + epsilon(one)*two) then
1196 0 : cos_dihedral = -one
1197 : end if
1198 : !we use complementary of standard angle, so
1199 : !cos_dihedral = -cos_dihedral
1200 :
1201 4608 : call acrossb(cp1232,cp3432,cpcp)
1202 18432 : cpcp(:) = cpcp(:)/n1/n2
1203 : !we use complementary of standard angle, but sin is invariant
1204 32256 : sin_dihedral = -dot_product(cpcp,rpt32)/norm2(rpt32)
1205 4608 : dih_sign = one
1206 4608 : if (sin_dihedral < -epsilon(one)) then
1207 1556 : dih_sign = -one
1208 : end if
1209 :
1210 : !DEBUG
1211 : !write(std_out,'(a,3E16.6)') 'ddihedral_d1 : cos abs(sin) dih_sign= ',&
1212 : !& cos_dihedral,sin_dihedral,dih_sign
1213 : !ENDDEBUG
1214 :
1215 : !ddihedral_d1 = dih_sign* acos(cos_dihedral)
1216 4608 : call acrossb(rpt32,cp1232,cp32_1232)
1217 4608 : call acrossb(rpt32,cp3432,cp32_3432)
1218 :
1219 18432 : rpt(:) = cp32_3432(:)/n1/n2 - cp32_1232(:)/n1/n1 * cos_dihedral
1220 4608 : bb(:) = zero
1221 :
1222 : !DEBUG
1223 : !write(std_out,*) 'ddihedral_d1 cp1232 cp3432 = ',cp1232,cp3432,rpt32
1224 : !write(std_out,*) 'ddihedral_d1 cp32_1232 cp32_3432 = ',cp32_1232,cp32_3432,cos_dihedral,n1,n2
1225 : !write(std_out,*) 'ddihedral_d1 rpt = ',rpt
1226 : !ENDDEBUG
1227 :
1228 4608 : tmp = sqrt(one-cos_dihedral**2)
1229 4608 : if (tmp > tol12) then
1230 : ! we use complementary of standard angle, so cosine in acos has - sign,
1231 : ! and it appears for the derivative
1232 12448 : bb(:) = -dih_sign * rpt(:) * (-one) / tmp
1233 : else
1234 10472 : bb(:) = dih_sign * cp32_3432(:) / n1 / n2 / norm2(cp32_3432)
1235 : end if
1236 :
1237 : !TEST: version from MOLECULAR VIBRATIONS EB Wilson
1238 :
1239 18432 : n23 = norm2(rpt32)
1240 18432 : rpt(:) = cp1232(:)*n23/n1/n1
1241 : !if (abs(bb(1)-rpt(1))+abs(bb(2)-rpt(2))+abs(bb(3)-rpt(3)) > tol10) then
1242 : !write(std_out,*) 'Compare bb1 : '
1243 : !write(std_out,*) bb(:), rpt(:), bb(:)-rpt(:)
1244 : !end if
1245 4608 : bb(:) = rpt(:)
1246 :
1247 4608 : end subroutine ddihedral_d1
1248 : !!***
1249 :
1250 : !!****f* ABINIT/ddihedral_d2
1251 : !! NAME
1252 : !! ddihedral_d2
1253 : !!
1254 : !! FUNCTION
1255 : !!
1256 : !! SOURCE
1257 : !!
1258 :
1259 4608 : subroutine ddihedral_d2(r1,r2,r3,r4,bb)
1260 :
1261 : !Arguments ------------------------------------
1262 : !arrays
1263 : real(dp),intent(in) :: r1(3),r2(3),r3(3),r4(3)
1264 : real(dp),intent(out) :: bb(3)
1265 :
1266 : !Local variables
1267 : !scalars
1268 : real(dp) :: cos_dihedral,dih_sign,n1,n2,n23,sin_dihedral,sp1232,sp3432,tmp
1269 : !arrays
1270 : real(dp) :: cp1232(3),cp1232_12(3),cp1232_34(3),cp32_1232(3),cp32_3432(3)
1271 : real(dp) :: cp3432(3),cp3432_12(3),cp3432_34(3),cpcp(3),rpt(3),rpt12(3)
1272 : real(dp) :: rpt32(3),rpt34(3)
1273 :
1274 : ! *************************************************************************
1275 18432 : rpt12(:) = r1(:)-r2(:)
1276 18432 : rpt32(:) = r3(:)-r2(:)
1277 18432 : rpt34(:) = r3(:)-r4(:)
1278 :
1279 4608 : call acrossb(rpt12,rpt32,cp1232)
1280 4608 : call acrossb(rpt34,rpt32,cp3432)
1281 :
1282 : !DEBUG
1283 : !write(std_out,*) ' cos_dihedral : cp1232 = ', cp1232
1284 : !write(std_out,*) ' cos_dihedral : cp3432 = ', cp3432
1285 : !ENDDEBUG
1286 :
1287 18432 : n1 = norm2(cp1232)
1288 18432 : n2 = norm2(cp3432)
1289 :
1290 18432 : cos_dihedral = dot_product(cp1232,cp3432)/n1/n2
1291 4608 : if (cos_dihedral > one - epsilon(one)*two) then
1292 : cos_dihedral = one
1293 3112 : else if(cos_dihedral < -one + epsilon(one)*two) then
1294 0 : cos_dihedral = -one
1295 : end if
1296 : !we use complementary of standard angle, so
1297 : !cos_dihedral = -cos_dihedral
1298 :
1299 4608 : call acrossb(cp1232,cp3432,cpcp)
1300 18432 : cpcp(:) = cpcp(:)/n1/n2
1301 : !we use complementary of standard angle, but sin is invariant
1302 32256 : sin_dihedral = -dot_product(cpcp,rpt32)/norm2(rpt32)
1303 4608 : dih_sign = one
1304 4608 : if (sin_dihedral < -tol12) then
1305 1536 : dih_sign = -one
1306 : end if
1307 :
1308 : !DEBUG
1309 : !write(std_out,'(a,3E16.6)') 'ddihedral_d2 : cos abs(sin) dih_sign= ',&
1310 : !& cos_dihedral,sin_dihedral,dih_sign
1311 : !ENDDEBUG
1312 :
1313 : !ddihedral_d2 = dih_sign* acos(cos_dihedral)
1314 4608 : call acrossb(rpt32,cp3432,cp32_3432)
1315 4608 : call acrossb(cp3432,rpt12,cp3432_12)
1316 4608 : call acrossb(cp1232,rpt34,cp1232_34)
1317 :
1318 4608 : call acrossb(rpt32,cp1232,cp32_1232)
1319 4608 : call acrossb(cp1232,rpt12,cp1232_12)
1320 4608 : call acrossb(cp3432,rpt34,cp3432_34)
1321 :
1322 : rpt(:) = -(cp32_3432(:) + cp3432_12(:) + cp1232_34(:))/n1/n2 &
1323 18432 : & +cos_dihedral*(cp32_1232(:)/n1/n1 + cp1232_12(:)/n1/n1 + cp3432_34(:)/n2/n2)
1324 4608 : bb(:) = zero
1325 4608 : tmp = sqrt(one-cos_dihedral**2)
1326 4608 : if (tmp > tol12) then
1327 : ! we use complementary of standard angle, so cosine in acos has - sign,
1328 : ! and it appears for derivative
1329 12448 : bb(:) = -dih_sign * rpt(:) * (-one) / tmp
1330 : else
1331 : bb(:) = dih_sign * cos_dihedral * &
1332 : & ( cp32_1232(:)/n1/n1/sqrt(cp32_1232(1)**2+cp32_1232(2)**2+cp32_1232(3)**2) &
1333 : & +cp1232_12(:)/n1/n1/sqrt(cp1232_12(1)**2+cp1232_12(2)**2+cp1232_12(3)**2) &
1334 5984 : & +cp3432_34(:)/n2/n2/sqrt(cp3432_34(1)**2+cp3432_34(2)**2+cp3432_34(3)**2) )
1335 : end if
1336 :
1337 : !TEST: version from MOLECULAR VIBRATIONS EB Wilson p. 61
1338 18432 : n23 = norm2(rpt32)
1339 18432 : sp1232 = dot_product(rpt12,rpt32)
1340 18432 : sp3432 = dot_product(rpt34,rpt32)
1341 :
1342 18432 : rpt(:) = -cp1232(:)*(n23-sp1232/n23)/n1/n1 - cp3432(:)*sp3432/n23/n2/n2
1343 : !if (abs(bb(1)-rpt(1))+abs(bb(2)-rpt(2))+abs(bb(3)-rpt(3)) > tol10) then
1344 : !write(std_out,*) 'Compare bb2 : '
1345 : !write(std_out,*) bb(:), rpt(:), bb(:)-rpt(:)
1346 : !write(std_out,*) -cp1232(:)*(n23-sp1232/n23)/n1/n1, -cp3432(:)*sp3432/n23/n2/n2
1347 : !end if
1348 4608 : bb(:) = rpt(:)
1349 :
1350 4608 : end subroutine ddihedral_d2
1351 : !!***
1352 :
1353 : !!****f* ABINIT/xcart2deloc
1354 : !! NAME
1355 : !! xcart2deloc
1356 : !!
1357 : !! FUNCTION
1358 : !! Calculate values of delocalized coordinates as a function of
1359 : !! cartesian ones. First primitive internals, then B matrix,
1360 : !! then F, then U then delocalized internals.
1361 : !!
1362 : !! INPUTS
1363 : !! deloc <type(delocint)>=Important variables for pred_delocint
1364 : !! |
1365 : !! | nang = Number of angles
1366 : !! | nbond = Number of bonds
1367 : !! | ncart = Number of cartesian directions
1368 : !! | (used for constraints)
1369 : !! | ndihed = Number of dihedrals
1370 : !! | nrshift = Dimension of rshift
1371 : !! | ninternal= Number of internal coordinates
1372 : !! | ninternal=nbond+nang+ndihed+ncart
1373 : !! |
1374 : !! | angs(2,3,nang) = Indexes to characterize angles
1375 : !! | bonds(2,2,nbond)= For a bond between iatom and jatom
1376 : !! | bonds(1,1,nbond) = iatom
1377 : !! | bonds(2,1,nbond) = icenter
1378 : !! | bonds(1,2,nbond) = jatom
1379 : !! | bonds(2,2,nbond) = irshift
1380 : !! | carts(2,ncart) = Index of total primitive internal,
1381 : !! | and atom (carts(2,:))
1382 : !! | dihedrals(2,4,ndihed)= Indexes to characterize dihedrals
1383 : !! |
1384 : !! | rshift(3,nrshift)= Shift in xred that must be done to find
1385 : !! | all neighbors of a given atom within a
1386 : !! | given number of neighboring shells
1387 : !! natom = Number of atoms
1388 : !! rprimd(3,3) = Dimensional real space primitive translations
1389 : !! (bohr)
1390 : !! xcart(3,natom) = Cartesian coordinates of atoms (bohr)
1391 : !!
1392 : !! OUTPUT
1393 : !! bt_inv_matrix(3*(natom-1),3*natom) = Inverse of B^{T} matrix
1394 : !! deloc_int(3*(natom-1)) = Delocalized internal coordinates
1395 : !! prim_int(ninternal) = Primitive internal coordinates
1396 : !!
1397 : !! SIDE EFFECTS
1398 : !! u_matrix(ninternal,3*(natom-1)) = Eigenvectors of BB^T matrix
1399 : !!
1400 : !! NOTES
1401 : !!
1402 : !! SOURCE
1403 :
1404 64 : subroutine xcart2deloc(deloc,natom,rprimd,xcart,bt_inv_matrix,u_matrix,deloc_int,prim_int)
1405 :
1406 : !Arguments ------------------------------------
1407 : !scalars
1408 : integer,intent(in) :: natom
1409 : type(delocint),intent(in) :: deloc
1410 : !arrays
1411 : real(dp),intent(in) :: rprimd(3,3),xcart(3,natom)
1412 : real(dp),intent(inout) :: u_matrix(deloc%ninternal,3*(natom-1))
1413 : real(dp),intent(out) :: bt_inv_matrix(3*(natom-1),3*natom)
1414 : real(dp),intent(out) :: deloc_int(3*(natom-1))
1415 : real(dp),intent(out) :: prim_int(deloc%ninternal)
1416 :
1417 : !Local variables-------------------------------
1418 : !scalars
1419 : integer :: ii
1420 : logical :: DEBUG=.FALSE.
1421 : !arrays
1422 128 : real(dp) :: b_matrix(deloc%ninternal,3*natom)
1423 :
1424 : ! ******************************************************************
1425 :
1426 64 : call calc_prim_int(deloc,natom,rprimd,xcart,prim_int)
1427 64 : if (DEBUG)then
1428 0 : write(std_out,*) 'Primitive Internals'
1429 0 : do ii=1,deloc%ninternal
1430 0 : write(std_out,*) prim_int(ii)
1431 : end do
1432 : end if
1433 :
1434 64 : call calc_b_matrix(deloc,natom,rprimd,xcart,b_matrix)
1435 64 : if (DEBUG)then
1436 0 : write(std_out,*) 'B Matrix'
1437 0 : do ii=1,deloc%ninternal
1438 0 : write(std_out,*) b_matrix(:,ii)
1439 : end do
1440 : end if
1441 :
1442 : call calc_btinv_matrix(b_matrix,natom,deloc%ninternal,&
1443 64 : & bt_inv_matrix,u_matrix)
1444 64 : if (DEBUG)then
1445 0 : write(std_out,*) 'BT Inverse Matrix'
1446 0 : do ii=1,3*natom
1447 0 : write(std_out,*) bt_inv_matrix(:,ii)
1448 : end do
1449 : end if
1450 :
1451 : !calculate value of delocalized internals
1452 :
1453 : call dgemv('T',deloc%ninternal,3*(natom-1),one,&
1454 64 : & u_matrix,deloc%ninternal,prim_int,1,zero,deloc_int,1)
1455 :
1456 64 : end subroutine xcart2deloc
1457 : !!***
1458 :
1459 :
1460 : !!****f* ABINIT/calc_btinv_matrix
1461 : !! NAME
1462 : !! calc_btinv_matrix
1463 : !!
1464 : !! FUNCTION
1465 : !!
1466 : !! INPUTS
1467 : !!
1468 : !! OUTPUT
1469 : !!
1470 : !! NOTES
1471 : !! bt_inv_matrix is inverse transpose of the delocalized
1472 : !! coordinate B matrix. b_matrix is the primitive internal B matrix
1473 : !!
1474 : !! SOURCE
1475 :
1476 64 : subroutine calc_btinv_matrix(b_matrix,natom,ninternal,bt_inv_matrix,u_matrix)
1477 :
1478 : !Arguments ------------------------------------
1479 : integer,intent(in) :: ninternal,natom
1480 : real(dp),intent(in) :: b_matrix(ninternal,3*natom)
1481 : real(dp),intent(out) :: bt_inv_matrix(3*(natom-1),3*natom)
1482 : real(dp),intent(inout) :: u_matrix(ninternal,3*(natom-1))
1483 :
1484 : !Local variables ------------------------------------
1485 : !scalars
1486 : integer :: ii,info,lwork
1487 : !arrays
1488 128 : real(dp) :: f_eigs(3*natom),f_matrix(3*natom,3*natom)
1489 128 : real(dp) :: s_matrix(3*natom,3*natom)
1490 128 : real(dp) :: s_red(3*natom,3*(natom-1))
1491 128 : real(dp) :: u_matrix_old(ninternal,3*(natom-1))
1492 64 : real(dp),allocatable :: work(:)
1493 :
1494 : !******************************************************************
1495 :
1496 : !f matrix = B^{T} B
1497 : call dgemm('T','N',3*natom,3*natom,ninternal,one,&
1498 64 : & b_matrix,ninternal,b_matrix,ninternal,zero,f_matrix,3*natom)
1499 :
1500 64 : lwork = max(1,3*3*natom-1)
1501 192 : ABI_MALLOC(work,(lwork))
1502 2752 : s_matrix(:,:) = f_matrix(:,:)
1503 :
1504 64 : call dsyev('V','L',3*natom,s_matrix,3*natom,f_eigs,work,lwork,info)
1505 :
1506 64 : ABI_FREE(work)
1507 :
1508 64 : if (abs(f_eigs(1)) + abs(f_eigs(2)) + abs(f_eigs(3)) > tol10 ) then
1509 0 : write(std_out,*) 'Error: 3 lowest eigenvalues are not zero'
1510 0 : write(std_out,*) ' internal coordinates do NOT span the full degrees of freedom !'
1511 0 : write(std_out,'(6E16.6)') f_eigs
1512 0 : ABI_ERROR("Aborting now")
1513 : end if
1514 64 : if ( abs(f_eigs(4)) < tol10 ) then
1515 0 : write(std_out,*) 'Error: fourth eigenvalue is zero'
1516 0 : write(std_out,*) ' internal coordinates do NOT span the full degrees of freedom !'
1517 0 : write(std_out,'(6E16.6)') f_eigs
1518 0 : ABI_ERROR("Aborting now")
1519 : end if
1520 :
1521 : !calculate U matrix from U = B * S_red * lambda^{-1/2}
1522 256 : do ii=1,3*(natom-1)
1523 1408 : s_red(:,ii) = s_matrix(:,ii+3)/sqrt(f_eigs(ii+3))
1524 : end do
1525 :
1526 10240 : u_matrix_old(:,:) = u_matrix(:,:)
1527 :
1528 : call dgemm('N','N',ninternal,3*(natom-1),3*natom,one,&
1529 64 : & b_matrix,ninternal,s_red,3*natom,zero,u_matrix,ninternal)
1530 :
1531 :
1532 : !align eigenvectors, to preserve a form of continuity in convergences
1533 : !!!! eigenvalues are no longer in increasing order!!! but only s_red is reordered
1534 : !so that btinv is correct.
1535 64 : call align_u_matrices(natom,ninternal,u_matrix,u_matrix_old,s_matrix,f_eigs)
1536 :
1537 : !calculate B_deloc^{-1} matrix for transformation of forces to deloc coord.
1538 : !(B^{T}_deloc)^{-1} = (B_deloc B^{T}_deloc)^{-1} B_deloc = lambda^{-3/2} S^{T} F
1539 : != ( S lambda^{3/2} )^{T} F
1540 :
1541 : !! DEFINITION
1542 : !! real(dp),intent(out) :: bt_inv_matrix(3*(natom-1),3*natom)
1543 :
1544 : !even better: B_deloc^{-1} = lambda^{-1/2} S^{T}
1545 256 : do ii=1,3*(natom-1)
1546 : ! s_red(:,ii) = s_matrix(:,ii+3)*sqrt(f_eigs(ii+3))
1547 1408 : bt_inv_matrix(ii,:) = s_matrix(:,ii+3)/sqrt(f_eigs(ii+3))
1548 : end do
1549 :
1550 64 : end subroutine calc_btinv_matrix
1551 : !!***
1552 :
1553 : !!****f* ABINIT/align_u_matrices
1554 : !! NAME
1555 : !! align_u_matrices
1556 : !!
1557 : !! FUNCTION
1558 : !!
1559 : !! INPUTS
1560 : !!
1561 : !! OUTPUT
1562 : !!
1563 : !! SOURCE
1564 :
1565 64 : subroutine align_u_matrices(natom,ninternal,u_matrix,u_matrix_old,s_matrix,f_eigs)
1566 :
1567 : !Arguments ------------------------------------
1568 : !scalars
1569 : integer,intent(in) :: ninternal,natom
1570 : !arrays
1571 : real(dp),intent(in) :: u_matrix_old(ninternal,3*(natom-1))
1572 : real(dp),intent(inout) :: f_eigs(3*natom)
1573 : real(dp),intent(inout) :: s_matrix(3*natom,3*natom)
1574 : real(dp),intent(inout) :: u_matrix(ninternal,3*(natom-1))
1575 :
1576 : !Local variables ------------------------------
1577 : !scalars
1578 : integer :: ii,iint1,imax
1579 : real(dp) :: ss
1580 : !arrays
1581 128 : integer :: eigv_flag(3*(natom-1)),eigv_ind(3*(natom-1))
1582 128 : real(dp) :: tmps(3*natom,3*natom)
1583 128 : real(dp) :: tmpu(ninternal,3*(natom-1))
1584 64 : real(dp) :: tmpf(3*natom)
1585 :
1586 : !******************************************************************
1587 :
1588 256 : eigv_flag(:) = 0
1589 256 : eigv_ind(:) = 0
1590 :
1591 : !just permit a change in sign
1592 256 : do iint1=1,3*(natom-1)
1593 : ss = zero
1594 10176 : do ii=1,ninternal
1595 10176 : ss = ss + u_matrix_old(ii,iint1)*u_matrix(ii,iint1)
1596 : end do
1597 192 : if (ss < -tol12) then
1598 0 : imax = -iint1
1599 : else
1600 : imax = iint1
1601 : end if
1602 192 : eigv_ind(iint1) = imax
1603 256 : eigv_flag(abs(imax)) = 1
1604 : end do
1605 :
1606 10240 : tmpu(:,:) = u_matrix
1607 2752 : tmps(:,:) = s_matrix
1608 448 : tmpf(:) = f_eigs
1609 : !exchange eigenvectors...
1610 256 : do iint1=1,3*(natom-1)
1611 192 : ss = one
1612 192 : if (eigv_ind(iint1) < 0) ss = -one
1613 :
1614 192 : imax = abs(eigv_ind(iint1))
1615 :
1616 10176 : tmpu(:,imax) = ss*u_matrix(:,iint1)
1617 :
1618 1344 : tmps(:,imax+3) = ss*s_matrix(:,iint1+3)
1619 :
1620 256 : tmpf(imax+3) = f_eigs(iint1+3)
1621 : end do
1622 :
1623 10240 : u_matrix(:,:) = tmpu(:,:)
1624 2752 : s_matrix(:,:) = tmps(:,:)
1625 448 : f_eigs(:) = tmpf(:)
1626 :
1627 64 : end subroutine align_u_matrices
1628 : !!***
1629 :
1630 : !!****f* ABINIT/xfh_recover_deloc
1631 : !! NAME
1632 : !! xfh_recover_deloc
1633 : !!
1634 : !! FUNCTION
1635 : !! Update the contents of the history xfhist taking values
1636 : !! from xred, acell, rprim, gred_corrected and strten
1637 : !!
1638 : !! INPUTS
1639 : !!
1640 : !! OUTPUT
1641 : !!
1642 : !! SOURCE
1643 :
1644 0 : subroutine xfh_recover_deloc(ab_xfh,ab_mover,acell,cycl_main,&
1645 0 : & gred,hessin,ndim,rprim,rprimd0,strten,ucvol,ucvol0,vin,vin_prev,&
1646 0 : & vout,vout_prev,xred,deloc,deloc_int,deloc_gred,btinv,gprimd,prim_int,&
1647 0 : & u_matrix)
1648 :
1649 : !Arguments ------------------------------------
1650 : !scalars
1651 :
1652 : integer,intent(in) :: ndim
1653 : integer,intent(out) :: cycl_main
1654 : real(dp),intent(inout) :: ucvol,ucvol0
1655 : type(ab_xfh_type),intent(inout) :: ab_xfh
1656 : type(abimover),intent(in) :: ab_mover
1657 : ! DELOCINT specials
1658 : type(delocint),intent(in) :: deloc
1659 :
1660 : !arrays
1661 : real(dp),intent(inout) :: acell(3)
1662 : real(dp),intent(inout) :: hessin(:,:)
1663 : real(dp),intent(inout) :: xred(3,ab_mover%natom)
1664 : real(dp),intent(inout) :: rprim(3,3)
1665 : real(dp),intent(inout) :: rprimd0(3,3)
1666 : real(dp),intent(inout) :: gred(3,ab_mover%natom)
1667 : real(dp),intent(inout) :: strten(6)
1668 : real(dp),intent(inout) :: vin(:)
1669 : real(dp),intent(inout) :: vin_prev(:)
1670 : real(dp),intent(inout) :: vout(:)
1671 : real(dp),intent(inout) :: vout_prev(:)
1672 : ! DELOCINT specials
1673 : real(dp),intent(inout) :: deloc_gred(3*(ab_mover%natom-1))
1674 : real(dp),intent(inout) :: deloc_int(3*(ab_mover%natom-1))
1675 : real(dp),intent(inout) :: btinv(3*(ab_mover%natom-1),3*ab_mover%natom)
1676 : real(dp),intent(inout) :: prim_int(:),u_matrix(:,:),gprimd(3,3)
1677 :
1678 : !Local variables-------------------------------
1679 : !scalars
1680 : integer :: ixfh
1681 0 : real(dp) :: xcart(3,ab_mover%natom)
1682 :
1683 : !*********************************************************************
1684 :
1685 0 : if(ab_xfh%nxfh/=0)then
1686 : ! Loop over previous time steps
1687 0 : do ixfh=1,ab_xfh%nxfh
1688 :
1689 : ! For that time step, get new (x,f) from xfhist
1690 0 : xred(:,:) =ab_xfh%xfhist(:,1:ab_mover%natom ,1,ixfh)
1691 0 : rprim(1:3,1:3)=ab_xfh%xfhist(:,ab_mover%natom+2:ab_mover%natom+4,1,ixfh)
1692 0 : acell(:) =ab_xfh%xfhist(:,ab_mover%natom+1,1,ixfh)
1693 0 : gred(:,:) =ab_xfh%xfhist(:,1:ab_mover%natom,2,ixfh)
1694 : ! This use of results_gs is unusual
1695 0 : strten(1:3) =ab_xfh%xfhist(:,ab_mover%natom+2,2,ixfh)
1696 0 : strten(4:6) =ab_xfh%xfhist(:,ab_mover%natom+3,2,ixfh)
1697 :
1698 : ! !DEBUG
1699 : ! write (ab_out,*) '---READ FROM XFHIST---'
1700 :
1701 : ! write (ab_out,*) 'XRED'
1702 : ! do kk=1,ab_mover%natom
1703 : ! write (ab_out,*) xred(:,kk)
1704 : ! end do
1705 : ! write (ab_out,*) 'FRED'
1706 : ! do kk=1,ab_mover%natom
1707 : ! write (ab_out,*) gred(:,kk)
1708 : ! end do
1709 : ! write(ab_out,*) 'RPRIM'
1710 : ! do kk=1,3
1711 : ! write(ab_out,*) rprim(:,kk)
1712 : ! end do
1713 : ! write(ab_out,*) 'ACELL'
1714 : ! write(ab_out,*) acell(:)
1715 : ! !DEBUG
1716 :
1717 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
1718 0 : call xred2xcart(ab_mover%natom,rprimd0,xcart,xred)
1719 : ! Convert input coordinates in Delocalized internals
1720 : call xcart2deloc(deloc,ab_mover%natom,rprimd0,xcart,&
1721 0 : & btinv,u_matrix,deloc_int,prim_int)
1722 : ! Convert forces to delocalized coordinates for next step
1723 0 : call gred2gdeloc(btinv,deloc_gred,gred,ab_mover%natom,gprimd)
1724 :
1725 : ! Transfer it in vin, vout
1726 : call xfpack_x2vin(acell,ab_mover%natom-1,&
1727 : & ndim,ab_mover%nsym,ab_mover%optcell,rprim,rprimd0,&
1728 0 : & ab_mover%symrel,ucvol,ucvol0,vin,deloc_int)
1729 : call xfpack_f2vout(deloc_gred,ab_mover%natom-1,&
1730 : & ndim,ab_mover%optcell,ab_mover%strtarget,strten,&
1731 0 : & ucvol,vout)
1732 : ! Get old time step, if any, and update inverse hessian
1733 0 : if(ixfh/=1)then
1734 0 : xred(:,:) =ab_xfh%xfhist(:,1:ab_mover%natom,1,ixfh-1)
1735 : rprim(1:3,1:3)=&
1736 0 : & ab_xfh%xfhist(:,ab_mover%natom+2:ab_mover%natom+4,1,ixfh-1)
1737 0 : acell(:)=ab_xfh%xfhist(:,ab_mover%natom+1,1,ixfh-1)
1738 0 : gred(:,:)=ab_xfh%xfhist(:,1:ab_mover%natom,2,ixfh-1)
1739 : ! This use of results_gs is unusual
1740 0 : strten(1:3)=ab_xfh%xfhist(:,ab_mover%natom+2,2,ixfh-1)
1741 0 : strten(4:6)=ab_xfh%xfhist(:,ab_mover%natom+3,2,ixfh-1)
1742 :
1743 : ! Convert input xred (reduced coordinates) to xcart (cartesian)
1744 0 : call xred2xcart(ab_mover%natom,rprimd0,xcart,xred)
1745 : ! Convert input coordinates in Delocalized internals
1746 : call xcart2deloc(deloc,ab_mover%natom,rprimd0,xcart,&
1747 0 : & btinv,u_matrix,deloc_int,prim_int)
1748 : ! Convert forces to delocalized coordinates for next step
1749 0 : call gred2gdeloc(btinv,deloc_gred,gred,ab_mover%natom,gprimd)
1750 :
1751 : ! Tranfer it in vin_prev, vout_prev
1752 : call xfpack_x2vin(acell,ab_mover%natom-1,&
1753 : & ndim,ab_mover%nsym,ab_mover%optcell,rprim,rprimd0,&
1754 0 : & ab_mover%symrel,ucvol,ucvol0,vin_prev,deloc_int)
1755 : call xfpack_f2vout(deloc_gred,ab_mover%natom-1,&
1756 : & ndim,ab_mover%optcell,ab_mover%strtarget,strten,&
1757 0 : & ucvol,vout_prev)
1758 :
1759 : ! write(ab_out,*) 'Hessian matrix before update',ndim,'x',ndim
1760 : ! write(ab_out,*) 'ixfh=',ixfh
1761 : ! do kk=1,ndim
1762 : ! do jj=1,ndim,3
1763 : ! if (jj+2<=ndim)then
1764 : ! write(ab_out,*) jj,hessin(jj:jj+2,kk)
1765 : ! else
1766 : ! write(ab_out,*) jj,hessin(jj:ndim,kk)
1767 : ! end if
1768 : ! end do
1769 : ! end do
1770 :
1771 : call hessupdt(hessin,ab_mover%iatfix,ab_mover%natom-1,ndim,&
1772 0 : & vin,vin_prev,vout,vout_prev)
1773 :
1774 : ! !DEBUG
1775 : ! write(ab_out,*) 'Hessian matrix after update',ndim,'x',ndim
1776 : ! do kk=1,ndim
1777 : ! do jj=1,ndim,3
1778 : ! if (jj+2<=ndim)then
1779 : ! write(ab_out,*) jj,hessin(jj:jj+2,kk)
1780 : ! else
1781 : ! write(ab_out,*) jj,hessin(jj:ndim,kk)
1782 : ! end if
1783 : ! end do
1784 : ! end do
1785 : ! !DEBUG
1786 :
1787 : end if !if(ab_xfh%nxfh/=0)
1788 :
1789 : ! End loop over previous time steps
1790 : end do
1791 :
1792 : ! The hessian has been generated,
1793 : ! as well as the latest vin and vout
1794 : ! so will cycle the main loop
1795 0 : cycl_main=1
1796 :
1797 : end if
1798 :
1799 0 : end subroutine xfh_recover_deloc
1800 : !!***
1801 :
1802 1 : end module m_pred_delocint
1803 : !!***
|