Statistiques
| Révision :

root / src / egrad_LEPS.f90

Historique | Voir | Annoter | Télécharger (5,12 ko)

1
  SUBROUTINE egrad_LEPS(nat,e,geom,grad) 
2
! This program computes the ernergy and gradien in cartesian coordinates
3
! for the cartesian geometry Geom
4

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

    
36
   IMPLICIT NONE
37
     integer, parameter :: KINT = kind(1)
38
     integer, parameter :: KREAL = kind(1.0d0)
39

    
40
! Number of atoms
41
       INTEGER(KINT), INTENT(IN) :: Nat
42
! Input geometry
43
       REAL(KREAL), INTENT(IN) :: Geom(Nat,3)
44
! output energy and gradient
45
       REAL(KREAL), INTENT(OUT) :: E,grad(Nat*3)
46

    
47

    
48
! Parameters to define the surface
49
      INTEGER(KINT), DIMENSION(6), PARAMETER :: IECOEF = (/-1,9,-45,45,-9,1/)
50
      INTEGER(KINT), DIMENSION(6), PARAMETER :: ISCOEF = (/-3,-2,-1,1,2,3/)
51
      REAL(KREAL), PARAMETER :: hh=0.001d0
52
      
53
! Variables
54
       INTEGER(KINT) :: i,iat,jat
55
       REAL(KREAL), ALLOCATABLE :: Xyztmp(:,:),GradTmp(:,:)
56
 
57
       LOGICAL :: Debug
58
  
59
      REAL(KREAL), external :: ELEPS_xyz
60

    
61

    
62
  INTERFACE
63
     function valid(string) result (isValid)
64
       CHARACTER(*), intent(in) :: string
65
       logical                  :: isValid
66
     END function VALID
67
     
68
  END INTERFACE
69

    
70
  debug=valid('egrad_leps')
71

    
72
 if (debug) WRITE(*,*) '================ Entering Egrad_leps ==================='
73
 if (debug) THEN
74
    WRITE(*,*) "Cartesian Geometry"
75
    DO I=1,Nat
76
       WRITE(*,'(1X,I5,3(1X,F12.6))') I,Geom(i,1:3)
77
    END DO
78
 END IF
79
      
80
      ALLOCATE(XyZTmp(Nat,3),GradTmp(Nat,3))
81

    
82
      e=ELEPS_xyz(nat,Geom)
83

    
84
! We now calculate the gradients using numerical derivatives
85
      Grad=0.d0
86
      GradTmp=0.d0
87
      do iat=1,3
88
         do jat=1,nat
89
            xyztmp=geom
90
            do i=1,6
91
               xyztmp(jat,iat)=geom(jat,iat)+ISCoef(i)*hh
92
               gradTmp(jat,iat)=gradTmp(jat,iat)+IECoef(i)*ELEPS_xyz(nat,xyztmp)
93
            end do
94
         end do
95
      end do
96
      gradTmp=gradTmp/(60.*hh)
97
      do iat=1,nat
98
       grad(3*iat-2:3*iat)=gradTmp(iat,1:3)
99
      end do
100

    
101
 if (debug) THEN
102
    WRITE(*,*) "Cartesian gradient "
103
    DO I=1,Nat
104
       WRITE(*,'(1X,I5,3(1X,F12.6))') I,Gradtmp(i,1:3)
105
    END DO
106
 END IF
107

    
108

    
109
      deallocate(xyztmp,gradTmp)
110

    
111

    
112
 if (debug) WRITE(*,*) '================ Exiting Egrad_leps ==================='
113

    
114
! ======================================================================
115
      end 
116

    
117

    
118

    
119
      function ELEPS_xyz(natoms,Xyz)
120

    
121
        use Path_module, only : order
122
        use Io_module, only : au2ev
123

    
124
   IMPLICIT NONE
125
     integer, parameter :: KINT = kind(1)
126
     integer, parameter :: KREAL = kind(1.0d0)
127

    
128

    
129
      INTEGER(KINT) ,INTENT(IN) :: natoms
130
      REAL(KREAL) ,INTENT(IN) :: Xyz(natoms,3)
131
      REAL(KREAL) :: ELEPS_xyz
132

    
133
      INTEGER(KINT) :: i
134
      REAL(KREAL) :: rAB, rBC, rAC
135

    
136
      REAL(KREAL), PARAMETER :: a=0.05, b=0.30, c=0.05
137
      REAL(KREAL), PARAMETER :: dAB=4.746, dBC=4.747, dAC=3.445
138
      REAL(KREAL), PARAMETER :: r0=0.742, alpha=1.942
139

    
140
      REAL(KREAL) :: Qbc,QAc,Qab,Jab,Jbc,Jac
141

    
142
      rAB=0.
143
      rAC=0.
144
      rBC=0.
145
      do i=1,3
146
         rBC=rBC+(xyz(Order(3),i)-xyz(order(2),i))**2
147
         rAB=rAB+(xyz(order(1),i)-xyz(order(2),i))**2
148
         rAC=rAC+(xyz(order(1),i)-xyz(order(3),i))**2
149
      end do
150
      rAB=sqrt(rAB)
151
      rBC=sqrt(rBC)
152
      rAC=sqrt(rAC)
153

    
154
! For consistency with previous articles : rAC is constrained to be 3.742
155
      rAC=3.742
156

    
157
      Qab = dab*(1.5*exp(-2*alpha*(rAB-r0))-exp(-alpha*(rAB-r0)))/(2+2*a)
158
      Qbc = dbc*(1.5*exp(-2*alpha*(rBC-r0))-exp(-alpha*(rBC-r0)))/(2+2*b)
159
      Qac = dac*(1.5*exp (-2*alpha*(rAC-r0))-exp(-alpha*(rAC-r0)))/(2+2*c)
160
      Jab = dab*(exp(-2*alpha*(rAB-r0))-6*exp(-alpha*(rAB-r0)))/(4+4*a)
161
      Jbc = dbc*(exp(-2*alpha*(rBC-r0))-6*exp(-alpha*(rBC-r0)))/(4+4*b)
162
      Jac = dac*(exp(-2*alpha*(rAC-r0))-6*exp(-alpha*(rAC-r0)))/(4+4*c)
163

    
164
! V(x,y) = Qab(x)+Qbc(y)+Qac(rac)-sqrt(Jab(x)**2+Jbc(y)**2+Jac(x)**2-Jab(x)*Jbc(y)-Jbc(y)*Jac(rac)-Jab(x)*Jac(rac))
165

    
166

    
167
      ELEPS_xyz=(Qab+Qbc+Qac-sqrt(Jab**2+Jbc**2+Jac**2-Jab*Jbc-Jbc*Jac-Jab*Jac))/au2eV
168

    
169
      return
170
    end function ELEPS_xyz