LCOV - code coverage report
Current view: top level - reference - MultiDomainRMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 99 106 93.4 %
Date: 2018-12-19 07:49:13 Functions: 14 17 82.4 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2013-2018 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             : #include "MultiDomainRMSD.h"
      23             : #include "SingleDomainRMSD.h"
      24             : #include "MetricRegister.h"
      25             : #include "tools/PDB.h"
      26             : 
      27             : namespace PLMD {
      28             : 
      29        2530 : PLUMED_REGISTER_METRIC(MultiDomainRMSD,"MULTI")
      30             : 
      31           7 : MultiDomainRMSD::MultiDomainRMSD( const ReferenceConfigurationOptions& ro ):
      32             :   ReferenceConfiguration(ro),
      33             :   ReferenceAtoms(ro),
      34           7 :   ftype(ro.getMultiRMSDType())
      35             : {
      36           7 : }
      37             : 
      38          28 : MultiDomainRMSD::~MultiDomainRMSD() {
      39           7 :   for(unsigned i=0; i<domains.size(); ++i) delete domains[i];
      40          21 : }
      41             : 
      42           7 : void MultiDomainRMSD::read( const PDB& pdb ) {
      43           7 :   unsigned nblocks =  pdb.getNumberOfAtomBlocks();
      44           7 :   if( nblocks<2 ) error("multidomain RMSD only has one block of atoms");
      45             : 
      46          14 :   std::vector<Vector> positions; std::vector<double> align, displace;
      47          14 :   std::string num; blocks.resize( nblocks+1 ); blocks[0]=0;
      48           7 :   for(unsigned i=0; i<nblocks; ++i) blocks[i+1]=pdb.getAtomBlockEnds()[i];
      49             : 
      50           7 :   double lower=0.0, upper=std::numeric_limits<double>::max( );
      51           7 :   parse("LOWER_CUTOFF",lower,true);
      52           7 :   parse("UPPER_CUTOFF",upper,true);
      53           7 :   bool nopbc=false; parseFlag("NOPBC",nopbc);
      54             : 
      55          21 :   for(unsigned i=1; i<=nblocks; ++i) {
      56          14 :     Tools::convert(i,num);
      57          14 :     if( ftype=="RMSD" ) {
      58           0 :       parse("TYPE"+num, ftype );
      59           0 :       parse("LOWER_CUTOFF"+num,lower,true);
      60           0 :       parse("UPPER_CUTOFF"+num,upper,true);
      61           0 :       nopbc=false; parseFlag("NOPBC"+num,nopbc);
      62             :     }
      63          14 :     domains.push_back( metricRegister().create<SingleDomainRMSD>( ftype ) );
      64          14 :     positions.resize( blocks[i] - blocks[i-1] );
      65          14 :     align.resize( blocks[i] - blocks[i-1] );
      66          14 :     displace.resize( blocks[i] - blocks[i-1] );
      67          14 :     unsigned n=0;
      68          87 :     for(unsigned j=blocks[i-1]; j<blocks[i]; ++j) {
      69          73 :       positions[n]=pdb.getPositions()[j];
      70          73 :       align[n]=pdb.getOccupancy()[j];
      71          73 :       displace[n]=pdb.getBeta()[j];
      72          73 :       n++;
      73             :     }
      74          14 :     domains[i-1]->setBoundsOnDistances( !nopbc, lower, upper );
      75          14 :     domains[i-1]->setReferenceAtoms( positions, align, displace );
      76          14 :     domains[i-1]->setupRMSDObject();
      77             : 
      78          14 :     double ww=0; parse("WEIGHT"+num, ww, true );
      79          14 :     if( ww==0 ) weights.push_back( 1.0 );
      80           0 :     else weights.push_back( ww );
      81             :   }
      82             :   // And set the atom numbers for this object
      83          14 :   setAtomNumbers( pdb.getAtomNumbers() );
      84           7 : }
      85             : 
      86           0 : void MultiDomainRMSD::setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in ) {
      87           0 :   plumed_error();
      88             : }
      89             : 
      90          37 : double MultiDomainRMSD::calculate( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
      91          74 :   double totd=0.; Tensor tvirial; std::vector<Vector> mypos; MultiValue tvals( 1, 3*pos.size()+9 );
      92          74 :   ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); myder.clear();
      93             : 
      94         111 :   for(unsigned i=0; i<domains.size(); ++i) {
      95             :     // Must extract appropriate positions here
      96          74 :     mypos.resize( blocks[i+1] - blocks[i] );
      97          74 :     if( myder.calcUsingPCAOption() ) domains[i]->setupPCAStorage( tder );
      98          74 :     unsigned n=0; for(unsigned j=blocks[i]; j<blocks[i+1]; ++j) { tder.setAtomIndex(n,j); mypos[n]=pos[j]; n++; }
      99          74 :     for(unsigned k=n; k<getNumberOfAtoms(); ++k) tder.setAtomIndex(k,3*pos.size()+10);
     100             :     // This actually does the calculation
     101          74 :     totd += weights[i]*domains[i]->calculate( mypos, pbc, tder, true );
     102             :     // Now merge the derivative
     103          74 :     myder.copyScaledDerivatives( 0, weights[i], tvals );
     104             :     // If PCA copy PCA stuff
     105          74 :     if( myder.calcUsingPCAOption() ) {
     106          44 :       unsigned n=0;
     107          44 :       if( tder.centeredpos.size()>0 ) myder.rot[i]=tder.rot[0];
     108         198 :       for(unsigned j=blocks[i]; j<blocks[i+1]; ++j) {
     109         154 :         myder.displacement[j]=weights[i]*tder.displacement[n];  // Multiplication by weights here ensures that normalisation is done correctly
     110         154 :         if( tder.centeredpos.size()>0 ) {
     111          77 :           myder.centeredpos[j]=tder.centeredpos[n];
     112          77 :           for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) myder.DRotDPos(p,q)[j]=tder.DRotDPos(p,q)[n];
     113             :         }
     114         154 :         n++;
     115             :       }
     116             :     }
     117             :     // Make sure virial status is set correctly in output derivative pack
     118             :     // This is only done here so I do this by using class friendship
     119          74 :     if( tder.virialWasSet() ) myder.boxWasSet=true;
     120             :   }
     121          37 :   if( !myder.updateComplete() ) myder.updateDynamicLists();
     122             : 
     123          37 :   if( !squared ) {
     124          15 :     totd=sqrt(totd); double xx=0.5/totd;
     125          15 :     myder.scaleAllDerivatives( xx );
     126             :   }
     127          74 :   return totd;
     128             : }
     129             : 
     130          22 : double MultiDomainRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, const std::vector<Value*>& vals, const std::vector<double>& arg,
     131             :                               ReferenceValuePack& myder, const bool& squared ) const {
     132             :   plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 );
     133          22 :   return calculate( pos, pbc, myder, squared );
     134             : }
     135             : 
     136           2 : bool MultiDomainRMSD::pcaIsEnabledForThisReference() {
     137           2 :   bool enabled=true;
     138           6 :   for(unsigned i=0; i<domains.size(); ++i) {
     139           4 :     if( !domains[i]->pcaIsEnabledForThisReference() ) enabled=false;
     140             :   }
     141           2 :   return enabled;
     142             : }
     143             : 
     144           2 : void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ) {
     145             :   plumed_dbg_assert( pcaIsEnabledForThisReference() );
     146           2 :   mypack.switchOnPCAOption();
     147           2 :   mypack.displacement.resize( getNumberOfAtoms() );
     148           2 :   mypack.centeredpos.resize( getNumberOfAtoms() );
     149           2 :   mypack.DRotDPos.resize(3,3); mypack.rot.resize( domains.size() );
     150           2 :   for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) mypack.DRotDPos(i,j).resize( getNumberOfAtoms() );
     151           2 : }
     152             : 
     153             : // Vector MultiDomainRMSD::getAtomicDisplacement( const unsigned& iatom ){
     154             : //   for(unsigned i=0;i<domains.size();++i){
     155             : //       unsigned n=0;
     156             : //       for(unsigned j=blocks[i];j<blocks[i+1];++j){
     157             : //           if( j==iatom ) return weights[i]*domains[i]->getAtomicDisplacement(n);
     158             : //           n++;
     159             : //       }
     160             : //   }
     161             : // }
     162             : 
     163          44 : double MultiDomainRMSD::projectAtomicDisplacementOnVector( const unsigned& iv, const Matrix<Vector>& vecs, const std::vector<Vector>& pos, ReferenceValuePack& mypack ) const {
     164          88 :   double totd=0.; Matrix<Vector> tvecs; std::vector<Vector> mypos; mypack.clear();
     165          88 :   MultiValue tvals( 1, mypack.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals );
     166         132 :   for(unsigned i=0; i<domains.size(); ++i) {
     167             :     // Must extract appropriate positions here
     168          88 :     mypos.resize( blocks[i+1] - blocks[i] ); tvecs.resize( 1, blocks[i+1] - blocks[i] );
     169          88 :     domains[i]->setupPCAStorage( tder );
     170          88 :     if( tder.centeredpos.size()>0 ) {
     171          44 :       for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q).resize( mypos.size() );
     172             :     }
     173             :     // Extract information from storage pack and put in local pack
     174          88 :     if( tder.centeredpos.size()>0 ) tder.rot[0]=mypack.rot[i];
     175          88 :     unsigned n=0;
     176         396 :     for(unsigned j=blocks[i]; j<blocks[i+1]; ++j) {
     177         308 :       mypos[n]=pos[j]; tder.setAtomIndex(n,j); tvecs( 0, n ) = vecs( iv, j );
     178         308 :       tder.displacement[n]=mypack.displacement[j] / weights[i];
     179         308 :       if( tder.centeredpos.size()>0 ) {
     180         154 :         tder.centeredpos[n]=mypack.centeredpos[j];
     181         154 :         for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q)[n]=mypack.DRotDPos(p,q)[j];
     182             :       }
     183         308 :       n++;
     184             :     }
     185          88 :     for(unsigned k=n; k<getNumberOfAtoms(); ++k) tder.setAtomIndex(k,3*pos.size()+10);
     186             : 
     187             :     // Do the calculations
     188          88 :     totd += weights[i]*domains[i]->projectAtomicDisplacementOnVector( 0, tvecs, mypos, tder );
     189             : 
     190             :     // And derivatives
     191          88 :     mypack.copyScaledDerivatives( 0, weights[i], tvals );
     192             :   }
     193          44 :   if( !mypack.updateComplete() ) mypack.updateDynamicLists();
     194             : 
     195          88 :   return totd;
     196             : }
     197             : 
     198        2523 : }

Generated by: LCOV version 1.13