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 5812 : Function::registerKeywords(keys); keys.use("ARG"); 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("the sum of all the input arguments"); 62 5810 : else if( keys.getDisplayName()=="MEAN" ) keys.setValueDescription("the mean of all the input arguments"); 63 5759 : } 64 : 65 : template <class T> 66 1442 : FunctionOfScalar<T>::FunctionOfScalar(const ActionOptions&ao): 67 : Action(ao), 68 : Function(ao), 69 1442 : firststep(true) 70 : { 71 1442 : myfunc.read( this ); 72 : // Get the names of the components 73 1437 : std::vector<std::string> components( keywords.getOutputComponents() ); 74 : // Create the values to hold the output 75 1394 : std::vector<std::string> str_ind( myfunc.getComponentsPerLabel() ); 76 2874 : for(unsigned i=0; i<components.size(); ++i) { 77 13 : if( str_ind.size()>0 ) { 78 26 : std::string compstr = components[i]; if( compstr==".#!value" ) compstr = ""; 79 40 : for(unsigned j=0; j<str_ind.size(); ++j) addComponentWithDerivatives( compstr + str_ind[j] ); 80 1424 : } else if( components[i]==".#!value" ) addValueWithDerivatives(); 81 2 : else if( components[i].find_first_of("_")!=std::string::npos ) { 82 2 : if( getNumberOfArguments()==1 ) addValueWithDerivatives(); 83 3 : else { for(unsigned j=0; j<getNumberOfArguments(); ++j) addComponentWithDerivatives( getPntrToArgument(j)->getName() + components[i] ); } 84 0 : } else addComponentWithDerivatives( components[i] ); 85 : } 86 : // Set the periodicities of the output components 87 1437 : myfunc.setPeriodicityForOutputs( this ); myfunc.setPrefactor( this, 1.0 ); 88 1450 : } 89 : 90 : template <class T> 91 3 : std::string FunctionOfScalar<T>::getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const { 92 3 : if( getName().find("SORT")==std::string::npos ) return ActionWithValue::getOutputComponentDescription( cname, keys ); 93 6 : return "the " + cname + "th largest of the input scalars"; 94 : } 95 : 96 : template <class T> 97 2188 : void FunctionOfScalar<T>::turnOnDerivatives() { 98 0 : if( !myfunc.derivativesImplemented() ) error("derivatives have not been implemended for " + getName() ); 99 2188 : ActionWithValue::turnOnDerivatives(); 100 2188 : } 101 : 102 : template <class T> 103 92866 : void FunctionOfScalar<T>::calculate() { 104 92866 : if( firststep ) { myfunc.setup( this ); firststep=false; } unsigned argstart = myfunc.getArgStart(); 105 210481 : std::vector<double> args( getNumberOfArguments() - argstart ); for(unsigned i=argstart; i<getNumberOfArguments(); ++i) args[i-argstart]=getPntrToArgument(i)->get(); 106 92866 : std::vector<double> vals( getNumberOfComponents() ); Matrix<double> derivatives( getNumberOfComponents(), args.size() ); 107 92866 : myfunc.calc( this, args, vals, derivatives ); 108 185769 : for(unsigned i=0; i<vals.size(); ++i) copyOutput(i)->set(vals[i]); 109 92866 : if( doNotCalculateDerivatives() ) return; 110 : 111 160600 : for(unsigned i=0; i<vals.size(); ++i) { 112 80315 : Value* val = getPntrToComponent(i); 113 176984 : for(unsigned j=0; j<args.size(); ++j) setDerivative( val, j, derivatives(i,j) ); 114 : } 115 : } 116 : 117 : } 118 : } 119 : #endif