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: 2024-10-18 14:00:25 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2016-2023 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             : namespace PLMD {
      39             : 
      40           0 : void ERMSD::clear() {
      41             :   reference_mat.clear();
      42           0 : }
      43             : 
      44             : //void ERMSD::calcLcs(const vector<Vector> & positions, vector<Vector> &)
      45             : 
      46           4 : void ERMSD::setReference(const std::vector<Vector> & reference, const std::vector<unsigned> & pairs_vec, double mycutoff) {
      47             : 
      48           4 :   natoms = reference.size();
      49           4 :   nresidues = natoms/3;
      50           4 :   unsigned npairs = pairs_vec.size()/2;
      51           4 :   pairs.resize(npairs);
      52          16 :   for(unsigned i=0; i<npairs; ++i) {
      53             : 
      54          12 :     pairs[i].first = pairs_vec[2*i];
      55          12 :     pairs[i].second = pairs_vec[2*i+1];
      56             :   }
      57             : 
      58           4 :   cutoff = mycutoff;
      59             :   std::vector<TensorGeneric<4,3> > deri;
      60           4 :   deri.resize(natoms*natoms);
      61           4 :   reference_mat.resize(nresidues*nresidues);
      62           4 :   Pbc fake_pbc;
      63             : 
      64           4 :   calcMat(reference,fake_pbc,reference_mat,deri);
      65             : 
      66           4 : }
      67             : 
      68     1139266 : bool ERMSD::inPair(unsigned i, unsigned j) {
      69             : 
      70     1139266 :   if(pairs.size()==0) return true;
      71     3982685 :   for(unsigned idx=0; idx<pairs.size(); idx++) {
      72     3414408 :     if(pairs[idx].first == i && pairs[idx].second == j) return true;
      73     3413730 :     if(pairs[idx].second == i && pairs[idx].first == j) return true;
      74             :   }
      75             :   return false;
      76             : }
      77             : 
      78         226 : void ERMSD::calcMat(const std::vector<Vector> & positions,const Pbc& pbc, std::vector<Vector4d> &mat, std::vector<TensorGeneric<4,3> > &Gderi) {
      79             : 
      80             :   std::vector<Vector3d> pos;
      81         226 :   pos.resize(3*nresidues);
      82             : 
      83             :   std::vector<Tensor3d> deri;
      84         226 :   deri.resize(nresidues*9);
      85             : 
      86             :   std::vector<Vector> centers;
      87         226 :   centers.resize(nresidues);
      88             : 
      89             :   unsigned idx_deri = 0;
      90             : 
      91         226 :   Tensor da_dxa = (2./3.)*Tensor::identity();
      92         226 :   Tensor da_dxb = -(1./3.)*Tensor::identity();
      93         226 :   Tensor da_dxc = -(1./3.)*Tensor::identity();
      94             : 
      95         226 :   Tensor db_dxa = -(1./3.)*Tensor::identity();
      96         226 :   Tensor db_dxb = (2./3.)*Tensor::identity();
      97         226 :   Tensor db_dxc = -(1./3.)*Tensor::identity();
      98             : 
      99             :   // Form factors - should this be somewhere else?
     100             : 
     101             :   double w = 1./3.;
     102         226 :   Vector form_factor = Vector(2.0,2.0,1.0/0.3);
     103             : 
     104       16272 :   for(unsigned res_idx=0; res_idx<natoms/3; res_idx++) {
     105             : 
     106             : 
     107       16046 :     const unsigned at_idx = 3*res_idx;
     108             :     //center
     109       64184 :     for (unsigned j=0; j<3; j++) {
     110       48138 :       centers[res_idx] += w*positions[at_idx+j];
     111             :     }
     112             : 
     113       16046 :     Vector3d a = delta(centers[res_idx],positions[at_idx]);
     114       16046 :     Vector3d b = delta(centers[res_idx],positions[at_idx+1]);
     115       16046 :     Vector3d d = crossProduct(a,b);
     116       16046 :     double ianorm = 1./a.modulo();
     117       16046 :     double idnorm = 1./d.modulo();
     118             : 
     119             :     // X vector: COM-C2
     120       16046 :     pos[at_idx] = a*ianorm;
     121             :     // Z versor: C2 x (COM-C4/C6)
     122       16046 :     pos[at_idx+2] = d*idnorm;
     123             :     // Y versor: Z x Y
     124       16046 :     pos[at_idx+1] = crossProduct(pos[at_idx+2],pos[at_idx]);
     125             : 
     126             :     // Derivatives ////////
     127       16046 :     Tensor3d t1 = ianorm*(Tensor::identity()-extProduct(pos[at_idx],pos[at_idx]));
     128             :     // dv1/dxa
     129       16046 :     deri[idx_deri] = (2./3. )*t1;
     130             :     // dv1/dxb
     131       16046 :     deri[idx_deri+3] = -(1./3.)*t1;
     132             :     // dv1/dxc
     133       16046 :     deri[idx_deri+6] = -(1./3.)*t1;
     134             : 
     135       16046 :     Tensor dd_dxa =  VcrossTensor(a,db_dxa) -VcrossTensor(b,da_dxa);
     136       16046 :     Tensor dd_dxb =  VcrossTensor(a,db_dxb)-VcrossTensor(b,da_dxb);
     137       16046 :     Tensor dd_dxc =  VcrossTensor(a,db_dxc)-VcrossTensor(b,da_dxc);
     138             : 
     139             :     // dv3/dxa
     140       16046 :     deri[idx_deri+2] = deriNorm(d,dd_dxa);
     141             :     // dv3/dxb
     142       16046 :     deri[idx_deri+5] = deriNorm(d,dd_dxb);
     143             :     // dv3/dxc
     144       16046 :     deri[idx_deri+8] = deriNorm(d,dd_dxc);
     145             : 
     146             :     // dv2/dxa = dv3/dxa cross v1 + v3 cross dv1/dxa
     147       32092 :     deri[idx_deri+1] =  (VcrossTensor(deri[idx_deri+2],pos[at_idx]) + \
     148       32092 :                          VcrossTensor(pos[at_idx+2],deri[idx_deri]));
     149             :     // dv2/dxb
     150       32092 :     deri[idx_deri+4] =  (VcrossTensor(deri[idx_deri+5],pos[at_idx]) + \
     151       32092 :                          VcrossTensor(pos[at_idx+2],deri[idx_deri+3]));
     152             :     // dv2/dxc
     153       32092 :     deri[idx_deri+7] =  (VcrossTensor(deri[idx_deri+8],pos[at_idx]) + \
     154       32092 :                          VcrossTensor(pos[at_idx+2],deri[idx_deri+6]));
     155             : 
     156       16046 :     idx_deri += 9;
     157             :     // End derivatives ///////
     158             : 
     159             :   }
     160             : 
     161             : 
     162             :   // Initialization (unnecessary?)
     163     1139492 :   for (unsigned i1=0; i1<nresidues*nresidues; i1++) {
     164     5696330 :     for (unsigned i2=0; i2<4; i2++) {
     165     4557064 :       mat[i1][i2] = 0.0;
     166             :     }
     167             :   }
     168             : 
     169         226 :   double maxdist = cutoff/form_factor[0];
     170         226 :   double gamma = pi/cutoff;
     171             :   unsigned idx;
     172             :   unsigned idx1 = 0;
     173             :   // Calculate mat
     174       16272 :   for (unsigned i=0; i<nresidues; i++) {
     175     1155312 :     for (unsigned j=0; j<nresidues; j++) {
     176             : 
     177             :       // skip i==j
     178     1139266 :       if(inPair(i,j) and i != j) {
     179             :         //if(i!=j){
     180             : 
     181             : 
     182             :         // Calculate normal distance first
     183      562966 :         Vector diff = delta(centers[i],centers[j]);
     184      562966 :         double d1 = diff.modulo();
     185      562966 :         if(d1<maxdist) {
     186             : 
     187             :           // calculate r_tilde_ij
     188       85382 :           Vector3d rtilde;
     189      341528 :           for (unsigned k=0; k<3; k++) {
     190     1024584 :             for (unsigned l=0; l<3; l++) {
     191      768438 :               rtilde[l] += pos[3*i+l][k]*diff[k]*form_factor[l];
     192             :             }
     193             :           }
     194       85382 :           double rtilde_norm = rtilde.modulo();
     195             : 
     196       85382 :           double irnorm = 1./rtilde_norm;
     197             : 
     198             :           // ellipsoidal cutoff
     199       85382 :           if(rtilde_norm < cutoff) {
     200       53822 :             idx = i*nresidues + j;
     201             : 
     202             : 
     203             :             // fill 4d matrix
     204       53822 :             double dummy = std::sin(gamma*rtilde_norm)/(rtilde_norm*gamma);
     205       53822 :             mat[idx][0] = dummy*rtilde[0];
     206       53822 :             mat[idx][1] = dummy*rtilde[1];
     207       53822 :             mat[idx][2] = dummy*rtilde[2];
     208       53822 :             mat[idx][3] = (1.+ std::cos(gamma*rtilde_norm))/gamma;
     209             : 
     210             :             // Derivative (drtilde_dx)
     211             :             std::vector<Tensor3d> drtilde_dx;
     212       53822 :             drtilde_dx.resize(6);
     213       53822 :             unsigned pos_idx = 3*i;
     214       53822 :             unsigned deri_idx = 9*i;
     215      215288 :             for (unsigned at=0; at<3; at++) {
     216      645864 :               for (unsigned l=0; l<3; l++) {
     217      484398 :                 Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.);
     218      484398 :                 Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff));
     219      484398 :                 drtilde_dx[at].setRow(l,vvec-rvec);
     220      484398 :                 drtilde_dx[at+3].setRow(l,rvec);
     221             :               }
     222             :             }
     223             : 
     224       53822 :             double dummy1 = (std::cos(gamma*rtilde_norm) - dummy);
     225             : 
     226       53822 :             idx1 = i*nresidues*6 + j*6;
     227             : 
     228      376754 :             for (unsigned l=0; l<6; l++) {
     229             :               //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n";
     230             : 
     231             :               // components 1,2,3
     232             :               // std::sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde +
     233             :               // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)*
     234             :               // (std::cos(gamma*|rtilde| - std::sin(gamma*|rtilde|)/gamma*|rtilde|))
     235      322932 :               Vector3d rdr = matmul(rtilde,drtilde_dx[l]);
     236      322932 :               Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr);
     237     1291728 :               for (unsigned m=0; m<3; m++) {
     238             :                 // Transpose here
     239             :                 //dG_dx[l].setRow(m,tt.getRow(m));
     240      968796 :                 Gderi[idx1+l].setRow(m,tt.getRow(m));
     241             :               }
     242             :               // component 4
     243             :               // - std::sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde)
     244             :               //dG_dx[l].setRow(3,-dummy*gamma*rdr);
     245      322932 :               Gderi[idx1+l].setRow(3,-dummy*gamma*rdr);
     246             :             }
     247             : 
     248             : 
     249             : 
     250             : 
     251             :           }
     252             :         }
     253             :       }
     254             : 
     255             :     }
     256             :   }
     257             : 
     258         226 : }
     259             : 
     260             : 
     261         222 : double ERMSD::calculate(const std::vector<Vector> & positions,const Pbc& pbc,\
     262             :                         std::vector<Vector> &derivatives, Tensor& virial) {
     263             : 
     264             : 
     265             :   double ermsd=0.;
     266             :   std::vector<Vector4d> mat;
     267         222 :   mat.resize(nresidues*nresidues);
     268             : 
     269             :   std::vector<TensorGeneric<4,3> > Gderi;
     270         222 :   Gderi.resize(natoms*natoms);
     271             : 
     272         222 :   calcMat(positions,pbc,mat,Gderi);
     273             : 
     274             :   unsigned idx1 = 0;
     275       15984 :   for(unsigned i=0; i<nresidues; i++) {
     276     1134864 :     for(unsigned j=0; j<nresidues; j++) {
     277     1119102 :       unsigned ii = i*nresidues + j;
     278             : 
     279     1119102 :       Vector4d dd = delta(reference_mat[ii],mat[ii]);
     280     1119102 :       double val = dd.modulo2();
     281             : 
     282     1119102 :       if(val>0.0 && i!=j) {
     283             : 
     284      256596 :         for(unsigned k=0; k<3; k++) {
     285      192447 :           idx1 = i*nresidues*6 + j*6 + k;
     286             : 
     287      192447 :           derivatives[3*i+k] += matmul(dd,Gderi[idx1]);
     288      192447 :           derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]);
     289             :         }
     290       64149 :         ermsd += val;
     291             :       }
     292             :     }
     293             :   }
     294             : 
     295         222 :   ermsd = std::sqrt(ermsd/nresidues);
     296         222 :   double iermsd = 1.0/(ermsd*nresidues);
     297       47508 :   for(unsigned i=0; i<natoms; ++i) {derivatives[i] *= iermsd;}
     298             : 
     299         222 :   return ermsd;
     300             : }
     301             : 
     302             : 
     303             : }

Generated by: LCOV version 1.16