1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2011-2021 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
checkFieldsAllowed()167   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
getOutputQuantity(const unsigned j)174 double ActionWithValue::getOutputQuantity(const unsigned j) const {
175   plumed_massert(j<values.size(),"index requested is out of bounds");
176   return values[j]->get();
177 }
178 
179 inline
getOutputQuantity(const std::string & name)180 double ActionWithValue::getOutputQuantity( const std::string& name ) const {
181   std::string thename; thename=getLabel() + "." + name;
182   for(unsigned i=0; i<values.size(); ++i) {
183     if( values[i]->name==thename ) return values[i]->value;
184   }
185   return 0.0;
186 }
187 
188 inline
setValue(const double & d)189 void ActionWithValue::setValue(const double& d) {
190   plumed_massert(values.size()==1, "cannot use setValue in multi-component actions");
191   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
192   values[0]->set(d);
193 }
194 
195 inline
getNumberOfComponents()196 int ActionWithValue::getNumberOfComponents() const {
197   return values.size();
198 }
199 
200 inline
useNumericalDerivatives()201 void ActionWithValue::useNumericalDerivatives() {
202   plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" );
203   numericalDerivatives=true;
204 }
205 
206 inline
checkNumericalDerivatives()207 bool ActionWithValue::checkNumericalDerivatives() const {
208   return numericalDerivatives;
209 }
210 
211 inline
doNotCalculateDerivatives()212 bool ActionWithValue::doNotCalculateDerivatives() const {
213   return noderiv;
214 }
215 
216 
217 
218 }
219 
220 #endif
221