root / src / Extrapol_int.f90 @ 1
Historique | Voir | Annoter | Télécharger (16,56 ko)
1 | 1 | equemene | SUBROUTINE Extrapol_int(iopt,s,dist,x0,y0,z0,xgeom,Coef,XgeomF) |
---|---|---|---|
2 | 1 | equemene | |
3 | 1 | equemene | ! This subroutine constructs the path, and if dist<>Infinity, it samples |
4 | 1 | equemene | ! the path to obtain geometries. |
5 | 1 | equemene | ! Basically, you call it twice: i) dist=infinity, it will calculate the length of the path |
6 | 1 | equemene | ! ii) dist finite, it will give you the images you want along the path. |
7 | 1 | equemene | ! |
8 | 1 | equemene | ! For now, it gives equidistant geometries |
9 | 1 | equemene | ! |
10 | 1 | equemene | |
11 | 1 | equemene | ! Default value of FRot=.TRUE. |
12 | 1 | equemene | ! Default value of NMaxPtPath = 1000 |
13 | 1 | equemene | ! IntCoordI(:,:) ! (NGeomI,3*Nat-6) |
14 | 1 | equemene | ! XyzGeomF(:,:,:) ! (NGeomF,3,Nat) |
15 | 1 | equemene | ! Default value of FAlign=.TRUE. |
16 | 1 | equemene | use Path_module, only : NMaxPtPath, IntCoordI, Pi, IndZmat, XyzGeomF, & |
17 | 1 | equemene | IntCoordF, IntTangent, Renum, Nom, Order, MassAt, SGeom, XyzGeomI, & |
18 | 1 | equemene | Atome, Nat, NGeomI, NCoord, NGeomF, OrderInv,NFroz,FrozAtoms |
19 | 1 | equemene | ! IndZmat(Nat,5) |
20 | 1 | equemene | |
21 | 1 | equemene | use Io_module |
22 | 1 | equemene | |
23 | 1 | equemene | |
24 | 1 | equemene | IMPLICIT NONE |
25 | 1 | equemene | |
26 | 1 | equemene | |
27 | 1 | equemene | REAL(KREAL), INTENT(OUT) :: s |
28 | 1 | equemene | ! X0(Nat),Y0(Nat),Z0(Nat): reference geometry. |
29 | 1 | equemene | REAL(KREAL), INTENT(IN) :: dist,X0(Nat),Y0(Nat),Z0(Nat) |
30 | 1 | equemene | REAL(KREAL), INTENT(IN) :: Xgeom(NGeomI),Coef(NGeomI,NCoord) |
31 | 1 | equemene | ! Iopt: Number of the cycles for the optimization |
32 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: Iopt |
33 | 1 | equemene | REAL(KREAL), INTENT(OUT) :: XGeomF(NGeomF) |
34 | 1 | equemene | |
35 | 1 | equemene | INTEGER(KINT) :: IdxGeom, I, J, K, Idx |
36 | 1 | equemene | REAL(KREAL) :: Rmsd,MRot(3,3), ds, u, v |
37 | 1 | equemene | REAL(KREAL) :: a_val, d |
38 | 1 | equemene | |
39 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: XyzTmp(:,:), XyzTmp2(:,:) ! (Nat,3) |
40 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: ValZmat(:,:),DerInt(:) ! (Nat,3) |
41 | 1 | equemene | |
42 | 1 | equemene | |
43 | 1 | equemene | LOGICAL :: debug, print,printspline |
44 | 1 | equemene | LOGICAL, EXTERNAL :: valid |
45 | 1 | equemene | |
46 | 1 | equemene | INTEGER(KINT) :: NSpline |
47 | 1 | equemene | CHARACTER(LCHARS) :: FileSpline,TmpChar |
48 | 1 | equemene | |
49 | 1 | equemene | |
50 | 1 | equemene | ! LOGICAL :: FAlign=.FALSE., FRot=.FALSE. |
51 | 1 | equemene | |
52 | 1 | equemene | ! We will calculate the length of the path, in MW coordinates... |
53 | 1 | equemene | ! this is done is a stupid way: we interpolate the zmatrix values, |
54 | 1 | equemene | ! convert them into cartesian, weight the cartesian |
55 | 1 | equemene | ! and calculate the evolution of the distance ! |
56 | 1 | equemene | ! We have to follow the same procedure for every geometry |
57 | 1 | equemene | ! so even for the first one, we have to convert it from zmat |
58 | 1 | equemene | ! to cartesian ! |
59 | 1 | equemene | |
60 | 1 | equemene | debug=valid("pathcreate") |
61 | 1 | equemene | print=valid("printgeom") |
62 | 1 | equemene | printspline=(valid("printspline").AND.(dist<=1e30)) |
63 | 1 | equemene | |
64 | 1 | equemene | if (debug) Call Header("Entering Extrapol_int") |
65 | 1 | equemene | |
66 | 1 | equemene | ! We want 100 points along the interpolating path |
67 | 1 | equemene | NSpline=int(NMaxPtPath/100) |
68 | 1 | equemene | if (printspline) THEN |
69 | 1 | equemene | WRITE(TmpChar,'(I5)') Iopt |
70 | 1 | equemene | FileSpline=Trim(adjustL(PathName)) // '_spline.' // AdjustL(TRIM(TmpChar)) |
71 | 1 | equemene | OPEN(IOTMP,FILE=FileSpline) |
72 | 1 | equemene | |
73 | 1 | equemene | END IF |
74 | 1 | equemene | |
75 | 1 | equemene | ALLOCATE(XyzTmp(Nat,3),XyzTmp2(Nat,3),valzmat(Nat,3),DerInt(NCoord)) |
76 | 1 | equemene | IdxGeom=1 |
77 | 1 | equemene | |
78 | 1 | equemene | XYZTmp2(1,1)=0. |
79 | 1 | equemene | XYZTmp2(1,2)=0. |
80 | 1 | equemene | XYZTmp2(1,3)=0. |
81 | 1 | equemene | XYZTmp2(2,2)=0. |
82 | 1 | equemene | XYZTmp2(2,3)=0. |
83 | 1 | equemene | XYZTmp2(3,3)=0. |
84 | 1 | equemene | |
85 | 1 | equemene | valzmat=0. |
86 | 1 | equemene | valzmat(2,1)=IntCoordI(1,1) |
87 | 1 | equemene | valzmat(3,1)=IntCoordI(1,2) |
88 | 1 | equemene | valzmat(3,2)=IntCoordI(1,3)*180./Pi |
89 | 1 | equemene | Idx=4 |
90 | 1 | equemene | DO I=4,Nat |
91 | 1 | equemene | ValZmat(I,1)=IntCoordI(1,Idx) |
92 | 1 | equemene | Idx=Idx+1 |
93 | 1 | equemene | DO J=2,3 |
94 | 1 | equemene | ValZmat(I,J)=IntCoordI(1,Idx)*180./Pi |
95 | 1 | equemene | Idx=Idx+1 |
96 | 1 | equemene | END DO |
97 | 1 | equemene | END DO |
98 | 1 | equemene | |
99 | 1 | equemene | XyzTmp2(2,1)=valzmat(2,1) |
100 | 1 | equemene | d=valzmat(3,1) |
101 | 1 | equemene | a_val=valzmat(3,2)/180.*Pi |
102 | 1 | equemene | ! write(*,*) "aval,pi",a_val,valzmat(3,2),pi |
103 | 1 | equemene | if (Nat.GE.3) THEN |
104 | 1 | equemene | if (IndZmat(3,2).EQ.1) THEN |
105 | 1 | equemene | XyzTmp2(3,1)=XYzTmp2(1,1)+d*cos(a_val) |
106 | 1 | equemene | ELSE |
107 | 1 | equemene | XyzTmp2(3,1)=XyzTmp2(2,1)-d*cos(a_val) |
108 | 1 | equemene | ENDIF |
109 | 1 | equemene | XyzTmp2(3,2)=d*sin(a_val) |
110 | 1 | equemene | ENDIF |
111 | 1 | equemene | ! i=1 |
112 | 1 | equemene | ! WRITE(*,*) 'TOTOCart:',i, (XYzTMP2(I,J),J=1,3) |
113 | 1 | equemene | ! WRITE(*,*) 'TOTOZma:',i, (valzmat(I,J),J=1,3) |
114 | 1 | equemene | ! i=2 |
115 | 1 | equemene | ! WRITE(*,*) 'TOTOCart:',i, (XYzTMP2(I,J),J=1,3) |
116 | 1 | equemene | ! WRITE(*,*) 'TOTOZma:',i, (valzmat(I,J),J=1,3) |
117 | 1 | equemene | ! i=3 |
118 | 1 | equemene | ! WRITE(*,*) 'TOTOCart:',i, (XYzTMP2(I,J),J=1,3) |
119 | 1 | equemene | ! WRITE(*,*) 'TOTOZma:',i, (valzmat(I,J),J=1,3) |
120 | 1 | equemene | |
121 | 1 | equemene | DO i=4,Nat |
122 | 1 | equemene | call ConvertZmat_cart(i,IndZmat,valzmat, & |
123 | 1 | equemene | XYzTMP2(1,1), XYzTMP2(1,2),XYzTMP2(1,3)) |
124 | 1 | equemene | ! WRITE(*,*) 'TOTOZma:',i,IndZmat(I,1), & |
125 | 1 | equemene | ! (IndZmat(I,J+1),valzmat(I,J),J=1,3) |
126 | 1 | equemene | ! WRITE(*,*) 'TOTOCart:',i, (XYzTMP2(I,J),J=1,3) |
127 | 1 | equemene | END DO |
128 | 1 | equemene | |
129 | 1 | equemene | ! We align this geometry with the original one |
130 | 1 | equemene | ! PFL 17/July/2006: only if we have more than 4 atoms. |
131 | 1 | equemene | IF (Nat.GE.4) THEN |
132 | 1 | equemene | ! The rotation matrix MRot has INTENT(OUT) in subroutine rotation_matrix(...), |
133 | 1 | equemene | ! which is called in the CalcRmsd(...). |
134 | 1 | equemene | ! PFL 24 Nov 2008 -> |
135 | 1 | equemene | ! If we have frozen atoms we align only those ones. |
136 | 1 | equemene | if (NFroz.GT.0) THEN |
137 | 1 | equemene | Call AlignPartial(Nat,x0,y0,z0, & |
138 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
139 | 1 | equemene | FrozAtoms,MRot) |
140 | 1 | equemene | ELSE |
141 | 1 | equemene | Call CalcRmsd(Nat, x0,y0,z0, & |
142 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
143 | 1 | equemene | MRot,rmsd,.TRUE.,.TRUE.) |
144 | 1 | equemene | END IF |
145 | 1 | equemene | ! <- PFL 24 Nov 2008 |
146 | 1 | equemene | END IF |
147 | 1 | equemene | |
148 | 1 | equemene | XyzGeomF(IdxGeom,:,:)=Reshape(XyzTmp2(:,:),(/3,Nat/),ORDER=(/2,1/)) |
149 | 1 | equemene | IntCoordF(IdxGeom,:)=IntCoordI(1,:) |
150 | 1 | equemene | |
151 | 1 | equemene | ! We calculate the first derivatives |
152 | 1 | equemene | u=0.d0 |
153 | 1 | equemene | DO Idx=1,NCoord |
154 | 1 | equemene | call splintder(u,v,DerInt(iDX),NGeomI,xgeom(1),IntCoordI(1,Idx),Coef(1,Idx)) |
155 | 1 | equemene | END DO |
156 | 1 | equemene | IntTangent(IdxGeom,:)=DerInt |
157 | 1 | equemene | |
158 | 1 | equemene | if (print.AND.(Dist.LE.1e20)) THEN |
159 | 1 | equemene | WRITE(IOOUT,'(1X,I5)') Nat |
160 | 1 | equemene | WRITE(IOOUT,*) "# Cartesian Coordinates for geom",IdxGeom |
161 | 1 | equemene | DO i=1,Nat |
162 | 1 | equemene | If (Renum) THEN |
163 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(I)), & |
164 | 1 | equemene | (XyzTmp2(Order(I),J),J=1,3) |
165 | 1 | equemene | ELSE |
166 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(OrderInv(I))), & |
167 | 1 | equemene | (XyzTmp2(I,J),J=1,3) |
168 | 1 | equemene | END IF |
169 | 1 | equemene | END DO |
170 | 1 | equemene | END IF |
171 | 1 | equemene | |
172 | 1 | equemene | ! We initialize the first geometry |
173 | 1 | equemene | ! PFL 26 Nov 2008 -> |
174 | 1 | equemene | ! Now, I copy XyzTmp2 into XyzTmp because XyzTmp2 has been aligned |
175 | 1 | equemene | ! with the reference geometry |
176 | 1 | equemene | |
177 | 1 | equemene | XyzTmp=XyzTmp2 |
178 | 1 | equemene | |
179 | 1 | equemene | ! XyzTmp(1,1)=0. |
180 | 1 | equemene | ! XyzTmp(1,2)=0. |
181 | 1 | equemene | ! XyzTmp(1,3)=0. |
182 | 1 | equemene | ! XyzTmp(2,2)=0. |
183 | 1 | equemene | ! XyzTmp(2,3)=0. |
184 | 1 | equemene | ! XyzTmp(3,3)=0. |
185 | 1 | equemene | |
186 | 1 | equemene | ! XyzTmp(2,1)=valzmat(2,1) |
187 | 1 | equemene | ! d=valzmat(3,1) |
188 | 1 | equemene | ! a_val=valzmat(3,2)/180.*Pi |
189 | 1 | equemene | |
190 | 1 | equemene | ! if (Nat.GE.3) THEN |
191 | 1 | equemene | ! if (IndZmat(3,2).EQ.1) THEN |
192 | 1 | equemene | ! XyzTmp(3,1)=XYzTmp(1,1)+d*cos(a_val) |
193 | 1 | equemene | ! ELSE |
194 | 1 | equemene | ! XyzTmp(3,1)=XyzTmp(2,1)-d*cos(a_val) |
195 | 1 | equemene | ! ENDIF |
196 | 1 | equemene | ! XyzTmp(3,2)=d*sin(a_val) |
197 | 1 | equemene | ! ENDIF |
198 | 1 | equemene | |
199 | 1 | equemene | ! DO i=4,Nat |
200 | 1 | equemene | ! call ConvertZmat_cart(i,IndZmat,valzmat, & |
201 | 1 | equemene | ! XYzTMP(1,1), XYzTMP(1,2),XYzTMP(1,3)) |
202 | 1 | equemene | ! END DO |
203 | 1 | equemene | |
204 | 1 | equemene | ! <- PFL 26 Nov 2008 |
205 | 1 | equemene | |
206 | 1 | equemene | s=0. |
207 | 1 | equemene | if (printspline) THEN |
208 | 1 | equemene | SELECT CASE (Nat) |
209 | 1 | equemene | CASE(2) |
210 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1) |
211 | 1 | equemene | CASE (3) |
212 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2) |
213 | 1 | equemene | CASE(4:) |
214 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2),valzmat(4:Nat,1:3) |
215 | 1 | equemene | END SELECT |
216 | 1 | equemene | END IF |
217 | 1 | equemene | valzmat=0.d0 |
218 | 1 | equemene | |
219 | 1 | equemene | DO K=1,NMaxPtPath |
220 | 1 | equemene | u=real(K)/NMaxPtPath*(NGeomI-1.) |
221 | 1 | equemene | |
222 | 1 | equemene | XYZTmp2(1,1)=0. |
223 | 1 | equemene | XYZTmp2(1,2)=0. |
224 | 1 | equemene | XYZTmp2(1,3)=0. |
225 | 1 | equemene | XYZTmp2(2,2)=0. |
226 | 1 | equemene | XYZTmp2(2,3)=0. |
227 | 1 | equemene | XYZTmp2(3,3)=0. |
228 | 1 | equemene | |
229 | 1 | equemene | ! We generate the interpolated Zmatrix |
230 | 1 | equemene | call splintder(u,v,DerInt(1),NGeomI,xgeom(1),IntCoordI(1,1),Coef(1,1)) |
231 | 1 | equemene | valzmat(2,1)=v |
232 | 1 | equemene | call splintder(u,v,DerInt(2),NGeomI,xgeom(1),IntCoordI(1,2),Coef(1,2)) |
233 | 1 | equemene | valzmat(3,1)=v |
234 | 1 | equemene | call splintder(u,v,DerInt(3),NGeomI,xgeom(1),IntCoordI(1,3),Coef(1,3)) |
235 | 1 | equemene | valzmat(3,2)=v*180./Pi |
236 | 1 | equemene | Idx=4 |
237 | 1 | equemene | DO I=4,Nat |
238 | 1 | equemene | call splintder(u,v,DerInt(Idx),NGeomI,xgeom(1),IntCoordI(1,Idx),Coef(1,Idx)) |
239 | 1 | equemene | valzmat(I,1)=v |
240 | 1 | equemene | Idx=Idx+1 |
241 | 1 | equemene | DO J=2,3 |
242 | 1 | equemene | call splintder(u,v,DerInt(Idx),NGeomI,xgeom(1),IntCoordI(1,Idx),Coef(1,Idx)) |
243 | 1 | equemene | valzmat(I,J)=v*180./pi |
244 | 1 | equemene | Idx=Idx+1 |
245 | 1 | equemene | END DO |
246 | 1 | equemene | END DO ! matches DO I=4,Nat |
247 | 1 | equemene | |
248 | 1 | equemene | ! We convert it into Cartesian coordinates |
249 | 1 | equemene | XyzTmp2(2,1)=valzmat(2,1) |
250 | 1 | equemene | d=valzmat(3,1) |
251 | 1 | equemene | a_val=valzmat(3,2)/180.*Pi |
252 | 1 | equemene | if (Nat.GE.3) THEN |
253 | 1 | equemene | if (IndZmat(3,2).EQ.1) THEN |
254 | 1 | equemene | XyzTmp2(3,1)=XYzTmp2(1,1)+d*cos(a_val) |
255 | 1 | equemene | ELSE |
256 | 1 | equemene | XyzTmp2(3,1)=XyzTmp2(2,1)-d*cos(a_val) |
257 | 1 | equemene | ENDIF |
258 | 1 | equemene | XyzTmp2(3,2)=d*sin(a_val) |
259 | 1 | equemene | ENDIF |
260 | 1 | equemene | |
261 | 1 | equemene | DO I=4,Nat |
262 | 1 | equemene | call ConvertZmat_cart(I,IndZmat,valzmat, & |
263 | 1 | equemene | XYzTMP2(1,1), XYzTMP2(1,2),XYzTMP2(1,3)) |
264 | 1 | equemene | END DO |
265 | 1 | equemene | |
266 | 1 | equemene | IF (Nat.GE.4) THEN |
267 | 1 | equemene | ! PFL 24 Nov 2008 -> |
268 | 1 | equemene | ! If we have frozen atoms we align only those ones. |
269 | 1 | equemene | if (NFroz.GT.0) THEN |
270 | 1 | equemene | Call AlignPartial(Nat,x0,y0,z0, & |
271 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
272 | 1 | equemene | FrozAtoms,MRot) |
273 | 1 | equemene | ELSE |
274 | 1 | equemene | ! PFL 26 Nov 2008! |
275 | 1 | equemene | ! Note to myself: in Extrapol_cart we always align on x0,y0,z0 but here |
276 | 1 | equemene | ! we align on the previous geom... what is the best ? Is there a difference ? |
277 | 1 | equemene | Call CalcRmsd(Nat, XyzTmp(1:Nat,1),XyzTmp(1:Nat,2),XyzTmp(1:Nat,3), & |
278 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
279 | 1 | equemene | MRot,rmsd,.TRUE.,.TRUE.) |
280 | 1 | equemene | END IF |
281 | 1 | equemene | ! <- PFL 24 Nov 2008 |
282 | 1 | equemene | END IF |
283 | 1 | equemene | |
284 | 1 | equemene | ds=0. |
285 | 1 | equemene | DO I=1,Nat |
286 | 1 | equemene | DO J=1,3 |
287 | 1 | equemene | ds=ds+MassAt(I)*(XYZTMp2(I,J)-XYZTmp(I,J))**2 |
288 | 1 | equemene | XYZTmp(I,J)=XyzTMP2(I,J) |
289 | 1 | equemene | END DO |
290 | 1 | equemene | END DO |
291 | 1 | equemene | |
292 | 1 | equemene | |
293 | 1 | equemene | s=s+sqrt(ds) |
294 | 1 | equemene | |
295 | 1 | equemene | if ((printspline).AND.(MOD(K,NSpline).EQ.0)) THEN |
296 | 1 | equemene | SELECT CASE (Nat) |
297 | 1 | equemene | CASE(2) |
298 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1) |
299 | 1 | equemene | CASE (3) |
300 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2) |
301 | 1 | equemene | CASE(4:) |
302 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2),valzmat(4:Nat,1:3) |
303 | 1 | equemene | END SELECT |
304 | 1 | equemene | END IF |
305 | 1 | equemene | |
306 | 1 | equemene | ! if (debug) WRITE(*,*) "Debug u,s,dist",u,s,dist |
307 | 1 | equemene | if (s>=dist) THEN |
308 | 1 | equemene | if (debug) THEN |
309 | 1 | equemene | WRITE(*,*) "DBG Zmat",s |
310 | 1 | equemene | WRITE(*,'(1X,I5)') IndZmat(1,1) |
311 | 1 | equemene | WRITE(*,'(1X,I5,I5,1X,F10.4)') IndZmat(2,1),IndZmat(2,2),valzmat(2,1) |
312 | 1 | equemene | WRITE(*,'(1X,I5,2(I5,1X,F10.4))') IndZmat(3,1),IndZmat(3,2),valzmat(3,1) & |
313 | 1 | equemene | ,IndZmat(3,3),valzmat(3,2) |
314 | 1 | equemene | DO I=4,Nat |
315 | 1 | equemene | WRITE(*,'(1X,I5,3(I5,1X,F10.4))') IndZmat(I,1),IndZmat(I,2),valzmat(I,1) & |
316 | 1 | equemene | ,IndZmat(I,3),valzmat(I,2),IndZmat(I,4),valzmat(I,3) |
317 | 1 | equemene | END DO |
318 | 1 | equemene | END IF ! matches if (debug) THEN |
319 | 1 | equemene | |
320 | 1 | equemene | s=s-dist |
321 | 1 | equemene | IdxGeom=IdxGeom+1 |
322 | 1 | equemene | SGeom(IdxGeom)=s+IdxGeom*dist |
323 | 1 | equemene | XgeomF(IdxGeom)=u |
324 | 1 | equemene | XyzGeomF(IdxGeom,:,:)=Reshape(XyzTmp2(:,:),(/3,Nat/),ORDER=(/2,1/)) |
325 | 1 | equemene | IntCoordF(IdxGeom,1)=valzmat(2,1) |
326 | 1 | equemene | IntCoordF(IdxGeom,2)=valzmat(3,1) |
327 | 1 | equemene | IntCoordF(IdxGeom,3)=valzmat(3,2)/180.*Pi |
328 | 1 | equemene | Idx=4 |
329 | 1 | equemene | DO I=4,Nat |
330 | 1 | equemene | IntCoordF(IdxGeom,Idx)=valzmat(I,1) |
331 | 1 | equemene | IntCoordF(IdxGeom,Idx+1)=valzmat(I,2)/180.*Pi |
332 | 1 | equemene | IntCoordF(IdxGeom,Idx+2)=valzmat(I,3)/180.*Pi |
333 | 1 | equemene | Idx=Idx+3 |
334 | 1 | equemene | END DO |
335 | 1 | equemene | IntTangent(IdxGeom,:)=DerInt |
336 | 1 | equemene | |
337 | 1 | equemene | if (print) THEN |
338 | 1 | equemene | WRITE(IOOUT,'(1X,I5)') Nat |
339 | 1 | equemene | WRITE(IOOUT,*) "# Cartesian coord for Geometry ",IdxGeom,K |
340 | 1 | equemene | ! PFL 17/July/2006: only if we have more than 4 atoms. |
341 | 1 | equemene | IF (Nat.GE.4) THEN |
342 | 1 | equemene | ! PFL 24 Nov 2008 -> |
343 | 1 | equemene | ! If we have frozen atoms we align only those ones. |
344 | 1 | equemene | if (NFroz.GT.0) THEN |
345 | 1 | equemene | Call AlignPartial(Nat,x0,y0,z0, & |
346 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
347 | 1 | equemene | FrozAtoms,MRot) |
348 | 1 | equemene | ELSE |
349 | 1 | equemene | Call CalcRmsd(Nat, x0,y0,z0, & |
350 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
351 | 1 | equemene | MRot,rmsd,.TRUE.,.TRUE.) |
352 | 1 | equemene | END IF |
353 | 1 | equemene | ! <- PFL 24 Nov 2008 |
354 | 1 | equemene | |
355 | 1 | equemene | END IF |
356 | 1 | equemene | |
357 | 1 | equemene | DO I=1,Nat |
358 | 1 | equemene | If (Renum) THEN |
359 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(I)), & |
360 | 1 | equemene | (XyzTmp2(Order(I),J),J=1,3) |
361 | 1 | equemene | ELSE |
362 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(OrderInv(I))), & |
363 | 1 | equemene | (XyzTmp2(I,J),J=1,3) |
364 | 1 | equemene | END IF |
365 | 1 | equemene | END DO |
366 | 1 | equemene | |
367 | 1 | equemene | END IF ! matches if (print) THEN |
368 | 1 | equemene | END IF ! matches if (s>=dist) THEN |
369 | 1 | equemene | END DO ! matches DO K=1,NMaxPtPath, Is it correct?? |
370 | 1 | equemene | |
371 | 1 | equemene | |
372 | 1 | equemene | if (printspline) THEN |
373 | 1 | equemene | SELECT CASE (Nat) |
374 | 1 | equemene | CASE(2) |
375 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1) |
376 | 1 | equemene | CASE (3) |
377 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2) |
378 | 1 | equemene | CASE(4:) |
379 | 1 | equemene | WRITE(IOTMP,'(15(1X,F10.5))') s,valzmat(2,1),valzmat(3,1:2),valzmat(4:Nat,1:3) |
380 | 1 | equemene | END SELECT |
381 | 1 | equemene | END IF |
382 | 1 | equemene | |
383 | 1 | equemene | if (s>=0.9*dist) THEN |
384 | 1 | equemene | if (debug) WRITE(*,*) "DBG Extrapol_int L383: Adding last geom" |
385 | 1 | equemene | write(*,*) "Extrapol_int u,xgeom(NGeomI),s,dist,s-dist",u,xgeom(NGeomI),s,dist,s-dist |
386 | 1 | equemene | ! u=xgeom(NGeomI) |
387 | 1 | equemene | s=s-dist |
388 | 1 | equemene | |
389 | 1 | equemene | |
390 | 1 | equemene | ! ! We generate the interpolated Zmatrix |
391 | 1 | equemene | ! call splintder(u,v,DerInt(1),NGeomI,xgeom(1),IntCoordI(1,1),Coef(1,1)) |
392 | 1 | equemene | ! valzmat(2,1)=v |
393 | 1 | equemene | ! call splintder(u,v,DerInt(2),NGeomI,xgeom(1),IntCoordI(1,2),Coef(1,2)) |
394 | 1 | equemene | ! valzmat(3,1)=v |
395 | 1 | equemene | ! call splintder(u,v,DerInt(3),NGeomI,xgeom(1),IntCoordI(1,3),Coef(1,3)) |
396 | 1 | equemene | ! valzmat(3,2)=v*180./Pi |
397 | 1 | equemene | ! Idx=4 |
398 | 1 | equemene | ! DO I=4,Nat |
399 | 1 | equemene | ! call splintder(u,v,DerInt(Idx),NGeomI,xgeom(1),IntCoordI(1,Idx),Coef(1,Idx)) |
400 | 1 | equemene | ! valzmat(I,1)=v |
401 | 1 | equemene | ! Idx=Idx+1 |
402 | 1 | equemene | ! DO J=2,3 |
403 | 1 | equemene | ! call splintder(u,v,DerInt(Idx),NGeomI,xgeom(1),IntCoordI(1,Idx),Coef(1,Idx)) |
404 | 1 | equemene | ! valzmat(I,J)=v*180./pi |
405 | 1 | equemene | ! Idx=Idx+1 |
406 | 1 | equemene | ! END DO |
407 | 1 | equemene | ! END DO ! matches DO I=4,Nat |
408 | 1 | equemene | |
409 | 1 | equemene | ! ! We convert it into Cartesian coordinates |
410 | 1 | equemene | ! XyzTmp2(2,1)=valzmat(2,1) |
411 | 1 | equemene | ! d=valzmat(3,1) |
412 | 1 | equemene | ! a_val=valzmat(3,2)/180.*Pi |
413 | 1 | equemene | ! if (Nat.GE.3) THEN |
414 | 1 | equemene | ! if (IndZmat(3,2).EQ.1) THEN |
415 | 1 | equemene | ! XyzTmp2(3,1)=XYzTmp2(1,1)+d*cos(a_val) |
416 | 1 | equemene | ! ELSE |
417 | 1 | equemene | ! XyzTmp2(3,1)=XyzTmp2(2,1)-d*cos(a_val) |
418 | 1 | equemene | ! ENDIF |
419 | 1 | equemene | ! XyzTmp2(3,2)=d*sin(a_val) |
420 | 1 | equemene | ! ENDIF |
421 | 1 | equemene | |
422 | 1 | equemene | ! DO I=4,Nat |
423 | 1 | equemene | ! call ConvertZmat_cart(I,IndZmat,valzmat, & |
424 | 1 | equemene | ! XYzTMP2(1,1), XYzTMP2(1,2),XYzTMP2(1,3)) |
425 | 1 | equemene | ! END DO |
426 | 1 | equemene | |
427 | 1 | equemene | ! IF (Nat.GE.4) THEN |
428 | 1 | equemene | ! ! PFL 24 Nov 2008 -> |
429 | 1 | equemene | ! ! If we have frozen atoms we align only those ones. |
430 | 1 | equemene | ! if (NFroz.GT.0) THEN |
431 | 1 | equemene | ! Call AlignPartial(Nat,x0,y0,z0, & |
432 | 1 | equemene | ! xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
433 | 1 | equemene | ! FrozAtoms,MRot) |
434 | 1 | equemene | ! ELSE |
435 | 1 | equemene | ! ! PFL 26 Nov 2008! |
436 | 1 | equemene | ! ! Note to myself: in Extrapol_cart we always align on x0,y0,z0 but here |
437 | 1 | equemene | ! ! we align on the previous geom... what is the best ? Is there a difference ? |
438 | 1 | equemene | ! Call CalcRmsd(Nat, XyzTmp(1:Nat,1),XyzTmp(1:Nat,2),XyzTmp(1:Nat,3), & |
439 | 1 | equemene | ! xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
440 | 1 | equemene | ! MRot,rmsd,.TRUE.,.TRUE.) |
441 | 1 | equemene | ! END IF |
442 | 1 | equemene | ! ! <- PFL 24 Nov 2008 |
443 | 1 | equemene | ! END IF |
444 | 1 | equemene | |
445 | 1 | equemene | IdxGeom=IdxGeom+1 |
446 | 1 | equemene | |
447 | 1 | equemene | |
448 | 1 | equemene | |
449 | 1 | equemene | IF (IdxGeom.GT.NGeomF) THEN |
450 | 1 | equemene | WRITE(IOOUT,*) "!!! ERROR in Extrapol_int !!!!" |
451 | 1 | equemene | WRITE(IOOUT,*) "Too many structures. Increase NMaxPath" |
452 | 1 | equemene | WRITE(*,*) "** PathCreate ***" |
453 | 1 | equemene | WRITE(*,*) "Distribution of points along the path is wrong." |
454 | 1 | equemene | WRITE(*,*) "Increase value of NMaxPtPath in the input file" |
455 | 1 | equemene | WRITE(*,*) "Present value is:", NMaxPtPath |
456 | 1 | equemene | STOP |
457 | 1 | equemene | END IF |
458 | 1 | equemene | |
459 | 1 | equemene | SGeom(IdxGeom)=s+IdxGeom*dist |
460 | 1 | equemene | XgeomF(IdxGeom)=min(u,NGeomI-1.d0) |
461 | 1 | equemene | XyzGeomF(IdxGeom,:,:)=Reshape(XyzTmp2(:,:),(/3,Nat/),ORDER=(/2,1/)) |
462 | 1 | equemene | ! XyzGeomF(IdxGeom,:,:)=XyzTmp2(:,:) |
463 | 1 | equemene | IntCoordF(IdxGeom,1)=valzmat(2,1) |
464 | 1 | equemene | IntCoordF(IdxGeom,2)=valzmat(3,1) |
465 | 1 | equemene | IntCoordF(IdxGeom,3)=valzmat(3,2)/180.*Pi |
466 | 1 | equemene | Idx=4 |
467 | 1 | equemene | DO I=4,Nat |
468 | 1 | equemene | IntCoordF(IdxGeom,Idx)=valzmat(I,1) |
469 | 1 | equemene | IntCoordF(IdxGeom,Idx+1)=valzmat(I,2)/180.*Pi |
470 | 1 | equemene | IntCoordF(IdxGeom,Idx+2)=valzmat(I,3)/180.*Pi |
471 | 1 | equemene | Idx=Idx+3 |
472 | 1 | equemene | END DO |
473 | 1 | equemene | IntTangent(IdxGeom,:)=DerInt |
474 | 1 | equemene | |
475 | 1 | equemene | if (print) THEN |
476 | 1 | equemene | WRITE(IOOUT,'(1X,I5)') Nat |
477 | 1 | equemene | WRITE(IOOUT,*) "# Cartesian coord for Geometry ",IdxGeom,K |
478 | 1 | equemene | ! PFL 17/July/2006: only if we have more than 4 atoms. |
479 | 1 | equemene | IF (Nat.GE.4) THEN |
480 | 1 | equemene | ! PFL 24 Nov 2008 -> |
481 | 1 | equemene | ! If we have frozen atoms we align only those ones. |
482 | 1 | equemene | if (NFroz.GT.0) THEN |
483 | 1 | equemene | Call AlignPartial(Nat,x0,y0,z0, & |
484 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
485 | 1 | equemene | FrozAtoms,MRot) |
486 | 1 | equemene | ELSE |
487 | 1 | equemene | Call CalcRmsd(Nat, x0,y0,z0, & |
488 | 1 | equemene | xyzTmp2(1,1),xyzTmp2(1,2),xyzTMP2(1,3), & |
489 | 1 | equemene | MRot,rmsd,.TRUE.,.TRUE.) |
490 | 1 | equemene | END IF |
491 | 1 | equemene | ! <- PFL 24 Nov 2008 |
492 | 1 | equemene | END IF |
493 | 1 | equemene | |
494 | 1 | equemene | DO I=1,Nat |
495 | 1 | equemene | If (Renum) THEN |
496 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(I)), & |
497 | 1 | equemene | (XyzTmp2(Order(I),J),J=1,3) |
498 | 1 | equemene | ELSE |
499 | 1 | equemene | WRITE(IOOUT,'(1X,A2,3(1X,F15.6))') Nom(Atome(OrderInv(I))), & |
500 | 1 | equemene | (XyzTmp2(I,J),J=1,3) |
501 | 1 | equemene | END IF |
502 | 1 | equemene | END DO ! matches DO I=1,Nat |
503 | 1 | equemene | END IF ! matches if (print) THEN |
504 | 1 | equemene | END IF ! matches if (s>=0.9*dist) THEN |
505 | 1 | equemene | |
506 | 1 | equemene | if (debug) WRITE(*,*) 's final =',s |
507 | 1 | equemene | |
508 | 1 | equemene | DEALLOCATE(XyzTmp,XyzTmp2,valzmat) |
509 | 1 | equemene | |
510 | 1 | equemene | if (printspline) CLOSE(IOTMP) |
511 | 1 | equemene | |
512 | 1 | equemene | if (debug) Call Header("Extrapol_int Over") |
513 | 1 | equemene | |
514 | 1 | equemene | |
515 | 1 | equemene | END SUBROUTINE EXTRAPOL_INT |