LCOV - code coverage report
Current view: top level - function - FunctionWithSingleArgument.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 60 65 92.3 %
Date: 2026-11-05 10:19:04 Functions: 15 18 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             : #ifndef __PLUMED_function_FunctionWithSingleArgument_h
      23             : #define __PLUMED_function_FunctionWithSingleArgument_h
      24             : 
      25             : #include "core/ActionWithArguments.h"
      26             : #include "core/ActionWithValue.h"
      27             : #include "core/ActionRegister.h"
      28             : #include "FunctionSetup.h"
      29             : 
      30             : namespace PLMD {
      31             : namespace function {
      32             : 
      33             : template <class T>
      34             : class FunctionWithSingleArgument :
      35             :   public ActionWithValue,
      36             :   public ActionWithArguments {
      37             : private:
      38             :   T f;
      39             :   bool ismatrix;
      40             : public:
      41             :   static void registerKeywords(Keywords& keys);
      42             :   explicit FunctionWithSingleArgument(const ActionOptions&);
      43             :   /// Get the label to write in the graph
      44           0 :   std::string writeInGraph() const override {
      45           0 :     std::size_t und = getName().find_last_of("_");
      46           0 :     return getName().substr(0,und);
      47             :   }
      48             :   unsigned getNumberOfDerivatives() override ;
      49             :   void calculate() override ;
      50             :   void apply() override ;
      51             : };
      52             : 
      53             : template <class T>
      54         123 : void FunctionWithSingleArgument<T>::registerKeywords(Keywords& keys) {
      55         123 :   Action::registerKeywords(keys);
      56         123 :   ActionWithValue::registerKeywords(keys);
      57         123 :   ActionWithArguments::registerKeywords(keys);
      58         123 :   std::string name = keys.getDisplayName();
      59         123 :   std::size_t und=name.find("_ONEARG");
      60         123 :   keys.setDisplayName( name.substr(0,und) );
      61         246 :   keys.addInputKeyword("compulsory","ARG","vector/matrix","the vector/matrix that is being used in input");
      62         123 :   T::registerKeywords( keys );
      63         123 : }
      64             : 
      65             : template <class T>
      66          53 : FunctionWithSingleArgument<T>::FunctionWithSingleArgument(const ActionOptions&ao):
      67             :   Action(ao),
      68             :   ActionWithValue(ao),
      69             :   ActionWithArguments(ao),
      70          53 :   ismatrix(false) {
      71             : 
      72          53 :   if( getNumberOfArguments()!=1 ) {
      73           0 :     error("should only be one argument in input for this action");
      74             :   }
      75          53 :   ismatrix = getPntrToArgument(0)->getRank()==2 && !getPntrToArgument(0)->hasDerivatives();
      76             : 
      77          53 :   std::vector<std::size_t> shape;
      78          53 :   FunctionData<T>::setup( f, keywords.getOutputComponents(), shape, true, this );
      79          53 : }
      80             : 
      81             : template <class T>
      82         118 : unsigned FunctionWithSingleArgument<T>::getNumberOfDerivatives() {
      83         118 :   return getPntrToArgument(0)->getNumberOfStoredValues();
      84             : }
      85             : 
      86             : template <class T>
      87        5553 : void FunctionWithSingleArgument<T>::calculate() {
      88             :   const Value* myarg = getPntrToArgument(0);
      89        5553 :   std::vector<double> args( myarg->getNumberOfStoredValues() );
      90        5553 :   if( ismatrix ) {
      91             :     unsigned nvals = 0;
      92         266 :     for(unsigned i=0; i<myarg->getShape()[0]; ++i) {
      93         247 :       nvals += myarg->getRowLength(i);
      94             :     }
      95          19 :     args.resize( nvals );
      96             :     unsigned k=0;
      97          19 :     unsigned ncols = myarg->getNumberOfColumns();
      98         266 :     for(unsigned i=0; i<myarg->getShape()[0]; ++i) {
      99         969 :       for(unsigned j=0; j<myarg->getRowLength(i); ++j) {
     100         722 :         args[k] = myarg->get(i*ncols + j, false);
     101         722 :         ++k;
     102             :       }
     103             :     }
     104             :   } else {
     105     8198545 :     for(unsigned i=0; i<args.size(); ++i) {
     106     8193011 :       args[i] = myarg->get( i );
     107             :     }
     108             :   }
     109        5553 :   std::vector<double> vals( getNumberOfComponents() ), deriv( getNumberOfComponents()*args.size() );
     110             :   auto funcout = FunctionOutput::create( getNumberOfComponents(),
     111             :                                          vals.data(),
     112             :                                          args.size(),
     113             :                                          deriv.data() );
     114        5553 :   T::calc( f,
     115        5553 :            doNotCalculateDerivatives(),
     116           0 :            View<const double>(args.data(), args.size()),
     117             :            funcout );
     118       11329 :   for(unsigned i=0; i<getNumberOfComponents(); ++i) {
     119        5776 :     Value* myval=getPntrToComponent(i);
     120        5776 :     myval->set( vals[i] );
     121             : 
     122        5776 :     if( doNotCalculateDerivatives() ) {
     123        1351 :       continue ;
     124             :     }
     125        4425 :     if( ismatrix ) {
     126          19 :       myval->resizeDerivatives( args.size() );
     127             :     }
     128      198678 :     for(unsigned j=0; j<args.size(); ++j) {
     129      194253 :       myval->setDerivative( j, funcout.derivs[i][j] );
     130             :     }
     131             :   }
     132        5553 : }
     133             : 
     134             : template <class T>
     135        5537 : void FunctionWithSingleArgument<T>::apply() {
     136             :   // Forces may have been added to any of the components (e.g. only to label.moment-3)
     137             :   bool hasforces=false;
     138        6878 :   for(unsigned i=0; i<getNumberOfComponents(); ++i) {
     139        5755 :     if( getPntrToComponent(i)->forcesWereAdded() ) {
     140             :       hasforces=true;
     141             :       break;
     142             :     }
     143             :   }
     144        5537 :   if( !hasforces ) {
     145             :     return ;
     146             :   }
     147             : 
     148             :   Value* myarg = getPntrToArgument(0);
     149        8839 :   for(unsigned i=0; i<getNumberOfComponents(); ++i) {
     150        4425 :     const Value* myval = getPntrToComponent(i);
     151        4425 :     if( !myval->forcesWereAdded() ) {
     152          11 :       continue;
     153             :     }
     154             :     double force = myval->getForce();
     155        4414 :     if( ismatrix ) {
     156             :       unsigned k=0;
     157          19 :       unsigned ncols = myarg->getNumberOfColumns();
     158         266 :       for(unsigned n=0; n<myarg->getShape()[0]; ++n) {
     159             :         const unsigned rowlen = myarg->getRowLength(n);
     160         969 :         for(unsigned j=0; j<rowlen; ++j) {
     161         722 :           myarg->addForce( n*ncols+j, force*myval->getDerivative(k), false );
     162             :           ++k;
     163             :         }
     164             :       }
     165             :     } else {
     166      197872 :       for(unsigned j=0; j<myarg->getNumberOfStoredValues(); ++j) {
     167      193477 :         myarg->addForce( j, force*myval->getDerivative(j) );
     168             :       }
     169             :     }
     170             :   }
     171             : }
     172             : 
     173             : }
     174             : }
     175             : #endif

Generated by: LCOV version 1.16