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 : { 70 : friend class ActionWithVector; 71 : friend class ActionWithArguments; 72 : private: 73 : /// This finishes setup on first step to check if actions are calculated during update 74 : bool firststep; 75 : /// An array containing the values for this action 76 : std::vector<std::unique_ptr<Value>> values; 77 : /// A vector that is used to hold the forces that we will apply on the input quantities 78 : std::vector<double> forcesForApply; 79 : std::vector<unsigned> valsToForce; 80 : /// Are we skipping the calculation of the derivatives 81 : bool noderiv; 82 : /// Are we using numerical derivatives to differentiate 83 : bool numericalDerivatives; 84 : /// Return the index for the component named name 85 : int getComponent( const std::string& name ) const; 86 : public: 87 : 88 : // -------- The action has one value only ---------------- // 89 : 90 : /// Add a value with the name label 91 : void addValue( const std::vector<unsigned>& shape=std::vector<unsigned>() ); 92 : /// Add a value with the name label that has derivatives 93 : virtual void addValueWithDerivatives( const std::vector<unsigned>& shape=std::vector<unsigned>() ); 94 : /// Set your default value to have no periodicity 95 : void setNotPeriodic(); 96 : /// Set the value to be periodic with a particular domain 97 : void setPeriodic( const std::string& min, const std::string& max ); 98 : protected: 99 : /// Get a pointer to the default value 100 : Value* getPntrToValue(); 101 : /// Set the default value (the one without name) 102 : void setValue(const double& d); 103 : 104 : // -------- The action has multiple components ---------- // 105 : 106 : public: 107 : /// Add a value with a name like label.name 108 : void addComponent( const std::string& name, const std::vector<unsigned>& shape=std::vector<unsigned>() ); 109 : /// Add a value with a name like label.name that has derivatives 110 : virtual void addComponentWithDerivatives( const std::string& name, const std::vector<unsigned>& shape=std::vector<unsigned>() ); 111 : /// Set your value component to have no periodicity 112 : void componentIsNotPeriodic( const std::string& name ); 113 : /// Set the value to be periodic with a particular domain 114 : void componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ); 115 : /// Get the description of this component 116 : virtual std::string getOutputComponentDescription( const std::string& cname, const Keywords& keys ) const ; 117 : protected: 118 : /// Return a pointer to the component by index 119 : Value* getPntrToComponent(int i); 120 : /// Get a const pointer to the ith component 121 : const Value* getConstPntrToComponent(int i) const; 122 : /// Return a pointer to the value by name 123 : Value* getPntrToComponent(const std::string& name); 124 : /// Accumulate the forces from the Values 125 : bool checkForForces(); 126 : /// Get the forces to apply 127 : const std::vector<double>& getForcesToApply() const; 128 : public: 129 : explicit ActionWithValue(const ActionOptions&ao); 130 : ~ActionWithValue(); 131 : 132 : /// Register all the relevant keywords for the action 133 : static void registerKeywords( Keywords& keys ); 134 : /// Insist that numerical derivatives should always be used for an action and make this fact appear in the manual 135 : static void noAnalyticalDerivatives(Keywords& keys); 136 : /// The components in the action will depend on the user 137 : static void useCustomisableComponents(Keywords& keys); 138 : /// Are we not calculating derivatives 139 : virtual bool doNotCalculateDerivatives() const ; 140 : /// Get the value of one of the components of the PLMD::Action 141 : double getOutputQuantity( const unsigned j ) const ; 142 : /// Get the value with a specific name (N.B. if there is no such value this returns zero) 143 : double getOutputQuantity( const std::string& name ) const ; 144 : 145 : // --- Routines for passing stuff to ActionWithArguments -- // 146 : 147 : /// Check if a value with a particular name is present. This is only used in PLMD::ActionWithArguments. 148 : /// You should not use it when manipulating components. 149 : bool exists( const std::string& name ) const; 150 : /// Return a pointer to the value with name (this is used to retrieve values in other PLMD::Actions) 151 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 152 : /// getPntrToComponent instead. 153 : Value* copyOutput( const std::string&name ) const; 154 : /// Return a pointer to the value with this number (this is used to retrieve values in other PLMD::Actions) 155 : /// You should NEVER use this routine to refer to the components of your PLMD::Action. Use 156 : /// getPntrToComponent instead. 157 : Value* copyOutput( const unsigned& n ) const; 158 : /// get a string that contains all the available components 159 : std::string getComponentsList( ) const ; 160 : /// get a vector that contains the label for all the components 161 : std::vector<std::string> getComponentsVector( ) const ; 162 : 163 : 164 : // -- Routines for everything else -- // 165 : 166 : /// Returns the number of values defined 167 : int getNumberOfComponents() const ; 168 : /// Clear the forces on the values 169 : virtual void clearInputForces( const bool& force=false ); 170 : /// Clear the derivatives of values wrt parameters 171 : virtual void clearDerivatives( const bool& force=false ); 172 : /// Calculate the gradients and store them for all the values (need for projections) 173 : virtual void setGradientsIfNeeded(); 174 : /// Set the value 175 : void setValue(Value*,double); 176 : /// Check if numerical derivatives should be used 177 : bool checkNumericalDerivatives() const override; 178 : /// This forces the class to use numerical derivatives 179 : void useNumericalDerivatives(); 180 : // These are things for using vectors of values as fields 181 0 : virtual void checkFieldsAllowed() { error("cannot use this action as a field"); } 182 : virtual unsigned getNumberOfDerivatives()=0; 183 : /// Activate the calculation of derivatives 184 : virtual void turnOnDerivatives(); 185 : /// Get the titles to use for the columns of the matrix 186 : virtual void getMatrixColumnTitles( std::vector<std::string>& argnames ) const ; 187 : /// This is used to check if we run calculate during the update step 188 : virtual bool calculateOnUpdate(); 189 4144415 : ActionWithValue* castToActionWithValue() noexcept final { return this; } 190 : }; 191 : 192 : inline 193 142134 : double ActionWithValue::getOutputQuantity(const unsigned j) const { 194 142134 : plumed_massert(j<values.size(),"index requested is out of bounds"); 195 142134 : return values[j]->get(); 196 : } 197 : 198 : inline 199 4679388 : double ActionWithValue::getOutputQuantity( const std::string& name ) const { 200 4679388 : auto offset=getLabel().size(); 201 10517714 : for(unsigned i=0; i<values.size(); ++i) { 202 : const std::string & valname=values[i]->name; 203 5946772 : if(valname.size()>offset+1 && valname[offset]=='.' ) { 204 : plumed_dbg_assert(Tools::startWith(valname,getLabel())); 205 2562488 : if(!std::strcmp(valname.c_str()+offset+1,name.c_str())) return values[i]->get(); 206 : } 207 : } 208 : return 0.0; 209 : } 210 : 211 : inline 212 168920 : void ActionWithValue::setValue(const double& d) { 213 168920 : plumed_massert(values.size()==1, "cannot use setValue in multi-component actions"); 214 168920 : plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); 215 168920 : values[0]->set(d); 216 168920 : } 217 : 218 : inline 219 : int ActionWithValue::getNumberOfComponents() const { 220 1145232335 : return values.size(); 221 : } 222 : 223 : inline 224 : void ActionWithValue::useNumericalDerivatives() { 225 : plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" ); 226 : numericalDerivatives=true; 227 : } 228 : 229 : inline 230 2339425 : bool ActionWithValue::checkNumericalDerivatives() const { 231 2339425 : return numericalDerivatives; 232 : } 233 : 234 : inline 235 229370842 : bool ActionWithValue::doNotCalculateDerivatives() const { 236 229370842 : return noderiv; 237 : } 238 : 239 : inline 240 : const std::vector<double>& ActionWithValue::getForcesToApply() const { 241 291884 : return forcesForApply; 242 : } 243 : 244 : inline 245 : Value* ActionWithValue::getPntrToValue() { 246 : plumed_dbg_massert(values.size()==1,"The number of components is not equal to one"); 247 : plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default"); 248 : return values[0].get(); 249 : } 250 : 251 : } 252 : 253 : #endif