LCOV - code coverage report
Current view: top level - function - Highest.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 25 26 96.2 %
Date: 2026-11-05 10:19:04 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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 "core/ActionRegister.h"
      23             : #include "FunctionShortcut.h"
      24             : #include "FunctionOfScalar.h"
      25             : #include "FunctionOfVector.h"
      26             : #include "FunctionWithSingleArgument.h"
      27             : #include "FunctionSetup.h"
      28             : 
      29             : namespace PLMD {
      30             : namespace function {
      31             : 
      32             : //+PLUMEDOC FUNCTION HIGHEST
      33             : /*
      34             : This function can be used to find the highest colvar by magnitude in a set.
      35             : 
      36             : This action allows you to find the highest of the input arguments.  As a first example of how it might be used consider the following input:
      37             : 
      38             : ```plumed
      39             : d1: DISTANCE ATOMS=1,2
      40             : d2: DISTANCE ATOMS=3,4
      41             : h1: HIGHEST ARG=d1,d2
      42             : PRINT ARG=h1 FILE=colvar
      43             : ```
      44             : 
      45             : The value, `h1`, that is output to the file `colvar` here will be equal to `d1` if `d1>d2` and will be equal to `d2` if `d2>d1`.  In other words, if
      46             : all the arguments input to a HIGHEST action are scalars then the output value will be a scalar that is equal to the largest of the input arguments.
      47             : Notice that you can also use this command with more than two arguments as illustrated below:
      48             : 
      49             : ```plumed
      50             : d1: DISTANCE ATOMS=1,2
      51             : d2: DISTANCE ATOMS=3,4
      52             : d3: DISTANCE ATOMS=5,6
      53             : d4: DISTANCE ATOMS=7,8
      54             : h1: HIGHEST ARG=d1,d2,d3,d4
      55             : PRINT ARG=h1 FILE=colvar
      56             : ```
      57             : 
      58             : ## Using a single vector as input
      59             : 
      60             : Instead of inputting multiple scalars you can input a single vector to this action instead as is illustrated below:
      61             : 
      62             : ```plumed
      63             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4
      64             : h1: HIGHEST ARG=d
      65             : PRINT ARG=h1 FILE=colvar
      66             : ```
      67             : 
      68             : The output from this action is a single scalar once again.  This single scalar is equal to the largest element of the input vector.
      69             : 
      70             : ## Using multiple vectors in input
      71             : 
      72             : If you input multiple vectors with the same numbers of elements to this action, as shown below, the output will be a vector.
      73             : 
      74             : 
      75             : ```plumed
      76             : d1: DISTANCE ATOMS1=1,2 ATOMS2=3,4
      77             : d2: DISTANCE ATOMS1=5,6 ATOMS2=7,8
      78             : d3: DISTANCE ATOMS1=9,10 ATOMS2=11,12
      79             : h2: HIGHEST ARG=d1,d2,d3
      80             : PRINT ARG=h2 FILE=colvar
      81             : ```
      82             : 
      83             : The elements of the output vector here are determined by doing an elementwise comparison of the elements in the input vectors.  In the above
      84             : input the first element of `h2` is equal to the distance between atoms 1 and 2 if this distance is larger than the distances between atoms 5 and 6 and the distance between atoms 9 and 10.
      85             : By the same token the second element of `h2` is equal to the distance between atoms 3 and 4 if this is larger than the distance between atoms 7 and 8 and the distance between atoms 11 and 12.
      86             : In other words, if the elements of the $j$th input vector are given by $v_i^{(j)}$ then the elements of the output vector, $h_i$ are given by:
      87             : 
      88             : $$
      89             : h_i = \max_j v_i^{(j)}
      90             : $$
      91             : 
      92             : Notice that you can also use a combination of scalars and vectors in the input to this action as shown below:
      93             : 
      94             : ```plumed
      95             : c: CONSTANT VALUE=0.05
      96             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4
      97             : h: HIGHEST ARG=d,c
      98             : PRINT ARG=h FILE=colvar
      99             : ```
     100             : 
     101             : For the input above the HIGHEST action outputs a vector with two elements.  The elements of this vector are equal to the distances between the pairs
     102             : of atoms that are specified in the DISTANCE command as long as those distances are greater than 0.05 nm.  If either of the two input distances is less
     103             : than 0.05 nm then the corresponding value in the vector `h` is set equal to 0.05 nm.
     104             : 
     105             : ## The MASK keyword
     106             : 
     107             : You should only use the MASK keyword for this action if you are using multiple arguments and at least one vector in the input to this action.
     108             : The following input illustrates how this keyword works:
     109             : 
     110             : ```plumed
     111             : m: CONSTANT VALUES=1,0
     112             : d1: DISTANCE ATOMS1=1,2 ATOMS2=3,4
     113             : d2: DISTANCE ATOMS1=5,6 ATOMS2=7,8
     114             : d3: DISTANCE ATOMS1=9,10 ATOMS2=11,12
     115             : h2: HIGHEST ARG=d1,d2,d3 MASK=m
     116             : ```
     117             : 
     118             : By using the MASK keyword here you ensure that only the first element of the output vector for `h2` is calculated. This element of the output vector
     119             : is evaluated as the corresponding element of the vector that is passed in the input to the MASK keyword is one.  By the same logic the second element
     120             : of the output vector is not computed because the corresponding element in the mask vector is 0.
     121             : 
     122             : The input above illustrates the key idea for the MASK keyword and is probably not very useful. To see an example where using a MASK for this type of action
     123             : is useful you should look at the expanded shortcuts in the documentation for [PARABETARMSD](PARABETARMSD.md).
     124             : 
     125             : */
     126             : //+ENDPLUMEDOC
     127             : 
     128             : //+PLUMEDOC FUNCTION LOWEST
     129             : /*
     130             : This function can be used to find the lowest colvar by magnitude in a set.
     131             : 
     132             : This action allows you to find the lowest of the input arguments.  As a first example of how it might be used consider the following input:
     133             : 
     134             : ```plumed
     135             : d1: DISTANCE ATOMS=1,2
     136             : d2: DISTANCE ATOMS=3,4
     137             : l1: LOWEST ARG=d1,d2
     138             : PRINT ARG=l1 FILE=colvar
     139             : ```
     140             : 
     141             : The value, `l1`, that is output to the file `colvar` here will be equal to `d1` if `d1<d2` and will be equal to `d2` if `d2<d1`.  In other words, if
     142             : all the arguments input to a LOWEST action are scalars then the output value will be a scalar that is equal to the smallest of the input arguments.
     143             : Notice that you can also use this command with more than two arguments as illustrated below:
     144             : 
     145             : ```plumed
     146             : d1: DISTANCE ATOMS=1,2
     147             : d2: DISTANCE ATOMS=3,4
     148             : d3: DISTANCE ATOMS=5,6
     149             : d4: DISTANCE ATOMS=7,8
     150             : l1: LOWEST ARG=d1,d2,d3,d4
     151             : PRINT ARG=l1 FILE=colvar
     152             : ```
     153             : 
     154             : ## Using a single vector as input
     155             : 
     156             : Instead of inputting multiple scalars you can input a single vector to this action instead as is illustrated below:
     157             : 
     158             : ```plumed
     159             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4
     160             : l1: LOWEST ARG=d
     161             : PRINT ARG=l1 FILE=colvar
     162             : ```
     163             : 
     164             : The output from this action is a single scalar once again.  This single scalar is equal to the smallest element of the input vector.
     165             : 
     166             : ## Using multiple vectors in input
     167             : 
     168             : If you input multiple vectors with the same numbers of elements to this action, as shown below, the output will be a vector.
     169             : 
     170             : 
     171             : ```plumed
     172             : d1: DISTANCE ATOMS1=1,2 ATOMS2=3,4
     173             : d2: DISTANCE ATOMS1=5,6 ATOMS2=7,8
     174             : d3: DISTANCE ATOMS1=9,10 ATOMS2=11,12
     175             : l2: LOWEST ARG=d1,d2,d3
     176             : PRINT ARG=l2 FILE=colvar
     177             : ```
     178             : 
     179             : The elements of the output vector here are determined by doing an elementwise comparison of the elements in the input vectors.  In the above
     180             : input the first element of `h2` is equal to the distance between atoms 1 and 2 if this distance is smaller than the distances between atoms 5 and 6 and the distance between atoms 9 and 10.
     181             : By the same token the second element of `h2` is equal to the distance between atoms 3 and 4 if this is smaller than the distance between atoms 7 and 8 and the distance between atoms 11 and 12.
     182             : In other words, if the elements of the $j$th input vector are given by $v_i^{(j)}$ then the elements of the output vector, $h_i$ are given by:
     183             : 
     184             : $$
     185             : h_i = \min_j v_i^{(j)}
     186             : $$
     187             : 
     188             : Notice that you can also use a combination of scalars and vectors in the input to this action as shown below:
     189             : 
     190             : ```plumed
     191             : c: CONSTANT VALUE=0.5
     192             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4
     193             : h: LOWEST ARG=d,c
     194             : PRINT ARG=h FILE=colvar
     195             : ```
     196             : 
     197             : For the input above the LOWEST action outputs a vector with two elements.  The elements of this vector are equal to the distances between the pairs
     198             : of atoms that are specified in the DISTANCE command as long as those distances are less than 0.5 nm.  If either of the two input distances is more
     199             : than 0.5 nm then the corresponding value in the vector `h` is set equal to 0.5 nm.
     200             : 
     201             : ## The MASK keyword
     202             : 
     203             : You should only use the MASK keyword for this action if you are using multiple arguments and at least one vector in the input to this action.
     204             : The following input illustrates how this keyword works:
     205             : 
     206             : ```plumed
     207             : m: CONSTANT VALUES=1,0
     208             : d1: DISTANCE ATOMS1=1,2 ATOMS2=3,4
     209             : d2: DISTANCE ATOMS1=5,6 ATOMS2=7,8
     210             : d3: DISTANCE ATOMS1=9,10 ATOMS2=11,12
     211             : h2: LOWEST ARG=d1,d2,d3 MASK=m
     212             : ```
     213             : 
     214             : By using the MASK keyword here you ensure that only the first element of the output vector for `h2` is calculated. This element of the output vector
     215             : is evaluated as the corresponding element of the vector that is passed in the input to the MASK keyword is one.  By the same logic the second element
     216             : of the output vector is not computed because the corresponding element in the mask vector is 0.
     217             : 
     218             : The input above illustrates the key idea for the MASK keyword and is probably not very useful. To see an example where using a MASK for this type of action
     219             : is useful you should look at the expanded shortcuts in the documentation for [PARABETARMSD](PARABETARMSD.md).
     220             : 
     221             : */
     222             : //+ENDPLUMEDOC
     223             : 
     224             : class Highest {
     225             : public:
     226             :   bool min;
     227             :   static void registerKeywords( Keywords& keys );
     228             :   static void read( Highest& func, ActionWithArguments* action, FunctionOptions& options );
     229             :   static void calc( const Highest& func, bool noderiv, const View<const double>& args, FunctionOutput& funcout );
     230             : };
     231             : 
     232             : typedef FunctionShortcut<Highest> HighestShortcut;
     233             : PLUMED_REGISTER_ACTION(HighestShortcut,"HIGHEST")
     234             : PLUMED_REGISTER_ACTION(HighestShortcut,"LOWEST")
     235             : typedef FunctionWithSingleArgument<Highest> OneargHighest;
     236             : PLUMED_REGISTER_ACTION(OneargHighest,"HIGHEST_ONEARG")
     237             : PLUMED_REGISTER_ACTION(OneargHighest,"LOWEST_ONEARG")
     238             : typedef FunctionOfScalar<Highest> ScalarHighest;
     239             : PLUMED_REGISTER_ACTION(ScalarHighest,"HIGHEST_SCALAR")
     240             : PLUMED_REGISTER_ACTION(ScalarHighest,"LOWEST_SCALAR")
     241             : typedef FunctionOfVector<Highest> VectorHighest;
     242             : PLUMED_REGISTER_ACTION(VectorHighest,"HIGHEST_VECTOR")
     243             : PLUMED_REGISTER_ACTION(VectorHighest,"LOWEST_VECTOR")
     244             : 
     245         298 : void Highest::registerKeywords( Keywords& keys ) {
     246         596 :   if( keys.getDisplayName().find("LOWEST")!=std::string::npos ) {
     247         386 :     keys.setValueDescription("scalar","the lowest of the input values");
     248             :   } else {
     249         210 :     keys.setValueDescription("scalar","the highest of the input values");
     250             :   }
     251         298 :   keys.add("hidden","MASKED_INPUT_ALLOWED","turns on that you are allowed to use masked inputs");
     252         298 : }
     253             : 
     254          66 : void Highest::read( Highest& func, ActionWithArguments* action, FunctionOptions& options ) {
     255          66 :   func.min=action->getName().find("LOWEST")!=std::string::npos;
     256          66 :   if( !func.min ) {
     257          23 :     plumed_assert( action->getName().find("HIGHEST")!=std::string::npos );
     258             :   }
     259         188 :   for(unsigned i=0; i<action->getNumberOfArguments(); ++i) {
     260         122 :     if( action->getPntrToArgument(i)->isPeriodic() ) {
     261           0 :       action->error("Cannot sort periodic values (check argument "+ action->getPntrToArgument(i)->getName() +")");
     262             :     }
     263             :   }
     264          66 : }
     265             : 
     266      103548 : void Highest::calc( const Highest& func, bool noderiv, const View<const double>& args, FunctionOutput& funcout ) {
     267      103548 :   if( !noderiv ) {
     268      340561 :     for(unsigned i=0; i<args.size(); ++i) {
     269      288808 :       funcout.derivs[0][i] = 0;
     270             :     }
     271             :   }
     272      103548 :   if( func.min ) {
     273      103409 :     funcout.values[0] = *std::min_element(args.begin(), args.end());
     274      103409 :     if( !noderiv ) {
     275       51742 :       funcout.derivs[0][std::min_element(args.begin(), args.end()) - args.begin()] = 1;
     276             :     }
     277             :   } else {
     278         139 :     funcout.values[0] = *std::max_element(args.begin(), args.end());
     279         139 :     if( !noderiv ) {
     280          11 :       funcout.derivs[0][std::max_element(args.begin(), args.end()) - args.begin()] = 1;
     281             :     }
     282             :   }
     283      103548 : }
     284             : 
     285             : }
     286             : }
     287             : 
     288             : 

Generated by: LCOV version 1.16