LCOV - code coverage report
Current view: top level - colvar - DihedralCorrelation.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 35 61 57.4 %
Date: 2025-12-04 11:19:34 Functions: 4 7 57.1 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2013-2020 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             : #ifdef __PLUMED_HAS_OPENACC
      23             : #define __PLUMED_USE_OPENACC 1
      24             : #endif //__PLUMED_HAS_OPENACC
      25             : #include "Colvar.h"
      26             : #include "ColvarShortcut.h"
      27             : #include "MultiColvarTemplate.h"
      28             : #include "tools/Torsion.h"
      29             : #include "core/ActionRegister.h"
      30             : 
      31             : #include <string>
      32             : #include <cmath>
      33             : 
      34             : namespace PLMD {
      35             : namespace colvar {
      36             : 
      37             : //+PLUMEDOC COLVAR DIHEDRAL_CORRELATION
      38             : /*
      39             : Measure the correlation between a pair of dihedral angles
      40             : 
      41             : This CV measures the correlation between two dihedral angles, $\phi$ and $\psi$, as follows:
      42             : 
      43             : $$
      44             : s = \frac{1}{2} \left[ 1 + \cos( \phi - \psi ) \right]
      45             : $$
      46             : 
      47             : An example input that computes and calculates this quantity with $\phi$ being the dihedral
      48             : angle involving atoms 1, 2, 3 and 4 and $\psi$ being the angle involving atoms 7, 8, 9 and 10
      49             : is shown below:
      50             : 
      51             : ```plumed
      52             : d: DIHEDRAL_CORRELATION ATOMS=1,2,3,4,5,6,7,8
      53             : PRINT ARG=d FILE=colvar
      54             : ```
      55             : 
      56             : If you want to calculate the dihedral correlations between multiple pairs of dihedral angles using
      57             : this action you would use an input like this one shown below:
      58             : 
      59             : ```plumed
      60             : d: DIHEDRAL_CORRELATION ...
      61             :   ATOMS1=1,2,3,4,5,6,7,8
      62             :   ATOMS2=9,10,11,12,13,14,15,16
      63             : ...
      64             : PRINT ARG=d FILE=colvar
      65             : ```
      66             : 
      67             : This input calculates and outputs a two dimensional vector that contains two of these dihedral correlation
      68             : values. Commands similar to these are used within the [DIHCOR](DIHCOR.md) shortcut.
      69             : 
      70             : The last thing to note is that by default a procedure akin to that used in [WHOLEMOLECULES](WHOLEMOLECULES.md)
      71             : is used to ensure that the sets of atoms that are specified to each ATOMS keyword are not broken by the periodic
      72             : boundary conditions.  If you would like to turn this off for any reason you add the NOPBC in your input file as shown
      73             : below:
      74             : 
      75             : ```plumed
      76             : d: DIHEDRAL_CORRELATION ATOMS=1,2,3,4,5,6,7,8 NOPBC
      77             : PRINT ARG=d FILE=colvar
      78             : ```
      79             : 
      80             : */
      81             : //+ENDPLUMEDOC
      82             : 
      83             : class DihedralCorrelation : public Colvar {
      84             : private:
      85             :   bool pbc;
      86             :   std::vector<double> value;
      87             :   std::vector<double> derivs;
      88             : public:
      89             :   static void registerKeywords( Keywords& keys );
      90             :   explicit DihedralCorrelation(const ActionOptions&);
      91             :   static void parseAtomList( const int& num, std::vector<AtomNumber>& t, ActionAtomistic* aa );
      92             :   static unsigned getModeAndSetupValues( ActionWithValue* av );
      93             :   void calculate() override;
      94             :   static void calculateCV( const ColvarInput& cvin, ColvarOutput& cvout );
      95             : };
      96             : 
      97             : typedef ColvarShortcut<DihedralCorrelation> DihedralCorrelationShortcut;
      98             : PLUMED_REGISTER_ACTION(DihedralCorrelationShortcut,"DIHEDRAL_CORRELATION")
      99             : PLUMED_REGISTER_ACTION(DihedralCorrelation,"DIHEDRAL_CORRELATION_SCALAR")
     100             : typedef MultiColvarTemplate<DihedralCorrelation> DihedralCorrelationMulti;
     101             : PLUMED_REGISTER_ACTION(DihedralCorrelationMulti,"DIHEDRAL_CORRELATION_VECTOR")
     102             : 
     103          10 : void DihedralCorrelation::registerKeywords( Keywords& keys ) {
     104          10 :   Colvar::registerKeywords( keys );
     105          20 :   keys.setDisplayName("DIHEDRAL_CORRELATION");
     106          10 :   keys.add("atoms","ATOMS","the set of 8 atoms that are being used to calculate this quantity");
     107          10 :   keys.add("hidden","NO_ACTION_LOG","suppresses printing from action on the log");
     108          20 :   keys.setValueDescription("scalar/vector","the DIHEDRAL_CORRELATION for these atoms");
     109          20 :   keys.reset_style("NUMERICAL_DERIVATIVES","hidden");
     110          10 : }
     111             : 
     112           0 : DihedralCorrelation::DihedralCorrelation(const ActionOptions&ao):
     113             :   PLUMED_COLVAR_INIT(ao),
     114           0 :   pbc(true),
     115           0 :   value(1) {
     116             :   std::vector<AtomNumber> atoms;
     117           0 :   parseAtomList(-1,atoms,this);
     118           0 :   if( atoms.size()!=8 ) {
     119           0 :     error("Number of specified atoms should be 8");
     120             :   }
     121             : 
     122           0 :   bool nopbc=!pbc;
     123           0 :   parseFlag("NOPBC",nopbc);
     124           0 :   pbc=!nopbc;
     125             : 
     126           0 :   if(pbc) {
     127           0 :     log.printf("  using periodic boundary conditions\n");
     128             :   } else {
     129           0 :     log.printf("  without periodic boundary conditions\n");
     130             :   }
     131           0 :   addValueWithDerivatives();
     132           0 :   setNotPeriodic();
     133           0 : }
     134             : 
     135           3 : void DihedralCorrelation::parseAtomList( const int& num, std::vector<AtomNumber>& t, ActionAtomistic* aa ) {
     136           3 :   aa->parseAtomList("ATOMS",num,t);
     137           3 :   if( num<0 && t.size()!=8 ) {
     138           0 :     aa->error("Number of specified atoms should be 8");
     139             :   }
     140           3 :   if( t.size()==8 ) {
     141           2 :     aa->log.printf("  correlation between dihedral angle for atoms %d %d %d %d and atoms %d %d %d %d\n",
     142             :                    t[0].serial(),t[1].serial(),t[2].serial(),t[3].serial(),t[4].serial(),t[5].serial(),t[6].serial(),t[7].serial());
     143             :   }
     144           3 : }
     145             : 
     146           1 : unsigned DihedralCorrelation::getModeAndSetupValues( ActionWithValue* av ) {
     147           1 :   av->addValueWithDerivatives();
     148           1 :   av->setNotPeriodic();
     149           1 :   return 0;
     150             : }
     151             : 
     152           0 : void DihedralCorrelation::calculate() {
     153             : 
     154           0 :   if(pbc) {
     155           0 :     makeWhole();
     156             :   }
     157           0 :   ColvarOutput cvout = ColvarOutput::createColvarOutput(value,derivs,this);
     158           0 :   calculateCV( ColvarInput::createColvarInput( 0, getPositions(), this ), cvout );
     159           0 :   setValue( value[0] );
     160           0 :   for(unsigned i=0; i<getPositions().size(); ++i) {
     161           0 :     setAtomsDerivatives( i, cvout.getAtomDerivatives(0, i) );
     162             :   }
     163           0 :   setBoxDerivatives( cvout.virial[0] );
     164           0 : }
     165             : 
     166          20 : void DihedralCorrelation::calculateCV( const ColvarInput& cvin, ColvarOutput& cvout ) {
     167          20 :   const Vector d10=delta(cvin.pos[1],cvin.pos[0]);
     168          20 :   const Vector d11=delta(cvin.pos[2],cvin.pos[1]);
     169          20 :   const Vector d12=delta(cvin.pos[3],cvin.pos[2]);
     170             : 
     171             :   Vector dd10,dd11,dd12;
     172             :   PLMD::Torsion t1;
     173          20 :   const double phi1  = t1.compute(d10,d11,d12,dd10,dd11,dd12);
     174             : 
     175          20 :   const Vector d20=delta(cvin.pos[5],cvin.pos[4]);
     176          20 :   const Vector d21=delta(cvin.pos[6],cvin.pos[5]);
     177          20 :   const Vector d22=delta(cvin.pos[7],cvin.pos[6]);
     178             : 
     179             :   Vector dd20,dd21,dd22;
     180             :   PLMD::Torsion t2;
     181          20 :   const double phi2 = t2.compute( d20, d21, d22, dd20, dd21, dd22 );
     182             : 
     183             :   // Calculate value
     184          20 :   const double diff = phi2 - phi1;
     185          20 :   cvout.values[0] = 0.5*(1.+std::cos(diff));
     186             :   // Derivatives wrt phi1
     187          20 :   const double dval = 0.5*std::sin(diff);
     188             :   dd10 *= dval;
     189             :   dd11 *= dval;
     190             :   dd12 *= dval;
     191             :   // And add
     192             :   cvout.derivs[0][0]=dd10;
     193             :   cvout.derivs[0][1]=dd11-dd10;
     194             :   cvout.derivs[0][2]=dd12-dd11;
     195             :   cvout.derivs[0][3]=-dd12;
     196             :   // Derivative wrt phi2
     197          20 :   dd20 *= -dval;
     198             :   dd21 *= -dval;
     199             :   dd22 *= -dval;
     200             :   // And add
     201             :   cvout.derivs[0][4]=dd20;
     202             :   cvout.derivs[0][5]=dd21-dd20;
     203             :   cvout.derivs[0][6]=dd22-dd21;
     204             :   cvout.derivs[0][7]=-dd22;
     205          40 :   cvout.virial.set( 0,
     206          20 :                     -(extProduct(d10,dd10)+extProduct(d11,dd11)+extProduct(d12,dd12))
     207          20 :                     - (extProduct(d20,dd20)+extProduct(d21,dd21)+extProduct(d22,dd22)) );
     208          20 : }
     209             : 
     210             : }
     211             : }

Generated by: LCOV version 1.16