subroutine egrad_mopac(e,geomcart,gradcart)

  ! This routines calculates the energy and the gradient of 
  ! a molecule, using mopac 

!----------------------------------------------------------------------
!  Copyright 2003-2014 Ecole Normale Supérieure de Lyon, 
!  Centre National de la Recherche Scientifique,
!  Université Claude Bernard Lyon 1. All rights reserved.
!
!  This work is registered with the Agency for the Protection of Programs 
!  as IDDN.FR.001.100009.000.S.P.2014.000.30625
!
!  Authors: P. Fleurat-Lessard, P. Dayal
!  Contact: optnpath@gmail.com
!
! This file is part of "Opt'n Path".
!
!  "Opt'n Path" is free software: you can redistribute it and/or modify
!  it under the terms of the GNU Affero General Public License as
!  published by the Free Software Foundation, either version 3 of the License,
!  or (at your option) any later version.
!
!  "Opt'n Path" is distributed in the hope that it will be useful,
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
!
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!  GNU Affero General Public License for more details.
!
!  You should have received a copy of the GNU Affero General Public License
!  along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>.
!
! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr,
! for commercial licensing opportunities.
!----------------------------------------------------------------------

  use Path_module, only : Nat, renum,Order,OrderInv,AtName, Coord, ProgExe, &
       FPBC, Lat_a, Lat_b, Lat_c, IPer
  use Io_module

  IMPLICIT NONE

  ! Energy (calculated if F300K=.F., else estimated)
  REAL(KREAL), INTENT (OUT) :: e
  ! Nb degree of freedom
  REAL(KREAL), INTENT (IN) :: geomcart(Nat,3)
  ! Gradient calculated at Geom geometry
  REAL(KREAL), INTENT (OUT) :: gradcart(3*NAt)

  ! ======================================================================

  character(LCHARS) :: LINE

  logical           :: debug
  LOGICAL, SAVE :: first=.true.

  REAL(KREAL) :: Pi

  INTEGER(KINT) :: iat, i, j, k, n3at
  INTEGER(KINT) :: ITmp1,ITmp2, Idx

  CHARACTER(132) :: FileIn, FileOut, FileChk

  CHARACTER(3) :: SepIn=' < ', SepOut=' > '
  CHARACTER(VLCHARS), SAVE ::  RunCommand

  ! ======================================================================

  INTERFACE
     function valid(string) result (isValid)
       CHARACTER(*), intent(in) :: string
       logical                  :: isValid
     END function VALID
  END INTERFACE

  ! ======================================================================

  Pi=dacos(-1.0d0)
  n3at=3*nat

  debug=valid('EGRAD')
  if (debug) WRITE(*,*) '================ Entering Egrad_Mopac ===================='

  if (first) THEN
     First=.FALSE.
     SepIn='   '
     SepOut='   '
  END IF
 
  gradcart=0.
  E=0.

  FileIn=Trim(CalcName) // "." // Trim(ISuffix)
  FileOut=Trim(CalcName) // "." // Trim(OSuffix)
  FileChk=Trim(CalcName) // ".arc"

  RunCommand=Trim(ProgExe) // SepIn // Trim(FileIn) 

  IF (DEBUG) WRITE(*,*)'RunCommand:',TRIM(RunCommand)

  ! we create the input file

  OPEN(IOTMP,File=FileIn)
  WRITE(IOTMP,'(A)') '* All comments are put at the begining of the file'
  Current => Mopac_comment
  DO WHILE (ASSOCIATED(Current%next))
     WRITE(IOTMP,'(A)') Trim(current%line)
     Current => current%next
  END DO

  Current => Mopac_root
  DO WHILE (ASSOCIATED(Current%next))
     WRITE(IOTMP,'(1X,A)') Trim(current%line)
     WRITE(*,'(1X,A)') Trim(current%line)
     Current => current%next
  END DO

  DO I=1,Nat
     If (renum) THEN
        Iat=Order(I)
        WRITE(IOTMP,'(1X,A10,3(1X,F15.8))') Trim(AtName(I)),GeomCart(Iat,:)
     ELSE
        Iat=OrderInv(I)
        WRITE(IOTMP,'(1X,A10,3(1X,F15.8))') Trim(AtName(Iat)),GeomCart(I,:)
     END IF
  END DO
! If we have periodic boundaries, we have to print them
  IF (FPBC) THEN
     IF (IPER>=1) THEN
        WRITE(IOTMP,'(1X," Tv ",3(1X,F15.8))') Lat_a(1:3)
     END IF
     IF (IPER>=2) THEN
        WRITE(IOTMP,'(1X," Tv ",3(1X,F15.8))') Lat_b(1:3)
     END IF
     IF (IPER>=3) THEN
        WRITE(IOTMP,'(1X," Tv ",3(1X,F15.8))') Lat_c(1:3)
     END IF
  END IF

     WRITE(IOTMP,'(1X,A)') Trim(Mopac_EndGeom)

  Current => Mopac_End
  DO WHILE (ASSOCIATED(Current%next))
     WRITE(IOTMP,'(1X,A)') Trim(current%line)
     Current => current%next
  END DO

  WRITE(IOTMP,*) 
  CLOSE(IOTMP)

  IF (debug) THEN
     WRITE(*,*) 'DBG EGRAD ' //  Trim(FileIn),' COORD=',TRIM(COORD)
     call system('cat ' // Trim(FileIn))
  END IF


  call system(RunCommand)

  if (debug) WRITE(*,*) 'DBG EGRAD, back from calculation'

  ! Whatever the coordinate system, we read the cartesian gradient
  ! and we convert it to Zmat or other if needed

  OPEN(IOTMP,FILE=FileOut, STATUS='old')
  ! We first search for the forces
  READ(IOTMP,'(A)') LINE

  DO WHILE (INDEX(LINE,'FINAL  POINT  AND  DERIVATIVES')==0)
     IF (INDEX(Line,'FINAL HEAT OF FORMATION').NE.0)  THEN
        Itmp1=Index(Line,"=")+1
        ITmp2=Index(Line,"KCAL")-1
        Read(Line(Itmp1:Itmp2),*) E
        E=E/au2kcal
     END IF
     READ(IOTMP,'(A)',END=999) LINE
  END DO

  if (debug) WRITE(*,*) "GradCart reading - renum=",Renum
  READ(IOTMP,'(A)') LINE
  READ(IOTMP,'(A)') LINE
  DO I=1,Nat
     Iat=I
     IF (renum) Iat=Order(I)
     DO J=1,3
        READ(IOTMP,'(A)') Line
! Gradient is on the 7th column
        DO K=1,6
           Line=AdjustL(Line)
           Idx=Index(Line," ")
           Line=AdjustL(Line(Idx+1:))
        END DO
        READ(Line,*) GradCart(3*Iat-3+j)
     END DO
     if (debug) WRITE(*,*) "I,Iat,GradCart:",I,Iat,GradCart(3*Iat-2:3*Iat)
  END DO

! Mopac gives the Forces in kcal/angstrom, so we convert it into the 
! gradient in ua/Angstrom 
  gradCart=gradCart/au2kcal

!  if (debug.AND.(COORD.EQ.'ZMAT')) THEN
!     DO WHILE (INDEX(LINE,'Internal Coordinate Forces')==0)
!        READ(IOTMP,'(A)') LINE
!!        WRITE(*,*) 'Pas bon:' // TRIM(LINE)
!     END DO
!     WRITE(*,*) TRIM(LINE)
!     DO I=1,Nat+2
!        READ(IOTMP,'(A)') LINE
!        WRITE(*,*) TRIM(LINE)
!     END DO
!  END IF

  CLOSE(IOTMP)

  if (debug) WRITE(*,*) '================  Egrad_Mopac Over ===================='

  RETURN

999 CONTINUE
  WRITE(*,*) 'We should not be here !!!!'
  STOP
  ! ======================================================================
end subroutine egrad_mopac
