LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_pred_delocint.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.4 % 562 424
Test Date: 2026-09-19 15:24:51 Functions: 92.3 % 13 12

            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              : !!***
        

Generated by: LCOV version 2.3-1