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