LCOV - code coverage report
Current view: top level - reference - DRMSD.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 59 66 89.4 %
Date: 2026-03-30 13:16:06 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2013-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             : #include "DRMSD.h"
      23             : #include "MetricRegister.h"
      24             : #include "tools/Pbc.h"
      25             : 
      26             : namespace PLMD {
      27             : 
      28       13855 : PLUMED_REGISTER_METRIC(DRMSD,"DRMSD")
      29             : 
      30          37 : DRMSD::DRMSD( const ReferenceConfigurationOptions& ro ):
      31             :   ReferenceConfiguration( ro ),
      32             :   SingleDomainRMSD( ro ),
      33          37 :   nopbc(true),
      34          37 :   bounds_were_set(false),
      35          37 :   lower(0),
      36          37 :   upper(std::numeric_limits<double>::max( )) {
      37          37 : }
      38             : 
      39          37 : void DRMSD::setBoundsOnDistances( bool dopbc, double lbound, double ubound ) {
      40          37 :   bounds_were_set=true;
      41          37 :   nopbc=!dopbc;
      42          37 :   lower=lbound;
      43          37 :   upper=ubound;
      44          37 : }
      45             : 
      46          11 : void DRMSD::readBounds( const PDB& pdb ) {
      47          11 :   if( bounds_were_set ) {
      48          11 :     return;
      49             :   }
      50             :   double tmp;
      51           0 :   nopbc=pdb.hasFlag("NOPBC");
      52           0 :   if( pdb.getArgumentValue("LOWER_CUTOFF",tmp) ) {
      53           0 :     lower=tmp;
      54             :   }
      55           0 :   if( pdb.getArgumentValue("UPPER_CUTOFF",tmp) ) {
      56           0 :     upper=tmp;
      57             :   }
      58           0 :   bounds_were_set=true;
      59             : }
      60             : 
      61           9 : void DRMSD::read( const PDB& pdb ) {
      62           9 :   readAtomsFromPDB( pdb );
      63           9 :   readBounds( pdb );
      64           9 :   setup_targets();
      65           9 : }
      66             : 
      67          26 : void DRMSD::setReferenceAtoms( const std::vector<Vector>& conf, const std::vector<double>& align_in, const std::vector<double>& displace_in ) {
      68          26 :   SingleDomainRMSD::setReferenceAtoms( conf, align_in, displace_in );
      69          26 :   setup_targets();
      70          26 : }
      71             : 
      72          35 : void DRMSD::setup_targets() {
      73          35 :   plumed_massert( bounds_were_set, "I am missing a call to DRMSD::setBoundsOnDistances");
      74             : 
      75          35 :   unsigned natoms = getNumberOfReferencePositions();
      76         839 :   for(unsigned i=0; i<natoms-1; ++i) {
      77       11955 :     for(unsigned j=i+1; j<natoms; ++j) {
      78       11151 :       double distance = delta( getReferencePosition(i), getReferencePosition(j) ).modulo();
      79       11151 :       if(distance < upper && distance > lower ) {
      80       10283 :         targets[std::make_pair(i,j)] = distance;
      81             :       }
      82             :     }
      83             :   }
      84          35 :   if( targets.empty() ) {
      85           0 :     error("drmsd will compare no distances - check upper and lower bounds are sensible");
      86             :   }
      87          35 : }
      88             : 
      89       38582 : double DRMSD::calc( const std::vector<Vector>& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const {
      90             :   plumed_dbg_assert(!targets.empty());
      91             : 
      92       38582 :   Vector distance;
      93       38582 :   myder.clear();
      94             :   double drmsd=0.;
      95    15553320 :   for(const auto & it : targets) {
      96             : 
      97    15514738 :     const unsigned i=getAtomIndex( it.first.first );
      98    15514738 :     const unsigned j=getAtomIndex( it.first.second );
      99             : 
     100    15514738 :     if(nopbc) {
     101       29400 :       distance=delta( pos[i], pos[j] );
     102             :     } else {
     103    15485338 :       distance=pbc.distance( pos[i], pos[j] );
     104             :     }
     105             : 
     106    15514738 :     const double len = distance.modulo();
     107    15514738 :     const double diff = len - it.second;
     108    15514738 :     const double der = diff / len;
     109             : 
     110    15514738 :     drmsd += diff * diff;
     111    15514738 :     myder.addAtomDerivatives( i, -der * distance );
     112    15514738 :     myder.addAtomDerivatives( j,  der * distance );
     113    15514738 :     myder.addBoxDerivatives( - der * Tensor(distance,distance) );
     114             :   }
     115             : 
     116       38582 :   const double inpairs = 1./static_cast<double>(targets.size());
     117             :   double idrmsd;
     118             : 
     119       38582 :   if(squared) {
     120          10 :     drmsd = drmsd * inpairs;
     121          10 :     idrmsd = 2.0 * inpairs;
     122             :   } else {
     123       38572 :     drmsd = std::sqrt( drmsd * inpairs );
     124       38572 :     idrmsd = inpairs / drmsd ;
     125             :   }
     126             : 
     127       38582 :   myder.scaleAllDerivatives( idrmsd );
     128             : 
     129       38582 :   return drmsd;
     130             : }
     131             : 
     132             : }

Generated by: LCOV version 1.16