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_core_ActionWithValue_h 23 : #define __PLUMED_core_ActionWithValue_h 24 : 25 : #include "Action.h" 26 : #include "Value.h" 27 : #include "tools/Exception.h" 28 : #include <vector> 29 : #include <memory> 30 : 31 : namespace PLMD { 32 : 33 : /** 34 : \ingroup MULTIINHERIT 35 : Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. 36 : This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function 37 : 38 : The vast majority of the PLMD::Action objects that are implemented in 39 : plumed calculate some quantity or a set of quantities. This could be 40 : the value of a CV, the value of a function or the potential due to a bias. 41 : PLMD::ActionWithValue provides the functionality for storing these quantities 42 : and (in tandem with PLMD::ActionWithArguments) the functionality for passing 43 : quantities between PLMD::Actions. When you are deciding what quantities 44 : your new PLMD::Action will need to store using PLMD::ActionWithValue you must 45 : ask yourself the following two questions: 46 : 47 : - Do I need to differentiate my output quantities 48 : - Is my PLMD::Action calculating a single thing or does the output have multiple components 49 : 50 : If the answer to the first of these questions is yes then you must setup your values 51 : you using either PLMD::ActionWithValue::addValueWithDerivatives() or 52 : PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you 53 : can set up values using PLMD::ActionWithValue::addValue() or PLMD::ActionWithValue::addComponent(). 54 : The precise routine you use to setup your values will depend on your answer to the 55 : second question. As you are probably aware if the output of your PLMD::Action is a 56 : single quantity you can reference that quantity in the input file using the label of the 57 : PLMD::Action it was calculated in. If your action <b> outputs only one quantity </b> 58 : we call that quantity the <b> value </b> of the Action. To set the <b> value </b> and get pointers to it 59 : you should <b> use the set of routines that have the word value in the name </b>. If, by contrast, 60 : your PLMD::Action calculates multiple quantities then these quantities are referenced in input using the 61 : label.component syntax. We refer to these <b> multiple quantities </b> the <b> components </b> 62 : of the PLMD::Action. Perhaps unsurprisingly, when you manipulate the <b> components </b> of an 63 : PLMD::Action you should use <b> the routines with the word component in the name. </b> 64 : */ 65 : 66 : class ActionWithValue : 67 : public virtual Action 68 : { 69 : private: 70 : /// An array containing the values for this action 71 : std::vector<std::unique_ptr<Value>> values; 72 : /// Are we skipping the calculation of the derivatives 73 : bool noderiv; 74 : /// Are we using numerical derivatives to differentiate 75 : bool numericalDerivatives; 76 : /// Return the index for the component named name 77 : int getComponent( const std::string& name ) const; 78 : public: 79 : 80 : // -------- The action has one value only ---------------- // 81 : 82 : /// Add a value with the name label 83 : void addValue(); 84 : /// Add a value with the name label that has derivatives 85 : void addValueWithDerivatives(); 86 : /// Set your default value to have no periodicity 87 : void setNotPeriodic(); 88 : /// Set the value to be periodic with a particular domain 89 : void setPeriodic( const std::string& min, const std::string& max ); 90 : protected: 91 : /// Get a pointer to the default value 92 : Value* getPntrToValue(); 93 : /// Set the default value (the one without name) 94 : void setValue(const double& d); 95 : 96 : // -------- The action has multiple components ---------- // 97 : 98 : public: 99 : /// Add a value with a name like label.name 100 : void addComponent( const std::string& name ); 101 : /// Add a value with a name like label.name that has derivatives 102 : void addComponentWithDerivatives( const std::string& name ); 103 : /// Set your value component to have no periodicity 104 : void componentIsNotPeriodic( const std::string& name ); 105 : /// Set the value to be periodic with a particular domain 106 : void componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ); 107 : protected: 108 : /// Return a pointer to the component by index 109 : Value* getPntrToComponent(int i); 110 : /// Return a pointer to the value by name 111 : Value* getPntrToComponent(const std::string& name); 112 : public: 113 : explicit ActionWithValue(const ActionOptions&ao); 114 : ~ActionWithValue(); 115 : 116 : /// Register all the relevant keywords for the action 117 : static void registerKeywords( Keywords& keys ); 118 : /// Insist that numerical derivatives should always be used for an action and make this fact appear in the manual 119 : static void noAnalyticalDerivatives(Keywords& keys); 120 : /// Puts a message into the manual that the components always output 121 : static void componentsAreNotOptional(Keywords& keys); 122 : /// The components in the action will depend on the user 123 : static void useCustomisableComponents(Keywords& keys); 124 : /// Are we not calculating derivatives 125 : virtual bool doNotCalculateDerivatives() const ; 126 : /// Get the value of one of the components of the PLMD::Action 127 : double getOutputQuantity( const unsigned j ) const ; 128 : /// Get the value with a specific name (N.B. if there is no such value this returns zero) 129 : double getOutputQuantity( const std::string& name ) const ; 130 : 131 : // --- Routines for passing stuff to ActionWithArguments -- // 132 : 133 : /// Check if a value with a particular name is present. This is only used in PLMD::ActionWithArguments. 134 : /// You should not use it when manipulating components. 135 : bool exists( const std::string& name ) const; 136 : /// Return a pointer to the value with name (this is used to retrieve values in other PLMD::Actions) 137 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 138 : /// getPntrToComponent instead. 139 : Value* copyOutput( const std::string&name ) const; 140 : /// Return a pointer to the value with this number (this is used to retrieve values in other PLMD::Actions) 141 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 142 : /// getPntrToComponent instead. 143 : Value* copyOutput( const unsigned& n ) const; 144 : /// get a string that contains all the available components 145 : std::string getComponentsList( ) const ; 146 : /// get a vector that contains the label for all the components 147 : std::vector<std::string> getComponentsVector( ) const ; 148 : 149 : 150 : // -- Routines for everything else -- // 151 : 152 : /// Returns the number of values defined 153 : int getNumberOfComponents() const ; 154 : /// Clear the forces on the values 155 : void clearInputForces(); 156 : /// Clear the derivatives of values wrt parameters 157 : virtual void clearDerivatives(); 158 : /// Calculate the gradients and store them for all the values (need for projections) 159 : void setGradientsIfNeeded(); 160 : /// Set the value 161 : void setValue(Value*,double); 162 : /// Check if numerical derivatives should be used 163 : bool checkNumericalDerivatives() const override; 164 : /// This forces the class to use numerical derivatives 165 : void useNumericalDerivatives(); 166 : // These are things for using vectors of values as fields 167 0 : virtual void checkFieldsAllowed() { error("cannot use this action as a field"); } 168 : virtual unsigned getNumberOfDerivatives()=0; 169 : /// Activate the calculation of derivatives 170 : virtual void turnOnDerivatives(); 171 : }; 172 : 173 : inline 174 153914 : double ActionWithValue::getOutputQuantity(const unsigned j) const { 175 153914 : plumed_massert(j<values.size(),"index requested is out of bounds"); 176 153914 : return values[j]->get(); 177 : } 178 : 179 : inline 180 2780094 : double ActionWithValue::getOutputQuantity( const std::string& name ) const { 181 5560188 : std::string thename; thename=getLabel() + "." + name; 182 6467996 : for(unsigned i=0; i<values.size(); ++i) { 183 3775267 : if( values[i]->name==thename ) return values[i]->value; 184 : } 185 : return 0.0; 186 : } 187 : 188 : inline 189 194067 : void ActionWithValue::setValue(const double& d) { 190 194067 : plumed_massert(values.size()==1, "cannot use setValue in multi-component actions"); 191 194067 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); 192 194067 : values[0]->set(d); 193 194067 : } 194 : 195 : inline 196 : int ActionWithValue::getNumberOfComponents() const { 197 142216 : return values.size(); 198 : } 199 : 200 : inline 201 2 : void ActionWithValue::useNumericalDerivatives() { 202 4 : plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" ); 203 2 : numericalDerivatives=true; 204 2 : } 205 : 206 : inline 207 1633909 : bool ActionWithValue::checkNumericalDerivatives() const { 208 1633953 : return numericalDerivatives; 209 : } 210 : 211 : inline 212 5924 : bool ActionWithValue::doNotCalculateDerivatives() const { 213 68367370 : return noderiv; 214 : } 215 : 216 : 217 : 218 : } 219 : 220 : #endif