TABLE OF CONTENTS


ABINIT/erlxconv [ Functions ]

[ Top ] [ Functions ]

NAME

  erlxconv

FUNCTION

  FIXME: add description.

INPUTS

OUTPUT

SOURCE

1166 subroutine erlxconv(hist,iexit,itime,itime_hist,ntime,tolmxde)
1167 
1168 !Arguments ------------------------------------
1169 !scalars
1170  integer,intent(in) :: itime,itime_hist,ntime
1171  integer,intent(inout) :: iexit
1172  real(dp), intent(in) :: tolmxde
1173 !arrays
1174  type(abihist),intent(inout) :: hist
1175 
1176 !Local variables-------------------------------
1177  integer :: ihist,ihist_prev,ihist_prev2
1178  real(dp) :: ediff1,ediff2,maxediff
1179  character(len=500) :: msg
1180 ! *************************************************************************
1181 
1182  if (itime_hist<3) then
1183    write(msg, '(a,a,a)' ) ch10,&
1184    ' erlxconv : minimum 3 Broyd/MD steps to check convergence of energy in relaxations',ch10
1185    call wrtout(std_out,msg,'COLL')
1186  else
1187    ihist = hist%ihist
1188    ihist_prev  = abihist_findIndex(hist,-1)
1189    ihist_prev2 = abihist_findIndex(hist,-2)
1190    ediff1 = hist%etot(ihist) - hist%etot(ihist_prev)
1191    ediff2 = hist%etot(ihist) - hist%etot(ihist_prev2)
1192    if ((abs(ediff1)<tolmxde).and.(abs(ediff2)<tolmxde)) then
1193      write(msg, '(a,a,i4,a,a,a,a,a,es11.4,a,a)' ) ch10,&
1194      ' At Broyd/MD step',itime,', energy is converged : ',ch10,&
1195      '  the difference in energy with respect to the two ',ch10,&
1196      '  previous steps is < tolmxde=',tolmxde,' ha',ch10
1197      call wrtout([std_out, ab_out], msg)
1198      iexit=1
1199    else
1200      maxediff = max(abs(ediff1),abs(ediff2))
1201      if(iexit==1)then
1202        write(msg, '(a,a,a,a,i5,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
1203        ' erlxconv : WARNING -',ch10,&
1204        '  ntime=',ntime,' was not enough Broyd/MD steps to converge energy: ',ch10,&
1205        '  max difference in energy =',maxediff,' > tolmxde=',tolmxde,' ha',ch10
1206        call wrtout([std_out, ab_out], msg)
1207 
1208        write(std_out,"(8a)")ch10,&
1209        "--- !RelaxConvergenceWarning",ch10,&
1210        "message: | ",ch10,TRIM(indent(msg)),ch10,&
1211        "..."
1212      else
1213        write(msg, '(a,a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
1214        ' erlxconv : at Broyd/MD step',itime,', energy has not converged yet. ',ch10,&
1215        '  max difference in energy=',maxediff,' > tolmxde=',tolmxde,' ha',ch10
1216        call wrtout(std_out,msg,'COLL')
1217      end if
1218    end if
1219  end if
1220 
1221 end subroutine erlxconv

ABINIT/fconv [ Functions ]

[ Top ] [ Functions ]

NAME

 fconv

FUNCTION

 Check maximal absolute value of force (hartree/bohr) against input tolerance; if below tolerance, return iexit=1.
 Takes into account the fact that the Broyden (or moldyn) step
 might be the last one (last itime), to print eventually modified message.
 Stresses are also included in the check, provided that optcell/=0.

 If optcell=1, takes only the trace into account
    optcell=2, takes all components into account
    optcell=3, takes traceless stress into account
    optcell=4, takes sigma(1 1) into account
    optcell=5, takes sigma(2 2) into account
    optcell=6, takes sigma(3 3) into account
    optcell=7, takes sigma(2,2),(2,3) and (3 3) into account
    optcell=8, takes sigma(1,1),(1,3) and (3 3) into account
    optcell=9, takes sigma(1,1),(1,2) and (2 2) into account
 In the case of stresses, target the tensor strtarget, and take into account the factor strfact

INPUTS

  fcart(3,natom)= forces on atoms in hartree/bohr in cartesian coordinates
  iatfix(3,natom)=1 for frozen atom, 0 for unfrozen
  itime=current number of Broyden/Moldyn iterations
  natom=number of atoms in unit cell
  ntime=maximum number of Broyden/Moldyn iterations allowed
  optcell=option for taking stresses into account (see above)
  strfact=factor that multiplies the stresses when they are compared to forces.
  strtarget(6)=components of the target stress tensor (hartree/bohr^3)
  strten(6)=components of the stress tensor (hartree/bohr^3)
  tolmxf=tolerance on maximal absolute value of components of forces

OUTPUT

  writes to unit std_out and to ab_out, and returns

SIDE EFFECTS

 Input/Output
  at input  : iexit=  0 if not the last itime,  1 if the last itime
  at output : iexit=  0 if not below tolerance, 1 if below tolerance

SOURCE

1028 subroutine fconv(fcart,iatfix,iexit,itime,natom,ntime,optcell,strfact,strtarget,strten,rprim,tolmxf)
1029 
1030 !Arguments ------------------------------------
1031 !scalars
1032  integer,intent(in) :: itime,natom,ntime,optcell
1033  integer,intent(inout) :: iexit
1034  real(dp),intent(in) :: strfact,tolmxf
1035 !arrays
1036  integer,intent(in) :: iatfix(3,natom)
1037  real(dp),intent(in) :: fcart(3,natom),strtarget(6),strten(6)
1038  real(dp), intent(in) :: rprim(3,3)
1039 
1040 !Local variables-------------------------------
1041 !scalars
1042  integer :: iatom,idir,istr
1043  real(dp) :: fmax,strdiag!,fcell
1044  character(len=500) :: msg
1045 !arrays
1046  real(dp) :: dstr(6)
1047 
1048 ! *************************************************************************
1049 
1050 ABI_UNUSED(rprim)
1051 
1052 !Compute maximal component of forces, EXCLUDING any fixed components
1053  fmax=zero
1054  do iatom=1,natom
1055    do idir=1,3
1056      if (iatfix(idir,iatom) /= 1) then
1057        if( abs(fcart(idir,iatom)) >= fmax ) fmax=abs(fcart(idir,iatom))
1058      end if
1059    end do
1060  end do
1061 
1062  dstr(:)=strten(:)-strtarget(:)
1063 
1064 !Eventually take into account the stress
1065  if(optcell==1)then
1066    strdiag=(dstr(1)+dstr(2)+dstr(3))/3.0_dp
1067    if(abs(strdiag)*strfact >= fmax ) fmax=abs(strdiag)*strfact
1068  else if(optcell==2)then
1069    do istr=1,6
1070      if(abs(dstr(istr))*strfact >= fmax ) fmax=abs(dstr(istr))*strfact
1071    end do
1072  else if(optcell==3)then
1073 !  Must take away the trace from diagonal elements
1074    strdiag=(dstr(1)+dstr(2)+dstr(3))/3.0_dp
1075    do istr=1,3
1076      if(abs(dstr(istr)-strdiag)*strfact >= fmax ) fmax=abs(dstr(istr)-strdiag)*strfact
1077    end do
1078    do istr=4,6
1079      if(abs(dstr(istr))*strfact >= fmax ) fmax=abs(dstr(istr))*strfact
1080    end do
1081 !  else if(optcell==4 .or. optcell==5 .or. optcell==6)then
1082 !    if(abs(dstr(optcell-3))*strfact >= fmax ) fmax=abs(dstr(optcell-3))*strfact
1083  else if(optcell==4) then
1084    ! only dstr 1 5 6 are in xfpack_f2vout. The other component shouldn't be checked.
1085    !fcell = dstr(1) * rprim(1,1) + dstr(6) * rprim(2,1) + dstr(5) * rprim(3,1)
1086    !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1087    !fcell = dstr(6) * rprim(1,1)
1088    !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1089    !fcell = dstr(5) * rprim(1,1)
1090    !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1091    fmax = maxval(abs(dstr([1, 5, 6])))*strfact
1092  else if(optcell==5) then ! 2 4 6
1093     !fcell = dstr(5) * rprim(3,3)
1094     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1095     !fcell = dstr(6) * rprim(1,2) + dstr(2) * rprim(2,2) + dstr(4) * rprim(3,2)
1096     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1097     !fcell = dstr(4) * rprim(2,2)
1098     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1099    fmax = maxval(abs(dstr([2, 4, 6])))*strfact
1100  else if(optcell==6) then
1101     !fcell =  dstr(5) * rprim(3,3)
1102     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1103     !fcell =  dstr(4) * rprim(3,3)
1104     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1105     !fcell = dstr(5) * rprim(1,3) + dstr(4) * rprim(2,3) + dstr(3) * rprim(3,3)
1106     !if (abs(fcell)*strfact >= fmax) fmax=abs(fcell)*strfact
1107     fmax = maxval(abs(dstr([3, 4, 5])))*strfact
1108  else if(optcell==7)then
1109    if(abs(dstr(2))*strfact >= fmax ) fmax=abs(dstr(2))*strfact
1110    if(abs(dstr(3))*strfact >= fmax ) fmax=abs(dstr(3))*strfact
1111    if(abs(dstr(4))*strfact >= fmax ) fmax=abs(dstr(4))*strfact
1112  else if(optcell==8)then
1113    if(abs(dstr(1))*strfact >= fmax ) fmax=abs(dstr(1))*strfact
1114    if(abs(dstr(3))*strfact >= fmax ) fmax=abs(dstr(3))*strfact
1115    if(abs(dstr(5))*strfact >= fmax ) fmax=abs(dstr(5))*strfact
1116  else if(optcell==9)then
1117    if(abs(dstr(1))*strfact >= fmax ) fmax=abs(dstr(1))*strfact
1118    if(abs(dstr(2))*strfact >= fmax ) fmax=abs(dstr(2))*strfact
1119    if(abs(dstr(6))*strfact >= fmax ) fmax=abs(dstr(6))*strfact
1120  end if
1121 
1122  if (fmax<tolmxf) then
1123    write(msg, '(a,a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
1124     ' At Broyd/MD step',itime,', gradients are converged : ',ch10,&
1125     '  max grad (force/stress) =',fmax,' < tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
1126    call wrtout([std_out, ab_out], msg)
1127    iexit=1
1128  else
1129    if(iexit==1)then
1130      write(msg, '(a,a,a,a,i5,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
1131       ' fconv : WARNING -',ch10,&
1132       '  ntime=',ntime,' was not enough Broyd/MD steps to converge gradients: ',ch10,&
1133       '  max grad (force/stress) =',fmax,' > tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
1134      call wrtout([std_out, ab_out], msg)
1135 
1136      write(std_out,"(8a)")ch10,&
1137        "--- !RelaxConvergenceWarning",ch10,&
1138        "message: | ",ch10,TRIM(indent(msg)),ch10,&
1139        "..."
1140 
1141    else
1142      write(msg, '(a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) &
1143        ' fconv : at Broyd/MD step',itime,', gradients have not converged yet. ',ch10,&
1144       '  max grad (force/stress) =',fmax,' > tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
1145      call wrtout(std_out,msg,'COLL')
1146    end if
1147    iexit=0
1148  end if
1149 
1150 end subroutine fconv

ABINIT/gettag [ Functions ]

[ Top ] [ Functions ]

NAME

 gettag

FUNCTION

 Set the tag associated to each atom,

INPUTS

 prtallatoms = Logical for PRTint ALL ATOMS
 atlist      = ATom LIST
 index       = index for each atom
 natom       = Number of ATOMs

OUTPUT

  tag = The string to put for each atom

SOURCE

1512 subroutine gettag(atlist,index,natom,prtallatoms,tag)
1513 
1514 !Arguments ------------------------------------
1515 !scalars
1516   logical,intent(in) :: prtallatoms
1517   integer,intent(in) :: natom
1518   logical,intent(in) :: atlist(natom)
1519   integer,intent(in) :: index
1520   character(len=7),intent(out)   :: tag
1521 
1522 ! *********************************************************************
1523 !The numbering will be from (1) to (9999)
1524 
1525  if (prtallatoms)then
1526    tag=''
1527  elseif (atlist(index)) then
1528    if (natom<10) then
1529      write(tag, '(a,I1.1,a)') ' (',index,')'
1530    elseif (natom<100) then
1531      write(tag, '(a,I2.2,a)') ' (',index,')'
1532    elseif (natom<1000) then
1533      write(tag, '(a,I3.3,a)') ' (',index,')'
1534    elseif (natom<10000) then
1535      write(tag, '(a,I4.4,a)') ' (',index,')'
1536    end if
1537  end if
1538 
1539  end subroutine gettag

ABINIT/m_mover [ Modules ]

[ Top ] [ Modules ]

NAME

  m_mover

FUNCTION

 Move ion or change acell according to forces and stresses

COPYRIGHT

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

SOURCE

16 #if defined HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19 
20 #include "abi_common.h"
21 
22 module m_mover
23 
24  use defs_basis
25  use m_abicore
26  use m_errors
27  use m_profiling_abi
28  use m_abimover
29  use m_abihist
30  use m_dtset
31  use m_xmpi
32  use m_nctk
33  use m_dtfil
34  use m_yaml
35 #ifdef HAVE_NETCDF
36  use netcdf
37 #endif
38 #if defined HAVE_LOTF
39  use lotfpath
40  use m_pred_lotf
41 #endif
42 
43  use defs_abitypes,        only : MPI_type
44  use m_fstrings,           only : strcat, sjoin, indent, itoa
45  use m_symtk,              only : matr3inv, symmetrize_xred
46  use m_geometry,           only : fcart2gred, chkdilatmx, xred2xcart
47  use m_time,               only : abi_wtime, sec2str
48  use m_exit,               only : get_start_time, have_timelimit_in, get_timelimit, enable_timelimit_in
49  use m_electronpositron,   only : electronpositron_type
50  use m_scfcv,              only : scfcv_t, scfcv_run
51  use m_effective_potential,only : effective_potential_type, effective_potential_evaluate
52  use m_initylmg,           only : initylmg
53  use m_xfpack,             only : xfh_update
54  use m_precpred_1geo,      only : precpred_1geo
55  use m_pred_delocint,      only : pred_delocint
56  use m_pred_bfgs,          only : pred_bfgs, pred_lbfgs
57  use m_pred_fire,          only : pred_fire
58  use m_pred_isokinetic,    only : pred_isokinetic
59  use m_pred_diisrelax,     only : pred_diisrelax
60  use m_pred_nose,          only : pred_nose
61  use m_pred_srkhna14,      only : pred_srkna14
62  use m_pred_isothermal,    only : pred_isothermal
63  use m_pred_verlet,        only : pred_verlet
64  use m_pred_velverlet,     only : pred_velverlet
65  use m_pred_moldyn,        only : pred_moldyn
66  use m_pred_langevin,      only : pred_langevin
67  use m_pred_steepdesc,     only : pred_steepdesc
68  use m_pred_simple,        only : pred_simple, prec_simple
69  use m_pred_hmc,           only : pred_hmc
70 !use m_generate_training_set, only : generate_training_set
71  use m_wvl_wfsinp, only : wvl_wfsinp_reformat
72  use m_wvl_rho,      only : wvl_mkrho
73  use m_effective_potential_file, only : effective_potential_file_mapHistToRef
74 #if defined DEV_MS_SCALEUP
75  use scup_global, only : global_set_parent_iter,global_set_print_parameters
76 #endif
77  use m_scup_dataset
78 
79  implicit none
80 
81  private

ABINIT/mover [ Functions ]

[ Top ] [ Functions ]

NAME

 mover

FUNCTION

 Move ion or change acell acording to forces and stresses

INPUTS

  amu_curr(ntypat)=mass of each atom for the current image
  dtfil <type(datafiles_type)>=variables related to files
  dtset <type(dataset_type)>=all input variables for this dataset
   | mband=maximum number of bands
   | mgfft=maximum size of 1D FFTs
   | mkmem =number of k points treated by this node
   |  angular momentum for nonlocal pseudopotential
   | mpw=maximum dimensioned size of npw.
   | natom=number of atoms in unit cell
   |  except on first call (hartree/bohr); updated on output
   | nfft=(effective) number of FFT grid points (for this processor)
   |      for the "coarse" grid (see NOTES below)
   | nkpt=number of k points.
   | nspden=number of spin-density components
   | nsppol=1 for unpolarized, 2 for spin-polarized
   | nsym=number of symmetry elements in space group
  itimimage_gstate= [optional] counter for the itimimage loop, in the calling routine.
  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
  mpi_enreg=information about MPI parallelization
  nfftf=(effective) number of FFT grid points (for this processor)
       for the "fine" grid (see NOTES below)
  npwarr(nkpt)=number of planewaves in basis and boundary at this k point.
  nattyp(ntypat)= # atoms of each type.
  paw_dmft  <type(paw_dmft_type)>= paw+dmft related data
  psps <type(pseudopotential_type)>=variables related to pseudopotentials
   | mpsang= 1+maximum angular momentum for nonlocal pseudopotentials
  rprimd(3,3)=dimensional primitive translations (bohr)
  scup_dtset <type(scup_dtset_type) = derived datatype holding all options
            for the evaluation of an effective electronic model using SCALE UP

OUTPUT

  results_gs <type(results_gs_type)>=results (energy and its components,
   forces and its components, the stress tensor) of a ground-state computation
  eigen(mband*nkpt*nsppol)=array for holding eigenvalues (hartree)
  resid(mband*nkpt*nsppol)=residuals for each band over all k points.

SIDE EFFECTS

 Rest of i/o is related to lda
  acell(3)=length scales of primitive translations (bohr)
  cg(2,mcg)=array for planewave coefficients of wavefunctions.
  electronpositron <type(electronpositron_type)>=quantities for the electron-positron annihilation
  initialized= if 0 the initialisation of the gstate run is not yet finished
  irrzon(nfft**(1-1/nsym),2,(nspden/nsppol)-3*(nspden/4))=irreducible zone data
  occ(mband*nkpt*nsppol=occupation number for each band (usually 2) at each k point.
  rhog(2,nfftf)=array for Fourier transform of electron density
  rhor(nfftf,nspden)=array for electron density in electrons/bohr**3.
  scf_history <type(scf_history_type)>=arrays obtained from previous SCF cycles
  symrec(3,3,nsym)=symmetry operations in reciprocal space
  taug(2,nfftf*dtset%usekden)=array for Fourier transform of kinetic energy density
  taur(nfftf,nspden*dtset%usekden)=array for kinetic energy density
  vel(3,natom)=old value of velocity; updated on output
  vel_cell(3,3)=old value of cell parameters velocity; updated on output
  xred(3,natom)=reduced dimensionless atomic coordinates; updated on output
  xred_old(3,natom)=work space for old xred
  eff_pot<type(effective_potential_type)> = optional,effective_potential datatype
  verbose = optional, default is true, flag to disable the verbose mode
  write_HIST = optional, default is true, flag to disble the write of the HIST file

NOTES

 This subroutine uses the arguments natom, xred, vel, amu_curr,
 vis, and dtion (the last two contained in dtset) to make
 molecular dynamics updates.  The rest of the lengthy
 argument list supports the underlying lda computation
 of forces, returned from subroutine scfcv

 USE OF FFT GRIDS:
 =================
 In case of PAW:
 ---------------
    Two FFT grids are used:
    - A "coarse" FFT grid (defined by ecut)
      for the application of the Hamiltonian on the plane waves basis.
      It is defined by nfft, ngfft, mgfft, ...
      Hamiltonian, wave-functions, density related to WFs (rhor here), ...
      are expressed on this grid.
    - A "fine" FFT grid (defined) by ecutdg)
      for the computation of the density inside PAW spheres.
      It is defined by nfftf, ngfftf, mgfftf, ...
      Total density, potentials, ...
      are expressed on this grid.
 In case of norm-conserving:
 ---------------------------
    - Only the usual FFT grid (defined by ecut) is used.
      It is defined by nfft, ngfft, mgfft, ...
      For compatibility reasons, (nfftf,ngfftf,mgfftf)
      are set equal to (nfft,ngfft,mgfft) in that case.

SOURCE

187 subroutine mover(scfcv_args,ab_xfh,acell,amu_curr,dtfil,&
188 & electronpositron,rhog,rhor,rprimd,vel,vel_cell,xred,xred_old,&
189 & effective_potential,filename_ddb,itimimage_gstate,verbose,writeHIST,scup_dtset,sc_size)
190 
191 !Arguments ------------------------------------
192 !scalars
193 integer, intent(in), optional :: itimimage_gstate
194 type(scfcv_t),intent(inout) :: scfcv_args
195 type(datafiles_type),intent(inout),target :: dtfil
196 type(electronpositron_type),pointer :: electronpositron
197 type(ab_xfh_type),intent(inout) :: ab_xfh
198 type(effective_potential_type),optional,intent(inout) :: effective_potential
199 logical,optional,intent(in) :: verbose
200 logical,optional,intent(in) :: writeHIST
201 character(len=fnlen),optional,intent(in) :: filename_ddb
202 !arrays
203 real(dp),intent(inout) :: acell(3)
204 real(dp), intent(in),target :: amu_curr(:) !(scfcv%dtset%ntypat)
205 real(dp), pointer :: rhog(:,:),rhor(:,:)
206 real(dp), intent(inout) :: xred(3,scfcv_args%dtset%natom),xred_old(3,scfcv_args%dtset%natom)
207 real(dp), intent(inout) :: vel(3,scfcv_args%dtset%natom),vel_cell(3,3),rprimd(3,3)
208 type(scup_dtset_type),optional, intent(inout) :: scup_dtset
209 integer,optional,intent(in) :: sc_size(3)
210 
211 !Local variables-------------------------------
212 !scalars
213 integer,parameter :: level=102,master=0
214 type(abihist) :: hist,hist_prev
215 type(abimover) :: ab_mover
216 type(abimover_specs) :: specs
217 type(abiforstr) :: preconforstr ! Preconditioned forces and stress
218 type(delocint) :: deloc
219 type(mttk_type) :: mttk_vars
220 integer :: itime,icycle,itime_hist,iexit=0,ifirst,ihist_prev,ihist_prev2,timelimit_exit,ncycle,nhisttot,kk,jj,me
221 integer :: ntime,option,comm
222 integer :: nerr_dilatmx,my_quit,ierr,quitsum_request
223 integer ABI_ASYNC :: quitsum_async
224 character(len=500) :: msg
225 !character(len=500) :: dilatmx_errmsg
226 character(len=8) :: stat4xml
227 character(len=35) :: fmt
228 character(len=fnlen) :: filename,fname_ddb,name_file
229 character(len=500) :: MY_NAME = "mover"
230 real(dp) :: gr_avg
231 logical :: DEBUG=.FALSE., need_verbose=.TRUE.,need_writeHIST=.TRUE.
232 logical :: need_scfcv_cycle = .TRUE., need_elec_eval = .FALSE.
233 logical :: changed,useprtxfase
234 logical :: skipcycle
235 integer :: minIndex,ii,similar,conv_retcode
236 integer :: iapp
237 logical :: file_exists
238 real(dp) :: minE,wtime_step,now,prev
239 !arrays
240 integer :: itimes(2)
241 real(dp) :: gprimd(3,3),rprim(3,3),rprimd_prev(3,3)
242 real(dp),allocatable :: gred_corrected(:,:),xred_prev(:,:)
243 ! ***************************************************************
244  need_verbose=.TRUE.
245  if(present(verbose)) need_verbose = verbose
246 
247  need_writeHIST=.TRUE.
248  if(present(writeHIST)) need_writeHIST = writeHIST
249 
250  ! enable time limit handler if not done in callers.
251  if (enable_timelimit_in(MY_NAME) == MY_NAME) then
252    if (need_verbose) then
253      write(std_out,*)"Enabling timelimit check in function: ",trim(MY_NAME)," with timelimit: ",trim(sec2str(get_timelimit()))
254    end if
255  end if
256 
257 !Table of contents
258 !(=>) Refers to an important call (scfcv,pred_*)
259 !
260 !01. Initialization of indexes and allocations of arrays
261 !02. Particularities of each predictor
262 !03. Set the number of iterations ntime
263 !04. Try to read history of previous calculations
264 !05. Allocate the hist structure
265 !06. First output before any itime or icycle
266 !07. Fill the history of the first SCFCV
267 !08. Loop for itime (From 1 to ntime)
268 !09. Loop for icycle (From 1 to ncycle)
269 !10. Output for each icycle (and itime)
270 !11. Symmetrize atomic coordinates over space group elements
271 !12. => Call to SCFCV routine and fill history with forces
272 !13. Write the history into the _HIST file
273 !14. Output after SCFCV
274 !15. => Test Convergence of forces and stresses
275 !16. => Precondition forces, stress and energy
276 !17. => Call to each predictor
277 !18. Use the history  to extract the new values
278 !19. End loop icycle
279 !20. End loop itime
280 !21. Set the final values of xred
281 !22. XML Output at the end
282 !23. Deallocate hist and ab_mover datatypes
283 !
284  call abimover_ini(ab_mover,amu_curr,dtfil,scfcv_args%dtset,specs)
285 
286  if (ab_mover%ionmov==10 .or. ab_mover%ionmov==11) call delocint_ini(deloc)
287 
288  if (ab_mover%ionmov==13 .or. ab_mover%ionmov==25)then
289    call mttk_ini(mttk_vars,ab_mover%nnos)
290  end if
291 
292 !###########################################################
293 !### 03. Set the number of iterations ntime
294 !###     By default ntime==1 but if the user enters a lower
295 !###     value, mover will execute at least one iteration
296 
297  if (scfcv_args%dtset%ntime<1)then
298    ntime=1
299  else
300    ntime=scfcv_args%dtset%ntime
301  end if
302 
303 !###########################################################
304 !### 04. Try to read history of previous calculations
305 !###     It requires NetCDF library
306 
307 !Init MPI data
308  comm=scfcv_args%mpi_enreg%comm_cell
309  me=xmpi_comm_rank(comm)
310 
311 
312 #if defined HAVE_NETCDF
313  filename=trim(ab_mover%filnam_ds(4))//'_HIST.nc'
314 
315  if (ab_mover%restartxf<0)then
316 !  Read history from file (and broadcast if MPI)
317    if (me==master) then
318      call read_md_hist(filename,hist_prev,specs%isVused,specs%isARused,ab_mover%restartxf==-3)
319    end if
320    call abihist_bcast(hist_prev,master,comm)
321 
322 !  If restartxf specifies to reconstruct the history
323    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-1)then
324      ntime=ntime+hist_prev%mxhist
325    end if
326 
327 !  If restartxf specifies to start from the lowest energy
328    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-2)then
329      minE=hist_prev%etot(1)
330      minIndex=1
331      do ii=1,hist_prev%mxhist
332        if(need_verbose) write(std_out,*) 'Iteration:',ii,' Total Energy:',hist_prev%etot(ii)
333        if (minE>hist_prev%etot(ii))then
334          minE=hist_prev%etot(ii)
335          minIndex=ii
336        end if
337      end do
338      if(need_verbose)write(std_out,*) 'The lowest energy occurs at iteration:',minIndex,'etotal=',minE
339      acell(:)   =hist_prev%acell(:,minIndex)
340      rprimd(:,:)=hist_prev%rprimd(:,:,minIndex)
341      xred(:,:)  =hist_prev%xred(:,:,minIndex)
342      vel(:, :) = hist_prev%vel(:, :, minIndex)
343      call abihist_free(hist_prev)
344    end if
345 !  If restarxf specifies to start to the last iteration
346    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-3)then
347      if(present(effective_potential))then
348        call effective_potential_file_mapHistToRef(effective_potential,hist_prev,comm,scfcv_args%dtset%iatfix,need_verbose,sc_size) ! Map Hist to Ref to order atoms
349        !xred(:,:) = hist_prev%xred(:,:,1) ! Fill xred with new ordering
350        hist%ihist = 1
351      end if
352      acell(:)   =hist_prev%acell(:,hist_prev%mxhist)
353      rprimd(:,:)=hist_prev%rprimd(:,:,hist_prev%mxhist)
354      xred(:,:)  =hist_prev%xred(:,:,hist_prev%mxhist)
355      vel(:, :) = hist_prev%vel(:, :, hist_prev%mxhist)
356      call abihist_free(hist_prev)
357    end if
358 
359  end if !if (ab_mover%restartxf<=0)
360 #endif
361 
362 !###########################################################
363 !### 05. Allocate the hist structure
364 
365  iexit=0; timelimit_exit=0
366  ncycle=specs%ncycle
367 
368  if(ab_mover%ionmov==25.and.scfcv_args%dtset%hmctt>=0)then
369    ncycle=scfcv_args%dtset%hmctt
370    if(scfcv_args%dtset%hmcsst>0.and.ab_mover%optcell/=0)then
371       ncycle=ncycle+scfcv_args%dtset%hmcsst
372    endif
373  endif
374 
375  nhisttot=ncycle*ntime;if (scfcv_args%dtset%nctime>0) nhisttot=nhisttot+1
376 !AM_2017 New version of the hist, we just store the needed history step not all of them...
377  if(specs%nhist/=-1)then
378   nhisttot = specs%nhist! We don't need to store all the history
379  endif
380 
381  call abihist_init(hist,ab_mover%natom,nhisttot,specs%isVused,specs%isARused)
382  call abiforstr_ini(preconforstr,ab_mover%natom)
383 
384 !###########################################################
385 !### 06. First output before any itime or icycle iteration
386 
387 !If effective potential is present forces will be compute with it
388  if (present(effective_potential))then
389    need_scfcv_cycle = .FALSE.
390    if(need_verbose)then
391      write(msg,'(2a,i2,5a,80a)')&
392 &     ch10,'=== [ionmov=',ab_mover%ionmov,'] ',trim(specs%method),' with effective potential',&
393 &     ch10,('=',kk=1,80)
394      call wrtout([std_out, ab_out], msg)
395    end if
396    need_elec_eval = .FALSE.
397    if(present(scup_dtset))then
398      need_elec_eval = scup_dtset%scup_elec_model
399    endif
400  else
401    if(need_verbose)then
402      write(msg,'(a,a,i2,a,a,a,80a)')&
403 &     ch10,'=== [ionmov=',ab_mover%ionmov,'] ',specs%method,&
404 &     ch10,('=',kk=1,80)
405      call wrtout([std_out, ab_out], msg)
406    end if
407  end if
408 
409 !Format for printing on each cycle
410  write(fmt,'(a6,i2,a4,i2,a4,i2,a4,i2,a9)')&
411   '(a,a,i',int(log10(real(ntime))+1),&
412   ',a,i',int(log10(real(ntime))+1),&
413   ',a,i',int(log10(real(ncycle))+1),&
414   ',a,i',int(log10(real(ncycle))+1),&
415   ',a,a,80a)'
416 
417 !###########################################################
418 !### 07. Fill the history of the first SCFCV
419 
420  if (ab_mover%ionmov==26)then
421 
422 !Tdep call need to merge with adewandre branch
423   else if (ab_mover%ionmov==27)then
424     if(present(filename_ddb))then
425       fname_ddb = trim(filename_ddb)
426     else
427       fname_ddb = trim(ab_mover%filnam_ds(3))//'_DDB'
428     end if
429     INQUIRE(FILE=filename, EXIST=file_exists)
430 
431     ABI_ERROR("This section has been disabled, ph_freez_disp is not defined in main ABINIT")
432 
433 ! XG 20200322 : The input variables ph_freez_disp are not documented neither tested, so they
434 ! have been removed from the allowed list in the parser. Also, you should not be here !
435 !   call generate_training_set(acell,ab_mover%ph_freez_disp_addStrain==1,ab_mover%ph_freez_disp_ampl,&
436 !&                             fname_ddb,hist,ab_mover%natom,ab_mover%ph_freez_disp_nampl,ntime,&
437 !&                             ab_mover%ph_ngqpt,ab_mover%ph_nqshift,ab_mover%ph_freez_disp_option,&
438 !&                             ab_mover%ph_qshift,scfcv_args%dtset%supercell_latt,&
439 !&                             rprimd,ab_mover%mdtemp(2),xred,comm,DEBUG)
440 
441 
442     !Fill history with the values of xred, acell and rprimd of the first configuration
443     acell(:)   =hist%acell(:,1)
444     rprimd(:,:)=hist%rprimd(:,:,1)
445     xred(:,:)  =hist%xred(:,:,1)
446 
447  else
448 
449    ! Fill history with the values of xred, acell and rprimd
450    call var2hist(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
451 
452    ! Fill velocities and ionic kinetic energy
453    call vel2hist(ab_mover%amass,hist,vel,vel_cell)
454    hist%time(hist%ihist)=zero
455 
456  end if
457 
458 !Decide if prtxfase will be called
459  useprtxfase=.FALSE.
460  do ii=1,ab_mover%natom
461    if (ab_mover%prtatlist(ii)/=0)then
462      useprtxfase=.TRUE.; exit
463    end if
464  end do
465 
466 !At beginning no error
467  nerr_dilatmx = 0
468 
469  ABI_MALLOC(xred_prev,(3,scfcv_args%dtset%natom))
470 
471 !###########################################################
472 !### 08. Loop for itime (From 1 to ntime)
473  quitsum_request = xmpi_request_null
474 
475  do itime=1,ntime
476 
477    call yaml_iterstart("itime", itime, dev_null, scfcv_args%dtset%use_yaml)
478 
479    ! Handle time limit condition.
480    if (itime == 1) prev = abi_wtime()
481    if (itime  > 1) then
482      now = abi_wtime()
483      wtime_step = now - prev
484      prev = now
485      write(msg,*)sjoin("{mover_itime:", itoa(itime - 1), ", wall_time: '", sec2str(wtime_step), "'} <<< TIME")
486      if(need_verbose)call wrtout(std_out, msg)
487      if (have_timelimit_in(MY_NAME)) then
488        if (itime > 2) then
489          call xmpi_wait(quitsum_request,ierr)
490          if (quitsum_async > 0) then
491            write(msg,"(3a)")"Approaching time limit ",trim(sec2str(get_timelimit())), ". Will exit itime loop in mover."
492            if(need_verbose) ABI_COMMENT(msg)
493            if(need_verbose) call wrtout(ab_out, msg)
494            timelimit_exit = 1
495            exit
496          end if
497        end if
498 
499        my_quit = 0; if (now - get_start_time() + 2.15 * wtime_step > get_timelimit()) my_quit = 1
500        call xmpi_isum(my_quit,quitsum_async,comm,quitsum_request,ierr)
501      end if
502    end if
503 
504    skipcycle=.FALSE.
505 #if defined HAVE_LOTF
506    if(ab_mover%ionmov==23 .and. .not. lotf_extrapolation(itime)) skipcycle=.True.
507 #endif
508 
509    ! If RMM-DIIS is used, decrease the number of NSCF steps done with wfoptalg before activating RMM-DIIS.
510    ! In vtowfk we have the condition: istep > 3 + dtset%rmm_diis
511    ! so setting rmm_diis = 1 gives:
512    !    4 NSCF iterations for itime == 1
513    !    1 NSCF iterations for itime >= 2.
514    if (scfcv_args%dtset%rmm_diis /= 0 .and. itime == 2) then
515      scfcv_args%dtset%rmm_diis = scfcv_args%dtset%rmm_diis - 3
516      if (scfcv_args%dtset%rmm_diis == 0) scfcv_args%dtset%rmm_diis = 1
517      call wrtout(std_out, sjoin(" itime == 2 with RMM-DIIS --> setting rmm_diis to:", itoa(scfcv_args%dtset%rmm_diis)))
518    end if
519 
520 !  ###########################################################
521 !  ### 09. Loop for icycle (From 1 to ncycle)
522    do icycle=1,ncycle
523 
524      call yaml_iterstart("icycle", icycle, dev_null, scfcv_args%dtset%use_yaml)
525 
526      itime_hist = (itime-1)*ncycle + icycle ! Store the time step in the history
527 
528 !    ###########################################################
529 !    ### 10. Output for each icycle (and itime)
530      if(need_verbose)then
531        write(msg,fmt)&
532         ch10,'--- Iteration: (',itime,'/',ntime,') Internal Cycle: (',icycle,'/',ncycle,')',ch10,('-',kk=1,80)
533         call wrtout([std_out, ab_out], msg)
534      end if
535      if (useprtxfase) call prtxfase(ab_mover,hist,itime_hist,std_out,mover_BEFORE)
536 
537      xred_prev(:,:)=xred(:,:)
538      rprimd_prev(:,:)=rprimd(:,:)
539 
540 !    ###########################################################
541 !    ### 11. Symmetrize atomic coordinates over space group elements
542 
543      call symmetrize_xred(ab_mover%natom,&
544       scfcv_args%dtset%nsym,scfcv_args%dtset%symrel,scfcv_args%dtset%tnons,xred,indsym=scfcv_args%indsym)
545 
546      changed = any(xred /= xred_prev)
547      if (changed)then
548        hist%xred(:,:,hist%ihist)=xred(:,:)
549        if(need_verbose) then
550          write(std_out,*) 'WARNING: ATOMIC COORDINATES WERE SYMMETRIZED'
551          write(std_out,*) 'DIFFERENCES:'
552          do kk=1,ab_mover%natom
553            write(std_out,*) xred(:,kk)-xred_prev(:,kk)
554          end do
555        end if
556        xred_prev(:,:)=xred(:,:)
557      end if
558 
559 !    ###########################################################
560 !    ### 12. => Call to SCFCV routine and fill history with forces
561      if (need_verbose) then
562        if (need_scfcv_cycle) then
563          write(msg,'(a,3a,33a,44a)')&
564           ch10,('-',kk=1,3),'SELF-CONSISTENT-FIELD CONVERGENCE',('-',kk=1,44)
565        else
566          write(msg,'(a,3a,33a,44a)')&
567           ch10,('-',kk=1,3),'EFFECTIVE POTENTIAL CALCULATION',('-',kk=1,44)
568        end if
569        call wrtout([std_out, ab_out], msg)
570      end if
571 
572      if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1.and.hist_prev%ihist<=hist_prev%mxhist)then
573 
574        call abihist_compare_and_copy(hist_prev,hist,ab_mover%natom,similar,tol8,specs%nhist==nhisttot)
575        hist_prev%ihist=hist_prev%ihist+1
576 
577      else
578        scfcv_args%ndtpawuj=0
579        iapp=itime
580        if(icycle>1.and.icycle/=ncycle) iapp=-1
581        if(itime==1 .and. icycle/=ncycle ) iapp=-icycle-1
582        if (ab_mover%ionmov==14.and.(icycle<ncycle)) iapp=-1
583 
584 #if defined HAVE_LOTF
585        if (ab_mover%ionmov/=23 .or.(lotf_extrapolation(itime).and.(icycle/=1.or.itime==1)))then
586 #endif
587          !call scfcv_new2(scfcv_args,electronpositron,rhog,rhor,rprimd,xred,xred_old,conv_retcode)
588 
589          !WVL - reformat the wavefunctions in the case of xred != xred_old
590          if (scfcv_args%dtset%usewvl == 1 .and. maxval(xred_old - xred) > zero) then
591            ! Before running scfcv, on non-first geometry step iterations,
592            ! we need to reformat the wavefunctions, taking into acount the new
593            ! coordinates. We prepare to change rhog (to be removed) and rhor.
594            ABI_FREE(rhog)
595            ABI_FREE(rhor)
596            call wvl_wfsinp_reformat(scfcv_args%dtset, scfcv_args%mpi_enreg,&
597 &           scfcv_args%psps, rprimd, scfcv_args%wvl, xred, xred_old)
598            scfcv_args%nfftf = scfcv_args%dtset%nfft
599            ABI_MALLOC(rhog,(2, scfcv_args%dtset%nfft))
600            ABI_MALLOC(rhor,(2, scfcv_args%dtset%nfft))
601            call wvl_mkrho(scfcv_args%dtset, scfcv_args%irrzon, scfcv_args%mpi_enreg,&
602 &           scfcv_args%phnons, rhor,scfcv_args%wvl%wfs,scfcv_args%wvl%den)
603          end if
604 
605 !        MAIN CALL TO SELF-CONSISTENT FIELD ROUTINE
606          if (need_scfcv_cycle) then
607 
608            call dtfil_init_time(dtfil,iapp)
609            itimes(1)=itime ; itimes(2)=1
610            if(present(itimimage_gstate))then
611              itimes(2)=itimimage_gstate
612            endif
613 
614 !DEBUG
615 ! write(std_out,'(a,5i4)')' m_mover, before scfcv_run : itimes(1:2)=',itimes(1:2)
616 !ENDDEBUG
617            call scfcv_run(scfcv_args, electronpositron, itimes, rhog, rhor, rprimd, xred, xred_old, conv_retcode)
618            if (conv_retcode == -1) then
619                msg = "Scf cycle returned conv_retcode == -1 (timelimit is approaching), this should not happen inside mover"
620                ABI_WARNING(msg)
621            end if
622 
623          else
624 !          For monte carlo don't need to recompute energy here (done in pred_montecarlo)
625            name_file='MD_anharmonic_terms_energy.dat'
626              if(itime == 1 .and. ab_mover%restartxf==-3)then
627                if(icycle==1)call effective_potential_file_mapHistToRef(effective_potential,hist,comm,scfcv_args%dtset%iatfix,&
628 &                                                                      need_verbose,sc_size=sc_size)!Map Hist to Ref to order atoms
629                xred(:,:) = hist%xred(:,:,1) ! Fill xred with new ordering
630                hist%ihist = 1
631              end if
632 
633 #if defined DEV_MS_SCALEUP
634            !If we a SCALE UP effective electron model give the iteration and set print-options
635            if(need_elec_eval)then
636               call global_set_parent_iter(itime)
637               ! Set all print options to false.
638               call global_set_print_parameters(geom=.FALSE.,eigvals=.FALSE.,eltic=.FALSE.,&
639 &                      orbocc=.FALSE.,bands=.FALSE.)
640               if(itime == 1 .or. modulo(itime,scup_dtset%scup_printniter) == 0)then
641                  call global_set_print_parameters(scup_dtset%scup_printgeom,scup_dtset%scup_printeigv,scup_dtset%scup_printeltic,&
642 &                         scup_dtset%scup_printorbocc,scup_dtset%scup_printbands)
643               end if
644            end if
645 #endif
646 
647            call effective_potential_evaluate( &
648 &           effective_potential,scfcv_args%results_gs%etotal,scfcv_args%results_gs%fcart,scfcv_args%results_gs%gred,&
649 &           scfcv_args%results_gs%strten,ab_mover%natom,rprimd,xred=xred,verbose=need_verbose,&
650 &           filename=name_file,elec_eval=need_elec_eval)
651 
652 !          Check if the simulation did not diverge...
653            if(itime > 3 .and.ABS(scfcv_args%results_gs%etotal - hist%etot(1)) > 1E5)then
654 !            We set to false the flag corresponding to the bound
655              effective_potential%anharmonics_terms%bounded = .FALSE.
656              if(need_verbose.and.me==master)then
657                ABI_WARNING("The simulation is diverging, please check your effective potential")
658              end if
659 !            Set the flag to finish the simulation
660              iexit=1
661              stat4xml="Failed"
662            else
663 !            We set to true the flag corresponding to the bound
664              effective_potential%anharmonics_terms%bounded = .TRUE.
665            end if
666          end if
667 #if defined HAVE_LOTF
668        end if
669 #endif
670 !      ANOMALOUS SITUATION
671 !      This is the only case where rprimd could change inside scfcv
672 !      It generates a weird condition, we start with a certain
673 !      value for rprimd before scfcv and after we finish with a different value.
674 !      Notice that normally scfcv should not change rprimd
675 !      And even worse if optcell==0
676 !      The solution here is to recompute acell and store these value
677 !      in the present record even if initially it was not exactly
678 !      the value entering in scfcv
679 !      One test case with these condition is bigdft/t10
680        if (any(rprimd(:,:)/=rprimd_prev(:,:))) then
681          hist%acell(:,hist%ihist)=acell(:)
682          hist%rprimd(:,:,hist%ihist)=rprimd(:,:)
683        end if
684 
685 !      ANOMALOUS SITUATIONS
686 !      * In ionmov 4 & 5 xred could change inside SCFCV
687 !      So we need to take the values from the output
688 !
689 !      * Inside scfcv_core.F90 there is a call to symmetrize_xred.F90
690 !      for the first SCF cycle symmetrize_xred could change xred
691        if (ab_mover%ionmov<10)then
692          changed = any(xred /= xred_prev)
693          if (changed)then
694            hist%xred(:,:,hist%ihist)=xred(:,:)
695            if(need_verbose)then
696              write(std_out,*) 'WARNING: ATOMIC COORDINATES WERE SYMMETRIZED AFTER SCFCV'
697              write(std_out,*) 'DIFFERENCES:'
698              do kk=1,ab_mover%natom
699                write(std_out,*) xred(:,kk)-xred_prev(:,kk)
700              end do
701            end if
702          end if
703        end if
704 
705 !      Fill velocities and ionic kinetic energy
706        call vel2hist(ab_mover%amass,hist,vel,vel_cell)
707 
708        hist%fcart(:,:,hist%ihist)=scfcv_args%results_gs%fcart(:,:)
709        hist%strten(:,hist%ihist) =scfcv_args%results_gs%strten(:)
710        hist%etot(hist%ihist)     =scfcv_args%results_gs%etotal
711        hist%entropy(hist%ihist)  =scfcv_args%results_gs%energies%entropy
712        hist%time(hist%ihist)     =real(itime,kind=dp)
713 
714 !      !######################################################################
715      end if ! if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1.and.hist_prev%ihist<=hist_prev%mxhist)then
716 
717 !    Store trajectory in xfh file
718      if((ab_xfh%nxfh==0.or.itime/=1)) then
719        ABI_MALLOC(gred_corrected,(3,scfcv_args%dtset%natom))
720        call fcart2gred(hist%fcart(:,:,hist%ihist),gred_corrected,rprimd,ab_mover%natom)
721 !      Get rid of mean force on whole unit cell,
722 !      but only if no generalized constraints are in effect
723        if (ab_mover%nconeq==0)then
724          do ii=1,3
725            if (ii/=3.or.ab_mover%jellslab==0) then
726              gr_avg=sum(gred_corrected(ii,:))/dble(ab_mover%natom)
727              gred_corrected(ii,:)=gred_corrected(ii,:)-gr_avg
728            end if
729          end do
730        end if
731        if (ncycle<10.and.ab_mover%restartxf>=0) then
732          do ii=1,3
733            rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
734          end do
735 
736 !        The size of ab_xfh%xfhist is to big for very large supercell.
737 !        Call it only for specific ionmov
738          if(any((/2,3,10,11,22/)==ab_mover%ionmov)) then
739            call xfh_update(ab_xfh,acell,gred_corrected,ab_mover%natom,rprim,hist%strten(:,hist%ihist),xred)
740          end if
741        end if
742        ABI_FREE(gred_corrected)
743      end if
744 
745 !    ###########################################################
746 !    ### 13. Write the history into the _HIST file
747 !    ###
748 
749 #if defined HAVE_NETCDF
750      if (need_writeHIST.and.me==master) then
751        ifirst=merge(0,1,(itime>1.or.icycle>1))
752        call write_md_hist(hist,filename,ifirst,itime_hist,ab_mover%natom,scfcv_args%dtset%nctime,&
753 &       ab_mover%ntypat,ab_mover%typat,amu_curr,ab_mover%znucl,ab_mover%dtion,scfcv_args%dtset%mdtemp)
754      end if
755 #endif
756 
757 !    ###########################################################
758 !    ### 14. Output after SCFCV
759      if(need_verbose.and.need_scfcv_cycle)then
760        write(msg,'(a,3a,a,72a)')ch10,('-',kk=1,3),'OUTPUT',('-',kk=1,71)
761        call wrtout([std_out, ab_out], msg)
762      end if
763      if (useprtxfase) then
764        call prtxfase(ab_mover,hist,itime_hist,ab_out,mover_AFTER)
765        call prtxfase(ab_mover,hist,itime_hist,std_out,mover_AFTER)
766      end if
767 
768 !    ###########################################################
769 !    ### 15. => Test Convergence of forces and stresses
770 
771      if (itime==ntime.and.icycle==ncycle)then
772        iexit=1
773        stat4xml="Failed"
774      else
775        stat4xml="Succeded"
776      end if
777 
778 !    Only if convergence is needed
779      if(specs%isFconv)then
780        if ((ab_mover%ionmov/=4.and.ab_mover%ionmov/=5).or.mod(itime,2)==1)then
781          if (scfcv_args%dtset%tolmxf/=0)then
782 
783            call fconv(hist%fcart(:,:,hist%ihist),&
784 &           scfcv_args%dtset%iatfix, &
785 &           iexit,itime,&
786 &           ab_mover%natom,&
787 &           ntime,&
788 &           ab_mover%optcell,&
789 &           scfcv_args%dtset%strfact,&
790 &           scfcv_args%dtset%strtarget,&
791 &           hist%strten(:,hist%ihist),&
792 &           rprim,&
793 &           scfcv_args%dtset%tolmxf)
794          else
795            call erlxconv(hist,iexit,itime,itime_hist,ntime,scfcv_args%dtset%tolmxde)
796          end if
797        end if
798      end if
799 
800      if (itime==ntime.and.icycle==ncycle) iexit=1
801 
802 !    ###########################################################
803 !    ### 16. => Precondition forces, stress and energy
804 !    ### 17. => Call to each predictor
805 
806      call precpred_1geo(ab_mover,ab_xfh,amu_curr,deloc,&
807 &     scfcv_args%dtset%chkdilatmx,&
808 &     scfcv_args%mpi_enreg%comm_cell,&
809 &     scfcv_args%dtset%dilatmx,dtfil%filnam_ds(4),&
810 &     hist,scfcv_args%dtset%hmctt,&
811 &     icycle,iexit,itime,mttk_vars,&
812 &     scfcv_args%dtset%nctime,ncycle,nerr_dilatmx,scfcv_args%dtset%npsp,ntime,&
813 &     scfcv_args%dtset%rprimd_orig,skipcycle,&
814 &     scfcv_args%dtset%usewvl)
815 
816 !    Write MOLDYN netcdf and POSABIN files (done every dtset%nctime time step)
817 !    This file is not created for multibinit run
818      if(need_scfcv_cycle .and. (ab_mover%ionmov/=23 .or. icycle==1))then
819        if (scfcv_args%dtset%nctime>0) then
820          jj=itime; if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1) jj=jj-hist_prev%mxhist
821          if (jj>0) then
822            option=3
823            ihist_prev = abihist_findIndex(hist,-1)
824            call wrt_moldyn_netcdf(ab_mover%amass,scfcv_args%dtset,jj,option,dtfil%fnameabo_moldyn,&
825 &           scfcv_args%mpi_enreg,scfcv_args%results_gs,&
826 &           hist%rprimd(:,:,ihist_prev),dtfil%unpos,hist%vel(:,:,hist%ihist),&
827 &           hist%xred(:,:,ihist_prev))
828          end if
829          if (iexit==1) hist%ihist=ihist_prev
830        end if
831      end if
832      if(iexit/=0) exit
833 
834 !    ###########################################################
835 !    ### 18. Use the history  to extract the new values of acell, rprimd and xred
836 
837      call hist2var(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
838 
839      if (ab_mover%optcell/=0) then
840        ! Cell may change
841 
842        call matr3inv(rprimd,gprimd)
843 
844 !      If metric has changed since the initialization, update the Ylm's
845        if (scfcv_args%psps%useylm==1)then
846          option=0
847          if (scfcv_args%dtset%iscf>0) option=1
848          call initylmg(gprimd,&
849 &         scfcv_args%kg,&
850 &         scfcv_args%dtset%kptns,&
851 &         scfcv_args%dtset%mkmem,&
852 &         scfcv_args%mpi_enreg,&
853 &         scfcv_args%psps%mpsang,&
854 &         scfcv_args%dtset%mpw,&
855 &         scfcv_args%dtset%nband,&
856 &         scfcv_args%dtset%nkpt,&
857 &         scfcv_args%npwarr,&
858 &         scfcv_args%dtset%nsppol,&
859 &         option,rprimd,&
860 &         scfcv_args%ylm,&
861 &         scfcv_args%ylmgr)
862        end if
863 
864      end if
865 
866      vel(:,:)=hist%vel(:,:,hist%ihist)
867 
868 !    vel_cell(3,3)= velocities of cell parameters
869 !    Not yet used here but compute it for consistency
870      vel_cell(:,:)=zero
871      if (ab_mover%ionmov==13 .and. hist%mxhist >= 2) then
872        if (itime_hist>2) then
873          ihist_prev2 = abihist_findIndex(hist,-2)
874          vel_cell(:,:)=(hist%rprimd(:,:,hist%ihist)- hist%rprimd(:,:,ihist_prev2))/(two*ab_mover%dtion)
875        else if (itime_hist>1) then
876          ihist_prev = abihist_findIndex(hist,-1)
877          vel_cell(:,:)=(hist%rprimd(:,:,hist%ihist)-hist%rprimd(:,:,ihist_prev))/(ab_mover%dtion)
878        end if
879      end if
880 
881 !    This is needed for some compilers such as
882 !    pathscale, g95, xlf that do not exit
883 !    from a loop if you change the upper limit
884 !    inside
885      if (icycle>=ncycle .and. scfcv_args%mpi_enreg%me == 0) then
886        if(need_verbose)write(std_out,*) 'EXIT:',icycle,ncycle
887        exit
888      end if
889 
890 
891      if (need_verbose) then
892        write(msg,*) 'ICYCLE',icycle,skipcycle
893        call wrtout(std_out,msg)
894        write(msg,*) 'NCYCLE',ncycle
895        call wrtout(std_out,msg)
896      end if
897      if (skipcycle) exit
898 
899 !    ###########################################################
900 !    ### 19. End loop icycle
901 
902    end do ! icycle
903 
904    if(iexit/=0)exit
905 
906 !  ###########################################################
907 !  ### 20. End loop itime
908 
909  end do ! itime
910 
911  ! Call fconv here if we exited due to wall time limit.
912  if (timelimit_exit==1 .and. specs%isFconv) then
913    iexit = timelimit_exit
914    ntime = itime-1
915    ihist_prev = abihist_findIndex(hist,-1)
916    if ((ab_mover%ionmov/=4.and.ab_mover%ionmov/=5)) then
917      if (scfcv_args%dtset%tolmxf/=0)then
918        call fconv(hist%fcart(:,:,ihist_prev),&
919 &       scfcv_args%dtset%iatfix, &
920 &       iexit, itime,&
921 &       ab_mover%natom,&
922 &       ntime,&
923 &       ab_mover%optcell,&
924 &       scfcv_args%dtset%strfact,&
925 &       scfcv_args%dtset%strtarget,&
926 &       hist%strten(:,ihist_prev),&
927 &       rprim,&
928 &       scfcv_args%dtset%tolmxf)
929      else
930        call erlxconv(hist,iexit,itime,itime_hist,ntime,scfcv_args%dtset%tolmxde)
931      end if
932    end if
933  end if
934 
935  ! Avoid pending requests if itime == ntime.
936  call xmpi_wait(quitsum_request,ierr)
937 
938 !###########################################################
939 !### 21. Set the final values of xred with the last computed values (not the last predicted)
940 
941  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
942  vel(:,:)=hist%vel(:,:,hist%ihist)
943 
944  if (DEBUG .and. ab_mover%ionmov==1)then
945    write (std_out,*) 'vel'
946    do kk=1,ab_mover%natom
947      write (std_out,*) hist%vel(:,kk,hist%ihist)
948    end do
949  end if
950 
951 !###########################################################
952 !### 22. XML Output at the end
953 
954 !XML output of the status
955  if (scfcv_args%mpi_enreg%me == 0 .and. scfcv_args%dtset%prtxml == 1) then
956    write(ab_xml_out, "(3a)") '    <geometryMinimisation type="',trim(specs%type4xml),'">'
957    write(ab_xml_out, "(5a)") '      <status cvState="',trim(stat4xml) ,'" stop-criterion="',trim(specs%crit4xml),'" />'
958    write(ab_xml_out, "(3a)") '    </geometryMinimisation>'
959  end if
960 
961 !###########################################################
962 !### 23. Deallocate hist and ab_mover datatypes
963 
964 !This call is needed to free an internal matrix. However, this is not optimal ...
965 !One should instead have a datastructure associated with the preconditioner.
966  if (ab_mover%goprecon>0) call prec_simple(ab_mover,preconforstr,hist,1,1,1)
967 
968  if (ab_mover%ionmov==13 .or. ab_mover%ionmov==25)then
969    call mttk_fin(mttk_vars)
970  end if
971 
972  if (ab_mover%ionmov==10 .or. ab_mover%ionmov==11) call delocint_fin(deloc)
973 
974  ABI_FREE(xred_prev)
975 
976  call abihist_free(hist)
977  call abihist_free(hist_prev)
978  call abimover_destroy(ab_mover)
979  call abiforstr_fin(preconforstr)
980 
981 contains

ABINIT/prtnatom [ Functions ]

[ Top ] [ Functions ]

NAME

 prtnatom

FUNCTION

 Print information for N atoms

INPUTS

 prtallatoms = Logical for PRTint ALL ATOMS
 atlist      = ATom LIST
 index       = index for each atom
 natom       = Number of ATOMs

OUTPUT

  tag = The string to put for aech atom

SOURCE

1562 subroutine prtnatom(atlist,iout,message,natom,prtallatoms,thearray)
1563 
1564 !Arguments ------------------------------------
1565 !scalars
1566   logical,intent(in) :: prtallatoms
1567   integer,intent(in) :: natom
1568   logical,intent(in) :: atlist(natom)
1569   integer,intent(in) :: iout
1570   character(len=*),intent(inout) :: message
1571 !arrays
1572   real(dp) :: thearray(3,natom)
1573 
1574 !Local variables-------------------------------
1575 !scalars
1576   integer :: kk
1577   character(len=7)   :: tag ! Maximal ' (9999)'
1578   character(len=18)   :: fmt
1579 
1580 ! *********************************************************************
1581 
1582  fmt='(a,a,1p,3e22.14,a)'
1583 
1584  do kk=1,natom
1585    if (atlist(kk)) then
1586      call gettag(atlist,kk,natom,prtallatoms,tag)
1587      write(message,fmt)TRIM(message),ch10,thearray(:,kk),tag
1588    end if
1589  end do
1590  call wrtout(iout,message,'COLL')
1591 
1592  end subroutine prtnatom

ABINIT/prtxfase [ Functions ]

[ Top ] [ Functions ]

NAME

 prtxfase

FUNCTION

 Print the values of xcart (X), forces (F) acell (A), Stresses (S), and energy (E)
 All values come from the history hist
 Also compute and print max and rms forces.
 Also compute absolute and relative differences with previous calculation

INPUTS

 ab_mover<type abimover>=Subset of dtset only related with movement of ions and acell, contains:
          | dtion:  Time step
          ! natom:  Number of atoms
          | vis:    viscosity
          | iatfix: Index of atoms and directions fixed
          | amass:  Mass of ions
 hist<type abihist>=Historical record of positions, forces, stresses, cell and energies,
 itime= time step
 iout=unit number for printing

OUTPUT

  (only writing)

SOURCE

1254 subroutine prtxfase(ab_mover,hist,itime,iout,pos)
1255 
1256 !Arguments ------------------------------------
1257 !scalars
1258  type(abimover),intent(in) :: ab_mover
1259  type(abihist),intent(in),target :: hist
1260  integer,intent(in) :: itime,iout
1261  integer,intent(in) :: pos
1262 !arrays
1263 
1264 !Local variables-------------------------------
1265 !scalars
1266  integer :: jj,kk,unfixd,iprt
1267  real(dp) :: val_max,val_rms,ucvol ! Values maximal and RMS, Volume of Unitary cell
1268  real(dp) :: dEabs,dErel ! Diff of energy absolute and relative
1269  real(dp) :: ekin
1270  real(dp) :: angle(3),rmet(3,3)
1271 !character(len=80*(max(ab_mover%natom,3)+1)) :: msg
1272 !MGNAG: This is not very safe. One should use line-based output istead of appending chars
1273 ! and then outputting everything! For the time being I use this temporary hack to solve the problem with NAG
1274  character(len=max(80*(max(ab_mover%natom,3)+1),50000)) :: msg
1275  character(len=18)   :: fmt1
1276  logical :: prtallatoms
1277 !arrays
1278  logical :: atlist(ab_mover%natom)
1279  real(dp),allocatable :: gred(:,:),xcart(:,:)
1280  real(dp),pointer :: acell(:),fcart(:,:),rprimd(:,:),strten(:),vel(:,:),xred(:,:)
1281 
1282 ! ***********************************************************
1283 
1284  fmt1='(a,a,1p,3e22.14)'
1285 
1286 !##########################################################
1287 !### 1. Organize list of atoms to print
1288 
1289  prtallatoms=.TRUE.
1290  do kk=1,ab_mover%natom
1291    if (ab_mover%prtatlist(kk)/=kk) prtallatoms=.FALSE.
1292  end do
1293 
1294  atlist(:)=.FALSE.
1295  do iprt=1,ab_mover%natom
1296    if (ab_mover%prtatlist(iprt)>0.and.ab_mover%prtatlist(iprt)<=ab_mover%natom) atlist(ab_mover%prtatlist(iprt))=.TRUE.
1297  end do
1298 
1299  acell  => hist%acell(:,hist%ihist)
1300  rprimd => hist%rprimd(:,:,hist%ihist)
1301  xred   => hist%xred(:,:,hist%ihist)
1302  fcart  => hist%fcart(:,:,hist%ihist)
1303  strten => hist%strten(:,hist%ihist)
1304  vel    => hist%vel(:,:,hist%ihist)
1305 
1306 !###########################################################
1307 !### 1. Positions
1308 
1309  ABI_MALLOC(xcart,(3,ab_mover%natom))
1310  call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
1311 
1312  write(msg, '(a,a)' )ch10,' Cartesian coordinates (xcart) [bohr]'
1313  call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,xcart)
1314 
1315  write(msg, '(a)' )' Reduced coordinates (xred)'
1316  call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,xred)
1317 
1318  ABI_FREE(xcart)
1319 
1320 !###########################################################
1321 !### 2. Forces
1322 
1323  if(pos==mover_AFTER)then
1324 
1325    ABI_MALLOC(gred,(3,ab_mover%natom))
1326    call fcart2gred(fcart,gred,rprimd,ab_mover%natom)
1327 
1328 !  Compute max |f| and rms f,
1329 !  EXCLUDING the components determined by iatfix
1330    val_max=0.0_dp
1331    val_rms=0.0_dp
1332    unfixd=0
1333    do kk=1,ab_mover%natom
1334      do jj=1,3
1335        if (ab_mover%iatfix(jj,kk) /= 1) then
1336          unfixd=unfixd+1
1337          val_rms=val_rms+fcart(jj,kk)**2
1338          val_max=max(val_max,abs(fcart(jj,kk)**2))
1339        end if
1340      end do
1341    end do
1342    if ( unfixd /= 0 ) val_rms=sqrt(val_rms/dble(unfixd))
1343 
1344    write(msg, '(a,1p,2e12.5,a)' ) ' Cartesian forces (fcart) [Ha/bohr]; max,rms=',sqrt(val_max),val_rms,' (free atoms)'
1345    call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,fcart)
1346 
1347    write(msg, '(a)' )' Gradient of E wrt nuclear positions in reduced coordinates (gred)'
1348    call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,gred)
1349    ABI_FREE(gred)
1350  end if
1351 
1352 !###########################################################
1353 !### 3. Velocities
1354 
1355 !Only if the velocities are being used
1356  if (hist%isVused)then
1357 !  Only if velocities are recorded in a history
1358    if (allocated(hist%vel))then
1359 !    Compute max |v| and rms v,
1360 !    EXCLUDING the components determined by iatfix
1361      val_max=0.0_dp
1362      val_rms=0.0_dp
1363      unfixd=0
1364      do kk=1,ab_mover%natom
1365        do jj=1,3
1366          if (ab_mover%iatfix(jj,kk) /= 1) then
1367            unfixd=unfixd+1
1368            val_rms=val_rms+vel(jj,kk)**2
1369            val_max=max(val_max,abs(vel(jj,kk)**2))
1370          end if
1371        end do
1372      end do
1373      if ( unfixd /= 0 ) val_rms=sqrt(val_rms/dble(unfixd))
1374 
1375      write(msg, '(a,1p,2e12.5,a)' ) &
1376 &     ' Cartesian velocities (vel) [bohr*Ha/hbar]; max,rms=',sqrt(val_max),val_rms,' (free atoms)'
1377      call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,vel)
1378 
1379 !    Compute the ionic kinetic energy (no cell shape kinetic energy yet)
1380      ekin=0.0_dp
1381      do kk=1,ab_mover%natom
1382        do jj=1,3
1383 !        Warning : the fixing of atoms is implemented in reduced
1384 !        coordinates, so that this expression is wrong
1385          if (ab_mover%iatfix(jj,kk) == 0) then
1386            ekin=ekin+0.5_dp*ab_mover%amass(kk)*vel(jj,kk)**2
1387          end if
1388        end do
1389      end do
1390      write(msg, '(a,1p,e22.14,a)' )' Kinetic energy of ions (ekin) [Ha]=',ekin
1391      call wrtout(iout,msg,'COLL')
1392    end if
1393  end if
1394 
1395 !###########################################################
1396 !### 3. ACELL
1397 
1398 !Only if the acell is being used
1399  if (hist%isARused)then
1400 !  Only if acell is recorded in a history
1401    if (allocated(hist%acell))then
1402      write(msg, '(a)' )' Scale of Primitive Cell (acell) [bohr]'
1403      write(msg,fmt1)TRIM(msg),ch10,acell(:)
1404      call wrtout(iout,msg,'COLL')
1405    end if
1406  end if
1407 
1408 !###########################################################
1409 !### 4. RPRIMD
1410 
1411 !Only if the acell is being used
1412  if (hist%isARused)then
1413 !  Only if rprimd is recorded in a history
1414    if (allocated(hist%rprimd))then
1415      write(msg, '(a)' )' Real space primitive translations (rprimd) [bohr]'
1416      do kk=1,3
1417        write(msg,fmt1)TRIM(msg),ch10,rprimd(:,kk)
1418      end do
1419      call wrtout(iout,msg,'COLL')
1420    end if
1421  end if
1422 
1423 !###########################################################
1424 !### 5. Unitary cell volume
1425 
1426  if (ab_mover%optcell/=0)then
1427 
1428    ucvol=&
1429 &   rprimd(1,1)*(rprimd(2,2)*rprimd(3,3)-rprimd(3,2)*rprimd(2,3))+&
1430 &   rprimd(2,1)*(rprimd(3,2)*rprimd(1,3)-rprimd(1,2)*rprimd(3,3))+&
1431 &   rprimd(3,1)*(rprimd(1,2)*rprimd(2,3)-rprimd(2,2)*rprimd(1,3))
1432 
1433    write(msg, '(a,1p,e22.14)' )' Unitary Cell Volume (ucvol) [Bohr^3]=',ucvol
1434    call wrtout(iout,msg,'COLL')
1435 
1436 !  ###########################################################
1437 !  ### 5. Angles and lengths
1438 
1439 !  Compute real space metric.
1440    rmet = MATMUL(TRANSPOSE(rprimd),rprimd)
1441 
1442    angle(1)=acos(rmet(2,3)/sqrt(rmet(2,2)*rmet(3,3)))/two_pi*360.0d0
1443    angle(2)=acos(rmet(1,3)/sqrt(rmet(1,1)*rmet(3,3)))/two_pi*360.0d0
1444    angle(3)=acos(rmet(1,2)/sqrt(rmet(1,1)*rmet(2,2)))/two_pi*360.0d0
1445 
1446    write(msg, '(a)' )' Angles (23,13,12)= [degrees]'
1447    write(msg,fmt1)TRIM(msg),ch10,angle(:)
1448    call wrtout(iout,msg,'COLL')
1449 
1450    write(msg, '(a)' ) ' Lengths [Bohr]'
1451    write(msg,fmt1)TRIM(msg),ch10,sqrt(rmet(1,1)),sqrt(rmet(2,2)),sqrt(rmet(3,3))
1452    call wrtout(iout,msg,'COLL')
1453 
1454 !  ###########################################################
1455 !  ### 5. Stress Tensor
1456 
1457    if(pos==mover_AFTER)then
1458 !    Only if strten is recorded in a history
1459      if (allocated(hist%strten))then
1460 
1461        write(msg, '(a)' ) ' Stress tensor in cartesian coordinates (strten) [Ha/bohr^3]'
1462 
1463        write(msg,fmt1)TRIM(msg),ch10,strten(1),strten(6),strten(5)
1464        write(msg,fmt1)TRIM(msg),ch10,strten(6),strten(2),strten(4)
1465        write(msg,fmt1)TRIM(msg),ch10,strten(5),strten(4),strten(3)
1466        call wrtout(iout,msg,'COLL')
1467      end if
1468    end if
1469  end if
1470 
1471 !###########################################################
1472 !### 6. Energy
1473 
1474  if(pos==mover_AFTER)then
1475    write(msg, '(a,1p,e22.14)' )' Total energy (etotal) [Ha]=',hist%etot(hist%ihist)
1476 
1477    if (itime>1)then
1478      jj = abihist_findIndex(hist,-1)
1479      dEabs=hist%etot(hist%ihist)-hist%etot(jj)
1480      dErel=2*dEabs/(abs(hist%etot(hist%ihist))+abs(hist%etot(jj)))
1481      write(msg, '(a,a,a,a)' )TRIM(msg),ch10,ch10,' Difference of energy with previous step (new-old):'
1482      write(msg, '(a,a,10a,a,1p,e12.5,a,10a,a,1p,e12.5)')&
1483       TRIM(msg),ch10,&
1484       (' ',jj=1,10),' Absolute (Ha)=',dEabs,ch10,&
1485       (' ',jj=1,10),' Relative     =',dErel
1486    end if
1487    call wrtout(iout,msg,'COLL')
1488  end if
1489 
1490  contains

ABINIT/wrt_moldyn_netcdf [ Functions ]

[ Top ] [ Functions ]

NAME

 wrt_moldyn_netcdf

FUNCTION

 Write two files for later molecular dynamics analysis:
  - MOLDYN.nc (netcdf format) : evolution of key quantities with time (pressure, energy, ...)
  - POSABIN : values of coordinates and velocities for the next time step

INPUTS

  amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
  dtset <type(dataset_type)>=all input variables for this dataset
  itime=time step index
  option=1: write MOLDYN.nc file (netcdf format)
         2: write POSABIN file
         3: write both
  moldyn_file=name of the MD netcdf file
  mpi_enreg=information about MPI parallelization
  results_gs <type(results_gs_type)>=results (energy and its components,
   forces and its components, the stress tensor) of a ground-state computation
  rprimd(3,3)=real space primitive translations
  unpos=unit number for POSABIN file
  vel(3,natom)=velocities of atoms
  xred(3,natom)=reduced coordinates of atoms

OUTPUT

  -- only printing --

SIDE EFFECTS

SOURCE

1630 subroutine wrt_moldyn_netcdf(amass,dtset,itime,option,moldyn_file,mpi_enreg,&
1631 &                            results_gs,rprimd,unpos,vel,xred)
1632 
1633  use defs_basis
1634  use defs_abitypes
1635  use m_results_gs
1636  use m_abicore
1637  use m_errors
1638 #if defined HAVE_NETCDF
1639  use netcdf
1640 #endif
1641 
1642  use m_io_tools,   only : open_file, get_unit
1643  use m_geometry,   only : xcart2xred, xred2xcart, metric
1644 
1645 !Arguments ------------------------------------
1646 !scalars
1647  integer,intent(in) :: itime,option,unpos
1648  character(fnlen),intent(in) :: moldyn_file
1649  type(dataset_type),intent(in) :: dtset
1650  type(MPI_type),intent(in) :: mpi_enreg
1651  type(results_gs_type),intent(in) :: results_gs
1652 !arrays
1653  real(dp),intent(in) :: amass(dtset%natom),rprimd(3,3)
1654  real(dp),intent(in),target :: vel(3,dtset%natom)
1655  real(dp),intent(in) :: xred(3,dtset%natom)
1656 
1657 !Local variables-------------------------------
1658 !scalars
1659  integer,save :: ipos=0
1660  integer :: iatom,ii
1661  character(len=500) :: msg
1662 #if defined HAVE_NETCDF
1663  integer :: AtomNumDimid,AtomNumId,CelId,CellVolumeId,DimCoordid,DimScalarid,DimVectorid
1664  integer :: EkinDimid,EkinId,EpotDimid,EpotId,EntropyDimid,EntropyId,MassDimid,MassId,NbAtomsid
1665  integer :: ncerr,ncid,PosId,StressDimid,StressId,TensorSymDimid
1666  integer :: TimeDimid,TimestepDimid,TimestepId
1667  logical :: atom_fix
1668  real(dp) :: ekin,ucvol
1669  character(len=fnlen) :: ficname
1670  character(len=16) :: chain
1671 #endif
1672 !arrays
1673 #if defined HAVE_NETCDF
1674  integer :: PrimVectId(3)
1675  real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
1676  real(dp),allocatable ::  xcart(:,:)
1677  real(dp),pointer :: vcart(:,:),vred(:,:),vtmp(:,:)
1678 #endif
1679 
1680 ! *************************************************************************
1681 
1682 !Only done by master processor, every nctime step
1683  if (mpi_enreg%me==0.and.dtset%nctime>0) then
1684 
1685 !  Netcdf file name
1686 #if defined HAVE_NETCDF
1687    ficname = trim(moldyn_file)//'.nc'
1688 #endif
1689 
1690 !  Xcart from Xred
1691 #if defined HAVE_NETCDF
1692    ABI_MALLOC(xcart,(3,dtset%natom))
1693    call xred2xcart(dtset%natom,rprimd,xcart,xred)
1694 #endif
1695 
1696 !  ==========================================================================
1697 !  First time step: write header of netcdf file
1698 !  ==========================================================================
1699    if (itime==1.and.(option==1.or.option==3)) then
1700 
1701      ipos=0
1702 
1703 #if defined HAVE_NETCDF
1704 !    Write message
1705      write(msg,'(4a)')ch10,' Open file ',trim(ficname),' to store molecular dynamics information.'
1706      call wrtout(std_out,msg,'COLL')
1707 
1708 !    Create netcdf file
1709      ncerr = nf90_create(ficname, NF90_CLOBBER , ncid)
1710      NCF_CHECK_MSG(ncerr,'nf90_create')
1711 
1712 !    Dimension time for netcdf (time dim is unlimited)
1713      ncerr = nf90_def_dim(ncid, "time", nf90_unlimited, TimeDimid)
1714      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1715 
1716 !    Symetric Tensor Dimension
1717      ncerr = nf90_def_dim(ncid, "DimTensor", size(results_gs%strten), TensorSymDimid)
1718      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1719 
1720 !    Coordinates Dimension
1721      ncerr = nf90_def_dim(ncid, "DimCoord", size(xcart,1), DimCoordid)
1722      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1723 
1724 !    Atoms Dimensions
1725      ncerr = nf90_def_dim(ncid, "NbAtoms", dtset%natom, NbAtomsid)
1726      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1727 
1728 !    Vector Dimension
1729      ncerr = nf90_def_dim(ncid, "DimVector", 3 , DimVectorid)
1730      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1731 
1732 !    Scalar Dimension
1733      ncerr = nf90_def_dim(ncid, "DimScalar", 1 , DimScalarid)
1734      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
1735 
1736 !    Time step and time unit
1737      ncerr = nf90_def_var(ncid, "Time_step", nf90_double , DimScalarid, TimestepDimid)
1738      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1739      ncerr = nf90_put_att(ncid, TimestepDimid, "units", "atomic time unit")
1740      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1741 
1742 !    Ionic masses
1743      ncerr = nf90_def_var(ncid, "Ionic_Mass", nf90_double , NbAtomsid, MassDimid)
1744      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1745      ncerr = nf90_put_att(ncid, MassDimid, "units", "atomic mass unit")
1746      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1747 
1748 !    Ionic atomic numbers
1749      ncerr = nf90_def_var(ncid, "Ionic_Atomic_Number", nf90_double , NbAtomsid, AtomNumDimid)
1750      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1751 
1752 !    E_pot
1753      ncerr = nf90_def_var(ncid, "E_pot", nf90_double , TimeDimid, EpotDimid)
1754      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1755      ncerr = nf90_put_att(ncid, EpotDimid, "units", "hartree")
1756      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1757 
1758 !    E_kin
1759      ncerr = nf90_def_var(ncid, "E_kin", nf90_double , TimeDimid, EkinDimid)
1760      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1761      ncerr = nf90_put_att(ncid, EkinDimid, "units", "hartree")
1762      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1763 
1764 !    Entropy
1765      ncerr = nf90_def_var(ncid, "Entropy", nf90_double , TimeDimid, EntropyDimid)
1766      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1767      ncerr = nf90_put_att(ncid, EntropyDimid, "units", "")
1768      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1769 
1770 !    Stress tensor
1771      ncerr = nf90_def_var(ncid, "Stress", nf90_double , (/TensorSymDimid,TimeDimid/), StressDimid)
1772      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1773      ncerr = nf90_put_att(ncid, StressDimid, "units", "hartree/bohr^3")
1774      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1775 
1776 !    Positions
1777      ncerr = nf90_def_var(ncid, "Position", nf90_double ,(/DimCoordid,NbAtomsid,TimeDimid/), PosId)
1778      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1779      ncerr = nf90_put_att(ncid, PosId, "units", "bohr")
1780      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1781 
1782 !    Celerities
1783      ncerr = nf90_def_var(ncid, "Celerity", nf90_double ,(/DimCoordid,NbAtomsid,TimeDimid/), CelId)
1784      NCF_CHECK_MSG(ncerr,'nf90_def_var')
1785      ncerr = nf90_put_att(ncid, CelId, "units", "bohr/(atomic time unit)")
1786      NCF_CHECK_MSG(ncerr,'nf90_put_att')
1787 
1788 !    In case of volume cell constant
1789      if (dtset%optcell==0) then
1790 !      Primitive vectors
1791        do ii = 1,3
1792          write(unit=chain,fmt='(a15,i1)') "PrimitiveVector",ii
1793          ncerr = nf90_def_var(ncid, trim(chain), nf90_double , DimVectorid, PrimVectId(ii))
1794          NCF_CHECK_MSG(ncerr,'nf90_def_var')
1795        end do
1796 !      Cell Volume
1797        ncerr = nf90_def_var(ncid, "Cell_Volume", nf90_double , DimScalarid, CellVolumeId)
1798        NCF_CHECK_MSG(ncerr,'nf90_def_var')
1799        ncerr = nf90_put_att(ncid, CellVolumeId, "units", "bohr^3")
1800        NCF_CHECK_MSG(ncerr,'nf90_put_att')
1801      end if
1802 
1803 !    Leave define mode and close file
1804      ncerr = nf90_enddef(ncid)
1805      NCF_CHECK_MSG(ncerr,'nf90_enddef')
1806      ncerr = nf90_close(ncid)
1807      NCF_CHECK_MSG(ncerr,'nf90_close')
1808 #endif
1809    end if
1810 
1811 !  ==========================================================================
1812 !  Write data to netcdf file (every nctime time step)
1813 !  ==========================================================================
1814    if (mod(itime, dtset%nctime)==0.and.(option==1.or.option==3)) then
1815 
1816      ipos=ipos+1
1817 
1818 #if defined HAVE_NETCDF
1819 !    Write message
1820      write(msg,'(3a)')ch10,' Store molecular dynamics information in file ',trim(ficname)
1821      call wrtout(std_out,msg,'COLL')
1822 
1823 !    Open netcdf file
1824      ncerr = nf90_open(ficname, nf90_write, ncid)
1825      NCF_CHECK_MSG(ncerr,'nf90_open')
1826 
1827 !    Time step
1828      ncerr = nf90_inq_varid(ncid, "Time_step", TimestepId)
1829      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1830      ncerr = nf90_put_var(ncid, TimestepId, dtset%dtion)
1831      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1832 
1833 !    Ionic masses
1834      ncerr = nf90_inq_varid(ncid, "Ionic_Mass", MassId)
1835      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1836      ncerr = nf90_put_var(ncid, MassId, amass, start = (/ 1 /), count=(/dtset%natom/))
1837      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1838 
1839 !    Ionic atomic numbers
1840      ncerr = nf90_inq_varid(ncid, "Ionic_Atomic_Number", AtomNumId)
1841      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1842      ncerr = nf90_put_var(ncid, AtomNumId, dtset%znucl(dtset%typat(:)),start=(/1/),count=(/dtset%natom/))
1843      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1844 
1845 !    Epot
1846      ncerr = nf90_inq_varid(ncid, "E_pot", EpotId)
1847      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1848      ncerr = nf90_put_var(ncid, EpotId, (/results_gs%etotal/), start=(/ipos/),count=(/1/))
1849      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1850 
1851 !    Ekin
1852      ekin=zero;atom_fix=(maxval(dtset%iatfix)>0)
1853      if (dtset%ionmov==1.or.(.not.atom_fix)) then
1854        vcart => vel
1855      else
1856        ABI_MALLOC(vcart,(3,dtset%natom))
1857        ABI_MALLOC(vred,(3,dtset%natom))
1858        vtmp => vel
1859        call xcart2xred(dtset%natom,rprimd,vtmp,vred)
1860        do iatom=1,dtset%natom
1861          do ii=1,3
1862            if (dtset%iatfix(ii,iatom)==1) vred(ii,iatom)=zero
1863          end do
1864        end do
1865        call xred2xcart(dtset%natom,rprimd,vcart,vred)
1866        ABI_FREE(vred)
1867      end if
1868      do iatom=1,dtset%natom
1869        do ii=1,3
1870          ekin=ekin+half*amass(iatom)*vcart(ii,iatom)**2
1871        end do
1872      end do
1873      if (dtset%ionmov/=1.and.atom_fix)  then
1874        ABI_FREE(vcart)
1875      end if
1876      ncerr = nf90_inq_varid(ncid, "E_kin", EkinId)
1877      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1878      ncerr = nf90_put_var(ncid, EkinId, (/ekin/), start = (/ipos/),count=(/1/))
1879      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1880 
1881 !    EntropyDimid
1882      ncerr = nf90_inq_varid(ncid, "Entropy", EntropyId)
1883      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1884      ncerr = nf90_put_var(ncid, EntropyId, (/results_gs%energies%entropy/),start = (/ipos/),count=(/1/))
1885      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1886 
1887 !    Stress tensor
1888      ncerr = nf90_inq_varid(ncid, "Stress", StressId)
1889      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1890      ncerr = nf90_put_var(ncid, StressId, results_gs%strten, &
1891 &     start=(/1,ipos/),count=(/size(results_gs%strten)/))
1892      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1893 
1894 !    Positions
1895      ncerr = nf90_inq_varid(ncid, "Position", PosId)
1896      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1897      ncerr = nf90_put_var(ncid, PosId, xcart, start=(/1,1,ipos/), &
1898 &     count=(/size(xcart,1),dtset%natom,1/))
1899      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1900 
1901 !    Celerities
1902      ncerr = nf90_inq_varid(ncid, "Celerity", CelId)
1903      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1904      ncerr = nf90_put_var(ncid, CelId, vel, start=(/1,1,ipos/), &
1905 &     count=(/size(vel,1),dtset%natom,1/)  )
1906      NCF_CHECK_MSG(ncerr,'nf90_put_var')
1907 
1908 !    In case of volume cell constant
1909      if (dtset%optcell==0.and.ipos==1) then
1910 !      Primitive vectors
1911        do ii = 1,3
1912          write(unit=chain,fmt='(a15,i1)') "PrimitiveVector",ii
1913          ncerr = nf90_inq_varid(ncid, trim(chain), PrimVectId(ii) )
1914          NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1915          ncerr = nf90_put_var(ncid, PrimVectId(ii), rprimd(:,ii))
1916          NCF_CHECK_MSG(ncerr,'nf90_put_var')
1917        end do
1918 !      Cell Volume
1919        call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
1920        ncerr = nf90_inq_varid(ncid, "Cell_Volume" , CellVolumeId)
1921        NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
1922        ncerr = nf90_put_var(ncid, CellVolumeId, ucvol)
1923        NCF_CHECK_MSG(ncerr,'nf90_put_var')
1924      end if
1925 
1926 !    Close file
1927      ncerr = nf90_close(ncid)
1928      NCF_CHECK_MSG(ncerr,'nf90_close')
1929 #endif
1930    end if
1931 
1932 !  ==========================================================================
1933 !  Write data to POSABIN file (every nctime time step if option=3)
1934 !  ==========================================================================
1935    if ((mod(itime, dtset%nctime)==0.and.option==3).or.(option==2)) then
1936 
1937 !    Open file for writing
1938      if (open_file('POSABIN',msg,unit=unpos,status='replace',form='formatted') /= 0 ) then
1939        ABI_ERROR(msg)
1940      end if
1941 
1942 !    Write Positions
1943      if (dtset%natom>=1) write(unpos,'(a7,3d18.5)') 'xred  ',(xred(ii,1),ii=1,3)
1944      if (dtset%natom>1) then
1945        do iatom=2,dtset%natom
1946          write(unpos,'(7x,3d18.5)') (xred(ii,iatom),ii=1,3)
1947        end do
1948      end if
1949 
1950 !    Write Velocities
1951      if (dtset%natom>=1) write(unpos,'(a7,3d18.5)') 'vel  ',(vel(ii,1),ii=1,3)
1952      if (dtset%natom>1) then
1953        do iatom=2,dtset%natom
1954          write(unpos,'(7x,3d18.5)') (vel(ii,iatom),ii=1,3)
1955        end do
1956      end if
1957 
1958 !    Close file
1959      close(unpos)
1960    end if
1961 
1962 #if defined HAVE_NETCDF
1963    ABI_FREE(xcart)
1964 #endif
1965 
1966 !  ==========================================================================
1967 !  End if master proc
1968  end if
1969 
1970 !Fake lines
1971 #if !defined HAVE_NETCDF
1972  if (.false.) write(std_out,*) moldyn_file,results_gs%etotal,rprimd(1,1)
1973 #endif
1974 
1975 end subroutine wrt_moldyn_netcdf