LCOV - code coverage report
Current view: top level - function - Sum.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 51 54 94.4 %
Date: 2026-11-05 10:19:04 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-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/ActionWithArguments.h"
      23             : #include "core/ActionWithValue.h"
      24             : #include "core/ActionRegister.h"
      25             : 
      26             : //+PLUMEDOC COLVAR SUM
      27             : /*
      28             : Calculate the sum of the arguments
      29             : 
      30             : This action takes a single vector, a single matrix or a single grid in input. The output is a scalar
      31             : that contains the sum of all the elements in the input vector/matrix/grid. This action is
      32             : very useful if you want to do calculations like the one illustrated in this example:
      33             : 
      34             : ```plumed
      35             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 ATOMS4=7,8
      36             : b: LESS_THAN ARG=d SWITCH={RATIONAL R_0=0.1}
      37             : s: SUM ARG=b PERIODIC=NO
      38             : PRINT ARG=s FILE=colvar
      39             : ```
      40             : 
      41             : This example calculates and outputs the number of distances that are less than 0.1 nm.
      42             : 
      43             : You can do something similar by summing the elements of a matrix as shown below:
      44             : 
      45             : ```plumed
      46             : c: CONTACT_MATRIX GROUP=1-100 SWITCH={RATIONAL R_0=0.1}
      47             : s: SUM ARG=c PERIODIC=NO
      48             : PRINT ARG=s FILE=colvar
      49             : ```
      50             : 
      51             : If you want to sum all the elements in a grid you can. However, if the input is a function on a grid
      52             : it is more likely that you will want to compute the integral using [INTEGRATE_GRID](INTEGRATE_GRID.md).
      53             : 
      54             : */
      55             : //+ENDPLUMEDOC
      56             : 
      57             : //+PLUMEDOC COLVAR MEAN
      58             : /*
      59             : Calculate the arithmetic mean of the elements in a vector
      60             : 
      61             : This action takes a single vector or a single matrix in input.  The output is a scalar
      62             : that contains the mean of all the elements in the input vector/matrix. This action is
      63             : useful if you want do to calculations like the one illustrated in this example:
      64             : 
      65             : ```plumed
      66             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 ATOMS4=7,8
      67             : m: MEAN ARG=d PERIODIC=NO
      68             : PRINT ARG=m FILE=colvar
      69             : ```
      70             : 
      71             : The output from the MEAN action here is the average over the four distances that are evaluated by the
      72             : DISTANCE action.  Notice that you can also do the calculation above using:
      73             : 
      74             : ```plumed
      75             : d: DISTANCE ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 ATOMS4=7,8
      76             : s: SUM ARG=d PERIODIC=NO
      77             : m: CUSTOM ARG=s FUNC=x/4 PERIODIC=NO
      78             : PRINT ARG=m FILE=colvar
      79             : ```
      80             : 
      81             : */
      82             : //+ENDPLUMEDOC
      83             : 
      84             : namespace PLMD {
      85             : namespace function {
      86             : 
      87             : class Sum :
      88             :   public ActionWithValue,
      89             :   public ActionWithArguments {
      90             : private:
      91             :   bool ismatrix;
      92             : public:
      93             :   static void registerKeywords(Keywords& keys);
      94             :   explicit Sum(const ActionOptions&);
      95             :   unsigned getNumberOfDerivatives() override ;
      96             :   void calculate() override ;
      97             :   void apply() override ;
      98             : };
      99             : 
     100             : PLUMED_REGISTER_ACTION(Sum,"SUM")
     101             : PLUMED_REGISTER_ACTION(Sum,"MEAN")
     102             : 
     103        1495 : void Sum::registerKeywords(Keywords& keys) {
     104        1495 :   Action::registerKeywords(keys);
     105        1495 :   ActionWithValue::registerKeywords(keys);
     106        1495 :   ActionWithArguments::registerKeywords(keys);
     107        2990 :   keys.addInputKeyword("compulsory","ARG","scalar/vector/matrix/grid","the vector/matrix/grid whose elements should be added together (the sum of a scalar is the scalar itself)");
     108        1495 :   keys.add("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function.  If the output is not periodic you must state this using PERIODIC=NO");
     109        5980 :   keys.setValueDescription("scalar","the " + keys.getDisplayName() + " of the elements in the input value");
     110        1495 :   keys.add("hidden","MASKED_INPUT_ALLOWED","turns on that you are allowed to use masked inputs ");
     111        2990 :   keys.reset_style("NUMERICAL_DERIVATIVES","hidden");
     112        1495 : }
     113             : 
     114         871 : Sum::Sum(const ActionOptions&ao):
     115             :   Action(ao),
     116             :   ActionWithValue(ao),
     117             :   ActionWithArguments(ao),
     118         871 :   ismatrix(false) {
     119             : 
     120         871 :   if( getNumberOfArguments()!=1 ) {
     121           0 :     error("should only be one argument in input for this action");
     122             :   }
     123         875 :   ismatrix = getPntrToArgument(0)->getRank()==2 && !getPntrToArgument(0)->hasDerivatives();
     124             : 
     125         871 :   addValue();
     126         871 :   std::vector<std::string> period;
     127        1742 :   parseVector("PERIODIC",period);
     128         871 :   if( period.size()==1 ) {
     129         870 :     if( period[0]!="NO") {
     130           0 :       error("input to PERIODIC keyword does not make sense");
     131             :     }
     132         870 :     setNotPeriodic();
     133           1 :   } else if( period.size()==2 ) {
     134           1 :     setPeriodic( period[0], period[1] );
     135             :   } else {
     136           0 :     error("input to PERIODIC keyword does not make sense");
     137             :   }
     138         871 : }
     139             : 
     140        1056 : unsigned Sum::getNumberOfDerivatives() {
     141        1056 :   return 0;
     142             : }
     143             : 
     144       50056 : void Sum::calculate() {
     145             :   double myval = 0;
     146             :   const Value* myarg = getPntrToArgument(0);
     147       50056 :   if( ismatrix ) {
     148         371 :     unsigned ncols = myarg->getNumberOfColumns();
     149       13936 :     for(unsigned i=0; i<myarg->getShape()[0]; ++i) {
     150      521346 :       for(unsigned j=0; j<myarg->getRowLength(i); ++j) {
     151      507781 :         myval += myarg->get(i*ncols + j, false);
     152             :       }
     153             :     }
     154             :   } else {
     155       49685 :     unsigned nargs = myarg->getNumberOfStoredValues();
     156     3201945 :     for(unsigned i=0; i<nargs; ++i) {
     157     3152260 :       myval += myarg->get(i);
     158             :     }
     159             :   }
     160       50056 :   if( getName()=="MEAN" ) {
     161        3817 :     getPntrToComponent(0)->set( myval / myarg->getNumberOfValues() );
     162             :   } else {
     163       46239 :     getPntrToComponent(0)->set( myval );
     164             :   }
     165       50056 : }
     166             : 
     167       50036 : void Sum::apply() {
     168       50036 :   if( !getPntrToComponent(0)->forcesWereAdded() ) {
     169             :     return ;
     170             :   }
     171             : 
     172             :   Value* myarg = getPntrToArgument(0);
     173       40549 :   double force = getPntrToComponent(0)->getForce(0);
     174       40549 :   if( getName()=="MEAN" ) {
     175        1861 :     force = force / myarg->getNumberOfValues();
     176             :   }
     177       40549 :   if( ismatrix ) {
     178         140 :     unsigned ncols = myarg->getNumberOfColumns();
     179        4068 :     for(unsigned i=0; i<myarg->getShape()[0]; ++i) {
     180      231324 :       for(unsigned j=0; j<myarg->getRowLength(i); ++j) {
     181      227396 :         myarg->addForce(i*ncols + j, force, false);
     182             :       }
     183             :     }
     184             :   } else {
     185       40409 :     unsigned nargs = myarg->getNumberOfStoredValues();
     186     2488594 :     for(unsigned i=0; i<nargs; ++i) {
     187     2448185 :       myarg->addForce( i, force );
     188             :     }
     189             :   }
     190             : }
     191             : 
     192             : }
     193             : 
     194             : 
     195             : }

Generated by: LCOV version 1.16