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 132068 : 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 66033 : }
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 of this replica: all the MPI processes running this PLUMED
224 : /// instance (set by the MD code with setMPIComm). It is valid on every process.
225 : Communicator& comm;
226 :
227 : /// Communicator between replicas, in multiple-replica simulations.
228 : /// It holds one process per replica, namely process 0 of comm (set with
229 : /// GREX setMPIIntercomm or setMPImultiSimComm).
230 : /// It is valid only on process 0 of comm. On the other processes it is
231 : /// MPI_COMM_SELF, so Get_size() returns 1 and Get_rank() returns 0 whatever
232 : /// the number of replicas, and communication over it reaches no other replica.
233 : /// Code that needs the number of replicas or the replica index on every
234 : /// process must read them on process 0 of comm and broadcast them over comm:
235 : /// \code
236 : /// unsigned nrep=0, irep=0;
237 : /// if(comm.Get_rank()==0) {
238 : /// nrep=multi_sim_comm.Get_size();
239 : /// irep=multi_sim_comm.Get_rank();
240 : /// }
241 : /// comm.Bcast(nrep,0);
242 : /// comm.Bcast(irep,0);
243 : /// \endcode
244 : /// The same applies to communication over multi_sim_comm: do it on process 0
245 : /// of comm, then broadcast the result over comm.
246 : /// For how MD codes set up these communicators, see \ref mpireplicas.
247 : Communicator& multi_sim_comm;
248 :
249 : /// Number of replicas in a multi-replica simulation (1 otherwise), and the index
250 : /// of this replica. Prefer these to multi_sim_comm.Get_size() and Get_rank(), which
251 : /// are only correct on the rank that received the inter-replica communicator: with
252 : /// several ranks per replica, the others see a single replica. These are computed
253 : /// once at initialization, so they are correct on every rank and need no
254 : /// communication, which makes them safe to call anywhere, including calculate().
255 : /// multi_sim_comm is still the communicator to use for exchanging data, and only on
256 : /// the rank that holds it.
257 : int getNumberOfReplicas() const;
258 : int getReplicaIndex() const;
259 :
260 : const Keywords& keywords;
261 : /// Prepare an Action for calculation
262 : /// This can be used by Action if they need some special preparation
263 : /// before calculation. Typical case is for collective variables
264 : /// which would like to change their list of requested atoms.
265 : /// By default (if not overridden) does nothing.
266 : virtual void prepare();
267 :
268 : /// Register all the relevant keywords for the action
269 : static void registerKeywords( Keywords& keys );
270 :
271 2152834 : virtual void lockRequests() {}
272 2152834 : virtual void unlockRequests() {}
273 :
274 : /// Calculate an Action.
275 : /// This method is called one or more times per step.
276 : /// The set of all Actions is calculated in forward order.
277 : virtual void calculate()=0;
278 :
279 : /// Apply an Action.
280 : /// This method is called one time per step.
281 : /// The set of all Actions is applied in backward order.
282 : virtual void apply()=0;
283 :
284 : /// Before Update.
285 : /// This is a special method that is called just
286 : /// before the update() method. It can be used by
287 : /// actions that want to do something irrespectively
288 : /// of the fact that update() is active or not.
289 : /// In other words, this is *always* called, even when action
290 : /// is not active.
291 5397106 : virtual void beforeUpdate() {}
292 :
293 : /// Update.
294 : /// This method is called one time per step.
295 : /// The set of all Actions is updated in forward order.
296 2144965 : virtual void update() {}
297 :
298 : /// RunFinalJobs
299 : /// This method is called once at the very end of the calculation.
300 : /// The set of all Actions in run for the final time in forward order.
301 50283 : virtual void runFinalJobs() {}
302 :
303 : /// Tell to the Action to flush open files
304 : void fflush();
305 :
306 : /// Returns the label
307 : const std::string & getLabel()const;
308 :
309 : /// Returns the name
310 : const std::string & getName()const;
311 :
312 : /// Set action to active
313 : virtual void activate();
314 :
315 : ///
316 : virtual void setOption(const std::string &s);
317 :
318 : virtual void clearOptions();
319 :
320 : /// Set action to inactive
321 : virtual void deactivate();
322 :
323 : /// Check if action is active
324 : bool isActive()const;
325 :
326 : /// Check if an option is on
327 : bool isOptionOn(const std::string &s)const;
328 :
329 : /// Return dependencies
330 : const Dependencies & getDependencies()const {
331 : return after;
332 : }
333 :
334 : /// Check if numerical derivatives should be performed
335 333456 : virtual bool checkNumericalDerivatives()const {
336 333456 : return false;
337 : }
338 :
339 : /// Check if the action needs gradient
340 3637084 : virtual bool checkNeedsGradients()const {
341 3637084 : return false;
342 : }
343 :
344 : /// Perform calculation using numerical derivatives
345 : /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
346 : /// are doing.
347 : virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
348 :
349 : /// Opens a file.
350 : /// This is similar to plain fopen, but with some extra functionality.
351 : /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
352 : /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
353 : FILE *fopen(const char *path, const char *mode);
354 : /// Closes a file opened with Action::fclose().
355 : int fclose(FILE*fp);
356 :
357 : /// Calculate the action given a pdb file as input. This is used to initialize
358 : /// things like distance from a point in CV map space given a pdb as an input file
359 : void calculateFromPDB( const PDB& );
360 : /// This is overwritten in ActionAtomistic so that we can read
361 : /// the atoms from the pdb input file rather than taking them from the
362 : /// MD code
363 0 : virtual void readAtomsFromPDB( const PDB& ) {}
364 : /// Check if we are on an exchange step
365 : bool getExchangeStep()const;
366 :
367 : /// Cite a paper see PlumedMain::cite
368 : std::string cite(const std::string&s);
369 :
370 : /// Get the defaults
371 : std::string getDefaultString() const ;
372 :
373 : /// Set the timestep that is stored in the action to the correct value
374 : void resetStoredTimestep();
375 :
376 : /// Get the info on what to calculate
377 : virtual std::string writeInGraph() const ;
378 : /// Specialized casts, to make PlumedMain run faster
379 346540 : virtual ActionWithValue* castToActionWithValue() noexcept {
380 346540 : return nullptr;
381 : }
382 92874 : virtual ActionWithArguments* castToActionWithArguments() noexcept {
383 92874 : return nullptr;
384 : }
385 3108135 : virtual ActionAtomistic* castToActionAtomistic() noexcept {
386 3108135 : return nullptr;
387 : }
388 3677991 : virtual ActionWithVirtualAtom* castToActionWithVirtualAtom() noexcept {
389 3677991 : return nullptr;
390 : }
391 0 : virtual PbcAction* castToPbcAction() noexcept {
392 0 : return nullptr;
393 : }
394 27281 : virtual ActionToPutData* castToActionToPutData() noexcept {
395 27281 : return nullptr;
396 : }
397 0 : virtual ActionToGetData* castToActionToGetData() noexcept {
398 0 : return nullptr;
399 : }
400 11392 : virtual DomainDecomposition* castToDomainDecomposition() noexcept {
401 11392 : return nullptr;
402 : }
403 666 : virtual ActionForInterface* castToActionForInterface() noexcept {
404 666 : return nullptr;
405 : }
406 98 : virtual ActionShortcut* castToActionShortcut() noexcept {
407 98 : return nullptr;
408 : }
409 : };
410 :
411 : /////////////////////
412 : // FAST INLINE METHODS
413 :
414 : inline
415 : const std::string & Action::getLabel()const {
416 48435180 : return actionLabel;
417 : }
418 :
419 : inline
420 : const std::string & Action::getName()const {
421 1135555 : return actionName;
422 : }
423 :
424 : template<class T>
425 193202 : void Action::parse(const std::string&key,T&t) {
426 : // Check keyword has been registered
427 193202 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
428 :
429 : // Now try to read the keyword
430 193202 : auto [present, found] = linemap.readAndRemove(key,t,replica_index);
431 :
432 193202 : if(present && !found) {
433 6 : error("keyword " + key +" could not be read correctly");
434 : }
435 :
436 : // If it isn't read and it is compulsory see if a default value was specified
437 330847 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
438 : std::string def;
439 32154 : if( keywords.getDefaultValue(key,def) ) {
440 24190 : if( def.length()==0 || !Tools::convertNoexcept(def,t) ) {
441 0 : plumed_error() <<"ERROR in action "<<actionName<<" with label "<<actionLabel<<" : keyword "<<key<<" has weird default value";
442 24190 : } else if( def.find(" ")!=std::string::npos ) {
443 48 : def = "{" + def + "}";
444 : }
445 72570 : defaults += " " + key + "=" + def;
446 15928 : } else if( keywords.style(key,"compulsory") ) {
447 0 : error("keyword " + key + " is compulsory for this action");
448 : }
449 : }
450 193199 : }
451 :
452 : template<class T>
453 69639 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
454 : // Check keyword has been registered
455 69639 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
456 69639 : if( !keywords.numbered(key) ) {
457 0 : error("numbered keywords are not allowed for " + key );
458 : }
459 :
460 : // Now try to read the keyword
461 : std::string num;
462 69639 : Tools::convert(no,num);
463 69639 : auto [present, found] = linemap.readAndRemove(key+num,t,replica_index);
464 69639 : return found;
465 : }
466 :
467 : template<class T>
468 109172 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
469 : // Check keyword has been registered
470 109172 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
471 109172 : unsigned size=t.size();
472 : bool skipcheck=false;
473 109172 : if(size==0) {
474 : skipcheck=true;
475 : }
476 : // Now try to read the keyword
477 109172 : auto [present, found] = linemap.readAndRemoveVector(key,t,replica_index);
478 109172 : if(present && !found) {
479 0 : error("keyword " + key +" could not be read correctly");
480 : }
481 :
482 : // Check vectors size is correct (not if this is atoms or ARG)
483 218344 : if( !keywords.style(key,"atoms") && found ) {
484 69076 : if( !skipcheck && t.size()!=size ) {
485 6 : error("vector read in for keyword " + key + " has the wrong size");
486 : }
487 : }
488 :
489 : // If it isn't read and it is compulsory see if a default value was specified
490 151255 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
491 : T val;
492 : std::string def;
493 6165 : if( keywords.getDefaultValue(key,def) ) {
494 6014 : if( def.length()==0 || !Tools::convertNoexcept(def,val) ) {
495 0 : plumed_error() <<"ERROR in action "<<actionName<<" with label "<<actionLabel<<" : keyword "<<key<<" has weird default value";
496 : } else {
497 6014 : if(t.size()>0) {
498 9788 : for(unsigned i=0; i<t.size(); ++i) {
499 4213 : t[i]=val;
500 : }
501 6018 : defaults += " " + key + "=" + def;
502 6779 : for(unsigned i=1; i<t.size(); ++i) {
503 7540 : defaults += "," + def;
504 : }
505 : } else {
506 3005 : t.push_back(val);
507 9015 : defaults += " " + key + "=" + def;
508 : }
509 : }
510 302 : } else if( keywords.style(key,"compulsory") ) {
511 0 : error("keyword " + key + " is compulsory for this action");
512 : }
513 103004 : } else if ( !found ) {
514 17885 : t.resize(0);
515 : }
516 109169 : }
517 :
518 : template<class T>
519 437083 : bool Action::parseNumberedVector(const std::string&key,
520 : const int no,
521 : std::vector<T>&t) {
522 437083 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
523 437083 : if( !keywords.numbered(key) ) {
524 0 : error("numbered keywords are not allowed for " + key );
525 : }
526 :
527 437083 : unsigned size=t.size();
528 : bool skipcheck=size==0;
529 : std::string num;
530 437083 : Tools::convert(no,num);
531 437083 : auto [present, found] = linemap.readAndRemoveVector(key+num,t,replica_index);
532 437083 : if(present && !found) {
533 0 : error("keyword " + key +" could not be read correctly");
534 : }
535 :
536 874166 : if( keywords.style(key,"compulsory") ) {
537 138 : if (!skipcheck && found && t.size()!=size ) {
538 0 : error("vector read in for keyword " + key + num + " has the wrong size");
539 : }
540 436945 : } else if ( !found ) {
541 2133 : t.resize(0);
542 : }
543 437083 : return found;
544 : }
545 :
546 : inline
547 5778282 : void Action::deactivate() {
548 : actionOptions.clear();
549 5778282 : active=false;
550 5778282 : }
551 :
552 : inline
553 : bool Action::isActive()const {
554 25920271 : return active;
555 : }
556 :
557 : inline
558 2183188 : bool Action::isOptionOn(const std::string &s)const {
559 2183188 : return actionOptions.count(s);
560 : }
561 :
562 : inline
563 : bool Action::getRestart()const {
564 6320 : return restart;
565 : }
566 :
567 : inline
568 : std::string Action::getDefaultString() const {
569 32 : return defaults;
570 : }
571 :
572 : }
573 : #endif
574 :
|