root / src / Egrad_baker.f90 @ 5
Historique | Voir | Annoter | Télécharger (12,7 ko)
1 |
subroutine Egrad_baker(E,Geom,Grad,NCoord,IGeom,IOpt,GeomCart,Flag_Opt_Geom,GeomOld,GeomCart_old) |
---|---|
2 |
|
3 |
! This routines calculates the energy E and the gradient Grad of |
4 |
! a molecule with Geometry Geom (may be in internal coordinates), |
5 |
! using for now, either Gaussian or Ext, more general later. |
6 |
|
7 |
use Path_module, only : Nat,AtName,Coord,dzdc,indzmat,Nom,Atome,massat,unit, & |
8 |
prog,NCart,XyzGeomF,IntCoordF,BTransInv, XyzGeomI, & |
9 |
GeomOld_all,BTransInvF,BTransInv_local,UMatF,UMat_local & |
10 |
, BprimT,a0,ScanCoord, Coordinate,NPrim,BMat_BakerT,BBT,BBT_inv & |
11 |
, Order,OrderInv, XPrimitiveF |
12 |
|
13 |
! IntCoordF(NGeomF,NCoord),GeomOld_all(NGeomF,NCoord) |
14 |
! allocated in Path.f90 |
15 |
|
16 |
use Io_module |
17 |
IMPLICIT NONE |
18 |
|
19 |
! Energy (calculated if F300K=.F., else estimated) |
20 |
REAL(KREAL), INTENT (OUT) :: E |
21 |
! NCoord: Number of the degrees of freedom |
22 |
! IGeom: index of the geometry. |
23 |
INTEGER(KINT), INTENT (IN) :: NCoord, IGeom, IOpt |
24 |
! Geometry at which gradient is calculated (cf Factual also): |
25 |
REAL(KREAL), INTENT (INOUT) :: Geom(NCoord) |
26 |
REAL(KREAL), INTENT (INOUT) :: GeomOld(NCoord) |
27 |
! Gradient calculated at Geom geometry: |
28 |
REAL(KREAL), INTENT (OUT) :: Grad(NCoord) |
29 |
! Cartesian geometry corresponding to (Internal Geometry) Geom: |
30 |
REAL(KREAL), INTENT (OUT) :: GeomCart(Nat,3) |
31 |
REAL(KREAL), INTENT (IN) :: GeomCart_old(Nat,3) |
32 |
LOGICAL,INTENT (IN) :: Flag_Opt_Geom |
33 |
|
34 |
! ====================================================================== |
35 |
|
36 |
CHARACTER(LCHARS) :: LINE |
37 |
LOGICAL :: debug |
38 |
LOGICAL, SAVE :: first=.true. |
39 |
LOGICAL, ALLOCATABLE :: Done(:) |
40 |
REAL(KREAL), SAVE :: Eold=1.e6 |
41 |
REAL(KREAL), ALLOCATABLE :: GradTmp(:) |
42 |
REAL(KREAL), ALLOCATABLE :: GradCart(:) |
43 |
REAL(KREAL), ALLOCATABLE :: x(:), y(:), z(:) |
44 |
REAL(KREAL) :: d, a_val, Pi |
45 |
|
46 |
INTEGER(KINT) :: iat, jat, kat, i, j, n3at,IBeg,Idx |
47 |
INTEGER(KINT), PARAMETER :: IOLOG=12, IOCOM=11 |
48 |
|
49 |
CHARACTER(LCHARS) :: ListName, CH32SVAR1 |
50 |
CHARACTER(VLCHARS), SAVE :: RstrtCopy, RunCommand |
51 |
LOGICAL, SAVE :: FCopyRstrt=.False., FOrderChecked=.False. |
52 |
LOGICAL :: FTmp |
53 |
INTEGER(kint) :: NbLists,LastIt,Nat4,NStep, Firstit |
54 |
INTEGER(KINT), PARAMETER :: NbExtName=4 |
55 |
|
56 |
REAL(KREAL), ALLOCATABLE :: XPrimRef(:), XPrim(:) ! NPrim |
57 |
|
58 |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
59 |
! |
60 |
!!!!!!!! PFL Debug |
61 |
! |
62 |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
63 |
REAL(KREAL), ALLOCATABLE :: GeomTmp(:,:) !3,Nat |
64 |
REAL(KREAL), ALLOCATABLE :: V(:,:) ! (NCoord,NCoord) |
65 |
REAL(KREAL), ALLOCATABLE :: XyzTmp(:,:) ! xyzatm(3,nat) |
66 |
REAL(KREAL) :: tol |
67 |
LOGICAL :: FAIL , FALOBBT,FALOBPrimt,FAloBBTInv |
68 |
LOGICAL :: DebugPFL |
69 |
|
70 |
! ====================================================================== |
71 |
LOGICAL, EXTERNAL :: valid |
72 |
! ====================================================================== |
73 |
|
74 |
INTEGER(KINT) :: OptGeom |
75 |
Namelist/path/OptGeom |
76 |
|
77 |
Pi=dacos(-1.0d0) |
78 |
n3at=3*nat |
79 |
|
80 |
debug=valid('EGRAD_baker') |
81 |
debugPFL=valid('bakerPFL') |
82 |
if (debug) WRITE(*,*) '================ Entering Egrad_baker =================' |
83 |
if (debug) Print *, 'EGrad.f90, L73, IOpt=', IOpt, ' Flag_Opt_Geom=',Flag_Opt_Geom |
84 |
|
85 |
Grad=0. |
86 |
E=0. |
87 |
|
88 |
ALLOCATE(GradCart(3*Nat)) |
89 |
ALLOCATE(x(Nat),y(Nat),z(Nat)) |
90 |
ALLOCATE(XPrimRef(NPrim),XPrim(NPrim)) |
91 |
|
92 |
SELECT CASE (COORD) |
93 |
CASE ('ZMAT') |
94 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
95 |
CASE ('BAKER') |
96 |
XPrimRef=XPrimitiveF(IGeom,:) |
97 |
IF (Flag_Opt_Geom) THEN |
98 |
IF (IOpt .EQ. 1) THEN |
99 |
GeomCart(:,1) = XyzGeomI(IGeom,1,:) |
100 |
GeomCart(:,2) = XyzGeomI(IGeom,2,:) |
101 |
GeomCart(:,3) = XyzGeomI(IGeom,3,:) |
102 |
ELSE |
103 |
if (debug) WRITE(*,*) 'Before Call ConvertBakerInternal_cart; L82, Egrad.f90' |
104 |
WRITE(*,*) 'GeomOld=' |
105 |
WRITE(*,'(12(1X,F6.3))') GeomOld |
106 |
WRITE(*,*) 'Geom=' |
107 |
WRITE(*,'(12(1X,F6.3))') Geom |
108 |
WRITE(*,*) 'GeomCart_old=' |
109 |
WRITE(*,'(20(1X,F6.3))') GeomCart_old |
110 |
Call ConvertBakerInternal_cart(GeomOld,Geom,GeomCart_old(:,1), & |
111 |
GeomCart_old(:,2),GeomCart_old(:,3),x,y,z,XPrim,XPrimRef) |
112 |
GeomCart(:,1) = x(:) |
113 |
GeomCart(:,2) = y(:) |
114 |
GeomCart(:,3) = z(:) |
115 |
END IF |
116 |
ELSE |
117 |
IF (IOpt .EQ. 0) THEN |
118 |
GeomCart(:,1) = XyzGeomF(IGeom,1,:) |
119 |
GeomCart(:,2) = XyzGeomF(IGeom,2,:) |
120 |
GeomCart(:,3) = XyzGeomF(IGeom,3,:) |
121 |
ELSE |
122 |
! IntCoordF(NGeomF,NCoord), XyzGeomF(NGeomF,3,Nat) |
123 |
! Geom has to be converted into x,y,z |
124 |
! GeomOld_all and XyzGeomF are old geometry in internal and cartesian coords resp. |
125 |
DO I=1,NCoord ! these variables are used in ConvertBakerInternal_cart() |
126 |
BTransInv_local(I,:) = BTransInvF(IGeom,I,:) |
127 |
UMat_local(:,I) = UMatF(IGeom,:,I) |
128 |
END DO |
129 |
if (debug) Print *, 'I am before Call ConvertBakerInternal_cart; L108, Egrad.f90' |
130 |
WRITE(*,*) 'GeomOld=' |
131 |
WRITE(*,'(12(1X,F6.3))') GeomOld |
132 |
WRITE(*,*) 'Geom=' |
133 |
WRITE(*,'(12(1X,F6.3))') Geom |
134 |
WRITE(*,*) 'DBG Egrad_baker L129 GeomCart_old=' |
135 |
DO I=1,Nat |
136 |
WRITE(*,'(3(1X,F12.8))') XyzGeomF(IGeom,:,I) |
137 |
END DO |
138 |
|
139 |
Call ConvertBakerInternal_cart(GeomOld_all(IGeom,:),Geom,XyzGeomF(IGeom,1,:), & |
140 |
XyzGeomF(IGeom,2,:),XyzGeomF(IGeom,3,:),x,y,z,XPrim,XPrimRef) |
141 |
if (debug) Print *, 'I am after Call ConvertBakerInternal_cart; L111, Egrad.f90' |
142 |
DO I=1,NCoord ! these variables are used in ConvertBakerInternal_cart() |
143 |
BTransInvF(IGeom,I,:) = BTransInv_local(I,:) |
144 |
END DO |
145 |
! GeomCart is actually XyzCoord and has INTENT(OUT) in this subroutine. |
146 |
GeomCart(:,1) = x(:) |
147 |
GeomCart(:,2) = y(:) |
148 |
GeomCart(:,3) = z(:) |
149 |
END IF ! matches IF (IOpt .EQ. 0) THEN |
150 |
END IF |
151 |
CASE ('MIXED') |
152 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
153 |
CASE ('CART') |
154 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
155 |
CASE ('HYBRID') |
156 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
157 |
CASE DEFAULT |
158 |
WRITE (*,*) "Coord=",TRIM(COORD)," not recognized. Stop" |
159 |
STOP |
160 |
END SELECT |
161 |
!WRITE(*,*) Nat |
162 |
!WRITE(*,*) 'GeomCart in Egrad_baker' |
163 |
!DO I=1,Nat |
164 |
! WRITE(*,'(1X,A,3(1X,F12.8))') AtName(I),GeomCart(I,1:3) |
165 |
!END DO |
166 |
|
167 |
SELECT CASE (Prog) |
168 |
CASE ('GAUSSIAN') |
169 |
! we call the Gaussian routine. |
170 |
! it will return the energy and the gradient in cartesian coordinates. |
171 |
! Gradient calculated at GeomCart geometry and stored in GradCart, which has INTENT(OUT) |
172 |
Call egrad_gaussian(E,GeomCart,GradCart) |
173 |
CASE ('MOPAC') |
174 |
! we call the Mopac routine. |
175 |
! it will return the energy and the gradient in cartesian coordinates. |
176 |
! Gradient calculated at GeomCart geometry and stored in GradCart, which has INTENT(OUT) |
177 |
Call egrad_mopac(E,GeomCart,GradCart) |
178 |
CASE ('VASP') |
179 |
Call egrad_vasp(E,Geomcart,GradCart) |
180 |
CASE ('TURBOMOLE') |
181 |
Call egrad_turbomole(E,Geomcart,GradCart) |
182 |
CASE ('EXT') |
183 |
Call egrad_ext(E,Geomcart,GradCart) |
184 |
CASE ('TEST') |
185 |
Call egrad_test(Nat,E,Geomcart,GradCart) |
186 |
CASE ('CHAMFRE') |
187 |
Call egrad_chamfre(Nat,E,Geomcart,GradCart) |
188 |
END SELECT |
189 |
if (debug) THEN |
190 |
WRITE(*,*) 'DBG EGRAD, GradCart read' |
191 |
DO Iat=1,Nat |
192 |
WRITE(*,'(1X,A10,3(1X,F15.8),A)') Trim(AtName(Iat)),GradCart(3*Iat-2:3*Iat) |
193 |
END DO |
194 |
END IF |
195 |
|
196 |
! If (PROG=="VASP") STOP |
197 |
|
198 |
! We have the gradient in Cartesian coordinates... which is ok for COORD=Cart, Hybrid |
199 |
! but we have to convert it into Zmat if COORD=Zmat |
200 |
SELECT CASE (COORD) |
201 |
CASE ("ZMAT") |
202 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
203 |
CASE ('BAKER') |
204 |
! We have the gradient in Cartesian coordinates... which is ok for COORD=Cart, Hybrid |
205 |
! but we have to convert it into internal coordinates if COORD=Baker |
206 |
!!!!!!!!!!!!!!!!!!!! |
207 |
! |
208 |
! PFL Debug |
209 |
! |
210 |
!!!!!!!!!!!!!!!!!!!! |
211 |
if (debugPFL) THEN |
212 |
WRITE(*,*) "DBG PFL Egrad_Baker... computing dzdc" |
213 |
if (.not.ALLOCATED(indzmat)) THEN |
214 |
ALLOCATE(indzmat(Nat,5)) |
215 |
IndZmat=0 |
216 |
Indzmat(1,1)=1 |
217 |
IndZmat(2,1)=2 |
218 |
IndZmat(2,2)=1 |
219 |
IndZmat(3,1)=3 |
220 |
IndZmat(3,2)=2 |
221 |
IndZmat(3,3)=1 |
222 |
IndZmat(4,1)=4 |
223 |
IndZmat(4,2)=3 |
224 |
IndZmat(4,3)=2 |
225 |
IndZmat(4,4)=1 |
226 |
END IF |
227 |
IF (.NOT.ALLOCATED(DzDc)) THEN |
228 |
ALLOCATE(DzDc(3,nat,3,Nat)) |
229 |
END IF |
230 |
if (.NOT.Allocated(GeomTmp)) Allocate(GeomTmp(3,Nat)) |
231 |
DO I=1,Nat |
232 |
GeomTmp(1,I)=GeomCart(OrderInv(I),1) |
233 |
GeomTmp(2,I)=GeomCart(OrderInv(i),2) |
234 |
GeomTmp(3,I)=GeomCart(OrderInv(i),3) |
235 |
END DO |
236 |
|
237 |
DzDc=0.d0 |
238 |
CALL CalcBMat_int (nat, GeomTmp, indzmat, dzdc, massat,atome) |
239 |
|
240 |
END IF ! if (debugPFL) |
241 |
!!!!!!!!!!!!!!!!!!!!!!!!! |
242 |
! Debugging PFL |
243 |
!!!!!!!!!!!!!!!!!!!!!!!! |
244 |
|
245 |
WRITE(*,*) "BTransInv_local Trans that is used originally" |
246 |
DO J=1,3*Nat |
247 |
WRITE(*,'(50(1X,F12.8))') BTransInv_local(:,J) |
248 |
END DO |
249 |
|
250 |
WRITE(*,*) "Calculating actual values using GeomCart" |
251 |
if (.NOT.Allocated(GeomTmp)) Allocate(GeomTmp(3,Nat)) |
252 |
GeomTmp(1,:)=GeomCart(1:Nat,1) |
253 |
GeomTmp(2,:)=GeomCart(1:Nat,2) |
254 |
GeomTmp(3,:)=GeomCart(1:Nat,3) |
255 |
|
256 |
! Computing B^prim: |
257 |
FAloBBT=.NOT.ALLOCATED(BBT) |
258 |
FAloBBTInv=.NOT.ALLOCATED(BBT_inv) |
259 |
FAloBPrimT=.NOT.ALLOCATED(BprimT) |
260 |
if (FAloBPrimT) ALLOCATE(Bprimt(3*Nat,NPrim)) |
261 |
if (FAloBBT) ALLOCATE(BBt(NCoord,NCoord)) |
262 |
if (FAloBBTInv) ALLOCATE(BBt_inv(NCoord,NCoord)) |
263 |
BprimT=0.d0 |
264 |
ScanCoord=>Coordinate |
265 |
I=0 |
266 |
DO WHILE (Associated(ScanCoord%next)) |
267 |
I=I+1 |
268 |
SELECT CASE (ScanCoord%Type) |
269 |
CASE ('BOND') |
270 |
CALL CONSTRAINTS_BONDLENGTH_DER(Nat,ScanCoord%at1,ScanCoord%AT2,GeomTmp,BprimT(1,I)) |
271 |
CASE ('ANGLE') |
272 |
CALL CONSTRAINTS_BONDANGLE_DER(Nat,ScanCoord%At1,ScanCoord%AT2,ScanCoord%At3,GeomTmp,BprimT(1,I)) |
273 |
CASE ('DIHEDRAL') |
274 |
CALL CONSTRAINTS_TORSION_DER2(Nat,ScanCoord%At1,ScanCoord%AT2,ScanCoord%At3,ScanCoord%At4,GeomTmp,BprimT(1,I)) |
275 |
END SELECT |
276 |
ScanCoord => ScanCoord%next |
277 |
END DO |
278 |
|
279 |
if (debug) THEN |
280 |
WRITE(*,*) "Bprim " |
281 |
DO J=1,3*Nat |
282 |
WRITE(*,'(50(1X,F12.6))') BprimT(J,:) |
283 |
END DO |
284 |
END IF |
285 |
|
286 |
BMat_BakerT = 0.d0 |
287 |
DO I=1,NCoord |
288 |
DO J=1,NPrim |
289 |
!BprimT is transpose of B^prim. |
290 |
!B = UMat^T B^prim, B^T = (B^prim)^T UMat |
291 |
BMat_BakerT(:,I)=BMat_BakerT(:,I)+BprimT(:,J)*UMat_local(J,I) |
292 |
END DO |
293 |
END DO |
294 |
|
295 |
BBT = 0.d0 |
296 |
DO I=1,NCoord |
297 |
DO J=1,3*Nat ! BBT(:,I) forms BB^T |
298 |
BBT(:,I) = BBT(:,I) + BMat_BakerT(J,:)*BMat_BakerT(J,I) |
299 |
END DO |
300 |
END DO |
301 |
|
302 |
BBT_inv = 0.d0 |
303 |
|
304 |
Call GenInv(NCoord,BBT,BBT_inv,NCoord) |
305 |
|
306 |
! ALLOCATE(V(NCoord,NCoord)) |
307 |
! tol = 1e-10 |
308 |
! ! BBT is destroyed by GINVSE |
309 |
! Call GINVSE(BBT,NCoord,NCoord,BBT_inv,NCoord,NCoord,NCoord,tol,V,NCoord,FAIL,IOOUT) |
310 |
! DEALLOCATE(V) |
311 |
! IF(Fail) Then |
312 |
! WRITE (*,*) "Failed in generalized inverse, L220, ConvertBaker...f90" |
313 |
! STOP |
314 |
! END IF |
315 |
|
316 |
!Print *, 'BBT_inv=' |
317 |
DO J=1,NCoord |
318 |
! WRITE(*,'(50(1X,F10.2))') BBT_inv(:,J) |
319 |
! Print *, BBT_inv(:,J) |
320 |
END DO |
321 |
!Print *, 'End of BBT_inv' |
322 |
|
323 |
! Calculation of (B^T)^-1 = (BB^T)^-1B: |
324 |
BTransInv_local = 0.d0 |
325 |
DO I=1,3*Nat |
326 |
DO J=1,NCoord |
327 |
BTransInv_local(:,I)=BTransInv_local(:,I)+BBT_inv(:,J)*BMat_BakerT(I,J) |
328 |
END DO |
329 |
END DO |
330 |
|
331 |
Print *, 'BMat_BakerT=' |
332 |
DO J=1,3*Nat |
333 |
WRITE(*,'(50(1X,F12.8))') BMat_BakerT(:,J) |
334 |
END DO |
335 |
|
336 |
WRITE(*,*) "BTransInv_local Trans corresponding to GeomCart" |
337 |
DO J=1,3*Nat |
338 |
WRITE(*,'(50(1X,F12.8))') BTransInv_local(:,J) |
339 |
END DO |
340 |
|
341 |
if (FAloBPrimT) DEALLOCATE(Bprimt) |
342 |
if (FAloBBT) DEALLOCATE(BBt) |
343 |
if (FAloBBTInv) DEALLOCATE(BBt_inv) |
344 |
|
345 |
Grad=0.d0 |
346 |
DO I=1, 3*Nat |
347 |
! Here Grad is gradient in Baker coordinates. GradCart(3*Nat) |
348 |
Grad(:) = Grad(:) + BTransInv_local(:,I)*GradCart(I) !BTransInv_local = BTransInv in Opt_Geom.f90 |
349 |
END DO |
350 |
!WRITE(*,*) 'In Egrad.f90, L263, Gradient:' |
351 |
!WRITE(*,'(12(1X,F8.4))') Grad(1:NCoord) |
352 |
CASE ('MIXED') |
353 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
354 |
CASE ("CART","HYBRID") |
355 |
WRITE (*,*) "Coord=",TRIM(COORD),": use Egrad.f90, instead of Egrad_baker.f90. Stop" |
356 |
CASE DEFAULT |
357 |
WRITE(*,*) "Coord=",AdjustL(Trim(COORD))," not yet implemented in Egradients. STOP" |
358 |
STOP |
359 |
END SELECT |
360 |
|
361 |
DEALLOCATE(GradCart) |
362 |
DEALLOCATE(x,y,z) |
363 |
IF (Debug) WRITE(*,*) 'DBG EGRAD_baker grad',grad(1:NCoord) |
364 |
|
365 |
if (debug) WRITE(*,*) '================ Egrad_baker Over ====================' |
366 |
|
367 |
!999 CONTINUE |
368 |
!if (.NOT.Ftmp) WRITE(*,*) 'We should not be here !!!!' |
369 |
!STOP |
370 |
! ====================================================================== |
371 |
end subroutine Egrad_baker |
372 |
|