LCOV - code coverage report
Current view: top level - src/45_geomoptim - m_pred_isothermal.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.7 % 443 362
Test Date: 2026-09-21 13:49:52 Functions: 100.0 % 4 4

            Line data    Source code
       1              : !!****m* ABINIT/m_pred_isothermal
       2              : !! NAME
       3              : !!  m_pred_isothermal
       4              : !!
       5              : !! FUNCTION
       6              : !! Ionmov predictors (13) Isothermal integrator
       7              : !! This program is decribed in the following paper
       8              : !! Explicit integrators for extended systems dynamics
       9              : !! Glenn J Martyna et al.
      10              : !! Mol. Phys., 1996, Vol. 87, pp. 1117-1157 [[cite:Martyna1996]]
      11              : !!
      12              : !! COPYRIGHT
      13              : !! Copyright (C) 1998-2026 ABINIT group (DCA, XG, GMR, JCC, JYR, SE)
      14              : !!  This file is distributed under the terms of the
      15              : !!  GNU General Public License, see ~abinit/COPYING
      16              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      17              : !!
      18              : !! SOURCE
      19              : 
      20              : #if defined HAVE_CONFIG_H
      21              : #include "config.h"
      22              : #endif
      23              : 
      24              : #include "abi_common.h"
      25              : 
      26              : module m_pred_isothermal
      27              : 
      28              :  use defs_basis
      29              :  use m_errors
      30              :  use m_abicore
      31              :  use m_abimover
      32              :  use m_abihist
      33              :  use m_linalg_interfaces
      34              : 
      35              :  use m_numeric_tools,  only : uniformrandom
      36              :  use m_geometry,       only : mkrdim, xcart2xred, xred2xcart, metric
      37              : 
      38              :  implicit none
      39              : 
      40              :  private
      41              : !!***
      42              : 
      43              :  public :: pred_isothermal
      44              : !!***
      45              : 
      46              : contains
      47              : !!***
      48              : 
      49              : !!****f* ABINIT/pred_isothermal
      50              : !! NAME
      51              : !! pred_isothermal
      52              : !!
      53              : !! FUNCTION
      54              : !! Ionmov predictors (13) Isothermal integrator
      55              : !!
      56              : !! IONMOV 13:
      57              : !! Reversible integrator of Martyna at al.
      58              : !! The equation of motion of the ions in contact with a thermostat
      59              : !! and a barostat are solved with the algorithm proposed by Martyna,
      60              : !! Tuckermann Tobias and Klein, Mol. Phys., 1996, p. 1117. [[cite:Martyna1996]]
      61              : !! Related parameters : the time step (dtion),
      62              : !! the initial temperature mdtemp(1), the final temperature mdtemp(2),
      63              : !! the number of thermostats (nnos), and the masses of thermostats (qmass).
      64              : !! If optcell=1 or 2, the mass of the barostat (bmass) must be given in addition.
      65              : !!
      66              : !! There are three sub cases according to the value of optcell
      67              : !! optcell=0: isothermal
      68              : !! optcell=1: homogeneous cell fluctuations
      69              : !! optcell=2: full cell fluctuation in addition to temperature control.
      70              : !!
      71              : !! INPUTS
      72              : !! ab_mover <type(abimover)> : Datatype with all the information
      73              : !!                                needed by the preditor
      74              : !! itime  : Index of the present iteration
      75              : !! ntime  : Maximal number of iterations
      76              : !! zDEBUG : if true print some debugging information
      77              : !!
      78              : !! SIDE EFFECTS
      79              : !! hist <type(abihist)> : History of positions,forces
      80              : !!                               acell, rprimd, stresses
      81              : !!
      82              : !! SOURCE
      83              : 
      84         9093 : subroutine pred_isothermal(ab_mover,hist,itime,mttk_vars,ntime,zDEBUG,iexit)
      85              : 
      86              : !Arguments ------------------------------------
      87              : !scalars
      88              :  type(abimover),intent(in)       :: ab_mover
      89              :  type(abihist),intent(inout) :: hist
      90              :  type(mttk_type),intent(inout) :: mttk_vars
      91              :  integer,intent(in) :: itime
      92              :  integer,intent(in) :: ntime
      93              :  integer,intent(in) :: iexit
      94              :  logical,intent(in) :: zDEBUG
      95              : 
      96              : !Local variables-------------------------------
      97              : !scalars
      98              :  integer  :: ii,kk,iatom,idim,idum=5,ierr
      99              :  integer,parameter :: lwork=8
     100              :  real(dp) :: ucvol,ucvol0,ucvol_next,mttk_aloc,mttk_aloc2,mttk_bloc,ekin
     101              :  real(dp) :: massvol=0
     102              :  real(dp),parameter :: esh2=one/six,esh4=esh2/20._dp,esh6=esh4/42._dp
     103              :  real(dp),parameter :: esh8=esh6/72._dp,nosetol=tol10,v2tol=tol8
     104              :  real(dp) :: etotal,rescale_vel,polysh,s1,s2,sigma2,v2gauss,vtest
     105              :  real(dp),save :: ktemp,vlogv
     106              :  character(len=5000) :: message
     107              : !arrays
     108              :  real(dp),allocatable,save :: fcart_m(:,:),vel_nexthalf(:,:)
     109              : 
     110              :  real(dp) :: mttk_alc(3),mttk_alc2(3),mttk_blc(3),mttk_psh(3)
     111              :  real(dp) :: mttk_tv(3,3),mttk_vt(3,3),mttk_ubox(3,3)
     112              :  real(dp) :: mttk_uu(3),mttk_uv(3),mttk_veig(3)
     113              :  real(dp) :: acell(3),acell0(3),acell_next(3)
     114              :  real(dp) :: rprimd(3,3),rprimd0(3,3),rprim(3,3),rprimd_next(3,3),rprim_next(3,3)
     115              :  real(dp) :: gprimd(3,3)
     116              :  real(dp) :: gmet(3,3)
     117              :  real(dp) :: rmet(3,3)
     118        18186 :  real(dp) :: fcart(3,ab_mover%natom)
     119        18186 :  real(dp) :: xcart(3,ab_mover%natom),xcart_next(3,ab_mover%natom)
     120        18186 :  real(dp) :: xred(3,ab_mover%natom),xred_next(3,ab_mover%natom)
     121         9093 :  real(dp) :: vel(3,ab_mover%natom)
     122              :  real(dp) :: strten(6),work(lwork)
     123              : 
     124              : !***************************************************************************
     125              : !Beginning of executable session
     126              : !***************************************************************************
     127              : 
     128         9093 :  if(iexit/=0)then
     129           31 :    ABI_SFREE(fcart_m)
     130           31 :    ABI_SFREE(vel_nexthalf)
     131              :    return
     132              :  end if
     133              : 
     134              : !write(std_out,*) 'isothermal 01'
     135              : !##########################################################
     136              : !### 01. Debugging and Verbose
     137              : 
     138         9062 :  if(zDEBUG)then
     139            0 :    write(std_out,'(a,3a,41a,36a)') ch10,('-',kk=1,3),&
     140            0 : &   'Debugging and Verbose for pred_isothermal',('-',kk=1,36)
     141            0 :    write(std_out,*) 'ionmov: ',13
     142            0 :    write(std_out,*) 'itime:  ',itime
     143              :  end if
     144              : 
     145              : !write(std_out,*) 'isothermal 01'
     146              : !##########################################################
     147              : !### 01. Allocate the vectors vin, vout and hessian matrix
     148              : !###     These arrays could be allocated from a previus
     149              : !###     dataset that exit before itime==ntime
     150              : 
     151         9062 :  if(itime==1)then
     152          233 :    ABI_SFREE(fcart_m)
     153          233 :    ABI_SFREE(vel_nexthalf)
     154              :  end if
     155              : 
     156         9062 :  if (.not.allocated(fcart_m))       then
     157          699 :    ABI_MALLOC(fcart_m,(3,ab_mover%natom))
     158              :  end if
     159         9062 :  if (.not.allocated(vel_nexthalf))  then
     160          699 :    ABI_MALLOC(vel_nexthalf,(3,ab_mover%natom))
     161              :  end if
     162              : 
     163              : !write(std_out,*) 'isothermal 02'
     164              : !##########################################################
     165              : !### 02. Obtain the present values from the history
     166              : 
     167         9062 :  call hist2var(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     168              : 
     169     35378022 :  fcart(:,:)=hist%fcart(:,:,hist%ihist)
     170        63434 :  strten(:) =hist%strten(:,hist%ihist)
     171     35378022 :  vel(:,:)  =hist%vel(:,:,hist%ihist)
     172         9062 :  etotal    =hist%etot(hist%ihist)
     173              : 
     174        36248 :  do ii=1,3
     175       117806 :    rprim(ii,1:3)=rprimd(ii,1:3)/acell(1:3)
     176              :  end do
     177         9062 :  call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     178              : 
     179         9062 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     180              : 
     181         9062 :  if(zDEBUG)then
     182            0 :    write (std_out,*) 'fcart:'
     183            0 :    do kk=1,ab_mover%natom
     184            0 :      write (std_out,*) fcart(:,kk)
     185              :    end do
     186            0 :    write (std_out,*) 'vel:'
     187            0 :    do kk=1,ab_mover%natom
     188            0 :      write (std_out,*) vel(:,kk)
     189              :    end do
     190            0 :    write (std_out,*) 'strten:'
     191            0 :    write (std_out,*) strten(1:3),ch10,strten(4:6)
     192            0 :    write (std_out,*) 'etotal:'
     193            0 :    write (std_out,*) etotal
     194              :  end if
     195              : 
     196              : !Save initial values
     197         9062 :  acell0(:)=acell(:)
     198         9062 :  rprimd0(:,:)=rprimd(:,:)
     199         9062 :  ucvol0=ucvol
     200              : 
     201              : !write(std_out,*) 'isothermal 03'
     202              : !##########################################################
     203              : !### 05. Seconde half velocity step
     204              : 
     205         9062 :  if (itime>1) then
     206              : 
     207              : !  Next Half velocity step
     208        35316 :    do idim=1,3
     209     25904088 :      fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
     210              :    end do
     211     34500525 :    vel(:,:)=vel_nexthalf(:,:)+ab_mover%dtion/two*fcart_m(:,:)
     212              : 
     213         8829 :    if (ab_mover%optcell==0) then
     214              : !    Update Thermostat variables and velocity
     215              :      call isotemp(ab_mover%amass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     216         7861 : &     ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,vel)
     217          968 :    else if (ab_mover%optcell==1) then
     218              : !    Update Thermostat variables and velocity
     219              :      call isopress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     220              : &     ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,&
     221           14 : &     strten,ab_mover%strtarget,ucvol,vel,vlogv)
     222          954 :    else if (ab_mover%optcell==2) then
     223              : !    Next half step for extended variables
     224              :      call isostress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     225              : &     ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,&
     226          954 : &     ab_mover%qmass,strten,ab_mover%strtarget,ucvol,vel)
     227              :    end if
     228              : 
     229         8829 :    if(itime==2) massvol=ekin+etotal
     230              : 
     231         8829 :    if (ab_mover%optcell==2) then
     232              : !    Evolution of cell and volume
     233          954 :      acell_next(:)=acell(:)
     234          954 :      ucvol_next=ucvol
     235              :    end if
     236              : 
     237         8829 :    call mkrdim(acell,rprim,rprimd)
     238         8829 :    call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     239              : 
     240         8829 :    if(zDEBUG)then
     241            0 :      write(std_out,*) 'Second half velocity step'
     242            0 :      write(std_out,*) 'Cell parameters:'
     243            0 :      write(std_out,*) 'rprimd:'
     244            0 :      do kk=1,3
     245            0 :        write(std_out,*) rprimd(:,kk)
     246              :      end do
     247            0 :      write(std_out,*) 'rprim:'
     248            0 :      do kk=1,3
     249            0 :        write(std_out,*) rprim(:,kk)
     250              :      end do
     251            0 :      write(std_out,*) 'acell:'
     252            0 :      write(std_out,*) acell(:)
     253            0 :      write(std_out,*) 'Conserved energy:',(ekin+etotal)-massvol,ekin,etotal
     254            0 :      write(std_out,*) 'Volume of unitqry cell (ucvol):',ucvol
     255              :    end if
     256              : 
     257              :  end if ! if (itime>1)
     258              : 
     259              : !write(std_out,*) 'isothermal 04'
     260              : !##########################################################
     261              : !### 03. Compute the next values
     262              : 
     263              : !The temperature is linear between initial and final values
     264              : !It is here converted from Kelvin to Hartree (kb_HaK)
     265         9062 :  ktemp=(ab_mover%mdtemp(1)+((ab_mover%mdtemp(2)-ab_mover%mdtemp(1))/dble(ntime-1))*(itime-1))*kb_HaK
     266              : 
     267         9062 :  if(zDEBUG)then
     268            0 :    write(std_out,*) 'Temperature in Kelvin (ktemp):',ktemp
     269            0 :    write(std_out,*) 'Initial temp (mdtemp(1)):',ab_mover%mdtemp(1)
     270            0 :    write(std_out,*) 'Final temp (mdtemp(2)):',ab_mover%mdtemp(2)
     271            0 :    write(std_out,*) 'Delay for atom permutation (delayperm)',ab_mover%delayperm
     272            0 :    write(std_out,*) 'dtion',ab_mover%dtion
     273            0 :    write(std_out,*) 'nnos:', ab_mover%nnos
     274            0 :    write(std_out,*) 'qmass', ab_mover%qmass(:)
     275            0 :    write(std_out,*) 'bmass',ab_mover%bmass
     276              :  end if
     277              : 
     278         9062 :  if(itime==1) then
     279          962 :    mttk_vars%glogs(:)=zero; mttk_vars%vlogs(:)=zero; mttk_vars%xlogs(:)=zero
     280         3029 :    mttk_vars%vboxg(:,:)=zero
     281          233 :    vlogv=zero
     282              : !  v2gauss is twice the kinetic energy
     283          233 :    v2gauss=0.0_dp
     284       219549 :    do iatom=1,ab_mover%natom
     285       877497 :      do idim=1,3
     286       877264 :        v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
     287              :      end do
     288              :    end do
     289              : 
     290              : !  If there is no kinetic energy
     291          233 :    if (v2gauss<=v2tol.and.itime==1) then
     292              : !    Maxwell-Boltzman distribution
     293       219549 :      v2gauss=zero
     294       219549 :      vtest=zero
     295       219549 :      do iatom=1,ab_mover%natom
     296       877497 :        do idim=1,3
     297       657948 :          vel(idim,iatom)=sqrt(kb_HaK*ab_mover%mdtemp(1)/ab_mover%amass(iatom))*cos(two_pi*uniformrandom(idum))
     298       877264 :          vel(idim,iatom)=vel(idim,iatom)*sqrt(-2._dp*log(uniformrandom(idum)))
     299              :        end do
     300              :      end do
     301              : 
     302              : !    Get rid of center-of-mass velocity
     303       219549 :      s1=sum(ab_mover%amass(:))
     304          932 :      do idim=1,3
     305       658647 :        s2=sum(ab_mover%amass(:)*vel(idim,:))
     306       658880 :        vel(idim,:)=vel(idim,:)-s2/s1
     307              :      end do
     308              : 
     309              : !    Recompute v2gauss
     310       219549 :      do iatom=1,ab_mover%natom
     311       877497 :        do idim=1,3
     312       657948 :          v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
     313       877264 :          vtest=vtest+vel(idim,iatom)/(3._dp*ab_mover%natom)
     314              :        end do
     315              :      end do
     316              : 
     317              : !    Now rescale the velocities to give the exact temperature
     318          233 :      rescale_vel=sqrt(3._dp*ab_mover%natom*kb_HaK*ab_mover%mdtemp(1)/v2gauss)
     319       877497 :      vel(:,:)=vel(:,:)*rescale_vel
     320              : 
     321              : !    Recompute v2gauss with the rescaled velocities
     322              :      v2gauss=zero
     323       219549 :      do iatom=1,ab_mover%natom
     324       877497 :        do idim=1,3
     325       877264 :          v2gauss=v2gauss+vel(idim,iatom)*vel(idim,iatom)*ab_mover%amass(iatom)
     326              :        end do
     327              :      end do
     328              : 
     329              : !    Compute the variance and print
     330          233 :      sigma2=(v2gauss/(3._dp*ab_mover%natom)-ab_mover%amass(1)*vtest**2)/kb_HaK
     331              : 
     332          233 :      if (zDEBUG)then
     333              :        write(message, '(a)' )&
     334            0 : &       ' Rescaling or initializing velocities to initial temperature'
     335            0 :        call wrtout(std_out,message,'COLL')
     336              :        write(message, '(a,d12.5,a,D12.5)' )&
     337            0 : &       ' --- Scaling factor :',rescale_vel,' Asked T (K) ',ab_mover%mdtemp(1)
     338            0 :        call wrtout(std_out,message,'COLL')
     339              :        write(message, '(a,d12.5,a,D12.5)' )&
     340            0 : &       ' --- Effective temperature',v2gauss/(3*ab_mover%natom*kb_HaK),' From variance', sigma2
     341            0 :        call wrtout(std_out,message,'COLL')
     342              :      end if
     343              : 
     344              :    end if !(v2gauss<=v2tol.and.itime==1)
     345              :  end if !(itime==1)
     346              : 
     347              : !XG070613 : Do not take away the following line , seems needed for the pathscale compiler
     348              : 
     349         9062 :  if (zDEBUG) write(std_out,*) 'vboxg',mttk_vars%vboxg(:,:)
     350              : 
     351              : 
     352              : !write(std_out,*) 'isothermal 05'
     353              : !##########################################################
     354              : !### 03. First half velocity step
     355              : 
     356              : !write(std_out,*) 'FIRST HALF VELOCITY STEP',ucvol
     357              : !write(std_out,*) 'OPTCELL option selected:',ab_mover%optcell
     358              : !write(std_out,*) 'RPRIMD'
     359              : !do kk=1,3
     360              : !write(std_out,*) rprimd(:,kk)
     361              : !end do
     362              : !write(std_out,*) 'RPRIM'
     363              : !do kk=1,3
     364              : !write(std_out,*) rprim(:,kk)
     365              : !end do
     366              : !write(std_out,*) 'ACELL'
     367              : !write(std_out,*) acell(:)
     368              : 
     369              : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     370              : !%%% BEGIN sub case optcell=0 Isothermal Ensemble
     371              : !%%%
     372         9062 :  if(ab_mover%optcell==0) then
     373              : !  There is no evolution of cell
     374         8068 :    acell_next(:)=acell(:)
     375         8068 :    ucvol_next=ucvol
     376         8068 :    rprim_next(:,:)=rprim(:,:)
     377         8068 :    rprimd_next(:,:)=rprimd(:,:)
     378              : !  Update Thermostat variables and scale velocitie
     379              :    call isotemp(ab_mover%amass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     380         8068 : &   ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,vel)
     381              : 
     382              : !  Half velocity step
     383        32272 :    do idim=1,3
     384     25966768 :      fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
     385              :    end do
     386     34587396 :    vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
     387              : !  New positions
     388              : !  Convert input xred (reduced coordinates) to xcart (cartesian)
     389         8068 :    call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     390     34587396 :    xcart_next(:,:)=xcart(:,:)+vel_nexthalf(:,:)*ab_mover%dtion
     391              : !  Convert back to xred (reduced coordinates)
     392         8068 :    call xcart2xred(ab_mover%natom,rprimd,xcart_next,xred_next)
     393              : !  %%%
     394              : !  %%% END sub case optcell=0 Isothermal Ensemble
     395              : !  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     396              : 
     397              : !  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     398              : !  %%% BEGIN sub case optcell=1 Isothermal-Isenthalpic
     399              : !  %%%       Ensemble (homogeneous cell deformation)
     400              : !  %%%
     401          994 :  else if (ab_mover%optcell==1) then
     402              : !  Only homogeneous evolution of cell
     403              : !  Evolution of cell we keep rprim constant
     404           16 :    rprim_next(:,:)=rprim(:,:)
     405              : !  Update Thermostat variables and velocity
     406              :    call isopress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     407              : &   ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,ab_mover%qmass,&
     408           16 : &   strten,ab_mover%strtarget,ucvol,vel,vlogv)
     409              : 
     410              : !  Half velocity step
     411           64 :    do idim=1,3
     412          256 :      fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
     413              :    end do
     414          272 :    vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
     415              : !  New positions
     416           16 :    mttk_aloc=exp(ab_mover%dtion/two*vlogv)
     417           16 :    mttk_aloc2=(vlogv*ab_mover%dtion/two)**2
     418           16 :    polysh=(((esh8*mttk_aloc2+esh6)*mttk_aloc2+esh4)*mttk_aloc2+esh2)*mttk_aloc2+one
     419           16 :    mttk_bloc=mttk_aloc*polysh*ab_mover%dtion
     420              : !  Convert input xred (reduced coordinates) to xcart (cartesian)
     421           16 :    call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     422          272 :    xcart_next(:,:)=xcart(:,:)*mttk_aloc**2+vel_nexthalf(:,:)*mttk_bloc
     423              : !  Update the volume and related quantities
     424           64 :    acell_next(:)=acell(:)*exp(ab_mover%dtion*vlogv)
     425              : !  ucvol=ucvol*exp(ab_mover%dtion*vlogv)
     426           16 :    call mkrdim(acell_next,rprim,rprimd_next)
     427           16 :    call metric(gmet,gprimd,-1,rmet,rprimd_next,ucvol_next)
     428              : !  Convert back to xred (reduced coordinates)
     429           16 :    call xcart2xred(ab_mover%natom,rprimd_next,xcart_next,xred_next)
     430              : !  Computation of the forces for the new positions
     431              : !  Compute DFT forces (big loop)
     432              : 
     433              : !  COMMENTED
     434              : !  This should be in mover.F90
     435              : 
     436              : !  !      If metric has changed since the initialization, update the Ylm's
     437              : !  if (ab_mover%optcell/=0.and.psps%useylm==1.and.itime>1)then
     438              : !  option=0;if (ab_mover%iscf>0) option=1
     439              : !  call initylmg(gprimd,kg,ab_mover%kptns,ab_mover%mkmem,mpi_enreg,psps%mpsang,ab_mover%mpw,ab_mover%nband,ab_mover%nkpt,&
     440              : !  &         npwarr,ab_mover%nsppol,option,rprimd_next,ylm,ylmgr)
     441              : !  end if
     442              : 
     443              : 
     444              : !  %%%
     445              : !  %%% END sub case optcell=1 Isothermal-Isenthalpic
     446              : !  %%%     Ensemble (homogeneous cell deformation)
     447              : !  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     448              : 
     449              : !  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     450              : !  %%% BEGIN sub case optcell=2 Isothermal-Isenthalpic
     451              : !  %%%       Ensemble (full cell deformation)
     452              : !  %%%
     453          978 :  else if (ab_mover%optcell==2) then
     454          978 :    acell_next=acell
     455              : !  Fisrt half step for extended variables
     456              :    call isostress(ab_mover%amass,ab_mover%bmass,ab_mover%dtion,ekin,ab_mover%iatfix,&
     457              : &   ktemp,mttk_vars,ab_mover%natom,ab_mover%nnos,&
     458          978 : &   ab_mover%qmass,strten,ab_mover%strtarget,ucvol,vel)
     459              : !  Half velocity step
     460         3912 :    do idim=1,3
     461       595944 :      fcart_m(idim,:)=fcart(idim,:)/ab_mover%amass(:)
     462              :    end do
     463       790354 :    vel_nexthalf(:,:)=vel(:,:)+ab_mover%dtion/two*fcart_m(:,:)
     464              : !  Convert input xred (reduced coordinates) to xcart (cartesian)
     465          978 :    call xred2xcart(ab_mover%natom,rprimd,xcart,xred)
     466              : !  New positions
     467        12714 :    mttk_vt(:,:)=mttk_vars%vboxg(:,:)
     468          978 :    call dsyev('V','U',3,mttk_vt,3,mttk_veig,work,lwork,ierr)
     469        12714 :    mttk_tv(:,:)=transpose(mttk_vt)
     470         3912 :    mttk_alc(:)=exp(ab_mover%dtion/two*mttk_veig(:))
     471         3912 :    mttk_alc2(:)=(mttk_veig(:)*ab_mover%dtion/two)**2
     472         3912 :    mttk_psh(:)=(((esh8*mttk_alc2(:)+esh6)*mttk_alc2(:)+esh4)*mttk_alc2(:)+esh2)*mttk_alc2(:)+one
     473         3912 :    mttk_blc(:)=mttk_alc(:)*mttk_psh(:)*ab_mover%dtion
     474              : !  Update the positions
     475       198322 :    do iatom=1,ab_mover%natom
     476      2565472 :      mttk_uu(:)=matmul(mttk_tv,xcart(:,iatom))
     477      2565472 :      mttk_uv(:)=matmul(mttk_tv,vel_nexthalf(:,iatom))
     478       789376 :      mttk_uu(:)=mttk_uu(:)*mttk_alc(:)**2+mttk_uv(:)*mttk_blc(:)
     479      3158482 :      xcart_next(:,iatom)=matmul(mttk_vt,mttk_uu)
     480              :    end do
     481              : !  Update the box (rprimd and rprim)
     482        39120 :    mttk_ubox(:,:)=matmul(mttk_tv,rprimd)
     483         3912 :    do idim=1,3
     484        12714 :      mttk_ubox(:,idim)=mttk_ubox(:,idim)*mttk_alc(:)**2
     485              :    end do
     486        39120 :    rprimd_next(:,:)=matmul(mttk_vt,mttk_ubox)
     487         3912 :    do idim=1,3
     488        12714 :      rprim_next(idim,:)=rprimd_next(idim,:)/acell(:)
     489              :    end do
     490              : !  Update the volume
     491          978 :    call metric(gmet,gprimd,-1,rmet,rprimd_next,ucvol)
     492              : !  Convert back to xred (reduced coordinates)
     493          978 :    call xcart2xred(ab_mover%natom,rprimd_next,xcart_next,xred_next)
     494              : !  Computation of the forces for the new positions
     495              : 
     496              : !  COMMENTED
     497              : !  This should be in mover.F90
     498              : 
     499              : !  !      If metric has changed since the initialization, update the Ylm's
     500              : !  if (ab_mover%optcell/=0.and.psps%useylm==1.and.itime>1)then
     501              : !  option=0;if (ab_mover%iscf>0) option=1
     502              : !  call initylmg(gprimd,kg,ab_mover%kptns,ab_mover%mkmem,mpi_enreg,psps%mpsang,ab_mover%mpw,ab_mover%nband,ab_mover%nkpt,&
     503              : !  &         npwarr,ab_mover%nsppol,option,rprimd_next,ylm,ylmgr)
     504              : !  end if
     505              : 
     506              : !  %%%
     507              : !  %%% END sub case optcell=2 Isothermal-Isenthalpic
     508              : !  %%%     Ensemble (full cell deformation)
     509              : !  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     510              :  else
     511              :    write(message, '(a,i12,a,a)' )&
     512            0 : &   '  Disallowed value for optcell=',ab_mover%optcell,ch10,&
     513            0 : &   '  Allowed values with ionmov==13 : 0 to 2.'
     514            0 :    ABI_BUG(message)
     515              :  end if
     516              : 
     517              : !write(std_out,*) 'OLD PARAMETERS'
     518              : !write(std_out,*) 'RPRIMD'
     519              : !do kk=1,3
     520              : !write(std_out,*) rprimd(:,kk)
     521              : !end do
     522              : !write(std_out,*) 'RPRIM'
     523              : !do kk=1,3
     524              : !write(std_out,*) rprim(:,kk)
     525              : !end do
     526              : !write(std_out,*) 'ACELL'
     527              : !write(std_out,*) acell(:)
     528              : 
     529              : !write(std_out,*) 'NEXT PARAMETERS'
     530              : !write(std_out,*) 'RPRIMD'
     531              : !do kk=1,3
     532              : !write(std_out,*) rprimd_next(:,kk)
     533              : !end do
     534              : !write(std_out,*) 'RPRIM'
     535              : !do kk=1,3
     536              : !write(std_out,*) rprim_next(:,kk)
     537              : !end do
     538              : !write(std_out,*) 'ACELL'
     539              : !write(std_out,*) acell_next(:)
     540              : 
     541              : 
     542              : !Those are the values store into the history
     543         9062 :  rprim=rprim_next
     544         9062 :  rprimd=rprimd_next
     545     35378022 :  xred=xred_next
     546     35378022 :  xcart=xcart_next
     547         9062 :  acell=acell_next
     548              : 
     549              : !write(std_out,*) 'isothermal 06'
     550              : !##########################################################
     551              :  !### 06. Update the history with the prediction
     552              : 
     553              : !Increase indexes
     554         9062 :  hist%ihist = abihist_findIndex(hist,+1)
     555              : 
     556              : !Fill the history with the variables
     557              : !xred, acell, rprimd, vel
     558         9062 :  call var2hist(acell,hist,ab_mover%natom,rprimd,xred,zDEBUG)
     559     35378022 :  hist%vel(:,:,hist%ihist)=vel(:,:)
     560         9062 :  hist%time(hist%ihist)=real(itime,kind=dp)*ab_mover%dtion
     561              : 
     562         9062 :  if(zDEBUG)then
     563            0 :    write (std_out,*) 'fcart:'
     564            0 :    do kk=1,ab_mover%natom
     565            0 :      write (std_out,*) fcart(:,kk)
     566              :    end do
     567            0 :    write (std_out,*) 'vel:'
     568            0 :    do kk=1,ab_mover%natom
     569            0 :      write (std_out,*) vel(:,kk)
     570              :    end do
     571            0 :    write (std_out,*) 'strten:'
     572            0 :    write (std_out,*) strten(1:3),ch10,strten(4:6)
     573            0 :    write (std_out,*) 'etotal:'
     574            0 :    write (std_out,*) etotal
     575              :  end if
     576              : 
     577              : end subroutine pred_isothermal
     578              : !!***
     579              : 
     580              : !!****f* ABINIT/isotemp
     581              : !! NAME
     582              : !! isotemp
     583              : !!
     584              : !! FUNCTION
     585              : !! performs one half step on isotemp parameters according to Martyna et al.
     586              : !!
     587              : !! INPUTS
     588              : !!  amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
     589              : !!  dtion=
     590              : !!  isotemp_data
     591              : !!  ktemp
     592              : !!  vel
     593              : !!
     594              : !! OUTPUT
     595              : !!  Only updates variables
     596              : !!
     597              : !! SIDE EFFECTS
     598              : !!  isotemp_data: updates the thermostat parameters
     599              : !!  vel=update the velocities
     600              : !!
     601              : !! SOURCE
     602              : 
     603        15929 : subroutine isotemp(amass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,qmass,vel)
     604              : 
     605              : !Arguments ------------------------------------
     606              : !scalars
     607              :  integer,intent(in) :: natom
     608              :  integer,intent(in) :: nnos
     609              :  real(dp),intent(in) :: dtion,ktemp
     610              :  real(dp),intent(out) :: ekin
     611              :  type(mttk_type) :: mttk_vars
     612              : !arrays
     613              :  real(dp),intent(in) :: amass(natom)
     614              :  real(dp),intent(inout) :: vel(3,natom)
     615              :  real(dp),intent(in) :: qmass(:)
     616              :  integer,intent(in) :: iatfix(:,:)
     617              : 
     618              : !Local variables ------------------------------
     619              : !scalars
     620              :  integer :: iatom,idir,inos
     621              :  real(dp) :: alocal,gnkt,nfree,scale
     622              :  !character(len=500) :: message
     623              : !arrays
     624        15929 :  real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
     625              : 
     626              : !***************************************************************************
     627              : !Beginning of executable session
     628              : !***************************************************************************
     629              : 
     630        47787 :  ABI_MALLOC(glogs,(nnos))
     631        31858 :  ABI_MALLOC(vlogs,(nnos))
     632        31858 :  ABI_MALLOC(xlogs,(nnos))
     633        31888 :  glogs(:)=mttk_vars%glogs(:)
     634        31888 :  vlogs(:)=mttk_vars%vlogs(:)
     635        31888 :  xlogs(:)=mttk_vars%xlogs(:)
     636        15929 :  scale=one
     637              : !Compute the ionic kinetic energy
     638        15929 :  nfree=zero
     639        15929 :  ekin=zero
     640     17089109 :  do iatom=1,natom
     641     68308649 :    do idir=1,3
     642              : !    Warning : the fixing of atomis is implemented in reduced
     643              : !    coordinates, so that this expression is wrong
     644     68292720 :      if (iatfix(idir,iatom) == 0) then
     645     51219540 :        ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
     646              : !      Counts the degrees of freedom
     647     51219540 :        nfree=nfree+one
     648              :      end if
     649              :    end do
     650              :  end do
     651        15929 :  gnkt=nfree*ktemp
     652              : !Update the forces
     653        15929 :  glogs(1)=(two*ekin-gnkt)/qmass(1)
     654        15929 :  vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
     655        15959 :  do inos=1,nnos-1
     656           30 :    alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
     657              :    vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
     658        15959 : &   dtion/four*glogs(nnos-inos)*alocal
     659              :  end do
     660              : !Update the particle velocities
     661        15929 :  alocal=exp(-dtion/two*vlogs(1))
     662        15929 :  scale=scale*alocal
     663              : !Update the forces
     664        15929 :  glogs(1)=(scale*scale*two*ekin-gnkt)/qmass(1)
     665              : !Update the thermostat positions
     666        31888 :  do inos=1,nnos
     667        31888 :    xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
     668              :  end do
     669              : !Update the thermostat velocities
     670        15959 :  do inos=1,nnos-1
     671           30 :    alocal=exp(-dtion/eight*vlogs(inos+1))
     672           30 :    vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
     673        15959 :    glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
     674              :  end do
     675        15929 :  vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
     676     68308649 :  vel(:,:)=vel(:,:)*scale
     677              : !Compute the ionic kinetic energy
     678        15929 :  ekin=zero
     679     17089109 :  do iatom=1,natom
     680     68308649 :    do idir=1,3
     681              : !    Warning : the fixing of atomis is implemented in reduced
     682              : !    coordinates, so that this expression is wrong
     683     68292720 :      if (iatfix(idir,iatom) == 0) then
     684     51219540 :        ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
     685              :      end if
     686              :    end do
     687              :  end do
     688              : !Compute the thermostat kinetic energy and add it to the ionic one
     689        15929 :  ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*nfree*ktemp
     690        15959 :  do inos=2,nnos
     691        15959 :    ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
     692              :  end do
     693        31888 :  mttk_vars%glogs(:)=glogs(:)
     694        31888 :  mttk_vars%vlogs(:)=vlogs(:)
     695        31888 :  mttk_vars%xlogs(:)=xlogs(:)
     696        15929 :  ABI_FREE(glogs)
     697        15929 :  ABI_FREE(vlogs)
     698        15929 :  ABI_FREE(xlogs)
     699              : !DEBUG
     700              : !write(std_out,*)'ekin added',half*qmass(1)*vlogs(1)**2,xlogs(1)*(nfree)*ktemp
     701              : !ENDEBUG
     702              : 
     703        15929 : end subroutine isotemp
     704              : !!***
     705              : 
     706              : !----------------------------------------------------------------------
     707              : 
     708              : !!****f* ABINIT/isopress
     709              : !! NAME
     710              : !! isopress
     711              : !!
     712              : !! FUNCTION
     713              : !! performs one half step on isopress parameters according to Martyna et al.
     714              : !!
     715              : !! INPUTS
     716              : !!  amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
     717              : !!  dtion= ionic time step
     718              : !!  isotemp_data
     719              : !!  ktemp
     720              : !!  press= current pressure of the system
     721              : !!  prtarget= target pressure
     722              : !!  ucvol= unit cell volume
     723              : !!  vel= current velocity
     724              : !!
     725              : !! OUTPUT
     726              : !!  Only updates variables
     727              : !!
     728              : !! SIDE EFFECTS
     729              : !!  isotemp_data: updates the thermostat parameters (saved variables: bouh !)
     730              : !!  vel=update the velocities
     731              : !!
     732              : !! SOURCE
     733              : 
     734           30 :  subroutine isopress(amass,bmass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,qmass,&
     735           30 :    & strten,strtarget,ucvol,vel,vlogv)
     736              : 
     737              : !Arguments ------------------------------------
     738              : !scalars
     739              :  integer,intent(in) :: nnos,natom
     740              :  real(dp),intent(in) :: dtion,ktemp,ucvol,bmass
     741              :  real(dp),intent(inout) :: vlogv
     742              :  real(dp),intent(out) :: ekin
     743              :  type(mttk_type) :: mttk_vars
     744              : !arrays
     745              :  real(dp),intent(in) :: amass(natom),strtarget(6),strten(6)
     746              :  real(dp),intent(inout) :: vel(3,natom)
     747              :  real(dp),intent(in) :: qmass(:)
     748              :  integer,intent(in) :: iatfix(:,:)
     749              : 
     750              : !Local variables ------------------------------
     751              : !scalars
     752              :  integer :: iatom,idir,inos
     753              :  real(dp) :: alocal,glogv,gn1kt,gnkt,nfree,odnf,press,prtarget,scale
     754              :  logical :: DEBUG=.FALSE.
     755              : !character(len=500) :: message
     756              : !arrays
     757           30 :  real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
     758              : 
     759              : !***************************************************************************
     760              : !Beginning of executable session
     761              : !***************************************************************************
     762              : 
     763           30 :  if(DEBUG) then
     764            0 :    write(std_out,*) ch10,'***',ch10
     765            0 :    write(std_out,*)' isopress : enter '
     766            0 :    write(std_out,*)' strtarget=',strtarget
     767            0 :    write(std_out,*)' bmass=',bmass
     768            0 :    write(std_out,*)' dtion=',dtion
     769            0 :    write(std_out,*)' ktemp=',ktemp
     770            0 :    write(std_out,*)' natom=',natom
     771            0 :    write(std_out,*)' nnos=',nnos
     772            0 :    write(std_out,*)' strten=',strten
     773            0 :    write(std_out,*)' ucvol=',ucvol
     774              :  end if
     775              : 
     776           90 :  ABI_MALLOC(glogs,(nnos))
     777           60 :  ABI_MALLOC(vlogs,(nnos))
     778           60 :  ABI_MALLOC(xlogs,(nnos))
     779          120 :  glogs(:)=mttk_vars%glogs(:)
     780          120 :  vlogs(:)=mttk_vars%vlogs(:)
     781          120 :  xlogs(:)=mttk_vars%xlogs(:)
     782           30 :  glogv   =mttk_vars%glogv
     783           30 :  scale=one
     784              : !Compute the ionic kinetic energy
     785           30 :  nfree=zero
     786           30 :  ekin=zero
     787          150 :  do iatom=1,natom
     788          510 :    do idir=1,3
     789              : !    Warning : the fixing of atomis is implemented in reduced
     790              : !    coordinates, so that this expression is wrong
     791          480 :      if (iatfix(idir,iatom) == 0) then
     792          360 :        ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
     793              : !      Counts the degrees of freedom
     794          360 :        nfree=nfree+one
     795              :      end if
     796              :    end do
     797              :  end do
     798           30 :  prtarget=-(strtarget(1)+strtarget(2)+strtarget(3))/three
     799           30 :  press=-(strten(1)+strten(2)+strten(3))/three
     800           30 :  gnkt=nfree*ktemp
     801           30 :  gn1kt=(nfree+one)*ktemp
     802           30 :  odnf=one+three/nfree
     803              : !Update the forces
     804           30 :  glogs(1)=(two*ekin+bmass*vlogv*vlogv-gn1kt)/qmass(1)
     805           30 :  glogv=(odnf*two*ekin+three*(press-prtarget)*ucvol)/bmass
     806              : !Update thermostat velocity
     807           30 :  vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
     808           90 :  do inos=1,nnos-1
     809           60 :    alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
     810              :    vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
     811           90 : &   dtion/four*glogs(nnos-inos)*alocal
     812              :  end do
     813              : !Update dLog(V)/dt
     814           30 :  alocal=exp(-dtion/eight*vlogs(1))
     815           30 :  vlogv=vlogv*alocal**2+dtion/four*glogv*alocal
     816              : !Update the particle velocities
     817           30 :  alocal=exp(-dtion/two*(vlogs(1)+odnf*vlogv))
     818           30 :  scale=scale*alocal
     819           30 :  ekin=ekin*alocal**2
     820           30 :  glogv=(odnf*two*ekin+three*(press-prtarget)*ucvol)/bmass
     821              : !Update the thermostat positions
     822          120 :  do inos=1,nnos
     823          120 :    xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
     824              :  end do
     825              : !Update dLog(V)/dt
     826           30 :  alocal=exp(-dtion/eight*vlogs(1))
     827           30 :  vlogv=vlogv*alocal**2+dtion/four*glogv*alocal
     828              : !Update the forces
     829           30 :  glogs(1)=(two*ekin+bmass*vlogv*vlogv-gn1kt)/qmass(1)
     830              : !Update the thermostat velocities
     831           90 :  do inos=1,nnos-1
     832           60 :    alocal=exp(-dtion/eight*vlogs(inos+1))
     833           60 :    vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
     834           90 :    glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
     835              :  end do
     836           30 :  vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
     837          510 :  vel(:,:)=vel(:,:)*scale
     838              : !Compute the ionic kinetic energy
     839           30 :  ekin=zero
     840          150 :  do iatom=1,natom
     841          510 :    do idir=1,3
     842              : !    Warning : the fixing of atomis is implemented in reduced
     843              : !    coordinates, so that this expression is wrong
     844          480 :      if (iatfix(idir,iatom) == 0) then
     845          360 :        ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
     846              :      end if
     847              :    end do
     848              :  end do
     849              : !Compute the thermostat kinetic energy and add it to the ionic one
     850              : !First thermostat
     851           30 :  ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*(nfree+one)*ktemp
     852              : !Other thermostats
     853           90 :  do inos=2,nnos
     854           90 :    ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
     855              :  end do
     856              : !Barostat
     857           30 :  ekin=ekin+half*bmass*vlogv**2+prtarget*ucvol
     858           30 :  ABI_FREE(glogs)
     859           30 :  ABI_FREE(vlogs)
     860           30 :  ABI_FREE(xlogs)
     861              : 
     862              : !DEBUG
     863              : !write(std_out,*) 'EKIN',ekin
     864              : !write(std_out,*) 'VLOGV',vlogv
     865              : !write(std_out,*)'ekin added T',half*qmass(:)*vlogs(:)**2,xlogs(:)*(nfree)*ktemp
     866              : !write(std_out,*)'ekin added P',half*bmass*vlogv**2,prtarget*ucvol
     867              : !write(std_out,*)'ekin last',ekin
     868              : !ENDDEBUG
     869           30 : end subroutine isopress
     870              : !!***
     871              : 
     872              : !----------------------------------------------------------------------
     873              : 
     874              : !!****f* ABINIT/isostress
     875              : !! NAME
     876              : !! isostress
     877              : !!
     878              : !! FUNCTION
     879              : !! performs one half step on isostress parameters according to Martyna et al.
     880              : !!
     881              : !! INPUTS
     882              : !!  amass(natom)=mass of each atom, in unit of electronic mass (=amu*1822...)
     883              : !!  dtion= ionic time step
     884              : !!  isotemp_data
     885              : !!  ktemp
     886              : !!  press= current pressure of the system
     887              : !!  prtarget= target pressure
     888              : !!  ucvol= unit cell volume
     889              : !!  vel= current velocity
     890              : !!
     891              : !! OUTPUT
     892              : !!  Only updates variables
     893              : !!
     894              : !! SIDE EFFECTS
     895              : !!  isotemp_data: updates the thermostat parameters (saved variables: bouh !)
     896              : !!  vel=update the velocities
     897              : !!
     898              : !! SOURCE
     899              : 
     900         1932 :  subroutine isostress(amass,bmass,dtion,ekin,iatfix,ktemp,mttk_vars,natom,nnos,&
     901         1932 :    & qmass,strten,strtarget,ucvol,vel)
     902              : 
     903              :  use m_linalg_interfaces
     904              : 
     905              : !Arguments ------------------------------------
     906              : !scalars
     907              :  integer,intent(in) :: natom,nnos
     908              :  real(dp),intent(in) :: dtion,ktemp,ucvol,bmass
     909              :  real(dp),intent(out) :: ekin
     910              :  type(mttk_type) :: mttk_vars
     911              : !arrays
     912              :  real(dp),intent(in) :: amass(natom),strtarget(6),strten(6),qmass(:)
     913              :  real(dp),intent(inout) :: vel(3,natom)
     914              :  integer, intent(in) :: iatfix(:,:)
     915              : 
     916              : !Local variables ------------------------------
     917              : !scalars
     918              :  integer,parameter :: lwork=8
     919              :  integer :: iatom,idir,info,inos,jdir
     920              :  real(dp) :: akinb,alocal,gn1kt,gnd2kt,nfree,odnf,trvg !,gnkt,scale
     921              :  logical  :: DEBUG=.FALSE.
     922              : !character(len=500) :: message
     923              : !arrays
     924              :  real(dp) :: akin(3,3),expdiag(3),gboxg(3,3),identity(3,3),press(3,3)
     925              :  real(dp) :: prtarget(3,3),tvtemp(3,3),uv(3),vboxg(3,3),veig(3),vtemp(3,3)
     926              :  real(dp) :: work(lwork)
     927         1932 :  real(dp),allocatable :: glogs(:),vlogs(:),xlogs(:)
     928              : 
     929              : !***************************************************************************
     930              : !Beginning of executable session
     931              : !***************************************************************************
     932              : 
     933         1932 :  if(DEBUG) then
     934            0 :    write(std_out,*) ch10,'***',ch10
     935            0 :    write(std_out,*)' isostress : enter '
     936            0 :    write(std_out,*)' strtarget=',strtarget
     937            0 :    write(std_out,*)' bmass=',bmass
     938            0 :    write(std_out,*)' dtion=',dtion
     939            0 :    write(std_out,*)' ktemp=',ktemp
     940            0 :    write(std_out,*)' natom=',natom
     941            0 :    write(std_out,*)' nnos=',nnos
     942            0 :    write(std_out,*)' strten=',strten
     943            0 :    write(std_out,*)' ucvol=',ucvol
     944              :  end if
     945              : 
     946         5796 :  ABI_MALLOC(glogs,(nnos))
     947         3864 :  ABI_MALLOC(vlogs,(nnos))
     948         3864 :  ABI_MALLOC(xlogs,(nnos))
     949         3924 :  glogs(:)=mttk_vars%glogs(:)
     950         3924 :  vlogs(:)=mttk_vars%vlogs(:)
     951         3924 :  xlogs(:)=mttk_vars%xlogs(:)
     952        25116 :  vboxg(:,:)=mttk_vars%vboxg(:,:)
     953         1932 :  identity(:,:)=zero
     954         7728 :  do idir=1,3
     955         7728 :    identity(idir,idir)=one
     956              :  end do
     957              : 
     958              : !write(std_out,*) 'isostress 02'
     959              : !##########################################################
     960              : !### 03. Compute the ionic kinetic energy
     961              : 
     962         1932 :  nfree=zero
     963         1932 :  ekin=zero
     964       393796 :  do iatom=1,natom
     965      1569388 :    do idir=1,3
     966              : !    Warning : the fixing of atomis is implemented in reduced
     967              : !    coordinates, so that this exprtargetion is wrong
     968      1567456 :      if (iatfix(idir,iatom) == 0) then
     969      1175592 :        ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
     970              : !      Counts the degrees of freedom
     971      1175592 :        nfree=nfree+one
     972              :      end if
     973              :    end do
     974              :  end do
     975              : 
     976         1932 :  gn1kt=(nfree+one)*ktemp
     977         1932 :  gnd2kt=(nfree+9)*ktemp
     978         1932 :  odnf=one+three/nfree
     979         1932 :  akin(:,:)=zero
     980       393796 :  do iatom=1,natom
     981      1569388 :    do idir=1,3
     982      5094232 :      do jdir=1,3
     983              : !      Warning : the fixing of atomis is implemented in reduced
     984              : !      coordinates, so that this expression is wrong
     985      4702368 :        akin(idir,jdir)=akin(idir,jdir)+0.5d0*amass(iatom)*vel(idir,iatom)*vel(jdir,iatom)
     986              :      end do
     987              :    end do
     988              :  end do
     989              :  akinb=zero
     990         7728 :  do idir=1,3
     991        25116 :    do jdir=1,3
     992        23184 :      akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
     993              :    end do
     994              :  end do
     995              : !Compute the pressure: from Voigt to tensor notation+kinetic energy
     996         7728 :  do idir=1,3
     997         5796 :    press(idir,idir)=-strten(idir)
     998         7728 :    prtarget(idir,idir)=-strtarget(idir)
     999              :  end do
    1000         1932 :  press(3,2)=-strten(4); press(1,3)=-strten(5); press(2,1)=-strten(6)
    1001         1932 :  prtarget(3,2)=-strtarget(4); prtarget(1,3)=-strtarget(5); prtarget(2,1)=-strtarget(6)
    1002         1932 :  press(2,3)=press(3,2); press(3,1)=press(1,3); press(1,2)=press(2,1)
    1003         1932 :  prtarget(2,3)=prtarget(3,2); prtarget(3,1)=prtarget(1,3); prtarget(1,2)=prtarget(2,1)
    1004              : !Update the forces
    1005         1932 :  glogs(1)=(two*ekin+two*akinb-gnd2kt)/qmass(1)
    1006        25116 :  gboxg(:,:)=(two*ekin/nfree*identity(:,:)+two*akin(:,:)+(press(:,:)-prtarget(:,:))*ucvol)/bmass
    1007              : !Update thermostat velocity
    1008         1932 :  if (nnos > 0) vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
    1009         1992 :  do inos=1,nnos-1
    1010           60 :    alocal=exp(-dtion/eight*vlogs(nnos+1-inos))
    1011              :    vlogs(nnos-inos)=vlogs(nnos-inos)*alocal*alocal+&
    1012         1992 : &   dtion/four*glogs(nnos-inos)*alocal
    1013              :  end do
    1014              : !Update box velocity
    1015         1932 :  alocal=exp(-dtion/eight*vlogs(1))
    1016              : 
    1017         1932 :  if(DEBUG) then
    1018            0 :    write(std_out,*)' gboxg(:,:)=',gboxg(:,:)
    1019            0 :    write(std_out,*)' vboxg(:,:)=',vboxg(:,:)
    1020            0 :    write(std_out,*)' alocal=',alocal
    1021              :  end if
    1022              : 
    1023        25116 :  vboxg(:,:)=vboxg(:,:)*alocal**2+dtion/four*gboxg(:,:)*alocal
    1024              : !Update the thermostat positions
    1025         3924 :  do inos=1,nnos
    1026         3924 :    xlogs(inos)=xlogs(inos)+vlogs(inos)*dtion/two
    1027              :  end do
    1028              : !Update the particle velocities
    1029         1932 :  trvg=(vboxg(1,1)+vboxg(2,2)+vboxg(3,3))/nfree
    1030        25116 :  vtemp(:,:)=vboxg(:,:)+(trvg+vlogs(1))*identity(:,:)
    1031         1932 :  call dsyev('V','U',3,vtemp,3,veig,work,lwork,info)
    1032              : !On exit, we have vtemp=U such that tU vtemp U = veig
    1033        25116 :  tvtemp(:,:)=transpose(vtemp)
    1034              : 
    1035         1932 :  if(DEBUG) then
    1036            0 :    write(std_out,*)' vboxg(:,:)=',vboxg(:,:)
    1037            0 :    write(std_out,*)' vtemp(:,:)=',vtemp(:,:)
    1038            0 :    write(std_out,*)' veig(:)=',veig(:)
    1039              :  end if
    1040              : 
    1041         1932 :  expdiag(1)=exp(-veig(1)*dtion/two)
    1042         1932 :  expdiag(2)=exp(-veig(2)*dtion/two)
    1043         1932 :  expdiag(3)=exp(-veig(3)*dtion/two)
    1044              :  !if(DEBUG) then
    1045              :  !  write(std_out,*)' isostress : expdiag(:)=',expdiag(:)  ! Do not remove this line : seems to be needed for g95 compilo
    1046              :  !end if
    1047       393796 :  do iatom=1,natom
    1048      5094232 :    uv(:)=matmul(tvtemp,vel(:,iatom))
    1049      1567456 :    uv(:)=uv(:)*expdiag(:)
    1050      6271756 :    vel(:,iatom)=matmul(vtemp,uv)
    1051              :  end do
    1052              : !Compute the ionic kinetic energy
    1053         1932 :  nfree=zero
    1054         1932 :  ekin=zero
    1055       393796 :  do iatom=1,natom
    1056      1569388 :    do idir=1,3
    1057              : !    Warning : the fixing of atomis is implemented in reduced
    1058              : !    coordinates, so that this expression is wrong
    1059      1567456 :      if (iatfix(idir,iatom) == 0) then
    1060      1175592 :        ekin=ekin+0.5d0*amass(iatom)*vel(idir,iatom)**2
    1061      1175592 :        if(DEBUG) then
    1062            0 :          write(std_out,*)'kin',iatom,ekin,vel(idir,iatom)
    1063              :        end if
    1064              : !      Counts the degrees of freedom
    1065      1175592 :        nfree=nfree+one
    1066              :      end if
    1067              :    end do
    1068              :  end do
    1069         1932 :  gn1kt=(nfree+one)*ktemp
    1070         1932 :  gnd2kt=(nfree+9)*ktemp
    1071         1932 :  odnf=one+three/nfree
    1072         1932 :  akin(:,:)=zero
    1073       393796 :  do iatom=1,natom
    1074      1569388 :    do idir=1,3
    1075      5094232 :      do jdir=1,3
    1076              : !      Warning : the fixing of atomis is implemented in reduced
    1077              : !      coordinates, so that this expression is wrong
    1078      4702368 :        akin(idir,jdir)=akin(idir,jdir)+0.5d0*amass(iatom)*vel(idir,iatom)*vel(jdir,iatom)
    1079              :      end do
    1080              :    end do
    1081              :  end do
    1082        25116 :  gboxg(:,:)=(two*ekin/nfree*identity(:,:)+two*akin(:,:)+(press(:,:)-prtarget(:,:))*ucvol)/bmass
    1083              : !Update box velocity
    1084              :  alocal=exp(-dtion/eight*vlogs(1))
    1085        25116 :  vboxg(:,:)=vboxg(:,:)*alocal**2+dtion/four*gboxg(:,:)*alocal
    1086              : !Compute the box kinetic energy
    1087              :  akinb=zero
    1088         7728 :  do idir=1,3
    1089        25116 :    do jdir=1,3
    1090        23184 :      akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
    1091              :    end do
    1092              :  end do
    1093         1932 :  glogs(1)=(two*ekin+two*akinb-gnd2kt)/qmass(1)
    1094              : !Update the thermostat velocities
    1095         1992 :  do inos=1,nnos-1
    1096           60 :    alocal=exp(-dtion/eight*vlogs(inos+1))
    1097           60 :    vlogs(inos)=vlogs(inos)*alocal*alocal+dtion/four*glogs(inos)*alocal
    1098         1992 :    glogs(inos+1)=(qmass(inos)*vlogs(inos)*vlogs(inos)-ktemp)/qmass(inos+1)
    1099              :  end do
    1100         1932 :  if (nnos > 0) vlogs(nnos)=vlogs(nnos)+glogs(nnos)*dtion/four
    1101              : !Compute the ionic kinetic energy
    1102         1932 :  ekin=zero
    1103       393796 :  do iatom=1,natom
    1104      1569388 :    do idir=1,3
    1105              : !    Warning : the fixing of atomis is implemented in reduced
    1106              : !    coordinates, so that this expression is wrong
    1107      1567456 :      if (iatfix(idir,iatom) == 0) then
    1108      1175592 :        ekin=ekin+half*amass(iatom)*vel(idir,iatom)**2
    1109              :      end if
    1110              :    end do
    1111              :  end do
    1112              : !Compute the thermostat kinetic energy and add it to the ionic one
    1113              : !First thermostat
    1114         1932 :  ekin=ekin+half*qmass(1)*vlogs(1)**2+xlogs(1)*(nfree+nine)*ktemp
    1115              : !Other thermostats
    1116         1992 :  do inos=2,nnos
    1117         1992 :    ekin=ekin+half*qmass(inos)*vlogs(inos)**2+xlogs(inos)*ktemp
    1118              :  end do
    1119              : !Barostat kinetic energy
    1120              :  akinb=zero
    1121         7728 :  do idir=1,3
    1122        25116 :    do jdir=1,3
    1123        23184 :      akinb=akinb+0.5d0*bmass*vboxg(idir,jdir)**2
    1124              :    end do
    1125              :  end do
    1126              : !ekin is the invariant minus the potential energy
    1127         1932 :  ekin=ekin+akinb+prtarget(1,1)*ucvol
    1128              : 
    1129        25116 :  mttk_vars%vboxg(:,:)=vboxg(:,:)
    1130         3924 :  mttk_vars%glogs(:)=glogs(:)
    1131         3924 :  mttk_vars%vlogs(:)=vlogs(:)
    1132         3924 :  mttk_vars%xlogs(:)=xlogs(:)
    1133         1932 :  ABI_FREE(glogs)
    1134         1932 :  ABI_FREE(vlogs)
    1135         1932 :  ABI_FREE(xlogs)
    1136              : 
    1137         1932 :  if(DEBUG) then
    1138              : !  write(std_out,*)'ekin added T',half*qmass(:)*vlogs(:)**2,xlogs(:)*(nfree)*ktemp
    1139              : !  write(std_out,*)'ekin added P',akinb,prtarget*ucvol
    1140              : !  write(std_out,*)'ekin last',ekin
    1141            0 :    write(std_out,*) ch10,' exiting from isostress',ch10
    1142              :  end if
    1143              : 
    1144         1932 : end subroutine isostress
    1145              : !!***
    1146              : 
    1147              : !----------------------------------------------------------------------
    1148              : 
    1149              : end module m_pred_isothermal
    1150              : !!***
        

Generated by: LCOV version 2.3-1