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 1613 : Keywords ActionOptions::emptyKeys;
34 :
35 5280 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
36 : plumed(p),
37 : line(l),
38 5280 : keys(emptyKeys)
39 : {
40 5280 : }
41 :
42 5278 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
43 5278 : plumed(ao.plumed),
44 : line(ao.line),
45 5278 : keys(keys)
46 : {
47 5278 : }
48 :
49 5497 : void Action::registerKeywords( Keywords& keys ) {
50 5497 : plumed_assert( keys.size()==0 );
51 21988 : 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 21988 : keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
53 21988 : keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
54 21988 : keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
55 5497 : }
56 :
57 5278 : Action::Action(const ActionOptions&ao):
58 : name(ao.line[0]),
59 : line(ao.line),
60 : update_from(std::numeric_limits<double>::max()),
61 : update_until(std::numeric_limits<double>::max()),
62 : active(false),
63 5278 : restart(ao.plumed.getRestart()),
64 5278 : doCheckPoint(ao.plumed.getCPT()),
65 5278 : plumed(ao.plumed),
66 5278 : log(plumed.getLog()),
67 5278 : comm(plumed.comm),
68 5278 : multi_sim_comm(plumed.multi_sim_comm),
69 52781 : keywords(ao.keys)
70 : {
71 : line.erase(line.begin());
72 10556 : log.printf("Action %s\n",name.c_str());
73 :
74 5278 : if(comm.Get_rank()==0) {
75 4283 : replica_index=multi_sim_comm.Get_rank();
76 : }
77 5278 : comm.Bcast(replica_index,0);
78 :
79 15707 : if ( keywords.exists("LABEL") ) { parse("LABEL",label); }
80 :
81 5278 : if(label.length()==0) {
82 3404 : std::string s; Tools::convert(plumed.getActionSet().size(),s);
83 3404 : label="@"+s;
84 : }
85 10557 : if( plumed.getActionSet().selectWithLabel<Action*>(label) ) error("label " + label + " has been already used");
86 10556 : log.printf(" with label %s\n",label.c_str());
87 11735 : if ( keywords.exists("UPDATE_FROM") ) parse("UPDATE_FROM",update_from);
88 5278 : if(update_from!=std::numeric_limits<double>::max()) log.printf(" only update from time %f\n",update_from);
89 11735 : if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until);
90 5278 : if(update_until!=std::numeric_limits<double>::max()) log.printf(" only update until time %f\n",update_until);
91 10556 : if ( keywords.exists("RESTART") ) {
92 1263 : std::string srestart="AUTO";
93 2524 : parse("RESTART",srestart);
94 1262 : if(srestart=="YES") restart=true;
95 1223 : else if(srestart=="NO") restart=false;
96 1221 : else if(srestart=="AUTO") {}
97 2 : else error("RESTART should be either YES, NO, or AUTO");
98 : }
99 5277 : }
100 :
101 15831 : Action::~Action() {
102 5277 : 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 5277 : }
106 :
107 39 : FILE* Action::fopen(const char *path, const char *mode) {
108 : bool write(false);
109 78 : 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 : files.insert(fp);
114 39 : return fp;
115 : }
116 :
117 39 : int Action::fclose(FILE*fp) {
118 : files.erase(fp);
119 39 : return plumed.fclose(fp);
120 : }
121 :
122 7070 : void Action::fflush() {
123 7070 : for(const auto & p : files) {
124 0 : std::fflush(p);
125 : }
126 7070 : }
127 :
128 30 : std::string Action::getKeyword(const std::string& key) {
129 : // Check keyword has been registered
130 30 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
131 :
132 : std::string outkey;
133 30 : 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 14045 : void Action::parseFlag(const std::string&key,bool & t) {
147 : // Check keyword has been registered
148 14045 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
149 : // Check keyword is a flag
150 28090 : if(!keywords.style(key,"nohtml")) {
151 56180 : 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 14045 : if(!Tools::parseFlag(line,key,t)) {
156 39393 : if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
157 2399 : t=false;
158 32196 : } 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 14045 : }
164 :
165 24102 : void Action::addDependency(Action*action) {
166 24102 : after.push_back(action);
167 24102 : }
168 :
169 378518 : 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 378518 : if(!active) {
175 190276 : this->unlockRequests();
176 190276 : prepare();
177 190276 : this->lockRequests();
178 : } else return;
179 495048 : for(const auto & p : after) p->activate();
180 190276 : active=true;
181 : }
182 :
183 267 : void Action::setOption(const std::string &s) {
184 : // This overloads the action and activate some options
185 : options.insert(s);
186 448 : for(const auto & p : after) p->setOption(s);
187 267 : }
188 :
189 0 : void Action::clearOptions() {
190 : // This overloads the action and activate some options
191 : options.clear();
192 0 : }
193 :
194 :
195 5290 : void Action::clearDependencies() {
196 : after.clear();
197 5290 : }
198 :
199 0 : std::string Action::getDocumentation()const {
200 0 : return std::string("UNDOCUMENTED ACTION");
201 : }
202 :
203 10069 : void Action::checkRead() {
204 10069 : 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 10069 : }
213 :
214 1145151 : long int Action::getStep()const {
215 2290302 : return plumed.getStep();
216 : }
217 :
218 930728 : double Action::getTime()const {
219 1861456 : return plumed.getAtoms().getTimeStep()*getStep();
220 : }
221 :
222 4996 : double Action::getTimeStep()const {
223 9992 : 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 154069 : void Action::prepare() {
237 154069 : return;
238 : }
239 :
240 30 : void Action::error( const std::string & msg ) const {
241 60 : log.printf("ERROR in input to action %s with label %s : %s \n \n", name.c_str(), label.c_str(), msg.c_str() );
242 240 : plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
243 : }
244 :
245 238 : void Action::warning( const std::string & msg ) {
246 476 : 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 27436 : 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 187132 : bool Action::checkUpdate()const {
271 187132 : double t=getTime();
272 187132 : 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 1544 : return plumed.getCPT();
278 : }
279 :
280 4839 : }
281 :
|