root / src / CalcRmsd.f90
Historique | Voir | Annoter | Télécharger (8,54 ko)
1 | 1 | pfleura2 | |
---|---|---|---|
2 | 1 | pfleura2 | ! This subroutine calculates RMSD (Root mean square deviation) using quaternions. |
3 | 1 | pfleura2 | ! It is baNatsed on the F90 routine bu E. Coutsias |
4 | 1 | pfleura2 | ! http://www.math.unm.edu/~vageli/homepage.html |
5 | 1 | pfleura2 | ! I (PFL) have just translated it, and I have changed the diagonalization |
6 | 1 | pfleura2 | ! subroutine. |
7 | 1 | pfleura2 | ! I also made some changes to make it suitable for Cart package. |
8 | 1 | pfleura2 | !---------------------------------------------------------------------- |
9 | 1 | pfleura2 | !---------------------------------------------------------------------- |
10 | 1 | pfleura2 | ! Copyright (C) 2004, 2005 Chaok Seok, Evangelos Coutsias and Ken Dill |
11 | 1 | pfleura2 | ! UCSF, Univeristy of New Mexico, Seoul National University |
12 | 1 | pfleura2 | ! Witten by Chaok Seok and Evangelos Coutsias 2004. |
13 | 1 | pfleura2 | |
14 | 1 | pfleura2 | ! This library is free software; you can redistribute it and/or |
15 | 1 | pfleura2 | ! modify it under the terms of the GNU Lesser General Public |
16 | 1 | pfleura2 | ! License as published by the Free Software Foundation; either |
17 | 1 | pfleura2 | ! version 2.1 of the License, or (at your option) any later version. |
18 | 1 | pfleura2 | ! |
19 | 1 | pfleura2 | |
20 | 1 | pfleura2 | ! This library is distributed in the hope that it will be useful, |
21 | 1 | pfleura2 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | 1 | pfleura2 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
23 | 1 | pfleura2 | ! Lesser General Public License for more details. |
24 | 1 | pfleura2 | ! |
25 | 1 | pfleura2 | |
26 | 1 | pfleura2 | ! You should have received a copy of the GNU Lesser General Public |
27 | 1 | pfleura2 | ! License along with this library; if not, write to the Free Software |
28 | 1 | pfleura2 | ! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
29 | 1 | pfleura2 | !---------------------------------------------------------------------------- |
30 | 12 | pfleura2 | !---------------------------------------------------------------------- |
31 | 12 | pfleura2 | ! Copyright 2003-2014 Ecole Normale Supérieure de Lyon, |
32 | 12 | pfleura2 | ! Centre National de la Recherche Scientifique, |
33 | 12 | pfleura2 | ! Université Claude Bernard Lyon 1. All rights reserved. |
34 | 12 | pfleura2 | ! |
35 | 12 | pfleura2 | ! This work is registered with the Agency for the Protection of Programs |
36 | 12 | pfleura2 | ! as IDDN.FR.001.100009.000.S.P.2014.000.30625 |
37 | 12 | pfleura2 | ! |
38 | 12 | pfleura2 | ! Authors: P. Fleurat-Lessard, P. Dayal |
39 | 12 | pfleura2 | ! Contact: optnpath@gmail.com |
40 | 12 | pfleura2 | ! |
41 | 12 | pfleura2 | ! This file is part of "Opt'n Path". |
42 | 12 | pfleura2 | ! |
43 | 12 | pfleura2 | ! "Opt'n Path" is free software: you can redistribute it and/or modify |
44 | 12 | pfleura2 | ! it under the terms of the GNU Affero General Public License as |
45 | 12 | pfleura2 | ! published by the Free Software Foundation, either version 3 of the License, |
46 | 12 | pfleura2 | ! or (at your option) any later version. |
47 | 12 | pfleura2 | ! |
48 | 12 | pfleura2 | ! "Opt'n Path" is distributed in the hope that it will be useful, |
49 | 12 | pfleura2 | ! but WITHOUT ANY WARRANTY; without even the implied warranty of |
50 | 12 | pfleura2 | ! |
51 | 12 | pfleura2 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
52 | 12 | pfleura2 | ! GNU Affero General Public License for more details. |
53 | 12 | pfleura2 | ! |
54 | 12 | pfleura2 | ! You should have received a copy of the GNU Affero General Public License |
55 | 12 | pfleura2 | ! along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>. |
56 | 12 | pfleura2 | ! |
57 | 12 | pfleura2 | ! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr, |
58 | 12 | pfleura2 | ! for commercial licensing opportunities. |
59 | 12 | pfleura2 | !---------------------------------------------------------------------- |
60 | 1 | pfleura2 | |
61 | 1 | pfleura2 | subroutine CalcRmsd(Nat,x0,y0,z0, x2,y2,z2,U,rmsd,FRot,FAlign) |
62 | 1 | pfleura2 | !----------------------------------------------------------------------- |
63 | 1 | pfleura2 | ! This subroutine calculates the least square rmsd of two coordinate |
64 | 1 | pfleura2 | ! sets coord1(3,n) and coord2(3,n) using a method based on quaternion. |
65 | 1 | pfleura2 | ! It then calculate the rotation matrix U and the centers of coord, and uses |
66 | 1 | pfleura2 | ! them to align the two molecules. |
67 | 1 | pfleura2 | ! x0(Nat), y0(Nat), z0(Nat) are the coordinates of the reference geometry. |
68 | 1 | pfleura2 | ! x2(Nat), y2(Nat), z2(Nat) are the coordinates of the geometry which is to |
69 | 1 | pfleura2 | ! be aligned with the reference geometry. |
70 | 1 | pfleura2 | ! The rotation matrix U has INTENT(OUT) in subroutine rotation_matrix(...), |
71 | 1 | pfleura2 | ! which is called in this CalcRmsd(...). |
72 | 1 | pfleura2 | ! rmsd: the root mean square deviation and calculated in this subroutine |
73 | 1 | pfleura2 | ! CalcRmsd(...). |
74 | 1 | pfleura2 | ! FRot: if .TRUE. the rotation matrix is calculated. This is the matrix that rotates |
75 | 1 | pfleura2 | ! the first molecule onto the second one. |
76 | 1 | pfleura2 | ! FAlgin: if .TRUE. then the second molecule is aligned on the first one. |
77 | 1 | pfleura2 | !----------------------------------------------------------------------- |
78 | 1 | pfleura2 | |
79 | 1 | pfleura2 | use VarTypes |
80 | 1 | pfleura2 | |
81 | 1 | pfleura2 | IMPLICIT NONE |
82 | 1 | pfleura2 | |
83 | 1 | pfleura2 | INTEGER(KINT) :: Nat |
84 | 1 | pfleura2 | real(KREAL) :: x0(Nat),y0(Nat),z0(Nat) |
85 | 1 | pfleura2 | real(KREAL) :: x2(Nat),y2(Nat),z2(Nat) |
86 | 1 | pfleura2 | real(KREAL) :: U(3,3), rmsd |
87 | 1 | pfleura2 | LOGICAL FRot,FAlign,Debug |
88 | 1 | pfleura2 | |
89 | 11 | pfleura2 | REAL(KREAL),ALLOCATABLE :: Coord1(:,:), Coord2(:,:) ! 3,Nat |
90 | 1 | pfleura2 | real(KREAL) :: x0c1,y0c1,z0c1, xc2,yc2,zc2 |
91 | 1 | pfleura2 | |
92 | 1 | pfleura2 | |
93 | 2 | pfleura2 | INTEGER(KINT) :: i, j, ia |
94 | 1 | pfleura2 | real(KREAL) :: x_norm, y_norm, lambda |
95 | 1 | pfleura2 | real(KREAL) :: Rmatrix(3,3) |
96 | 2 | pfleura2 | real(KREAL) :: S(4, 4) |
97 | 2 | pfleura2 | real(KREAL) :: EigVec(4, 4), EigVal(4) |
98 | 1 | pfleura2 | |
99 | 1 | pfleura2 | INTERFACE |
100 | 1 | pfleura2 | function valid(string) result (isValid) |
101 | 1 | pfleura2 | CHARACTER(*), intent(in) :: string |
102 | 1 | pfleura2 | logical :: isValid |
103 | 1 | pfleura2 | END function VALID |
104 | 1 | pfleura2 | END INTERFACE |
105 | 1 | pfleura2 | |
106 | 1 | pfleura2 | |
107 | 1 | pfleura2 | debug=valid('CalcRmsd').OR.valid('align').OR.valid('alignpartial') |
108 | 1 | pfleura2 | |
109 | 11 | pfleura2 | if (debug) Call Header("Entering CalcRmsd") |
110 | 11 | pfleura2 | |
111 | 11 | pfleura2 | if (debug) THEN |
112 | 11 | pfleura2 | WRITE(*,*) "NAt=",NAt |
113 | 11 | pfleura2 | WRITE(*,*) x0 |
114 | 11 | pfleura2 | WRITE(*,*) y0 |
115 | 11 | pfleura2 | WRITE(*,*) z0 |
116 | 11 | pfleura2 | END IF |
117 | 11 | pfleura2 | |
118 | 11 | pfleura2 | ALLOCATE(Coord1(3,Nat),Coord2(3,Nat)) |
119 | 1 | pfleura2 | ! calculate the barycenters, centroidal coordinates, and the norms |
120 | 1 | pfleura2 | x_norm = 0.0d0 |
121 | 1 | pfleura2 | y_norm = 0.0d0 |
122 | 1 | pfleura2 | x0c1=0. |
123 | 1 | pfleura2 | y0c1=0. |
124 | 1 | pfleura2 | z0c1=0. |
125 | 1 | pfleura2 | xc2=0. |
126 | 1 | pfleura2 | yc2=0. |
127 | 1 | pfleura2 | zc2=0. |
128 | 1 | pfleura2 | do ia=1,Nat |
129 | 11 | pfleura2 | if (debug) WRITE(*,'(A,I5,4(1X,F10.4))') 'ia...',ia,x0(ia), & |
130 | 11 | pfleura2 | x2(ia),x0c1,xc2 |
131 | 1 | pfleura2 | x0c1=x0c1+x0(ia) |
132 | 1 | pfleura2 | xc2=xc2+x2(ia) |
133 | 1 | pfleura2 | y0c1=y0c1+y0(ia) |
134 | 1 | pfleura2 | yc2=yc2+y2(ia) |
135 | 1 | pfleura2 | z0c1=z0c1+z0(ia) |
136 | 1 | pfleura2 | zc2=zc2+z2(ia) |
137 | 11 | pfleura2 | if (debug) WRITE(*,'(A,I5,4(1X,F10.4))') 'ia...',ia,x0(ia), & |
138 | 11 | pfleura2 | x2(ia),x0c1,xc2 |
139 | 1 | pfleura2 | END DO |
140 | 1 | pfleura2 | x0c1=x0c1/dble(Nat) |
141 | 1 | pfleura2 | y0c1=y0c1/dble(Nat) |
142 | 1 | pfleura2 | z0c1=z0c1/dble(Nat) |
143 | 1 | pfleura2 | xc2=xc2/dble(Nat) |
144 | 1 | pfleura2 | yc2=yc2/dble(Nat) |
145 | 1 | pfleura2 | zc2=zc2/dble(Nat) |
146 | 1 | pfleura2 | |
147 | 1 | pfleura2 | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center1',x0c1,y0c1,z0c1 |
148 | 1 | pfleura2 | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center2',xc2,yc2,zc2 |
149 | 1 | pfleura2 | do i=1,Nat |
150 | 1 | pfleura2 | Coord1(1,i)=x0(i)-x0c1 |
151 | 1 | pfleura2 | Coord1(2,i)=y0(i)-y0c1 |
152 | 1 | pfleura2 | Coord1(3,i)=z0(i)-z0c1 |
153 | 1 | pfleura2 | Coord2(1,i)=x2(i)-xc2 |
154 | 1 | pfleura2 | Coord2(2,i)=y2(i)-yc2 |
155 | 1 | pfleura2 | Coord2(3,i)=z2(i)-zc2 |
156 | 1 | pfleura2 | x_norm=x_norm+Coord1(1,i)**2+Coord1(2,i)**2+Coord1(3,i)**2 |
157 | 1 | pfleura2 | y_norm=y_norm+Coord2(1,i)**2+Coord2(2,i)**2+Coord2(3,i)**2 |
158 | 1 | pfleura2 | end do |
159 | 1 | pfleura2 | |
160 | 1 | pfleura2 | IF (debug) THEN |
161 | 1 | pfleura2 | WRITE(*,*) "R matrix" |
162 | 1 | pfleura2 | DO I=1,3 |
163 | 1 | pfleura2 | WRITE(*,*) (RMatrix(I,j),j=1,3) |
164 | 1 | pfleura2 | END DO |
165 | 1 | pfleura2 | END IF |
166 | 1 | pfleura2 | |
167 | 1 | pfleura2 | ! calculate the R matrix |
168 | 1 | pfleura2 | do i = 1, 3 |
169 | 1 | pfleura2 | do j = 1, 3 |
170 | 1 | pfleura2 | Rmatrix(i,j)=0. |
171 | 1 | pfleura2 | do ia=1,Nat |
172 | 1 | pfleura2 | Rmatrix(i,j) = Rmatrix(i,j)+Coord1(i,ia)*Coord2(j,ia) |
173 | 1 | pfleura2 | END DO |
174 | 1 | pfleura2 | end do |
175 | 1 | pfleura2 | end do |
176 | 1 | pfleura2 | |
177 | 1 | pfleura2 | IF (debug) THEN |
178 | 1 | pfleura2 | WRITE(*,*) "R matrix" |
179 | 1 | pfleura2 | DO I=1,3 |
180 | 1 | pfleura2 | WRITE(*,*) (RMatrix(I,j),j=1,3) |
181 | 1 | pfleura2 | END DO |
182 | 1 | pfleura2 | END IF |
183 | 1 | pfleura2 | |
184 | 1 | pfleura2 | |
185 | 1 | pfleura2 | ! S matrix |
186 | 1 | pfleura2 | S(1, 1) = Rmatrix(1, 1) + Rmatrix(2, 2) + Rmatrix(3, 3) |
187 | 1 | pfleura2 | S(2, 1) = Rmatrix(2, 3) - Rmatrix(3, 2) |
188 | 1 | pfleura2 | S(3, 1) = Rmatrix(3, 1) - Rmatrix(1, 3) |
189 | 1 | pfleura2 | S(4, 1) = Rmatrix(1, 2) - Rmatrix(2, 1) |
190 | 1 | pfleura2 | |
191 | 1 | pfleura2 | S(1, 2) = S(2, 1) |
192 | 1 | pfleura2 | S(2, 2) = Rmatrix(1, 1) - Rmatrix(2, 2) - Rmatrix(3, 3) |
193 | 1 | pfleura2 | S(3, 2) = Rmatrix(1, 2) + Rmatrix(2, 1) |
194 | 1 | pfleura2 | S(4, 2) = Rmatrix(1, 3) + Rmatrix(3, 1) |
195 | 1 | pfleura2 | |
196 | 1 | pfleura2 | S(1, 3) = S(3, 1) |
197 | 1 | pfleura2 | S(2, 3) = S(3, 2) |
198 | 1 | pfleura2 | S(3, 3) =-Rmatrix(1, 1) + Rmatrix(2, 2) - Rmatrix(3, 3) |
199 | 1 | pfleura2 | S(4, 3) = Rmatrix(2, 3) + Rmatrix(3, 2) |
200 | 1 | pfleura2 | |
201 | 1 | pfleura2 | S(1, 4) = S(4, 1) |
202 | 1 | pfleura2 | S(2, 4) = S(4, 2) |
203 | 1 | pfleura2 | S(3, 4) = S(4, 3) |
204 | 1 | pfleura2 | S(4, 4) =-Rmatrix(1, 1) - Rmatrix(2, 2) + Rmatrix(3, 3) |
205 | 1 | pfleura2 | |
206 | 1 | pfleura2 | |
207 | 1 | pfleura2 | ! PFL : I use my usual Jacobi diagonalisation |
208 | 1 | pfleura2 | ! Calculate eigenvalues and eigenvectors, and |
209 | 1 | pfleura2 | ! take the maximum eigenvalue lambda and the corresponding eigenvector q. |
210 | 1 | pfleura2 | |
211 | 1 | pfleura2 | IF (debug) THEN |
212 | 1 | pfleura2 | WRITE(*,*) "S matrix" |
213 | 1 | pfleura2 | DO I=1,4 |
214 | 1 | pfleura2 | WRITE(*,*) (S(I,j),j=1,4) |
215 | 1 | pfleura2 | END DO |
216 | 1 | pfleura2 | END IF |
217 | 1 | pfleura2 | |
218 | 1 | pfleura2 | Call Jacobi(S,4,EigVal,EigVec,4) |
219 | 1 | pfleura2 | |
220 | 1 | pfleura2 | Call Trie(4,EigVal,EigVec,4) |
221 | 1 | pfleura2 | |
222 | 1 | pfleura2 | Lambda=EigVal(4) |
223 | 1 | pfleura2 | |
224 | 1 | pfleura2 | ! RMS Deviation |
225 | 1 | pfleura2 | rmsd=sqrt(max(0.0d0,((x_norm+y_norm)-2.0d0*lambda))/dble(Nat)) |
226 | 1 | pfleura2 | ! The subroutine rotation_matrix(...) constructs rotation matrix U as output |
227 | 1 | pfleura2 | ! from the input quaternion EigVec(1,4). |
228 | 1 | pfleura2 | if (FRot.OR.FAlign) Call rotation_matrix(EigVec(1,4),U) |
229 | 1 | pfleura2 | IF (FAlign) THEN |
230 | 1 | pfleura2 | DO I=1,Nat |
231 | 1 | pfleura2 | x2(i)=Coord2(1,i)*U(1,1)+Coord2(2,i)*U(2,1) & |
232 | 1 | pfleura2 | +Coord2(3,i)*U(3,1) +x0c1 |
233 | 1 | pfleura2 | y2(i)=Coord2(1,i)*U(1,2)+Coord2(2,i)*U(2,2) & |
234 | 1 | pfleura2 | +Coord2(3,i)*U(3,2) +y0c1 |
235 | 1 | pfleura2 | z2(i)=Coord2(1,i)*U(1,3)+Coord2(2,i)*U(2,3) & |
236 | 1 | pfleura2 | +Coord2(3,i)*U(3,3) +z0c1 |
237 | 1 | pfleura2 | END DO |
238 | 1 | pfleura2 | END IF |
239 | 1 | pfleura2 | |
240 | 11 | pfleura2 | DEALLOCATE(Coord1,Coord2) |
241 | 11 | pfleura2 | |
242 | 11 | pfleura2 | END subroutine CalcRmsd |