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 : #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 1607 : Keywords ActionOptions::emptyKeys;
34 :
35 5260 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
36 : plumed(p),
37 : line(l),
38 5260 : keys(emptyKeys)
39 : {
40 5260 : }
41 :
42 5258 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
43 : plumed(ao.plumed),
44 : line(ao.line),
45 5258 : keys(keys)
46 : {
47 5258 : }
48 :
49 5477 : void Action::registerKeywords( Keywords& keys ) {
50 5477 : plumed_assert( keys.size()==0 );
51 5477 : 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 5477 : keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
53 5477 : keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
54 5477 : keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
55 5477 : }
56 :
57 5258 : Action::Action(const ActionOptions&ao):
58 5258 : name(ao.line[0]),
59 : line(ao.line),
60 5258 : update_from(std::numeric_limits<double>::max()),
61 5258 : update_until(std::numeric_limits<double>::max()),
62 : active(false),
63 5258 : restart(ao.plumed.getRestart()),
64 5258 : doCheckPoint(ao.plumed.getCPT()),
65 : plumed(ao.plumed),
66 5258 : log(plumed.getLog()),
67 : comm(plumed.comm),
68 : multi_sim_comm(plumed.multi_sim_comm),
69 36807 : keywords(ao.keys)
70 : {
71 5258 : line.erase(line.begin());
72 5258 : log.printf("Action %s\n",name.c_str());
73 :
74 5258 : if(comm.Get_rank()==0) {
75 4263 : replica_index=multi_sim_comm.Get_rank();
76 : }
77 5258 : comm.Bcast(replica_index,0);
78 :
79 5258 : if ( keywords.exists("LABEL") ) { parse("LABEL",label); }
80 :
81 5258 : if(label.length()==0) {
82 1695 : std::string s; Tools::convert(plumed.getActionSet().size(),s);
83 1695 : label="@"+s;
84 : }
85 5258 : if( plumed.getActionSet().selectWithLabel<Action*>(label) ) error("label " + label + " has been already used");
86 5258 : log.printf(" with label %s\n",label.c_str());
87 5258 : if ( keywords.exists("UPDATE_FROM") ) parse("UPDATE_FROM",update_from);
88 5258 : if(update_from!=std::numeric_limits<double>::max()) log.printf(" only update from time %f\n",update_from);
89 5258 : if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until);
90 5258 : if(update_until!=std::numeric_limits<double>::max()) log.printf(" only update until time %f\n",update_until);
91 5258 : if ( keywords.exists("RESTART") ) {
92 1260 : std::string srestart="AUTO";
93 1260 : parse("RESTART",srestart);
94 1260 : if(srestart=="YES") restart=true;
95 1221 : else if(srestart=="NO") restart=false;
96 1219 : else if(srestart=="AUTO") {}
97 2 : else error("RESTART should be either YES, NO, or AUTO");
98 : }
99 5257 : }
100 :
101 10514 : Action::~Action() {
102 5257 : if(files.size()!=0) {
103 0 : std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n";
104 : }
105 5257 : }
106 :
107 39 : FILE* Action::fopen(const char *path, const char *mode) {
108 39 : bool write(false);
109 39 : for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true;
110 : FILE* fp;
111 39 : if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode);
112 39 : else fp=plumed.fopen(path,mode);
113 39 : files.insert(fp);
114 39 : return fp;
115 : }
116 :
117 39 : int Action::fclose(FILE*fp) {
118 39 : files.erase(fp);
119 39 : return plumed.fclose(fp);
120 : }
121 :
122 7041 : void Action::fflush() {
123 7041 : for(const auto & p : files) {
124 0 : std::fflush(p);
125 : }
126 7041 : }
127 :
128 28 : std::string Action::getKeyword(const std::string& key) {
129 : // Check keyword has been registered
130 28 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
131 :
132 28 : std::string outkey;
133 28 : if( Tools::getKey(line,key,outkey ) ) return key + outkey;
134 :
135 0 : if( keywords.style(key,"compulsory") ) {
136 0 : if( keywords.getDefaultValue(key,outkey) ) {
137 0 : if( outkey.length()==0 ) error("keyword " + key + " has weird default value");
138 0 : return key + "=" + outkey;
139 : } else {
140 0 : error("keyword " + key + " is compulsory for this action");
141 : }
142 : }
143 0 : return "";
144 : }
145 :
146 14011 : void Action::parseFlag(const std::string&key,bool & t) {
147 : // Check keyword has been registered
148 14011 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
149 : // Check keyword is a flag
150 14011 : if(!keywords.style(key,"nohtml")) {
151 14011 : plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag");
152 : }
153 :
154 : // Read in the flag otherwise get the default value from the keywords object
155 14011 : if(!Tools::parseFlag(line,key,t)) {
156 13101 : if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
157 2399 : t=false;
158 10702 : } else if ( !keywords.getLogicalDefault(key,t) ) {
159 0 : log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() );
160 0 : plumed_error();
161 : }
162 : }
163 14011 : }
164 :
165 24088 : void Action::addDependency(Action*action) {
166 24088 : after.push_back(action);
167 24088 : }
168 :
169 378255 : void Action::activate() {
170 : // preparation step is called only the first time an Action is activated.
171 : // since it could change its dependences (e.g. in an ActionAtomistic which is
172 : // accessing to a virtual atom), this is done just before dependencies are
173 : // activated
174 378255 : if(!active) {
175 190097 : this->unlockRequests();
176 190097 : prepare();
177 190097 : this->lockRequests();
178 566413 : } else return;
179 190097 : for(const auto & p : after) p->activate();
180 190097 : active=true;
181 : }
182 :
183 594 : void Action::setOption(const std::string &s) {
184 : // This overloads the action and activate some options
185 594 : options.insert(s);
186 594 : for(const auto & p : after) p->setOption(s);
187 594 : }
188 :
189 0 : void Action::clearOptions() {
190 : // This overloads the action and activate some options
191 0 : options.clear();
192 0 : }
193 :
194 :
195 5280 : void Action::clearDependencies() {
196 5280 : after.clear();
197 5280 : }
198 :
199 0 : std::string Action::getDocumentation()const {
200 0 : return std::string("UNDOCUMENTED ACTION");
201 : }
202 :
203 10031 : void Action::checkRead() {
204 10031 : if(!line.empty()) {
205 0 : std::string msg="cannot understand the following words from the input line : ";
206 0 : for(unsigned i=0; i<line.size(); i++) {
207 0 : if(i>0) msg = msg + ", ";
208 0 : msg = msg + line[i];
209 : }
210 0 : error(msg);
211 : }
212 10031 : }
213 :
214 1144455 : long int Action::getStep()const {
215 1144455 : return plumed.getStep();
216 : }
217 :
218 930502 : double Action::getTime()const {
219 930502 : return plumed.getAtoms().getTimeStep()*getStep();
220 : }
221 :
222 4996 : double Action::getTimeStep()const {
223 4996 : return plumed.getAtoms().getTimeStep();
224 : }
225 :
226 :
227 :
228 0 : void Action::exit(int c) {
229 0 : plumed.exit(c);
230 0 : }
231 :
232 0 : void Action::calculateNumericalDerivatives( ActionWithValue* a ) {
233 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");
234 : }
235 :
236 153911 : void Action::prepare() {
237 153911 : return;
238 : }
239 :
240 30 : void Action::error( const std::string & msg ) const {
241 30 : log.printf("ERROR in input to action %s with label %s : %s \n \n", name.c_str(), label.c_str(), msg.c_str() );
242 30 : plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
243 : }
244 :
245 238 : void Action::warning( const std::string & msg ) {
246 238 : log.printf("WARNING for action %s with label %s : %s \n", name.c_str(), label.c_str(), msg.c_str() );
247 238 : }
248 :
249 0 : void Action::calculateFromPDB( const PDB& pdb ) {
250 0 : activate();
251 0 : for(const auto & p : after) {
252 0 : ActionWithValue*av=dynamic_cast<ActionWithValue*>(p);
253 0 : if(av) { av->clearInputForces(); av->clearDerivatives(); }
254 0 : p->readAtomsFromPDB( pdb );
255 0 : p->calculate();
256 : }
257 0 : readAtomsFromPDB( pdb );
258 0 : calculate();
259 0 : }
260 :
261 13718 : bool Action::getExchangeStep()const {
262 13718 : return plumed.getExchangeStep();
263 : }
264 :
265 12 : std::string Action::cite(const std::string&s) {
266 12 : return plumed.cite(s);
267 : }
268 :
269 : /// Check if action should be updated.
270 186953 : bool Action::checkUpdate()const {
271 186953 : double t=getTime();
272 186953 : if(t<update_until && (update_from==std::numeric_limits<double>::max() || t>=update_from)) return true;
273 510 : else return false;
274 : }
275 :
276 772 : bool Action::getCPT()const {
277 772 : return plumed.getCPT();
278 : }
279 :
280 4821 : }
281 :
|