root / src / Calc_baker.f90 @ 5
Historique | Voir | Annoter | Télécharger (40,28 ko)
1 |
SUBROUTINE Calc_baker(atome,r_cov,fact,frozen,IGeomRef) |
---|---|
2 |
! |
3 |
! This subroutine analyses a geometry to construct the baker |
4 |
! delocalized internal coordinates |
5 |
! v1.0 |
6 |
! We use only one geometry |
7 |
! |
8 |
Use Path_module, only : max_Z,NMaxL,Nom,MaxFroz,NFroz,Pi,Massat,a0,BMat_BakerT, & |
9 |
Nat,NCoord,XyzGeomI,NGeomI,NGeomF,UMat,NPrim,BTransInv, & |
10 |
IntCoordI,Coordinate,CurrentCoord,ScanCoord,BprimT,BBT, & |
11 |
BBT_inv,Xprimitive,XPrimitiveF,Symmetry_elimination,UMat_local, & |
12 |
BTransInv_local, UMatF,BTransInvF, & |
13 |
indzmat, dzdc,renum,order,OrderInv |
14 |
! BMat_BakerT(3*Nat,NCoord), NCoord=3*Nat or NFree=3*Nat-6-Symmetry_elimination |
15 |
! depending upon the coordinate choice. IntCoordI(NGeomI,NCoord) where |
16 |
! UMat(NPrim,NCoord), NCoord number of vectors in UMat matrix, i.e. NCoord |
17 |
! Baker coordinates. NPrim is the number of primitive internal coordinates. |
18 |
|
19 |
Use Io_module |
20 |
IMPLICIT NONE |
21 |
|
22 |
! IGeom: Geometry index, IGeomRef: Reference Geometry. |
23 |
INTEGER(KINT), INTENT(IN) :: atome(Nat),IGeomRef |
24 |
REAL(KREAL), INTENT(IN) :: fact |
25 |
REAL(KREAL), INTENT(IN) :: r_cov(0:Max_Z) |
26 |
! Frozen contains the indices of frozen atoms |
27 |
INTEGER(KINT), INTENT(IN) :: Frozen(*) |
28 |
|
29 |
INTEGER(KINT), ALLOCATABLE :: LIAISONS(:,:) ! (Nat,0:NMaxL) |
30 |
REAL(KREAL), ALLOCATABLE :: Geom(:,:) !(3,Nat) |
31 |
! NPrim is the number of primitive coordinates and NCoord is the number |
32 |
! of internal coordinates. BMat is actually (NPrim,3*Nat). |
33 |
REAL(KREAL), ALLOCATABLE :: GMat(:,:) !(NPrim,NPrim) |
34 |
! EigVec(..) contains ALL eigevectors of BMat times BprimT, NOT only Baker Coordinate vectors. |
35 |
REAL(KREAL), ALLOCATABLE :: EigVec(:,:), EigVal(:) ! EigVec(NPrim,NPrim) |
36 |
REAL(KREAL), ALLOCATABLE :: x(:), y(:), z(:) |
37 |
REAL(KREAL), ALLOCATABLE :: x_refGeom(:), y_refGeom(:), z_refGeom(:) |
38 |
!REAL(KREAL), ALLOCATABLE :: V(:,:) ! (3*Nat,3*Nat) |
39 |
!REAL(KREAL), ALLOCATABLE :: P(:) ! Used in Baker Coordinates: Matrix Inversion |
40 |
REAL(KREAL), ALLOCATABLE :: UMat_tmp(:,:) |
41 |
INTEGER(KINT) :: NbBonds, NbAngles, NbDihedrals, IGeom |
42 |
|
43 |
real(KREAL) :: vx, vy, vz, Norm |
44 |
real(KREAL) :: vx1,vy1,vz1,norm1 |
45 |
real(KREAL) :: vx2,vy2,vz2,norm2 |
46 |
real(KREAL) :: vx3,vy3,vz3,norm3 |
47 |
real(KREAL) :: vx4,vy4,vz4,norm4 |
48 |
real(KREAL) :: vx5,vy5,vz5,norm5 |
49 |
|
50 |
INTEGER(KINT) :: I, J, IAt, K |
51 |
INTEGER(KINT) :: Kat, Lat, L |
52 |
|
53 |
REAL(KREAL) :: sAngleIatIKat, sAngleIIatLat |
54 |
|
55 |
LOGICAL :: debug, bond, AddPrimitiveCoord |
56 |
|
57 |
INTERFACE |
58 |
function valid(string) result (isValid) |
59 |
CHARACTER(*), intent(in) :: string |
60 |
logical :: isValid |
61 |
END function VALID |
62 |
|
63 |
|
64 |
FUNCTION angle(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2) |
65 |
use Path_module, only : Pi,KINT, KREAL |
66 |
real(KREAL) :: v1x,v1y,v1z,norm1 |
67 |
real(KREAL) :: v2x,v2y,v2z,norm2 |
68 |
real(KREAL) :: angle |
69 |
END FUNCTION ANGLE |
70 |
|
71 |
|
72 |
|
73 |
FUNCTION angle_d(v1x,v1y,v1z,norm1,v2x,v2y,v2z,norm2,v3x,v3y,v3z,norm3) |
74 |
use Path_module, only : Pi,KINT, KREAL |
75 |
real(KREAL) :: v1x,v1y,v1z,norm1 |
76 |
real(KREAL) :: v2x,v2y,v2z,norm2 |
77 |
real(KREAL) :: v3x,v3y,v3z,norm3 |
78 |
real(KREAL) :: angle_d,ca,sa |
79 |
END FUNCTION ANGLE_D |
80 |
|
81 |
|
82 |
|
83 |
|
84 |
SUBROUTINE Calc_Xprim(nat,x,y,z,Coordinate,NPrim,XPrimitive,XPrimRef) |
85 |
! |
86 |
! This subroutine uses the description of a list of Coordinates |
87 |
! to compute the values of the coordinates for a given geometry. |
88 |
! |
89 |
!!!!!!!!!! |
90 |
! Input: |
91 |
! Na: INTEGER, Number of atoms |
92 |
! x,y,z(Na): REAL, cartesian coordinates of the considered geometry |
93 |
! Coordinate (Pointer(ListCoord)): description of the wanted coordiantes |
94 |
! NPrim, INTEGER: Number of coordinates to compute |
95 |
! |
96 |
! Optional: XPrimRef(NPrim) REAL: array that contains coordinates values for |
97 |
! a former geometry. Useful for Dihedral angles evolution... |
98 |
|
99 |
!!!!!!!!!!! |
100 |
! Output: |
101 |
! XPrimimite(NPrim) REAL: array that will contain the values of the coordinates |
102 |
! |
103 |
!!!!!!!!! |
104 |
|
105 |
Use VarTypes |
106 |
Use Io_module |
107 |
Use Path_module, only : pi |
108 |
|
109 |
IMPLICIT NONE |
110 |
|
111 |
Type (ListCoord), POINTER :: Coordinate |
112 |
INTEGER(KINT), INTENT(IN) :: Nat,NPrim |
113 |
REAL(KREAL), INTENT(IN) :: x(Nat), y(Nat), z(Nat) |
114 |
REAL(KREAL), INTENT(IN), OPTIONAL :: XPrimRef(NPrim) |
115 |
REAL(KREAL), INTENT(OUT) :: XPrimitive(NPrim) |
116 |
|
117 |
END SUBROUTINE CALC_XPRIM |
118 |
END INTERFACE |
119 |
|
120 |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
121 |
! |
122 |
!!!!!!!! PFL Debug |
123 |
! |
124 |
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
125 |
INTEGER(KINT) :: I1,I2,I3,I4 |
126 |
LOGICAL :: debugPFL |
127 |
REAL(KREAL), ALLOCATABLE :: val_zmat(:,:) |
128 |
INTEGER(KINT), ALLOCATABLE :: indzmat0(:,:) |
129 |
|
130 |
|
131 |
debug=valid("Calc_baker") |
132 |
debugPFL=valid("BakerPFL") |
133 |
if (debug) WRITE(*,*) "============= Entering Cal_baker ==============" |
134 |
|
135 |
IF (Nat.le.2) THEN |
136 |
WRITE(*,*) "I do not work for less than 2 atoms :-p" |
137 |
RETURN |
138 |
END IF |
139 |
|
140 |
IF (debug) THEN |
141 |
WRITE(*,*) "DBG Calc_baker, geom" |
142 |
DO I=1,Nat |
143 |
WRITE(*,'(1X,I5,":",I3,3(1X,F15.3))') I,atome(I),XyzGeomI(IGeomRef,1:3,I) |
144 |
END DO |
145 |
END IF |
146 |
|
147 |
|
148 |
|
149 |
|
150 |
! we construct the list of bonds, valence angles and dihedral angles using this connectivity |
151 |
ALLOCATE(Coordinate) |
152 |
NULLIFY(Coordinate%next) |
153 |
NbBonds=0 |
154 |
NbAngles=0 |
155 |
NbDihedrals=0 |
156 |
|
157 |
CurrentCoord => Coordinate |
158 |
|
159 |
ALLOCATE(Liaisons(Nat,0:NMaxL),Geom(3,Nat),x(Nat),y(Nat),z(Nat)) |
160 |
ALLOCATE(x_refGeom(Nat),y_refGeom(Nat),z_refGeom(Nat)) |
161 |
|
162 |
x_refGeom(1:Nat) = XyzGeomI(IGeomRef,1,1:Nat) |
163 |
y_refGeom(1:Nat) = XyzGeomI(IGeomRef,2,1:Nat) |
164 |
z_refGeom(1:Nat) = XyzGeomI(IGeomRef,3,1:Nat) |
165 |
|
166 |
!!!!!!!!!!!!!!!!!!!! |
167 |
! |
168 |
! PFL Debug |
169 |
! |
170 |
!!!!!!!!!!!!!!!!!!!! |
171 |
if (debugPFL) THEN |
172 |
WRITE(*,*) "DBG PFL Calc_BAKER - Calculating Zmat" |
173 |
if (.not.ALLOCATED(indzmat)) THEN |
174 |
ALLOCATE(indzmat(Nat,5)) |
175 |
END IF |
176 |
IF (.NOT.ALLOCATED(DzDc)) THEN |
177 |
ALLOCATE(DzDc(3,nat,3,Nat)) |
178 |
END IF |
179 |
IF (.NOT.ALLOCATED(Val_zmat)) THEN |
180 |
ALLOCATE(val_zmat(nat,3)) |
181 |
END IF |
182 |
IF (.NOT.ALLOCATED(indzmat0)) THEN |
183 |
ALLOCATE(indzmat0(nat,5)) |
184 |
END IF |
185 |
! We construct a Zmat |
186 |
IF (Frozen(1).NE.0) THEN |
187 |
Renum=.TRUE. |
188 |
!!! remplcaer indzmat par indzmat0 puis renumerotation |
189 |
call Calc_zmat_const_frag(Nat,atome,IndZmat0,val_zmat, & |
190 |
x_refGeom,y_refGeom,z_refGeom, & |
191 |
r_cov,fact,frozen) |
192 |
ELSE |
193 |
!no zmat... we create our own |
194 |
call Calc_zmat_frag(Nat,atome,IndZmat0,val_zmat, & |
195 |
x_refGeom,y_refGeom,z_refGeom, & |
196 |
r_cov,fact) |
197 |
END IF |
198 |
|
199 |
DO I=1,Nat |
200 |
Order(IndZmat0(I,1))=I |
201 |
OrderInv(I)=IndZmat0(I,1) |
202 |
END DO |
203 |
IndZmat(1,1)=Order(IndZmat0(1,1)) |
204 |
IndZmat(2,1)=Order(IndZmat0(2,1)) |
205 |
IndZmat(2,2)=Order(IndZmat0(2,2)) |
206 |
IndZmat(3,1)=Order(IndZmat0(3,1)) |
207 |
IndZmat(3,2)=Order(IndZmat0(3,2)) |
208 |
IndZmat(3,3)=Order(IndZmat0(3,3)) |
209 |
DO I=4,Nat |
210 |
DO J=1,4 |
211 |
IndZmat(I,J)=Order(IndZmat0(I,J)) |
212 |
END DO |
213 |
end do |
214 |
|
215 |
|
216 |
WRITE(*,*) "DBG PFL CalcBaker, IndZmat0" |
217 |
DO I=1,Nat |
218 |
WRITE(*,*) I, indZmat0(I,:) |
219 |
end do |
220 |
|
221 |
WRITE(*,*) "DBG PFL CalcBaker, IndZmat" |
222 |
DO I=1,Nat |
223 |
WRITE(*,*) I, indZmat(I,:) |
224 |
end do |
225 |
|
226 |
|
227 |
DO I=1,Nat |
228 |
I1=indzmat0(I,1) |
229 |
I2=indzmat0(I,2) |
230 |
I3=indzmat0(I,3) |
231 |
I4=indzmat0(I,4) |
232 |
! Adding BOND between at1 and at2 |
233 |
WRITE(*,*) "DBG Indzmat",I,I1,I2,I3,I4 |
234 |
if (I2.NE.0) THEN |
235 |
NbBonds=NbBonds+1 |
236 |
! values of the coordinate (bond) is calculated for the reference geometry |
237 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) |
238 |
! are determined using all geometries. vecteur is defined in bib_oper.f |
239 |
Call vecteur(I1,I2,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
240 |
! CurrentCoord%value=Norm2 |
241 |
WRITE(*,'(1X,A,I5,A,2(1X,F12.6))') "Bond",NbBonds," Norm2,val_zmat",Norm2,val_zmat(I,1) |
242 |
CurrentCoord%value=val_zmat(I,1) |
243 |
CurrentCoord%SignDihedral = 0 |
244 |
CurrentCoord%At1=I1 |
245 |
CurrentCoord%At2=I2 |
246 |
CurrentCoord%Type="BOND" |
247 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
248 |
ALLOCATE(CurrentCoord%next) |
249 |
NULLIFY(CurrentCoord%next%next) |
250 |
END IF |
251 |
CurrentCoord => CurrentCoord%next |
252 |
END IF !IE.NE.0 |
253 |
if (I3.NE.0) THEN |
254 |
|
255 |
NbAngles=NbAngles+1 |
256 |
! values of the coordinate (bond) is calculated for the reference geometry |
257 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) are |
258 |
! determined using all geometries. |
259 |
Call vecteur(i2,I3,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
260 |
Call vecteur(i2,I1,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
261 |
! CurrentCoord%value=angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180. |
262 |
WRITE(*,'(1X,A,I5,A,2(1X,F12.6))') "Angle",NbAngles," angle,val_zmat", & |
263 |
angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2),val_zmat(I,2) |
264 |
CurrentCoord%value=val_zmat(I,2)*Pi/180. |
265 |
CurrentCoord%SignDihedral = 0 |
266 |
CurrentCoord%At1=I1 |
267 |
CurrentCoord%At2=I2 |
268 |
CurrentCoord%At3=I3 |
269 |
CurrentCoord%Type="ANGLE" |
270 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
271 |
ALLOCATE(CurrentCoord%next) |
272 |
NULLIFY(CurrentCoord%next%next) |
273 |
END IF |
274 |
CurrentCoord => CurrentCoord%next |
275 |
END IF ! matches IF (I3.NE.0) |
276 |
if (I4.NE.0) THEN |
277 |
NbDihedrals=NbDihedrals+1 |
278 |
Call vecteur(I2,I1,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
279 |
Call vecteur(I2,I3,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
280 |
Call vecteur(I3,I4,x_refGeom,y_refGeom,z_refGeom,vx3,vy3,vz3,Norm3) |
281 |
CALL produit_vect(vx1,vy1,vz1,vx2,vy2,vz2, & |
282 |
vx4,vy4,vz4,norm4) |
283 |
CALL produit_vect(vx3,vy3,vz3,vx2,vy2,vz2, & |
284 |
vx5,vy5,vz5,norm5) |
285 |
! CurrentCoord%value=angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, & |
286 |
! vx2,vy2,vz2,norm2)*Pi/180. |
287 |
WRITE(*,'(1X,A,I5,A,2(1X,F12.6))') "Dihedral",NbDihedrals, & |
288 |
" angle_d,val_zmat", & |
289 |
angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, & |
290 |
vx2,vy2,vz2,norm2) & |
291 |
,val_zmat(I,3) |
292 |
|
293 |
CurrentCoord%value = val_zmat(I,3)*Pi/180. |
294 |
CurrentCoord%SignDihedral = int(sign(1.D0,val_zmat(I,3))) |
295 |
CurrentCoord%At1=I1 |
296 |
CurrentCoord%At2=I2 |
297 |
CurrentCoord%At3=I3 |
298 |
CurrentCoord%At4=I4 |
299 |
CurrentCoord%Type="DIHEDRAL" |
300 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
301 |
ALLOCATE(CurrentCoord%next) |
302 |
NULLIFY(CurrentCoord%next%next) |
303 |
END IF |
304 |
CurrentCoord => CurrentCoord%next |
305 |
END IF ! matches IF (I4.NE.0) |
306 |
END DO ! matches DO I=1,Nat |
307 |
deallocate(indzmat0) |
308 |
|
309 |
ELSE !! if (debugPFL) |
310 |
|
311 |
DO IGeom=1, NGeomI |
312 |
!IGeom=1 ! need when using only first geometry. |
313 |
x(1:Nat) = XyzGeomI(IGeom,1,1:Nat) |
314 |
y(1:Nat) = XyzGeomI(IGeom,2,1:Nat) |
315 |
z(1:Nat) = XyzGeomI(IGeom,3,1:Nat) |
316 |
|
317 |
! First step: we calculate the connectivity |
318 |
Liaisons=0 |
319 |
|
320 |
Call CalcCnct(Nat,atome,x,y,z,LIAISONS,r_cov,fact) |
321 |
|
322 |
IF (debug) THEN |
323 |
WRITE(*,*) 'Connectivity done' |
324 |
DO I=1,Nat |
325 |
WRITE(*,'(1X,I5,":",I3,"=",15I4)') I,(Liaisons(I,J),J=0,NMaxL) |
326 |
WRITE(*,'(1X,I5,":",I3,"=",15I4)') I,(Liaisons(I,:)) |
327 |
END DO |
328 |
DO I=1,Nat |
329 |
WRITE(*,'(1X,I5,":",I3," r_cov=",F15.6)') I,atome(I),r_cov(atome(I)) |
330 |
END DO |
331 |
END IF |
332 |
|
333 |
DO I=1,Nat |
334 |
IF (Liaisons(I,0).NE.0) THEN |
335 |
DO J=1,Liaisons(I,0) |
336 |
! We add the bond |
337 |
Iat=Liaisons(I,J) |
338 |
IF (Iat.GT.I) THEN |
339 |
! Checking the uniqueness of bond. |
340 |
! Duplicate bonds should not be added. |
341 |
AddPrimitiveCoord=.True. |
342 |
ScanCoord=>Coordinate |
343 |
DO WHILE (Associated(ScanCoord%next)) |
344 |
IF (ScanCoord%Type .EQ. 'BOND') THEN |
345 |
IF (ScanCoord%At1 .EQ. Iat) THEN |
346 |
IF (ScanCoord%At2 .EQ. I) THEN |
347 |
AddPrimitiveCoord=.False. |
348 |
END IF |
349 |
END IF |
350 |
END IF |
351 |
ScanCoord => ScanCoord%next |
352 |
END DO |
353 |
|
354 |
IF (AddPrimitiveCoord) THEN |
355 |
NbBonds=NbBonds+1 |
356 |
! values of the coordinate (bond) is calculated for the reference geometry |
357 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) |
358 |
! are determined using all geometries. vecteur is defined in bib_oper.f |
359 |
Call vecteur(I,Iat,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
360 |
CurrentCoord%value=Norm2 |
361 |
CurrentCoord%SignDihedral = 0 |
362 |
CurrentCoord%At1=Iat |
363 |
CurrentCoord%At2=I |
364 |
CurrentCoord%Type="BOND" |
365 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
366 |
ALLOCATE(CurrentCoord%next) |
367 |
NULLIFY(CurrentCoord%next%next) |
368 |
END IF |
369 |
CurrentCoord => CurrentCoord%next |
370 |
END IF ! matches IF (AddPrimitiveCoord) THEN |
371 |
END IF ! matches IF (Iat.GT.I) THEN |
372 |
|
373 |
! Call Annul(Liaisons,IAt,I,Nat,NMaxL) |
374 |
! Liaisons(Iat,0)=Liaisons(Iat,0)-1 |
375 |
|
376 |
! We add the valence angles |
377 |
DO K=J+1,Liaisons(I,0) |
378 |
Kat=Liaisons(I,K) |
379 |
IF (Kat.GT.I) THEN |
380 |
! Checking the uniqueness of valence angle. |
381 |
! Duplicate bonds should not be added. |
382 |
AddPrimitiveCoord=.True. |
383 |
ScanCoord=>Coordinate |
384 |
DO WHILE (Associated(ScanCoord%next)) |
385 |
IF (ScanCoord%Type .EQ. 'ANGLE') THEN |
386 |
IF (ScanCoord%At1 .EQ. Iat) THEN |
387 |
IF (ScanCoord%At2 .EQ. I) THEN |
388 |
IF (ScanCoord%At3 .EQ. Kat) THEN |
389 |
AddPrimitiveCoord=.False. |
390 |
END IF |
391 |
END IF |
392 |
END IF |
393 |
END IF |
394 |
ScanCoord => ScanCoord%next |
395 |
END DO ! matches DO WHILE (Associated(ScanCoord%next)) |
396 |
|
397 |
IF (AddPrimitiveCoord) THEN |
398 |
IF (debug) WRITE(*,*) "Adding angle:",Iat,I,Kat |
399 |
NbAngles=NbAngles+1 |
400 |
! values of the coordinate (bond) is calculated for the reference geometry |
401 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) are |
402 |
! determined using all geometries. |
403 |
Call vecteur(i,kat,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
404 |
Call vecteur(i,Iat,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
405 |
CurrentCoord%value=angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180. |
406 |
CurrentCoord%SignDihedral = 0 |
407 |
sAngleIatIKat=abs(sin(angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180.)) |
408 |
CurrentCoord%At1=Iat |
409 |
CurrentCoord%At2=I |
410 |
CurrentCoord%At3=KAt |
411 |
CurrentCoord%Type="ANGLE" |
412 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
413 |
ALLOCATE(CurrentCoord%next) |
414 |
NULLIFY(CurrentCoord%next%next) |
415 |
END IF |
416 |
CurrentCoord => CurrentCoord%next |
417 |
END IF ! matches IF (AddPrimitiveCoord) THEN |
418 |
ELSE ! matches IF (Kat.GT.I) THEN |
419 |
! Kat is less than I. If there is a bond between I and Kat, then this angle |
420 |
! has already been taken into account. |
421 |
if (debug) WRITE(*,*) "Testing angle:",Iat,I,Kat |
422 |
Bond=.FALSE. |
423 |
DO L=1,Liaisons(Iat,0) |
424 |
IF (Liaisons(Iat,L).EQ.Kat) Bond=.TRUE. |
425 |
END DO |
426 |
IF (.NOT.Bond) THEN |
427 |
IF (debug) WRITE(*,*) "Not Bond Adding angle:",Iat,I,Kat |
428 |
|
429 |
! Checking the uniqueness of valence angle. |
430 |
! Duplicate bonds should not be added. |
431 |
AddPrimitiveCoord=.True. |
432 |
ScanCoord=>Coordinate |
433 |
DO WHILE (Associated(ScanCoord%next)) |
434 |
IF (ScanCoord%Type .EQ. 'ANGLE') THEN |
435 |
IF (ScanCoord%At1 .EQ. Iat) THEN |
436 |
IF (ScanCoord%At2 .EQ. I) THEN |
437 |
IF (ScanCoord%At3 .EQ. Kat) THEN |
438 |
AddPrimitiveCoord=.False. |
439 |
END IF |
440 |
END IF |
441 |
END IF |
442 |
END IF |
443 |
ScanCoord => ScanCoord%next |
444 |
END DO |
445 |
|
446 |
IF (AddPrimitiveCoord) THEN |
447 |
NbAngles=NbAngles+1 |
448 |
! values of the coordinate (bond) is calculated for the reference geometry |
449 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) |
450 |
! are determined using all geometries. |
451 |
Call vecteur(i,kat,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
452 |
Call vecteur(i,Iat,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
453 |
CurrentCoord%value=angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180. |
454 |
CurrentCoord%SignDihedral = 0 |
455 |
CurrentCoord%At1=Iat |
456 |
CurrentCoord%At2=I |
457 |
CurrentCoord%At3=KAt |
458 |
CurrentCoord%Type="ANGLE" |
459 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
460 |
ALLOCATE(CurrentCoord%next) |
461 |
NULLIFY(CurrentCoord%next%next) |
462 |
END IF |
463 |
CurrentCoord => CurrentCoord%next |
464 |
END IF ! matches IF (AddPrimitiveCoord) THEN |
465 |
END IF ! matches IF (.NOT.Bond) THEN |
466 |
END IF ! matches IF (Kat.GT.I) THEN, after else |
467 |
END DO ! matches DO K=J+1,Liaisons(I,0) |
468 |
END DO ! matches DO J=1,Liaisons(I,0) |
469 |
END IF ! matches IF (Liaisons(I,0).NE.0) THEN |
470 |
|
471 |
! We add dihedral angles. We do not concentrate on necessary angles, ie those that are |
472 |
! needed to build the molecule. Instead we collect all of them, and the choice of the best |
473 |
! ones will be done when diagonalizing the Baker matrix. |
474 |
IF (Liaisons(I,0).GE.3) Then |
475 |
DO J=1,Liaisons(I,0) |
476 |
Iat=Liaisons(I,J) |
477 |
! values of the coordinate (bond) is calculated for the reference geometry |
478 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) are |
479 |
! determined using all geometries. |
480 |
Call vecteur(Iat,i,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
481 |
|
482 |
DO K=J+1,Liaisons(I,0) |
483 |
Kat=Liaisons(I,K) |
484 |
Call vecteur(i,kat,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
485 |
sAngleIatIKat=abs(sin(angle(vx1,vy1,vz1,Norm1,-vx2,-vy2,-vz2,Norm2)*Pi/180.)) |
486 |
|
487 |
DO L=K+1,Liaisons(I,0) |
488 |
Lat=Liaisons(I,L) |
489 |
if (debug) WRITE(*,*) "0-Dihe Kat,I,Iat:",Kat,I,Iat,angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2) |
490 |
Call vecteur(iat,lat,x_refGeom,y_refGeom,z_refGeom,vx3,vy3,vz3,Norm3) |
491 |
sAngleIIatLat=abs(sin(angle(vx3,vy3,vz3,Norm3,vx2,vy2,vz2,Norm2)*Pi/180.)) |
492 |
if (debug) WRITE(*,*) "0-Dihe I,Iat,Lat:",angle(vx3,vy3,vz3,Norm3,vx2,vy2,vz2,Norm2) |
493 |
IF ((sAngleIatIKat.ge.0.01d0).AND.(sAngleIIatLat.ge.0.01d0)) THEN |
494 |
if (debug) WRITE(*,*) "Adding dihedral:",Kat,I,Iat,Lat |
495 |
|
496 |
! Checking for the uniqueness of valence angle. |
497 |
! Duplicate bonds should not be added. |
498 |
AddPrimitiveCoord=.True. |
499 |
ScanCoord=>Coordinate |
500 |
DO WHILE (Associated(ScanCoord%next)) |
501 |
IF (ScanCoord%Type .EQ. 'DIHEDRAL') THEN |
502 |
IF (ScanCoord%At1 .EQ. Kat) THEN |
503 |
IF (ScanCoord%At2 .EQ. I) THEN |
504 |
IF (ScanCoord%At3 .EQ. Iat) THEN |
505 |
IF (ScanCoord%At4 .EQ. Lat) THEN |
506 |
AddPrimitiveCoord=.False. |
507 |
END IF |
508 |
END IF |
509 |
END IF |
510 |
END IF |
511 |
END IF |
512 |
ScanCoord => ScanCoord%next |
513 |
END DO ! matches DO WHILE (Associated(ScanCoord%next)) |
514 |
|
515 |
! IF (AddPrimitiveCoord) THEN |
516 |
! NbDihedrals=NbDihedrals+1 |
517 |
! CALL produit_vect(vx3,vy3,vz3,vx2,vy2,vz2, & |
518 |
! vx5,vy5,vz5,norm5) |
519 |
!CALL produit_vect(vx1,vy1,vz1,vx2,vy2,vz2, & |
520 |
! vx4,vy4,vz4,norm4) |
521 |
! CurrentCoord%value=angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, & |
522 |
! vx2,vy2,vz2,norm2)*Pi/180. |
523 |
! CurrentCoord%SignDihedral = 0 |
524 |
! CurrentCoord%At1=Kat |
525 |
! CurrentCoord%At2=I |
526 |
! CurrentCoord%At3=IAt |
527 |
! CurrentCoord%At4=LAt |
528 |
!WRITE(*,'(1X,":(dihed 1)",I5," - ",I5," - ",I5," - ",I5," = ",F15.6)') & |
529 |
! ScanCoord%At1,ScanCoord%At2,ScanCoord%At3,ScanCoord%At4,ScanCoord%Value*180./Pi |
530 |
! CurrentCoord%Type="DIHEDRAL" |
531 |
! IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
532 |
! ALLOCATE(CurrentCoord%next) |
533 |
! NULLIFY(CurrentCoord%next%next) |
534 |
! END IF |
535 |
! CurrentCoord => CurrentCoord%next |
536 |
!END IF ! matches IF (AddPrimitiveCoord) THEN |
537 |
|
538 |
END IF ! matches IF ((sAngleIatIKat.ge.0.01d0).AND.(sAngleIIatLat.ge.0.01d0)) THEN |
539 |
END DO ! matches DO L=K+1,Liaisons(I,0) |
540 |
END DO ! matches DO K=J+1,Liaisons(I,0) |
541 |
END DO ! matches DO J=1,Liaisons(I,0) |
542 |
END IF !matches IF (Liaisons(I,0).GE.3) Then |
543 |
|
544 |
! we now add other dihedrals |
545 |
DO J=1,Liaisons(I,0) |
546 |
Iat=Liaisons(I,J) |
547 |
If (Iat.LE.I) Cycle |
548 |
! values of the coordinate (bond) is calculated for the reference geometry |
549 |
! whereas the coordinates (bonds) (CurrentCoord%At1, CurrentCoord%At2, etc.) are |
550 |
! determined using all geometries. |
551 |
Call vecteur(Iat,i,x_refGeom,y_refGeom,z_refGeom,vx2,vy2,vz2,Norm2) |
552 |
|
553 |
DO K=1,Liaisons(I,0) |
554 |
IF (Liaisons(I,K).EQ.Iat) Cycle |
555 |
Kat=Liaisons(I,K) |
556 |
Call vecteur(i,kat,x_refGeom,y_refGeom,z_refGeom,vx1,vy1,vz1,Norm1) |
557 |
sAngleIatIKat=abs(sin(angle(vx1,vy1,vz1,Norm1,-vx2,-vy2,-vz2,Norm2)*Pi/180.)) |
558 |
|
559 |
DO L=1,Liaisons(Iat,0) |
560 |
Lat=Liaisons(Iat,L) |
561 |
IF (Lat.eq.I) Cycle |
562 |
|
563 |
if (debug) WRITE(*,*) "Dihe Kat,I,Iat:",angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2),sAngleIatIKat |
564 |
Call vecteur(iat,lat,x_refGeom,y_refGeom,z_refGeom,vx,vy,vz,Norm) |
565 |
|
566 |
sAngleIIatLat=abs(sin(angle(vx,vy,vz,Norm,vx2,vy2,vz2,Norm2)*Pi/180.)) |
567 |
if (debug) WRITE(*,*) "Dihe I,Iat,Lat:",angle(vx,vy,vz,Norm,vx2,vy2,vz2,Norm2) |
568 |
! we add the dihedral angle Kat-I-Iat-Lat |
569 |
if (debug) WRITE(*,*) "Trying dihedral:",Kat,I,Iat,Lat,sAngleIatIKat,sAngleIIatLat |
570 |
IF ((Lat.NE.Kat).AND.(Lat.Ne.I).AND.(sAngleIatIKat.ge.0.01d0) & |
571 |
.AND.(sAngleIIatLat.ge.0.01d0)) THEN |
572 |
if (debug) WRITE(*,*) "Adding dihedral:",Kat,I,Iat,Lat |
573 |
|
574 |
! Checking for the uniqueness of valence angle. |
575 |
! Duplicate bonds should not be added. |
576 |
AddPrimitiveCoord=.True. |
577 |
ScanCoord=>Coordinate |
578 |
DO WHILE (Associated(ScanCoord%next)) |
579 |
IF (ScanCoord%Type .EQ. 'DIHEDRAL') THEN |
580 |
IF (ScanCoord%At1 .EQ. Kat) THEN |
581 |
IF (ScanCoord%At2 .EQ. I) THEN |
582 |
IF (ScanCoord%At3 .EQ. Iat) THEN |
583 |
IF (ScanCoord%At4 .EQ. Lat) THEN |
584 |
AddPrimitiveCoord=.False. |
585 |
END IF |
586 |
END IF |
587 |
END IF |
588 |
END IF |
589 |
END IF |
590 |
ScanCoord => ScanCoord%next |
591 |
END DO |
592 |
|
593 |
IF (AddPrimitiveCoord) THEN |
594 |
NbDihedrals=NbDihedrals+1 |
595 |
Call vecteur(iat,lat,x_refGeom,y_refGeom,z_refGeom,vx3,vy3,vz3,Norm3) |
596 |
CALL produit_vect(vx3,vy3,vz3,vx2,vy2,vz2, & |
597 |
vx5,vy5,vz5,norm5) |
598 |
CALL produit_vect(vx1,vy1,vz1,vx2,vy2,vz2, & |
599 |
vx4,vy4,vz4,norm4) |
600 |
CurrentCoord%value=angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, & |
601 |
vx2,vy2,vz2,norm2)*Pi/180. |
602 |
CurrentCoord%At1=Kat |
603 |
CurrentCoord%At2=I |
604 |
CurrentCoord%At3=IAt |
605 |
CurrentCoord%At4=LAt |
606 |
CurrentCoord%Type="DIHEDRAL" |
607 |
CurrentCoord%SignDihedral=int(sign(1.d0,angle_d(vx4,vy4,vz4,norm4, & |
608 |
vx5,vy5,vz5,norm5, vx2,vy2,vz2,norm2))) |
609 |
WRITE(*,'(1X,":(dihed 2)",I5," - ",I5," - ",I5," - ",I5," = ",F15.6)') ScanCoord%At1,& |
610 |
ScanCoord%At2, ScanCoord%At3,ScanCoord%At4,ScanCoord%Value*180./Pi |
611 |
IF (.NOT.ASSOCIATED(CurrentCoord%next)) THEN |
612 |
ALLOCATE(CurrentCoord%next) |
613 |
NULLIFY(CurrentCoord%next%next) |
614 |
END IF |
615 |
CurrentCoord => CurrentCoord%next |
616 |
END IF ! matches IF (AddPrimitiveCoord) THEN |
617 |
END IF ! matches IF ((Lat.NE.Kat).AND.(Lat.Ne.I).AND.(sAngleIatIKat.ge.0.01d0) ..... |
618 |
END DO ! matches DO L=1,Liaisons(Iat,0) |
619 |
END DO ! matches DO K=1,Liaisons(I,0) |
620 |
END DO ! matches DO J=1,Liaisons(I,0) |
621 |
END DO ! end of loop over all atoms, DO I=1, Nat |
622 |
END DO ! matches DO IGeom=1, NGeomI |
623 |
|
624 |
|
625 |
|
626 |
END IF ! if (debugPFL) |
627 |
DEALLOCATE(Liaisons) |
628 |
|
629 |
WRITE(*,*) "I have found" |
630 |
WRITE(*,*) NbBonds, " bonds" |
631 |
WRITE(*,*) NbAngles, " angles" |
632 |
WRITE(*,*) NbDihedrals, " dihedrals" |
633 |
|
634 |
WRITE(*,*) 'All in all...' |
635 |
ScanCoord=>Coordinate |
636 |
I=0 |
637 |
DO WHILE (Associated(ScanCoord%next)) |
638 |
I=I+1 |
639 |
SELECT CASE (ScanCoord%Type) |
640 |
CASE ('BOND') |
641 |
!WRITE(IOOUT,'(1X,I3,":",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,ScanCoord%At2,ScanCoord%Value |
642 |
WRITE(*,'(1X,I3,":(bond )",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,ScanCoord%At2,ScanCoord%Value |
643 |
CASE ('ANGLE') |
644 |
!WRITE(IOOUT,'(1X,I3,":",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1, & |
645 |
! ScanCoord%At2, ScanCoord%At3,ScanCoord%Value*180./Pi |
646 |
WRITE(*,'(1X,I3,":(angle)",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1, & |
647 |
ScanCoord%At2, ScanCoord%At3,ScanCoord%Value*180./Pi |
648 |
CASE ('DIHEDRAL') |
649 |
!WRITE(IOOUT,'(1X,I3,":",I5," - ",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,& |
650 |
! ScanCoord%At2, ScanCoord%At3,ScanCoord%At4,ScanCoord%Value*180./Pi |
651 |
WRITE(*,'(1X,I3,":(dihed)",I5," - ",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,& |
652 |
ScanCoord%At2, ScanCoord%At3,ScanCoord%At4,ScanCoord%Value*180./Pi |
653 |
END SELECT |
654 |
ScanCoord => ScanCoord%next |
655 |
END DO |
656 |
|
657 |
! NPrim is the number of primitive coordinates. |
658 |
NPrim=NbBonds+NbAngles+NbDihedrals |
659 |
|
660 |
! Now calculating values of all primitive bonds for all geometries: |
661 |
ALLOCATE(Xprimitive(NgeomI,NPrim),XPrimitiveF(NGeomF,NPrim)) |
662 |
ALLOCATE(UMatF(NGeomF,NPrim,NCoord)) |
663 |
ALLOCATE(BTransInvF(NGeomF,NCoord,3*Nat)) |
664 |
|
665 |
! We calculate the Primitive values for the first geometry, this plays a special role |
666 |
! as it will serve as a reference for other geometries ! |
667 |
|
668 |
x(1:Nat) = XyzGeomI(1,1,1:Nat) |
669 |
y(1:Nat) = XyzGeomI(1,2,1:Nat) |
670 |
z(1:Nat) = XyzGeomI(1,3,1:Nat) |
671 |
|
672 |
Call Calc_Xprim(nat,x,y,z,Coordinate,NPrim,XPrimitive(1,:)) |
673 |
|
674 |
DO IGeom=2, NGeomI |
675 |
|
676 |
x(1:Nat) = XyzGeomI(IGeom,1,1:Nat) |
677 |
y(1:Nat) = XyzGeomI(IGeom,2,1:Nat) |
678 |
z(1:Nat) = XyzGeomI(IGeom,3,1:Nat) |
679 |
|
680 |
Call Calc_Xprim(nat,x,y,z,Coordinate,NPrim,XPrimitive(IGeom,:),Xprimitive(1,:)) |
681 |
|
682 |
! ScanCoord=>Coordinate |
683 |
! I=0 ! index for the NPrim (NPrim is the number of primitive coordinates). |
684 |
! DO WHILE (Associated(ScanCoord%next)) |
685 |
! I=I+1 |
686 |
! SELECT CASE (ScanCoord%Type) |
687 |
! CASE ('BOND') |
688 |
! Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx2,vy2,vz2,Norm2) |
689 |
! Xprimitive(IGeom,I) = Norm2 |
690 |
! CASE ('ANGLE') |
691 |
! Call vecteur(ScanCoord%At2,ScanCoord%At3,x,y,z,vx1,vy1,vz1,Norm1) |
692 |
! Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx2,vy2,vz2,Norm2) |
693 |
! Xprimitive(IGeom,I) = angle(vx1,vy1,vz1,Norm1,vx2,vy2,vz2,Norm2)*Pi/180. |
694 |
! CASE ('DIHEDRAL') |
695 |
|
696 |
|
697 |
! Call vecteur(ScanCoord%At2,ScanCoord%At1,x,y,z,vx1,vy1,vz1,Norm1) |
698 |
! Call vecteur(ScanCoord%At2,ScanCoord%At3,x,y,z,vx2,vy2,vz2,Norm2) |
699 |
! Call vecteur(ScanCoord%At3,ScanCoord%At4,x,y,z,vx3,vy3,vz3,Norm3) |
700 |
! Call produit_vect(vx1,vy1,vz1,vx2,vy2,vz2, & |
701 |
! vx4,vy4,vz4,norm4) |
702 |
! Call produit_vect(vx3,vy3,vz3,vx2,vy2,vz2, & |
703 |
! vx5,vy5,vz5,norm5) |
704 |
|
705 |
! DiheTmp= angle_d(vx4,vy4,vz4,norm4,vx5,vy5,vz5,norm5, & |
706 |
! vx2,vy2,vz2,norm2) |
707 |
! Xprimitive(IGeom,I) = DiheTmp*Pi/180. |
708 |
! ! We treat large dihedral angles differently as +180=-180 mathematically and physically |
709 |
! ! but this causes lots of troubles when converting baker to cart. |
710 |
! ! So we ensure that large dihedral angles always have the same sign |
711 |
! if (abs(ScanCoord%SignDihedral).NE.1) THEN |
712 |
! ScanCoord%SignDihedral=Int(Sign(1.D0,DiheTmp)) |
713 |
! ELSE |
714 |
! If ((abs(DiheTmp).GE.170.D0).AND.(Sign(1.,DiheTmp)*ScanCoord%SignDihedral<0)) THEN |
715 |
! Xprimitive(IGeom,I) = DiheTmp*Pi/180.+ ScanCoord%SignDihedral*2.*Pi |
716 |
! END IF |
717 |
! END IF |
718 |
! ! Another test... will all this be consistent ??? |
719 |
! ! We want the shortest path, so we check that the change in dihedral angles is less than Pi: |
720 |
! IF (IGeom.GT.1) THEN |
721 |
! IF (abs(Xprimitive(IGeom,I)-XPrimitive(IGeom-1,I)).GE.Pi) THEN |
722 |
! if ((Xprimitive(IGeom,I)-XPrimitive(IGeom-1,I)).GE.Pi) THEN |
723 |
! Xprimitive(IGeom,I)=Xprimitive(IGeom,I)-2.d0*Pi |
724 |
! ELSE |
725 |
! Xprimitive(IGeom,I)=Xprimitive(IGeom,I)+2.d0*Pi |
726 |
! END IF |
727 |
! END IF |
728 |
! END IF |
729 |
! END SELECT |
730 |
! ScanCoord => ScanCoord%next |
731 |
! END DO ! matches DO WHILE (Associated(ScanCoord%next)) |
732 |
END DO ! matches DO IGeom=1, NGeomI |
733 |
|
734 |
IF (debug) THEN |
735 |
WRITE(*,*) "DBG Calc_Baker Xprimitives for all geometries" |
736 |
DO IGeom=1, NGeomI |
737 |
WRITE(*,*) "Geometry ",IGeom |
738 |
ScanCoord=>Coordinate |
739 |
I=0 ! index for the NPrim (NPrim is the number of primitive coordinates). |
740 |
DO WHILE (Associated(ScanCoord%next)) |
741 |
I=I+1 |
742 |
SELECT CASE (ScanCoord%Type) |
743 |
CASE ('BOND') |
744 |
WRITE(*,'(1X,I3,":",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,ScanCoord%At2,Xprimitive(IGeom,I) |
745 |
CASE ('ANGLE') |
746 |
WRITE(*,'(1X,I3,":",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1, & |
747 |
ScanCoord%At2, ScanCoord%At3,Xprimitive(IGeom,I)*180./Pi |
748 |
CASE ('DIHEDRAL') |
749 |
WRITE(*,'(1X,I3,":",I5," - ",I5," - ",I5," - ",I5," = ",F15.6)') I,ScanCoord%At1,& |
750 |
ScanCoord%At2, ScanCoord%At3,ScanCoord%At4,Xprimitive(IGeom,I)*180./Pi |
751 |
END SELECT |
752 |
ScanCoord => ScanCoord%next |
753 |
END DO ! matches DO WHILE (Associated(ScanCoord%next)) |
754 |
END DO ! matches DO IGeom=1, NGeomI |
755 |
END IF |
756 |
! Here reference geometry is assigned to Geom. Earlier x,y,z(Nat) were assigned from XyzGeomI(...) |
757 |
! before the call of this (Calc_baker) subroutine and passed to this subroutine as arguments of the |
758 |
! subroutine. |
759 |
! PFL 19 Feb 2008 -> |
760 |
! In order to reproduce the B matrix in the Baker article, one has |
761 |
! to divide Geom by a0. |
762 |
! However, this is inconsitent with our way of storing geometries |
763 |
! so we do not do it ! |
764 |
|
765 |
Geom(1,:)=XyzGeomI(IGeomRef,1,1:Nat) ! XyzGeomI(NGeomI,3,Nat) |
766 |
Geom(2,:)=XyzGeomI(IGeomRef,2,1:Nat) |
767 |
Geom(3,:)=XyzGeomI(IGeomRef,3,1:Nat) |
768 |
|
769 |
! <- PFL 19 Feb 2008 |
770 |
|
771 |
! We now have to compute dq/dx... |
772 |
ALLOCATE(BprimT(3*Nat,NPrim)) |
773 |
BprimT=0.d0 |
774 |
|
775 |
ScanCoord=>Coordinate |
776 |
I=0 |
777 |
DO WHILE (Associated(ScanCoord%next)) |
778 |
I=I+1 |
779 |
SELECT CASE (ScanCoord%Type) |
780 |
CASE ('BOND') |
781 |
CALL CONSTRAINTS_BONDLENGTH_DER(Nat,ScanCoord%at1,ScanCoord%AT2, & |
782 |
Geom,BprimT(1,I)) |
783 |
CASE ('ANGLE') |
784 |
CALL CONSTRAINTS_BONDANGLE_DER(Nat,ScanCoord%At1,ScanCoord%AT2, & |
785 |
ScanCoord%At3,Geom,BprimT(1,I)) |
786 |
CASE ('DIHEDRAL') |
787 |
CALL CONSTRAINTS_TORSION_DER2(Nat,ScanCoord%At1,ScanCoord%AT2, & |
788 |
ScanCoord%At3,ScanCoord%At4,Geom,BprimT(1,I)) |
789 |
! CALL CONSTRAINTS_TORSION_DER(Nat,ScanCoord%At1,ScanCoord%AT2, & |
790 |
! ScanCoord%At3,ScanCoord%At4,Geom,BprimT(1,I)) |
791 |
|
792 |
END SELECT |
793 |
ScanCoord => ScanCoord%next |
794 |
END DO |
795 |
|
796 |
|
797 |
!!!!!!!!!!!!!!!!!!!! |
798 |
! |
799 |
! PFL Debug |
800 |
! |
801 |
!!!!!!!!!!!!!!!!!!!! |
802 |
|
803 |
if (debugPFL) THEN |
804 |
WRITe(*,*) "DBG PFL Calc_Baker =====" |
805 |
DzDc=0.d0 |
806 |
WRITE(*,*) "PFL DBG, DzdC" |
807 |
do I=1,Nat |
808 |
Geom(1,i)=XyzGeomI(IGeomRef,1,orderInv(i)) ! XyzGeomI(NGeomI,3,Nat) |
809 |
Geom(2,i)=XyzGeomI(IGeomRef,2,OrderInv(i)) |
810 |
Geom(3,i)=XyzGeomI(IGeomRef,3,OrderInv(i)) |
811 |
WRITE(*,*) I,OrderInv(I),Geom(:,I) |
812 |
end do |
813 |
CALL CalcBMat_int (nat, Geom, indzmat, dzdc, massat,atome) |
814 |
|
815 |
WRITE(*,*) "PFL DBG, BPrimT" |
816 |
DO I=1,NPrim |
817 |
WRITE(*,'(50(1X,F12.6))') BPrimT(:,I) |
818 |
END DO |
819 |
WRITe(*,*) "DBG PFL Calc_Baker =====" |
820 |
END IF |
821 |
|
822 |
!!!!!!!!!!!!!!!!!!!! |
823 |
! |
824 |
! PFL Debug |
825 |
! |
826 |
!!!!!!!!!!!!!!!!!!!! |
827 |
|
828 |
DEALLOCATE(Geom) |
829 |
|
830 |
! BprimT(3*Nat,NPrim) |
831 |
! We now compute G=B(BT) matrix |
832 |
ALLOCATE(Gmat(NPrim,NPrim)) |
833 |
GMat=0.d0 |
834 |
DO I=1,NPrim |
835 |
DO J=1,3*Nat |
836 |
GMat(:,I)=Gmat(:,I)+BprimT(J,:)*BprimT(J,I) !*1.d0/mass(atome(int(K/3.d0))) |
837 |
END DO |
838 |
END DO |
839 |
|
840 |
!!!!!!!!!!!!!!!!!!!! |
841 |
! |
842 |
! PFL Debug ---> |
843 |
! |
844 |
!!!!!!!!!!!!!!!!!!!! |
845 |
if (debugPFL) THEN |
846 |
GMat=0.d0 |
847 |
DO I=1,NPrim |
848 |
GMat(I,I)=1. |
849 |
END DO |
850 |
END IF |
851 |
|
852 |
!!!!!!!!!!!!!!!!!!!! |
853 |
! |
854 |
! <--- PFL Debug |
855 |
! |
856 |
!!!!!!!!!!!!!!!!!!!! |
857 |
|
858 |
!DO I=1,NPrim |
859 |
! WRITE(*,'(20(1X,F6.3))') GMat(1:min(20,NPrim),I) |
860 |
!END DO |
861 |
|
862 |
! We diagonalize G |
863 |
ALLOCATE(EigVal(NPrim),EigVec(NPrim,NPrim)) |
864 |
Call Jacobi(GMat,NPrim,EigVal,EigVec,NPrim) |
865 |
Call Trie(NPrim,EigVal,EigVec,NPrim) |
866 |
DO I=1,NPrim |
867 |
WRITE(*,'(1X,"Vector ",I3,": e=",F8.3)') I,EigVal(i) |
868 |
WRITE(*,'(20(1X,F8.4))') EigVec(1:min(20,NPrim),I) |
869 |
END DO |
870 |
|
871 |
!DO I=1,NPrim |
872 |
! WRITE(*,'(1X,"Vector ",I3,(20(F8.3)))') I,EigVec(1:min(20,NPrim),I) |
873 |
! END DO |
874 |
|
875 |
!DO I=1,NPrim |
876 |
! WRITE(*,'(1X,"Vector ",I3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,F8.3,& |
877 |
! F8.3,F8.3,F8.3,F8.3,F8.3)') I,EigVec(1,I),EigVec(4,I),EigVec(6,I),EigVec(14,I),EigVec(16,I),& |
878 |
!EigVec(2,I),EigVec(3,I),EigVec(5,I),EigVec(12,I),EigVec(13,I),EigVec(15,I),EigVec(7,I),& |
879 |
!EigVec(8,I),EigVec(9,I),EigVec(10,I),EigVec(11,I),EigVec(17,I) |
880 |
!END DO |
881 |
|
882 |
! We construct the new DzDc(b=baker) matrix |
883 |
! UMat is nonredundant vector set, i.e. set of eigenvectors of BB^T corresponding |
884 |
! to eigenvalues > zero. |
885 |
ALLOCATE(UMat(NPrim,NCoord)) |
886 |
ALLOCATE(UMat_local(NPrim,NCoord)) |
887 |
ALLOCATE(UMat_tmp(NPrim,3*Nat-6)) |
888 |
! BMat_BakerT(3*Nat,NCoord), allocated in Path.f90, |
889 |
! NCoord=3*Nat-6 |
890 |
BMat_BakerT = 0.d0 |
891 |
J=0 |
892 |
UMat=0.d0 |
893 |
UMat_tmp=0.d0 |
894 |
DO I=1,NPrim |
895 |
IF (abs(eigval(I))>=1e-6) THEN |
896 |
J=J+1 |
897 |
DO K=1,NPrim |
898 |
!DzDcb(:,J)=DzDcb(:,J)+Eigvec(K,I)*BprimT(:,K) ! original |
899 |
! BprimT is transpose of B^prim. |
900 |
! B = UMat^T B^prim, B^T = (B^prim)^T UMat |
901 |
BMat_BakerT(:,J)=BMat_BakerT(:,J)+BprimT(:,K)*Eigvec(K,I) |
902 |
!Dzdcb(:,J)=DzDcb(:,J)+Eigvec(K,:)*BprimT(I,K) |
903 |
END DO |
904 |
IF(J .GT. 3*Nat-6) THEN |
905 |
WRITE(*,*) 'Number of vectors in Eigvec with eigval .GT. 1e-6(=UMat) (=' & |
906 |
,J,') exceeded 3*Nat-6=',3*Nat-6, & |
907 |
'Stopping the calculation.' |
908 |
STOP |
909 |
END IF |
910 |
UMat_tmp(:,J) = Eigvec(:,I) |
911 |
END IF |
912 |
END DO |
913 |
|
914 |
if (debug) THEN |
915 |
WRITE(*,*) "DBG Calc_Baker: UMat" |
916 |
DO I=1,3*Nat-6 |
917 |
WRITE(*,'(50(1X,F12.8))') UMat_tmp(:,I) |
918 |
END DO |
919 |
END IF |
920 |
|
921 |
! THIS IS TO BE CORRECTED: |
922 |
UMat = UMat_tmp |
923 |
!J=0 |
924 |
!DO I=1, 3*Nat-6 |
925 |
! IF ((I .NE. 6) .AND. (I .NE. 7) .AND. (I .NE. 9)) Then |
926 |
! J=J+1 |
927 |
! Print *, 'J=', J, ' I=', I |
928 |
! UMat(:,J) = UMat_tmp(:,I) |
929 |
!END IF |
930 |
!END DO |
931 |
! BMat_BakerT=0.d0 |
932 |
!DO I=1,NCoord |
933 |
! DO J=1,NPrim |
934 |
! B = UMat^T B^prim, B^T = (B^prim)^T UMat |
935 |
! BMat_BakerT(:,I)=BMat_BakerT(:,I)+BprimT(:,J)*UMat(J,I) |
936 |
! END DO |
937 |
!END DO |
938 |
! TO BE CORRECTED, ENDS HERE. |
939 |
|
940 |
IntCoordI=0.d0 |
941 |
DO IGeom=1, NGeomI |
942 |
DO I=1, NPrim |
943 |
! Transpose of UMat is needed below, that is why UMat(I,:). |
944 |
IntCoordI(IGeom,:) = IntCoordI(IGeom,:) + UMat(I,:)*Xprimitive(IGeom,I) |
945 |
END DO |
946 |
END DO |
947 |
|
948 |
if (debug) THEN |
949 |
WRITE(*,*) "DBG Calc_Baker IntCoordI" |
950 |
DO IGeom=1, NGeomI |
951 |
WRITE(*,'(1X,I5,":",30(1X,F10.6))') IGeom,IntCoordI(IGeom,:) |
952 |
END DO |
953 |
END IF |
954 |
|
955 |
|
956 |
! the following might be used to get rid of some coordinates that |
957 |
! do not respect the symmetry of the problem. |
958 |
|
959 |
! ! We look at the group symmetry of the molecule. Nothing complicate here |
960 |
! ! we just look for planar symmetry. |
961 |
! ! We first place it into the standard orientation |
962 |
! Call Std_ori(Nat,x,y,z,a,b,c,massat) |
963 |
|
964 |
! ! Is the molecule planar |
965 |
! DO I=1,Nat |
966 |
! WRITE(*,*) nom(atome(i)),x(i),y(i),z(i) |
967 |
! END DO |
968 |
DEALLOCATE(BprimT,GMat,EigVal,EigVec) ! BprimT is B^prim^T |
969 |
! Calculation of BTransInv starts here: |
970 |
! Calculation of BBT(3*Nat-6,3*Nat-6)=BB^T: |
971 |
! BMat_BakerT(3*Nat,NCoord) is Transpose of B = UMat^TB^prim |
972 |
ALLOCATE(BBT(NCoord,NCoord)) |
973 |
BBT = 0.d0 |
974 |
DO I=1, NCoord |
975 |
DO J=1, 3*Nat |
976 |
! BBT(:,I) forms BB^T |
977 |
BBT(:,I) = BBT(:,I) + BMat_BakerT(J,:)*BMat_BakerT(J,I) |
978 |
END DO |
979 |
END DO |
980 |
|
981 |
!ALLOCATE(V(3*Nat,3*Nat)) |
982 |
!Call GINVSE(BBT,3*Nat,3*Nat,BBT_inv,3*Nat,3*Nat,3*Nat,1e-6,V,3*Nat,FAIL,NOUT) |
983 |
!DEALLOCATE(V) |
984 |
ALLOCATE(BBT_inv(NCoord,NCoord)) |
985 |
! GenInv is in Mat_util.f90 |
986 |
Call GenInv(NCoord,BBT,BBT_inv,NCoord) |
987 |
|
988 |
! Calculation of (B^T)^-1 = (BB^T)^-1B: |
989 |
!ALLOCATE(BTransInv(3*Nat-6,3*Nat)) ! allocated in Path.f90 |
990 |
BTransInv = 0.d0 |
991 |
DO I=1, 3*Nat |
992 |
DO J=1, NCoord |
993 |
BTransInv(:,I) = BTransInv(:,I) + BBT_inv(:,J)*BMat_BakerT(I,J) |
994 |
END DO |
995 |
END DO |
996 |
BTransInv_local = BTransInv |
997 |
UMat_local = UMat |
998 |
DEALLOCATE(BBT,BBT_inv,UMat_tmp) |
999 |
DEALLOCATE(x_refGeom,y_refGeom,z_refGeom,x,y,z) |
1000 |
IF (debug) WRITE(*,*) "DBG Calc_baker over." |
1001 |
END SUBROUTINE Calc_baker |