Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2016-2019 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 :
23 : /*
24 : This vast majority of the source code in this file was writting by
25 : Sandro Bottaro with some help from Giovanni Bussi
26 : */
27 :
28 : #include "ERMSD.h"
29 : #include "PDB.h"
30 : #include "Matrix.h"
31 : #include "Tensor.h"
32 :
33 : #include "Pbc.h"
34 : #include <cmath>
35 : #include <iostream>
36 :
37 :
38 : using namespace std;
39 : namespace PLMD {
40 :
41 :
42 0 : void ERMSD::clear() {
43 : reference_mat.clear();
44 0 : }
45 :
46 : //void ERMSD::calcLcs(const vector<Vector> & positions, vector<Vector> &)
47 :
48 4 : void ERMSD::setReference(const vector<Vector> & reference, const std::vector<unsigned> & pairs_vec, double mycutoff) {
49 :
50 :
51 4 : natoms = reference.size();
52 4 : nresidues = natoms/3;
53 4 : unsigned npairs = pairs_vec.size()/2;
54 4 : pairs.resize(npairs);
55 : //for(unsigned i=0;i<2*npairs;++i) {
56 : // std::cout << "CCC " << pairs_vec[i] << " ";
57 : //}
58 28 : for(unsigned i=0; i<npairs; ++i) {
59 :
60 36 : pairs[i].first = pairs_vec[2*i];
61 24 : pairs[i].second = pairs_vec[2*i+1];
62 : }
63 :
64 4 : cutoff = mycutoff;
65 : std::vector<TensorGeneric<4,3> > deri;
66 4 : deri.resize(natoms*natoms);
67 4 : reference_mat.resize(nresidues*nresidues);
68 4 : Pbc fake_pbc;
69 :
70 :
71 4 : calcMat(reference,fake_pbc,reference_mat,deri);
72 :
73 4 : }
74 :
75 :
76 1139266 : bool ERMSD::inPair(unsigned i, unsigned j) {
77 :
78 : //return true;
79 1139266 : if(pairs.size()==0) return true;
80 7395737 : for(unsigned idx=0; idx<pairs.size(); idx++) {
81 : //std::cout << "AAA " << pairs[idx][0] << " " << pairs[idx][1] << "\n";
82 3414408 : if(pairs[idx].first == i && pairs[idx].second == j) return true;
83 3413730 : if(pairs[idx].second == i && pairs[idx].first == j) return true;
84 : }
85 : return false;
86 : }
87 : //double ERMSD::calculate(const std::vector<Vector> & positions,
88 : // std::vector<Vector> &derivatives, Tensor& virial) const {
89 :
90 : // Pbc fake_pbc;
91 : // return ERMSD::calculate(positions,fake_pbc,derivatives,virial,false);
92 : // }
93 :
94 :
95 :
96 226 : void ERMSD::calcMat(const std::vector<Vector> & positions,const Pbc& pbc, std::vector<Vector4d> &mat, std::vector<TensorGeneric<4,3> > &Gderi) {
97 :
98 : std::vector<Vector3d> pos;
99 226 : pos.resize(3*nresidues);
100 :
101 : std::vector<Tensor3d> deri;
102 226 : deri.resize(nresidues*9);
103 :
104 : std::vector<Vector> centers;
105 226 : centers.resize(nresidues);
106 :
107 : unsigned idx_deri = 0;
108 :
109 226 : Tensor da_dxa = (2./3.)*Tensor::identity();
110 226 : Tensor da_dxb = -(1./3.)*Tensor::identity();
111 226 : Tensor da_dxc = -(1./3.)*Tensor::identity();
112 :
113 226 : Tensor db_dxa = -(1./3.)*Tensor::identity();
114 226 : Tensor db_dxb = (2./3.)*Tensor::identity();
115 226 : Tensor db_dxc = -(1./3.)*Tensor::identity();
116 :
117 : // Form factors - should this be somewhere else?
118 :
119 : double w = 1./3.;
120 : Vector form_factor = Vector(2.0,2.0,1.0/0.3);
121 :
122 32318 : for(unsigned res_idx=0; res_idx<natoms/3; res_idx++) {
123 :
124 :
125 16046 : const unsigned at_idx = 3*res_idx;
126 : //center
127 112322 : for (unsigned j=0; j<3; j++) {
128 144414 : centers[res_idx] += w*positions[at_idx+j];
129 : }
130 :
131 48138 : Vector3d a = delta(centers[res_idx],positions[at_idx]);
132 32092 : Vector3d b = delta(centers[res_idx],positions[at_idx+1]);
133 16046 : Vector3d d = crossProduct(a,b);
134 16046 : double ianorm = 1./a.modulo();
135 16046 : double idnorm = 1./d.modulo();
136 :
137 : // X vector: COM-C2
138 16046 : pos[at_idx] = a*ianorm;
139 : // Z versor: C2 x (COM-C4/C6)
140 32092 : pos[at_idx+2] = d*idnorm;
141 : // Y versor: Z x Y
142 16046 : pos[at_idx+1] = crossProduct(pos[at_idx+2],pos[at_idx]);
143 :
144 : // Derivatives ////////
145 16046 : Tensor3d t1 = ianorm*(Tensor::identity()-extProduct(pos[at_idx],pos[at_idx]));
146 : // dv1/dxa
147 32092 : deri[idx_deri] = (2./3. )*t1;
148 : // dv1/dxb
149 32092 : deri[idx_deri+3] = -(1./3.)*t1;
150 : // dv1/dxc
151 32092 : deri[idx_deri+6] = -(1./3.)*t1;
152 :
153 16046 : Tensor dd_dxa = VcrossTensor(a,db_dxa) -VcrossTensor(b,da_dxa);
154 16046 : Tensor dd_dxb = VcrossTensor(a,db_dxb)-VcrossTensor(b,da_dxb);
155 16046 : Tensor dd_dxc = VcrossTensor(a,db_dxc)-VcrossTensor(b,da_dxc);
156 :
157 : // dv3/dxa
158 32092 : deri[idx_deri+2] = deriNorm(d,dd_dxa);
159 : // dv3/dxb
160 32092 : deri[idx_deri+5] = deriNorm(d,dd_dxb);
161 : // dv3/dxc
162 32092 : deri[idx_deri+8] = deriNorm(d,dd_dxc);
163 :
164 : // dv2/dxa = dv3/dxa cross v1 + v3 cross dv1/dxa
165 32092 : deri[idx_deri+1] = (VcrossTensor(deri[idx_deri+2],pos[at_idx]) + \
166 32092 : VcrossTensor(pos[at_idx+2],deri[idx_deri]));
167 : // dv2/dxb
168 32092 : deri[idx_deri+4] = (VcrossTensor(deri[idx_deri+5],pos[at_idx]) + \
169 32092 : VcrossTensor(pos[at_idx+2],deri[idx_deri+3]));
170 : // dv2/dxc
171 32092 : deri[idx_deri+7] = (VcrossTensor(deri[idx_deri+8],pos[at_idx]) + \
172 32092 : VcrossTensor(pos[at_idx+2],deri[idx_deri+6]));
173 :
174 16046 : idx_deri += 9;
175 : // End derivatives ///////
176 :
177 : }
178 :
179 :
180 : // Initialization (unnecessary?)
181 2278758 : for (unsigned i1=0; i1<nresidues*nresidues; i1++) {
182 10253394 : for (unsigned i2=0; i2<4; i2++) {
183 9114128 : mat[i1][i2] = 0.0;
184 : }
185 : }
186 :
187 226 : double maxdist = cutoff/form_factor[0];
188 226 : double gamma = pi/cutoff;
189 : unsigned idx;
190 : unsigned idx1 = 0;
191 : // Calculate mat
192 32318 : for (unsigned i=0; i<nresidues; i++) {
193 2294578 : for (unsigned j=0; j<nresidues; j++) {
194 :
195 : // skip i==j
196 1139266 : if(inPair(i,j) and i != j) {
197 : //if(i!=j){
198 :
199 :
200 : // Calculate normal distance first
201 1688898 : Vector diff = delta(centers[i],centers[j]);
202 562966 : double d1 = diff.modulo();
203 : //std::cout << inPair(i,j) << " " << i << " " << j << " "<< d1 <<"\n";
204 : //std::cout << inPair(i,j) << " " << i << " " << j << " "<< d1 <<"\n";
205 562966 : if(d1<maxdist) {
206 :
207 : // calculate r_tilde_ij
208 85382 : Vector3d rtilde;
209 597674 : for (unsigned k=0; k<3; k++) {
210 1793022 : for (unsigned l=0; l<3; l++) {
211 1536876 : rtilde[l] += pos[3*i+l][k]*diff[k]*form_factor[l];
212 : }
213 : }
214 85382 : double rtilde_norm = rtilde.modulo();
215 :
216 85382 : double irnorm = 1./rtilde_norm;
217 :
218 : // ellipsoidal cutoff
219 85382 : if(rtilde_norm < cutoff) {
220 53822 : idx = i*nresidues + j;
221 : //std::cout << i << " " << j << " " << rtilde_norm << " " << idx <<"\n";
222 :
223 :
224 : // fill 4d matrix
225 53822 : double dummy = sin(gamma*rtilde_norm)/(rtilde_norm*gamma);
226 107644 : mat[idx][0] = dummy*rtilde[0];
227 107644 : mat[idx][1] = dummy*rtilde[1];
228 107644 : mat[idx][2] = dummy*rtilde[2];
229 107644 : mat[idx][3] = (1.+ cos(gamma*rtilde_norm))/gamma;
230 :
231 : // Derivative (drtilde_dx)
232 : std::vector<Tensor3d> drtilde_dx;
233 53822 : drtilde_dx.resize(6);
234 53822 : unsigned pos_idx = 3*i;
235 53822 : unsigned deri_idx = 9*i;
236 376754 : for (unsigned at=0; at<3; at++) {
237 1130262 : for (unsigned l=0; l<3; l++) {
238 968796 : Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.);
239 968796 : Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff));
240 968796 : drtilde_dx[at].setRow(l,vvec-rvec);
241 968796 : drtilde_dx[at+3].setRow(l,rvec);
242 : }
243 : }
244 :
245 : //std::vector<TensorGeneric<4,3> > dG_dx;
246 : //dG_dx.resize(6);
247 :
248 53822 : double dummy1 = (cos(gamma*rtilde_norm) - dummy);
249 :
250 53822 : idx1 = i*nresidues*6 + j*6;
251 :
252 699686 : for (unsigned l=0; l<6; l++) {
253 : //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n";
254 :
255 : // components 1,2,3
256 : // sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde +
257 : // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)*
258 : // (cos(gamma*|rtilde| - sin(gamma*|rtilde|)/gamma*|rtilde|))
259 645864 : Vector3d rdr = matmul(rtilde,drtilde_dx[l]);
260 645864 : Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr);
261 2260524 : for (unsigned m=0; m<3; m++) {
262 : // Transpose here
263 : //dG_dx[l].setRow(m,tt.getRow(m));
264 1937592 : Gderi[idx1+l].setRow(m,tt.getRow(m));
265 : }
266 : // component 4
267 : // - sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde)
268 : //dG_dx[l].setRow(3,-dummy*gamma*rdr);
269 645864 : Gderi[idx1+l].setRow(3,-dummy*gamma*rdr);
270 : }
271 :
272 :
273 :
274 :
275 : }
276 : }
277 : }
278 :
279 : }
280 : }
281 :
282 226 : }
283 :
284 :
285 222 : double ERMSD::calculate(const std::vector<Vector> & positions,const Pbc& pbc,\
286 : std::vector<Vector> &derivatives, Tensor& virial) {
287 :
288 :
289 : double ermsd=0.;
290 : std::vector<Vector4d> mat;
291 222 : mat.resize(nresidues*nresidues);
292 :
293 : std::vector<TensorGeneric<4,3> > Gderi;
294 222 : Gderi.resize(natoms*natoms);
295 :
296 222 : calcMat(positions,pbc,mat,Gderi);
297 :
298 : unsigned idx1 = 0;
299 31746 : for(unsigned i=0; i<nresidues; i++) {
300 2253966 : for(unsigned j=0; j<nresidues; j++) {
301 1119102 : unsigned ii = i*nresidues + j;
302 :
303 2238204 : Vector4d dd = delta(reference_mat[ii],mat[ii]);
304 1119102 : double val = dd.modulo2();
305 : //std::cout << "AAA " << i << " " << j << " " << ii << " "<< val << "\n";
306 :
307 1119102 : if(val>0.0 && i!=j) {
308 :
309 449043 : for(unsigned k=0; k<3; k++) {
310 192447 : idx1 = i*nresidues*6 + j*6 + k;
311 :
312 577341 : derivatives[3*i+k] += matmul(dd,Gderi[idx1]);
313 577341 : derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]);
314 : }
315 64149 : ermsd += val;
316 : }
317 : }
318 : }
319 :
320 : //std::cout << ermsd << " ";
321 : //if(pairs.size()!=0) nresidues=pairs.size();
322 : //std::cout << ermsd << " " << nresidues;
323 222 : ermsd = sqrt(ermsd/nresidues);
324 222 : double iermsd = 1.0/(ermsd*nresidues);
325 94794 : for(unsigned i=0; i<natoms; ++i) {derivatives[i] *= iermsd;}
326 :
327 222 : return ermsd;
328 : }
329 :
330 :
331 4839 : }
|