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 28212 : 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 : public:
103 :
104 : /// Reference to main plumed object
105 : PlumedMain& plumed;
106 :
107 : /// Reference to the log stream
108 : Log& log;
109 :
110 : /// Specify that this Action depends on another one
111 : void addDependency(Action*);
112 :
113 : /// Clear the dependence list for this Action
114 : void clearDependencies();
115 :
116 : /// Return the present timestep
117 : long int getStep()const;
118 :
119 : /// Return the present time
120 : double getTime()const;
121 :
122 : /// Return the timestep
123 : double getTimeStep()const;
124 :
125 : /// Return true if we are doing a restart
126 : bool getRestart()const;
127 :
128 : /// Return true if we are doing at a checkpoint step
129 : bool getCPT()const;
130 :
131 : /// Just read one of the keywords and return the whole thing as a string
132 : std::string getKeyword(const std::string& key);
133 :
134 : /// Parse one keyword as generic type
135 : template<class T>
136 : void parse(const std::string&key,T&t);
137 :
138 : /// Parse one numbered keyword as generic type
139 : template<class T>
140 : bool parseNumbered(const std::string&key, const int no, T&t);
141 :
142 : /// Parse one keyword as std::vector
143 : template<class T>
144 : void parseVector(const std::string&key,std::vector<T>&t);
145 :
146 : /// Parse a vector with a number
147 : template<class T>
148 : bool parseNumberedVector(const std::string& key, const int no, std::vector<T>&t);
149 :
150 : /// Parse one keyword as boolean flag
151 : void parseFlag(const std::string&key,bool&t);
152 :
153 : /// Crash calculation and print documentation
154 : [[noreturn]] void error( const std::string & msg ) const;
155 :
156 : /// Issue a warning
157 : void warning( const std::string & msg );
158 :
159 : /// Exit with error code c
160 : void exit(int c=0);
161 :
162 : ///
163 : std::set<FILE*> files;
164 :
165 : public:
166 : /// Standard constructor from ActionOptions
167 : explicit Action(const ActionOptions&);
168 : /// Destructor
169 : virtual ~Action();
170 : private:
171 : /// Copy constructor is deleted
172 : Action(const Action&a) = delete;
173 : /// Assignment operator is deleted
174 : Action& operator=(const Action&a) = delete;
175 : int replica_index;
176 : public:
177 : /// Check if Action was properly read.
178 : /// This checks if Action::line is empty. It must be called after
179 : /// a final Action has been initialized
180 : void checkRead();
181 :
182 : Communicator& comm;
183 : Communicator& multi_sim_comm;
184 :
185 : const Keywords& keywords;
186 : /// Prepare an Action for calculation
187 : /// This can be used by Action if they need some special preparation
188 : /// before calculation. Typical case is for collective variables
189 : /// which would like to change their list of requested atoms.
190 : /// By default (if not overridden) does nothing.
191 : virtual void prepare();
192 :
193 : /// Register all the relevant keywords for the action
194 : static void registerKeywords( Keywords& keys );
195 :
196 945438 : virtual void lockRequests() {}
197 945438 : virtual void unlockRequests() {}
198 :
199 : /// Calculate an Action.
200 : /// This method is called one or more times per step.
201 : /// The set of all Actions is calculated in forward order.
202 : virtual void calculate()=0;
203 :
204 : /// Apply an Action.
205 : /// This method is called one time per step.
206 : /// The set of all Actions is applied in backward order.
207 : virtual void apply()=0;
208 :
209 : /// Before Update.
210 : /// This is a special method that is called just
211 : /// before the update() method. It can be used by
212 : /// actions that want to do something irrespectively
213 : /// of the fact that update() is active or not.
214 : /// In other words, this is *always* called, even when action
215 : /// is not active.
216 1806737 : virtual void beforeUpdate() {}
217 :
218 : /// Update.
219 : /// This method is called one time per step.
220 : /// The set of all Actions is updated in forward order.
221 412153 : virtual void update() {}
222 :
223 : /// RunFinalJobs
224 : /// This method is called once at the very end of the calculation.
225 : /// The set of all Actions in run for the final time in forward order.
226 13316 : virtual void runFinalJobs() {}
227 :
228 : /// Tell to the Action to flush open files
229 : void fflush();
230 :
231 : virtual std::string getDocumentation()const;
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 {return after;}
258 :
259 : /// Check if numerical derivatives should be performed
260 251765 : virtual bool checkNumericalDerivatives()const {return false;}
261 :
262 : /// Check if the action needs gradient
263 1633696 : virtual bool checkNeedsGradients()const {return false;}
264 :
265 : /// Perform calculation using numerical derivatives
266 : /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
267 : /// are doing.
268 : virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
269 :
270 : /// Opens a file.
271 : /// This is similar to plain fopen, but with some extra functionality.
272 : /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
273 : /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
274 : FILE *fopen(const char *path, const char *mode);
275 : /// Closes a file opened with Action::fclose().
276 : int fclose(FILE*fp);
277 :
278 : /// Calculate the action given a pdb file as input. This is used to initialize
279 : /// things like distance from a point in CV map space given a pdb as an input file
280 : void calculateFromPDB( const PDB& );
281 : /// This is overwritten in ActionAtomistic so that we can read
282 : /// the atoms from the pdb input file rather than taking them from the
283 : /// MD code
284 0 : virtual void readAtomsFromPDB( const PDB& ) {}
285 : /// Check if we are on an exchange step
286 : bool getExchangeStep()const;
287 :
288 : /// Cite a paper see PlumedMain::cite
289 : std::string cite(const std::string&s);
290 : };
291 :
292 : /////////////////////
293 : // FAST INLINE METHODS
294 :
295 : inline
296 : const std::string & Action::getLabel()const {
297 60592886 : return label;
298 : }
299 :
300 : inline
301 : const std::string & Action::getName()const {
302 7713 : return name;
303 : }
304 :
305 : template<class T>
306 45290 : void Action::parse(const std::string&key,T&t) {
307 : // if(!Tools::parse(line,key,t)){
308 : // log.printf("ERROR parsing keyword %s\n",key.c_str());
309 : // log.printf("%s\n",getDocumentation().c_str());
310 : // this->exit(1);
311 : // }
312 : // Check keyword has been registered
313 45290 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
314 :
315 : // Now try to read the keyword
316 : std::string def;
317 45290 : bool present=Tools::findKeyword(line,key);
318 45290 : bool found=Tools::parse(line,key,t,replica_index);
319 45293 : if(present && !found) error("keyword " + key +" could not be read correctly");
320 :
321 : // If it isn't read and it is compulsory see if a default value was specified
322 93364 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
323 15194 : if( keywords.getDefaultValue(key,def) ) {
324 2479 : if( def.length()==0 || !Tools::convertNoexcept(def,t) ) {
325 0 : plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
326 : }
327 10236 : } else if( keywords.style(key,"compulsory") ) {
328 3 : error("keyword " + key + " is compulsory for this action");
329 : }
330 : }
331 45287 : }
332 :
333 : template<class T>
334 4623 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
335 : // Check keyword has been registered
336 4623 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
337 4623 : if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
338 :
339 : // Now try to read the keyword
340 4623 : std::string num; Tools::convert(no,num);
341 9246 : return Tools::parse(line,key+num,t,replica_index);
342 : }
343 :
344 : template<class T>
345 29950 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
346 : // if(!Tools::parseVector(line,key,t)){
347 : // log.printf("ERROR parsing keyword %s\n",key.c_str());
348 : // log.printf("%s\n",getDocumentation().c_str());
349 : // this->exit(1);
350 : // }
351 :
352 : // Check keyword has been registered
353 29950 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
354 29950 : unsigned size=t.size(); bool skipcheck=false;
355 29950 : if(size==0) skipcheck=true;
356 :
357 : // Now try to read the keyword
358 : std::string def; T val;
359 29950 : bool present=Tools::findKeyword(line,key);
360 29950 : bool found=Tools::parseVector(line,key,t,replica_index);
361 29951 : if(present && !found) error("keyword " + key +" could not be read correctly");
362 :
363 : // Check vectors size is correct (not if this is atoms or ARG)
364 59898 : if( !keywords.style(key,"atoms") && found ) {
365 : // bool skipcheck=false;
366 : // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
367 13485 : if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
368 : }
369 :
370 : // If it isn't read and it is compulsory see if a default value was specified
371 42958 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
372 1876 : if( keywords.getDefaultValue(key,def) ) {
373 836 : if( def.length()==0 || !Tools::convertNoexcept(def,val) ) {
374 0 : plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
375 : } else {
376 2422 : if(t.size()>0) for(unsigned i=0; i<t.size(); ++i) t[i]=val;
377 236 : else t.push_back(val);
378 : }
379 204 : } else if( keywords.style(key,"compulsory") ) {
380 4 : error("keyword " + key + " is compulsory for this action");
381 : }
382 29008 : } else if ( !found ) {
383 5935 : t.resize(0);
384 : }
385 29946 : }
386 :
387 : template<class T>
388 3447 : bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
389 3447 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
390 3447 : if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
391 :
392 3447 : unsigned size=t.size(); bool skipcheck=false;
393 3447 : if(size==0) skipcheck=true;
394 3447 : std::string num; Tools::convert(no,num);
395 3447 : bool present=Tools::findKeyword(line,key);
396 3447 : bool found=Tools::parseVector(line,key+num,t,replica_index);
397 3447 : if(present && !found) error("keyword " + key +" could not be read correctly");
398 :
399 6894 : if( keywords.style(key,"compulsory") ) {
400 90 : if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size");
401 3357 : } else if ( !found ) {
402 992 : t.resize(0);
403 : }
404 3447 : return found;
405 : }
406 :
407 : inline
408 1823622 : void Action::deactivate() {
409 : options.clear();
410 1823622 : active=false;
411 1823622 : }
412 :
413 : inline
414 : bool Action::isActive()const {
415 7612264 : return active;
416 : }
417 :
418 : inline
419 1404234 : bool Action::isOptionOn(const std::string &s)const {
420 1404234 : return options.count(s);
421 : }
422 :
423 : inline
424 : bool Action::getRestart()const {
425 3486 : return restart;
426 : }
427 :
428 : }
429 : #endif
430 :
|