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