TABLE OF CONTENTS


ABINIT/m_mep [ Modules ]

[ Top ] [ Modules ]

NAME

  m_mep

FUNCTION

  This module provides several routines and datatypes for the
  Minimal Energy Path (MEP) search implementation.

COPYRIGHT

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

INPUTS

OUTPUT

SOURCE

21 #if defined HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "abi_common.h"
26 
27 MODULE m_mep
28 
29  use defs_basis
30  use m_abicore
31  use m_errors
32  use m_dtset
33  use m_xmpi
34 
35  use defs_abitypes, only : MPI_type
36  use m_geometry,    only : gred2fcart, fcart2gred, xcart2xred, xred2xcart, metric
37  use m_bfgs,        only : hessupdt
38  use m_results_img, only : results_img_type, gather_array_img
39 
40  implicit none
41 
42  private
43 
44 !public procedures
45  public :: mep_init
46  public :: mep_destroy
47  public :: mep_steepest
48  public :: mep_qmin
49  public :: mep_lbfgs
50  public :: mep_gbfgs
51  public :: mep_rk4
52  public :: mep_img_dotp
53  public :: mep_img_norm
54  public :: mep_img_dotp_red
55  public :: mep_img_norm_red

m_mep/mep_destroy [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_destroy

FUNCTION

  Destroy the content of a datastructure of type mep_type.

INPUTS

OUTPUT

SIDE EFFECTS

  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.

SOURCE

164 subroutine mep_destroy(mep_param)
165 
166 !Arguments ------------------------------------
167 !scalars
168  type(mep_type),intent(inout) :: mep_param
169 
170 !************************************************************************
171 
172  ABI_SFREE(mep_param%bfgs_xprev)
173  ABI_SFREE(mep_param%gbfgs_hess)
174  ABI_SFREE(mep_param%bfgs_fprev)
175  ABI_SFREE(mep_param%lbfgs_hess)
176  ABI_SFREE(mep_param%qmin_vel)
177  ABI_SFREE(mep_param%rk4_xcart1)
178  ABI_SFREE(mep_param%rk4_fcart1)
179  ABI_SFREE(mep_param%rk4_fcart2)
180  ABI_SFREE(mep_param%rk4_fcart3)
181 
182  nullify(mep_param%iatfix)
183 
184 end subroutine mep_destroy

m_mep/mep_gbfgs [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_gbfgs

FUNCTION

  Make a path (string of images) evolve according to a
  global Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm

INPUTS

  itime=time step
  list_dynimage(nimage)=list of dynamical images.
  mep_param=datastructure of type mep_type.
  mpi_enreg=MPI-parallelisation information
  mep_param=several parameters for Minimal Energy Path (MEP) search.
  natom=number of atoms
  ndynimage=number of dynamical images along the path
  nimage=number of images (including static ones)
  nimage_tot=total number of images
  rprimd(3,3,nimage)=dimensional primitive translations for each image along the path

OUTPUT

SIDE EFFECTS

  mep_param=datastructure of type mep_type.
            History for Runge-Kutta algorithm is filled up
  xcart(3,natom,nimage)=cartesian coordinates of atoms in each image along the path
                        before and after time evolution
  xred(3,natom,nimage)=reduced coordinates of atoms in each image along the path
                       before and after time evolution

NOTES

  Could see Numerical Recipes (Fortran), 1986, page 307.
  Has to work in cartesian coordinates

SOURCE

609 subroutine mep_gbfgs(fcart,itime,list_dynimage,mep_param,mpi_enreg,natom,&
610 &                    ndynimage,nimage,nimage_tot,rprimd,xcart,xred)
611 
612 !Arguments ------------------------------------
613 !scalars
614  integer,intent(in) :: itime,natom,ndynimage,nimage,nimage_tot
615  type(mep_type),intent(inout) :: mep_param
616  type(MPI_type),intent(in) :: mpi_enreg
617 !arrays
618  integer,intent(in) :: list_dynimage(ndynimage)
619  real(dp),intent(in) :: fcart(3,natom,nimage),rprimd(3,3,nimage)
620  real(dp),intent(inout) :: xcart(3,natom,nimage),xred(3,natom,nimage)
621 !Local variables-------------------------------
622 !scalars
623  integer :: iatom,idynimage,ii,iimage,iimage_tot,indi,indj,ierr
624  integer :: jdynimage,jatom,jj,mu,ndynimage_tot,nu
625  logical :: reset
626  real(dp),parameter :: initial_Hessian=1._dp ! in Bohr^2/Hartree
627  real(dp) :: dot1,dot2,stepsize,ucvol
628  character(len=500) :: msg
629 !arrays
630  integer,allocatable :: dynimage_tot(:),iatfix_fake(:,:),ind_dynimage_tot(:)
631  integer,allocatable :: list_dynimage_tot(:)
632  real(dp) :: favg(3),gprimd(3,3),gmet(3,3),rmet(3,3)
633  real(dp),allocatable :: buffer(:,:),buffer_all(:,:),gred(:,:)
634  real(dp),allocatable :: fcart_all(:,:,:),fcartp_all(:,:,:)
635  real(dp),allocatable :: gmet_all(:,:,:),gprimd_all(:,:,:),rprimd_all(:,:,:)
636  real(dp),allocatable :: xcart_all(:,:,:),xcartp_all(:,:,:),xred_old(:,:),xstep_all(:,:,:)
637 
638 !************************************************************************
639 
640 !Retrieve indexes of all dynamical images
641  ABI_MALLOC(ind_dynimage_tot,(nimage_tot))
642  if (mpi_enreg%paral_img==1) then
643    ABI_MALLOC(dynimage_tot,(nimage_tot))
644    dynimage_tot=0
645    do idynimage=1,ndynimage
646      iimage=list_dynimage(idynimage)
647      iimage_tot=mpi_enreg%my_imgtab(iimage)
648      dynimage_tot(iimage_tot)=1
649    end do
650    call xmpi_sum(dynimage_tot,mpi_enreg%comm_img,ierr)
651    ndynimage_tot=count(dynimage_tot(:)>0)
652    ABI_MALLOC(list_dynimage_tot,(ndynimage_tot))
653    idynimage=0;ind_dynimage_tot(:)=-1
654    do iimage_tot=1,nimage_tot
655      if (dynimage_tot(iimage_tot)>0) then
656        idynimage=idynimage+1
657        ind_dynimage_tot(iimage_tot)=idynimage
658        list_dynimage_tot(idynimage)=iimage_tot
659      end if
660    end do
661    ABI_FREE(dynimage_tot)
662  else
663    ndynimage_tot=ndynimage
664    ABI_MALLOC(list_dynimage_tot,(ndynimage))
665    ind_dynimage_tot(:)=-1
666    do idynimage=1,ndynimage
667      ind_dynimage_tot(list_dynimage(idynimage))=idynimage
668      list_dynimage_tot(idynimage)=list_dynimage(idynimage)
669    end do
670  end if
671 
672 !Allocate history array (at first time step)
673  if (itime==1) then
674    if (allocated(mep_param%bfgs_xprev)) then
675      ABI_FREE(mep_param%bfgs_xprev)
676    end if
677    if (allocated(mep_param%bfgs_fprev)) then
678      ABI_FREE(mep_param%bfgs_fprev)
679    end if
680    if (allocated(mep_param%gbfgs_hess)) then
681      ABI_FREE(mep_param%gbfgs_hess)
682    end if
683    ABI_MALLOC(mep_param%bfgs_xprev,(3,natom,ndynimage))
684    ABI_MALLOC(mep_param%bfgs_fprev,(3,natom,ndynimage))
685    ABI_MALLOC(mep_param%gbfgs_hess,(3*natom*ndynimage_tot,3*natom*ndynimage_tot))
686    mep_param%bfgs_xprev=zero
687    mep_param%bfgs_fprev=zero
688  end if
689 
690 !Retrieve positions and forces for all images
691  ABI_MALLOC(xcart_all,(3,natom,ndynimage_tot))
692  ABI_MALLOC(fcart_all,(3,natom,ndynimage_tot))
693  ABI_MALLOC(xcartp_all,(3,natom,ndynimage_tot))
694  ABI_MALLOC(fcartp_all,(3,natom,ndynimage_tot))
695  ABI_MALLOC(rprimd_all,(3,3,ndynimage_tot))
696  ABI_MALLOC(gprimd_all,(3,3,ndynimage_tot))
697  ABI_MALLOC(gmet_all,(3,3,ndynimage_tot))
698  if (mpi_enreg%paral_img==1) then
699    ABI_MALLOC(buffer,(12*natom+27,nimage))
700    ABI_MALLOC(buffer_all,(12*natom+27,nimage_tot))
701    buffer=zero
702    do idynimage=1,ndynimage
703      iimage=list_dynimage(idynimage)
704      call metric(gmet,gprimd,-1,rmet,rprimd(:,:,iimage),ucvol)
705      buffer(         1:3 *natom  ,iimage)=reshape(xcart(:,:,iimage),(/3*natom/))
706      buffer(3 *natom+1:6 *natom  ,iimage)=reshape(fcart(:,:,iimage),(/3*natom/))
707      buffer(6 *natom+1:9 *natom  ,iimage)=reshape(mep_param%bfgs_xprev(:,:,idynimage),(/3*natom/))
708      buffer(9 *natom+1:12*natom  ,iimage)=reshape(mep_param%bfgs_fprev(:,:,idynimage),(/3*natom/))
709      buffer(12*natom+1:12*natom+9,iimage)=reshape(rprimd(:,:,iimage),(/9/))
710      buffer(12*natom+10:12*natom+18,iimage)=reshape(gprimd(:,:),(/9/))
711      buffer(12*natom+19:12*natom+27,iimage)=reshape(gmet(:,:),(/9/))
712    end do
713    call gather_array_img(buffer,buffer_all,mpi_enreg,allgather=.true.)
714    do idynimage=1,ndynimage_tot
715      iimage_tot=list_dynimage_tot(idynimage)
716      do iatom=1,natom
717        indi=12*(iatom-1)
718        do ii=1,3
719          xcart_all (ii,iatom,idynimage)= buffer_all(indi  +ii,iimage_tot)
720          fcart_all (ii,iatom,idynimage)=-buffer_all(indi+3+ii,iimage_tot) ! use fcart=-cartesian_force
721          xcartp_all(ii,iatom,idynimage)= buffer_all(indi+6+ii,iimage_tot)
722          fcartp_all(ii,iatom,idynimage)= buffer_all(indi+9+ii,iimage_tot)
723        end do
724      end do
725      indi=12*natom
726      rprimd_all(1:3,1:3,idynimage)=reshape(buffer_all(indi+ 1:indi+ 9,iimage_tot),(/3,3/))
727      gprimd_all(1:3,1:3,idynimage)=reshape(buffer_all(indi+10:indi+18,iimage_tot),(/3,3/))
728      gmet_all  (1:3,1:3,idynimage)=reshape(buffer_all(indi+19:indi+27,iimage_tot),(/3,3/))
729    end do
730    ABI_FREE(buffer)
731    ABI_FREE(buffer_all)
732  else
733    do idynimage=1,ndynimage
734      iimage=list_dynimage(idynimage)
735      xcart_all(:,:,idynimage)= xcart(:,:,iimage)
736      fcart_all(:,:,idynimage)=-fcart(:,:,iimage) ! use fcart=-cartesian_force
737      xcartp_all(:,:,idynimage)=mep_param%bfgs_xprev(:,:,idynimage)
738      fcartp_all(:,:,idynimage)=mep_param%bfgs_fprev(:,:,idynimage)
739      rprimd_all(:,:,idynimage)=rprimd(:,:,iimage)
740      call metric(gmet_all(:,:,idynimage),gprimd_all(:,:,idynimage),-1,rmet,rprimd(:,:,iimage),ucvol)
741    end do
742  end if
743 
744 !Test if a reset is needed
745  reset=.false.
746  if (itime>1) then
747    dot1=zero;dot2=zero
748    do idynimage=1,ndynimage_tot
749      dot1=dot2+mep_img_dotp(fcartp_all(:,:,idynimage),fcart_all (:,:,idynimage))
750      dot2=dot1+mep_img_dotp(fcartp_all(:,:,idynimage),fcartp_all(:,:,idynimage))
751    end do
752    reset=((dot2<two*abs(dot1)).or.abs(dot2)<tol8)
753    if (reset) then
754      msg=' Resetting Hessian matrix.'
755      call wrtout(std_out,msg,'COLL')
756      call wrtout(ab_out ,msg,'COLL')
757    end if
758  end if
759 
760 !===> First step or reset: initialize the Hessian matrix
761  if (itime==1.or.reset) then
762    mep_param%gbfgs_hess(:,:)=zero
763    do idynimage=1,ndynimage_tot
764      indi=3*natom*(idynimage-1)
765      do iatom=1,natom
766        do mu=1,3
767          do nu=1,3
768            do ii=1,3
769              do jj=1,3
770                if (mep_param%iatfix(ii,iatom)==0.and. &
771 &                  mep_param%iatfix(jj,iatom)==0) then
772                    mep_param%gbfgs_hess(indi+mu,indi+nu)=mep_param%gbfgs_hess(indi+mu,indi+nu) &
773 &                    +rprimd_all(mu,ii,idynimage)*rprimd_all(nu,jj,idynimage) &
774 &                    *gmet_all(ii,jj,idynimage)*initial_Hessian
775                end if
776              end do
777            end do
778          end do
779        end do
780        indi=indi+3
781      end do
782    end do
783 
784 !===> Other steps: update the Hessian matrix
785  else
786 
787 !  Impose here f-fprev=0 (cannot be done inside hessupdt in cartesian coordinates)
788    ABI_MALLOC(gred,(3,natom))
789    do idynimage=1,ndynimage_tot
790      fcartp_all(:,:,idynimage)=fcartp_all(:,:,idynimage)-fcart_all(:,:,idynimage)
791      call fcart2gred(fcartp_all(:,:,idynimage),gred,rprimd_all(:,:,idynimage),natom)
792      where (mep_param%iatfix(:,:)==1) ! iatfix is defined in reduced coordinates
793        gred(:,:)=zero
794      end where
795      call gred2fcart(favg,.TRUE.,fcartp_all(:,:,idynimage),gred,gprimd_all(:,:,idynimage),natom)
796      do iatom=1,natom
797        fcartp_all(:,iatom,idynimage)=fcartp_all(:,iatom,idynimage) &
798 &                                   +fcart_all(:,iatom,idynimage)+favg(:)
799      end do
800    end do
801    ABI_FREE(gred)
802 
803 !  f-fprev=0 has already been imposed for fixed atoms:
804 !  we call hessupdt with no fixed atom
805    ABI_MALLOC(iatfix_fake,(3,natom))
806    iatfix_fake(:,:)=0
807    call hessupdt(mep_param%gbfgs_hess,&
808 &                iatfix_fake,natom,3*natom*ndynimage_tot, &
809                  xcart_all,xcartp_all,fcart_all,fcartp_all, &
810 &                nimage=ndynimage_tot)
811    ABI_FREE(iatfix_fake)
812  end if
813 
814 !Free memory
815  ABI_FREE(xcart_all)
816  ABI_FREE(xcartp_all)
817  ABI_FREE(fcartp_all)
818  ABI_FREE(rprimd_all)
819  ABI_FREE(gprimd_all)
820  ABI_FREE(gmet_all)
821 
822 !Update history
823  do idynimage=1,ndynimage
824    iimage=list_dynimage(idynimage)
825    mep_param%bfgs_xprev(:,:,idynimage)=xcart(:,:,iimage)
826    mep_param%bfgs_fprev(:,:,idynimage)=fcart(:,:,iimage)
827  end do
828 
829 !Compute image step
830  ABI_MALLOC(xstep_all,(3,natom,ndynimage_tot))
831  xstep_all=zero
832  do idynimage=1,ndynimage_tot
833    indi=3*natom*(idynimage-1)
834    do iatom=1,natom
835      do ii=1,3
836        do jdynimage=1,ndynimage_tot
837          indj=3*natom*(jdynimage-1)
838          do jatom=1,natom
839            do jj=1,3
840 !            Be careful: minus sign because fcart=-cartesian_force
841              xstep_all(ii,iatom,idynimage)=xstep_all(ii,iatom,idynimage) &
842 &                           -fcart_all(jj,jatom,jdynimage) &
843 &                           *mep_param%gbfgs_hess(indi+ii,indj+jj)
844            end do
845            indj=indj+3
846          end do
847        end do
848      end do
849      indi=indi+3
850    end do
851  end do
852 
853 !Restrict image step size
854  stepsize=zero
855  do idynimage=1,ndynimage_tot
856    stepsize=stepsize+mep_img_dotp(xstep_all(:,:,idynimage),xstep_all(:,:,idynimage))
857  end do
858  stepsize=sqrt(stepsize)
859  if (stepsize>=mep_param%mep_mxstep*dble(ndynimage_tot)) then
860    xstep_all=xstep_all*mep_param%mep_mxstep*dble(ndynimage_tot)/stepsize
861    write(msg,'(a,i3,a)') " Restricting BFGS step size."
862    call wrtout(std_out,msg,'COLL')
863    call wrtout(ab_out ,msg,'COLL')
864  end if
865 
866 !Update positions
867  ABI_MALLOC(xred_old,(3,natom))
868  do idynimage=1,ndynimage
869    iimage=list_dynimage(idynimage)
870    iimage_tot=mpi_enreg%my_imgtab(iimage)
871    xred_old(:,:)=xred(:,:,iimage)
872    xcart(:,:,iimage)=xcart(:,:,iimage)+xstep_all(:,:,ind_dynimage_tot(iimage_tot))
873    call xcart2xred(natom,rprimd(:,:,iimage),xcart(:,:,iimage),xred(:,:,iimage))
874 !  In case atom is fixed, we restore its previous value
875    do iatom=1,natom
876      if (any(mep_param%iatfix(:,iatom)==1)) then
877        where(mep_param%iatfix(:,iatom)==1)
878          xred(:,iatom,iimage)=xred_old(:,iatom)
879        end where
880        call xred2xcart(1,rprimd(:,:,iimage),xcart(:,iatom,iimage),xred(:,iatom,iimage))
881      end if
882    end do
883  end do
884  ABI_FREE(xred_old)
885 
886 !Free memory
887  ABI_FREE(fcart_all)
888  ABI_FREE(xstep_all)
889  ABI_FREE(ind_dynimage_tot)
890  ABI_FREE(list_dynimage_tot)
891 
892 end subroutine mep_gbfgs

m_mep/mep_img_dotp [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_img_dotp

FUNCTION

  Compute the dot product of two vectors in the configuration space:
    Vect1(3,natom).Vect2(3,natom)

INPUTS

  vect1(3,natom)=input vector 1
  vect2(3,natom)=input vector 2

OUTPUT

  mep_img_dotp=dot product

SOURCE

1080 function mep_img_dotp(vect1,vect2)
1081 
1082 !Arguments ------------------------------------
1083 !scalars
1084  real(dp) :: mep_img_dotp
1085 !arrays
1086  real(dp),intent(in) :: vect1(:,:),vect2(:,:)
1087 !Local variables-------------------------------
1088 !scalars
1089  integer :: size1,size2
1090 !arrays
1091 
1092 !************************************************************************
1093 
1094  size1=size(vect1,1);size2=size(vect1,2)
1095  if (size1/=size(vect2,1).or.size2/=size(vect2,2)) then
1096    ABI_BUG("Error on dimensions !")
1097  end if
1098 
1099  mep_img_dotp=sum(vect1*vect2)
1100 
1101 end function mep_img_dotp

m_mep/mep_img_dotp_red [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_img_dotp_red

FUNCTION

  Compute the dot product of two vectors in the configuration space:
    Vect1(3,natom).Vect2(3,natom)
  using reduced coordinates

INPUTS

  rmet(3,3)=metric tensor
  vect1(3,natom)=input vector 1
  vect2(3,natom)=input vector 2

OUTPUT

  mep_img_dotp_red=dot product

SOURCE

1159 function mep_img_dotp_red(rmet,vect1,vect2)
1160 
1161 !Arguments ------------------------------------
1162 !scalars
1163  real(dp) :: mep_img_dotp_red
1164 !arrays
1165  real(dp),intent(in) :: rmet(3,3)
1166  real(dp),intent(in) :: vect1(:,:),vect2(:,:)
1167 !Local variables-------------------------------
1168 !scalars
1169  integer :: iatom,ii,jj,size1,size2
1170 
1171 !************************************************************************
1172 
1173  size1=size(vect1,1);size2=size(vect1,2)
1174  if (size1/=size(vect2,1).or.size2/=size(vect2,2).or.size1/=3) then
1175    ABI_BUG("Error on dimensions !")
1176  end if
1177 
1178  mep_img_dotp_red=zero
1179  do iatom=1,size2
1180    do ii=1,3
1181      do jj=1,3
1182        mep_img_dotp_red=mep_img_dotp_red+vect1(ii,iatom)*vect2(jj,iatom)*rmet(ii,jj)
1183      end do
1184    end do
1185  end do
1186 
1187 end function mep_img_dotp_red

m_mep/mep_img_norm [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_img_norm

FUNCTION

  Compute the norm of a vector in the configuration space:
    |Vect(3,natom)|

INPUTS

  vect(3,natom)=input vector

OUTPUT

  mep_img_norm=norm

SOURCE

1123 function mep_img_norm(vect)
1124 
1125 !Arguments ------------------------------------
1126 !scalars
1127  real(dp) :: mep_img_norm
1128 !arrays
1129  real(dp),intent(in) :: vect(:,:)
1130 
1131 !************************************************************************
1132 
1133  mep_img_norm=sqrt(sum(vect*vect))
1134 
1135 end function mep_img_norm

m_mep/mep_img_norm_red [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_img_norm_red

FUNCTION

  Compute the norm of a vector in the configuration space:
    |Vect(3,natom)|
  using reduced coordinates

INPUTS

  rmet(3,3)=metric tensor
  vect(3,natom)=input vector

OUTPUT

  mep_img_norm_red=norm

SOURCE

1211 function mep_img_norm_red(rmet,vect)
1212 
1213 !Arguments ------------------------------------
1214 !scalars
1215  real(dp) :: mep_img_norm_red
1216 !arrays
1217  real(dp),intent(in) :: rmet(3,3)
1218  real(dp),intent(in) :: vect(:,:)
1219 
1220 !************************************************************************
1221 
1222  mep_img_norm_red=sqrt(mep_img_dotp_red(rmet,vect,vect))
1223 
1224 end function mep_img_norm_red

m_mep/mep_init [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_init

FUNCTION

  Initialize a datastructure of type mep_type.

INPUTS

  dtset <type(dataset_type)>=all input variables in current dataset

OUTPUT

SIDE EFFECTS

  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.

SOURCE

113 subroutine mep_init(dtset,mep_param)
114 
115 !Arguments ------------------------------------
116 !scalars
117  type(dataset_type),target,intent(in) :: dtset
118  type(mep_type),intent(inout) :: mep_param
119 
120 !************************************************************************
121 
122  if((dtset%imgmov==1).or.(dtset%imgmov==2).or.(dtset%imgmov==5))then
123    mep_param%cineb_start  = dtset%cineb_start
124    mep_param%mep_solver   = dtset%mep_solver
125    mep_param%neb_algo     = dtset%neb_algo
126    mep_param%string_algo  = dtset%string_algo
127    mep_param%fxcartfactor = dtset%fxcartfactor
128    mep_param%mep_mxstep   = dtset%mep_mxstep
129    mep_param%neb_spring   = dtset%neb_spring
130    mep_param%iatfix       =>dtset%iatfix
131  else
132    mep_param%cineb_start  = -1
133    mep_param%mep_solver   = -1
134    mep_param%neb_algo     = -1
135    mep_param%string_algo  = -1
136    mep_param%fxcartfactor = zero
137    mep_param%mep_mxstep   = 100._dp
138    mep_param%neb_spring   = zero
139    nullify(mep_param%iatfix)
140  end if
141 
142 end subroutine mep_init

m_mep/mep_lbfgs [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_lbfgs

FUNCTION

  Make a path (string of images) evolve according to a
  local Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm

INPUTS

  itime=time step
  list_dynimage(nimage)=list of dynamical images.
  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.
  natom=number of atoms
  ndynimage=number of dynamical images along the path
  nimage=number of images (including static ones)
  rprimd(3,3,nimage)=dimensional primitive translations for each image along the path

OUTPUT

SIDE EFFECTS

  mep_param=datastructure of type mep_type.
            History for Runge-Kutta algorithm is filled up
  xcart(3,natom,nimage)=cartesian coordinates of atoms in each image along the path
                        before and after time evolution
  xred(3,natom,nimage)=reduced coordinates of atoms in each image along the path
                       before and after time evolution

NOTES

  Could see Numerical Recipes (Fortran), 1986, page 307.

SOURCE

431 subroutine mep_lbfgs(fcart,itime,list_dynimage,mep_param,natom,ndynimage,&
432 &                    nimage,rprimd,xcart,xred)
433 
434 !Arguments ------------------------------------
435 !scalars
436  integer,intent(in) :: itime,natom,ndynimage,nimage
437  type(mep_type),intent(inout) :: mep_param
438 !arrays
439  integer,intent(in) :: list_dynimage(ndynimage)
440  real(dp),intent(in) :: rprimd(3,3,nimage)
441  real(dp),intent(in) :: fcart(3,natom,nimage)
442  real(dp),intent(inout) :: xcart(3,natom,nimage),xred(3,natom,nimage)
443 !Local variables-------------------------------
444 !scalars
445  integer :: iatom,idynimage,ii,iimage,indi,indj,jatom,jj
446  logical :: reset
447  real(dp),parameter :: initial_Hessian=1._dp ! in Bohr^2/Hartree
448  real(dp) :: dot1,dot2,stepsize,ucvol
449  character(len=500) :: msg
450 !arrays
451  real(dp) :: gprimd(3,3),gmet(3,3),rmet(3,3)
452  real(dp),allocatable :: gred(:,:),xstep(:,:)
453 
454 !************************************************************************
455 
456 !Allocate history array (at first time step)
457  if (itime==1) then
458    if (allocated(mep_param%bfgs_xprev)) then
459      ABI_FREE(mep_param%bfgs_xprev)
460    end if
461    if (allocated(mep_param%bfgs_fprev)) then
462      ABI_FREE(mep_param%bfgs_fprev)
463    end if
464    if (allocated(mep_param%lbfgs_hess)) then
465      ABI_FREE(mep_param%lbfgs_hess)
466    end if
467    ABI_MALLOC(mep_param%bfgs_xprev,(3,natom,ndynimage))
468    ABI_MALLOC(mep_param%bfgs_fprev,(3,natom,ndynimage))
469    ABI_MALLOC(mep_param%lbfgs_hess,(3*natom,3*natom,ndynimage))
470    mep_param%bfgs_xprev=zero
471    mep_param%bfgs_fprev=zero
472  end if
473 
474 !Temporary storage
475  ABI_MALLOC(gred,(3,natom))
476  ABI_MALLOC(xstep,(3,natom))
477 
478 !Loop over images
479  do idynimage=1,ndynimage
480    iimage=list_dynimage(idynimage)
481    call metric(gmet,gprimd,-1,rmet,rprimd(:,:,iimage),ucvol)
482    call fcart2gred(fcart(:,:,iimage),gred,rprimd(:,:,iimage),natom)
483 
484 !  Test if a reset is needed
485    reset=.false.
486    if (itime>1) then
487      dot1=mep_img_dotp(mep_param%bfgs_fprev(:,:,idynimage),gred)
488      dot2=mep_img_dotp(mep_param%bfgs_fprev(:,:,idynimage), &
489 &                      mep_param%bfgs_fprev(:,:,idynimage))
490 !     dot1=mep_img_dotp_red(rmet,mep_param%bfgs_fprev(:,:,idynimage),gred)
491 !     dot2=mep_img_dotp_red(rmet,mep_param%bfgs_fprev(:,:,idynimage), &
492 !&                               mep_param%bfgs_fprev(:,:,idynimage))
493      reset=((dot2<two*abs(dot1)).or.abs(dot2)<tol8)
494      if (reset) then
495        write(msg,'(a,i3,a)') " Resetting Hessian matrix for image ",iimage,"."
496        call wrtout(std_out,msg,'COLL')
497        call wrtout(ab_out ,msg,'COLL')
498      end if
499    end if
500 
501 !  ===> First step or reset: initialize the Hessian matrix (in reduced coordinates)
502    if (itime==1.or.reset) then
503      mep_param%lbfgs_hess(:,:,idynimage)=zero
504      do iatom=1,natom
505        indi=3*(iatom-1)
506        do ii=1,3
507          do jj=1,3
508            if (mep_param%iatfix(ii,iatom)==0.and. &
509 &              mep_param%iatfix(jj,iatom)==0) then
510              mep_param%lbfgs_hess(indi+ii,indi+jj,idynimage)=gmet(ii,jj)*initial_Hessian
511            end if
512          end do
513        end do
514      end do
515 
516 !  ===> Other steps: update the Hessian matrix
517    else
518      call hessupdt(mep_param%lbfgs_hess(:,:,idynimage),&
519 &                  mep_param%iatfix,natom,3*natom, &
520                    xred(:,:,iimage),mep_param%bfgs_xprev(:,:,idynimage),&
521                    gred(:,:),mep_param%bfgs_fprev(:,:,idynimage))
522    end if
523 
524 !  Update history
525    mep_param%bfgs_xprev(:,:,idynimage)=xred(:,:,iimage)
526    mep_param%bfgs_fprev(:,:,idynimage)=gred(:,:)
527 
528 !  Compute image step
529    xstep=zero
530    do iatom=1,natom
531      indi=3*(iatom-1)
532      do ii=1,3
533        do jatom=1,natom
534          indj=3*(jatom-1)
535          do jj=1,3
536            xstep(ii,iatom)=xstep(ii,iatom) &
537 &             -mep_param%lbfgs_hess(indi+ii,indj+jj,idynimage)*gred(jj,jatom)
538          end do
539        end do
540      end do
541    end do
542 
543 !  Restrict image step size
544    stepsize=mep_img_norm_red(rmet,xstep)
545    if (stepsize>=mep_param%mep_mxstep) then
546      xstep=xstep*mep_param%mep_mxstep/stepsize
547      write(msg,'(a,i3,a)') " Restricting BFGS step size of image ",iimage,"."
548      call wrtout(std_out,msg,'COLL')
549      call wrtout(ab_out ,msg,'COLL')
550    end if
551 
552 !  Update positions
553    xred(:,:,iimage)=xred(:,:,iimage)+xstep(:,:)
554 
555 !  In case atom is fixed, we restore its previous value
556    where(mep_param%iatfix(:,:)==1)
557      xred(:,:,iimage)=mep_param%bfgs_xprev(:,:,idynimage)
558    end where
559 
560    call xred2xcart(natom,rprimd(:,:,iimage),xcart(:,:,iimage),xred(:,:,iimage))
561 
562 !End loop over images
563  end do
564 
565  ABI_FREE(gred)
566  ABI_FREE(xstep)
567 
568 end subroutine mep_lbfgs

m_mep/mep_qmin [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_qmin

FUNCTION

  Make a path (string of images) evolve according to a quick-minimizer algorithm

INPUTS

  fcart(3,natom,nimage)=cartesian forces in each image along the path
  itime=time step
  list_dynimage(nimage)=list of dynamical images.
  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.
  natom=number of atoms
  ndynimage=number of dynamical images along the path
  nimage=number of images (including static ones)
  results_img(nimage)=datastructure that hold data for each image
                      (positions, forces, energy, ...)
  rprimd(3,3,nimage)=dimensional primitive translations for each image along the path

OUTPUT

SIDE EFFECTS

  xcart(3,natom,nimage)=cartesian coordinates of atoms in each image along the path
                        before and after time evolution
  xred(3,natom,nimage)=reduced coordinates of atoms in each image along the path
                       before and after time evolution

SOURCE

310 subroutine mep_qmin(fcart,itime,list_dynimage,mep_param,natom,ndynimage,nimage,rprimd,xcart,xred)
311 
312 !Arguments ------------------------------------
313 !scalars
314  integer,intent(in) :: itime,natom,ndynimage,nimage
315  type(mep_type),intent(inout) :: mep_param
316 !arrays
317  integer,intent(in) :: list_dynimage(ndynimage)
318  real(dp),intent(in) :: fcart(3,natom,nimage),rprimd(3,3,nimage)
319  real(dp),intent(inout) :: xcart(3,natom,nimage),xred(3,natom,nimage)
320 !Local variables-------------------------------
321 !scalars
322  integer :: iatom,idynimage,iimage
323  real(dp) :: stepsize,vdotf
324  character(len=500) :: msg
325 !arrays
326  real(dp) :: vel_red(3)
327  real(dp),allocatable :: xred_old(:,:),xstep(:,:)
328 
329 !***********************************************************************
330 
331 !Allocate history array (at first time step)
332  if (itime==1) then
333    if (allocated(mep_param%qmin_vel)) then
334      ABI_FREE(mep_param%qmin_vel)
335    end if
336    ABI_MALLOC(mep_param%qmin_vel,(3,natom,ndynimage))
337    mep_param%qmin_vel=zero
338  end if
339 
340  ABI_MALLOC(xred_old,(3,natom))
341  ABI_MALLOC(xstep,(3,natom))
342 
343  do idynimage=1,ndynimage
344    iimage=list_dynimage(idynimage)
345    xred_old(:,:)=xred(:,:,iimage)
346 
347 !  Compute velocities
348    vdotf=mep_img_dotp(mep_param%qmin_vel(:,:,idynimage),fcart(:,:,iimage))
349    if (vdotf>=zero) then
350      mep_param%qmin_vel(:,:,idynimage)=vdotf*fcart(:,:,iimage) &
351 &                              /mep_img_norm(fcart(:,:,iimage))
352    else
353      mep_param%qmin_vel(:,:,idynimage)=zero
354      write(msg,'(a,i3,a)') " Setting velocities of image ",iimage," to zero."
355      call wrtout(std_out,msg,'COLL')
356      call wrtout(ab_out ,msg,'COLL')
357    end if
358    mep_param%qmin_vel(:,:,idynimage)=mep_param%qmin_vel(:,:,idynimage) &
359 &                   +mep_param%fxcartfactor*fcart(:,:,iimage)
360 
361 !  Compute image step
362    xstep(:,:)=mep_param%fxcartfactor*mep_param%qmin_vel(:,:,idynimage)
363    stepsize=mep_img_norm(xstep)
364    if (stepsize>=mep_param%mep_mxstep) then
365      xstep=xstep*mep_param%mep_mxstep/stepsize
366      write(msg,'(a,i3,a)') " Restricting step size of image ",iimage,"."
367      call wrtout(std_out,msg,'COLL')
368      call wrtout(ab_out ,msg,'COLL')
369    end if
370 
371 !  Update positions
372    xcart(:,:,iimage)=xcart(:,:,iimage)+xstep(:,:)
373    call xcart2xred(natom,rprimd(:,:,iimage),xcart(:,:,iimage),xred(:,:,iimage))
374 
375 !  In case atom is fixed, we restore its previous value
376    do iatom=1,natom
377      if (any(mep_param%iatfix(:,iatom)==1)) then
378        call xcart2xred(1,rprimd(:,:,iimage),mep_param%qmin_vel(:,iatom,idynimage),vel_red)
379        where(mep_param%iatfix(:,iatom)==1)
380          xred(:,iatom,iimage)=xred_old(:,iatom)
381          vel_red(:)=zero
382        end where
383        call xred2xcart(1,rprimd(:,:,iimage),xcart(:,iatom,iimage),xred(:,iatom,iimage))
384        call xred2xcart(1,rprimd(:,:,iimage),mep_param%qmin_vel(:,iatom,idynimage),vel_red)
385      end if
386    end do
387 
388  end do
389 
390  ABI_FREE(xred_old)
391  ABI_FREE(xstep)
392 
393 end subroutine mep_qmin

m_mep/mep_rk4 [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_rk4

FUNCTION

  Make a path (string of images) evolve according to a fourfth-order Runge-Kutta algorithm

INPUTS

  itime=time step
  list_dynimage(nimage)=list of dynamical images.
  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.
  natom=number of atoms
  ndynimage=number of dynamical images along the path
  nimage=number of images (including static ones)

OUTPUT

SIDE EFFECTS

  mep_param=datastructure of type mep_type.
            History for Runge-Kutta algorithm is filled up
  xcart(3,natom,nimage)=cartesian coordinates of atoms in each image along the path
                        before and after time evolution
                        after time evolution
  xred(3,natom,nimage)=reduced coordinates of atoms in each image along the path
                       before and after time evolution

SOURCE

 926 subroutine mep_rk4(fcart,itime,list_dynimage,mep_param,natom,ndynimage,nimage,rprimd,xcart,xred)
 927 
 928 !Arguments ------------------------------------
 929 !scalars
 930  integer,intent(in) :: itime,natom,ndynimage,nimage
 931  type(mep_type),intent(inout) :: mep_param
 932 !arrays
 933  integer,intent(in) :: list_dynimage(ndynimage)
 934  real(dp),intent(in) :: rprimd(3,3,nimage)
 935  real(dp),intent(in) :: fcart(3,natom,nimage)
 936  real(dp),intent(inout) :: xcart(3,natom,nimage),xred(3,natom,nimage)
 937 !Local variables-------------------------------
 938 !scalars
 939  integer,save :: istep_rk=0
 940  integer :: iatom,idynimage,iimage
 941  real(dp) :: stepsize
 942  character(len=500) :: msg
 943 !arrays
 944  real(dp),allocatable :: xred_old(:,:),xstep(:,:)
 945 
 946 !************************************************************************
 947 
 948 !Step for RK4 algorithm
 949  istep_rk=mod(itime,4)
 950 
 951 !Store data according to Runge-Kutta algo step
 952  if (istep_rk==1) then
 953    if (allocated(mep_param%rk4_xcart1)) then
 954      ABI_FREE(mep_param%rk4_xcart1)
 955    end if
 956    if (allocated(mep_param%rk4_fcart1)) then
 957      ABI_FREE(mep_param%rk4_fcart1)
 958    end if
 959    ABI_MALLOC(mep_param%rk4_xcart1,(3,natom,nimage))
 960    ABI_MALLOC(mep_param%rk4_fcart1,(3,natom,nimage))
 961    mep_param%rk4_xcart1 = xcart
 962    mep_param%rk4_fcart1 = fcart
 963  else if (istep_rk==2) then
 964    if (allocated(mep_param%rk4_fcart2)) then
 965      ABI_FREE(mep_param%rk4_fcart2)
 966    end if
 967    ABI_MALLOC(mep_param%rk4_fcart2,(3,natom,nimage))
 968    mep_param%rk4_fcart2 = fcart
 969  else if (istep_rk==3) then
 970    if (allocated(mep_param%rk4_fcart3)) then
 971      ABI_FREE(mep_param%rk4_fcart3)
 972    end if
 973    ABI_MALLOC(mep_param%rk4_fcart3,(3,natom,nimage))
 974    mep_param%rk4_fcart3 = fcart
 975  end if
 976 
 977  ABI_MALLOC(xred_old,(3,natom))
 978  if (istep_rk==0) then
 979    ABI_MALLOC(xstep,(3,natom))
 980  end if
 981 
 982  do idynimage=1,ndynimage
 983    iimage=list_dynimage(idynimage)
 984    xred_old(:,:)=xred(:,:,iimage)
 985 
 986 !  Note that one uses fcart, for which the sum of forces on all atoms vanish
 987 
 988 !  Intermediate Runge-Kutta step 1
 989    if      (istep_rk==1) then
 990      xcart(:,:,iimage)=mep_param%rk4_xcart1(:,:,iimage) &
 991 &       -half*mep_param%fxcartfactor*fcart(:,:,iimage)
 992 
 993 !  Intermediate Runge-Kutta step 2
 994    else if (istep_rk==2) then
 995      xcart(:,:,iimage)=mep_param%rk4_xcart1(:,:,iimage) &
 996 &       -half*mep_param%fxcartfactor*fcart(:,:,iimage)
 997 
 998 !  Intermediate Runge-Kutta step 3
 999    else if (istep_rk==3) then
1000      xcart(:,:,iimage)=mep_param%rk4_xcart1(:,:,iimage) &
1001 &       -mep_param%fxcartfactor*fcart(:,:,iimage)
1002 
1003 !  Final Runge-Kutta step
1004    else if (istep_rk==0) then
1005 !    Compute image step
1006      xstep(:,:)=third*mep_param%fxcartfactor &
1007 &      *(half*fcart(:,:,iimage) &
1008 &       +half*mep_param%rk4_fcart1(:,:,iimage) &
1009 &       +mep_param%rk4_fcart2(:,:,iimage) &
1010 &       +mep_param%rk4_fcart3(:,:,iimage))
1011      stepsize=mep_img_norm(xstep)
1012      if (stepsize>=mep_param%mep_mxstep) then
1013        xstep=xstep*mep_param%mep_mxstep/stepsize
1014        write(msg,'(a,i3,a)') " Restricting step size of image ",iimage,"."
1015        call wrtout(std_out,msg,'COLL')
1016        call wrtout(ab_out ,msg,'COLL')
1017      end if
1018 !    Update positions
1019      xcart(:,:,iimage)=mep_param%rk4_xcart1(:,:,iimage)+xstep(:,:)
1020    end if
1021 
1022    call xcart2xred(natom,rprimd(:,:,iimage),xcart(:,:,iimage),xred(:,:,iimage))
1023 
1024 !  In case atom is fixed, we restore its previous value
1025    do iatom=1,natom
1026      if (any(mep_param%iatfix(:,iatom)==1)) then
1027        where(mep_param%iatfix(:,iatom)==1)
1028          xred(:,iatom,iimage)=xred_old(:,iatom)
1029        end where
1030        call xred2xcart(1,rprimd(:,:,iimage),xcart(:,iatom,iimage),xred(:,iatom,iimage))
1031      end if
1032    end do
1033 
1034  end do
1035 
1036  ABI_FREE(xred_old)
1037  if (istep_rk==0) then
1038    ABI_FREE(xstep)
1039  end if
1040 
1041 !Cancel storage when final RK step has been done
1042  if (istep_rk==0) then
1043    if (allocated(mep_param%rk4_xcart1)) then
1044      ABI_FREE(mep_param%rk4_xcart1)
1045    end if
1046    if (allocated(mep_param%rk4_fcart1)) then
1047      ABI_FREE(mep_param%rk4_fcart1)
1048    end if
1049    if (allocated(mep_param%rk4_fcart2)) then
1050      ABI_FREE(mep_param%rk4_fcart2)
1051    end if
1052    if (allocated(mep_param%rk4_fcart3)) then
1053      ABI_FREE(mep_param%rk4_fcart3)
1054    end if
1055  end if
1056 
1057 end subroutine mep_rk4

m_mep/mep_steepest [ Functions ]

[ Top ] [ m_mep ] [ Functions ]

NAME

  mep_steepest

FUNCTION

  Make a path (string of images) evolve according to a steepest descent algorithm

INPUTS

  fcart(3,natom,nimage)=cartesian forces in each image along the path
  list_dynimage(nimage)=list of dynamical images.
  mep_param=datastructure of type mep_type.
            several parameters for Minimal Energy Path (MEP) search.
  natom=number of atoms
  ndynimage=number of dynamical images along the path
  nimage=number of images (including static ones)
  results_img(nimage)=datastructure that hold data for each image
                      (positions, forces, energy, ...)
  rprimd(3,3,nimage)=dimensional primitive translations for each image along the path

OUTPUT

SIDE EFFECTS

  xcart(3,natom,nimage)=cartesian coordinates of atoms in each image along the path
                        before and after time evolution
  xred(3,natom,nimage)=reduced coordinates of atoms in each image along the path
                       before and after time evolution

SOURCE

218 subroutine mep_steepest(fcart,list_dynimage,mep_param,natom,ndynimage,nimage,rprimd,xcart,xred)
219 
220 !Arguments ------------------------------------
221 !scalars
222  integer,intent(in) :: natom,ndynimage,nimage
223  type(mep_type),intent(in) :: mep_param
224 !arrays
225  integer,intent(in) :: list_dynimage(ndynimage)
226  real(dp),intent(in) :: fcart(3,natom,nimage),rprimd(3,3,nimage)
227  real(dp),intent(inout) :: xcart(3,natom,nimage),xred(3,natom,nimage)
228 !Local variables-------------------------------
229 !scalars
230  integer :: iatom,idynimage,iimage
231  real(dp) :: stepsize
232  character(len=500) :: msg
233 !arrays
234  real(dp),allocatable :: xred_old(:,:),xstep(:,:)
235 
236 !************************************************************************
237 
238  ABI_MALLOC(xred_old,(3,natom))
239  ABI_MALLOC(xstep,(3,natom))
240 
241  do idynimage=1,ndynimage
242    iimage=list_dynimage(idynimage)
243    xred_old(:,:)=xred(:,:,iimage)
244 
245 !  Compute image step
246 !  Note that one uses fcart, for which the sum of forces on all atoms vanish
247    xstep(:,:)=mep_param%fxcartfactor*fcart(:,:,iimage)
248    stepsize=mep_img_norm(xstep)
249    if (stepsize>=mep_param%mep_mxstep) then
250      xstep=xstep*mep_param%mep_mxstep/stepsize
251      write(msg,'(a,i3,a)') " Restricting step size of image ",iimage,"."
252      call wrtout(std_out,msg,'COLL')
253      call wrtout(ab_out ,msg,'COLL')
254    end if
255 
256 !  Update positions
257    xcart(:,:,iimage)=xcart(:,:,iimage)+xstep(:,:)
258    call xcart2xred(natom,rprimd(:,:,iimage),xcart(:,:,iimage),xred(:,:,iimage))
259 
260 !  In case atom is fixed, we restore its previous value
261    do iatom=1,natom
262      if (any(mep_param%iatfix(:,iatom)==1)) then
263        where(mep_param%iatfix(:,iatom)==1)
264          xred(:,iatom,iimage)=xred_old(:,iatom)
265        end where
266        call xred2xcart(1,rprimd(:,:,iimage),xcart(:,iatom,iimage),xred(:,iatom,iimage))
267      end if
268    end do
269 
270  end do
271 
272  ABI_FREE(xred_old)
273  ABI_FREE(xstep)
274 
275 end subroutine mep_steepest

m_mep/mep_type [ Types ]

[ Top ] [ m_mep ] [ Types ]

NAME

 mep_type

FUNCTION

 Datatype with the variables required to perform MEP search

SOURCE

67  type,public :: mep_type
68 ! Scalars
69   integer  :: cineb_start  ! Starting iteration for the CI-NEB
70   integer  :: mep_solver   ! Selection of a solver for the ODE
71   integer  :: neb_algo     ! Selection of the variant of the NEB method
72   integer  :: string_algo  ! Selection of the variant of the String Method
73   real(dp) :: fxcartfactor ! Time step for steepest descent or RK4
74   real(dp) :: mep_mxstep   ! Selection of a max. step size for the ODE
75 ! Arrays
76   integer,pointer      :: iatfix(:,:)=>null() ! Atoms to fix (this pointer is associated with dtset%iatfix)
77   real(dp)             :: neb_spring(2)       ! Spring constants for the NEB method
78   real(dp),allocatable :: bfgs_xprev(:,:,:)   ! BFGS storage (prev positions)
79   real(dp),allocatable :: bfgs_fprev(:,:,:)   ! BFGS storage (prev forces)
80   real(dp),allocatable :: gbfgs_hess(:,:)     ! global-BFGS storage (Hessian matrix)
81   real(dp),allocatable :: lbfgs_hess(:,:,:)   ! local-BFGS storage (Hessian matrix)
82   real(dp),allocatable :: qmin_vel(:,:,:)     ! Quick-min algo storage (velocities)
83   real(dp),allocatable :: rk4_xcart1(:,:,:)   ! 4th-order Runge-Kutta storage
84   real(dp),allocatable :: rk4_fcart1(:,:,:)   ! 4th-order Runge-Kutta storage
85   real(dp),allocatable :: rk4_fcart2(:,:,:)   ! 4th-order Runge-Kutta storage
86   real(dp),allocatable :: rk4_fcart3(:,:,:)   ! 4th-order Runge-Kutta storage
87  end type mep_type