LCOV - code coverage report
Current view: top level - src/95_drive - m_mover.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.6 % 732 634
Test Date: 2026-09-21 19:39:32 Functions: 100.0 % 7 7

            Line data    Source code
       1              : !!****m* ABINIT/m_mover
       2              : !! NAME
       3              : !!  m_mover
       4              : !!
       5              : !! FUNCTION
       6              : !! Move ion or change acell according to forces and stresses
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, SE, FLambert,MT)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_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_pimd
      32              :  use m_xmpi
      33              :  use m_nctk
      34              :  use m_dtfil
      35              :  use m_yaml
      36              :  use netcdf
      37              : #if defined HAVE_LOTF
      38              :  use lotfpath
      39              :  use m_pred_lotf
      40              : #endif
      41              : 
      42              :  use defs_abitypes,        only : MPI_type
      43              :  use m_fstrings,           only : strcat, sjoin, indent, itoa
      44              :  use m_matrix,             only : matr3inv
      45              :  use m_symtk,              only : symmetrize_xred
      46              :  use m_geometry,           only : fcart2gred, chkdilatmx, xred2xcart, metric
      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_kg,                 only : getcut, getph
      54              :  use m_xfpack,             only : xfh_update
      55              :  use m_mkrho,              only : initro
      56              :  use m_pawfgr,             only : pawfgr_type, pawfgr_init, pawfgr_destroy
      57              :  use m_precpred_1geo,      only : precpred_1geo
      58              :  use m_pred_simple,        only : prec_simple
      59              :  !use m_generate_training_set, only : generate_training_set
      60              :  use m_wvl_wfsinp, only : wvl_wfsinp_reformat
      61              :  use m_wvl_rho,      only : wvl_mkrho
      62              :  use m_effective_potential_file, only : effective_potential_file_mapHistToRef
      63              : #if defined DEV_MS_SCALEUP
      64              :  use scup_global, only : global_set_parent_iter,global_set_print_parameters
      65              : #endif
      66              :  use m_scup_dataset
      67              :  use m_multibinit_dataset
      68              : 
      69              :  implicit none
      70              : 
      71              :  private
      72              : !!***
      73              : 
      74              :  public :: mover
      75              : !!***
      76              : 
      77              : contains
      78              : !!***
      79              : 
      80              : !!****f* ABINIT/mover
      81              : !! NAME
      82              : !! mover
      83              : !!
      84              : !! FUNCTION
      85              : !! Move ion or change acell acording to forces and stresses
      86              : !!
      87              : !! INPUTS
      88              : !!  amu_curr(ntypat)=mass of each atom for the current image
      89              : !!  dtfil <type(datafiles_type)>=variables related to files
      90              : !!  dtset <type(dataset_type)>=all input variables for this dataset
      91              : !!   | mband=maximum number of bands
      92              : !!   | mgfft=maximum size of 1D FFTs
      93              : !!   | mkmem =number of k points treated by this node
      94              : !!   |  angular momentum for nonlocal pseudopotential
      95              : !!   | mpw=maximum dimensioned size of npw.
      96              : !!   | natom=number of atoms in unit cell
      97              : !!   |  except on first call (hartree/bohr); updated on output
      98              : !!   | nfft=(effective) number of FFT grid points (for this processor)
      99              : !!   |      for the "coarse" grid (see NOTES below)
     100              : !!   | nkpt=number of k points.
     101              : !!   | nspden=number of spin-density components
     102              : !!   | nsppol=1 for unpolarized, 2 for spin-polarized
     103              : !!   | nsym=number of symmetry elements in space group
     104              : !!  itimimage_gstate= [optional] counter for the itimimage loop, in the calling routine.
     105              : !!  mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
     106              : !!  mpi_enreg=information about MPI parallelization
     107              : !!  nfftf=(effective) number of FFT grid points (for this processor)
     108              : !!       for the "fine" grid (see NOTES below)
     109              : !!  npwarr(nkpt)=number of planewaves in basis and boundary at this k point.
     110              : !!  nattyp(ntypat)= # atoms of each type.
     111              : !!  paw_dmft  <type(paw_dmft_type)>= paw+dmft related data
     112              : !!  psps <type(pseudopotential_type)>=variables related to pseudopotentials
     113              : !!   | mpsang= 1+maximum angular momentum for nonlocal pseudopotentials
     114              : !!  rprimd(3,3)=dimensional primitive translations (bohr)
     115              : !!  scup_dtset <type(scup_dtset_type) = derived datatype holding all options
     116              :  !!            for the evaluation of an effective electronic model using SCALE UP
     117              : !!
     118              : !! OUTPUT
     119              : !!  results_gs <type(results_gs_type)>=results (energy and its components,
     120              : !!   forces and its components, the stress tensor) of a ground-state computation
     121              : !!  eigen(mband*nkpt*nsppol)=array for holding eigenvalues (hartree)
     122              : !!  resid(mband*nkpt*nsppol)=residuals for each band over all k points.
     123              : !!
     124              : !! SIDE EFFECTS
     125              : !! Rest of i/o is related to lda
     126              : !!  acell(3)=length scales of primitive translations (bohr)
     127              : !!  cg(2,mcg)=array for planewave coefficients of wavefunctions.
     128              : !!  electronpositron <type(electronpositron_type)>=quantities for the electron-positron annihilation
     129              : !!  initialized= if 0 the initialisation of the gstate run is not yet finished
     130              : !!  irrzon(nfft**(1-1/nsym),2,(nspden/nsppol)-3*(nspden/4))=irreducible zone data
     131              : !!  occ(mband*nkpt*nsppol=occupation number for each band (usually 2) at each k point.
     132              : !!  rhog(2,nfftf)=array for Fourier transform of electron density
     133              : !!  rhor(nfftf,nspden)=array for electron density in electrons/bohr**3.
     134              : !!  scf_history <type(scf_history_type)>=arrays obtained from previous SCF cycles
     135              : !!  symrec(3,3,nsym)=symmetry operations in reciprocal space
     136              : !!  taug(2,nfftf*dtset%usekden)=array for Fourier transform of kinetic energy density
     137              : !!  taur(nfftf,nspden*dtset%usekden)=array for kinetic energy density
     138              : !!  vel(3,natom)=old value of velocity; updated on output
     139              : !!  vel_cell(3,3)=old value of cell parameters velocity; updated on output
     140              : !!  xred(3,natom)=reduced dimensionless atomic coordinates; updated on output
     141              : !!  xred_old(3,natom)=work space for old xred
     142              : !!  eff_pot<type(effective_potential_type)> = optional,effective_potential datatype
     143              : !!  verbose = optional, default is true, flag to disable the verbose mode
     144              : !!  write_HIST = optional, default is true, flag to disble the write of the HIST file
     145              : !!
     146              : !! NOTES
     147              : !! This subroutine uses the arguments natom, xred, vel, amu_curr,
     148              : !! vis, and dtion (the last two contained in dtset) to make
     149              : !! molecular dynamics updates.  The rest of the lengthy
     150              : !! argument list supports the underlying lda computation
     151              : !! of forces, returned from subroutine scfcv
     152              : !!
     153              : !! USE OF FFT GRIDS:
     154              : !! =================
     155              : !! In case of PAW:
     156              : !! ---------------
     157              : !!    Two FFT grids are used:
     158              : !!    - A "coarse" FFT grid (defined by ecut)
     159              : !!      for the application of the Hamiltonian on the plane waves basis.
     160              : !!      It is defined by nfft, ngfft, mgfft, ...
     161              : !!      Hamiltonian, wave-functions, density related to WFs (rhor here), ...
     162              : !!      are expressed on this grid.
     163              : !!    - A "fine" FFT grid (defined) by ecutdg)
     164              : !!      for the computation of the density inside PAW spheres.
     165              : !!      It is defined by nfftf, ngfftf, mgfftf, ...
     166              : !!      Total density, potentials, ...
     167              : !!      are expressed on this grid.
     168              : !! In case of norm-conserving:
     169              : !! ---------------------------
     170              : !!    - Only the usual FFT grid (defined by ecut) is used.
     171              : !!      It is defined by nfft, ngfft, mgfft, ...
     172              : !!      For compatibility reasons, (nfftf,ngfftf,mgfftf)
     173              : !!      are set equal to (nfft,ngfft,mgfft) in that case.
     174              : !!
     175              : !! SOURCE
     176              : 
     177          393 : subroutine mover(scfcv_args,ab_xfh,acell,amu_curr,dtfil,&
     178          393 : & electronpositron,rhog,rhor,rprimd,vel,vel_cell,xred,xred_old,&
     179              : & effective_potential,filename_ddb,itimimage_gstate,verbose,verbose_cycle,writeHIST,scup_dtset,sc_size,multibinit_dtset)
     180              : 
     181              : !Arguments ------------------------------------
     182              : !scalars
     183              : integer, intent(in), optional :: itimimage_gstate
     184              : type(scfcv_t),intent(inout) :: scfcv_args
     185              : type(datafiles_type),intent(inout),target :: dtfil
     186              : type(electronpositron_type),pointer :: electronpositron
     187              : type(ab_xfh_type),intent(inout) :: ab_xfh
     188              : type(effective_potential_type),optional,intent(inout) :: effective_potential
     189              : logical,optional,intent(in) :: verbose
     190              : logical,optional,intent(in) :: verbose_cycle
     191              : logical,optional,intent(in) :: writeHIST
     192              : character(len=fnlen),optional,intent(in) :: filename_ddb
     193              : !arrays
     194              : real(dp),intent(inout) :: acell(3)
     195              : real(dp), intent(in),target :: amu_curr(:) !(scfcv%dtset%ntypat)
     196              : real(dp), pointer :: rhog(:,:),rhor(:,:)
     197              : real(dp), intent(inout) :: xred(3,scfcv_args%dtset%natom),xred_old(3,scfcv_args%dtset%natom)
     198              : real(dp), intent(inout) :: vel(3,scfcv_args%dtset%natom),vel_cell(3,3),rprimd(3,3)
     199              : type(scup_dtset_type),optional, intent(inout) :: scup_dtset
     200              : type(multibinit_dtset_type),optional, intent(inout) ::multibinit_dtset
     201              : integer,optional,intent(in) :: sc_size(3)
     202              : 
     203              : !Local variables-------------------------------
     204              : !scalars
     205              : integer,parameter :: level=102,master=0
     206          393 : type(abihist) :: hist,hist_prev
     207              : type(abimover) :: ab_mover
     208              : type(abimover_specs) :: specs
     209          393 : type(abiforstr) :: preconforstr ! Preconditioned forces and stress
     210          393 : type(delocint) :: deloc
     211              : type(pawfgr_type) :: pawfgr
     212          393 : type(mttk_type) :: mttk_vars
     213          393 : type(pimd_type) :: pimd_param
     214              : integer :: itime,icycle,itime_hist,iexit=0,ifirst,ihist_prev,ihist_prev2,timelimit_exit,ncycle,nhisttot,kk,jj,me
     215              : integer :: nmpi,ntime,option,comm,mgfftf,nfftf
     216              : integer :: nerr_dilatmx,my_quit,ierr,quitsum_request
     217              : integer ABI_ASYNC :: quitsum_async
     218              : character(len=500) :: msg
     219              : !character(len=500) :: dilatmx_errmsg
     220              : character(len=8) :: stat4xml
     221              : character(len=35) :: fmt
     222              : character(len=fnlen) :: filename,fname_ddb,name_file
     223              : character(len=500) :: MY_NAME = "mover"
     224              : real(dp) :: gr_avg,ecut_eff,ecutdg_eff,ucvol,boxcut,gsqcut_eff
     225              : logical :: DEBUG=.FALSE., effective_potential_verbose, need_verbose=.TRUE.,need_verbose_cycle=.TRUE.,need_writeHIST=.TRUE.
     226              : logical :: need_scfcv_cycle = .TRUE., need_elec_eval = .FALSE.
     227              : logical :: changed,useprtxfase
     228              : logical :: skipcycle,force_hist_copy=.FALSE.
     229              : integer :: minIndex,ii,similar,conv_retcode
     230              : integer :: iapp
     231              : logical :: file_exists
     232              : logical :: re_init_rho
     233              : #ifdef FC_NVHPC
     234              : logical :: wrong=.false. !Silly trick to prevent NVHPC optimization issue
     235              : #endif
     236              : real(dp) :: minE,wtime_step,now,prev
     237              : !arrays
     238              : integer :: itimes(2),ngfft(18),ngfftf(18)
     239              : real(dp) :: gprimd(3,3),rprim(3,3),rprimd_prev(3,3),gmet(3,3),rmet(3,3)
     240          393 : real(dp),allocatable :: gred_corrected(:,:),xred_prev(:,:),ph1df(:,:),tmp(:,:),tmp_1d(:)
     241              : real(dp) :: k0(3)
     242              : ! ***************************************************************
     243          393 :  need_verbose=.TRUE.
     244          393 :  if(present(verbose)) need_verbose = verbose
     245              : 
     246          393 :   need_verbose_cycle=.TRUE.
     247          393 :   if(present(verbose_cycle)) need_verbose_cycle = verbose_cycle
     248              : 
     249          393 :   need_writeHIST=.TRUE.
     250          393 :   if(present(writeHIST)) need_writeHIST = writeHIST
     251              : 
     252              :  ! enable time limit handler if not done in callers.
     253          393 :  if (enable_timelimit_in(MY_NAME) == MY_NAME) then
     254          393 :    if (need_verbose) then
     255            0 :      write(std_out,*)"Enabling timelimit check in function: ",trim(MY_NAME)," with timelimit: ",trim(sec2str(get_timelimit()))
     256              :    end if
     257              :  end if
     258              : 
     259          393 :  re_init_rho = .FALSE.
     260              : 
     261              : !Table of contents
     262              : !(=>) Refers to an important call (scfcv,pred_*)
     263              : !
     264              : !01. Initialization of indexes and allocations of arrays
     265              : !02. Particularities of each predictor
     266              : !03. Set the number of iterations ntime
     267              : !04. Try to read history of previous calculations
     268              : !05. Allocate the hist structure
     269              : !06. First output before any itime or icycle
     270              : !07. Fill the history of the first SCFCV
     271              : !08. Loop for itime (From 1 to ntime)
     272              : !09. Loop for icycle (From 1 to ncycle)
     273              : !10. Output for each icycle (and itime)
     274              : !11. Symmetrize atomic coordinates over space group elements
     275              : !12. => Call to SCFCV routine and fill history with forces
     276              : !13. Write the history into the _HIST file
     277              : !14. Output after SCFCV
     278              : !15. => Test Convergence of forces and stresses
     279              : !16. => Precondition forces, stress and energy
     280              : !17. => Call to each predictor
     281              : !18. Use the history  to extract the new values
     282              : !19. End loop icycle
     283              : !20. End loop itime
     284              : !21. Set the final values of xred
     285              : !22. XML Output at the end
     286              : !23. Deallocate hist and ab_mover datatypes
     287              : !
     288          393 :  call abimover_ini(ab_mover,amu_curr,dtfil,scfcv_args%dtset,specs)
     289              : 
     290          393 :  if (ab_mover%ionmov==10 .or. ab_mover%ionmov==11) call delocint_ini(deloc)
     291              : 
     292          393 :  if (ab_mover%ionmov==13 .or. ab_mover%ionmov==25)then
     293           31 :    call mttk_ini(mttk_vars,ab_mover%nnos)
     294              :  end if
     295              : 
     296              : !###########################################################
     297              : !### 03. Set the number of iterations ntime
     298              : !###     By default ntime==1 but if the user enters a lower
     299              : !###     value, mover will execute at least one iteration
     300              : 
     301          393 :  if (scfcv_args%dtset%ntime<1)then
     302            0 :    ntime=1
     303              :  else
     304          393 :    ntime=scfcv_args%dtset%ntime
     305              :  end if
     306              : 
     307              : !###########################################################
     308              : !### 04. Try to read history of previous calculations
     309              : !###     It requires NetCDF library
     310              : 
     311              : !Init MPI data
     312          393 :  comm=scfcv_args%mpi_enreg%comm_cell
     313          393 :  me=xmpi_comm_rank(comm)
     314              : 
     315              : 
     316          393 :  filename=trim(ab_mover%filnam_ds(4))//'_HIST.nc'
     317              : 
     318              : 
     319          393 :  if (ab_mover%restartxf<0)then
     320              : !  Read history from file (and broadcast if MPI)
     321           15 :    if (me==master) then
     322           15 :      call read_md_hist(filename,hist_prev,specs%isVused,specs%isARused,ab_mover%restartxf==-3)
     323              :      endif
     324              : 
     325              : 
     326           15 :    call abihist_bcast(hist_prev,master,comm)
     327              : 
     328              : 
     329              : !  If restartxf specifies to reconstruct the history
     330           15 :    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-1)then
     331            1 :      ntime=ntime+hist_prev%mxhist
     332              :    end if
     333              : 
     334              : !  If non deterministic algorithm is used, forcing reading of input hist file
     335           15 :    if (ab_mover%ionmov==16) then
     336            0 :      force_hist_copy=.TRUE.
     337              :    end if
     338              : 
     339              : !  If restartxf specifies to start from the lowest energy
     340           15 :    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-2)then
     341            0 :      minE=hist_prev%etot(1)
     342            0 :      minIndex=1
     343            0 :      do ii=1,hist_prev%mxhist
     344            0 :        if(need_verbose) write(std_out,*) 'Iteration:',ii,' Total Energy:',hist_prev%etot(ii)
     345            0 :        if (minE>hist_prev%etot(ii))then
     346            0 :          minE=hist_prev%etot(ii)
     347            0 :          minIndex=ii
     348              :        end if
     349              :      end do
     350            0 :      if(need_verbose)write(std_out,*) 'The lowest energy occurs at iteration:',minIndex,'etotal=',minE
     351            0 :      acell(:)   =hist_prev%acell(:,minIndex)
     352            0 :      rprimd(:,:)=hist_prev%rprimd(:,:,minIndex)
     353            0 :      xred(:,:)  =hist_prev%xred(:,:,minIndex)
     354            0 :      vel(:, :) = hist_prev%vel(:, :, minIndex)
     355            0 :      call abihist_free(hist_prev)
     356              :    end if
     357              : !  If restarxf specifies to start to the last iteration
     358           15 :    if (hist_prev%mxhist>0.and.ab_mover%restartxf==-3)then
     359            3 :      if(present(effective_potential))then
     360            3 :        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
     361              :        !xred(:,:) = hist_prev%xred(:,:,1) ! Fill xred with new ordering
     362            3 :        hist%ihist = 1
     363              :      end if
     364           12 :      acell(:)   =hist_prev%acell(:,hist_prev%mxhist)
     365           39 :      rprimd(:,:)=hist_prev%rprimd(:,:,hist_prev%mxhist)
     366          323 :      xred(:,:)  =hist_prev%xred(:,:,hist_prev%mxhist)
     367          323 :      vel(:, :) = hist_prev%vel(:, :, hist_prev%mxhist)
     368            3 :      call abihist_free(hist_prev)
     369              :    end if
     370              : 
     371              :  end if !if (ab_mover%restartxf<=0)
     372              : 
     373              : !###########################################################
     374              : !### 05. Allocate the hist structure
     375              : 
     376          393 :  iexit=0; timelimit_exit=0
     377          393 :  ncycle=specs%ncycle
     378              : 
     379          393 :  if(ab_mover%ionmov==25.and.scfcv_args%dtset%hmctt>=0)then
     380            2 :    ncycle=scfcv_args%dtset%hmctt
     381            2 :    if(scfcv_args%dtset%hmcsst>0.and.ab_mover%optcell/=0)then
     382            0 :       ncycle=ncycle+scfcv_args%dtset%hmcsst
     383              :    endif
     384              :  endif
     385              : 
     386          393 :  nhisttot=ncycle*ntime;if (scfcv_args%dtset%nctime>0) nhisttot=nhisttot+1
     387              : !AM_2017 New version of the hist, we just store the needed history step not all of them...
     388          393 :  if(specs%nhist/=-1)then
     389          393 :   nhisttot = specs%nhist! We don't need to store all the history
     390              :  endif
     391              : 
     392          393 :  call abihist_init(hist,ab_mover%natom,nhisttot,specs%isVused,specs%isARused)
     393          393 :  call abiforstr_ini(preconforstr,ab_mover%natom)
     394              : 
     395              : !###########################################################
     396              : !### 06. First output before any itime or icycle iteration
     397              : 
     398              : !If effective potential is present forces will be compute with it
     399          393 :  if (present(effective_potential))then
     400           44 :    need_scfcv_cycle = .FALSE.
     401           44 :    if(need_verbose)then
     402              :      write(msg,'(2a,i2,5a,80a)')&
     403           44 : &     ch10,'=== [ionmov=',ab_mover%ionmov,'] ',trim(specs%method),' with effective potential',&
     404         3608 : &     ch10,('=',kk=1,80)
     405          132 :      call wrtout([std_out, ab_out], msg)
     406              :    end if
     407           44 :    need_elec_eval = .FALSE.
     408           44 :    if(present(scup_dtset))then
     409           44 :      need_elec_eval = scup_dtset%scup_elec_model
     410              :    endif
     411              :  else
     412          349 :    if(need_verbose)then
     413              :      write(msg,'(a,a,i2,a,a,a,80a)')&
     414          349 : &     ch10,'=== [ionmov=',ab_mover%ionmov,'] ',trim(specs%method),&
     415        28618 : &     ch10,('=',kk=1,80)
     416         1047 :      call wrtout([std_out, ab_out], msg)
     417              :    end if
     418              :  end if
     419              : 
     420              : !Format for printing on each cycle
     421              :  write(fmt,'(a6,i2,a4,i2,a4,i2,a4,i2,a9)')&
     422          393 :   '(a,a,i',int(log10(real(ntime))+1),&
     423          393 :   ',a,i',int(log10(real(ntime))+1),&
     424          393 :   ',a,i',int(log10(real(ncycle))+1),&
     425          393 :   ',a,i',int(log10(real(ncycle))+1),&
     426          786 :   ',a,a,80a)'
     427              : 
     428              : !###########################################################
     429              : !### 07. Fill the history of the first SCFCV
     430              : 
     431          393 :  if (ab_mover%ionmov==26)then
     432              : 
     433              : !Tdep call need to merge with adewandre branch
     434          393 :   else if (ab_mover%ionmov==27)then
     435            0 :     if(present(filename_ddb))then
     436            0 :       fname_ddb = trim(filename_ddb)
     437              :     else
     438            0 :       fname_ddb = trim(ab_mover%filnam_ds(3))//'_DDB'
     439              :     end if
     440            0 :     INQUIRE(FILE=filename, EXIST=file_exists)
     441              : 
     442            0 :     ABI_ERROR("This section has been disabled, ph_freez_disp is not defined in main ABINIT")
     443              : 
     444              : ! XG 20200322 : The input variables ph_freez_disp are not documented neither tested, so they
     445              : ! have been removed from the allowed list in the parser. Also, you should not be here !
     446              : !   call generate_training_set(acell,ab_mover%ph_freez_disp_addStrain==1,ab_mover%ph_freez_disp_ampl,&
     447              : !&                             fname_ddb,hist,ab_mover%natom,ab_mover%ph_freez_disp_nampl,ntime,&
     448              : !&                             ab_mover%ph_ngqpt,ab_mover%ph_nqshift,ab_mover%ph_freez_disp_option,&
     449              : !&                             ab_mover%ph_qshift,scfcv_args%dtset%supercell_latt,&
     450              : !&                             rprimd,ab_mover%mdtemp(2),xred,comm,DEBUG)
     451              : 
     452              : 
     453              :     !Fill history with the values of xred, acell and rprimd of the first configuration
     454            0 :     acell(:)   =hist%acell(:,1)
     455            0 :     rprimd(:,:)=hist%rprimd(:,:,1)
     456            0 :     xred(:,:)  =hist%xred(:,:,1)
     457              : 
     458              :  else
     459              : 
     460              :    ! Fill history with the values of xred, acell and rprimd
     461          393 :    call var2hist(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
     462              : 
     463              : 
     464              :    ! Fill velocities and ionic kinetic energy
     465          393 :    call vel2hist(ab_mover%amass,hist,vel,vel_cell)
     466          393 :    hist%time(hist%ihist)=zero
     467              : 
     468              :  end if
     469              : 
     470              : !Decide if prtxfase will be called
     471          393 :  useprtxfase=.FALSE.
     472         5276 :  do ii=1,ab_mover%natom
     473         5276 :    if (ab_mover%prtatlist(ii)/=0)then
     474              :      useprtxfase=.TRUE.; exit
     475              :    end if
     476              :  end do
     477              : 
     478              : !At beginning no error
     479          393 :  nerr_dilatmx = 0
     480              : !Copy the number of degrees of freedom in hist structure
     481          393 :  hist%ndof=ab_mover%ndof
     482              : 
     483         1179 :   ABI_MALLOC(xred_prev,(3,scfcv_args%dtset%natom))
     484              : 
     485          393 :   if (present(effective_potential) .and. need_verbose .and. .not.need_verbose_cycle .and. ab_mover%ionmov==25) then
     486          162 :     write(msg,'(3a,80a)') ch10,'--- Initial state',ch10,('-',kk=1,80)
     487            6 :     call wrtout([std_out, ab_out], msg)
     488            2 :     if(present(multibinit_dtset))then
     489              :       call effective_potential_evaluate( &
     490              : &     effective_potential,scfcv_args%results_gs%etotal,scfcv_args%results_gs%fcart,scfcv_args%results_gs%gred,&
     491              : &     scfcv_args%results_gs%strten,ab_mover%natom,rprimd,xred=xred,verbose=need_verbose,&
     492              : &     elec_eval=need_elec_eval,efield_type=multibinit_dtset%efield_type,efield=multibinit_dtset%efield,&
     493              : &     efield_lambda=multibinit_dtset%efield_lambda,nefield=multibinit_dtset%nefield,&
     494              : &     efield_period=multibinit_dtset%efield_period,efield_phase=multibinit_dtset%efield_phase,&
     495              : &     efield_gmean=multibinit_dtset%efield_gmean,efield_gvel=multibinit_dtset%efield_gvel,efield_sigma=multibinit_dtset%efield_sigma,&
     496            2 : &     efield_background=multibinit_dtset%efield_background,time=zero)
     497              :     else
     498              :       call effective_potential_evaluate( &
     499              : &     effective_potential,scfcv_args%results_gs%etotal,scfcv_args%results_gs%fcart,scfcv_args%results_gs%gred,&
     500              : &     scfcv_args%results_gs%strten,ab_mover%natom,rprimd,xred=xred,verbose=need_verbose,&
     501            0 : &     elec_eval=need_elec_eval,time=zero)
     502              :     end if
     503              :   end if
     504              : 
     505              : !###########################################################
     506              : !### 08. Loop for itime (From 1 to ntime)
     507          393 :  quitsum_request = xmpi_request_null
     508              : 
     509         3655 :  do itime=1,ntime
     510              : 
     511         3655 :    call yaml_iterstart("itime", itime, dev_null, scfcv_args%dtset%use_yaml)
     512              : 
     513              :    ! Handle time limit condition.
     514         3655 :    if (itime == 1) prev = abi_wtime()
     515         3655 :    if (itime  > 1) then
     516         3262 :      now = abi_wtime()
     517         3262 :      wtime_step = now - prev
     518         3262 :      prev = now
     519         3262 :      write(msg,*)sjoin("{mover_itime:", itoa(itime - 1), ", wall_time: '", sec2str(wtime_step), "'} <<< TIME")
     520         3262 :      if(need_verbose)call wrtout(std_out, msg)
     521         3262 :      if (have_timelimit_in(MY_NAME)) then
     522            0 :        if (itime > 2) then
     523            0 :          call xmpi_wait(quitsum_request,ierr)
     524            0 :          if (quitsum_async > 0) then
     525            0 :            write(msg,"(3a)")"Approaching time limit ",trim(sec2str(get_timelimit())), ". Will exit itime loop in mover."
     526            0 :            if(need_verbose) ABI_COMMENT(msg)
     527            0 :            if(need_verbose) call wrtout(ab_out, msg)
     528              :            timelimit_exit = 1
     529              :            exit
     530              :          end if
     531              :        end if
     532              : 
     533            0 :        my_quit = 0; if (now - get_start_time() + 2.15 * wtime_step > get_timelimit()) my_quit = 1
     534            0 :        call xmpi_isum(my_quit,quitsum_async,comm,quitsum_request,ierr)
     535              :      end if
     536              :    end if
     537              : 
     538         3655 :    skipcycle=.FALSE.
     539              : #if defined HAVE_LOTF
     540              :    if(ab_mover%ionmov==23 .and. .not. lotf_extrapolation(itime)) skipcycle=.True.
     541              : #endif
     542              : 
     543              :    ! If RMM-DIIS is used, decrease the number of NSCF steps done with wfoptalg before activating RMM-DIIS.
     544              :    ! In vtowfk we have the condition: istep > 3 + dtset%rmm_diis
     545              :    ! so setting rmm_diis = 1 gives:
     546              :    !    4 NSCF iterations for itime == 1
     547              :    !    1 NSCF iterations for itime >= 2.
     548         3655 :     if (scfcv_args%dtset%rmm_diis /= 0 .and. itime == 2) then
     549            0 :       scfcv_args%dtset%rmm_diis = scfcv_args%dtset%rmm_diis - 3
     550            0 :       if (scfcv_args%dtset%rmm_diis == 0) scfcv_args%dtset%rmm_diis = 1
     551            0 :       call wrtout(std_out, sjoin(" itime == 2 with RMM-DIIS --> setting rmm_diis to:", itoa(scfcv_args%dtset%rmm_diis)))
     552              :     end if
     553              : 
     554         3655 :     if (need_verbose .and. .not.need_verbose_cycle) then
     555        16524 :       write(msg,'(2a,i0,a,i0,2a,80a)') ch10,'--- Iteration: (',itime,'/',ntime,')',ch10,('-',kk=1,80)
     556          612 :       call wrtout([std_out, ab_out], msg)
     557              :     end if
     558              : 
     559              : !  ###########################################################
     560              : !  ### 09. Loop for icycle (From 1 to ncycle)
     561        12503 :    do icycle=1,ncycle
     562              : 
     563        11496 :      call yaml_iterstart("icycle", icycle, dev_null, scfcv_args%dtset%use_yaml)
     564              : 
     565        11496 :      itime_hist = (itime-1)*ncycle + icycle ! Store the time step in the history
     566              : 
     567              : !    ###########################################################
     568              : !    ### 10. Output for each icycle (and itime)
     569        11496 :       if(need_verbose.and.need_verbose_cycle)then
     570              :         write(msg,fmt)&
     571       282204 :          ch10,'--- Iteration: (',itime,'/',ntime,') Internal Cycle: (',icycle,'/',ncycle,')',ch10,('-',kk=1,80)
     572        10452 :         call wrtout([std_out, ab_out], msg)
     573              :       end if
     574        11496 :      if (useprtxfase) call prtxfase(ab_mover,hist,itime_hist,std_out,mover_BEFORE)
     575              : 
     576     35517980 :      xred_prev(:,:)=xred(:,:)
     577        11496 :      rprimd_prev(:,:)=rprimd(:,:)
     578              : 
     579              : !    ###########################################################
     580              : !    ### 11. Symmetrize atomic coordinates over space group elements
     581              : 
     582              :      call symmetrize_xred(ab_mover%natom,&
     583        11496 :       scfcv_args%dtset%nsym,scfcv_args%dtset%symrel,scfcv_args%dtset%tnons,xred,indsym=scfcv_args%indsym)
     584              : 
     585     35516132 :      changed = any(xred /= xred_prev)
     586        11496 :      if (changed)then
     587         1909 :        hist%xred(:,:,hist%ihist)=xred(:,:)
     588           49 :        if(need_verbose) then
     589           49 :          write(std_out,*) 'WARNING: ATOMIC COORDINATES WERE SYMMETRIZED'
     590           49 :          write(std_out,*) 'DIFFERENCES:'
     591          514 :          do kk=1,ab_mover%natom
     592         1909 :            write(std_out,*) xred(:,kk)-xred_prev(:,kk)
     593              :          end do
     594              :        end if
     595         1909 :        xred_prev(:,:)=xred(:,:)
     596              :      end if
     597              : 
     598              : !    ###########################################################
     599              : !    ### 12. => Call to SCFCV routine and fill history with forces
     600        11496 :       if (need_verbose.and.need_verbose_cycle) then
     601         3484 :         if (need_scfcv_cycle) then
     602              :           write(msg,'(a,3a,33a,44a)')&
     603        78432 :            ch10,('-',kk=1,3),'SELF-CONSISTENT-FIELD CONVERGENCE',('-',kk=1,44)
     604              :        else
     605              :          write(msg,'(a,3a,33a,44a)')&
     606        88800 :           ch10,('-',kk=1,3),'EFFECTIVE POTENTIAL CALCULATION',('-',kk=1,44)
     607              :        end if
     608        10452 :        call wrtout([std_out, ab_out], msg)
     609              :      end if
     610              : 
     611        11496 :      if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1.and.hist_prev%ihist<=hist_prev%mxhist)then
     612              : 
     613            2 :        call abihist_compare_and_copy(hist_prev,hist,ab_mover%natom,similar,tol8,specs%nhist==nhisttot,force_hist_copy)
     614            2 :        hist_prev%ihist=hist_prev%ihist+1
     615              : 
     616            2 :        if (hist_prev%ihist==hist_prev%mxhist) re_init_rho=.TRUE.
     617              : 
     618              :      else
     619        11494 :        scfcv_args%ndtpawuj=0
     620        11494 :        iapp=itime
     621        11494 :        if(icycle>1.and.icycle/=ncycle) iapp=-1
     622        11494 :        if(itime==1 .and. icycle/=ncycle ) iapp=-icycle-1
     623        11494 :        if (ab_mover%ionmov==14.and.(icycle<ncycle)) iapp=-1
     624              : 
     625              : #if defined HAVE_LOTF
     626              :        if (ab_mover%ionmov/=23 .or.(lotf_extrapolation(itime).and.(icycle/=1.or.itime==1)))then
     627              : #endif
     628              :          !call scfcv_new2(scfcv_args,electronpositron,rhog,rhor,rprimd,xred,xred_old,conv_retcode)
     629              : 
     630              :          !WVL - reformat the wavefunctions in the case of xred != xred_old
     631     35517946 :          if (scfcv_args%dtset%usewvl == 1 .and. maxval(xred_old - xred) > zero) then
     632              :            ! Before running scfcv, on non-first geometry step iterations,
     633              :            ! we need to reformat the wavefunctions, taking into acount the new
     634              :            ! coordinates. We prepare to change rhog (to be removed) and rhor.
     635            0 :            ABI_FREE(rhog)
     636            0 :            ABI_FREE(rhor)
     637              :            call wvl_wfsinp_reformat(scfcv_args%dtset, scfcv_args%mpi_enreg,&
     638            0 : &           scfcv_args%psps, rprimd, scfcv_args%wvl, xred, xred_old)
     639            0 :            scfcv_args%nfftf = scfcv_args%dtset%nfft
     640            0 :            ABI_MALLOC(rhog,(2, scfcv_args%dtset%nfft))
     641            0 :            ABI_MALLOC(rhor,(2, scfcv_args%dtset%nfft))
     642              :            call wvl_mkrho(scfcv_args%dtset, scfcv_args%irrzon, scfcv_args%mpi_enreg,&
     643            0 : &           scfcv_args%phnons, rhor,scfcv_args%wvl%wfs,scfcv_args%wvl%den)
     644              :          end if
     645              : 
     646              :          !Do another initialization of rho using the last atomic positions
     647              :          !to avoid potential problems during restart of MD
     648        11494 :          if (re_init_rho) then
     649              :             !Recompute some local quantities required by initro
     650            1 :             call pawfgr_init(pawfgr,scfcv_args%dtset,mgfftf,nfftf,ecut_eff,ecutdg_eff,ngfft,ngfftf)
     651            3 :             ABI_MALLOC(ph1df,(2,3*(2*mgfftf+1)*scfcv_args%dtset%natom))
     652            1 :             call getph(scfcv_args%atindx,scfcv_args%dtset%natom,ngfftf(1),ngfftf(2),ngfftf(3),ph1df,xred)
     653            1 :             call metric(gmet,gprimd,ab_out,rmet,rprimd,ucvol)
     654            1 :             k0(:)=0.0_dp
     655            1 :             call getcut(boxcut,ecutdg_eff,gmet,gsqcut_eff,scfcv_args%dtset%iboxcut,ab_out,k0,ngfftf)
     656              :             !Reinitialise density from current xred
     657              :             call initro(scfcv_args%atindx,scfcv_args%dtset%densty,gmet,gsqcut_eff,&
     658              : &             scfcv_args%psps%usepaw,mgfftf,scfcv_args%mpi_enreg,scfcv_args%psps%mqgrid_vl,&
     659              : &             scfcv_args%dtset%natom,scfcv_args%nattyp,nfftf,ngfftf,scfcv_args%dtset%nspden,&
     660              : &             scfcv_args%psps%ntypat,scfcv_args%psps,scfcv_args%pawtab,ph1df,&
     661              : &             scfcv_args%psps%qgrid_vl,rhog,rhor,scfcv_args%dtset%spinat,ucvol,&
     662            1 : &             scfcv_args%psps%usepaw,scfcv_args%dtset%ziontypat,scfcv_args%dtset%znucl)
     663            1 :             call pawfgr_destroy(pawfgr)
     664            1 :             ABI_FREE(ph1df)
     665            1 :             re_init_rho = .FALSE.
     666              :             ! Also update scf_history with the correct density for density prediction if required
     667            3 :              if (scfcv_args%scf_history%history_size>0) scfcv_args%scf_history%atmrho_last(:)=rhor(:,1)
     668              :          end if
     669              : 
     670              : !        MAIN CALL TO SELF-CONSISTENT FIELD ROUTINE
     671        11494 :          if (need_scfcv_cycle) then
     672              : 
     673         1632 :            call dtfil%init_time(iapp)
     674         1632 :            itimes(1)=itime; itimes(2)=1
     675         1632 :            if(present(itimimage_gstate))then
     676         1632 :              itimes(2)=itimimage_gstate
     677              :            endif
     678              : 
     679              : !DEBUG
     680              : ! write(std_out,'(a,5i4)')' m_mover, before scfcv_run : itimes(1:2)=',itimes(1:2)
     681              : !ENDDEBUG
     682         1632 :            call scfcv_run(scfcv_args, electronpositron, itimes, rhog, rhor, rprimd, xred, xred_old, conv_retcode)
     683         1632 :            if (conv_retcode == -1) then
     684            0 :                msg = "Scf cycle returned conv_retcode == -1 (timelimit is approaching), this should not happen inside mover"
     685            0 :                ABI_WARNING(msg)
     686              :            end if
     687              : 
     688              :          else
     689              : !          For monte carlo don't need to recompute energy here (done in pred_montecarlo)
     690         9862 :            name_file='MD_anharmonic_terms_energy.dat'
     691         9862 :              if(itime == 1 .and. ab_mover%restartxf==-3)then
     692            9 :                 if(icycle==1)call effective_potential_file_mapHistToRef(effective_potential,hist,comm,scfcv_args%dtset%iatfix,&
     693            9 : &                                                                      need_verbose.and.need_verbose_cycle,sc_size=sc_size)!Map Hist to Ref to order atoms
     694         2249 :                xred(:,:) = hist%xred(:,:,1) ! Fill xred with new ordering
     695            9 :                hist%ihist = 1
     696              :              end if
     697              : 
     698              : #if defined DEV_MS_SCALEUP
     699              :            !If we a SCALE UP effective electron model give the iteration and set print-options
     700              :            if(need_elec_eval)then
     701              :               call global_set_parent_iter(itime)
     702              :               ! Set all print options to false.
     703              :               call global_set_print_parameters(geom=.FALSE.,eigvals=.FALSE.,eltic=.FALSE.,&
     704              : &                      orbocc=.FALSE.,bands=.FALSE.)
     705              :               if(itime == 1 .or. modulo(itime,scup_dtset%scup_printniter) == 0)then
     706              :                  call global_set_print_parameters(scup_dtset%scup_printgeom,scup_dtset%scup_printeigv,scup_dtset%scup_printeltic,&
     707              : &                         scup_dtset%scup_printorbocc,scup_dtset%scup_printbands)
     708              :               end if
     709              :            end if
     710              : #endif
     711              : 
     712         9862 :             effective_potential_verbose = need_verbose .and. (need_verbose_cycle .or. icycle == ncycle)
     713         9862 :             if(present(multibinit_dtset))then
     714              :                  !TODO: use multibinit_dtset to set the parameters of the effective potential
     715              :                  call effective_potential_evaluate( &
     716              : &               effective_potential,scfcv_args%results_gs%etotal,scfcv_args%results_gs%fcart,scfcv_args%results_gs%gred,&
     717              : &               scfcv_args%results_gs%strten,ab_mover%natom,rprimd,xred=xred,verbose=effective_potential_verbose,&
     718              : &               filename=name_file,elec_eval=need_elec_eval,efield_type=multibinit_dtset%efield_type,efield=multibinit_dtset%efield,&
     719              : &               efield_lambda=multibinit_dtset%efield_lambda,nefield=multibinit_dtset%nefield,&
     720              : &               efield_period=multibinit_dtset%efield_period,efield_phase=multibinit_dtset%efield_phase,&
     721              : &               efield_gmean=multibinit_dtset%efield_gmean,efield_gvel=multibinit_dtset%efield_gvel,efield_sigma=multibinit_dtset%efield_sigma,&
     722         9862 : &               efield_background=multibinit_dtset%efield_background,time=itime*ab_mover%dtion)
     723              :             else
     724              :                  call effective_potential_evaluate( &
     725              : &               effective_potential,scfcv_args%results_gs%etotal,scfcv_args%results_gs%fcart,scfcv_args%results_gs%gred,&
     726              : &               scfcv_args%results_gs%strten,ab_mover%natom,rprimd,xred=xred,verbose=effective_potential_verbose,&
     727            0 : &               filename=name_file,elec_eval=need_elec_eval,time=itime*ab_mover%dtion)
     728              :             end if
     729              : 
     730              : 
     731              : 
     732              : 
     733              : !          Check if the simulation did not diverge...
     734         9862 :            if(itime > 3 .and.ABS(scfcv_args%results_gs%etotal - hist%etot(1)) > 1E5)then
     735              : !            We set to false the flag corresponding to the bound
     736            0 :              effective_potential%anharmonics_terms%bounded = .FALSE.
     737            0 :              if(need_verbose.and.me==master)then
     738            0 :                ABI_WARNING("The simulation is diverging, please check your effective potential")
     739              :              end if
     740              : !            Set the flag to finish the simulation
     741            0 :              iexit=1
     742            0 :              stat4xml="Failed"
     743              :            else
     744              : !            We set to true the flag corresponding to the bound
     745         9862 :              effective_potential%anharmonics_terms%bounded = .TRUE.
     746              :            end if
     747              :          end if
     748              : #if defined HAVE_LOTF
     749              :        end if
     750              : #endif
     751              : !      ANOMALOUS SITUATION
     752              : !      This is the only case where rprimd could change inside scfcv
     753              : !      It generates a weird condition, we start with a certain
     754              : !      value for rprimd before scfcv and after we finish with a different value.
     755              : !      Notice that normally scfcv should not change rprimd
     756              : !      And even worse if optcell==0
     757              : !      The solution here is to recompute acell and store these value
     758              : !      in the present record even if initially it was not exactly
     759              : !      the value entering in scfcv
     760              : !      One test case with these condition is bigdft/t10
     761       149422 :        if (any(rprimd(:,:)/=rprimd_prev(:,:))) then
     762            0 :          hist%acell(:,hist%ihist)=acell(:)
     763            0 :          hist%rprimd(:,:,hist%ihist)=rprimd(:,:)
     764              :        end if
     765              : 
     766              : !      ANOMALOUS SITUATIONS
     767              : !      * In ionmov 4 & 5 xred could change inside SCFCV
     768              : !      So we need to take the values from the output
     769              : !
     770              : !      * Inside scfcv_core.F90 there is a call to symmetrize_xred.F90
     771              : !      for the first SCF cycle symmetrize_xred could change xred
     772        11494 :        if (ab_mover%ionmov<10)then
     773        17439 :          changed = any(xred /= xred_prev)
     774         1411 :          if (changed)then
     775          168 :            hist%xred(:,:,hist%ihist)=xred(:,:)
     776           16 :            if(need_verbose)then
     777           16 :              write(std_out,*) 'WARNING: ATOMIC COORDINATES WERE SYMMETRIZED AFTER SCFCV'
     778           16 :              write(std_out,*) 'DIFFERENCES:'
     779           54 :              do kk=1,ab_mover%natom
     780          168 :                write(std_out,*) xred(:,kk)-xred_prev(:,kk)
     781              :              end do
     782              :            end if
     783              :          end if
     784              :        end if
     785              : 
     786              : !      Fill velocities and ionic kinetic energy
     787        11494 :        call vel2hist(ab_mover%amass,hist,vel,vel_cell)
     788              : 
     789     35517946 :        hist%fcart(:,:,hist%ihist)=scfcv_args%results_gs%fcart(:,:)
     790        80458 :        hist%strten(:,hist%ihist) =scfcv_args%results_gs%strten(:)
     791        11494 :        hist%etot(hist%ihist)     =scfcv_args%results_gs%etotal
     792        11494 :        hist%entropy(hist%ihist)  =scfcv_args%results_gs%energies%entropy
     793        11494 :        hist%time(hist%ihist)     =real(itime,kind=dp)
     794              : 
     795              : !      !######################################################################
     796              :      end if ! if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1.and.hist_prev%ihist<=hist_prev%mxhist)then
     797              : 
     798              : !    Store trajectory in xfh file
     799        11496 :      if((ab_xfh%nxfh==0.or.itime/=1)) then
     800        34488 :        ABI_MALLOC(gred_corrected,(3,scfcv_args%dtset%natom))
     801        11496 :        call fcart2gred(hist%fcart(:,:,hist%ihist),gred_corrected,rprimd,ab_mover%natom)
     802              : !      Get rid of mean force on whole unit cell,
     803              : !      but only if no generalized constraints are in effect
     804        11496 :        if (ab_mover%nconeq==0)then
     805        45668 :          do ii=1,3
     806        45668 :            if (ii/=3.or.ab_mover%jellslab==0) then
     807     26663404 :              gr_avg=sum(gred_corrected(ii,:))/dble(ab_mover%natom)
     808     26663405 :              gred_corrected(ii,:)=gred_corrected(ii,:)-gr_avg
     809              :            end if
     810              :          end do
     811              :        end if
     812        11496 :        if (ncycle<10.and.ab_mover%restartxf>=0) then
     813        13192 :          do ii=1,3
     814        42874 :            rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
     815              :          end do
     816              : 
     817              : !        The size of ab_xfh%xfhist is to big for very large supercell.
     818              : !        Call it only for specific ionmov
     819        14561 :          if(any((/2,3,10,11,22/)==ab_mover%ionmov)) then
     820         1158 :            call xfh_update(ab_xfh,acell,gred_corrected,ab_mover%natom,rprim,hist%strten(:,hist%ihist),xred)
     821              :          end if
     822              :        end if
     823        11496 :        ABI_FREE(gred_corrected)
     824              :      end if
     825              : 
     826              : !    ###########################################################
     827              : !    ### 13. Write the history into the _HIST file
     828              : !    ###
     829              : 
     830        11496 :      if (need_writeHIST.and.me==master) then
     831        10394 :        ifirst=merge(0,1,(itime>1.or.icycle>1))
     832              :        call write_md_hist(hist,filename,ifirst,itime_hist,ab_mover%natom,scfcv_args%dtset%nctime,&
     833        10394 : &       ab_mover%ntypat,ab_mover%typat,amu_curr,ab_mover%znucl,ab_mover%dtion,scfcv_args%dtset%mdtemp)
     834              :      end if
     835              : 
     836              : !    ###########################################################
     837              : !    ### 14. Output after SCFCV
     838        11496 :       if(need_verbose.and.need_verbose_cycle.and.need_scfcv_cycle)then
     839       122550 :         write(msg,'(a,3a,a,72a)')ch10,('-',kk=1,3),'OUTPUT',('-',kk=1,71)
     840         4902 :         call wrtout([std_out, ab_out], msg)
     841              :       end if
     842        11496 :      if (useprtxfase.and..not.ab_mover%use_pimd_routine) then
     843         1624 :        call prtxfase(ab_mover,hist,itime_hist,ab_out,mover_AFTER)
     844         1624 :        call prtxfase(ab_mover,hist,itime_hist,std_out,mover_AFTER)
     845              :      end if
     846              : 
     847              : !    ###########################################################
     848              : !    ### 15. => Test Convergence of forces and stresses
     849              : 
     850        11496 :      if (itime==ntime.and.icycle==ncycle)then
     851          183 :        iexit=1
     852          183 :        stat4xml="Failed"
     853              :      else
     854        11313 :        stat4xml="Succeded"
     855              :      end if
     856              : 
     857              : !    Only if convergence is needed
     858        11496 :      if(specs%isFconv)then
     859         1344 :        if ((ab_mover%ionmov/=4.and.ab_mover%ionmov/=5).or.mod(itime,2)==1)then
     860         1330 :          if (scfcv_args%dtset%tolmxf/=0)then
     861              : 
     862              :            call fconv(hist%fcart(:,:,hist%ihist),&
     863              : &           scfcv_args%dtset%iatfix, &
     864              : &           iexit,itime,&
     865              : &           ab_mover%natom,&
     866              : &           ntime,&
     867              : &           ab_mover%optcell,&
     868              : &           scfcv_args%dtset%strfact,&
     869              : &           scfcv_args%dtset%strtarget,&
     870              : &           hist%strten(:,hist%ihist),&
     871              : &           rprim,&
     872         1326 : &           scfcv_args%dtset%tolmxf)
     873              :          else
     874            4 :            call erlxconv(hist,iexit,itime,itime_hist,ntime,scfcv_args%dtset%tolmxde)
     875              :          end if
     876              :        end if
     877              :      end if
     878              : 
     879        11496 :      if (itime==ntime.and.icycle==ncycle) iexit=1
     880              : 
     881              : !    ###########################################################
     882              : !    ### 16. => Precondition forces, stress and energy
     883              : !    ### 17. => Call to each predictor
     884              : !    Some MOLDYN algorithms require pimd_param to be initialized
     885        11496 :      if(ab_mover%use_pimd_routine) then
     886           10 :        call pimd_init(scfcv_args%dtset,pimd_param,me==master,force_imgmov=9)
     887              :      end if
     888              : 
     889              :      call precpred_1geo(ab_mover,ab_xfh,amu_curr,deloc,&
     890              : &     scfcv_args%dtset%chkdilatmx,&
     891              : &     scfcv_args%mpi_enreg%comm_cell,&
     892              : &     scfcv_args%dtset%dilatmx,dtfil%filnam_ds(4),&
     893              : &     hist,scfcv_args%dtset%hmctt,&
     894              : &     icycle,iexit,itime,mttk_vars,&
     895              : &     scfcv_args%dtset%nctime,ncycle,nerr_dilatmx,scfcv_args%dtset%npsp,ntime,&
     896        11496 : &     pimd_param,scfcv_args%dtset%rprimd_orig,skipcycle,scfcv_args%dtset%usewvl)
     897              : 
     898              : !    Write MOLDYN netcdf and POSABIN files (done every dtset%nctime time step)
     899              : !    This file is not created for multibinit run
     900        11496 :      if(need_scfcv_cycle .and. (ab_mover%ionmov/=23 .or. icycle==1))then
     901         1634 :        if (scfcv_args%dtset%nctime>0) then
     902           34 :          jj=itime; if(hist_prev%mxhist>0.and.ab_mover%restartxf==-1) jj=jj-hist_prev%mxhist
     903           34 :          if (jj>0) then
     904           32 :            option=3
     905           32 :            ihist_prev = abihist_findIndex(hist,-1)
     906              :            call wrt_moldyn_netcdf(ab_mover%amass,scfcv_args%dtset,jj,option,dtfil%fnameabo_moldyn,&
     907              : &           scfcv_args%mpi_enreg,scfcv_args%results_gs,&
     908              : &           hist%rprimd(:,:,ihist_prev),dtfil%unpos,hist%vel(:,:,hist%ihist),&
     909           32 : &           hist%xred(:,:,ihist_prev))
     910              :          end if
     911           34 :          if (iexit==1) hist%ihist=ihist_prev
     912              :        end if
     913              :      end if
     914        11496 :      if(iexit/=0) exit
     915              : 
     916              : !    ###########################################################
     917              : !    ### 18. Use the history  to extract the new values of acell, rprimd and xred
     918              : 
     919        11103 :      call hist2var(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
     920              :      ! /!\ ---- DO NOT CHANGE THESE LINES WITHOUT CORE DEVELOPERS PERMISSION ---- /!\
     921              :      ! LB-03/2026:
     922              :      ! A noise can accumulate in acell,rprimd and xred after each iterations,
     923              :      ! resulting in different results for different MPI processes.
     924              :      ! This has been observed using threads, but could happen in other contexts.
     925              :      ! This slowly worsens the ionic dynamics, leading to wrong results after many iterations.
     926              :      ! So here we compute the mean over all MPI processes to reduce the noise.
     927              :      ! This error is difficult to test as it is observed in long runs only, so BE VERY CAREFUL.
     928              :      ! Note : the cost of these MPI communications is negligible.
     929              :      ! comm = comm_cell
     930        11103 :      nmpi = xmpi_comm_size(comm)
     931        11103 :      if (nmpi>1) then
     932         4518 :        ABI_MALLOC(tmp,(size(xred,1),size(xred,2)))
     933       287690 :        tmp(:,:) = xred(:,:) / nmpi
     934         1506 :        call xmpi_sum(tmp,comm,ierr)
     935         1506 :        if (ierr/=0) then
     936            0 :          ABI_ERROR("Error in mpi sum (tmp)")
     937              :        end if
     938       287690 :        xred(:,:) = tmp(:,:)
     939         1506 :        ABI_FREE(tmp)
     940         1506 :        ABI_MALLOC(tmp,(size(rprimd,1),size(rprimd,2)))
     941        19578 :        tmp(:,:) = rprimd(:,:) / nmpi
     942         1506 :        call xmpi_sum(tmp,comm,ierr)
     943         1506 :        if (ierr/=0) then
     944            0 :          ABI_ERROR("Error in mpi sum (tmp)")
     945              :        end if
     946        19578 :        rprimd(:,:) = tmp(:,:)
     947         1506 :        ABI_FREE(tmp)
     948         1506 :        ABI_MALLOC(tmp_1d,(size(acell)))
     949         6024 :        tmp_1d(:) = acell(:) / nmpi
     950         1506 :        call xmpi_sum(tmp_1d,comm,ierr)
     951         1506 :        if (ierr/=0) then
     952            0 :          ABI_ERROR("Error in mpi sum (tmp)")
     953              :        end if
     954         6024 :        acell(:) = tmp_1d(:)
     955         6024 :        ABI_FREE(tmp_1d)
     956              :      end if
     957              :      ! /!\--------------------/!\
     958              : 
     959        11103 :      if (ab_mover%optcell/=0) then
     960              :        ! Cell may change
     961              : 
     962              : #ifdef FC_NVHPC
     963              :        ! Yet another wild NVHPC bug (only on eos_nvhpc_23.9_elpa)
     964              :        if(wrong) write(100,*) xred
     965              : #endif
     966         1295 :        call matr3inv(rprimd,gprimd)
     967              : 
     968              : !      If metric has changed since the initialization, update the Ylm's
     969         1295 :        if (scfcv_args%psps%useylm==1)then
     970          100 :          option=0
     971          100 :          if (scfcv_args%dtset%iscf>0) option=1
     972              :          call initylmg(gprimd,&
     973              : &         scfcv_args%kg,&
     974              : &         scfcv_args%dtset%kptns,&
     975              : &         scfcv_args%dtset%mkmem,&
     976              : &         scfcv_args%mpi_enreg,&
     977              : &         scfcv_args%psps%mpsang,&
     978              : &         scfcv_args%dtset%mpw,&
     979              : &         scfcv_args%dtset%nband,&
     980              : &         scfcv_args%dtset%nkpt,&
     981              : &         scfcv_args%npwarr,&
     982              : &         scfcv_args%dtset%nsppol,&
     983              : &         option,rprimd,&
     984              : &         scfcv_args%ylm,&
     985          100 : &         scfcv_args%ylmgr)
     986              :        end if
     987              : 
     988              :      end if
     989              : 
     990     35494135 :      vel(:,:)=hist%vel(:,:,hist%ihist)
     991              : 
     992              : !    vel_cell(3,3)= velocities of cell parameters
     993              : !    Not yet used here but compute it for consistency
     994       144339 :      vel_cell(:,:)=hist%vel_cell(:,:,hist%ihist)
     995        11103 :      if (ab_mover%ionmov==13 .and. hist%mxhist >= 2) then
     996         1026 :        if (itime_hist>2) then
     997          968 :          ihist_prev2 = abihist_findIndex(hist,-2)
     998        12584 :          vel_cell(:,:)=(hist%rprimd(:,:,hist%ihist)- hist%rprimd(:,:,ihist_prev2))/(two*ab_mover%dtion)
     999           58 :        else if (itime_hist>1) then
    1000           29 :          ihist_prev = abihist_findIndex(hist,-1)
    1001          377 :          vel_cell(:,:)=(hist%rprimd(:,:,hist%ihist)-hist%rprimd(:,:,ihist_prev))/(ab_mover%dtion)
    1002              :        end if
    1003              :      end if
    1004              : 
    1005              : !    This is needed for some compilers such as
    1006              : !    pathscale, g95, xlf that do not exit
    1007              : !    from a loop if you change the upper limit
    1008              : !    inside
    1009        11103 :       if (icycle>=ncycle .and. scfcv_args%mpi_enreg%me == 0) then
    1010         2255 :         if(need_verbose.and.need_verbose_cycle)write(std_out,*) 'EXIT:',icycle,ncycle
    1011              :         exit
    1012              :       end if
    1013              : 
    1014              : 
    1015         8848 :       if (need_verbose.and.need_verbose_cycle) then
    1016         1040 :         write(msg,*) 'ICYCLE',icycle,skipcycle
    1017         1040 :         call wrtout(std_out,msg)
    1018         1040 :         write(msg,*) 'NCYCLE',ncycle
    1019         1040 :        call wrtout(std_out,msg)
    1020              :      end if
    1021        10248 :      if (skipcycle) exit
    1022              : 
    1023              : !    ###########################################################
    1024              : !    ### 19. End loop icycle
    1025              : 
    1026              :    end do ! icycle
    1027              : 
    1028         3655 :    if(iexit/=0)exit
    1029              : 
    1030              : !  ###########################################################
    1031              : !  ### 20. End loop itime
    1032              : 
    1033              :  end do ! itime
    1034              : 
    1035              :  ! Call fconv here if we exited due to wall time limit.
    1036            0 :  if (timelimit_exit==1 .and. specs%isFconv) then
    1037            0 :    iexit = timelimit_exit
    1038            0 :    ntime = itime-1
    1039            0 :    ihist_prev = abihist_findIndex(hist,-1)
    1040            0 :    if ((ab_mover%ionmov/=4.and.ab_mover%ionmov/=5)) then
    1041            0 :      if (scfcv_args%dtset%tolmxf/=0)then
    1042              :        call fconv(hist%fcart(:,:,ihist_prev),&
    1043              : &       scfcv_args%dtset%iatfix, &
    1044              : &       iexit, itime,&
    1045              : &       ab_mover%natom,&
    1046              : &       ntime,&
    1047              : &       ab_mover%optcell,&
    1048              : &       scfcv_args%dtset%strfact,&
    1049              : &       scfcv_args%dtset%strtarget,&
    1050              : &       hist%strten(:,ihist_prev),&
    1051              : &       rprim,&
    1052            0 : &       scfcv_args%dtset%tolmxf)
    1053              :      else
    1054            0 :        call erlxconv(hist,iexit,itime,itime_hist,ntime,scfcv_args%dtset%tolmxde)
    1055              :      end if
    1056              :    end if
    1057              :  end if
    1058              : 
    1059              :  ! Avoid pending requests if itime == ntime.
    1060          393 :  call xmpi_wait(quitsum_request,ierr)
    1061              : 
    1062              : !###########################################################
    1063              : !### 21. Set the final values of xred with the last computed values (not the last predicted)
    1064              : 
    1065          393 :  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,DEBUG)
    1066        23845 :  vel(:,:)=hist%vel(:,:,hist%ihist)
    1067              : 
    1068          393 :  if (DEBUG .and. ab_mover%ionmov==1)then
    1069            0 :    write (std_out,*) 'vel'
    1070            0 :    do kk=1,ab_mover%natom
    1071            0 :      write (std_out,*) hist%vel(:,kk,hist%ihist)
    1072              :    end do
    1073              :  end if
    1074              : 
    1075              : !###########################################################
    1076              : !### 22. XML Output at the end
    1077              : 
    1078              : !XML output of the status
    1079          393 :  if (scfcv_args%mpi_enreg%me == 0 .and. scfcv_args%dtset%prtxml == 1) then
    1080            1 :    write(ab_xml_out, "(3a)") '    <geometryMinimisation type="',trim(specs%type4xml),'">'
    1081            1 :    write(ab_xml_out, "(5a)") '      <status cvState="',trim(stat4xml) ,'" stop-criterion="',trim(specs%crit4xml),'" />'
    1082            1 :    write(ab_xml_out, "(3a)") '    </geometryMinimisation>'
    1083              :  end if
    1084              : 
    1085              : !###########################################################
    1086              : !### 23. Deallocate hist and ab_mover datatypes
    1087              : 
    1088              : !This call is needed to free an internal matrix. However, this is not optimal ...
    1089              : !One should instead have a datastructure associated with the preconditioner.
    1090          393 :  if (ab_mover%goprecon>0) call prec_simple(ab_mover,preconforstr,hist,1,1,1)
    1091              : 
    1092          393 :  if (ab_mover%ionmov==13 .or. ab_mover%ionmov==25)then
    1093           31 :    call mttk_fin(mttk_vars)
    1094              :  end if
    1095              : 
    1096          393 :  if (ab_mover%ionmov==10 .or. ab_mover%ionmov==11) call delocint_fin(deloc)
    1097              : 
    1098          393 :  ABI_FREE(xred_prev)
    1099              : 
    1100          393 :  call abihist_free(hist)
    1101              : 
    1102          393 :  call abihist_free(hist_prev)
    1103          393 :  call abimover_destroy(ab_mover)
    1104          786 :  call abiforstr_fin(preconforstr)
    1105              : 
    1106              : contains
    1107              : !!***
    1108              : 
    1109              : !!****f* ABINIT/fconv
    1110              : !!
    1111              : !! NAME
    1112              : !! fconv
    1113              : !!
    1114              : !! FUNCTION
    1115              : !! Check maximal absolute value of force (hartree/bohr) against input tolerance; if below tolerance, return iexit=1.
    1116              : !! Takes into account the fact that the Broyden (or moldyn) step
    1117              : !! might be the last one (last itime), to print eventually modified message.
    1118              : !! Stresses are also included in the check, provided that optcell/=0.
    1119              : !!
    1120              : !! If optcell=1, takes only the trace into account
    1121              : !!    optcell=2, takes all components into account
    1122              : !!    optcell=3, takes traceless stress into account
    1123              : !!    optcell=4, takes sigma(1,1), sigma(2,1) and sigma(3,1) into account
    1124              : !!    optcell=5, takes sigma(1,2), sigma(2,2) and sigma(3,2) into account
    1125              : !!    optcell=6, takes sigma(1,3), sigma(2,3) and sigma(3,3) into account
    1126              : !!    optcell=7, takes sigma(2,2),(2,3) and (3 3) into account
    1127              : !!    optcell=8, takes sigma(1,1),(1,3) and (3 3) into account
    1128              : !!    optcell=9, takes sigma(1,1),(1,2) and (2 2) into account
    1129              : !! In the case of stresses, target the tensor strtarget, and take into account the factor strfact
    1130              : !!
    1131              : !! INPUTS
    1132              : !!  fcart(3,natom)= forces on atoms in hartree/bohr in cartesian coordinates
    1133              : !!  iatfix(3,natom)=1 for frozen atom, 0 for unfrozen
    1134              : !!  itime=current number of Broyden/Moldyn iterations
    1135              : !!  natom=number of atoms in unit cell
    1136              : !!  ntime=maximum number of Broyden/Moldyn iterations allowed
    1137              : !!  optcell=option for taking stresses into account (see above)
    1138              : !!  strfact=factor that multiplies the stresses when they are compared to forces.
    1139              : !!  strtarget(6)=components of the target stress tensor (hartree/bohr^3)
    1140              : !!  strten(6)=components of the stress tensor (hartree/bohr^3)
    1141              : !!  tolmxf=tolerance on maximal absolute value of components of forces
    1142              : !!
    1143              : !! OUTPUT
    1144              : !!  writes to unit std_out and to ab_out, and returns
    1145              : !!
    1146              : !! SIDE EFFECTS
    1147              : !! Input/Output
    1148              : !!  at input  : iexit=  0 if not the last itime,  1 if the last itime
    1149              : !!  at output : iexit=  0 if not below tolerance, 1 if below tolerance
    1150              : !!
    1151              : !! SOURCE
    1152              : 
    1153         1326 : subroutine fconv(fcart,iatfix,iexit,itime,natom,ntime,optcell,strfact,strtarget,strten,rprim,tolmxf)
    1154              : 
    1155              : !Arguments ------------------------------------
    1156              : !scalars
    1157              :  integer,intent(in) :: itime,natom,ntime,optcell
    1158              :  integer,intent(inout) :: iexit
    1159              :  real(dp),intent(in) :: strfact,tolmxf
    1160              : !arrays
    1161              :  integer,intent(in) :: iatfix(3,natom)
    1162              :  real(dp),intent(in) :: fcart(3,natom),strtarget(6),strten(6)
    1163              :  real(dp), intent(in) :: rprim(3,3)
    1164              : 
    1165              : !Local variables-------------------------------
    1166              : !scalars
    1167              :  integer :: iatom,idir,istr
    1168              :  real(dp) :: fmax,strdiag,fcell
    1169              :  character(len=500) :: msg
    1170              : !arrays
    1171              :  real(dp) :: dstr(6)
    1172              : 
    1173              : ! *************************************************************************
    1174              : 
    1175              : ABI_UNUSED(rprim)
    1176              : 
    1177              : !Compute maximal component of forces, EXCLUDING any fixed components
    1178         1326 :  fmax=zero
    1179         5158 :  do iatom=1,natom
    1180        16654 :    do idir=1,3
    1181        15328 :      if (iatfix(idir,iatom) /= 1) then
    1182        10470 :        if( abs(fcart(idir,iatom)) >= fmax ) fmax=abs(fcart(idir,iatom))
    1183              :      end if
    1184              :    end do
    1185              :  end do
    1186              : 
    1187         9282 :  dstr(:)=strten(:)-strtarget(:)
    1188              : 
    1189              : !Eventually take into account the stress
    1190         1326 :  if(optcell==1)then
    1191          226 :    strdiag=(dstr(1)+dstr(2)+dstr(3))/3.0_dp
    1192          226 :    if(abs(strdiag)*strfact >= fmax ) fmax=abs(strdiag)*strfact
    1193              :  else if(optcell==2)then
    1194          938 :    do istr=1,6
    1195          938 :      if(abs(dstr(istr))*strfact >= fmax ) fmax=abs(dstr(istr))*strfact
    1196              :    end do
    1197              :  else if(optcell==3)then
    1198              : !  Must take away the trace from diagonal elements
    1199           14 :    strdiag=(dstr(1)+dstr(2)+dstr(3))/3.0_dp
    1200           56 :    do istr=1,3
    1201           56 :      if(abs(dstr(istr)-strdiag)*strfact >= fmax ) fmax=abs(dstr(istr)-strdiag)*strfact
    1202              :    end do
    1203           56 :    do istr=4,6
    1204           56 :      if(abs(dstr(istr))*strfact >= fmax ) fmax=abs(dstr(istr))*strfact
    1205              :    end do
    1206              : !  else if(optcell==4 .or. optcell==5 .or. optcell==6)then
    1207              : !    if(abs(dstr(optcell-3))*strfact >= fmax ) fmax=abs(dstr(optcell-3))*strfact
    1208              :  else if(optcell==4) then
    1209              : !  Only the first lattice vector is relaxed. Check the three stress components
    1210              : !  conjugate to its generalized coordinates, consistently with xfpack_f2vout.
    1211           50 :    fcell = maxval(abs(dstr([1,5,6]))) * strfact
    1212           10 :    if (fcell >= fmax) fmax=fcell
    1213              :  else if(optcell==5) then
    1214              : !  Only the second lattice vector is relaxed.
    1215            0 :    fcell = maxval(abs(dstr([2,4,6]))) * strfact
    1216            0 :    if (fcell >= fmax) fmax=fcell
    1217              :  else if(optcell==6) then
    1218              : !  Only the third lattice vector is relaxed.
    1219           35 :    fcell = maxval(abs(dstr([3,4,5]))) * strfact
    1220            7 :    if (fcell >= fmax) fmax=fcell
    1221              :  else if(optcell==7)then
    1222           14 :    if(abs(dstr(2))*strfact >= fmax ) fmax=abs(dstr(2))*strfact
    1223           14 :    if(abs(dstr(3))*strfact >= fmax ) fmax=abs(dstr(3))*strfact
    1224           14 :    if(abs(dstr(4))*strfact >= fmax ) fmax=abs(dstr(4))*strfact
    1225              :  else if(optcell==8)then
    1226            0 :    if(abs(dstr(1))*strfact >= fmax ) fmax=abs(dstr(1))*strfact
    1227            0 :    if(abs(dstr(3))*strfact >= fmax ) fmax=abs(dstr(3))*strfact
    1228            0 :    if(abs(dstr(5))*strfact >= fmax ) fmax=abs(dstr(5))*strfact
    1229              :  else if(optcell==9)then
    1230            5 :    if(abs(dstr(1))*strfact >= fmax ) fmax=abs(dstr(1))*strfact
    1231            5 :    if(abs(dstr(2))*strfact >= fmax ) fmax=abs(dstr(2))*strfact
    1232            5 :    if(abs(dstr(6))*strfact >= fmax ) fmax=abs(dstr(6))*strfact
    1233              :  end if
    1234              : 
    1235         1326 :  if (fmax<tolmxf) then
    1236          220 :    write(msg, '(a,a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
    1237          220 :     ' At Broyd/MD step',itime,', gradients are converged : ',ch10,&
    1238          440 :     '  max grad (force/stress) =',fmax,' < tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
    1239          660 :    call wrtout([std_out, ab_out], msg)
    1240          220 :    iexit=1
    1241              :  else
    1242         1106 :    if(iexit==1)then
    1243           96 :      write(msg, '(a,a,a,a,i5,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
    1244           96 :       ' fconv : WARNING -',ch10,&
    1245           96 :       '  ntime=',ntime,' was not enough Broyd/MD steps to converge gradients: ',ch10,&
    1246          192 :       '  max grad (force/stress) =',fmax,' > tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
    1247          288 :      call wrtout([std_out, ab_out], msg)
    1248              : 
    1249           96 :      write(std_out,"(8a)")ch10,&
    1250           96 :        "--- !RelaxConvergenceWarning",ch10,&
    1251           96 :        "message: | ",ch10,TRIM(indent(msg)),ch10,&
    1252          192 :        "..."
    1253              : 
    1254              :    else
    1255              :      write(msg, '(a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) &
    1256         1010 :        ' fconv : at Broyd/MD step',itime,', gradients have not converged yet. ',ch10,&
    1257         2020 :       '  max grad (force/stress) =',fmax,' > tolmxf=',tolmxf,' ha/bohr (free atoms)',ch10
    1258         1010 :      call wrtout(std_out,msg,'COLL')
    1259              :    end if
    1260         1106 :    iexit=0
    1261              :  end if
    1262              : 
    1263         1326 : end subroutine fconv
    1264              : !!***
    1265              : 
    1266              : !!****f* ABINIT/erlxconv
    1267              : !! NAME
    1268              : !!  erlxconv
    1269              : !!
    1270              : !! FUNCTION
    1271              : !!  FIXME: add description.
    1272              : !!
    1273              : !! INPUTS
    1274              : !!
    1275              : !! OUTPUT
    1276              : !!
    1277              : !! SOURCE
    1278              : 
    1279            4 : subroutine erlxconv(hist,iexit,itime,itime_hist,ntime,tolmxde)
    1280              : 
    1281              : !Arguments ------------------------------------
    1282              : !scalars
    1283              :  integer,intent(in) :: itime,itime_hist,ntime
    1284              :  integer,intent(inout) :: iexit
    1285              :  real(dp), intent(in) :: tolmxde
    1286              : !arrays
    1287              :  type(abihist),intent(inout) :: hist
    1288              : 
    1289              : !Local variables-------------------------------
    1290              :  integer :: ihist,ihist_prev,ihist_prev2
    1291              :  real(dp) :: ediff1,ediff2,maxediff
    1292              :  character(len=500) :: msg
    1293              : ! *************************************************************************
    1294              : 
    1295            4 :  if (itime_hist<3) then
    1296            2 :    write(msg, '(a,a,a)' ) ch10,&
    1297            4 :    ' erlxconv : minimum 3 Broyd/MD steps to check convergence of energy in relaxations',ch10
    1298            2 :    call wrtout(std_out,msg,'COLL')
    1299              :  else
    1300            2 :    ihist = hist%ihist
    1301            2 :    ihist_prev  = abihist_findIndex(hist,-1)
    1302            2 :    ihist_prev2 = abihist_findIndex(hist,-2)
    1303            2 :    ediff1 = hist%etot(ihist) - hist%etot(ihist_prev)
    1304            2 :    ediff2 = hist%etot(ihist) - hist%etot(ihist_prev2)
    1305            2 :    if ((abs(ediff1)<tolmxde).and.(abs(ediff2)<tolmxde)) then
    1306            1 :      write(msg, '(a,a,i4,a,a,a,a,a,es11.4,a,a)' ) ch10,&
    1307            1 :      ' At Broyd/MD step',itime,', energy is converged : ',ch10,&
    1308            1 :      '  the difference in energy with respect to the two ',ch10,&
    1309            2 :      '  previous steps is < tolmxde=',tolmxde,' ha',ch10
    1310            3 :      call wrtout([std_out, ab_out], msg)
    1311            1 :      iexit=1
    1312              :    else
    1313            1 :      maxediff = max(abs(ediff1),abs(ediff2))
    1314            1 :      if(iexit==1)then
    1315            0 :        write(msg, '(a,a,a,a,i5,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
    1316            0 :        ' erlxconv : WARNING -',ch10,&
    1317            0 :        '  ntime=',ntime,' was not enough Broyd/MD steps to converge energy: ',ch10,&
    1318            0 :        '  max difference in energy =',maxediff,' > tolmxde=',tolmxde,' ha',ch10
    1319            0 :        call wrtout([std_out, ab_out], msg)
    1320              : 
    1321            0 :        write(std_out,"(8a)")ch10,&
    1322            0 :        "--- !RelaxConvergenceWarning",ch10,&
    1323            0 :        "message: | ",ch10,TRIM(indent(msg)),ch10,&
    1324            0 :        "..."
    1325              :      else
    1326            1 :        write(msg, '(a,a,i4,a,a,a,es11.4,a,es11.4,a,a)' ) ch10,&
    1327            1 :        ' erlxconv : at Broyd/MD step',itime,', energy has not converged yet. ',ch10,&
    1328            2 :        '  max difference in energy=',maxediff,' > tolmxde=',tolmxde,' ha',ch10
    1329            1 :        call wrtout(std_out,msg,'COLL')
    1330              :      end if
    1331              :    end if
    1332              :  end if
    1333              : 
    1334            4 : end subroutine erlxconv
    1335              : !!***
    1336              : 
    1337              : end subroutine mover
    1338              : !!***
    1339              : 
    1340              : !!****f* ABINIT/prtxfase
    1341              : !!
    1342              : !! NAME
    1343              : !! prtxfase
    1344              : !!
    1345              : !! FUNCTION
    1346              : !! Print the values of xcart (X), forces (F) acell (A), Stresses (S), and energy (E)
    1347              : !! All values come from the history hist
    1348              : !! Also compute and print max and rms forces.
    1349              : !! Also compute absolute and relative differences with previous calculation
    1350              : !!
    1351              : !! INPUTS
    1352              : !! ab_mover<type abimover>=Subset of dtset only related with movement of ions and acell, contains:
    1353              : !!          | dtion:  Time step
    1354              : !!          ! natom:  Number of atoms
    1355              : !!          | vis:    viscosity
    1356              : !!          | iatfix: Index of atoms and directions fixed
    1357              : !!          | amass:  Mass of ions
    1358              : !! hist<type abihist>=Historical record of positions, forces, stresses, cell and energies,
    1359              : !! itime= time step
    1360              : !! iout=unit number for printing
    1361              : !!
    1362              : !! OUTPUT
    1363              : !!  (only writing)
    1364              : !!
    1365              : !! SOURCE
    1366              : 
    1367         4882 : subroutine prtxfase(ab_mover,hist,itime,iout,pos)
    1368              : 
    1369              : !Arguments ------------------------------------
    1370              : !scalars
    1371              :  type(abimover),intent(in) :: ab_mover
    1372              :  type(abihist),intent(in),target :: hist
    1373              :  integer,intent(in) :: itime,iout
    1374              :  integer,intent(in) :: pos
    1375              : !arrays
    1376              : 
    1377              : !Local variables-------------------------------
    1378              : !scalars
    1379              :  integer :: jj,kk,unfixd,iprt
    1380              :  real(dp) :: val_max,val_rms,ucvol ! Values maximal and RMS, Volume of Unitary cell
    1381              :  real(dp) :: dEabs,dErel ! Diff of energy absolute and relative
    1382              :  real(dp) :: ekin
    1383              :  real(dp) :: angle(3),rmet(3,3)
    1384              : !character(len=80*(max(ab_mover%natom,3)+1)) :: msg
    1385              : !MGNAG: This is not very safe. One should use line-based output istead of appending chars
    1386              : ! and then outputting everything! For the time being I use this temporary hack to solve the problem with NAG
    1387         4882 :  character(len=max(80*(max(ab_mover%natom,3)+1),50000)) :: msg
    1388              :  character(len=18)   :: fmt1
    1389              :  logical :: prtallatoms
    1390              : !arrays
    1391         9764 :  logical :: atlist(ab_mover%natom)
    1392         4882 :  real(dp),allocatable :: gred(:,:),xcart(:,:)
    1393         4882 :  real(dp),pointer :: acell(:),fcart(:,:),rprimd(:,:),strten(:),vel(:,:),xred(:,:)
    1394              : 
    1395              : ! ***********************************************************
    1396              : 
    1397         4882 :  fmt1='(a,a,1p,3e22.14)'
    1398              : 
    1399              : !##########################################################
    1400              : !### 1. Organize list of atoms to print
    1401              : 
    1402         4882 :  prtallatoms=.TRUE.
    1403        29185 :  do kk=1,ab_mover%natom
    1404        29185 :    if (ab_mover%prtatlist(kk)/=kk) prtallatoms=.FALSE.
    1405              :  end do
    1406              : 
    1407        29185 :  atlist(:)=.FALSE.
    1408        29185 :  do iprt=1,ab_mover%natom
    1409        29185 :    if (ab_mover%prtatlist(iprt)>0.and.ab_mover%prtatlist(iprt)<=ab_mover%natom) atlist(ab_mover%prtatlist(iprt))=.TRUE.
    1410              :  end do
    1411              : 
    1412         4882 :  acell  => hist%acell(:,hist%ihist)
    1413         4882 :  rprimd => hist%rprimd(:,:,hist%ihist)
    1414         4882 :  xred   => hist%xred(:,:,hist%ihist)
    1415         4882 :  fcart  => hist%fcart(:,:,hist%ihist)
    1416         4882 :  strten => hist%strten(:,hist%ihist)
    1417         4882 :  vel    => hist%vel(:,:,hist%ihist)
    1418              : 
    1419              : !###########################################################
    1420              : !### 1. Positions
    1421              : 
    1422        14646 :  ABI_MALLOC(xcart,(3,ab_mover%natom))
    1423         4882 :  call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
    1424              : 
    1425         4882 :  write(msg, '(a,a)' )ch10,' Cartesian coordinates (xcart) [bohr]'
    1426         4882 :  call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,xcart)
    1427              : 
    1428         4882 :  write(msg, '(a)' )' Reduced coordinates (xred)'
    1429         4882 :  call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,xred)
    1430              : 
    1431         4882 :  ABI_FREE(xcart)
    1432              : 
    1433              : !###########################################################
    1434              : !### 2. Forces
    1435              : 
    1436         4882 :  if(pos==mover_AFTER)then
    1437              : 
    1438         9744 :    ABI_MALLOC(gred,(3,ab_mover%natom))
    1439         3248 :    call fcart2gred(fcart,gred,rprimd,ab_mover%natom)
    1440              : 
    1441              : !  Compute max |f| and rms f,
    1442              : !  EXCLUDING the components determined by iatfix
    1443         3248 :    val_max=0.0_dp
    1444         3248 :    val_rms=0.0_dp
    1445         3248 :    unfixd=0
    1446        19410 :    do kk=1,ab_mover%natom
    1447        67896 :      do jj=1,3
    1448        64648 :        if (ab_mover%iatfix(jj,kk) /= 1) then
    1449        45690 :          unfixd=unfixd+1
    1450        45690 :          val_rms=val_rms+fcart(jj,kk)**2
    1451        45690 :          val_max=max(val_max,abs(fcart(jj,kk)**2))
    1452              :        end if
    1453              :      end do
    1454              :    end do
    1455         3248 :    if ( unfixd /= 0 ) val_rms=sqrt(val_rms/dble(unfixd))
    1456              : 
    1457         3248 :    write(msg, '(a,1p,2e12.5,a)' ) ' Cartesian forces (fcart) [Ha/bohr]; max,rms=',sqrt(val_max),val_rms,' (free atoms)'
    1458         3248 :    call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,fcart)
    1459              : 
    1460         3248 :    write(msg, '(a)' )' Gradient of E wrt nuclear positions in reduced coordinates (gred)'
    1461         3248 :    call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,gred)
    1462         3248 :    ABI_FREE(gred)
    1463              :  end if
    1464              : 
    1465              : !###########################################################
    1466              : !### 3. Velocities
    1467              : 
    1468              : !Only if the velocities are being used
    1469         4882 :  if (hist%isVused)then
    1470              : !  Only if velocities are recorded in a history
    1471         1219 :    if (allocated(hist%vel))then
    1472              : !    Compute max |v| and rms v,
    1473              : !    EXCLUDING the components determined by iatfix
    1474         1219 :      val_max=0.0_dp
    1475         1219 :      val_rms=0.0_dp
    1476         1219 :      unfixd=0
    1477        17038 :      do kk=1,ab_mover%natom
    1478        64495 :        do jj=1,3
    1479        63276 :          if (ab_mover%iatfix(jj,kk) /= 1) then
    1480        45864 :            unfixd=unfixd+1
    1481        45864 :            val_rms=val_rms+vel(jj,kk)**2
    1482        45864 :            val_max=max(val_max,abs(vel(jj,kk)**2))
    1483              :          end if
    1484              :        end do
    1485              :      end do
    1486         1219 :      if ( unfixd /= 0 ) val_rms=sqrt(val_rms/dble(unfixd))
    1487              : 
    1488              :      write(msg, '(a,1p,2e12.5,a)' ) &
    1489         1219 : &     ' Cartesian velocities (vel) [bohr*Ha/hbar]; max,rms=',sqrt(val_max),val_rms,' (free atoms)'
    1490         1219 :      call prtnatom(atlist,iout,msg,ab_mover%natom,prtallatoms,vel)
    1491              : 
    1492              : !    Compute the ionic kinetic energy (no cell shape kinetic energy yet)
    1493         1219 :      ekin=0.0_dp
    1494        17038 :      do kk=1,ab_mover%natom
    1495        64495 :        do jj=1,3
    1496              : !        Warning : the fixing of atoms is implemented in reduced
    1497              : !        coordinates, so that this expression is wrong
    1498        63276 :          if (ab_mover%iatfix(jj,kk) == 0) then
    1499        45864 :            ekin=ekin+0.5_dp*ab_mover%amass(kk)*vel(jj,kk)**2
    1500              :          end if
    1501              :        end do
    1502              :      end do
    1503         1219 :      write(msg, '(a,1p,e22.14,a)' )' Kinetic energy of ions (ekin) [Ha]=',ekin
    1504         1219 :      call wrtout(iout,msg,'COLL')
    1505              :    end if
    1506              :  end if
    1507              : 
    1508              : !###########################################################
    1509              : !### 3. ACELL
    1510              : 
    1511              : !Only if the acell is being used
    1512         4882 :  if (hist%isARused)then
    1513              : !  Only if acell is recorded in a history
    1514         1286 :    if (allocated(hist%acell))then
    1515         1286 :      write(msg, '(a)' )' Scale of Primitive Cell (acell) [bohr]'
    1516         1286 :      write(msg,fmt1)TRIM(msg),ch10,acell(:)
    1517         1286 :      call wrtout(iout,msg,'COLL')
    1518              :    end if
    1519              :  end if
    1520              : 
    1521              : !###########################################################
    1522              : !### 4. RPRIMD
    1523              : 
    1524              : !Only if the acell is being used
    1525         4882 :  if (hist%isARused)then
    1526              : !  Only if rprimd is recorded in a history
    1527         1286 :    if (allocated(hist%rprimd))then
    1528         1286 :      write(msg, '(a)' )' Real space primitive translations (rprimd) [bohr]'
    1529         5144 :      do kk=1,3
    1530         5144 :        write(msg,fmt1)TRIM(msg),ch10,rprimd(:,kk)
    1531              :      end do
    1532         1286 :      call wrtout(iout,msg,'COLL')
    1533              :    end if
    1534              :  end if
    1535              : 
    1536              : !###########################################################
    1537              : !### 5. Unitary cell volume
    1538              : 
    1539         4882 :  if (ab_mover%optcell/=0)then
    1540              : 
    1541              :    ucvol=&
    1542              : &   rprimd(1,1)*(rprimd(2,2)*rprimd(3,3)-rprimd(3,2)*rprimd(2,3))+&
    1543              : &   rprimd(2,1)*(rprimd(3,2)*rprimd(1,3)-rprimd(1,2)*rprimd(3,3))+&
    1544         1223 : &   rprimd(3,1)*(rprimd(1,2)*rprimd(2,3)-rprimd(2,2)*rprimd(1,3))
    1545              : 
    1546         1223 :    write(msg, '(a,1p,e22.14)' )' Unitary Cell Volume (ucvol) [Bohr^3]=',ucvol
    1547         1223 :    call wrtout(iout,msg,'COLL')
    1548              : 
    1549              : !  ###########################################################
    1550              : !  ### 5. Angles and lengths
    1551              : 
    1552              : !  Compute real space metric.
    1553        81941 :    rmet = MATMUL(TRANSPOSE(rprimd),rprimd)
    1554              : 
    1555         1223 :    angle(1)=acos(rmet(2,3)/sqrt(rmet(2,2)*rmet(3,3)))/two_pi*360.0d0
    1556         1223 :    angle(2)=acos(rmet(1,3)/sqrt(rmet(1,1)*rmet(3,3)))/two_pi*360.0d0
    1557         1223 :    angle(3)=acos(rmet(1,2)/sqrt(rmet(1,1)*rmet(2,2)))/two_pi*360.0d0
    1558              : 
    1559         1223 :    write(msg, '(a)' )' Angles (23,13,12)= [degrees]'
    1560         1223 :    write(msg,fmt1)TRIM(msg),ch10,angle(:)
    1561         1223 :    call wrtout(iout,msg,'COLL')
    1562              : 
    1563         1223 :    write(msg, '(a)' ) ' Lengths [Bohr]'
    1564         1223 :    write(msg,fmt1)TRIM(msg),ch10,sqrt(rmet(1,1)),sqrt(rmet(2,2)),sqrt(rmet(3,3))
    1565         1223 :    call wrtout(iout,msg,'COLL')
    1566              : 
    1567              : !  ###########################################################
    1568              : !  ### 5. Stress Tensor
    1569              : 
    1570         1223 :    if(pos==mover_AFTER)then
    1571              : !    Only if strten is recorded in a history
    1572          812 :      if (allocated(hist%strten))then
    1573              : 
    1574          812 :        write(msg, '(a)' ) ' Stress tensor in cartesian coordinates (strten) [Ha/bohr^3]'
    1575              : 
    1576          812 :        write(msg,fmt1)TRIM(msg),ch10,strten(1),strten(6),strten(5)
    1577          812 :        write(msg,fmt1)TRIM(msg),ch10,strten(6),strten(2),strten(4)
    1578          812 :        write(msg,fmt1)TRIM(msg),ch10,strten(5),strten(4),strten(3)
    1579          812 :        call wrtout(iout,msg,'COLL')
    1580              :      end if
    1581              :    end if
    1582              :  end if
    1583              : 
    1584              : !###########################################################
    1585              : !### 6. Energy
    1586              : 
    1587         9764 :  if(pos==mover_AFTER)then
    1588         3248 :    write(msg, '(a,1p,e22.14)' )' Total energy (etotal) [Ha]=',hist%etot(hist%ihist)
    1589              : 
    1590         3248 :    if (itime>1)then
    1591         2554 :      jj = abihist_findIndex(hist,-1)
    1592         2554 :      dEabs=hist%etot(hist%ihist)-hist%etot(jj)
    1593         2554 :      dErel=2*dEabs/(abs(hist%etot(hist%ihist))+abs(hist%etot(jj)))
    1594         2554 :      write(msg, '(a,a,a,a)' )TRIM(msg),ch10,ch10,' Difference of energy with previous step (new-old):'
    1595              :      write(msg, '(a,a,10a,a,1p,e12.5,a,10a,a,1p,e12.5)')&
    1596         2554 :       TRIM(msg),ch10,&
    1597        30648 :       (' ',jj=1,10),' Absolute (Ha)=',dEabs,ch10,&
    1598        58742 :       (' ',jj=1,10),' Relative     =',dErel
    1599              :    end if
    1600         3248 :    call wrtout(iout,msg,'COLL')
    1601              :  end if
    1602              : 
    1603              :  contains
    1604              : !!***
    1605              : 
    1606              : !!****f* ABINIT/gettag
    1607              : !!
    1608              : !! NAME
    1609              : !! gettag
    1610              : !!
    1611              : !! FUNCTION
    1612              : !! Set the tag associated to each atom,
    1613              : !!
    1614              : !! INPUTS
    1615              : !! prtallatoms = Logical for PRTint ALL ATOMS
    1616              : !! atlist      = ATom LIST
    1617              : !! index       = index for each atom
    1618              : !! natom       = Number of ATOMs
    1619              : !!
    1620              : !! OUTPUT
    1621              : !!  tag = The string to put for each atom
    1622              : !!
    1623              : !! SOURCE
    1624              : 
    1625        86999 : subroutine gettag(atlist,index,natom,prtallatoms,tag)
    1626              : 
    1627              : !Arguments ------------------------------------
    1628              : !scalars
    1629              :   logical,intent(in) :: prtallatoms
    1630              :   integer,intent(in) :: natom
    1631              :   logical,intent(in) :: atlist(natom)
    1632              :   integer,intent(in) :: index
    1633              :   character(len=7),intent(out)   :: tag
    1634              : 
    1635              : ! *********************************************************************
    1636              : !The numbering will be from (1) to (9999)
    1637              : 
    1638        86999 :  if (prtallatoms)then
    1639        84269 :    tag=''
    1640         2730 :  elseif (atlist(index)) then
    1641         2730 :    if (natom<10) then
    1642            0 :      write(tag, '(a,I1.1,a)') ' (',index,')'
    1643         2730 :    elseif (natom<100) then
    1644         2730 :      write(tag, '(a,I2.2,a)') ' (',index,')'
    1645            0 :    elseif (natom<1000) then
    1646            0 :      write(tag, '(a,I3.3,a)') ' (',index,')'
    1647            0 :    elseif (natom<10000) then
    1648            0 :      write(tag, '(a,I4.4,a)') ' (',index,')'
    1649              :    end if
    1650              :  end if
    1651              : 
    1652        86999 :  end subroutine gettag
    1653              : !!***
    1654              : 
    1655              : !!****f* ABINIT/prtnatom
    1656              : !!
    1657              : !! NAME
    1658              : !! prtnatom
    1659              : !!
    1660              : !! FUNCTION
    1661              : !! Print information for N atoms
    1662              : !!
    1663              : !! INPUTS
    1664              : !! prtallatoms = Logical for PRTint ALL ATOMS
    1665              : !! atlist      = ATom LIST
    1666              : !! index       = index for each atom
    1667              : !! natom       = Number of ATOMs
    1668              : !!
    1669              : !! OUTPUT
    1670              : !!  tag = The string to put for aech atom
    1671              : !!
    1672              : !! SOURCE
    1673              : 
    1674              : 
    1675        17479 : subroutine prtnatom(atlist,iout,message,natom,prtallatoms,thearray)
    1676              : 
    1677              : !Arguments ------------------------------------
    1678              : !scalars
    1679              :   logical,intent(in) :: prtallatoms
    1680              :   integer,intent(in) :: natom
    1681              :   logical,intent(in) :: atlist(natom)
    1682              :   integer,intent(in) :: iout
    1683              :   character(len=*),intent(inout) :: message
    1684              : !arrays
    1685              :   real(dp) :: thearray(3,natom)
    1686              : 
    1687              : !Local variables-------------------------------
    1688              : !scalars
    1689              :   integer :: kk
    1690              :   character(len=7)   :: tag ! Maximal ' (9999)'
    1691              :   character(len=18)   :: fmt
    1692              : 
    1693              : ! *********************************************************************
    1694              : 
    1695        17479 :  fmt='(a,a,1p,3e22.14,a)'
    1696              : 
    1697       114228 :  do kk=1,natom
    1698       114228 :    if (atlist(kk)) then
    1699        86999 :      call gettag(atlist,kk,natom,prtallatoms,tag)
    1700        86999 :      write(message,fmt)TRIM(message),ch10,thearray(:,kk),tag
    1701              :    end if
    1702              :  end do
    1703        17479 :  call wrtout(iout,message,'COLL')
    1704              : 
    1705        17479 :  end subroutine prtnatom
    1706              : !!***
    1707              : 
    1708              : end subroutine prtxfase
    1709              : !!***
    1710              : 
    1711              : !!****f* ABINIT/wrt_moldyn_netcdf
    1712              : !! NAME
    1713              : !! wrt_moldyn_netcdf
    1714              : !!
    1715              : !! FUNCTION
    1716              : !! Write two files for later molecular dynamics analysis:
    1717              : !!  - MOLDYN.nc (netcdf format) : evolution of key quantities with time (pressure, energy, ...)
    1718              : !!  - POSABIN : values of coordinates and velocities for the next time step
    1719              : !!
    1720              : !! INPUTS
    1721              : !!  amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
    1722              : !!  dtset <type(dataset_type)>=all input variables for this dataset
    1723              : !!  itime=time step index
    1724              : !!  option=1: write MOLDYN.nc file (netcdf format)
    1725              : !!         2: write POSABIN file
    1726              : !!         3: write both
    1727              : !!  moldyn_file=name of the MD netcdf file
    1728              : !!  mpi_enreg=information about MPI parallelization
    1729              : !!  results_gs <type(results_gs_type)>=results (energy and its components,
    1730              : !!   forces and its components, the stress tensor) of a ground-state computation
    1731              : !!  rprimd(3,3)=real space primitive translations
    1732              : !!  unpos=unit number for POSABIN file
    1733              : !!  vel(3,natom)=velocities of atoms
    1734              : !!  xred(3,natom)=reduced coordinates of atoms
    1735              : !!
    1736              : !! OUTPUT
    1737              : !!  -- only printing --
    1738              : !!
    1739              : !! SIDE EFFECTS
    1740              : !!
    1741              : !! SOURCE
    1742              : 
    1743           32 : subroutine wrt_moldyn_netcdf(amass,dtset,itime,option,moldyn_file,mpi_enreg,&
    1744           32 : &                            results_gs,rprimd,unpos,vel,xred)
    1745              : 
    1746              :  use defs_basis
    1747              :  use defs_abitypes
    1748              :  use m_results_gs
    1749              :  use m_abicore
    1750              :  use m_errors
    1751              :  use netcdf
    1752              : 
    1753              :  use m_io_tools,   only : open_file, get_unit
    1754              :  use m_geometry,   only : xcart2xred, xred2xcart, metric
    1755              : 
    1756              : !Arguments ------------------------------------
    1757              : !scalars
    1758              :  integer,intent(in) :: itime,option,unpos
    1759              :  character(fnlen),intent(in) :: moldyn_file
    1760              :  type(dataset_type),intent(in) :: dtset
    1761              :  type(MPI_type),intent(in) :: mpi_enreg
    1762              :  type(results_gs_type),intent(in) :: results_gs
    1763              : !arrays
    1764              :  real(dp),intent(in) :: amass(dtset%natom),rprimd(3,3)
    1765              :  real(dp),intent(in),target :: vel(3,dtset%natom)
    1766              :  real(dp),intent(in) :: xred(3,dtset%natom)
    1767              : 
    1768              : !Local variables-------------------------------
    1769              : !scalars
    1770              :  integer,save :: ipos=0
    1771              :  integer :: iatom,ii
    1772              :  character(len=500) :: msg
    1773              :  integer :: AtomNumDimid,AtomNumId,CelId,CellVolumeId,DimCoordid,DimScalarid,DimVectorid
    1774              :  integer :: EkinDimid,EkinId,EpotDimid,EpotId,EntropyDimid,EntropyId,MassDimid,MassId,NbAtomsid
    1775              :  integer :: ncerr,ncid,PosId,StressDimid,StressId,TensorSymDimid
    1776              :  integer :: TimeDimid,TimestepDimid,TimestepId
    1777              :  logical :: atom_fix
    1778              :  real(dp) :: ekin,ucvol
    1779              :  character(len=fnlen) :: ficname
    1780              :  character(len=16) :: chain
    1781              : !arrays
    1782              :  integer :: PrimVectId(3)
    1783              :  real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
    1784           32 :  real(dp),allocatable ::  xcart(:,:)
    1785           32 :  real(dp),pointer :: vcart(:,:),vred(:,:),vtmp(:,:)
    1786              : ! *************************************************************************
    1787              : 
    1788              : !Only done by master processor, every nctime step
    1789           26 :  if (mpi_enreg%me==0.and.dtset%nctime>0) then
    1790              : 
    1791              : !  Netcdf file name
    1792           26 :    ficname = trim(moldyn_file)//'.nc'
    1793              : 
    1794              : !  Xcart from Xred
    1795           78 :    ABI_MALLOC(xcart,(3,dtset%natom))
    1796           26 :    call xred2xcart(dtset%natom,rprimd,xcart,xred)
    1797              : 
    1798              : !  ==========================================================================
    1799              : !  First time step: write header of netcdf file
    1800              : !  ==========================================================================
    1801           26 :    if (itime==1.and.(option==1.or.option==3)) then
    1802              : 
    1803            5 :      ipos=0
    1804              : 
    1805              : !    Write message
    1806            5 :      write(msg,'(4a)')ch10,' Open file ',trim(ficname),' to store molecular dynamics information.'
    1807            5 :      call wrtout(std_out,msg,'COLL')
    1808              : 
    1809              : !    Create netcdf file
    1810            5 :      ncerr = nf90_create(ficname, NF90_CLOBBER , ncid)
    1811            5 :      NCF_CHECK_MSG(ncerr,'nf90_create')
    1812              : 
    1813              : !    Dimension time for netcdf (time dim is unlimited)
    1814            5 :      ncerr = nf90_def_dim(ncid, "time", nf90_unlimited, TimeDimid)
    1815            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1816              : 
    1817              : !    Symetric Tensor Dimension
    1818            5 :      ncerr = nf90_def_dim(ncid, "DimTensor", size(results_gs%strten), TensorSymDimid)
    1819            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1820              : 
    1821              : !    Coordinates Dimension
    1822            5 :      ncerr = nf90_def_dim(ncid, "DimCoord", size(xcart,1), DimCoordid)
    1823            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1824              : 
    1825              : !    Atoms Dimensions
    1826            5 :      ncerr = nf90_def_dim(ncid, "NbAtoms", dtset%natom, NbAtomsid)
    1827            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1828              : 
    1829              : !    Vector Dimension
    1830            5 :      ncerr = nf90_def_dim(ncid, "DimVector", 3 , DimVectorid)
    1831            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1832              : 
    1833              : !    Scalar Dimension
    1834            5 :      ncerr = nf90_def_dim(ncid, "DimScalar", 1 , DimScalarid)
    1835            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_dim')
    1836              : 
    1837              : !    Time step and time unit
    1838            5 :      ncerr = nf90_def_var(ncid, "Time_step", nf90_double , DimScalarid, TimestepDimid)
    1839            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1840            5 :      ncerr = nf90_put_att(ncid, TimestepDimid, "units", "atomic time unit")
    1841            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1842              : 
    1843              : !    Ionic masses
    1844            5 :      ncerr = nf90_def_var(ncid, "Ionic_Mass", nf90_double , NbAtomsid, MassDimid)
    1845            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1846            5 :      ncerr = nf90_put_att(ncid, MassDimid, "units", "atomic mass unit")
    1847            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1848              : 
    1849              : !    Ionic atomic numbers
    1850            5 :      ncerr = nf90_def_var(ncid, "Ionic_Atomic_Number", nf90_double , NbAtomsid, AtomNumDimid)
    1851            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1852              : 
    1853              : !    E_pot
    1854            5 :      ncerr = nf90_def_var(ncid, "E_pot", nf90_double , TimeDimid, EpotDimid)
    1855            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1856            5 :      ncerr = nf90_put_att(ncid, EpotDimid, "units", "hartree")
    1857            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1858              : 
    1859              : !    E_kin
    1860            5 :      ncerr = nf90_def_var(ncid, "E_kin", nf90_double , TimeDimid, EkinDimid)
    1861            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1862            5 :      ncerr = nf90_put_att(ncid, EkinDimid, "units", "hartree")
    1863            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1864              : 
    1865              : !    Entropy
    1866            5 :      ncerr = nf90_def_var(ncid, "Entropy", nf90_double , TimeDimid, EntropyDimid)
    1867            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1868            5 :      ncerr = nf90_put_att(ncid, EntropyDimid, "units", "")
    1869            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1870              : 
    1871              : !    Stress tensor
    1872           15 :      ncerr = nf90_def_var(ncid, "Stress", nf90_double , (/TensorSymDimid,TimeDimid/), StressDimid)
    1873            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1874            5 :      ncerr = nf90_put_att(ncid, StressDimid, "units", "hartree/bohr^3")
    1875            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1876              : 
    1877              : !    Positions
    1878           20 :      ncerr = nf90_def_var(ncid, "Position", nf90_double ,(/DimCoordid,NbAtomsid,TimeDimid/), PosId)
    1879            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1880            5 :      ncerr = nf90_put_att(ncid, PosId, "units", "bohr")
    1881            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1882              : 
    1883              : !    Celerities
    1884           20 :      ncerr = nf90_def_var(ncid, "Celerity", nf90_double ,(/DimCoordid,NbAtomsid,TimeDimid/), CelId)
    1885            5 :      NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1886            5 :      ncerr = nf90_put_att(ncid, CelId, "units", "bohr/(atomic time unit)")
    1887            5 :      NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1888              : 
    1889              : !    In case of volume cell constant
    1890            5 :      if (dtset%optcell==0) then
    1891              : !      Primitive vectors
    1892           20 :        do ii = 1,3
    1893           15 :          write(unit=chain,fmt='(a15,i1)') "PrimitiveVector",ii
    1894           15 :          ncerr = nf90_def_var(ncid, trim(chain), nf90_double , DimVectorid, PrimVectId(ii))
    1895           20 :          NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1896              :        end do
    1897              : !      Cell Volume
    1898            5 :        ncerr = nf90_def_var(ncid, "Cell_Volume", nf90_double , DimScalarid, CellVolumeId)
    1899            5 :        NCF_CHECK_MSG(ncerr,'nf90_def_var')
    1900            5 :        ncerr = nf90_put_att(ncid, CellVolumeId, "units", "bohr^3")
    1901            5 :        NCF_CHECK_MSG(ncerr,'nf90_put_att')
    1902              :      end if
    1903              : 
    1904              : !    Leave define mode and close file
    1905            5 :      ncerr = nf90_enddef(ncid)
    1906            5 :      NCF_CHECK_MSG(ncerr,'nf90_enddef')
    1907            5 :      ncerr = nf90_close(ncid)
    1908            5 :      NCF_CHECK_MSG(ncerr,'nf90_close')
    1909              :    end if
    1910              : 
    1911              : !  ==========================================================================
    1912              : !  Write data to netcdf file (every nctime time step)
    1913              : !  ==========================================================================
    1914           26 :    if (mod(itime, dtset%nctime)==0.and.(option==1.or.option==3)) then
    1915              : 
    1916           10 :      ipos=ipos+1
    1917              : 
    1918              : !    Write message
    1919           10 :      write(msg,'(3a)')ch10,' Store molecular dynamics information in file ',trim(ficname)
    1920           10 :      call wrtout(std_out,msg,'COLL')
    1921              : 
    1922              : !    Open netcdf file
    1923           10 :      ncerr = nf90_open(ficname, nf90_write, ncid)
    1924           10 :      NCF_CHECK_MSG(ncerr,'nf90_open')
    1925              : 
    1926              : !    Time step
    1927           10 :      ncerr = nf90_inq_varid(ncid, "Time_step", TimestepId)
    1928           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1929           10 :      ncerr = nf90_put_var(ncid, TimestepId, dtset%dtion)
    1930           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1931              : 
    1932              : !    Ionic masses
    1933           10 :      ncerr = nf90_inq_varid(ncid, "Ionic_Mass", MassId)
    1934           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1935           20 :      ncerr = nf90_put_var(ncid, MassId, amass, start = (/ 1 /), count=(/dtset%natom/))
    1936           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1937              : 
    1938              : !    Ionic atomic numbers
    1939           10 :      ncerr = nf90_inq_varid(ncid, "Ionic_Atomic_Number", AtomNumId)
    1940           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1941          100 :      ncerr = nf90_put_var(ncid, AtomNumId, dtset%znucl(dtset%typat(:)),start=(/1/),count=(/dtset%natom/))
    1942           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1943              : 
    1944              : !    Epot
    1945           10 :      ncerr = nf90_inq_varid(ncid, "E_pot", EpotId)
    1946           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1947           30 :      ncerr = nf90_put_var(ncid, EpotId, (/results_gs%etotal/), start=(/ipos/),count=(/1/))
    1948           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1949              : 
    1950              : !    Ekin
    1951          170 :      ekin=zero;atom_fix=(maxval(dtset%iatfix)>0)
    1952           10 :      if (dtset%ionmov==1.or.(.not.atom_fix)) then
    1953           10 :        vcart => vel
    1954              :      else
    1955            0 :        ABI_MALLOC(vcart,(3,dtset%natom))
    1956            0 :        ABI_MALLOC(vred,(3,dtset%natom))
    1957            0 :        vtmp => vel
    1958            0 :        call xcart2xred(dtset%natom,rprimd,vtmp,vred)
    1959            0 :        do iatom=1,dtset%natom
    1960            0 :          do ii=1,3
    1961            0 :            if (dtset%iatfix(ii,iatom)==1) vred(ii,iatom)=zero
    1962              :          end do
    1963              :        end do
    1964            0 :        call xred2xcart(dtset%natom,rprimd,vcart,vred)
    1965            0 :        ABI_FREE(vred)
    1966              :      end if
    1967           50 :      do iatom=1,dtset%natom
    1968          170 :        do ii=1,3
    1969          160 :          ekin=ekin+half*amass(iatom)*vcart(ii,iatom)**2
    1970              :        end do
    1971              :      end do
    1972           10 :      if (dtset%ionmov/=1.and.atom_fix)  then
    1973            0 :        ABI_FREE(vcart)
    1974              :      end if
    1975           10 :      ncerr = nf90_inq_varid(ncid, "E_kin", EkinId)
    1976           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1977           30 :      ncerr = nf90_put_var(ncid, EkinId, (/ekin/), start = (/ipos/),count=(/1/))
    1978           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1979              : 
    1980              : !    EntropyDimid
    1981           10 :      ncerr = nf90_inq_varid(ncid, "Entropy", EntropyId)
    1982           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1983           30 :      ncerr = nf90_put_var(ncid, EntropyId, (/results_gs%energies%entropy/),start = (/ipos/),count=(/1/))
    1984           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1985              : 
    1986              : !    Stress tensor
    1987           10 :      ncerr = nf90_inq_varid(ncid, "Stress", StressId)
    1988           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1989              :      ncerr = nf90_put_var(ncid, StressId, results_gs%strten, &
    1990           30 : &     start=(/1,ipos/),count=(/size(results_gs%strten)/))
    1991           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1992              : 
    1993              : !    Positions
    1994           10 :      ncerr = nf90_inq_varid(ncid, "Position", PosId)
    1995           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    1996              :      ncerr = nf90_put_var(ncid, PosId, xcart, start=(/1,1,ipos/), &
    1997           70 : &     count=(/size(xcart,1),dtset%natom,1/))
    1998           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    1999              : 
    2000              : !    Celerities
    2001           10 :      ncerr = nf90_inq_varid(ncid, "Celerity", CelId)
    2002           10 :      NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    2003              :      ncerr = nf90_put_var(ncid, CelId, vel, start=(/1,1,ipos/), &
    2004           70 : &     count=(/size(vel,1),dtset%natom,1/)  )
    2005           10 :      NCF_CHECK_MSG(ncerr,'nf90_put_var')
    2006              : 
    2007              : !    In case of volume cell constant
    2008           10 :      if (dtset%optcell==0.and.ipos==1) then
    2009              : !      Primitive vectors
    2010           20 :        do ii = 1,3
    2011           15 :          write(unit=chain,fmt='(a15,i1)') "PrimitiveVector",ii
    2012           15 :          ncerr = nf90_inq_varid(ncid, trim(chain), PrimVectId(ii) )
    2013           15 :          NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    2014           15 :          ncerr = nf90_put_var(ncid, PrimVectId(ii), rprimd(:,ii))
    2015           20 :          NCF_CHECK_MSG(ncerr,'nf90_put_var')
    2016              :        end do
    2017              : !      Cell Volume
    2018            5 :        call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
    2019            5 :        ncerr = nf90_inq_varid(ncid, "Cell_Volume" , CellVolumeId)
    2020            5 :        NCF_CHECK_MSG(ncerr,'nf90_inq_varid')
    2021            5 :        ncerr = nf90_put_var(ncid, CellVolumeId, ucvol)
    2022            5 :        NCF_CHECK_MSG(ncerr,'nf90_put_var')
    2023              :      end if
    2024              : 
    2025              : !    Close file
    2026           10 :      ncerr = nf90_close(ncid)
    2027           10 :      NCF_CHECK_MSG(ncerr,'nf90_close')
    2028              :    end if
    2029              : 
    2030              : !  ==========================================================================
    2031              : !  Write data to POSABIN file (every nctime time step if option=3)
    2032              : !  ==========================================================================
    2033           26 :    if ((mod(itime, dtset%nctime)==0.and.option==3).or.(option==2)) then
    2034              : 
    2035              : !    Open file for writing
    2036           10 :      if (open_file('POSABIN',msg,unit=unpos,status='replace',form='formatted') /= 0 ) then
    2037            0 :        ABI_ERROR(msg)
    2038              :      end if
    2039              : 
    2040              : !    Write Positions
    2041           10 :      if (dtset%natom>=1) write(unpos,'(a7,3d18.5)') 'xred  ',(xred(ii,1),ii=1,3)
    2042           10 :      if (dtset%natom>1) then
    2043           40 :        do iatom=2,dtset%natom
    2044           40 :          write(unpos,'(7x,3d18.5)') (xred(ii,iatom),ii=1,3)
    2045              :        end do
    2046              :      end if
    2047              : 
    2048              : !    Write Velocities
    2049           10 :      if (dtset%natom>=1) write(unpos,'(a7,3d18.5)') 'vel  ',(vel(ii,1),ii=1,3)
    2050           10 :      if (dtset%natom>1) then
    2051           40 :        do iatom=2,dtset%natom
    2052           40 :          write(unpos,'(7x,3d18.5)') (vel(ii,iatom),ii=1,3)
    2053              :        end do
    2054              :      end if
    2055              : 
    2056              : !    Close file
    2057           10 :      close(unpos)
    2058              :    end if
    2059              : 
    2060           26 :    ABI_FREE(xcart)
    2061              : 
    2062              : !  ==========================================================================
    2063              : !  End if master proc
    2064              :  end if
    2065              : 
    2066           58 : end subroutine wrt_moldyn_netcdf
    2067              : !!***
    2068              : 
    2069              : end module m_mover
    2070              : !!***
        

Generated by: LCOV version 2.3-1