LCOV - code coverage report
Current view: top level - tools - ERMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 120 122 98.4 %
Date: 2020-11-18 11:20:57 Functions: 6 7 85.7 %

          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 : }

Generated by: LCOV version 1.13