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_FunctionOfScalar_h 23 : #define __PLUMED_function_FunctionOfScalar_h 24 : 25 : #include "Function.h" 26 : #include "FunctionSetup.h" 27 : #include "Custom.h" 28 : 29 : namespace PLMD { 30 : namespace function { 31 : 32 : /** 33 : \ingroup INHERIT 34 : This is the abstract base class to use for implementing new CV function, within it there is 35 : \ref AddingAFunction "information" as to how to go about implementing a new function. 36 : */ 37 : 38 : template <class T> 39 : class FunctionOfScalar : public Function { 40 : private: 41 : /// Set equal to one if we are doing evaluateGridFunction 42 : unsigned argstart; 43 : /// The function that is being computed 44 : T myfunc; 45 : /// Buffers for the arguments, values and derivatives (kept to avoid allocations at every step) 46 : std::vector<double> args, vals, deriv; 47 : public: 48 : explicit FunctionOfScalar(const ActionOptions&); 49 6315 : virtual ~FunctionOfScalar() {} 50 : /// Get the label to write in the graph 51 : std::string writeInGraph() const override ; 52 : std::string getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const override ; 53 : void calculate() override; 54 : static void registerKeywords(Keywords&); 55 : }; 56 : 57 : template <class T> 58 4276 : void FunctionOfScalar<T>::registerKeywords(Keywords& keys) { 59 4276 : Function::registerKeywords(keys); 60 4276 : std::string name = keys.getDisplayName(); 61 4276 : std::size_t und=name.find("_SCALAR"); 62 8552 : keys.setDisplayName( name.substr(0,und) ); 63 4276 : keys.add("hidden","NO_ACTION_LOG","suppresses printing from action on the log"); 64 4276 : T::registerKeywords( keys ); 65 4276 : if( keys.getDisplayName()=="SUM" ) { 66 0 : keys.setValueDescription("scalar","the sum of all the input arguments"); 67 4276 : } else if( keys.getDisplayName()=="MEAN" ) { 68 0 : keys.setValueDescription("scalar","the mean of all the input arguments"); 69 4276 : } else if( keys.getDisplayName()=="EVALUATE_FUNCTION_FROM_GRID" ) { 70 24 : keys.addInputKeyword("compulsory","ARG","scalar/grid",""); 71 : } 72 4276 : } 73 : 74 : template <class T> 75 2110 : FunctionOfScalar<T>::FunctionOfScalar(const ActionOptions&ao): 76 : Action(ao), 77 : Function(ao), 78 2110 : argstart(0) { 79 : // Check if first argument is grid 80 2110 : if( getPntrToArgument(0)->getRank()>0 && getPntrToArgument(0)->hasDerivatives() ) { 81 4 : argstart=1; 82 : } 83 : // Create the values to hold the output 84 2110 : std::vector<std::size_t> shape; 85 2110 : FunctionData<T>::setup( myfunc, keywords.getOutputComponents(), shape, true, this ); 86 2123 : } 87 : 88 : template <class T> 89 0 : std::string FunctionOfScalar<T>::writeInGraph() const { 90 0 : std::size_t und = getName().find_last_of("_"); 91 0 : return getName().substr(0,und); 92 : } 93 : 94 : template <class T> 95 3 : std::string FunctionOfScalar<T>::getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const { 96 3 : if( getName().find("SORT")==std::string::npos ) { 97 0 : return ActionWithValue::getOutputComponentDescription( cname, keys ); 98 : } 99 6 : return "the " + cname + "th smallest of the input scalars"; 100 : } 101 : 102 : template <class T> 103 105630 : void FunctionOfScalar<T>::calculate() { 104 105630 : args.resize( getNumberOfArguments() - argstart ); 105 239309 : for(unsigned i=argstart; i<getNumberOfArguments(); ++i) { 106 133679 : args[i-argstart]=getPntrToArgument(i)->get(); 107 : } 108 : // functions only set the derivatives that are not zero, so the buffers are reset here 109 105630 : vals.assign( getNumberOfComponents(), 0.0 ); 110 105630 : deriv.assign( getNumberOfComponents()*args.size(), 0.0 ); 111 : auto funcout = FunctionOutput::create( getNumberOfComponents(), 112 : vals.data(), 113 : args.size(), 114 : deriv.data() ); 115 105630 : T::calc( myfunc, 116 105630 : doNotCalculateDerivatives(), 117 103902 : View<const double>(args.data(),args.size()), 118 : funcout ); 119 211297 : for(unsigned i=0; i<vals.size(); ++i) { 120 105667 : copyOutput(i)->set(vals[i]); 121 : } 122 105630 : if( doNotCalculateDerivatives() ) { 123 15770 : return; 124 : } 125 : unsigned dstart = 0; 126 91535 : for(unsigned i=0; i<argstart; ++i) { 127 1675 : dstart += getPntrToArgument(i)->getNumberOfStoredValues(); 128 : } 129 : 130 179750 : for(unsigned i=0; i<vals.size(); ++i) { 131 89890 : Value* val = getPntrToComponent(i); 132 199336 : for(unsigned j=0; j<args.size(); ++j) { 133 109446 : setDerivative( val, dstart+j, funcout.derivs[i][j] ); 134 : } 135 : } 136 : } 137 : 138 : 139 : 140 : /// Explicit specialization defined in the corresponding .cpp file; declared 141 : /// here so that every translation unit instantiating the template sees it. 142 : template <> std::string FunctionOfScalar<Custom>::writeInGraph() const; 143 : } 144 : } 145 : #endif