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