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 1958 : Keywords ActionOptions::emptyKeys;
34 :
35 6228 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
36 : plumed(p),
37 : line(l),
38 6228 : keys(emptyKeys)
39 : {
40 6228 : }
41 :
42 6226 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
43 : plumed(ao.plumed),
44 : line(ao.line),
45 6226 : keys(keys)
46 : {
47 6226 : }
48 :
49 6492 : void Action::registerKeywords( Keywords& keys ) {
50 6492 : plumed_assert( keys.size()==0 );
51 25968 : 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 25968 : keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
53 25968 : keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
54 25968 : keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
55 6492 : }
56 :
57 6226 : 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 6226 : restart(ao.plumed.getRestart()),
64 6226 : doCheckPoint(ao.plumed.getCPT()),
65 : plumed(ao.plumed),
66 6226 : log(plumed.getLog()),
67 : comm(plumed.comm),
68 : multi_sim_comm(plumed.multi_sim_comm),
69 49809 : keywords(ao.keys)
70 : {
71 6226 : line.erase(line.begin());
72 6226 : log.printf("Action %s\n",name.c_str());
73 :
74 6226 : if(comm.Get_rank()==0) {
75 5136 : replica_index=multi_sim_comm.Get_rank();
76 : }
77 6226 : comm.Bcast(replica_index,0);
78 :
79 18520 : if ( keywords.exists("LABEL") ) { parse("LABEL",label); }
80 :
81 6226 : if(label.length()==0) {
82 4042 : std::string s; Tools::convert(plumed.getActionSet().size(),s);
83 4042 : label="@"+s;
84 : }
85 12452 : if( plumed.getActionSet().selectWithLabel<Action*>(label) ) error("label " + label + " has been already used");
86 6226 : log.printf(" with label %s\n",label.c_str());
87 13858 : if ( keywords.exists("UPDATE_FROM") ) parse("UPDATE_FROM",update_from);
88 6226 : if(update_from!=std::numeric_limits<double>::max()) log.printf(" only update from time %f\n",update_from);
89 13858 : if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until);
90 6226 : if(update_until!=std::numeric_limits<double>::max()) log.printf(" only update until time %f\n",update_until);
91 12453 : if ( keywords.exists("RESTART") ) {
92 1468 : std::string srestart="AUTO";
93 2935 : parse("RESTART",srestart);
94 1467 : if(srestart=="YES") restart=true;
95 1398 : else if(srestart=="NO") restart=false;
96 1396 : else if(srestart=="AUTO") {}
97 2 : else error("RESTART should be either YES, NO, or AUTO");
98 : }
99 6225 : }
100 :
101 12450 : Action::~Action() {
102 6225 : 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 6225 : }
106 :
107 73 : FILE* Action::fopen(const char *path, const char *mode) {
108 : bool write(false);
109 73 : for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true;
110 : FILE* fp;
111 73 : if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode);
112 73 : else fp=plumed.fopen(path,mode);
113 : files.insert(fp);
114 73 : return fp;
115 : }
116 :
117 91 : int Action::fclose(FILE*fp) {
118 : files.erase(fp);
119 91 : return plumed.fclose(fp);
120 : }
121 :
122 9935 : void Action::fflush() {
123 19870 : for(const auto & p : files) {
124 0 : std::fflush(p);
125 : }
126 9935 : }
127 :
128 29 : std::string Action::getKeyword(const std::string& key) {
129 : // Check keyword has been registered
130 29 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
131 :
132 : std::string outkey;
133 29 : 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 17176 : void Action::parseFlag(const std::string&key,bool & t) {
147 : // Check keyword has been registered
148 17176 : plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
149 : // Check keyword is a flag
150 34352 : if(!keywords.style(key,"nohtml")) {
151 49006 : 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 17176 : if(!Tools::parseFlag(line,key,t)) {
156 47850 : if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
157 2522 : t=false;
158 26856 : } 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 17176 : }
164 :
165 25790 : void Action::addDependency(Action*action) {
166 25790 : after.push_back(action);
167 25790 : }
168 :
169 815505 : 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 815505 : if(!active) {
175 456102 : this->unlockRequests();
176 456102 : prepare();
177 456102 : this->lockRequests();
178 815505 : } else return;
179 1434668 : for(const auto & p : after) p->activate();
180 456102 : active=true;
181 : }
182 :
183 594 : void Action::setOption(const std::string &s) {
184 : // This overloads the action and activate some options
185 : options.insert(s);
186 1587 : 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 : options.clear();
192 0 : }
193 :
194 :
195 6201 : void Action::clearDependencies() {
196 : after.clear();
197 6201 : }
198 :
199 0 : std::string Action::getDocumentation()const {
200 0 : return std::string("UNDOCUMENTED ACTION");
201 : }
202 :
203 11778 : void Action::checkRead() {
204 11778 : 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 11778 : }
213 :
214 1995619 : long int Action::getStep()const {
215 3991238 : return plumed.getStep();
216 : }
217 :
218 1370523 : double Action::getTime()const {
219 2741046 : return plumed.getAtoms().getTimeStep()*getStep();
220 : }
221 :
222 16159 : double Action::getTimeStep()const {
223 32318 : 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 313565 : void Action::prepare() {
237 313565 : 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 240 : plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
243 : }
244 :
245 153 : void Action::warning( const std::string & msg ) {
246 153 : log.printf("WARNING for action %s with label %s : %s \n", name.c_str(), label.c_str(), msg.c_str() );
247 153 : }
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 27689 : bool Action::getExchangeStep()const {
262 55378 : return plumed.getExchangeStep();
263 : }
264 :
265 24 : std::string Action::cite(const std::string&s) {
266 24 : return plumed.cite(s);
267 : }
268 :
269 : /// Check if action should be updated.
270 448251 : bool Action::checkUpdate()const {
271 448251 : double t=getTime();
272 448251 : if(t<update_until && (update_from==std::numeric_limits<double>::max() || t>=update_from)) return true;
273 510 : else return false;
274 : }
275 :
276 976 : bool Action::getCPT()const {
277 1952 : return plumed.getCPT();
278 : }
279 :
280 5874 : }
281 :
|