root / src / AlignPartial.f90
Historique | Voir | Annoter | Télécharger (6,48 ko)
1 | 1 | pfleura2 | subroutine AlignPartial(na, x,y,z,x2,y2,z2,ListAt,U) |
---|---|---|---|
2 | 1 | pfleura2 | !----------------------------------------------------------------------- |
3 | 1 | pfleura2 | ! This subroutine calculates the least square rmsd of two coordinate |
4 | 1 | pfleura2 | ! sets coord1(3,n) and coord2(3,n) using a method based on quaternion. |
5 | 1 | pfleura2 | ! It then calculate the rotation matrix U and the centers of coord, and uses |
6 | 1 | pfleura2 | ! them to align the two molecules. |
7 | 1 | pfleura2 | ! This new version does not use all atoms to calculate the RMSD and rotation matrix |
8 | 1 | pfleura2 | ! but only those which are 'true' in ListAt |
9 | 1 | pfleura2 | !----------------------------------------------------------------------- |
10 | 1 | pfleura2 | ! Input parameters: |
11 | 1 | pfleura2 | ! Na : number of atoms |
12 | 1 | pfleura2 | ! x,y,z : coordinates of the first geometry |
13 | 1 | pfleura2 | ! x2,y2,z2 : coordinates of the second geometry |
14 | 1 | pfleura2 | ! ListAt : Logical, T if this atom should be considered in the RMSD calc and |
15 | 1 | pfleura2 | ! alignment. |
16 | 1 | pfleura2 | ! |
17 | 1 | pfleura2 | ! output parameters: |
18 | 1 | pfleura2 | ! U : Real, (3x3) matrix for rotation |
19 | 1 | pfleura2 | ! x2,y2,z2 : coordinates of the second geometry ALIGNED to the first one |
20 | 1 | pfleura2 | !----------------------------------------------------------------------- |
21 | 1 | pfleura2 | |
22 | 12 | pfleura2 | !---------------------------------------------------------------------- |
23 | 12 | pfleura2 | ! Copyright 2003-2014 Ecole Normale Supérieure de Lyon, |
24 | 12 | pfleura2 | ! Centre National de la Recherche Scientifique, |
25 | 12 | pfleura2 | ! Université Claude Bernard Lyon 1. All rights reserved. |
26 | 12 | pfleura2 | ! |
27 | 12 | pfleura2 | ! This work is registered with the Agency for the Protection of Programs |
28 | 12 | pfleura2 | ! as IDDN.FR.001.100009.000.S.P.2014.000.30625 |
29 | 12 | pfleura2 | ! |
30 | 12 | pfleura2 | ! Authors: P. Fleurat-Lessard, P. Dayal |
31 | 12 | pfleura2 | ! Contact: optnpath@gmail.com |
32 | 12 | pfleura2 | ! |
33 | 12 | pfleura2 | ! This file is part of "Opt'n Path". |
34 | 12 | pfleura2 | ! |
35 | 12 | pfleura2 | ! "Opt'n Path" is free software: you can redistribute it and/or modify |
36 | 12 | pfleura2 | ! it under the terms of the GNU Affero General Public License as |
37 | 12 | pfleura2 | ! published by the Free Software Foundation, either version 3 of the License, |
38 | 12 | pfleura2 | ! or (at your option) any later version. |
39 | 12 | pfleura2 | ! |
40 | 12 | pfleura2 | ! "Opt'n Path" is distributed in the hope that it will be useful, |
41 | 12 | pfleura2 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of |
42 | 12 | pfleura2 | ! |
43 | 12 | pfleura2 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
44 | 12 | pfleura2 | ! GNU Affero General Public License for more details. |
45 | 12 | pfleura2 | ! |
46 | 12 | pfleura2 | ! You should have received a copy of the GNU Affero General Public License |
47 | 12 | pfleura2 | ! along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>. |
48 | 12 | pfleura2 | ! |
49 | 12 | pfleura2 | ! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr, |
50 | 12 | pfleura2 | ! for commercial licensing opportunities. |
51 | 12 | pfleura2 | !---------------------------------------------------------------------- |
52 | 12 | pfleura2 | |
53 | 1 | pfleura2 | Use VarTypes |
54 | 1 | pfleura2 | IMPLICIT NONE |
55 | 1 | pfleura2 | |
56 | 1 | pfleura2 | |
57 | 1 | pfleura2 | integer(KINT) :: na, NaT |
58 | 1 | pfleura2 | Real(KREAL) :: x(na),y(Na),z(Na) |
59 | 1 | pfleura2 | Real(KREAL) :: x2(Na),y2(Na),z2(Na) |
60 | 1 | pfleura2 | Real(KREAL) :: U(3,3), rmsd |
61 | 1 | pfleura2 | LOGICAL Debug, ListAt(Na) |
62 | 1 | pfleura2 | |
63 | 1 | pfleura2 | REAL(KREAL) :: Coord1(3,Na), Coord2(3,Na) |
64 | 1 | pfleura2 | Real(KREAL) :: xc1,yc1,zc1, xc2,yc2,zc2 |
65 | 1 | pfleura2 | |
66 | 1 | pfleura2 | |
67 | 2 | pfleura2 | integer(KINT) :: i, j, ia |
68 | 1 | pfleura2 | Real(KREAL) :: x_norm, y_norm, lambda |
69 | 1 | pfleura2 | Real(KREAL) :: Rmatrix(3,3) |
70 | 2 | pfleura2 | Real(KREAL) :: S(4, 4) |
71 | 2 | pfleura2 | Real(KREAL) :: EigVec(4, 4), EigVal(4) |
72 | 1 | pfleura2 | |
73 | 1 | pfleura2 | INTERFACE |
74 | 1 | pfleura2 | function valid(string) result (isValid) |
75 | 1 | pfleura2 | CHARACTER(*), intent(in) :: string |
76 | 1 | pfleura2 | logical :: isValid |
77 | 1 | pfleura2 | END function VALID |
78 | 1 | pfleura2 | END INTERFACE |
79 | 1 | pfleura2 | |
80 | 1 | pfleura2 | |
81 | 1 | pfleura2 | debug=valid('CalcRmsd').OR.valid('align').OR.valid('alignpartial') |
82 | 1 | pfleura2 | |
83 | 1 | pfleura2 | ! calculate the barycenters, centroidal coordinates, and the norms |
84 | 1 | pfleura2 | x_norm = 0.0d0 |
85 | 1 | pfleura2 | y_norm = 0.0d0 |
86 | 1 | pfleura2 | xc1=0. |
87 | 1 | pfleura2 | yc1=0. |
88 | 1 | pfleura2 | zc1=0. |
89 | 1 | pfleura2 | xc2=0. |
90 | 1 | pfleura2 | yc2=0. |
91 | 1 | pfleura2 | zc2=0. |
92 | 1 | pfleura2 | |
93 | 1 | pfleura2 | if (debug) THEN |
94 | 1 | pfleura2 | WRITE(*,*) "DBG AlignPartial X2,Y2,Z2 before align" |
95 | 1 | pfleura2 | DO Ia=1,na |
96 | 1 | pfleura2 | WRITE(*,*) x2(ia),y2(ia),z2(ia) |
97 | 1 | pfleura2 | END DO |
98 | 1 | pfleura2 | END IF |
99 | 1 | pfleura2 | |
100 | 1 | pfleura2 | NAt=0 |
101 | 1 | pfleura2 | do ia=1,na |
102 | 1 | pfleura2 | IF (listat(ia)) THEN |
103 | 1 | pfleura2 | Nat=NAt+1 |
104 | 1 | pfleura2 | xc1=xc1+x(ia) |
105 | 1 | pfleura2 | xc2=xc2+x2(ia) |
106 | 1 | pfleura2 | yc1=yc1+y(ia) |
107 | 1 | pfleura2 | yc2=yc2+y2(ia) |
108 | 1 | pfleura2 | zc1=zc1+z(ia) |
109 | 1 | pfleura2 | zc2=zc2+z2(ia) |
110 | 1 | pfleura2 | ! if (debug) WRITE(*,'(A,I5,4(1X,F10.4))') 'ia...',ia,x(ia), |
111 | 1 | pfleura2 | ! & x2(ia),xc1,xc2 |
112 | 1 | pfleura2 | END IF |
113 | 1 | pfleura2 | END DO |
114 | 1 | pfleura2 | |
115 | 1 | pfleura2 | if (Nat.EQ.0) THEN |
116 | 1 | pfleura2 | WRITE(*,*) "ERROR, AlignPartial: ListAt is empty :-)" |
117 | 1 | pfleura2 | END IF |
118 | 1 | pfleura2 | xc1=xc1/dble(nat) |
119 | 1 | pfleura2 | yc1=yc1/dble(nat) |
120 | 1 | pfleura2 | zc1=zc1/dble(nat) |
121 | 1 | pfleura2 | xc2=xc2/dble(nat) |
122 | 1 | pfleura2 | yc2=yc2/dble(nat) |
123 | 1 | pfleura2 | zc2=zc2/dble(nat) |
124 | 1 | pfleura2 | |
125 | 1 | pfleura2 | IF (Debug) WRITE(*,*) 'Found :', Nat, ' atoms' |
126 | 1 | pfleura2 | IF (debug) WRITE(*,*) (ListAt(I),I=1,Na) |
127 | 1 | pfleura2 | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center1',xc1,yc1,zc1 |
128 | 1 | pfleura2 | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center2',xc2,yc2,zc2 |
129 | 1 | pfleura2 | do i=1,na |
130 | 1 | pfleura2 | Coord1(1,i)=x(i)-xc1 |
131 | 1 | pfleura2 | Coord1(2,i)=y(i)-yc1 |
132 | 1 | pfleura2 | Coord1(3,i)=z(i)-zc1 |
133 | 1 | pfleura2 | Coord2(1,i)=x2(i)-xc2 |
134 | 1 | pfleura2 | Coord2(2,i)=y2(i)-yc2 |
135 | 1 | pfleura2 | Coord2(3,i)=z2(i)-zc2 |
136 | 1 | pfleura2 | IF (ListAt(I)) THEN |
137 | 1 | pfleura2 | x_norm=x_norm+Coord1(1,i)**2+Coord1(2,i)**2+Coord1(3,i)**2 |
138 | 1 | pfleura2 | y_norm=y_norm+Coord2(1,i)**2+Coord2(2,i)**2+Coord2(3,i)**2 |
139 | 1 | pfleura2 | END IF |
140 | 1 | pfleura2 | end do |
141 | 1 | pfleura2 | |
142 | 1 | pfleura2 | ! calculate the R matrix |
143 | 1 | pfleura2 | do i = 1, 3 |
144 | 1 | pfleura2 | do j = 1, 3 |
145 | 1 | pfleura2 | Rmatrix(i,j)=0. |
146 | 1 | pfleura2 | do ia=1,na |
147 | 1 | pfleura2 | If (ListAt(ia)) Rmatrix(i,j) = Rmatrix(i,j)+Coord1(i,ia)*Coord2(j,ia) |
148 | 1 | pfleura2 | END DO |
149 | 1 | pfleura2 | end do |
150 | 1 | pfleura2 | end do |
151 | 1 | pfleura2 | |
152 | 1 | pfleura2 | IF (debug) THEN |
153 | 1 | pfleura2 | WRITE(*,*) "R matrix" |
154 | 1 | pfleura2 | DO I=1,3 |
155 | 1 | pfleura2 | WRITE(*,*) (RMatrix(I,j),j=1,3) |
156 | 1 | pfleura2 | END DO |
157 | 1 | pfleura2 | END IF |
158 | 1 | pfleura2 | |
159 | 1 | pfleura2 | |
160 | 1 | pfleura2 | ! S matrix |
161 | 1 | pfleura2 | S(1, 1) = Rmatrix(1, 1) + Rmatrix(2, 2) + Rmatrix(3, 3) |
162 | 1 | pfleura2 | S(2, 1) = Rmatrix(2, 3) - Rmatrix(3, 2) |
163 | 1 | pfleura2 | S(3, 1) = Rmatrix(3, 1) - Rmatrix(1, 3) |
164 | 1 | pfleura2 | S(4, 1) = Rmatrix(1, 2) - Rmatrix(2, 1) |
165 | 1 | pfleura2 | |
166 | 1 | pfleura2 | S(1, 2) = S(2, 1) |
167 | 1 | pfleura2 | S(2, 2) = Rmatrix(1, 1) - Rmatrix(2, 2) - Rmatrix(3, 3) |
168 | 1 | pfleura2 | S(3, 2) = Rmatrix(1, 2) + Rmatrix(2, 1) |
169 | 1 | pfleura2 | S(4, 2) = Rmatrix(1, 3) + Rmatrix(3, 1) |
170 | 1 | pfleura2 | |
171 | 1 | pfleura2 | S(1, 3) = S(3, 1) |
172 | 1 | pfleura2 | S(2, 3) = S(3, 2) |
173 | 1 | pfleura2 | S(3, 3) =-Rmatrix(1, 1) + Rmatrix(2, 2) - Rmatrix(3, 3) |
174 | 1 | pfleura2 | S(4, 3) = Rmatrix(2, 3) + Rmatrix(3, 2) |
175 | 1 | pfleura2 | |
176 | 1 | pfleura2 | S(1, 4) = S(4, 1) |
177 | 1 | pfleura2 | S(2, 4) = S(4, 2) |
178 | 1 | pfleura2 | S(3, 4) = S(4, 3) |
179 | 1 | pfleura2 | S(4, 4) =-Rmatrix(1, 1) - Rmatrix(2, 2) + Rmatrix(3, 3) |
180 | 1 | pfleura2 | |
181 | 1 | pfleura2 | |
182 | 1 | pfleura2 | ! PFL : I use my usual Jacobi diagonalisation |
183 | 1 | pfleura2 | ! Calculate eigenvalues and eigenvectors, and |
184 | 1 | pfleura2 | ! take the maximum eigenvalue lambda and the corresponding eigenvector q. |
185 | 1 | pfleura2 | |
186 | 1 | pfleura2 | IF (debug) THEN |
187 | 1 | pfleura2 | WRITE(*,*) "S matrix" |
188 | 1 | pfleura2 | DO I=1,4 |
189 | 1 | pfleura2 | WRITE(*,*) (S(I,j),j=1,4) |
190 | 1 | pfleura2 | END DO |
191 | 1 | pfleura2 | END IF |
192 | 1 | pfleura2 | |
193 | 1 | pfleura2 | Call Jacobi(S,4,EigVal,EigVec,4) |
194 | 1 | pfleura2 | |
195 | 1 | pfleura2 | Call Trie(4,EigVal,EigVec,4) |
196 | 1 | pfleura2 | |
197 | 1 | pfleura2 | Lambda=EigVal(4) |
198 | 1 | pfleura2 | |
199 | 1 | pfleura2 | ! RMS Deviation |
200 | 1 | pfleura2 | rmsd=sqrt(max(0.0d0,((x_norm+y_norm)-2.0d0*lambda))/dble(nat)) |
201 | 1 | pfleura2 | if (debug) WRITE(*,*) "AlignPartial rmsd:",rmsd |
202 | 1 | pfleura2 | Call rotation_matrix(EigVec(1,4),U) |
203 | 1 | pfleura2 | |
204 | 1 | pfleura2 | |
205 | 1 | pfleura2 | IF (debug) THEN |
206 | 1 | pfleura2 | WRITE(*,*) "U matrix" |
207 | 1 | pfleura2 | DO I=1,3 |
208 | 1 | pfleura2 | WRITE(*,*) (U(I,j),j=1,3) |
209 | 1 | pfleura2 | END DO |
210 | 1 | pfleura2 | END IF |
211 | 1 | pfleura2 | |
212 | 1 | pfleura2 | DO I=1,na |
213 | 1 | pfleura2 | x2(i)=Coord2(1,i)*U(1,1)+Coord2(2,i)*U(2,1) + Coord2(3,i)*U(3,1) +xc1 |
214 | 1 | pfleura2 | y2(i)=Coord2(1,i)*U(1,2)+Coord2(2,i)*U(2,2) + Coord2(3,i)*U(3,2) +yc1 |
215 | 1 | pfleura2 | z2(i)=Coord2(1,i)*U(1,3)+Coord2(2,i)*U(2,3) + Coord2(3,i)*U(3,3) +zc1 |
216 | 1 | pfleura2 | END DO |
217 | 1 | pfleura2 | |
218 | 1 | pfleura2 | if (debug) THEN |
219 | 1 | pfleura2 | WRITE(*,*) "DBG AlignPartial X2,Y2,Z2 after align" |
220 | 1 | pfleura2 | DO Ia=1,na |
221 | 1 | pfleura2 | WRITE(*,*) x2(ia),y2(ia),z2(ia) |
222 | 1 | pfleura2 | END DO |
223 | 1 | pfleura2 | END IF |
224 | 1 | pfleura2 | |
225 | 1 | pfleura2 | |
226 | 1 | pfleura2 | END subroutine AlignPartial |