root / src / egrad_test.f90 @ 7
Historique | Voir | Annoter | Télécharger (6,5 ko)
1 |
SUBROUTINE egrad_test(nat,e,geom,grad) |
---|---|
2 |
! This program reads cartesian coordinates from the file Ext.in |
3 |
! and print the energy (in au) and gradient (in au/Ang) in the file Ext.out |
4 |
! format D25.15 |
5 |
|
6 |
IMPLICIT NONE |
7 |
integer, parameter :: KINT = kind(1) |
8 |
integer, parameter :: KREAL = kind(1.0d0) |
9 |
|
10 |
INTEGER(KINT), INTENT(IN) :: Nat |
11 |
REAL(KREAL), INTENT(OUT) :: E,grad(Nat*3) |
12 |
REAL(KREAL), INTENT(IN) :: Geom(Nat,3) |
13 |
|
14 |
! Bohr --> Angstr |
15 |
real(KREAL), parameter :: BOHR = 0.52917726D+00 |
16 |
! |
17 |
! Parameters to define the surface |
18 |
INTEGER(KINT), DIMENSION(6), PARAMETER :: IECOEF = (/-1,9,-45,45,-9,1/) |
19 |
INTEGER(KINT), DIMENSION(6), PARAMETER :: ISCOEF = (/-3,-2,-1,1,2,3/) |
20 |
REAL(KREAL), PARAMETER :: hh=0.001d0 |
21 |
|
22 |
! Variables |
23 |
INTEGER(KINT) :: i,j,iat,jat |
24 |
REAL(KREAL), ALLOCATABLE :: Xyztmp(:,:),GradTmp(:,:) |
25 |
REAL(KREAL) :: xp,yp |
26 |
|
27 |
CHARACTER(132) :: Line |
28 |
LOGICAL :: Debug |
29 |
|
30 |
real(KREAL), parameter :: zero = 0.0_KREAL, one = 1.0_KREAL |
31 |
REAL(KREAL), external :: Exyz |
32 |
|
33 |
|
34 |
INTERFACE |
35 |
function valid(string) result (isValid) |
36 |
CHARACTER(*), intent(in) :: string |
37 |
logical :: isValid |
38 |
END function VALID |
39 |
|
40 |
END INTERFACE |
41 |
|
42 |
debug=valid('egrad_test') |
43 |
|
44 |
if (debug) WRITE(*,*) '================ Entering Egrad_test ===================' |
45 |
if (debug) THEN |
46 |
WRITE(*,*) "Cartesian Geometry" |
47 |
DO I=1,Nat |
48 |
WRITE(*,'(1X,I5,3(1X,F12.6))') I,Geom(i,1:3) |
49 |
END DO |
50 |
END IF |
51 |
|
52 |
ALLOCATE(XyZTmp(Nat,3),GradTmp(Nat,3)) |
53 |
|
54 |
e=Exyz(nat,Geom) |
55 |
|
56 |
! We now calculate the gradients using numerical derivatives |
57 |
Grad=0.d0 |
58 |
GradTmp=0.d0 |
59 |
do iat=1,3 |
60 |
do jat=1,nat |
61 |
xyztmp=geom |
62 |
do i=1,6 |
63 |
xyztmp(jat,iat)=geom(jat,iat)+ISCoef(i)*hh |
64 |
gradTmp(jat,iat)=gradTmp(jat,iat)+IECoef(i)*Exyz(nat,xyztmp) |
65 |
end do |
66 |
end do |
67 |
end do |
68 |
gradTmp=gradTmp/(60.*hh) |
69 |
do iat=1,nat |
70 |
grad(3*iat-2:3*iat)=gradTmp(iat,1:3) |
71 |
end do |
72 |
|
73 |
if (debug) THEN |
74 |
WRITE(*,*) "Cartesian gradient GradTmp" |
75 |
DO I=1,Nat |
76 |
WRITE(*,'(1X,I5,3(1X,F12.6))') I,Gradtmp(i,1:3) |
77 |
END DO |
78 |
WRITE(*,*) "Cartesian gradient Grad" |
79 |
WRITE(*,'(50(1X,F12.6))') Grad |
80 |
|
81 |
END IF |
82 |
|
83 |
|
84 |
deallocate(xyztmp,gradTmp) |
85 |
|
86 |
|
87 |
if (debug) WRITE(*,*) '================ Exiting Egrad_test ===================' |
88 |
|
89 |
! ====================================================================== |
90 |
end |
91 |
|
92 |
|
93 |
|
94 |
function Exyz(natoms,Xyz) |
95 |
|
96 |
use Path_module, only : order |
97 |
|
98 |
IMPLICIT NONE |
99 |
integer, parameter :: KINT = kind(1) |
100 |
integer, parameter :: KREAL = kind(1.0d0) |
101 |
|
102 |
|
103 |
INTEGER(KINT) ,INTENT(IN) :: natoms |
104 |
REAL(KREAL) ,INTENT(IN) :: Xyz(natoms,3) |
105 |
REAL(KREAL) :: Exyz |
106 |
|
107 |
INTEGER(KINT) :: i |
108 |
REAL(KREAL) :: dCH,dNH,dCN |
109 |
|
110 |
real(KREAL) :: autoA,autoeV |
111 |
parameter (autoA=0.52917715d0) |
112 |
parameter (autoeV=27.21183d0) |
113 |
|
114 |
|
115 |
real(KREAL) :: Q(3) |
116 |
real(KREAL) :: TT,gR,pR |
117 |
|
118 |
real(KREAL) :: mB,mC,mH |
119 |
real(KREAL) :: T,RN,RC,r1,r2,r3 |
120 |
|
121 |
real(KREAL) :: Z1,Z12,V1 |
122 |
real(KREAL) :: Z2,Z22,V2 |
123 |
real(KREAL) :: Z3,Z32,V3 |
124 |
|
125 |
real(KREAL) :: S1,S2,S3,S12,S22,S32,POLY |
126 |
real(KREAL) :: E1,E2,E3,HY1,HY2,HY3,SWITCH,V123 |
127 |
|
128 |
LOGICAL :: Debug |
129 |
LOGICAL, SAVE :: First=.TRUE. |
130 |
|
131 |
INTERFACE |
132 |
function valid(string) result (isValid) |
133 |
CHARACTER(*), intent(in) :: string |
134 |
logical :: isValid |
135 |
END function VALID |
136 |
|
137 |
END INTERFACE |
138 |
|
139 |
debug=valid('exyz') |
140 |
|
141 |
|
142 |
|
143 |
dCN=0. |
144 |
dCH=0. |
145 |
dNH=0. |
146 |
do i=1,3 |
147 |
dCN=dCN+(xyz(Order(3),i)-xyz(order(2),i))**2 |
148 |
dCH=dCH+(xyz(order(1),i)-xyz(order(2),i))**2 |
149 |
dNH=dNH+(xyz(order(1),i)-xyz(order(3),i))**2 |
150 |
end do |
151 |
R1=sqrt(dCH) |
152 |
R2=sqrt(dCN) |
153 |
R3=sqrt(dNH) |
154 |
|
155 |
IF (debug.AND.First) THEN |
156 |
WRITE(*,*) "Exyz in Test, dCH,dCN,dNH:",R1,R2,R3 |
157 |
END IF |
158 |
|
159 |
! R1=R1*autoA |
160 |
! R2=R2*autoA |
161 |
! R3=R3*autoA |
162 |
|
163 |
!.....CH |
164 |
Z1=R1-1.0823 |
165 |
Z12=Z1*Z1 |
166 |
V1=-2.8521*(1.0+5.5297*Z1+8.7166*Z12+5.3082*Z1*Z12)*dexp(-5.5297*Z1) |
167 |
!.....CN |
168 |
Z2=R2-1.1718 |
169 |
Z22=Z2*Z2 |
170 |
V2=-7.9282*(1.0+5.2448*Z2+7.3416*Z22+4.9785*Z2*Z22)*dexp(-5.2448*Z2) |
171 |
!.....NH |
172 |
Z3=R3-1.0370 |
173 |
Z32=Z3*Z3 |
174 |
V3=-3.9938*(1.0+3.0704*Z3)*dexp(-3.0704*Z3) |
175 |
|
176 |
! write(6,*) v1,v2,v3 |
177 |
|
178 |
!.....THREE BODY TERMS |
179 |
Z1=R1-1.9607 |
180 |
Z2=R2-2.2794 |
181 |
Z3=R3-1.8687 |
182 |
S1=0.4436*Z1+0.6091*Z2+0.6575*Z3 |
183 |
S2=-.8941*Z1+0.2498*Z2+0.3718*Z3 |
184 |
S3=0.0622*Z1-0.7527*Z2+0.6554*Z3 |
185 |
|
186 |
S12=S1*S1 |
187 |
S22=S2*S2 |
188 |
S32=S3*S3 |
189 |
POLY=-3.0578*(1.0+1.9076*S1-0.5008*S2-0.0149*S3+0.6695*S12 & |
190 |
-1.3535*S22-1.0501*S32+0.2698*S1*S2-1.1120*S1*S3 & |
191 |
+1.9310*S2*S3-0.0877*S1*S12+0.0044*S2*S22+0.0700 & |
192 |
*S3*S32+0.0898*S12*S2-1.0186*S1*S22-0.0911*S12 & |
193 |
*S3+0.0017*S1*S32+0.4567*S22*S3-0.8840*S2*S32 & |
194 |
+0.3333*S1*S2*S3-0.0367*S12*S12+0.4821*S22*S22 & |
195 |
+0.2564*S32*S32-0.0017*S12*S1*S2-0.2278*S12*S22 & |
196 |
-0.1287*S1*S2*S22+0.1759*S1*S12*S3-0.0399*S12*S32 & |
197 |
-0.1447*S1*S3*S32-0.3147*S2*S22*S3+0.1233*S22*S32 & |
198 |
+0.3161*S2*S3*S32+0.0919*S12*S2*S3-0.0954*S1*S22*S3 & |
199 |
+0.1778*S1*S2*S32-0.1892*S22*S22*S2) |
200 |
|
201 |
|
202 |
E1=dexp(3.9742*Z1/2.) |
203 |
E2=dexp(4.3688*Z2/2.) |
204 |
E3=dexp(1.5176*Z3/2.) |
205 |
HY1=(E1-1.0/E1)/(E1+1.0/E1) |
206 |
HY2=(E2-1.0/E2)/(E2+1.0/E2) |
207 |
HY3=(E3-1.0/E3)/(E3+1.0/E3) |
208 |
SWITCH=(1.0-HY1)*(1.0-HY2)*(1.0-HY3) |
209 |
V123=SWITCH*POLY |
210 |
|
211 |
! write(6,*) v123,V1+V2+V3+V123 |
212 |
|
213 |
Exyz=(V1+V2+V3+V123)/autoeV |
214 |
|
215 |
First=.FALSE. |
216 |
|
217 |
return |
218 |
end function Exyz |
219 |
|
220 |
function Exyz2(natoms,Xyz) |
221 |
|
222 |
IMPLICIT NONE |
223 |
integer, parameter :: KINT = kind(1) |
224 |
integer, parameter :: KREAL = kind(1.0d0) |
225 |
|
226 |
|
227 |
INTEGER(KINT) ,INTENT(IN) :: natoms |
228 |
REAL(KREAL) ,INTENT(IN) :: Xyz(natoms,3) |
229 |
REAL(KREAL) :: Exyz |
230 |
|
231 |
INTEGER(KINT) :: i,j,iat,jat |
232 |
REAL(KREAL) :: Exyz2 |
233 |
|
234 |
real(KREAL) :: autoA,autoeV |
235 |
parameter (autoA=0.52917715d0) |
236 |
parameter (autoeV=27.21183d0) |
237 |
|
238 |
|
239 |
real(KREAL) :: Q(3) |
240 |
real(KREAL) :: TT,gR,pR |
241 |
|
242 |
real(KREAL) :: mB,mC,mH |
243 |
real(KREAL) :: T,RN,RC,r1,r2,r3 |
244 |
|
245 |
real(KREAL) :: Z1,Z12,V1 |
246 |
real(KREAL) :: Z2,Z22,V2 |
247 |
real(KREAL) :: Z3,Z32,V3 |
248 |
|
249 |
real(KREAL) :: S1,S2,S3,S12,S22,S32,POLY |
250 |
real(KREAL) :: E1,E2,E3,HY1,HY2,HY3,SWITCH,V123 |
251 |
|
252 |
Exyz=0. |
253 |
do jat=1,natoms |
254 |
do iat=1,3 |
255 |
Exyz=Exyz+(3*iat-3+jat)*xyz(jat,iat)**2 |
256 |
end do |
257 |
end do |
258 |
|
259 |
Exyz2=Exyz |
260 |
|
261 |
return |
262 |
end function Exyz2 |