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 101956 : 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 50977 : }
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 1481788 : virtual void lockRequests() {}
237 1481788 : 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 4136353 : 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 1298373 : 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 46014 : 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 {
296 : return after;
297 : }
298 :
299 : /// Check if numerical derivatives should be performed
300 283700 : virtual bool checkNumericalDerivatives()const {
301 283700 : return false;
302 : }
303 :
304 : /// Check if the action needs gradient
305 2639630 : virtual bool checkNeedsGradients()const {
306 2639630 : return false;
307 : }
308 :
309 : /// Perform calculation using numerical derivatives
310 : /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
311 : /// are doing.
312 : virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
313 :
314 : /// Opens a file.
315 : /// This is similar to plain fopen, but with some extra functionality.
316 : /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
317 : /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
318 : FILE *fopen(const char *path, const char *mode);
319 : /// Closes a file opened with Action::fclose().
320 : int fclose(FILE*fp);
321 :
322 : /// Calculate the action given a pdb file as input. This is used to initialize
323 : /// things like distance from a point in CV map space given a pdb as an input file
324 : void calculateFromPDB( const PDB& );
325 : /// This is overwritten in ActionAtomistic so that we can read
326 : /// the atoms from the pdb input file rather than taking them from the
327 : /// MD code
328 0 : virtual void readAtomsFromPDB( const PDB& ) {}
329 : /// Check if we are on an exchange step
330 : bool getExchangeStep()const;
331 :
332 : /// Cite a paper see PlumedMain::cite
333 : std::string cite(const std::string&s);
334 :
335 : /// Get the defaults
336 : std::string getDefaultString() const ;
337 :
338 : /// Set the timestep that is stored in the action to the correct value
339 : void resetStoredTimestep();
340 :
341 : /// Get the info on what to calculate
342 : virtual std::string writeInGraph() const ;
343 : /// Specialized casts, to make PlumedMain run faster
344 295188 : virtual ActionWithValue* castToActionWithValue() noexcept {
345 295188 : return nullptr;
346 : }
347 73685 : virtual ActionWithArguments* castToActionWithArguments() noexcept {
348 73685 : return nullptr;
349 : }
350 2176585 : virtual ActionAtomistic* castToActionAtomistic() noexcept {
351 2176585 : return nullptr;
352 : }
353 3415945 : virtual ActionWithVirtualAtom* castToActionWithVirtualAtom() noexcept {
354 3415945 : return nullptr;
355 : }
356 0 : virtual PbcAction* castToPbcAction() noexcept {
357 0 : return nullptr;
358 : }
359 7346910 : virtual ActionToPutData* castToActionToPutData() noexcept {
360 7346910 : return nullptr;
361 : }
362 0 : virtual ActionToGetData* castToActionToGetData() noexcept {
363 0 : return nullptr;
364 : }
365 7908 : virtual DomainDecomposition* castToDomainDecomposition() noexcept {
366 7908 : return nullptr;
367 : }
368 624 : virtual ActionForInterface* castToActionForInterface() noexcept {
369 624 : return nullptr;
370 : }
371 100 : virtual ActionShortcut* castToActionShortcut() noexcept {
372 100 : return nullptr;
373 : }
374 : };
375 :
376 : /////////////////////
377 : // FAST INLINE METHODS
378 :
379 : inline
380 : const std::string & Action::getLabel()const {
381 178385997 : return label;
382 : }
383 :
384 : inline
385 : const std::string & Action::getName()const {
386 20716214 : return name;
387 : }
388 :
389 : template<class T>
390 140794 : void Action::parse(const std::string&key,T&t) {
391 : // Check keyword has been registered
392 140794 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
393 :
394 : // Now try to read the keyword
395 : std::string def;
396 140794 : bool present=Tools::findKeyword(line,key);
397 140794 : bool found=Tools::parse(line,key,t,replica_index);
398 140794 : 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 251072 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
404 20985 : if( keywords.getDefaultValue(key,def) ) {
405 15286 : if( def.length()==0 || !Tools::convertNoexcept(def,t) ) {
406 0 : plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
407 : }
408 30572 : defaults += " " + key + "=" + def;
409 11398 : } else if( keywords.style(key,"compulsory") ) {
410 3 : error("keyword " + key + " is compulsory for this action");
411 : }
412 : }
413 140791 : }
414 :
415 : template<class T>
416 42824 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
417 : // Check keyword has been registered
418 42824 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
419 42824 : if( !keywords.numbered(key) ) {
420 0 : error("numbered keywords are not allowed for " + key );
421 : }
422 :
423 : // Now try to read the keyword
424 : std::string num;
425 42824 : Tools::convert(no,num);
426 85648 : return Tools::parse(line,key+num,t,replica_index);
427 : }
428 :
429 : template<class T>
430 82746 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
431 : // Check keyword has been registered
432 82746 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
433 82746 : unsigned size=t.size();
434 : bool skipcheck=false;
435 82746 : if(size==0) {
436 : skipcheck=true;
437 : }
438 :
439 : // Now try to read the keyword
440 : std::string def;
441 : T val;
442 82746 : bool present=Tools::findKeyword(line,key);
443 82746 : bool found=Tools::parseVector(line,key,t,replica_index);
444 82746 : if(present && !found) {
445 2 : error("keyword " + key +" could not be read correctly");
446 : }
447 :
448 : // Check vectors size is correct (not if this is atoms or ARG)
449 165490 : if( !keywords.style(key,"atoms") && found ) {
450 : // bool skipcheck=false;
451 : // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
452 51804 : if( !skipcheck && t.size()!=size ) {
453 6 : error("vector read in for keyword " + key + " has the wrong size");
454 : }
455 : }
456 :
457 : // If it isn't read and it is compulsory see if a default value was specified
458 112869 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
459 3073 : if( keywords.getDefaultValue(key,def) ) {
460 2964 : if( def.length()==0 || !Tools::convertNoexcept(def,val) ) {
461 0 : plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
462 : } else {
463 2964 : if(t.size()>0) {
464 5319 : for(unsigned i=0; i<t.size(); ++i) {
465 3530 : t[i]=val;
466 : }
467 2858 : defaults += " " + key + "=" + def;
468 3890 : for(unsigned i=1; i<t.size(); ++i) {
469 4922 : defaults += "," + def;
470 : }
471 : } else {
472 1535 : t.push_back(val);
473 3070 : defaults += " " + key + "=" + def;
474 : }
475 : }
476 218 : } else if( keywords.style(key,"compulsory") ) {
477 4 : error("keyword " + key + " is compulsory for this action");
478 : }
479 79669 : } else if ( !found ) {
480 13418 : t.resize(0);
481 : }
482 82742 : }
483 :
484 : template<class T>
485 196349 : bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
486 196349 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
487 196349 : if( !keywords.numbered(key) ) {
488 0 : error("numbered keywords are not allowed for " + key );
489 : }
490 :
491 196349 : unsigned size=t.size();
492 : bool skipcheck=false;
493 196349 : if(size==0) {
494 : skipcheck=true;
495 : }
496 : std::string num;
497 196349 : Tools::convert(no,num);
498 196349 : bool present=Tools::findKeyword(line,key);
499 196349 : bool found=Tools::parseVector(line,key+num,t,replica_index);
500 196349 : if(present && !found) {
501 0 : error("keyword " + key +" could not be read correctly");
502 : }
503 :
504 392698 : if( keywords.style(key,"compulsory") ) {
505 115 : if (!skipcheck && found && t.size()!=size ) {
506 0 : error("vector read in for keyword " + key + num + " has the wrong size");
507 : }
508 196234 : } else if ( !found ) {
509 1585 : t.resize(0);
510 : }
511 196349 : return found;
512 : }
513 :
514 : inline
515 4388032 : void Action::deactivate() {
516 : options.clear();
517 4388032 : active=false;
518 4388032 : }
519 :
520 : inline
521 : bool Action::isActive()const {
522 226810074 : return active;
523 : }
524 :
525 : inline
526 1858577 : bool Action::isOptionOn(const std::string &s)const {
527 1858577 : return options.count(s);
528 : }
529 :
530 : inline
531 : bool Action::getRestart()const {
532 4183 : return restart;
533 : }
534 :
535 : inline
536 : std::string Action::getDefaultString() const {
537 32 : return defaults;
538 : }
539 :
540 : }
541 : #endif
542 :
|