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