root / src / AlignPartial.f90 @ 2
Historique | Voir | Annoter | Télécharger (5,3 ko)
1 | 1 | equemene | subroutine AlignPartial(na, x,y,z,x2,y2,z2,ListAt,U) |
---|---|---|---|
2 | 1 | equemene | !----------------------------------------------------------------------- |
3 | 1 | equemene | ! This subroutine calculates the least square rmsd of two coordinate |
4 | 1 | equemene | ! sets coord1(3,n) and coord2(3,n) using a method based on quaternion. |
5 | 1 | equemene | ! It then calculate the rotation matrix U and the centers of coord, and uses |
6 | 1 | equemene | ! them to align the two molecules. |
7 | 1 | equemene | ! This new version does not use all atoms to calculate the RMSD and rotation matrix |
8 | 1 | equemene | ! but only those which are 'true' in ListAt |
9 | 1 | equemene | !----------------------------------------------------------------------- |
10 | 1 | equemene | ! Input parameters: |
11 | 1 | equemene | ! Na : number of atoms |
12 | 1 | equemene | ! x,y,z : coordinates of the first geometry |
13 | 1 | equemene | ! x2,y2,z2 : coordinates of the second geometry |
14 | 1 | equemene | ! ListAt : Logical, T if this atom should be considered in the RMSD calc and |
15 | 1 | equemene | ! alignment. |
16 | 1 | equemene | ! Debug : True if additionnal printing is requiered |
17 | 1 | equemene | ! |
18 | 1 | equemene | ! output parameters: |
19 | 1 | equemene | ! U : Real, (3x3) matrix for rotation |
20 | 1 | equemene | ! Rmsd : Read, the rmsd |
21 | 1 | equemene | ! x2,y2,z2 : coordinates of the second geometry ALIGNED to the first one |
22 | 1 | equemene | !----------------------------------------------------------------------- |
23 | 1 | equemene | |
24 | 1 | equemene | Use VarTypes |
25 | 1 | equemene | IMPLICIT NONE |
26 | 1 | equemene | |
27 | 1 | equemene | |
28 | 1 | equemene | integer(KINT) :: na, NaT |
29 | 1 | equemene | Real(KREAL) :: x(na),y(Na),z(Na) |
30 | 1 | equemene | Real(KREAL) :: x2(Na),y2(Na),z2(Na) |
31 | 1 | equemene | Real(KREAL) :: U(3,3), rmsd |
32 | 1 | equemene | LOGICAL Debug, ListAt(Na) |
33 | 1 | equemene | |
34 | 1 | equemene | REAL(KREAL) :: Coord1(3,Na), Coord2(3,Na) |
35 | 1 | equemene | Real(KREAL) :: xc1,yc1,zc1, xc2,yc2,zc2 |
36 | 1 | equemene | |
37 | 1 | equemene | |
38 | 1 | equemene | integer(KINT) :: i, j, nd, ia |
39 | 1 | equemene | Real(KREAL) :: x_norm, y_norm, lambda |
40 | 1 | equemene | Real(KREAL) :: Rmatrix(3,3) |
41 | 1 | equemene | Real(KREAL) :: S(4,4), dS(4,4), q(4) |
42 | 1 | equemene | Real(KREAL) :: tmp(3),tmp1(4),tmp2(4),EigVec(4,4), EigVal(4) |
43 | 1 | equemene | |
44 | 1 | equemene | INTERFACE |
45 | 1 | equemene | function valid(string) result (isValid) |
46 | 1 | equemene | CHARACTER(*), intent(in) :: string |
47 | 1 | equemene | logical :: isValid |
48 | 1 | equemene | END function VALID |
49 | 1 | equemene | END INTERFACE |
50 | 1 | equemene | |
51 | 1 | equemene | |
52 | 1 | equemene | debug=valid('CalcRmsd').OR.valid('align').OR.valid('alignpartial') |
53 | 1 | equemene | |
54 | 1 | equemene | ! calculate the barycenters, centroidal coordinates, and the norms |
55 | 1 | equemene | x_norm = 0.0d0 |
56 | 1 | equemene | y_norm = 0.0d0 |
57 | 1 | equemene | xc1=0. |
58 | 1 | equemene | yc1=0. |
59 | 1 | equemene | zc1=0. |
60 | 1 | equemene | xc2=0. |
61 | 1 | equemene | yc2=0. |
62 | 1 | equemene | zc2=0. |
63 | 1 | equemene | |
64 | 1 | equemene | if (debug) THEN |
65 | 1 | equemene | WRITE(*,*) "DBG AlignPartial X2,Y2,Z2 before align" |
66 | 1 | equemene | DO Ia=1,na |
67 | 1 | equemene | WRITE(*,*) x2(ia),y2(ia),z2(ia) |
68 | 1 | equemene | END DO |
69 | 1 | equemene | END IF |
70 | 1 | equemene | |
71 | 1 | equemene | NAt=0 |
72 | 1 | equemene | do ia=1,na |
73 | 1 | equemene | IF (listat(ia)) THEN |
74 | 1 | equemene | Nat=NAt+1 |
75 | 1 | equemene | xc1=xc1+x(ia) |
76 | 1 | equemene | xc2=xc2+x2(ia) |
77 | 1 | equemene | yc1=yc1+y(ia) |
78 | 1 | equemene | yc2=yc2+y2(ia) |
79 | 1 | equemene | zc1=zc1+z(ia) |
80 | 1 | equemene | zc2=zc2+z2(ia) |
81 | 1 | equemene | ! if (debug) WRITE(*,'(A,I5,4(1X,F10.4))') 'ia...',ia,x(ia), |
82 | 1 | equemene | ! & x2(ia),xc1,xc2 |
83 | 1 | equemene | END IF |
84 | 1 | equemene | END DO |
85 | 1 | equemene | |
86 | 1 | equemene | if (Nat.EQ.0) THEN |
87 | 1 | equemene | WRITE(*,*) "ERROR, AlignPartial: ListAt is empty :-)" |
88 | 1 | equemene | END IF |
89 | 1 | equemene | xc1=xc1/dble(nat) |
90 | 1 | equemene | yc1=yc1/dble(nat) |
91 | 1 | equemene | zc1=zc1/dble(nat) |
92 | 1 | equemene | xc2=xc2/dble(nat) |
93 | 1 | equemene | yc2=yc2/dble(nat) |
94 | 1 | equemene | zc2=zc2/dble(nat) |
95 | 1 | equemene | |
96 | 1 | equemene | IF (Debug) WRITE(*,*) 'Found :', Nat, ' atoms' |
97 | 1 | equemene | IF (debug) WRITE(*,*) (ListAt(I),I=1,Na) |
98 | 1 | equemene | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center1',xc1,yc1,zc1 |
99 | 1 | equemene | IF (debug) WRITE(*,'(1X,A,3(1X,F10.4))') 'Center2',xc2,yc2,zc2 |
100 | 1 | equemene | do i=1,na |
101 | 1 | equemene | Coord1(1,i)=x(i)-xc1 |
102 | 1 | equemene | Coord1(2,i)=y(i)-yc1 |
103 | 1 | equemene | Coord1(3,i)=z(i)-zc1 |
104 | 1 | equemene | Coord2(1,i)=x2(i)-xc2 |
105 | 1 | equemene | Coord2(2,i)=y2(i)-yc2 |
106 | 1 | equemene | Coord2(3,i)=z2(i)-zc2 |
107 | 1 | equemene | IF (ListAt(I)) THEN |
108 | 1 | equemene | x_norm=x_norm+Coord1(1,i)**2+Coord1(2,i)**2+Coord1(3,i)**2 |
109 | 1 | equemene | y_norm=y_norm+Coord2(1,i)**2+Coord2(2,i)**2+Coord2(3,i)**2 |
110 | 1 | equemene | END IF |
111 | 1 | equemene | end do |
112 | 1 | equemene | |
113 | 1 | equemene | ! calculate the R matrix |
114 | 1 | equemene | do i = 1, 3 |
115 | 1 | equemene | do j = 1, 3 |
116 | 1 | equemene | Rmatrix(i,j)=0. |
117 | 1 | equemene | do ia=1,na |
118 | 1 | equemene | If (ListAt(ia)) Rmatrix(i,j) = Rmatrix(i,j)+Coord1(i,ia)*Coord2(j,ia) |
119 | 1 | equemene | END DO |
120 | 1 | equemene | end do |
121 | 1 | equemene | end do |
122 | 1 | equemene | |
123 | 1 | equemene | IF (debug) THEN |
124 | 1 | equemene | WRITE(*,*) "R matrix" |
125 | 1 | equemene | DO I=1,3 |
126 | 1 | equemene | WRITE(*,*) (RMatrix(I,j),j=1,3) |
127 | 1 | equemene | END DO |
128 | 1 | equemene | END IF |
129 | 1 | equemene | |
130 | 1 | equemene | |
131 | 1 | equemene | ! S matrix |
132 | 1 | equemene | S(1, 1) = Rmatrix(1, 1) + Rmatrix(2, 2) + Rmatrix(3, 3) |
133 | 1 | equemene | S(2, 1) = Rmatrix(2, 3) - Rmatrix(3, 2) |
134 | 1 | equemene | S(3, 1) = Rmatrix(3, 1) - Rmatrix(1, 3) |
135 | 1 | equemene | S(4, 1) = Rmatrix(1, 2) - Rmatrix(2, 1) |
136 | 1 | equemene | |
137 | 1 | equemene | S(1, 2) = S(2, 1) |
138 | 1 | equemene | S(2, 2) = Rmatrix(1, 1) - Rmatrix(2, 2) - Rmatrix(3, 3) |
139 | 1 | equemene | S(3, 2) = Rmatrix(1, 2) + Rmatrix(2, 1) |
140 | 1 | equemene | S(4, 2) = Rmatrix(1, 3) + Rmatrix(3, 1) |
141 | 1 | equemene | |
142 | 1 | equemene | S(1, 3) = S(3, 1) |
143 | 1 | equemene | S(2, 3) = S(3, 2) |
144 | 1 | equemene | S(3, 3) =-Rmatrix(1, 1) + Rmatrix(2, 2) - Rmatrix(3, 3) |
145 | 1 | equemene | S(4, 3) = Rmatrix(2, 3) + Rmatrix(3, 2) |
146 | 1 | equemene | |
147 | 1 | equemene | S(1, 4) = S(4, 1) |
148 | 1 | equemene | S(2, 4) = S(4, 2) |
149 | 1 | equemene | S(3, 4) = S(4, 3) |
150 | 1 | equemene | S(4, 4) =-Rmatrix(1, 1) - Rmatrix(2, 2) + Rmatrix(3, 3) |
151 | 1 | equemene | |
152 | 1 | equemene | |
153 | 1 | equemene | ! PFL : I use my usual Jacobi diagonalisation |
154 | 1 | equemene | ! Calculate eigenvalues and eigenvectors, and |
155 | 1 | equemene | ! take the maximum eigenvalue lambda and the corresponding eigenvector q. |
156 | 1 | equemene | |
157 | 1 | equemene | IF (debug) THEN |
158 | 1 | equemene | WRITE(*,*) "S matrix" |
159 | 1 | equemene | DO I=1,4 |
160 | 1 | equemene | WRITE(*,*) (S(I,j),j=1,4) |
161 | 1 | equemene | END DO |
162 | 1 | equemene | END IF |
163 | 1 | equemene | |
164 | 1 | equemene | Call Jacobi(S,4,EigVal,EigVec,4) |
165 | 1 | equemene | |
166 | 1 | equemene | Call Trie(4,EigVal,EigVec,4) |
167 | 1 | equemene | |
168 | 1 | equemene | Lambda=EigVal(4) |
169 | 1 | equemene | |
170 | 1 | equemene | ! RMS Deviation |
171 | 1 | equemene | rmsd=sqrt(max(0.0d0,((x_norm+y_norm)-2.0d0*lambda))/dble(nat)) |
172 | 1 | equemene | if (debug) WRITE(*,*) "AlignPartial rmsd:",rmsd |
173 | 1 | equemene | Call rotation_matrix(EigVec(1,4),U) |
174 | 1 | equemene | |
175 | 1 | equemene | |
176 | 1 | equemene | IF (debug) THEN |
177 | 1 | equemene | WRITE(*,*) "U matrix" |
178 | 1 | equemene | DO I=1,3 |
179 | 1 | equemene | WRITE(*,*) (U(I,j),j=1,3) |
180 | 1 | equemene | END DO |
181 | 1 | equemene | END IF |
182 | 1 | equemene | |
183 | 1 | equemene | DO I=1,na |
184 | 1 | equemene | x2(i)=Coord2(1,i)*U(1,1)+Coord2(2,i)*U(2,1) + Coord2(3,i)*U(3,1) +xc1 |
185 | 1 | equemene | y2(i)=Coord2(1,i)*U(1,2)+Coord2(2,i)*U(2,2) + Coord2(3,i)*U(3,2) +yc1 |
186 | 1 | equemene | z2(i)=Coord2(1,i)*U(1,3)+Coord2(2,i)*U(2,3) + Coord2(3,i)*U(3,3) +zc1 |
187 | 1 | equemene | END DO |
188 | 1 | equemene | |
189 | 1 | equemene | if (debug) THEN |
190 | 1 | equemene | WRITE(*,*) "DBG AlignPartial X2,Y2,Z2 after align" |
191 | 1 | equemene | DO Ia=1,na |
192 | 1 | equemene | WRITE(*,*) x2(ia),y2(ia),z2(ia) |
193 | 1 | equemene | END DO |
194 | 1 | equemene | END IF |
195 | 1 | equemene | |
196 | 1 | equemene | |
197 | 1 | equemene | END subroutine AlignPartial |