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