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 "tools/Matrix.h" 27 : 28 : namespace PLMD { 29 : namespace function { 30 : 31 : /** 32 : \ingroup INHERIT 33 : This is the abstract base class to use for implementing new CV function, within it there is 34 : \ref AddingAFunction "information" as to how to go about implementing a new function. 35 : */ 36 : 37 : template <class T> 38 : class FunctionOfScalar : public Function { 39 : private: 40 : /// The function that is being computed 41 : T myfunc; 42 : /// Are we on the first step 43 : bool firststep; 44 : public: 45 : explicit FunctionOfScalar(const ActionOptions&); 46 2874 : virtual ~FunctionOfScalar() {} 47 : /// Get the label to write in the graph 48 3 : std::string writeInGraph() const override { return myfunc.getGraphInfo( getName() ); } 49 : std::string getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const override ; 50 : void calculate() override; 51 : static void registerKeywords(Keywords&); 52 : void turnOnDerivatives() override; 53 : }; 54 : 55 : template <class T> 56 2906 : void FunctionOfScalar<T>::registerKeywords(Keywords& keys) { 57 2906 : Function::registerKeywords(keys); std::string name = keys.getDisplayName(); 58 2906 : std::size_t und=name.find("_SCALAR"); keys.setDisplayName( name.substr(0,und) ); 59 5812 : keys.add("hidden","NO_ACTION_LOG","suppresses printing from action on the log"); 60 2906 : T tfunc; tfunc.registerKeywords( keys ); 61 5814 : if( keys.getDisplayName()=="SUM" ) keys.setValueDescription("scalar","the sum of all the input arguments"); 62 5810 : else if( keys.getDisplayName()=="MEAN" ) keys.setValueDescription("scalar","the mean of all the input arguments"); 63 5808 : else if( keys.getDisplayName()=="EVALUATE_FUNCTION_FROM_GRID" ) keys.addInputKeyword("compulsory","ARG","scalar/grid",""); 64 5759 : } 65 : 66 : template <class T> 67 1442 : FunctionOfScalar<T>::FunctionOfScalar(const ActionOptions&ao): 68 : Action(ao), 69 : Function(ao), 70 1442 : firststep(true) 71 : { 72 1442 : myfunc.read( this ); 73 : // Get the names of the components 74 1437 : std::vector<std::string> components( keywords.getOutputComponents() ); 75 : // Create the values to hold the output 76 1394 : std::vector<std::string> str_ind( myfunc.getComponentsPerLabel() ); 77 2874 : for(unsigned i=0; i<components.size(); ++i) { 78 13 : if( str_ind.size()>0 ) { 79 26 : std::string compstr = components[i]; if( compstr==".#!value" ) compstr = ""; 80 40 : for(unsigned j=0; j<str_ind.size(); ++j) addComponentWithDerivatives( compstr + str_ind[j] ); 81 1424 : } else if( components[i]==".#!value" ) addValueWithDerivatives(); 82 2 : else if( components[i].find_first_of("_")!=std::string::npos ) { 83 2 : if( getNumberOfArguments()==1 ) addValueWithDerivatives(); 84 3 : else { for(unsigned j=0; j<getNumberOfArguments(); ++j) addComponentWithDerivatives( getPntrToArgument(j)->getName() + components[i] ); } 85 0 : } else addComponentWithDerivatives( components[i] ); 86 : } 87 : // Set the periodicities of the output components 88 1437 : myfunc.setPeriodicityForOutputs( this ); myfunc.setPrefactor( this, 1.0 ); 89 1450 : } 90 : 91 : template <class T> 92 3 : std::string FunctionOfScalar<T>::getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const { 93 3 : if( getName().find("SORT")==std::string::npos ) return ActionWithValue::getOutputComponentDescription( cname, keys ); 94 6 : return "the " + cname + "th largest of the input scalars"; 95 : } 96 : 97 : template <class T> 98 2188 : void FunctionOfScalar<T>::turnOnDerivatives() { 99 0 : if( !myfunc.derivativesImplemented() ) error("derivatives have not been implemended for " + getName() ); 100 2188 : ActionWithValue::turnOnDerivatives(); 101 2188 : } 102 : 103 : template <class T> 104 92866 : void FunctionOfScalar<T>::calculate() { 105 92866 : if( firststep ) { myfunc.setup( this ); firststep=false; } unsigned argstart = myfunc.getArgStart(); 106 210481 : std::vector<double> args( getNumberOfArguments() - argstart ); for(unsigned i=argstart; i<getNumberOfArguments(); ++i) args[i-argstart]=getPntrToArgument(i)->get(); 107 92866 : std::vector<double> vals( getNumberOfComponents() ); Matrix<double> derivatives( getNumberOfComponents(), args.size() ); 108 92866 : myfunc.calc( this, args, vals, derivatives ); 109 185769 : for(unsigned i=0; i<vals.size(); ++i) copyOutput(i)->set(vals[i]); 110 92866 : if( doNotCalculateDerivatives() ) return; 111 : 112 160600 : for(unsigned i=0; i<vals.size(); ++i) { 113 80315 : Value* val = getPntrToComponent(i); 114 176984 : for(unsigned j=0; j<args.size(); ++j) setDerivative( val, j, derivatives(i,j) ); 115 : } 116 : } 117 : 118 : } 119 : } 120 : #endif