Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2019 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 "Value.h"
29 : #include "tools/Tools.h"
30 : #include "tools/Log.h"
31 :
32 : namespace PLMD {
33 :
34 : class PDB;
35 : class PlumedMain;
36 : class Communicator;
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 10558 : 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 : {
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 : 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 disabled (private and unimplemented)
172 : explicit Action(const Action&a);
173 : /// Assignment operator is disabled (private and unimplemented)
174 : Action& operator=(const Action&a);
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 4157 : virtual void lockRequests() {}
197 4157 : 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 224788 : 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 132913 : 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 4920 : 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 42116 : virtual bool checkNumericalDerivatives()const {return false;}
261 :
262 : /// Check if the action needs gradient
263 183771 : 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 26752563 : return label;
298 : }
299 :
300 : inline
301 : const std::string & Action::getName()const {
302 361 : return name;
303 : }
304 :
305 : template<class T>
306 28073 : 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 28073 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
314 :
315 : // Now try to read the keyword
316 : std::string def;
317 28073 : bool present=Tools::findKeyword(line,key);
318 28073 : bool found=Tools::parse(line,key,t,replica_index);
319 28079 : 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 84213 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
323 16710 : if( keywords.getDefaultValue(key,def) ) {
324 1725 : if( def.length()==0 || !Tools::convert(def,t) ) {
325 0 : log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() );
326 0 : this->exit(1);
327 : }
328 7688 : } else if( keywords.style(key,"compulsory") ) {
329 3 : error("keyword " + key + " is compulsory for this action");
330 : }
331 : }
332 28070 : }
333 :
334 : template<class T>
335 3587 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
336 : // Check keyword has been registered
337 3587 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
338 3587 : if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
339 :
340 : // Now try to read the keyword
341 3587 : std::string num; Tools::convert(no,num);
342 10761 : return Tools::parse(line,key+num,t,replica_index);
343 : }
344 :
345 : template<class T>
346 11614 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
347 : // if(!Tools::parseVector(line,key,t)){
348 : // log.printf("ERROR parsing keyword %s\n",key.c_str());
349 : // log.printf("%s\n",getDocumentation().c_str());
350 : // this->exit(1);
351 : // }
352 :
353 : // Check keyword has been registered
354 11614 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
355 11614 : unsigned size=t.size(); bool skipcheck=false;
356 11614 : if(size==0) skipcheck=true;
357 :
358 : // Now try to read the keyword
359 : std::string def; T val;
360 11614 : bool present=Tools::findKeyword(line,key);
361 11614 : bool found=Tools::parseVector(line,key,t,replica_index);
362 11619 : if(present && !found) error("keyword " + key +" could not be read correctly");
363 :
364 : // Check vectors size is correct (not if this is atoms or ARG)
365 23230 : if( !keywords.style(key,"atoms") && found ) {
366 : // bool skipcheck=false;
367 : // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
368 5924 : if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size");
369 : }
370 :
371 : // If it isn't read and it is compulsory see if a default value was specified
372 34834 : if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
373 1903 : if( keywords.getDefaultValue(key,def) ) {
374 546 : if( def.length()==0 || !Tools::convert(def,val) ) {
375 0 : log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() );
376 0 : this->exit(1);
377 : } else {
378 3973 : if(t.size()>0) for(unsigned i=0; i<t.size(); ++i) t[i]=val;
379 64 : else t.push_back(val);
380 : }
381 174 : } else if( keywords.style(key,"compulsory") ) {
382 4 : error("keyword " + key + " is compulsory for this action");
383 : }
384 10977 : } else if ( !found ) {
385 4129 : t.resize(0);
386 : }
387 11610 : }
388 :
389 : template<class T>
390 2726 : bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
391 2726 : plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
392 2726 : if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key );
393 :
394 2726 : unsigned size=t.size(); bool skipcheck=false;
395 2726 : if(size==0) skipcheck=true;
396 2726 : std::string num; Tools::convert(no,num);
397 2726 : bool present=Tools::findKeyword(line,key);
398 5452 : bool found=Tools::parseVector(line,key+num,t,replica_index);
399 2726 : if(present && !found) error("keyword " + key +" could not be read correctly");
400 :
401 5452 : if( keywords.style(key,"compulsory") ) {
402 76 : if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size");
403 2671 : } else if ( !found ) {
404 778 : t.resize(0);
405 : }
406 2726 : return found;
407 : }
408 :
409 : inline
410 236697 : void Action::deactivate() {
411 : options.clear();
412 236697 : active=false;
413 236697 : }
414 :
415 : inline
416 : bool Action::isActive()const {
417 1119019 : return active;
418 : }
419 :
420 : inline
421 : bool Action::isOptionOn(const std::string &s)const {
422 : return options.count(s);
423 : }
424 :
425 : inline
426 : bool Action::getRestart()const {
427 2650 : return restart;
428 : }
429 :
430 : }
431 : #endif
432 :
|