LCOV - code coverage report
Current view: top level - multicolvar - XYTorsion.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 74 84 88.1 %
Date: 2026-03-30 13:16:06 Functions: 20 25 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             : #include "MultiColvarBase.h"
      23             : #include "AtomValuePack.h"
      24             : #include "core/ActionRegister.h"
      25             : #include "tools/Torsion.h"
      26             : #include "tools/SwitchingFunction.h"
      27             : 
      28             : #include <string>
      29             : #include <cmath>
      30             : 
      31             : namespace PLMD {
      32             : namespace multicolvar {
      33             : 
      34             : //+PLUMEDOC MCOLVAR XYTORSIONS
      35             : /*
      36             : Calculate the torsional angle around the x axis from the positive y direction.
      37             : 
      38             : \par Examples
      39             : 
      40             : The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and
      41             : the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
      42             : \plumedfile
      43             : d1: XYTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
      44             : PRINT ARG=d1.between
      45             : \endplumedfile
      46             : (See also \ref PRINT).
      47             : */
      48             : //+ENDPLUMEDOC
      49             : 
      50             : //+PLUMEDOC MCOLVAR XZTORSIONS
      51             : /*
      52             : Calculate the torsional angle around the x axis from the positive z direction.
      53             : 
      54             : \par Examples
      55             : 
      56             : The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and
      57             : the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
      58             : \plumedfile
      59             : d1: XZTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
      60             : PRINT ARG=d1.*
      61             : \endplumedfile
      62             : (See also \ref PRINT).
      63             : */
      64             : //+ENDPLUMEDOC
      65             : 
      66             : //+PLUMEDOC MCOLVAR YXTORSIONS
      67             : /*
      68             : Calculate the torsional angle around the y axis from the positive x direction.
      69             : 
      70             : \par Examples
      71             : 
      72             : The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and
      73             : the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
      74             : \plumedfile
      75             : d1: YXTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
      76             : PRINT ARG=d1.*
      77             : \endplumedfile
      78             : (See also \ref PRINT).
      79             : */
      80             : //+ENDPLUMEDOC
      81             : 
      82             : //+PLUMEDOC MCOLVAR YZTORSIONS
      83             : /*
      84             : Calculate the torsional angle around the y axis from the positive z direction.
      85             : 
      86             : \par Examples
      87             : 
      88             : The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and
      89             : the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
      90             : \plumedfile
      91             : d1: YZTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
      92             : PRINT ARG=d1.*
      93             : \endplumedfile
      94             : (See also \ref PRINT).
      95             : */
      96             : //+ENDPLUMEDOC
      97             : 
      98             : //+PLUMEDOC MCOLVAR ZXTORSIONS
      99             : /*
     100             : Calculate the torsional angle around the z axis from the positive x direction.
     101             : 
     102             : \par Examples
     103             : 
     104             : The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and
     105             : the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
     106             : \plumedfile
     107             : d1: ZXTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
     108             : PRINT ARG=d1.*
     109             : \endplumedfile
     110             : (See also \ref PRINT).
     111             : */
     112             : //+ENDPLUMEDOC
     113             : 
     114             : //+PLUMEDOC MCOLVAR ZYTORSIONS
     115             : /*
     116             : Calculate the torsional angle around the z axis from the positive y direction.
     117             : 
     118             : \par Examples
     119             : 
     120             : The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and
     121             : the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2.  The minimum of these two quantities is then output
     122             : \plumedfile
     123             : d1: ZYTORSIONS ATOMS1=3,5 ATOMS2=1,2 BETWEEN={GAUSSIAN LOWER=0 UPPER=pi SMEAR=0.1}
     124             : PRINT ARG=d1.*
     125             : \endplumedfile
     126             : (See also \ref PRINT).
     127             : */
     128             : //+ENDPLUMEDOC
     129             : 
     130             : 
     131             : 
     132             : 
     133             : class XYTorsion : public MultiColvarBase {
     134             : private:
     135             :   bool use_sf;
     136             :   unsigned myc1, myc2;
     137             :   SwitchingFunction sf1;
     138             : public:
     139             :   static void registerKeywords( Keywords& keys );
     140             :   explicit XYTorsion(const ActionOptions&);
     141             : // active methods:
     142             :   double compute( const unsigned& tindex, AtomValuePack& myatoms ) const override;
     143             :   double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& ) const override;
     144             : /// Returns the number of coordinates of the field
     145           3 :   bool isPeriodic() override {
     146           3 :     return true;
     147             :   }
     148           1 :   void retrieveDomain( std::string& min, std::string& max) override {
     149             :     min="-pi";
     150             :     max="pi";
     151           1 :   }
     152             : };
     153             : 
     154       13785 : PLUMED_REGISTER_ACTION(XYTorsion,"XYTORSIONS")
     155       13785 : PLUMED_REGISTER_ACTION(XYTorsion,"XZTORSIONS")
     156       13785 : PLUMED_REGISTER_ACTION(XYTorsion,"YXTORSIONS")
     157       13785 : PLUMED_REGISTER_ACTION(XYTorsion,"YZTORSIONS")
     158       13789 : PLUMED_REGISTER_ACTION(XYTorsion,"ZXTORSIONS")
     159       13787 : PLUMED_REGISTER_ACTION(XYTorsion,"ZYTORSIONS")
     160             : 
     161          27 : void XYTorsion::registerKeywords( Keywords& keys ) {
     162          27 :   MultiColvarBase::registerKeywords( keys );
     163          27 :   keys.use("MAX");
     164          27 :   keys.use("ALT_MIN");
     165          27 :   keys.use("MEAN");
     166          27 :   keys.use("MIN");
     167          27 :   keys.use("LOWEST");
     168          27 :   keys.use("HIGHEST");
     169          27 :   keys.use("BETWEEN");
     170          27 :   keys.use("HISTOGRAM");
     171          27 :   keys.use("MOMENTS");
     172          54 :   keys.add("numbered","ATOMS","the atoms involved in each of the torsion angles you wish to calculate. "
     173             :            "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one torsion will be "
     174             :            "calculated for each ATOM keyword you specify (all ATOM keywords should "
     175             :            "specify the indices of two atoms).  The eventual number of quantities calculated by this "
     176             :            "action will depend on what functions of the distribution you choose to calculate.");
     177          54 :   keys.reset_style("ATOMS","atoms");
     178          54 :   keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group");
     179          54 :   keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all "
     180             :            "the atoms in GROUPB. This must be used in conjunction with GROUPB.");
     181          54 :   keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms "
     182             :            "in GROUPB. This must be used in conjunction with GROUPA.");
     183          54 :   keys.add("optional","SWITCH","A switching function that ensures that only angles are only computed when atoms are within "
     184             :            "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available.");
     185          27 : }
     186             : 
     187           3 : XYTorsion::XYTorsion(const ActionOptions&ao):
     188             :   Action(ao),
     189             :   MultiColvarBase(ao),
     190           3 :   use_sf(false) {
     191           3 :   if( getName().find("XY")!=std::string::npos) {
     192           0 :     myc1=0;
     193           0 :     myc2=1;
     194           3 :   } else if( getName().find("XZ")!=std::string::npos) {
     195           0 :     myc1=0;
     196           0 :     myc2=2;
     197           3 :   } else if( getName().find("YX")!=std::string::npos) {
     198           0 :     myc1=1;
     199           0 :     myc2=0;
     200           3 :   } else if( getName().find("YZ")!=std::string::npos) {
     201           0 :     myc1=1;
     202           0 :     myc2=2;
     203           3 :   } else if( getName().find("ZX")!=std::string::npos) {
     204           2 :     myc1=2;
     205           2 :     myc2=0;
     206           1 :   } else if( getName().find("ZY")!=std::string::npos) {
     207           1 :     myc1=2;
     208           1 :     myc2=1;
     209             :   } else {
     210           0 :     plumed_error();
     211             :   }
     212             : 
     213             :   // Read in switching function
     214             :   std::string sfinput, errors;
     215           6 :   parse("SWITCH",sfinput);
     216           3 :   if( sfinput.length()>0 ) {
     217           2 :     use_sf=true;
     218           2 :     weightHasDerivatives=true;
     219           2 :     sf1.set(sfinput,errors);
     220           2 :     if( errors.length()!=0 ) {
     221           0 :       error("problem reading SWITCH keyword : " + errors );
     222             :     }
     223           2 :     log.printf("  only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() );
     224           2 :     setLinkCellCutoff( sf1.get_dmax() );
     225             :   }
     226             : 
     227             :   // Read in the atoms
     228             :   std::vector<AtomNumber> all_atoms;
     229           6 :   readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms );
     230           3 :   if( atom_lab.size()==0 ) {
     231           2 :     readAtomsLikeKeyword( "ATOMS", 2, all_atoms );
     232             :   }
     233           3 :   setupMultiColvarBase( all_atoms );
     234             :   // And check everything has been read in correctly
     235           3 :   checkRead();
     236           3 : }
     237             : 
     238         110 : double XYTorsion::calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& myatoms ) const {
     239         110 :   if(!use_sf) {
     240             :     return 1.0;
     241             :   }
     242             : 
     243         100 :   Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
     244         100 :   double dw, w = sf1.calculateSqr( distance.modulo2(), dw );
     245         100 :   addAtomDerivatives( 0, 0, (-dw)*distance, myatoms );
     246         100 :   addAtomDerivatives( 0, 1, (+dw)*distance, myatoms );
     247         100 :   myatoms.addBoxDerivatives( 0, (-dw)*Tensor(distance,distance) );
     248         100 :   return w;
     249             : }
     250             : 
     251          50 : double XYTorsion::compute( const unsigned& tindex, AtomValuePack& myatoms ) const {
     252          50 :   Vector dd0, dd1, dd2, axis, rot, distance;
     253          50 :   axis.zero();
     254          50 :   rot.zero();
     255          50 :   rot[myc1]=1;
     256          50 :   axis[myc2]=1;
     257          50 :   distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) );
     258             :   PLMD::Torsion t;
     259          50 :   double torsion=t.compute( distance, rot, axis, dd0, dd1, dd2 );
     260             : 
     261          50 :   addAtomDerivatives( 1, 0, -dd0, myatoms );
     262          50 :   addAtomDerivatives( 1, 1, dd0, myatoms );
     263          50 :   myatoms.addBoxDerivatives( 1, -extProduct(distance,dd0) );
     264          50 :   return torsion;
     265             : }
     266             : 
     267             : }
     268             : }
     269             : 

Generated by: LCOV version 1.16