LCOV - code coverage report
Current view: top level - adjmat - ContactMatrix.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 44 46 95.7 %
Date: 2025-12-04 11:19:34 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2015-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 "ContactMatrix.h"
      23             : #include "core/ActionRegister.h"
      24             : 
      25             : //+PLUMEDOC MATRIX CONTACT_MATRIX_PROPER
      26             : /*
      27             : Adjacency matrix in which two atoms are adjacent if they are within a certain cutoff.
      28             : 
      29             : As discussed [here](module_adjmat.md) a useful tool for developing complex collective variables is the notion of the
      30             : so called adjacency matrix.  An adjacency matrix is an $N \times N$ matrix in which the $i$th, $j$th element tells you whether
      31             : or not the $i$th and $j$th atoms/molecules from a set of $N$ atoms/molecules are adjacent or not.  These matrices can then be further
      32             : analyzed using a number of other algorithms as is detailed in \cite tribello-clustering.
      33             : 
      34             : For this action the elements of the contact matrix are calculated using:
      35             : 
      36             : $$
      37             :  a_{ij} = \sigma( |\mathbf{r}_{ij}| )
      38             : $$
      39             : 
      40             : where $|\mathbf{r}_{ij}|$ is the magnitude of the vector connecting atoms $i$ and $j$ and where $\sigma$ is a switching function.
      41             : 
      42             : ## Examples
      43             : 
      44             : The input shown below calculates a $6 \times 6$ matrix whose elements are equal to one if atom $i$ and atom $j$ are within 0.3 nm
      45             : of each other and which is zero otherwise.  The columns in this matrix are then summed so as to give the coordination number for each atom.
      46             : The final quantity output in the colvar file is thus the average coordination number.
      47             : 
      48             : ```plumed
      49             : mat: CONTACT_MATRIX ATOMS=1-6 SWITCH={EXP D_0=0.2 R_0=0.1 D_MAX=0.66}
      50             : ones: ONES SIZE=6
      51             : csums: MATRIX_TIMES_VECTOR ARG=mat,ones
      52             : PRINT ARG=csums FILE=colvar
      53             : ```
      54             : 
      55             : */
      56             : //+ENDPLUMEDOC
      57             : 
      58             : namespace PLMD {
      59             : namespace adjmat {
      60             : 
      61             : typedef AdjacencyMatrixBase<ContactMatrix> cmap;
      62             : PLUMED_REGISTER_ACTION(cmap,"CONTACT_MATRIX_PROPER")
      63             : 
      64         788 : void ContactMatrix::registerKeywords( Keywords& keys ) {
      65        1576 :   keys.setDisplayName("CONTACT_MATRIX");
      66         788 :   keys.add("compulsory","NN","6","The n parameter of the switching function ");
      67         788 :   keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN");
      68         788 :   keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function");
      69         788 :   keys.add("compulsory","R_0","The r_0 parameter of the switching function");
      70         788 :   keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. "
      71             :            "The following provides information on the \\ref switchingfunction that are available. "
      72             :            "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords.");
      73        1576 :   keys.linkActionInDocs("SWITCH","LESS_THAN");
      74         788 : }
      75             : 
      76         219 : void ContactMatrix::parseInput( AdjacencyMatrixBase<ContactMatrix>* action ) {
      77             :   std::string errors;
      78             :   std::string swinput;
      79         438 :   action->parse("SWITCH",swinput);
      80         219 :   if( swinput.length()>0 ) {
      81         192 :     switchingFunction.set( swinput, errors );
      82         192 :     if( errors.length()!=0 ) {
      83           0 :       action->error("problem reading switching function description " + errors);
      84             :     }
      85             :   } else {
      86          27 :     int nn=0;
      87          27 :     int mm=0;
      88          27 :     double r_0=-1.0;
      89          27 :     double d_0= 0.0;
      90          27 :     action->parse("NN",nn);
      91          27 :     action->parse("MM",mm);
      92          27 :     action->parse("R_0",r_0);
      93          27 :     action->parse("D_0",d_0);
      94          27 :     if( r_0<0.0 ) {
      95           0 :       action->error("you must set a value for R_0");
      96             :     }
      97          27 :     switchingFunction.set(nn,mm,r_0,d_0);
      98             :   }
      99             :   // And set the link cell cutoff
     100         219 :   action->log.printf("  switching function cutoff is %s \n",switchingFunction.description().c_str() );
     101         219 :   action->setLinkCellCutoff( true, switchingFunction.get_dmax() );
     102         219 : }
     103             : 
     104    46204029 : void ContactMatrix::calculateWeight( const ContactMatrix& data,
     105             :                                      const AdjacencyMatrixInput& input,
     106             :                                      MatrixOutput output ) {
     107             :   const double mod2 = input.pos.modulo2();
     108    46204029 :   if( mod2<epsilon ) {
     109    42058225 :     return;  // Atoms can't be bonded to themselves
     110             :   }
     111             :   double dfunc;
     112    46202477 :   output.val[0] = data.switchingFunction.calculateSqr( mod2, dfunc );
     113    46202477 :   if( output.val[0]<epsilon ) {
     114    33229841 :     output.val[0] = 0.0;
     115    33229841 :     return;
     116             :   }
     117    12972636 :   if( input.noderiv ) {
     118             :     return;
     119             :   }
     120     4145804 :   const Vector v { (-dfunc)*input.pos[0],
     121             :                    (-dfunc)*input.pos[1],
     122     4145804 :                    (-dfunc)*input.pos[2] };
     123     4145804 :   output.deriv[0] = v[0];
     124     4145804 :   output.deriv[1] = v[1];
     125     4145804 :   output.deriv[2] = v[2];
     126     4145804 :   output.deriv[3] =-v[0];
     127     4145804 :   output.deriv[4] =-v[1];
     128     4145804 :   output.deriv[5] =-v[2];
     129             : 
     130     4145804 :   output.assignOuterProduct( 6, v, input.pos);
     131             : }
     132             : 
     133             : } // namespace adjmat
     134             : } // namespace PLMD

Generated by: LCOV version 1.16