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 : #include <cstring> 31 : 32 : namespace PLMD { 33 : 34 : /** 35 : \ingroup MULTIINHERIT 36 : Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. 37 : This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function 38 : 39 : The vast majority of the PLMD::Action objects that are implemented in 40 : plumed calculate some quantity or a set of quantities. This could be 41 : the value of a CV, the value of a function or the potential due to a bias. 42 : PLMD::ActionWithValue provides the functionality for storing these quantities 43 : and (in tandem with PLMD::ActionWithArguments) the functionality for passing 44 : quantities between PLMD::Actions. When you are deciding what quantities 45 : your new PLMD::Action will need to store using PLMD::ActionWithValue you must 46 : ask yourself the following two questions: 47 : 48 : - Do I need to differentiate my output quantities 49 : - Is my PLMD::Action calculating a single thing or does the output have multiple components 50 : 51 : If the answer to the first of these questions is yes then you must setup your values 52 : you using either PLMD::ActionWithValue::addValueWithDerivatives() or 53 : PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you 54 : can set up values using PLMD::ActionWithValue::addValue() or PLMD::ActionWithValue::addComponent(). 55 : The precise routine you use to setup your values will depend on your answer to the 56 : second question. As you are probably aware if the output of your PLMD::Action is a 57 : single quantity you can reference that quantity in the input file using the label of the 58 : PLMD::Action it was calculated in. If your action <b> outputs only one quantity </b> 59 : we call that quantity the <b> value </b> of the Action. To set the <b> value </b> and get pointers to it 60 : you should <b> use the set of routines that have the word value in the name </b>. If, by contrast, 61 : your PLMD::Action calculates multiple quantities then these quantities are referenced in input using the 62 : label.component syntax. We refer to these <b> multiple quantities </b> the <b> components </b> 63 : of the PLMD::Action. Perhaps unsurprisingly, when you manipulate the <b> components </b> of an 64 : PLMD::Action you should use <b> the routines with the word component in the name. </b> 65 : */ 66 : 67 : class ActionWithValue : 68 : public virtual Action { 69 : friend class ActionWithVector; 70 : friend class ActionWithArguments; 71 : private: 72 : /// This finishes setup on first step to check if actions are calculated during update 73 : bool firststep; 74 : /// An array containing the values for this action 75 : std::vector<std::unique_ptr<Value>> values; 76 : /// A vector that is used to hold the forces that we will apply on the input quantities 77 : std::vector<double> forcesForApply; 78 : std::vector<unsigned> valsToForce; 79 : /// Are we skipping the calculation of the derivatives 80 : bool noderiv; 81 : /// Are we using numerical derivatives to differentiate 82 : bool numericalDerivatives; 83 : /// Return the index for the component named name 84 : int getComponent( const std::string& name ) const; 85 : public: 86 : 87 : // -------- The action has one value only ---------------- // 88 : 89 : /// Add a value with the name label 90 : void addValue( const std::vector<unsigned>& shape=std::vector<unsigned>() ); 91 : /// Add a value with the name label that has derivatives 92 : virtual void addValueWithDerivatives( const std::vector<unsigned>& shape=std::vector<unsigned>() ); 93 : /// Set your default value to have no periodicity 94 : void setNotPeriodic(); 95 : /// Set the value to be periodic with a particular domain 96 : void setPeriodic( const std::string& min, const std::string& max ); 97 : protected: 98 : /// Get a pointer to the default value 99 : Value* getPntrToValue(); 100 : /// Set the default value (the one without name) 101 : void setValue(const double& d); 102 : 103 : // -------- The action has multiple components ---------- // 104 : 105 : public: 106 : /// Add a value with a name like label.name 107 : void addComponent( const std::string& name, const std::vector<unsigned>& shape=std::vector<unsigned>() ); 108 : /// Add a value with a name like label.name that has derivatives 109 : virtual void addComponentWithDerivatives( const std::string& name, const std::vector<unsigned>& shape=std::vector<unsigned>() ); 110 : /// Set your value component to have no periodicity 111 : void componentIsNotPeriodic( const std::string& name ); 112 : /// Set the value to be periodic with a particular domain 113 : void componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ); 114 : /// Get the description of this component 115 : virtual std::string getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const ; 116 : protected: 117 : /// Return a pointer to the component by index 118 : Value* getPntrToComponent(int i); 119 : /// Get a const pointer to the ith component 120 : const Value* getConstPntrToComponent(int i) const; 121 : /// Return a pointer to the value by name 122 : Value* getPntrToComponent(const std::string& name); 123 : /// Accumulate the forces from the Values 124 : bool checkForForces(); 125 : /// Get the forces to apply 126 : const std::vector<double>& getForcesToApply() const; 127 : public: 128 : explicit ActionWithValue(const ActionOptions&ao); 129 : ~ActionWithValue(); 130 : 131 : /// Register all the relevant keywords for the action 132 : static void registerKeywords( Keywords& keys ); 133 : /// Insist that numerical derivatives should always be used for an action and make this fact appear in the manual 134 : static void noAnalyticalDerivatives(Keywords& keys); 135 : /// The components in the action will depend on the user 136 : static void useCustomisableComponents(Keywords& keys); 137 : /// Are we not calculating derivatives 138 : virtual bool doNotCalculateDerivatives() const ; 139 : /// Get the value of one of the components of the PLMD::Action 140 : double getOutputQuantity( const unsigned j ) const ; 141 : /// Get the value with a specific name (N.B. if there is no such value this returns zero) 142 : double getOutputQuantity( const std::string& name ) const ; 143 : 144 : // --- Routines for passing stuff to ActionWithArguments -- // 145 : 146 : /// Check if a value with a particular name is present. This is only used in PLMD::ActionWithArguments. 147 : /// You should not use it when manipulating components. 148 : bool exists( const std::string& name ) const; 149 : /// Return a pointer to the value with name (this is used to retrieve values in other PLMD::Actions) 150 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 151 : /// getPntrToComponent instead. 152 : Value* copyOutput( const std::string&name ) const; 153 : /// Return a pointer to the value with this number (this is used to retrieve values in other PLMD::Actions) 154 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 155 : /// getPntrToComponent instead. 156 : Value* copyOutput( const unsigned& n ) const; 157 : /// get a string that contains all the available components 158 : std::string getComponentsList( ) const ; 159 : /// get a vector that contains the label for all the components 160 : std::vector<std::string> getComponentsVector( ) const ; 161 : 162 : 163 : // -- Routines for everything else -- // 164 : 165 : /// Returns the number of values defined 166 : int getNumberOfComponents() const ; 167 : /// Clear the forces on the values 168 : virtual void clearInputForces( const bool& force=false ); 169 : /// Clear the derivatives of values wrt parameters 170 : virtual void clearDerivatives( const bool& force=false ); 171 : /// Calculate the gradients and store them for all the values (need for projections) 172 : virtual void setGradientsIfNeeded(); 173 : /// Set the value 174 : void setValue(Value*,double); 175 : /// Check if numerical derivatives should be used 176 : bool checkNumericalDerivatives() const override; 177 : /// This forces the class to use numerical derivatives 178 : void useNumericalDerivatives(); 179 : // These are things for using vectors of values as fields 180 0 : virtual void checkFieldsAllowed() { 181 0 : error("cannot use this action as a field"); 182 : } 183 : virtual unsigned getNumberOfDerivatives()=0; 184 : /// Activate the calculation of derivatives 185 : virtual void turnOnDerivatives(); 186 : /// Get the titles to use for the columns of the matrix 187 : virtual void getMatrixColumnTitles( std::vector<std::string>& argnames ) const ; 188 : /// This is used to check if we run calculate during the update step 189 : virtual bool calculateOnUpdate(); 190 4165103 : ActionWithValue* castToActionWithValue() noexcept final { 191 4165103 : return this; 192 : } 193 : }; 194 : 195 : inline 196 149394 : double ActionWithValue::getOutputQuantity(const unsigned j) const { 197 149394 : plumed_massert(j<values.size(),"index requested is out of bounds"); 198 149394 : return values[j]->get(); 199 : } 200 : 201 : inline 202 4717934 : double ActionWithValue::getOutputQuantity( const std::string& name ) const { 203 4717934 : auto offset=getLabel().size(); 204 10601300 : for(unsigned i=0; i<values.size(); ++i) { 205 : const std::string & valname=values[i]->name; 206 5993978 : if(valname.size()>offset+1 && valname[offset]=='.' ) { 207 : plumed_dbg_assert(Tools::startWith(valname,getLabel())); 208 2580170 : if(!std::strcmp(valname.c_str()+offset+1,name.c_str())) { 209 110612 : return values[i]->get(); 210 : } 211 : } 212 : } 213 : return 0.0; 214 : } 215 : 216 : inline 217 170926 : void ActionWithValue::setValue(const double& d) { 218 170926 : plumed_massert(values.size()==1, "cannot use setValue in multi-component actions"); 219 170926 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); 220 170926 : values[0]->set(d); 221 170926 : } 222 : 223 : inline 224 : int ActionWithValue::getNumberOfComponents() const { 225 1164268400 : return values.size(); 226 : } 227 : 228 : inline 229 : void ActionWithValue::useNumericalDerivatives() { 230 : plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" ); 231 : numericalDerivatives=true; 232 : } 233 : 234 : inline 235 2358698 : bool ActionWithValue::checkNumericalDerivatives() const { 236 2358698 : return numericalDerivatives; 237 : } 238 : 239 : inline 240 231904555 : bool ActionWithValue::doNotCalculateDerivatives() const { 241 231904555 : return noderiv; 242 : } 243 : 244 : inline 245 : const std::vector<double>& ActionWithValue::getForcesToApply() const { 246 293930 : return forcesForApply; 247 : } 248 : 249 : inline 250 : Value* ActionWithValue::getPntrToValue() { 251 : plumed_dbg_massert(values.size()==1,"The number of components is not equal to one"); 252 : plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default"); 253 : return values[0].get(); 254 : } 255 : 256 : } 257 : 258 : #endif