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 "PlumedMain.h"
23 : #include "ActionAtomistic.h"
24 : #include "ActionPilot.h"
25 : #include "ActionRegister.h"
26 : #include "ActionSet.h"
27 : #include "ActionWithValue.h"
28 : #include "ActionWithVirtualAtom.h"
29 : #include "Atoms.h"
30 : #include "CLToolMain.h"
31 : #include "ExchangePatterns.h"
32 : #include "GREX.h"
33 : #include "config/Config.h"
34 : #include "tools/Citations.h"
35 : #include "tools/Communicator.h"
36 : #include "tools/DLLoader.h"
37 : #include "tools/Exception.h"
38 : #include "tools/IFile.h"
39 : #include "tools/Log.h"
40 : #include "tools/OpenMP.h"
41 : #include "tools/Tools.h"
42 : #include "tools/Stopwatch.h"
43 : #include "lepton/Exception.h"
44 : #include "DataFetchingObject.h"
45 : #include <cstdlib>
46 : #include <cstring>
47 : #include <set>
48 : #include <unordered_map>
49 : #include <exception>
50 : #include <stdexcept>
51 : #include <ios>
52 : #include <new>
53 : #include <typeinfo>
54 : #ifdef __PLUMED_LIBCXX11
55 : #include <system_error>
56 : #include <future>
57 : #include <memory>
58 : #include <functional>
59 : #endif
60 :
61 :
62 : using namespace std;
63 :
64 : namespace PLMD {
65 :
66 : /// Small utility just used in this file to throw arbitrary exceptions
67 18 : static void testThrow(const char* what) {
68 36 : auto words=Tools::getWords(what);
69 18 : plumed_assert(words.size()>0);
70 : #define __PLUMED_THROW_NOMSG(type) if(words[0]==#type) throw type()
71 : #define __PLUMED_THROW_MSG(type) if(words[0]==#type) throw type(what)
72 19 : __PLUMED_THROW_MSG(PLMD::ExceptionError);
73 18 : __PLUMED_THROW_MSG(PLMD::ExceptionDebug);
74 17 : __PLUMED_THROW_MSG(PLMD::Exception);
75 16 : __PLUMED_THROW_MSG(PLMD::lepton::Exception);
76 14 : __PLUMED_THROW_NOMSG(std::bad_exception);
77 : #ifdef __PLUMED_LIBCXX11
78 : __PLUMED_THROW_NOMSG(std::bad_array_new_length);
79 : #endif
80 14 : __PLUMED_THROW_NOMSG(std::bad_alloc);
81 : #ifdef __PLUMED_LIBCXX11
82 : __PLUMED_THROW_NOMSG(std::bad_function_call);
83 : __PLUMED_THROW_NOMSG(std::bad_weak_ptr);
84 : #endif
85 13 : __PLUMED_THROW_NOMSG(std::bad_cast);
86 12 : __PLUMED_THROW_NOMSG(std::bad_typeid);
87 11 : __PLUMED_THROW_MSG(std::underflow_error);
88 10 : __PLUMED_THROW_MSG(std::overflow_error);
89 9 : __PLUMED_THROW_MSG(std::range_error);
90 8 : __PLUMED_THROW_MSG(std::runtime_error);
91 7 : __PLUMED_THROW_MSG(std::out_of_range);
92 6 : __PLUMED_THROW_MSG(std::length_error);
93 5 : __PLUMED_THROW_MSG(std::domain_error);
94 4 : __PLUMED_THROW_MSG(std::invalid_argument);
95 3 : __PLUMED_THROW_MSG(std::logic_error);
96 :
97 : #ifdef __PLUMED_LIBCXX11
98 : if(words[0]=="std::system_error") {
99 : plumed_assert(words.size()>2);
100 : int error_code;
101 : Tools::convert(words[2],error_code);
102 : if(words[1]=="std::generic_category") throw std::system_error(error_code,std::generic_category(),what);
103 : if(words[1]=="std::system_category") throw std::system_error(error_code,std::system_category(),what);
104 : if(words[1]=="std::iostream_category") throw std::system_error(error_code,std::iostream_category(),what);
105 : if(words[1]=="std::future_category") throw std::system_error(error_code,std::future_category(),what);
106 : }
107 : #endif
108 :
109 1 : if(words[0]=="std::ios_base::failure") {
110 : #ifdef __PLUMED_LIBCXX11
111 : int error_code=0;
112 : if(words.size()>2) Tools::convert(words[2],error_code);
113 : if(words.size()>1 && words[1]=="std::generic_category") throw std::ios_base::failure(what,std::error_code(error_code,std::generic_category()));
114 : if(words.size()>1 && words[1]=="std::system_category") throw std::ios_base::failure(what,std::error_code(error_code,std::system_category()));
115 : if(words.size()>1 && words[1]=="std::iostream_category") throw std::ios_base::failure(what,std::error_code(error_code,std::iostream_category()));
116 : if(words.size()>1 && words[1]=="std::future_category") throw std::ios_base::failure(what,std::error_code(error_code,std::future_category()));
117 : #endif
118 2 : throw std::ios_base::failure(what);
119 : }
120 :
121 0 : plumed_error() << "unknown exception " << what;
122 : }
123 :
124 2726 : PlumedMain::PlumedMain():
125 : initialized(false),
126 : // automatically write on log in destructor
127 : stopwatch_fwd(log),
128 : step(0),
129 : active(false),
130 : mydatafetcher(DataFetchingObject::create(sizeof(double),*this)),
131 : endPlumed(false),
132 : atoms_fwd(*this),
133 : actionSet_fwd(*this),
134 : bias(0.0),
135 : work(0.0),
136 : exchangeStep(false),
137 : restart(false),
138 : doCheckPoint(false),
139 : stopFlag(NULL),
140 : stopNow(false),
141 : novirial(false),
142 40890 : detailedTimers(false)
143 : {
144 2726 : log.link(comm);
145 5452 : log.setLinePrefix("PLUMED: ");
146 2726 : }
147 :
148 : // destructor needed to delete forward declarated objects
149 4830 : PlumedMain::~PlumedMain() {
150 4830 : }
151 :
152 : /////////////////////////////////////////////////////////////
153 : // MAIN INTERPRETER
154 :
155 : #define CHECK_INIT(ini,word) plumed_massert(ini,"cmd(\"" + word +"\") should be only used after plumed initialization")
156 : #define CHECK_NOTINIT(ini,word) plumed_massert(!(ini),"cmd(\"" + word +"\") should be only used before plumed initialization")
157 : #define CHECK_NOTNULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"" + word + "\")");
158 :
159 :
160 517989 : void PlumedMain::cmd(const std::string & word,void*val) {
161 :
162 : // Enumerate all possible commands:
163 : enum {
164 : #include "PlumedMainEnum.inc"
165 : };
166 :
167 : // Static object (initialized once) containing the map of commands:
168 : const static std::unordered_map<std::string, int> word_map = {
169 : #include "PlumedMainMap.inc"
170 521883 : };
171 :
172 : try {
173 :
174 517989 : auto ss=stopwatch.startPause();
175 :
176 1035978 : std::vector<std::string> words=Tools::getWords(word);
177 517989 : unsigned nw=words.size();
178 517989 : if(nw==0) {
179 : // do nothing
180 : } else {
181 : int iword=-1;
182 : double d;
183 : const auto it=word_map.find(words[0]);
184 517989 : if(it!=word_map.end()) iword=it->second;
185 517989 : switch(iword) {
186 : case cmd_setBox:
187 38493 : CHECK_INIT(initialized,word);
188 38493 : CHECK_NOTNULL(val,word);
189 38493 : atoms.setBox(val);
190 : break;
191 : case cmd_setPositions:
192 42333 : CHECK_INIT(initialized,word);
193 42333 : atoms.setPositions(val);
194 : break;
195 : case cmd_setMasses:
196 42336 : CHECK_INIT(initialized,word);
197 42336 : atoms.setMasses(val);
198 : break;
199 : case cmd_setCharges:
200 32740 : CHECK_INIT(initialized,word);
201 32740 : atoms.setCharges(val);
202 : break;
203 : case cmd_setPositionsX:
204 0 : CHECK_INIT(initialized,word);
205 0 : atoms.setPositions(val,0);
206 : break;
207 : case cmd_setPositionsY:
208 0 : CHECK_INIT(initialized,word);
209 0 : atoms.setPositions(val,1);
210 : break;
211 : case cmd_setPositionsZ:
212 0 : CHECK_INIT(initialized,word);
213 0 : atoms.setPositions(val,2);
214 : break;
215 : case cmd_setVirial:
216 32835 : CHECK_INIT(initialized,word);
217 32835 : CHECK_NOTNULL(val,word);
218 32835 : atoms.setVirial(val);
219 : break;
220 : case cmd_setEnergy:
221 9488 : CHECK_INIT(initialized,word);
222 9488 : CHECK_NOTNULL(val,word);
223 9488 : atoms.setEnergy(val);
224 : break;
225 : case cmd_setForces:
226 42333 : CHECK_INIT(initialized,word);
227 42333 : atoms.setForces(val);
228 : break;
229 : case cmd_setForcesX:
230 0 : CHECK_INIT(initialized,word);
231 0 : atoms.setForces(val,0);
232 : break;
233 : case cmd_setForcesY:
234 0 : CHECK_INIT(initialized,word);
235 0 : atoms.setForces(val,1);
236 : break;
237 : case cmd_setForcesZ:
238 0 : CHECK_INIT(initialized,word);
239 0 : atoms.setForces(val,2);
240 : break;
241 : case cmd_calc:
242 83583 : CHECK_INIT(initialized,word);
243 83583 : calc();
244 : break;
245 : case cmd_prepareDependencies:
246 87 : CHECK_INIT(initialized,word);
247 87 : prepareDependencies();
248 : break;
249 : case cmd_shareData:
250 72 : CHECK_INIT(initialized,word);
251 72 : shareData();
252 : break;
253 : case cmd_prepareCalc:
254 2060 : CHECK_INIT(initialized,word);
255 2060 : prepareCalc();
256 : break;
257 : case cmd_performCalc:
258 10 : CHECK_INIT(initialized,word);
259 10 : performCalc();
260 : break;
261 : case cmd_performCalcNoUpdate:
262 2122 : CHECK_INIT(initialized,word);
263 2122 : performCalcNoUpdate();
264 : break;
265 : case cmd_update:
266 67 : CHECK_INIT(initialized,word);
267 67 : update();
268 : break;
269 : case cmd_setStep:
270 9693 : CHECK_INIT(initialized,word);
271 9705 : CHECK_NOTNULL(val,word);
272 9690 : step=(*static_cast<int*>(val));
273 9690 : atoms.startStep();
274 : break;
275 : case cmd_setStepLong:
276 75995 : CHECK_INIT(initialized,word);
277 75995 : CHECK_NOTNULL(val,word);
278 75995 : step=(*static_cast<long int*>(val));
279 75995 : atoms.startStep();
280 : break;
281 : // words used less frequently:
282 : case cmd_setAtomsNlocal:
283 1128 : CHECK_INIT(initialized,word);
284 1128 : CHECK_NOTNULL(val,word);
285 1128 : atoms.setAtomsNlocal(*static_cast<int*>(val));
286 : break;
287 : case cmd_setAtomsGatindex:
288 976 : CHECK_INIT(initialized,word);
289 976 : atoms.setAtomsGatindex(static_cast<int*>(val),false);
290 : break;
291 : case cmd_setAtomsFGatindex:
292 0 : CHECK_INIT(initialized,word);
293 0 : atoms.setAtomsGatindex(static_cast<int*>(val),true);
294 : break;
295 : case cmd_setAtomsContiguous:
296 152 : CHECK_INIT(initialized,word);
297 152 : CHECK_NOTNULL(val,word);
298 152 : atoms.setAtomsContiguous(*static_cast<int*>(val));
299 : break;
300 : case cmd_createFullList:
301 104 : CHECK_INIT(initialized,word);
302 104 : CHECK_NOTNULL(val,word);
303 104 : atoms.createFullList(static_cast<int*>(val));
304 : break;
305 : case cmd_getFullList:
306 104 : CHECK_INIT(initialized,word);
307 104 : CHECK_NOTNULL(val,word);
308 104 : atoms.getFullList(static_cast<int**>(val));
309 : break;
310 : case cmd_clearFullList:
311 104 : CHECK_INIT(initialized,word);
312 104 : atoms.clearFullList();
313 : break;
314 : /* ADDED WITH API==6 */
315 : case cmd_getDataRank:
316 32 : CHECK_INIT(initialized,words[0]); plumed_assert(nw==2 || nw==3);
317 162 : if( nw==2 ) DataFetchingObject::get_rank( actionSet, words[1], "", static_cast<long*>(val) );
318 0 : else DataFetchingObject::get_rank( actionSet, words[1], words[2], static_cast<long*>(val) );
319 : break;
320 : /* ADDED WITH API==6 */
321 : case cmd_getDataShape:
322 0 : CHECK_INIT(initialized,words[0]); plumed_assert(nw==2 || nw==3);
323 66 : if( nw==2 ) DataFetchingObject::get_shape( actionSet, words[1], "", static_cast<long*>(val) );
324 0 : else DataFetchingObject::get_shape( actionSet, words[1], words[2], static_cast<long*>(val) );
325 : break;
326 : /* ADDED WITH API==6 */
327 : case cmd_setMemoryForData:
328 32 : CHECK_INIT(initialized,words[0]); plumed_assert(nw==2 || nw==3);
329 194 : if( nw==2 ) mydatafetcher->setData( words[1], "", val );
330 0 : else mydatafetcher->setData( words[1], words[2], val );
331 : break;
332 : /* ADDED WITH API==6 */
333 : case cmd_setErrorHandler:
334 : {
335 0 : if(val) error_handler=*static_cast<plumed_error_handler*>(val);
336 0 : else error_handler.handler=NULL;
337 : }
338 : break;
339 : case cmd_read:
340 0 : CHECK_INIT(initialized,word);
341 66 : if(val)readInputFile(static_cast<char*>(val));
342 66 : else readInputFile("plumed.dat");
343 : break;
344 : case cmd_readInputLine:
345 197 : CHECK_INIT(initialized,word);
346 197 : CHECK_NOTNULL(val,word);
347 460 : readInputLine(static_cast<char*>(val));
348 157 : break;
349 : case cmd_clear:
350 0 : CHECK_INIT(initialized,word);
351 0 : actionSet.clearDelete();
352 : break;
353 : case cmd_getApiVersion:
354 20 : CHECK_NOTNULL(val,word);
355 20 : *(static_cast<int*>(val))=6;
356 20 : break;
357 : // commands which can be used only before initialization:
358 : case cmd_init:
359 771 : CHECK_NOTINIT(initialized,word);
360 771 : init();
361 : break;
362 : case cmd_setRealPrecision:
363 664 : CHECK_NOTINIT(initialized,word);
364 664 : CHECK_NOTNULL(val,word);
365 664 : atoms.setRealPrecision(*static_cast<int*>(val));
366 1326 : mydatafetcher=DataFetchingObject::create(*static_cast<int*>(val),*this);
367 663 : break;
368 : case cmd_setMDLengthUnits:
369 620 : CHECK_NOTINIT(initialized,word);
370 620 : CHECK_NOTNULL(val,word);
371 620 : atoms.MD2double(val,d);
372 620 : atoms.setMDLengthUnits(d);
373 : break;
374 : case cmd_setMDChargeUnits:
375 620 : CHECK_NOTINIT(initialized,word);
376 620 : CHECK_NOTNULL(val,word);
377 620 : atoms.MD2double(val,d);
378 620 : atoms.setMDChargeUnits(d);
379 : break;
380 : case cmd_setMDMassUnits:
381 620 : CHECK_NOTINIT(initialized,word);
382 620 : CHECK_NOTNULL(val,word);
383 620 : atoms.MD2double(val,d);
384 620 : atoms.setMDMassUnits(d);
385 : break;
386 : case cmd_setMDEnergyUnits:
387 42 : CHECK_NOTINIT(initialized,word);
388 42 : CHECK_NOTNULL(val,word);
389 42 : atoms.MD2double(val,d);
390 42 : atoms.setMDEnergyUnits(d);
391 : break;
392 : case cmd_setMDTimeUnits:
393 5 : CHECK_NOTINIT(initialized,word);
394 5 : CHECK_NOTNULL(val,word);
395 5 : atoms.MD2double(val,d);
396 5 : atoms.setMDTimeUnits(d);
397 : break;
398 : case cmd_setNaturalUnits:
399 : // set the boltzman constant for MD in natural units (kb=1)
400 : // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...)
401 : // use as cmd("setNaturalUnits")
402 0 : CHECK_NOTINIT(initialized,word);
403 0 : atoms.setMDNaturalUnits(true);
404 : break;
405 : case cmd_setNoVirial:
406 48 : CHECK_NOTINIT(initialized,word);
407 48 : novirial=true;
408 48 : break;
409 : case cmd_setPlumedDat:
410 671 : CHECK_NOTINIT(initialized,word);
411 671 : CHECK_NOTNULL(val,word);
412 671 : plumedDat=static_cast<char*>(val);
413 : break;
414 : case cmd_setMPIComm:
415 293 : CHECK_NOTINIT(initialized,word);
416 293 : comm.Set_comm(val);
417 293 : atoms.setDomainDecomposition(comm);
418 : break;
419 : case cmd_setMPIFComm:
420 0 : CHECK_NOTINIT(initialized,word);
421 0 : comm.Set_fcomm(val);
422 0 : atoms.setDomainDecomposition(comm);
423 : break;
424 : case cmd_setMPImultiSimComm:
425 0 : CHECK_NOTINIT(initialized,word);
426 0 : multi_sim_comm.Set_comm(val);
427 : break;
428 : case cmd_setNatoms:
429 771 : CHECK_NOTINIT(initialized,word);
430 771 : CHECK_NOTNULL(val,word);
431 771 : atoms.setNatoms(*static_cast<int*>(val));
432 : break;
433 : case cmd_setTimestep:
434 671 : CHECK_NOTINIT(initialized,word);
435 671 : CHECK_NOTNULL(val,word);
436 671 : atoms.setTimeStep(val);
437 : break;
438 : /* ADDED WITH API==2 */
439 : case cmd_setKbT:
440 53 : CHECK_NOTINIT(initialized,word);
441 53 : CHECK_NOTNULL(val,word);
442 53 : atoms.setKbT(val);
443 : break;
444 : /* ADDED WITH API==3 */
445 : case cmd_setRestart:
446 5 : CHECK_NOTINIT(initialized,word);
447 5 : CHECK_NOTNULL(val,word);
448 5 : if(*static_cast<int*>(val)!=0) restart=true;
449 : break;
450 : /* ADDED WITH API==4 */
451 : case cmd_doCheckPoint:
452 0 : CHECK_INIT(initialized,word);
453 0 : CHECK_NOTNULL(val,word);
454 0 : doCheckPoint = false;
455 0 : if(*static_cast<int*>(val)!=0) doCheckPoint = true;
456 : break;
457 : /* ADDED WITH API==6 */
458 : case cmd_setNumOMPthreads:
459 0 : CHECK_NOTNULL(val,word);
460 0 : OpenMP::setNumThreads(*static_cast<int*>(val)>0?*static_cast<int*>(val):1);
461 : break;
462 : /* ADDED WITH API==6 */
463 : /* only used for testing */
464 : case cmd_throw:
465 18 : CHECK_NOTNULL(val,word);
466 18 : testThrow((const char*) val);
467 : /* STOP API */
468 : case cmd_setMDEngine:
469 668 : CHECK_NOTINIT(initialized,word);
470 668 : CHECK_NOTNULL(val,word);
471 668 : MDEngine=static_cast<char*>(val);
472 : break;
473 : case cmd_setLog:
474 657 : CHECK_NOTINIT(initialized,word);
475 657 : log.link(static_cast<FILE*>(val));
476 : break;
477 : case cmd_setLogFile:
478 45 : CHECK_NOTINIT(initialized,word);
479 45 : CHECK_NOTNULL(val,word);
480 156 : log.open(static_cast<char*>(val));
481 45 : break;
482 : // other commands that should be used after initialization:
483 : case cmd_setStopFlag:
484 83512 : CHECK_INIT(initialized,word);
485 83512 : CHECK_NOTNULL(val,word);
486 83512 : stopFlag=static_cast<int*>(val);
487 83512 : break;
488 : case cmd_getExchangesFlag:
489 0 : CHECK_INIT(initialized,word);
490 0 : CHECK_NOTNULL(val,word);
491 0 : exchangePatterns.getFlag((*static_cast<int*>(val)));
492 : break;
493 : case cmd_setExchangesSeed:
494 0 : CHECK_INIT(initialized,word);
495 0 : CHECK_NOTNULL(val,word);
496 0 : exchangePatterns.setSeed((*static_cast<int*>(val)));
497 : break;
498 : case cmd_setNumberOfReplicas:
499 0 : CHECK_INIT(initialized,word);
500 0 : CHECK_NOTNULL(val,word);
501 0 : exchangePatterns.setNofR((*static_cast<int*>(val)));
502 : break;
503 : case cmd_getExchangesList:
504 0 : CHECK_INIT(initialized,word);
505 0 : CHECK_NOTNULL(val,word);
506 0 : exchangePatterns.getList((static_cast<int*>(val)));
507 : break;
508 : case cmd_runFinalJobs:
509 624 : CHECK_INIT(initialized,word);
510 624 : runJobsAtEndOfCalculation();
511 : break;
512 : case cmd_isEnergyNeeded:
513 77 : CHECK_INIT(initialized,word);
514 77 : CHECK_NOTNULL(val,word);
515 154 : if(atoms.isEnergyNeeded()) *(static_cast<int*>(val))=1;
516 77 : else *(static_cast<int*>(val))=0;
517 : break;
518 : case cmd_getBias:
519 2132 : CHECK_INIT(initialized,word);
520 2132 : CHECK_NOTNULL(val,word);
521 2198 : atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val);
522 2132 : break;
523 : case cmd_checkAction:
524 0 : CHECK_NOTNULL(val,word);
525 0 : plumed_assert(nw==2);
526 0 : *(static_cast<int*>(val))=(actionRegister().check(words[1]) ? 1:0);
527 0 : break;
528 : case cmd_setExtraCV:
529 20 : CHECK_NOTNULL(val,word);
530 20 : plumed_assert(nw==2);
531 20 : atoms.setExtraCV(words[1],val);
532 : break;
533 : case cmd_setExtraCVForce:
534 20 : CHECK_NOTNULL(val,word);
535 20 : plumed_assert(nw==2);
536 20 : atoms.setExtraCVForce(words[1],val);
537 : break;
538 : case cmd_GREX:
539 1023 : if(!grex) grex.reset(new GREX(*this));
540 1023 : plumed_massert(grex,"error allocating grex");
541 : {
542 1023 : std::string kk=words[1];
543 1536 : for(unsigned i=2; i<words.size(); i++) kk+=" "+words[i];
544 3069 : grex->cmd(kk.c_str(),val);
545 : }
546 1023 : break;
547 : case cmd_CLTool:
548 6242 : CHECK_NOTINIT(initialized,word);
549 6242 : if(!cltool) cltool.reset(new CLToolMain);
550 : {
551 6242 : std::string kk=words[1];
552 6242 : for(unsigned i=2; i<words.size(); i++) kk+=" "+words[i];
553 18726 : cltool->cmd(kk.c_str(),val);
554 : }
555 6242 : break;
556 : case cmd_convert:
557 : {
558 : double v;
559 0 : plumed_assert(words.size()==2);
560 0 : if(Tools::convert(words[1],v)) atoms.double2MD(v,val);
561 : }
562 0 : break;
563 : default:
564 5 : plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands.");
565 : break;
566 : }
567 517989 : }
568 :
569 66 : } catch (std::exception &e) {
570 66 : if(log.isOpen()) {
571 47 : log<<"\n\n################################################################################\n\n";
572 113 : log<<e.what();
573 47 : log<<"\n\n################################################################################\n\n";
574 47 : log.flush();
575 : }
576 66 : throw;
577 : }
578 517923 : }
579 :
580 : ////////////////////////////////////////////////////////////////////////
581 :
582 771 : void PlumedMain::init() {
583 : // check that initialization just happens once
584 771 : initialized=true;
585 771 : atoms.init();
586 771 : if(!log.isOpen()) log.link(stdout);
587 771 : log<<"PLUMED is starting\n";
588 2313 : log<<"Version: "<<config::getVersionLong()<<" (git: "<<config::getVersionGit()<<") "
589 3084 : <<"compiled on " <<config::getCompilationDate() << " at " << config::getCompilationTime() << "\n";
590 771 : log<<"Please cite this paper when using PLUMED ";
591 2313 : log<<cite("Tribello, Bonomi, Branduardi, Camilloni, and Bussi, Comput. Phys. Commun. 185, 604 (2014)");
592 771 : log<<"\n";
593 771 : log<<"For further information see the PLUMED web page at http://www.plumed.org\n";
594 1542 : log<<"Root: "<<config::getPlumedRoot()<<"\n";
595 3084 : log<<"For installed feature, see "<<config::getPlumedRoot() + "/src/config/config.txt\n";
596 771 : log.printf("Molecular dynamics engine: %s\n",MDEngine.c_str());
597 771 : log.printf("Precision of reals: %d\n",atoms.getRealPrecision());
598 771 : log.printf("Running over %d %s\n",comm.Get_size(),(comm.Get_size()>1?"nodes":"node"));
599 771 : log<<"Number of threads: "<<OpenMP::getNumThreads()<<"\n";
600 771 : log<<"Cache line size: "<<OpenMP::getCachelineSize()<<"\n";
601 1542 : log.printf("Number of atoms: %d\n",atoms.getNatoms());
602 771 : if(grex) log.printf("GROMACS-like replica exchange is on\n");
603 771 : log.printf("File suffix: %s\n",getSuffix().c_str());
604 771 : if(plumedDat.length()>0) {
605 1342 : readInputFile(plumedDat);
606 : plumedDat="";
607 : }
608 771 : atoms.updateUnits();
609 771 : log.printf("Timestep: %f\n",atoms.getTimeStep());
610 771 : if(atoms.getKbT()>0.0)
611 48 : log.printf("KbT: %f\n",atoms.getKbT());
612 : else {
613 723 : log.printf("KbT has not been set by the MD engine\n");
614 723 : log.printf("It should be set by hand where needed\n");
615 : }
616 771 : log<<"Relevant bibliography:\n";
617 771 : log<<citations;
618 771 : log<<"Please read and cite where appropriate!\n";
619 771 : log<<"Finished setup\n";
620 771 : }
621 :
622 685 : void PlumedMain::readInputFile(std::string str) {
623 685 : plumed_assert(initialized);
624 685 : log.printf("FILE: %s\n",str.c_str());
625 685 : IFile ifile;
626 685 : ifile.link(*this);
627 685 : ifile.open(str);
628 685 : ifile.allowNoEOL();
629 685 : std::vector<std::string> words;
630 5934 : while(Tools::getParsedLine(ifile,words) && !endPlumed) readInputWords(words);
631 685 : endPlumed=false;
632 685 : log.printf("END FILE: %s\n",str.c_str());
633 685 : log.flush();
634 :
635 2055 : pilots=actionSet.select<ActionPilot*>();
636 685 : }
637 :
638 276 : void PlumedMain::readInputLine(const std::string & str) {
639 276 : plumed_assert(initialized);
640 276 : if(str.empty()) return;
641 276 : std::vector<std::string> words=Tools::getWords(str);
642 276 : citations.clear();
643 276 : readInputWords(words);
644 236 : if(!citations.empty()) {
645 4 : log<<"Relevant bibliography:\n";
646 4 : log<<citations;
647 4 : log<<"Please read and cite where appropriate!\n";
648 276 : }
649 : }
650 :
651 6231 : void PlumedMain::readInputWords(const std::vector<std::string> & words) {
652 6231 : plumed_assert(initialized);
653 12422 : if(words.empty())return;
654 6231 : else if(words[0]=="_SET_SUFFIX") {
655 3 : plumed_assert(words.size()==2);
656 3 : setSuffix(words[1]);
657 : } else {
658 6228 : std::vector<std::string> interpreted(words);
659 6228 : Tools::interpretLabel(interpreted);
660 12456 : auto action=actionRegister().create(ActionOptions(*this,interpreted));
661 6190 : if(!action) {
662 : std::string msg;
663 : msg ="ERROR\nI cannot understand line:";
664 20 : for(unsigned i=0; i<interpreted.size(); ++i) msg+=" "+interpreted[i];
665 : msg+="\nMaybe a missing space or a typo?";
666 2 : log << msg;
667 2 : log.flush();
668 6 : plumed_merror(msg);
669 : };
670 6188 : action->checkRead();
671 12416 : actionSet.emplace_back(std::move(action));
672 : };
673 :
674 12382 : pilots=actionSet.select<ActionPilot*>();
675 : }
676 :
677 : ////////////////////////////////////////////////////////////////////////
678 :
679 0 : void PlumedMain::exit(int c) {
680 0 : comm.Abort(c);
681 0 : }
682 :
683 6226 : Log& PlumedMain::getLog() {
684 6226 : return log;
685 : }
686 :
687 83583 : void PlumedMain::calc() {
688 83583 : prepareCalc();
689 83583 : performCalc();
690 83583 : }
691 :
692 85643 : void PlumedMain::prepareCalc() {
693 85643 : prepareDependencies();
694 85643 : shareData();
695 85643 : }
696 :
697 : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
698 : // here we have the main steps in "calc()"
699 : // they can be called individually, but the standard thing is to
700 : // traverse them in this order:
701 85958 : void PlumedMain::prepareDependencies() {
702 :
703 : // Stopwatch is stopped when sw goes out of scope
704 171916 : auto sw=stopwatch.startStop("1 Prepare dependencies");
705 :
706 : // activate all the actions which are on step
707 : // activation is recursive and enables also the dependencies
708 : // before doing that, the prepare() method is called to see if there is some
709 : // new/changed dependency (up to now, only useful for dependences on virtual atoms,
710 : // which can be dynamically changed).
711 :
712 : // First switch off all actions
713 966762 : for(const auto & p : actionSet) {
714 708888 : p->deactivate();
715 : }
716 :
717 : // for optimization, an "active" flag remains false if no action at all is active
718 85958 : active=mydatafetcher->activate();
719 924120 : for(unsigned i=0; i<pilots.size(); ++i) {
720 376102 : if(pilots[i]->onStep()) {
721 292721 : pilots[i]->activate();
722 292721 : active=true;
723 : }
724 : };
725 :
726 : // also, if one of them is the total energy, tell to atoms that energy should be collected
727 966762 : for(const auto & p : actionSet) {
728 708888 : if(p->isActive()) {
729 456492 : if(p->checkNeedsGradients()) p->setOption("GRADIENTS");
730 : }
731 85958 : }
732 :
733 85958 : }
734 :
735 85715 : void PlumedMain::shareData() {
736 : // atom positions are shared (but only if there is something to do)
737 87203 : if(!active)return;
738 : // Stopwatch is stopped when sw goes out of scope
739 168454 : auto sw=stopwatch.startStop("2 Sharing data");
740 168454 : if(atoms.getNatoms()>0) atoms.share();
741 : }
742 :
743 2122 : void PlumedMain::performCalcNoUpdate() {
744 2122 : waitData();
745 2122 : justCalculate();
746 2122 : backwardPropagate();
747 2122 : }
748 :
749 83593 : void PlumedMain::performCalc() {
750 83593 : waitData();
751 83593 : justCalculate();
752 83593 : backwardPropagate();
753 83593 : update();
754 83593 : mydatafetcher->finishDataGrab();
755 83593 : }
756 :
757 85829 : void PlumedMain::waitData() {
758 87317 : if(!active)return;
759 : // Stopwatch is stopped when sw goes out of scope
760 168682 : auto sw=stopwatch.startStop("3 Waiting for data");
761 168682 : if(atoms.getNatoms()>0) atoms.wait();
762 : }
763 :
764 85829 : void PlumedMain::justCalculate() {
765 87317 : if(!active)return;
766 : // Stopwatch is stopped when sw goes out of scope
767 168682 : auto sw=stopwatch.startStop("4 Calculating (forward loop)");
768 84341 : bias=0.0;
769 84341 : work=0.0;
770 :
771 : int iaction=0;
772 : // calculate the active actions in order (assuming *backward* dependence)
773 952467 : for(const auto & pp : actionSet) {
774 : Action* p(pp.get());
775 699444 : if(p->isActive()) {
776 : // Stopwatch is stopped when sw goes out of scope.
777 : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
778 455250 : Stopwatch::Handler sw;
779 455250 : if(detailedTimers) {
780 : std::string actionNumberLabel;
781 1690 : Tools::convert(iaction,actionNumberLabel);
782 3380 : const unsigned m=actionSet.size();
783 1690 : unsigned k=0; unsigned n=1; while(n<m) { n*=10; k++; }
784 1690 : const int pad=k-actionNumberLabel.length();
785 2820 : for(int i=0; i<pad; i++) actionNumberLabel=" "+actionNumberLabel;
786 8450 : sw=stopwatch.startStop("4A "+actionNumberLabel+" "+p->getLabel());
787 : }
788 455250 : ActionWithValue*av=dynamic_cast<ActionWithValue*>(p);
789 455250 : ActionAtomistic*aa=dynamic_cast<ActionAtomistic*>(p);
790 : {
791 455250 : if(av) av->clearInputForces();
792 455250 : if(av) av->clearDerivatives();
793 : }
794 : {
795 455250 : if(aa) aa->clearOutputForces();
796 595399 : if(aa) if(aa->isActive()) aa->retrieveAtoms();
797 : }
798 455250 : if(p->checkNumericalDerivatives()) p->calculateNumericalDerivatives();
799 454703 : else p->calculate();
800 : // This retrieves components called bias
801 844876 : if(av) bias+=av->getOutputQuantity("bias");
802 844876 : if(av) work+=av->getOutputQuantity("work");
803 455250 : if(av)av->setGradientsIfNeeded();
804 455250 : ActionWithVirtualAtom*avv=dynamic_cast<ActionWithVirtualAtom*>(p);
805 455250 : if(avv)avv->setGradientsIfNeeded();
806 : }
807 699444 : iaction++;
808 84341 : }
809 : }
810 :
811 0 : void PlumedMain::justApply() {
812 0 : backwardPropagate();
813 0 : update();
814 0 : }
815 :
816 85715 : void PlumedMain::backwardPropagate() {
817 87203 : if(!active)return;
818 : int iaction=0;
819 : // Stopwatch is stopped when sw goes out of scope
820 168454 : auto sw=stopwatch.startStop("5 Applying (backward loop)");
821 : // apply them in reverse order
822 1649865 : for(auto pp=actionSet.rbegin(); pp!=actionSet.rend(); ++pp) {
823 698592 : const auto & p(pp->get());
824 698592 : if(p->isActive()) {
825 :
826 : // Stopwatch is stopped when sw goes out of scope.
827 : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
828 454578 : Stopwatch::Handler sw;
829 454578 : if(detailedTimers) {
830 : std::string actionNumberLabel;
831 1690 : Tools::convert(iaction,actionNumberLabel);
832 3380 : const unsigned m=actionSet.size();
833 1690 : unsigned k=0; unsigned n=1; while(n<m) { n*=10; k++; }
834 1690 : const int pad=k-actionNumberLabel.length();
835 2815 : for(int i=0; i<pad; i++) actionNumberLabel=" "+actionNumberLabel;
836 8450 : sw=stopwatch.startStop("5A "+actionNumberLabel+" "+p->getLabel());
837 : }
838 :
839 454578 : p->apply();
840 454578 : ActionAtomistic*a=dynamic_cast<ActionAtomistic*>(p);
841 : // still ActionAtomistic has a special treatment, since they may need to add forces on atoms
842 454578 : if(a) a->applyForces();
843 :
844 : }
845 698592 : iaction++;
846 : }
847 :
848 : // Stopwatch is stopped when sw goes out of scope.
849 : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
850 168454 : Stopwatch::Handler sw1;
851 84340 : if(detailedTimers) sw1=stopwatch.startStop("5B Update forces");
852 : // this is updating the MD copy of the forces
853 252681 : if(atoms.getNatoms()>0) atoms.updateForces();
854 : }
855 :
856 83660 : void PlumedMain::update() {
857 85148 : if(!active)return;
858 :
859 : // Stopwatch is stopped when sw goes out of scope
860 164344 : auto sw=stopwatch.startStop("6 Update");
861 :
862 : // update step (for statistics, etc)
863 164344 : updateFlags.push(true);
864 938641 : for(const auto & p : actionSet) {
865 692125 : p->beforeUpdate();
866 1587587 : if(p->isActive() && p->checkUpdate() && updateFlagsTop()) p->update();
867 : }
868 164348 : while(!updateFlags.empty()) updateFlags.pop();
869 82172 : if(!updateFlags.empty()) plumed_merror("non matching changes in the update flags");
870 : // Check that no action has told the calculation to stop
871 82172 : if(stopNow) {
872 55 : if(stopFlag) (*stopFlag)=1;
873 0 : else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)");
874 : }
875 :
876 : // flush by default every 10000 steps
877 : // hopefully will not affect performance
878 : // also if receive checkpointing signal
879 82172 : if(step%10000==0||doCheckPoint) {
880 767 : fflush();
881 767 : log.flush();
882 15413 : for(const auto & p : actionSet) p->fflush();
883 82172 : }
884 : }
885 :
886 2 : void PlumedMain::load(const std::string& ss) {
887 2 : if(DLLoader::installed()) {
888 2 : std::string s=ss;
889 2 : size_t n=s.find_last_of(".");
890 3 : std::string extension="";
891 2 : std::string base=s;
892 6 : if(n!=std::string::npos && n<s.length()-1) extension=s.substr(n+1);
893 6 : if(n!=std::string::npos && n<s.length()) base=s.substr(0,n);
894 2 : if(extension=="cpp") {
895 : // full path command, including environment setup
896 : // this will work even if plumed is not in the execution path or if it has been
897 : // installed with a name different from "plumed"
898 14 : std::string cmd=config::getEnvCommand()+" \""+config::getPlumedRoot()+"\"/scripts/mklib.sh "+s;
899 2 : log<<"Executing: "<<cmd;
900 2 : if(comm.Get_size()>0) log<<" (only on master node)";
901 2 : log<<"\n";
902 4 : if(comm.Get_rank()==0) system(cmd.c_str());
903 2 : comm.Barrier();
904 4 : base="./"+base;
905 : }
906 8 : s=base+"."+config::getSoExt();
907 2 : void *p=dlloader.load(s);
908 2 : if(!p) {
909 3 : const std::string error_msg="I cannot load library " + ss + " " + dlloader.error();
910 1 : log<<"ERROR\n";
911 1 : log<<error_msg<<"\n";
912 3 : plumed_merror(error_msg);
913 : }
914 2 : log<<"Loading shared library "<<s.c_str()<<"\n";
915 1 : log<<"Here is the new list of available actions\n";
916 1 : log<<actionRegister();
917 0 : } else plumed_merror("loading not enabled, please recompile with -D__PLUMED_HAS_DLOPEN");
918 1 : }
919 :
920 2765 : double PlumedMain::getBias() const {
921 2765 : return bias;
922 : }
923 :
924 450 : double PlumedMain::getWork() const {
925 450 : return work;
926 : }
927 :
928 73 : FILE* PlumedMain::fopen(const char *path, const char *mode) {
929 73 : std::string mmode(mode);
930 73 : std::string ppath(path);
931 73 : std::string suffix(getSuffix());
932 73 : std::string ppathsuf=ppath+suffix;
933 73 : FILE*fp=std::fopen(const_cast<char*>(ppathsuf.c_str()),const_cast<char*>(mmode.c_str()));
934 73 : if(!fp) fp=std::fopen(const_cast<char*>(ppath.c_str()),const_cast<char*>(mmode.c_str()));
935 73 : plumed_massert(fp,"file " + ppath + " cannot be found");
936 73 : return fp;
937 : }
938 :
939 91 : int PlumedMain::fclose(FILE*fp) {
940 91 : return std::fclose(fp);
941 : }
942 :
943 2289 : std::string PlumedMain::cite(const std::string&item) {
944 2289 : return citations.cite(item);
945 : }
946 :
947 1328 : void PlumedMain::fflush() {
948 5519 : for(const auto & p : files) {
949 2863 : p->flush();
950 : }
951 1328 : }
952 :
953 3985 : void PlumedMain::insertFile(FileBase&f) {
954 7970 : files.insert(&f);
955 3985 : }
956 :
957 4259 : void PlumedMain::eraseFile(FileBase&f) {
958 8518 : files.erase(&f);
959 4259 : }
960 :
961 55 : void PlumedMain::stop() {
962 55 : stopNow=true;
963 55 : }
964 :
965 624 : void PlumedMain::runJobsAtEndOfCalculation() {
966 7650 : for(const auto & p : actionSet) {
967 5778 : p->runFinalJobs();
968 : }
969 624 : }
970 :
971 : #ifdef __PLUMED_HAS_PYTHON
972 : // This is here to stop cppcheck throwing an error
973 : #endif
974 :
975 5874 : }
976 :
977 : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|