LCOV - code coverage report
Current view: top level - function - MoreThan.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 27 41 65.9 %
Date: 2025-04-08 21:11:17 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2017 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 "MoreThan.h"
      23             : #include "FunctionShortcut.h"
      24             : #include "FunctionOfScalar.h"
      25             : #include "FunctionOfVector.h"
      26             : #include "FunctionOfMatrix.h"
      27             : #include "core/ActionRegister.h"
      28             : 
      29             : #include <cmath>
      30             : 
      31             : namespace PLMD {
      32             : namespace function {
      33             : 
      34             : //+PLUMEDOC FUNCTION MORE_THAN
      35             : /*
      36             : Use a switching function to determine how many of the input variables are more than a certain cutoff.
      37             : 
      38             : This action takes one argument, $r$ and evaluates the following function:
      39             : 
      40             : $$
      41             : w(s) = 1 - s(r)
      42             : $$
      43             : 
      44             : In this equation $s(r)$ is one of the switching functions described in the documentation for the action [LESS_THAN](LESS_THAN.md).
      45             : The output value $w$ is thus a number between 0 and 1 that tells you if the input value is greater than some cutoff.  Furthermore,
      46             : the value of $w$ smoothly from zero to one as the input value $r$ crosses the threshold of interest so any function of this value
      47             : is differentiable.
      48             : 
      49             : The following example, shows how we can apply the function above on the instantaneous value of the distance between atom 1 and 2.
      50             : The MORE_THAN action here is used to determine whether the input distance is greater than 0.2 nm.
      51             : 
      52             : ```plumed
      53             : d: DISTANCE ATOMS=1,2
      54             : b: MORE_THAN ARG=d SWITCH={RATIONAL R_0=0.2}
      55             : ```
      56             : 
      57             : You can use all the switching function options described in the documentation for [LESS_THAN](LESS_THAN.md) here in place of RATIONAL.
      58             : 
      59             : ## Non rank zero arguments
      60             : 
      61             : Instead of passing a single scalar in the input to the `MORE_THAN` action you can pass a single vector as shown here:
      62             : 
      63             : ```plumed
      64             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 ATOMS4=7,8
      65             : b: MORE_THAN ARG=d SWITCH={RATIONAL R_0=0.2}
      66             : ```
      67             : 
      68             : The input to the `MORE_THAN` action here is a vector with four elements. The output from the action `b` is similarly
      69             : a vector with four elements. In calculating the elements of this vector PLUMED applies the function described in the previous
      70             : section on each of the distances in turn. The first element of `b` thus tells you if the distance between atoms 1 and 2 is between
      71             : greater than 0.2 nm, the second element tells you if the distance between atoms 3 and 4 is greater than 0.2 nm and so on.
      72             : 
      73             : You can use the commands in the above example input to evaluate the number of distances that greater than a threshold as follows:
      74             : 
      75             : ```plumed
      76             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 ATOMS4=7,8
      77             : b: MORE_THAN ARG=d SWITCH={RATIONAL R_0=0.2}
      78             : s: SUM ARG=b PERIODIC=NO
      79             : PRINT ARG=s FILE=colvar
      80             : ```
      81             : 
      82             : The final scalar that is output here is evaluated using the following summation:
      83             : 
      84             : $$
      85             : s = \sum_i 1 - s(d_i)
      86             : $$
      87             : 
      88             : where the sum over $i$ here runs over the four distances in the above expression. This scalar tells you the number of distances that are
      89             : more than 0.2 nm.
      90             : 
      91             : Notice that you can do something similar with a matrix as input as shown below:
      92             : 
      93             : ```plumed
      94             : d: DISTANCE_MATRIX GROUPA=1-10 GROUPB=11-20
      95             : b: MORE_THAN ARG=d SWITCH={RATIONAL R_0=0.2}
      96             : s: SUM ARG=b PERIODIC=NO
      97             : PRINT ARG=s FILE=colvar
      98             : ```
      99             : 
     100             : This input tells PLUMED to calculate the 100 distances between the atoms in the two input groups. The final value that is printed to the colvar file then
     101             : tells you how many of these distances are greater than 0.2 nm.
     102             : 
     103             : */
     104             : //+ENDPLUMEDOC
     105             : 
     106             : //+PLUMEDOC FUNCTION MORE_THAN_VECTOR
     107             : /*
     108             : Use a switching function to determine how many of elements in the input vector are more than a certain cutoff.
     109             : 
     110             : \par Examples
     111             : 
     112             : */
     113             : //+ENDPLUMEDOC
     114             : 
     115             : //+PLUMEDOC COLVAR MORE_THAN_MATRIX
     116             : /*
     117             : Transform all the elements of a matrix using a switching function that is one when the input value is larger than a threshold
     118             : 
     119             : \par Examples
     120             : 
     121             : */
     122             : //+ENDPLUMEDOC
     123             : 
     124             : typedef FunctionShortcut<MoreThan> MoreThanShortcut;
     125             : PLUMED_REGISTER_ACTION(MoreThanShortcut,"MORE_THAN")
     126             : typedef FunctionOfScalar<MoreThan> ScalarMoreThan;
     127             : PLUMED_REGISTER_ACTION(ScalarMoreThan,"MORE_THAN_SCALAR")
     128             : typedef FunctionOfVector<MoreThan> VectorMoreThan;
     129             : PLUMED_REGISTER_ACTION(VectorMoreThan,"MORE_THAN_VECTOR")
     130             : typedef FunctionOfMatrix<MoreThan> MatrixMoreThan;
     131             : PLUMED_REGISTER_ACTION(MatrixMoreThan,"MORE_THAN_MATRIX")
     132             : 
     133         248 : void MoreThan::registerKeywords(Keywords& keys) {
     134         248 :   keys.add("compulsory","NN","6","The n parameter of the switching function ");
     135         248 :   keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN");
     136         248 :   keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function");
     137         248 :   keys.add("compulsory","R_0","The r_0 parameter of the switching function");
     138         248 :   keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. "
     139             :            "The following provides information on the \\ref switchingfunction that are available. "
     140             :            "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords.");
     141         248 :   keys.addFlag("SQUARED",false,"is the input quantity the square of the value that you would like to apply the switching function to");
     142         496 :   keys.setValueDescription("scalar/vector/matrix","a function that is one if the if the input is more than a threshold");
     143         248 : }
     144             : 
     145          68 : void MoreThan::read( ActionWithArguments* action ) {
     146          68 :   if( action->getNumberOfArguments()!=1 ) {
     147           0 :     action->error("should only be one argument to more_than actions");
     148             :   }
     149          68 :   if( action->getPntrToArgument(0)->isPeriodic() ) {
     150           0 :     action->error("cannot use this function on periodic functions");
     151             :   }
     152             : 
     153             : 
     154             :   std::string sw,errors;
     155         136 :   action->parse("SWITCH",sw);
     156          68 :   if(sw.length()>0) {
     157          68 :     switchingFunction.set(sw,errors);
     158          68 :     if( errors.length()!=0 ) {
     159           0 :       action->error("problem reading SWITCH keyword : " + errors );
     160             :     }
     161             :   } else {
     162           0 :     int nn=6;
     163           0 :     int mm=0;
     164           0 :     double d0=0.0;
     165           0 :     double r0=0.0;
     166           0 :     action->parse("R_0",r0);
     167           0 :     if(r0<=0.0) {
     168           0 :       action->error("R_0 should be explicitly specified and positive");
     169             :     }
     170           0 :     action->parse("D_0",d0);
     171           0 :     action->parse("NN",nn);
     172           0 :     action->parse("MM",mm);
     173           0 :     switchingFunction.set(nn,mm,r0,d0);
     174             :   }
     175          68 :   action->log<<"  using switching function with cutoff "<<switchingFunction.description()<<"\n";
     176          68 :   action->parseFlag("SQUARED",squared);
     177          68 :   if( squared ) {
     178           6 :     action->log<<"  input quantity is square of quantity that switching function acts upon\n";
     179             :   }
     180          68 : }
     181             : 
     182      556662 : void MoreThan::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const {
     183             :   plumed_dbg_assert( args.size()==1 );
     184      556662 :   if( squared ) {
     185      469112 :     vals[0] = 1.0 - switchingFunction.calculateSqr( args[0], derivatives(0,0) );
     186             :   } else {
     187       87550 :     vals[0] = 1.0 - switchingFunction.calculate( args[0], derivatives(0,0) );
     188             :   }
     189      556662 :   derivatives(0,0) = -args[0]*derivatives(0,0);
     190      556662 : }
     191             : 
     192             : }
     193             : }
     194             : 
     195             : 

Generated by: LCOV version 1.16