Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 : #include "Action.h"
23 : #include "ActionWithValue.h"
24 : #include "PlumedMain.h"
25 : #include "tools/Log.h"
26 : #include "tools/Exception.h"
27 : #include "Atoms.h"
28 : #include "ActionSet.h"
29 : #include <iostream>
30 :
31 : namespace PLMD {
32 :
33 841 : Keywords ActionOptions::emptyKeys;
34 :
35 2347 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
36 : plumed(p),
37 : line(l),
38 2347 : keys(emptyKeys)
39 : {
40 2347 : }
41 :
42 2347 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
43 : plumed(ao.plumed),
44 : line(ao.line),
45 2347 : keys(keys)
46 : {
47 2347 : }
48 :
49 2507 : void Action::registerKeywords( Keywords& keys ) {
50 2507 : plumed_assert( keys.size()==0 );
51 2507 : keys.add( "hidden", "LABEL", "a label for the action so that its output can be referenced in the input to other actions. Actions with scalar output are referenced using their label only. Actions with vector output must have a separate label for every component. Individual componets are then refered to using label.component" );
52 2507 : keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
53 2507 : keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
54 2507 : keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
55 2507 : }
56 :
57 2347 : Action::Action(const ActionOptions&ao):
58 2347 : name(ao.line[0]),
59 : line(ao.line),
60 2347 : update_from(std::numeric_limits<double>::max()),
61 2347 : update_until(std::numeric_limits<double>::max()),
62 : active(false),
63 2347 : restart(ao.plumed.getRestart()),
64 2347 : doCheckPoint(ao.plumed.getCPT()),
65 : plumed(ao.plumed),
66 2347 : log(plumed.getLog()),
67 : comm(plumed.comm),
68 : multi_sim_comm(plumed.multi_sim_comm),
69 16429 : keywords(ao.keys)
70 : {
71 2347 : line.erase(line.begin());
72 2347 : log.printf("Action %s\n",name.c_str());
73 :
74 2347 : if ( keywords.exists("LABEL") ) { parse("LABEL",label); }
75 :
76 2347 : if(label.length()==0) {
77 843 : std::string s; Tools::convert(plumed.getActionSet().size(),s);
78 843 : label="@"+s;
79 : }
80 2347 : if( plumed.getActionSet().selectWithLabel<Action*>(label) ) error("label " + label + " has been already used");
81 2347 : log.printf(" with label %s\n",label.c_str());
82 2347 : if ( keywords.exists("UPDATE_FROM") ) parse("UPDATE_FROM",update_from);
83 2347 : if(update_from!=std::numeric_limits<double>::max()) log.printf(" only update from time %f\n",update_from);
84 2347 : if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until);
85 2347 : if(update_until!=std::numeric_limits<double>::max()) log.printf(" only update until time %f\n",update_until);
86 2347 : if ( keywords.exists("RESTART") ) {
87 649 : std::string srestart="AUTO";
88 649 : parse("RESTART",srestart);
89 649 : if(srestart=="YES") restart=true;
90 612 : else if(srestart=="NO") restart=false;
91 610 : else if(srestart=="AUTO") {}
92 0 : else error("RESTART should be either YES, NO, or AUTO");
93 : }
94 2347 : }
95 :
96 4694 : Action::~Action() {
97 2347 : if(files.size()!=0) {
98 0 : std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n";
99 : }
100 2347 : }
101 :
102 34 : FILE* Action::fopen(const char *path, const char *mode) {
103 34 : bool write(false);
104 34 : for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true;
105 : FILE* fp;
106 34 : if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode);
107 34 : else fp=plumed.fopen(path,mode);
108 34 : files.insert(fp);
109 34 : return fp;
110 : }
111 :
112 34 : int Action::fclose(FILE*fp) {
113 34 : files.erase(fp);
114 34 : return plumed.fclose(fp);
115 : }
116 :
117 3803 : void Action::fflush() {
118 3803 : for(files_iterator p=files.begin(); p!=files.end(); ++p) {
119 0 : std::fflush((*p));
120 : }
121 3803 : }
122 :
123 24 : std::string Action::getKeyword(const std::string& key) {
124 : // Check keyword has been registered
125 24 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
126 :
127 24 : std::string outkey;
128 24 : if( Tools::getKey(line,key,outkey ) ) return key + outkey;
129 :
130 0 : if( keywords.style(key,"compulsory") ) {
131 0 : if( keywords.getDefaultValue(key,outkey) ) {
132 0 : if( outkey.length()==0 ) error("keyword " + key + " has weird default value");
133 0 : return key + "=" + outkey;
134 : } else {
135 0 : error("keyword " + key + " is compulsory for this action");
136 : }
137 : }
138 0 : return "";
139 : }
140 :
141 7664 : void Action::parseFlag(const std::string&key,bool & t) {
142 : // Check keyword has been registered
143 7664 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
144 : // Check keyword is a flag
145 7664 : if(!keywords.style(key,"nohtml")) {
146 7664 : plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag");
147 : }
148 :
149 : // Read in the flag otherwise get the default value from the keywords object
150 7664 : if(!Tools::parseFlag(line,key,t)) {
151 7272 : if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
152 2037 : t=false;
153 5235 : } else if ( !keywords.getLogicalDefault(key,t) ) {
154 0 : log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() );
155 0 : plumed_error();
156 : }
157 : }
158 7664 : }
159 :
160 18947 : void Action::addDependency(Action*action) {
161 18947 : after.push_back(action);
162 18947 : }
163 :
164 239064 : void Action::activate() {
165 : // preparation step is called only the first time an Action is activated.
166 : // since it could change its dependences (e.g. in an ActionAtomistic which is
167 : // accessing to a virtual atom), this is done just before dependencies are
168 : // activated
169 239064 : if(!active) {
170 108738 : this->unlockRequests();
171 108738 : prepare();
172 108738 : this->lockRequests();
173 369390 : } else return;
174 108738 : for(Dependencies::iterator p=after.begin(); p!=after.end(); ++p) (*p)->activate();
175 108738 : active=true;
176 : }
177 :
178 594 : void Action::setOption(const std::string &s) {
179 : // This overloads the action and activate some options
180 594 : options.insert(s);
181 594 : for(Dependencies::iterator p=after.begin(); p!=after.end(); ++p) (*p)->setOption(s);
182 594 : }
183 :
184 0 : void Action::clearOptions() {
185 : // This overloads the action and activate some options
186 0 : options.clear();
187 0 : }
188 :
189 :
190 3355 : void Action::clearDependencies() {
191 3355 : after.clear();
192 3355 : }
193 :
194 0 : std::string Action::getDocumentation()const {
195 0 : return std::string("UNDOCUMENTED ACTION");
196 : }
197 :
198 4456 : void Action::checkRead() {
199 4456 : if(!line.empty()) {
200 0 : std::string msg="cannot understand the following words from the input line : ";
201 0 : for(unsigned i=0; i<line.size(); i++) {
202 0 : if(i>0) msg = msg + ", ";
203 0 : msg = msg + line[i];
204 : }
205 0 : error(msg);
206 : }
207 4456 : }
208 :
209 784942 : long int Action::getStep()const {
210 784942 : return plumed.getStep();
211 : }
212 :
213 671951 : double Action::getTime()const {
214 671951 : return plumed.getAtoms().getTimeStep()*getStep();
215 : }
216 :
217 3143 : double Action::getTimeStep()const {
218 3143 : return plumed.getAtoms().getTimeStep();
219 : }
220 :
221 :
222 :
223 0 : void Action::exit(int c) {
224 0 : plumed.exit(c);
225 0 : }
226 :
227 0 : void Action::calculateNumericalDerivatives( ActionWithValue* a ) {
228 0 : plumed_merror("if you get here it means that you are trying to use numerical derivatives for a class that does not implement them");
229 : }
230 :
231 85388 : void Action::prepare() {
232 85388 : return;
233 : }
234 :
235 0 : void Action::error( const std::string & msg ) const {
236 0 : log.printf("ERROR in input to action %s with label %s : %s \n \n", name.c_str(), label.c_str(), msg.c_str() );
237 0 : plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
238 : }
239 :
240 1 : void Action::warning( const std::string & msg ) {
241 1 : log.printf("WARNING for action %s with label %s : %s \n", name.c_str(), label.c_str(), msg.c_str() );
242 1 : }
243 :
244 0 : void Action::calculateFromPDB( const PDB& pdb ) {
245 0 : activate();
246 0 : for(Dependencies::iterator p=after.begin(); p!=after.end(); ++p) {
247 0 : ActionWithValue*av=dynamic_cast<ActionWithValue*>(*p);
248 0 : if(av) { av->clearInputForces(); av->clearDerivatives(); }
249 0 : (*p)->readAtomsFromPDB( pdb );
250 0 : (*p)->calculate();
251 : }
252 0 : readAtomsFromPDB( pdb );
253 0 : calculate();
254 0 : }
255 :
256 7892 : bool Action::getExchangeStep()const {
257 7892 : return plumed.getExchangeStep();
258 : }
259 :
260 3 : std::string Action::cite(const std::string&s) {
261 3 : return plumed.cite(s);
262 : }
263 :
264 : /// Check if action should be updated.
265 107502 : bool Action::checkUpdate()const {
266 107502 : double t=getTime();
267 107502 : if(t<update_until && (update_from==std::numeric_limits<double>::max() || t>=update_from)) return true;
268 510 : else return false;
269 : }
270 :
271 80 : bool Action::getCPT()const {
272 80 : return plumed.getCPT();
273 : }
274 :
275 :
276 :
277 2523 : }
278 :
|