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