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_Action_h
23 #define __PLUMED_core_Action_h
24 #include <vector>
25 #include <string>
26 #include <set>
27 #include "tools/Keywords.h"
28 #include "tools/Tools.h"
29 #include "tools/Log.h"
30
31 namespace PLMD {
32
33 class PDB;
34 class PlumedMain;
35 class Communicator;
36 class ActionWithValue;
37
38 /// This class is used to bring the relevant information to the Action constructor.
39 /// Only Action and ActionRegister class can access to its content, which is
40 /// kept private to other classes, and may change in the future.
41 class ActionOptions {
42 friend class Action;
43 friend class ActionRegister;
44 /// Reference to main PlumedMain object
45 PlumedMain& plumed;
46 /// Input line which sets up the action
47 std::vector<std::string> line;
48 /// The documentation for this action
49 const Keywords& keys;
50 static Keywords emptyKeys;
51 public:
52 /// Constructor
53 ActionOptions(PlumedMain&p,const std::vector<std::string>&);
54 ActionOptions(const ActionOptions&,const Keywords& keys);
55 };
56
57 /// Base class for all the input Actions.
58 /// The input Actions are more or less corresponding to the directives
59 /// in the plumed.dat file and are applied in order at each time-step.
60 class Action {
61 friend class ActionShortcut;
62
63 /// Name of the directive in the plumed.dat file.
64 const std::string name;
65
66 /// Label of the Action, as set with LABEL= in the plumed.dat file.
67 std::string label;
68
69 /// Directive line.
70 /// This line is progressively erased during Action construction
71 /// so as to check if all the present keywords are correct.
72 std::vector<std::string> line;
73
74 /// Update only after this time.
75 double update_from;
76
77 /// Update only until this time.
78 double update_until;
79
80 public:
81
82 /// Check if action should be updated.
83 bool checkUpdate()const;
84
85 public:
86 typedef std::vector<Action*> Dependencies;
87
88 private:
89 /// Actions on which this Action depends.
90 Dependencies after;
91
92 /// Switch to activate Action on this step.
93 bool active;
94
95 /// Option that you might have enabled
96 std::set<std::string> options;
97
98 bool restart;
99
100 bool doCheckPoint;
101
102 public:
103
104 /// Reference to main plumed object
105 PlumedMain& plumed;
106
107 /// Reference to the log stream
108 Log& log;
109
110 /// Specify that this Action depends on another one
111 void addDependency(Action*);
112
113 /// Clear the dependence list for this Action
114 void clearDependencies();
115
116 /// Return the present timestep
117 long int getStep()const;
118
119 /// Return the present time
120 double getTime()const;
121
122 /// Return the timestep
123 double getTimeStep()const;
124
125 /// Return true if we are doing a restart
126 bool getRestart()const;
127
128 /// Return true if we are doing at a checkpoint step
129 bool getCPT()const;
130
131 /// Just read one of the keywords and return the whole thing as a string
132 std::string getKeyword(const std::string& key);
133
134 /// Parse one keyword as generic type
135 template<class T>
136 void parse(const std::string&key,T&t);
137
138 /// Parse one numbered keyword as generic type
139 template<class T>
140 bool parseNumbered(const std::string&key, const int no, T&t);
141
142 /// Parse one keyword as std::vector
143 template<class T>
144 void parseVector(const std::string&key,std::vector<T>&t);
145
146 /// Parse a vector with a number
147 template<class T>
148 bool parseNumberedVector(const std::string& key, const int no, std::vector<T>&t);
149
150 /// Parse one keyword as boolean flag
151 void parseFlag(const std::string&key,bool&t);
152
153 /// Crash calculation and print documentation
154 void error( const std::string & msg ) const;
155
156 /// Issue a warning
157 void warning( const std::string & msg );
158
159 /// Exit with error code c
160 void exit(int c=0);
161
162 ///
163 std::set<FILE*> files;
164
165 public:
166 /// Standard constructor from ActionOptions
167 explicit Action(const ActionOptions&);
168 /// Destructor
169 virtual ~Action();
170 private:
171 /// Copy constructor is deleted
172 Action(const Action&a) = delete;
173 /// Assignment operator is deleted
174 Action& operator=(const Action&a) = delete;
175 int replica_index;
176 public:
177 /// Check if Action was properly read.
178 /// This checks if Action::line is empty. It must be called after
179 /// a final Action has been initialized
180 void checkRead();
181
182 Communicator& comm;
183 Communicator& multi_sim_comm;
184
185 const Keywords& keywords;
186 /// Prepare an Action for calculation
187 /// This can be used by Action if they need some special preparation
188 /// before calculation. Typical case is for collective variables
189 /// which would like to change their list of requested atoms.
190 /// By default (if not overridden) does nothing.
191 virtual void prepare();
192
193 /// Register all the relevant keywords for the action
194 static void registerKeywords( Keywords& keys );
195
lockRequests()196 virtual void lockRequests() {}
unlockRequests()197 virtual void unlockRequests() {}
198
199 /// Calculate an Action.
200 /// This method is called one or more times per step.
201 /// The set of all Actions is calculated in forward order.
202 virtual void calculate()=0;
203
204 /// Apply an Action.
205 /// This method is called one time per step.
206 /// The set of all Actions is applied in backward order.
207 virtual void apply()=0;
208
209 /// Before Update.
210 /// This is a special method that is called just
211 /// before the update() method. It can be used by
212 /// actions that want to do something irrespectively
213 /// of the fact that update() is active or not.
214 /// In other words, this is *always* called, even when action
215 /// is not active.
beforeUpdate()216 virtual void beforeUpdate() {}
217
218 /// Update.
219 /// This method is called one time per step.
220 /// The set of all Actions is updated in forward order.
update()221 virtual void update() {}
222
223 /// RunFinalJobs
224 /// This method is called once at the very end of the calculation.
225 /// The set of all Actions in run for the final time in forward order.
runFinalJobs()226 virtual void runFinalJobs() {}
227
228 /// Tell to the Action to flush open files
229 void fflush();
230
231 virtual std::string getDocumentation()const;
232
233 /// Returns the label
234 const std::string & getLabel()const;
235
236 /// Returns the name
237 const std::string & getName()const;
238
239 /// Set action to active
240 virtual void activate();
241
242 ///
243 virtual void setOption(const std::string &s);
244
245 virtual void clearOptions();
246
247 /// Set action to inactive
248 virtual void deactivate();
249
250 /// Check if action is active
251 bool isActive()const;
252
253 /// Check if an option is on
254 bool isOptionOn(const std::string &s)const;
255
256 /// Return dependencies
getDependencies()257 const Dependencies & getDependencies()const {return after;}
258
259 /// Check if numerical derivatives should be performed
checkNumericalDerivatives()260 virtual bool checkNumericalDerivatives()const {return false;}
261
262 /// Check if the action needs gradient
checkNeedsGradients()263 virtual bool checkNeedsGradients()const {return false;}
264
265 /// Perform calculation using numerical derivatives
266 /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
267 /// are doing.
268 virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
269
270 /// Opens a file.
271 /// This is similar to plain fopen, but with some extra functionality.
272 /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
273 /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
274 FILE *fopen(const char *path, const char *mode);
275 /// Closes a file opened with Action::fclose().
276 int fclose(FILE*fp);
277
278 /// Calculate the action given a pdb file as input. This is used to initialize
279 /// things like distance from a point in CV map space given a pdb as an input file
280 void calculateFromPDB( const PDB& );
281 /// This is overwritten in ActionAtomistic so that we can read
282 /// the atoms from the pdb input file rather than taking them from the
283 /// MD code
readAtomsFromPDB(const PDB &)284 virtual void readAtomsFromPDB( const PDB& ) {}
285 /// Check if we are on an exchange step
286 bool getExchangeStep()const;
287
288 /// Cite a paper see PlumedMain::cite
289 std::string cite(const std::string&s);
290 };
291
292 /////////////////////
293 // FAST INLINE METHODS
294
295 inline
getLabel()296 const std::string & Action::getLabel()const {
297 return label;
298 }
299
300 inline
getName()301 const std::string & Action::getName()const {
302 return name;
303 }
304
305 template<class T>
parse(const std::string & key,T & t)306 void Action::parse(const std::string&key,T&t) {
307 // if(!Tools::parse(line,key,t)){
308 // log.printf("ERROR parsing keyword %s\n",key.c_str());
309 // log.printf("%s\n",getDocumentation().c_str());
310 // this->exit(1);
311 // }
312 // Check keyword has been registered
313 plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
314
315 // Now try to read the keyword
316 std::string def;
317 bool present=Tools::findKeyword(line,key);
318 bool found=Tools::parse(line,key,t,replica_index);
319 if(present && !found) error("keyword " + key +" could not be read correctly");
320
321 // If it isn't read and it is compulsory see if a default value was specified
322 if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
323 if( keywords.getDefaultValue(key,def) ) {
324 if( def.length()==0 || !Tools::convert(def,t) ) {
325 log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() );
326 this->exit(1);
327 }
328 } else if( keywords.style(key,"compulsory") ) {
329 error("keyword " + key + " is compulsory for this action");
330 }
331 }
332 }
333
334 template<class T>
parseNumbered(const std::string & key,const int no,T & t)335 bool Action::parseNumbered(const std::string&key, const int no, T&t) {
336 // Check keyword has been registered
337 plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
338 if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
339
340 // Now try to read the keyword
341 std::string num; Tools::convert(no,num);
342 return Tools::parse(line,key+num,t,replica_index);
343 }
344
345 template<class T>
parseVector(const std::string & key,std::vector<T> & t)346 void Action::parseVector(const std::string&key,std::vector<T>&t) {
347 // if(!Tools::parseVector(line,key,t)){
348 // log.printf("ERROR parsing keyword %s\n",key.c_str());
349 // log.printf("%s\n",getDocumentation().c_str());
350 // this->exit(1);
351 // }
352
353 // Check keyword has been registered
354 plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
355 unsigned size=t.size(); bool skipcheck=false;
356 if(size==0) skipcheck=true;
357
358 // Now try to read the keyword
359 std::string def; T val;
360 bool present=Tools::findKeyword(line,key);
361 bool found=Tools::parseVector(line,key,t,replica_index);
362 if(present && !found) error("keyword " + key +" could not be read correctly");
363
364 // Check vectors size is correct (not if this is atoms or ARG)
365 if( !keywords.style(key,"atoms") && found ) {
366 // bool skipcheck=false;
367 // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
368 if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
369 }
370
371 // If it isn't read and it is compulsory see if a default value was specified
372 if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
373 if( keywords.getDefaultValue(key,def) ) {
374 if( def.length()==0 || !Tools::convert(def,val) ) {
375 log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() );
376 this->exit(1);
377 } else {
378 if(t.size()>0) for(unsigned i=0; i<t.size(); ++i) t[i]=val;
379 else t.push_back(val);
380 }
381 } else if( keywords.style(key,"compulsory") ) {
382 error("keyword " + key + " is compulsory for this action");
383 }
384 } else if ( !found ) {
385 t.resize(0);
386 }
387 }
388
389 template<class T>
parseNumberedVector(const std::string & key,const int no,std::vector<T> & t)390 bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
391 plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
392 if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
393
394 unsigned size=t.size(); bool skipcheck=false;
395 if(size==0) skipcheck=true;
396 std::string num; Tools::convert(no,num);
397 bool present=Tools::findKeyword(line,key);
398 bool found=Tools::parseVector(line,key+num,t,replica_index);
399 if(present && !found) error("keyword " + key +" could not be read correctly");
400
401 if( keywords.style(key,"compulsory") ) {
402 if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size");
403 } else if ( !found ) {
404 t.resize(0);
405 }
406 return found;
407 }
408
409 inline
deactivate()410 void Action::deactivate() {
411 options.clear();
412 active=false;
413 }
414
415 inline
isActive()416 bool Action::isActive()const {
417 return active;
418 }
419
420 inline
isOptionOn(const std::string & s)421 bool Action::isOptionOn(const std::string &s)const {
422 return options.count(s);
423 }
424
425 inline
getRestart()426 bool Action::getRestart()const {
427 return restart;
428 }
429
430 }
431 #endif
432
433