Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2011-2018 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 "tools/Tools.h"
24 : #include "tools/OpenMP.h"
25 : #include <cstring>
26 : #include "ActionPilot.h"
27 : #include "ActionWithValue.h"
28 : #include "ActionAtomistic.h"
29 : #include "ActionWithVirtualAtom.h"
30 : #include "Atoms.h"
31 : #include <set>
32 : #include "config/Config.h"
33 : #include <cstdlib>
34 : #include "ActionRegister.h"
35 : #include "GREX.h"
36 : #include "tools/Exception.h"
37 : #include "Atoms.h"
38 : #include "ActionSet.h"
39 : #include "tools/Log.h"
40 : #include "tools/DLLoader.h"
41 : #include "tools/Communicator.h"
42 : #include "CLToolMain.h"
43 : #include "tools/Stopwatch.h"
44 : #include "tools/Citations.h"
45 : #include "ExchangePatterns.h"
46 : #include "tools/IFile.h"
47 :
48 : using namespace std;
49 :
50 : #include "PlumedMainEnum.inc"
51 :
52 : namespace PLMD {
53 :
54 390586 : std::map<std::string, int> & plumedMainWordMap() {
55 390586 : static std::map<std::string, int> word_map;
56 : static bool init=false;
57 390586 : if(!init) {
58 : #include "PlumedMainMap.inc"
59 : }
60 390586 : init=true;
61 390586 : return word_map;
62 : }
63 :
64 1159 : PlumedMain::PlumedMain():
65 1159 : comm(*new Communicator),
66 1159 : multi_sim_comm(*new Communicator),
67 1159 : dlloader(*new DLLoader),
68 : cltool(NULL),
69 1159 : stopwatch(*new Stopwatch),
70 : grex(NULL),
71 : initialized(false),
72 1159 : log(*new Log),
73 1159 : citations(*new Citations),
74 : step(0),
75 : active(false),
76 1159 : atoms(*new Atoms(*this)),
77 1159 : actionSet(*new ActionSet(*this)),
78 : bias(0.0),
79 : work(0.0),
80 1159 : exchangePatterns(*new(ExchangePatterns)),
81 : exchangeStep(false),
82 : restart(false),
83 : doCheckPoint(false),
84 : stopFlag(NULL),
85 : stopNow(false),
86 : novirial(false),
87 11590 : detailedTimers(false)
88 : {
89 1159 : log.link(comm);
90 1159 : log.setLinePrefix("PLUMED: ");
91 1159 : stopwatch.start();
92 1159 : stopwatch.pause();
93 1159 : }
94 :
95 3470 : PlumedMain::~PlumedMain() {
96 1159 : stopwatch.start();
97 1159 : stopwatch.stop();
98 1159 : if(initialized) log<<stopwatch;
99 1159 : delete &exchangePatterns;
100 1159 : delete &actionSet;
101 1159 : delete &citations;
102 1159 : delete &atoms;
103 1159 : delete &log;
104 1159 : if(grex) delete grex;
105 1159 : delete &stopwatch;
106 1159 : if(cltool) delete cltool;
107 1159 : delete &dlloader;
108 1159 : delete &comm;
109 1159 : delete &multi_sim_comm;
110 2311 : }
111 :
112 : /////////////////////////////////////////////////////////////
113 : // MAIN INTERPRETER
114 :
115 : #define CHECK_INIT(ini,word) plumed_massert(ini,"cmd(\"" + word +"\") should be only used after plumed initialization")
116 : #define CHECK_NOTINIT(ini,word) plumed_massert(!(ini),"cmd(\"" + word +"\") should be only used before plumed initialization")
117 : #define CHECK_NOTNULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"" + word + "\")");
118 :
119 :
120 195293 : void PlumedMain::cmd(const std::string & word,void*val) {
121 :
122 195293 : stopwatch.start();
123 :
124 195293 : std::vector<std::string> words=Tools::getWords(word);
125 195293 : unsigned nw=words.size();
126 195293 : if(nw==0) {
127 : // do nothing
128 : } else {
129 195293 : int iword=-1;
130 : double d;
131 195293 : std::map<std::string, int>::const_iterator it=plumedMainWordMap().find(words[0]);
132 195293 : if(it!=plumedMainWordMap().end()) iword=it->second;
133 195293 : switch(iword) {
134 : case cmd_setBox:
135 20963 : CHECK_INIT(initialized,word);
136 20963 : CHECK_NOTNULL(val,word);
137 20963 : atoms.setBox(val);
138 20963 : break;
139 : case cmd_setPositions:
140 20991 : CHECK_INIT(initialized,word);
141 20991 : atoms.setPositions(val);
142 20991 : break;
143 : case cmd_setMasses:
144 20991 : CHECK_INIT(initialized,word);
145 20991 : atoms.setMasses(val);
146 20991 : break;
147 : case cmd_setCharges:
148 18773 : CHECK_INIT(initialized,word);
149 18773 : atoms.setCharges(val);
150 18773 : break;
151 : case cmd_setPositionsX:
152 0 : CHECK_INIT(initialized,word);
153 0 : atoms.setPositions(val,0);
154 0 : break;
155 : case cmd_setPositionsY:
156 0 : CHECK_INIT(initialized,word);
157 0 : atoms.setPositions(val,1);
158 0 : break;
159 : case cmd_setPositionsZ:
160 0 : CHECK_INIT(initialized,word);
161 0 : atoms.setPositions(val,2);
162 0 : break;
163 : case cmd_setVirial:
164 18841 : CHECK_INIT(initialized,word);
165 18841 : CHECK_NOTNULL(val,word);
166 18841 : atoms.setVirial(val);
167 18841 : break;
168 : case cmd_setEnergy:
169 2150 : CHECK_INIT(initialized,word);
170 2150 : CHECK_NOTNULL(val,word);
171 2150 : atoms.setEnergy(val);
172 2150 : break;
173 : case cmd_setForces:
174 20991 : CHECK_INIT(initialized,word);
175 20991 : atoms.setForces(val);
176 20991 : break;
177 : case cmd_setForcesX:
178 0 : CHECK_INIT(initialized,word);
179 0 : atoms.setForces(val,0);
180 0 : break;
181 : case cmd_setForcesY:
182 0 : CHECK_INIT(initialized,word);
183 0 : atoms.setForces(val,1);
184 0 : break;
185 : case cmd_setForcesZ:
186 0 : CHECK_INIT(initialized,word);
187 0 : atoms.setForces(val,2);
188 0 : break;
189 : case cmd_calc:
190 21467 : CHECK_INIT(initialized,word);
191 21467 : calc();
192 21467 : break;
193 : case cmd_prepareDependencies:
194 0 : CHECK_INIT(initialized,word);
195 0 : prepareDependencies();
196 0 : break;
197 : case cmd_shareData:
198 0 : CHECK_INIT(initialized,word);
199 0 : shareData();
200 0 : break;
201 : case cmd_prepareCalc:
202 80 : CHECK_INIT(initialized,word);
203 80 : prepareCalc();
204 80 : break;
205 : case cmd_performCalc:
206 0 : CHECK_INIT(initialized,word);
207 0 : performCalc();
208 0 : break;
209 : case cmd_performCalcNoUpdate:
210 80 : CHECK_INIT(initialized,word);
211 80 : performCalcNoUpdate();
212 80 : break;
213 : case cmd_update:
214 10 : CHECK_INIT(initialized,word);
215 10 : update();
216 10 : break;
217 : case cmd_setStep:
218 2218 : CHECK_INIT(initialized,word);
219 2218 : CHECK_NOTNULL(val,word);
220 2218 : step=(*static_cast<int*>(val));
221 2218 : atoms.startStep();
222 2218 : break;
223 : case cmd_setStepLong:
224 19319 : CHECK_INIT(initialized,word);
225 19319 : CHECK_NOTNULL(val,word);
226 19319 : step=(*static_cast<long int*>(val));
227 19319 : atoms.startStep();
228 19319 : break;
229 : // words used less frequently:
230 : case cmd_setAtomsNlocal:
231 150 : CHECK_INIT(initialized,word);
232 150 : CHECK_NOTNULL(val,word);
233 150 : atoms.setAtomsNlocal(*static_cast<int*>(val));
234 150 : break;
235 : case cmd_setAtomsGatindex:
236 134 : CHECK_INIT(initialized,word);
237 134 : atoms.setAtomsGatindex(static_cast<int*>(val),false);
238 134 : break;
239 : case cmd_setAtomsFGatindex:
240 0 : CHECK_INIT(initialized,word);
241 0 : atoms.setAtomsGatindex(static_cast<int*>(val),true);
242 0 : break;
243 : case cmd_setAtomsContiguous:
244 16 : CHECK_INIT(initialized,word);
245 16 : CHECK_NOTNULL(val,word);
246 16 : atoms.setAtomsContiguous(*static_cast<int*>(val));
247 16 : break;
248 : case cmd_createFullList:
249 5 : CHECK_INIT(initialized,word);
250 5 : CHECK_NOTNULL(val,word);
251 5 : atoms.createFullList(static_cast<int*>(val));
252 5 : break;
253 : case cmd_getFullList:
254 5 : CHECK_INIT(initialized,word);
255 5 : CHECK_NOTNULL(val,word);
256 5 : atoms.getFullList(static_cast<int**>(val));
257 5 : break;
258 : case cmd_clearFullList:
259 5 : CHECK_INIT(initialized,word);
260 5 : atoms.clearFullList();
261 5 : break;
262 : case cmd_read:
263 0 : CHECK_INIT(initialized,word);
264 0 : if(val)readInputFile(static_cast<char*>(val));
265 0 : else readInputFile("plumed.dat");
266 0 : break;
267 : case cmd_readInputLine:
268 62 : CHECK_INIT(initialized,word);
269 62 : CHECK_NOTNULL(val,word);
270 62 : readInputLine(static_cast<char*>(val));
271 62 : break;
272 : case cmd_clear:
273 0 : CHECK_INIT(initialized,word);
274 0 : actionSet.clearDelete();
275 0 : break;
276 : case cmd_getApiVersion:
277 4 : CHECK_NOTNULL(val,word);
278 4 : *(static_cast<int*>(val))=4;
279 4 : break;
280 : // commands which can be used only before initialization:
281 : case cmd_init:
282 331 : CHECK_NOTINIT(initialized,word);
283 331 : init();
284 331 : break;
285 : case cmd_setRealPrecision:
286 292 : CHECK_NOTINIT(initialized,word);
287 292 : CHECK_NOTNULL(val,word);
288 292 : atoms.setRealPrecision(*static_cast<int*>(val));
289 292 : break;
290 : case cmd_setMDLengthUnits:
291 288 : CHECK_NOTINIT(initialized,word);
292 288 : CHECK_NOTNULL(val,word);
293 288 : atoms.MD2double(val,d);
294 288 : atoms.setMDLengthUnits(d);
295 288 : break;
296 : case cmd_setMDChargeUnits:
297 288 : CHECK_NOTINIT(initialized,word);
298 288 : CHECK_NOTNULL(val,word);
299 288 : atoms.MD2double(val,d);
300 288 : atoms.setMDChargeUnits(d);
301 288 : break;
302 : case cmd_setMDMassUnits:
303 288 : CHECK_NOTINIT(initialized,word);
304 288 : CHECK_NOTNULL(val,word);
305 288 : atoms.MD2double(val,d);
306 288 : atoms.setMDMassUnits(d);
307 288 : break;
308 : case cmd_setMDEnergyUnits:
309 0 : CHECK_NOTINIT(initialized,word);
310 0 : CHECK_NOTNULL(val,word);
311 0 : atoms.MD2double(val,d);
312 0 : atoms.setMDEnergyUnits(d);
313 0 : break;
314 : case cmd_setMDTimeUnits:
315 0 : CHECK_NOTINIT(initialized,word);
316 0 : CHECK_NOTNULL(val,word);
317 0 : atoms.MD2double(val,d);
318 0 : atoms.setMDTimeUnits(d);
319 0 : break;
320 : case cmd_setNaturalUnits:
321 : // set the boltzman constant for MD in natural units (kb=1)
322 : // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...)
323 : // use as cmd("setNaturalUnits")
324 0 : CHECK_NOTINIT(initialized,word);
325 0 : atoms.setMDNaturalUnits(true);
326 0 : break;
327 : case cmd_setNoVirial:
328 4 : CHECK_NOTINIT(initialized,word);
329 4 : novirial=true;
330 4 : break;
331 : case cmd_setPlumedDat:
332 295 : CHECK_NOTINIT(initialized,word);
333 295 : CHECK_NOTNULL(val,word);
334 295 : plumedDat=static_cast<char*>(val);
335 295 : break;
336 : case cmd_setMPIComm:
337 115 : CHECK_NOTINIT(initialized,word);
338 115 : comm.Set_comm(val);
339 115 : atoms.setDomainDecomposition(comm);
340 115 : break;
341 : case cmd_setMPIFComm:
342 0 : CHECK_NOTINIT(initialized,word);
343 0 : comm.Set_fcomm(val);
344 0 : atoms.setDomainDecomposition(comm);
345 0 : break;
346 : case cmd_setMPImultiSimComm:
347 0 : CHECK_NOTINIT(initialized,word);
348 0 : multi_sim_comm.Set_comm(val);
349 0 : break;
350 : case cmd_setNatoms:
351 331 : CHECK_NOTINIT(initialized,word);
352 331 : CHECK_NOTNULL(val,word);
353 331 : atoms.setNatoms(*static_cast<int*>(val));
354 331 : break;
355 : case cmd_setTimestep:
356 292 : CHECK_NOTINIT(initialized,word);
357 292 : CHECK_NOTNULL(val,word);
358 292 : atoms.setTimeStep(val);
359 292 : break;
360 : /* ADDED WITH API==2 */
361 : case cmd_setKbT:
362 4 : CHECK_NOTINIT(initialized,word);
363 4 : CHECK_NOTNULL(val,word);
364 4 : atoms.setKbT(val);
365 4 : break;
366 : /* ADDED WITH API==3 */
367 : case cmd_setRestart:
368 0 : CHECK_NOTINIT(initialized,word);
369 0 : CHECK_NOTNULL(val,word);
370 0 : if(*static_cast<int*>(val)!=0) restart=true;
371 0 : break;
372 : /* ADDED WITH API==4 */
373 : case cmd_doCheckPoint:
374 0 : CHECK_INIT(initialized,word);
375 0 : CHECK_NOTNULL(val,word);
376 0 : doCheckPoint = false;
377 0 : if(*static_cast<int*>(val)!=0) doCheckPoint = true;
378 0 : break;
379 : /* STOP API */
380 : case cmd_setMDEngine:
381 292 : CHECK_NOTINIT(initialized,word);
382 292 : CHECK_NOTNULL(val,word);
383 292 : MDEngine=static_cast<char*>(val);
384 292 : break;
385 : case cmd_setLog:
386 288 : CHECK_NOTINIT(initialized,word);
387 288 : log.link(static_cast<FILE*>(val));
388 288 : break;
389 : case cmd_setLogFile:
390 4 : CHECK_NOTINIT(initialized,word);
391 4 : CHECK_NOTNULL(val,word);
392 4 : log.open(static_cast<char*>(val));
393 4 : break;
394 : // other commands that should be used after initialization:
395 : case cmd_setStopFlag:
396 21409 : CHECK_INIT(initialized,word);
397 21409 : CHECK_NOTNULL(val,word);
398 21409 : stopFlag=static_cast<int*>(val);
399 21409 : break;
400 : case cmd_getExchangesFlag:
401 0 : CHECK_INIT(initialized,word);
402 0 : CHECK_NOTNULL(val,word);
403 0 : exchangePatterns.getFlag((*static_cast<int*>(val)));
404 0 : break;
405 : case cmd_setExchangesSeed:
406 0 : CHECK_INIT(initialized,word);
407 0 : CHECK_NOTNULL(val,word);
408 0 : exchangePatterns.setSeed((*static_cast<int*>(val)));
409 0 : break;
410 : case cmd_setNumberOfReplicas:
411 0 : CHECK_INIT(initialized,word);
412 0 : CHECK_NOTNULL(val,word);
413 0 : exchangePatterns.setNofR((*static_cast<int*>(val)));
414 0 : break;
415 : case cmd_getExchangesList:
416 0 : CHECK_INIT(initialized,word);
417 0 : CHECK_NOTNULL(val,word);
418 0 : exchangePatterns.getList((static_cast<int*>(val)));
419 0 : break;
420 : case cmd_runFinalJobs:
421 288 : CHECK_INIT(initialized,word);
422 288 : runJobsAtEndOfCalculation();
423 288 : break;
424 : case cmd_isEnergyNeeded:
425 0 : CHECK_INIT(initialized,word);
426 0 : CHECK_NOTNULL(val,word);
427 0 : if(atoms.isEnergyNeeded()) *(static_cast<int*>(val))=1;
428 0 : else *(static_cast<int*>(val))=0;
429 0 : break;
430 : case cmd_getBias:
431 83 : CHECK_INIT(initialized,word);
432 83 : CHECK_NOTNULL(val,word);
433 83 : atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val);
434 83 : break;
435 : case cmd_checkAction:
436 0 : CHECK_NOTNULL(val,word);
437 0 : plumed_assert(nw==2);
438 0 : *(static_cast<int*>(val))=(actionRegister().check(words[1]) ? 1:0);
439 0 : break;
440 : case cmd_GREX:
441 493 : if(!grex) grex=new GREX(*this);
442 493 : plumed_massert(grex,"error allocating grex");
443 : {
444 493 : std::string kk=words[1];
445 493 : for(unsigned i=2; i<words.size(); i++) kk+=" "+words[i];
446 493 : grex->cmd(kk.c_str(),val);
447 : }
448 493 : break;
449 : case cmd_CLTool:
450 2653 : CHECK_NOTINIT(initialized,word);
451 2653 : if(!cltool) cltool=new CLToolMain;
452 : {
453 2653 : std::string kk=words[1];
454 2653 : for(unsigned i=2; i<words.size(); i++) kk+=" "+words[i];
455 2653 : cltool->cmd(kk.c_str(),val);
456 : }
457 2653 : break;
458 : default:
459 0 : plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands.");
460 : break;
461 : }
462 : }
463 195293 : stopwatch.pause();
464 195293 : }
465 :
466 : ////////////////////////////////////////////////////////////////////////
467 :
468 331 : void PlumedMain::init() {
469 : // check that initialization just happens once
470 331 : initialized=true;
471 331 : atoms.init();
472 331 : if(!log.isOpen()) log.link(stdout);
473 331 : log<<"PLUMED is starting\n";
474 331 : log<<"Version: "<<config::getVersionLong()<<" (git: "<<config::getVersionGit()<<") compiled on " __DATE__ " at " __TIME__ "\n";
475 331 : log<<"Please cite this paper when using PLUMED ";
476 331 : log<<cite("Tribello, Bonomi, Branduardi, Camilloni, and Bussi, Comput. Phys. Commun. 185, 604 (2014)");
477 331 : log<<"\n";
478 331 : log<<"For further information see the PLUMED web page at http://www.plumed.org\n";
479 331 : log<<"Root: "<<config::getPlumedRoot()<<"\n";
480 331 : log<<"For installed feature, see "<<config::getPlumedRoot() + "/src/config/config.txt\n";
481 331 : log.printf("Molecular dynamics engine: %s\n",MDEngine.c_str());
482 331 : log.printf("Precision of reals: %d\n",atoms.getRealPrecision());
483 331 : log.printf("Running over %d %s\n",comm.Get_size(),(comm.Get_size()>1?"nodes":"node"));
484 331 : log<<"Number of threads: "<<OpenMP::getNumThreads()<<"\n";
485 331 : log<<"Cache line size: "<<OpenMP::getCachelineSize()<<"\n";
486 331 : log.printf("Number of atoms: %d\n",atoms.getNatoms());
487 331 : if(grex) log.printf("GROMACS-like replica exchange is on\n");
488 331 : log.printf("File suffix: %s\n",getSuffix().c_str());
489 331 : if(plumedDat.length()>0) {
490 295 : readInputFile(plumedDat);
491 295 : plumedDat="";
492 : }
493 331 : atoms.updateUnits();
494 331 : log.printf("Timestep: %f\n",atoms.getTimeStep());
495 331 : if(atoms.getKbT()>0.0)
496 4 : log.printf("KbT: %f\n",atoms.getKbT());
497 : else {
498 327 : log.printf("KbT has not been set by the MD engine\n");
499 327 : log.printf("It should be set by hand where needed\n");
500 : }
501 331 : log<<"Relevant bibliography:\n";
502 331 : log<<citations;
503 331 : log<<"Please read and cite where appropriate!\n";
504 331 : log<<"Finished setup\n";
505 331 : }
506 :
507 296 : void PlumedMain::readInputFile(std::string str) {
508 296 : plumed_assert(initialized);
509 296 : log.printf("FILE: %s\n",str.c_str());
510 296 : IFile ifile;
511 296 : ifile.link(*this);
512 296 : ifile.open(str);
513 296 : ifile.allowNoEOL();
514 592 : std::vector<std::string> words;
515 296 : while(Tools::getParsedLine(ifile,words) && words[0]!="ENDPLUMED") readInputWords(words);
516 296 : log.printf("END FILE: %s\n",str.c_str());
517 296 : log.flush();
518 :
519 592 : pilots=actionSet.select<ActionPilot*>();
520 296 : }
521 :
522 62 : void PlumedMain::readInputLine(const std::string & str) {
523 62 : plumed_assert(initialized);
524 124 : if(str.empty()) return;
525 62 : std::vector<std::string> words=Tools::getWords(str);
526 62 : citations.clear();
527 62 : readInputWords(words);
528 62 : if(!citations.empty()) {
529 2 : log<<"Relevant bibliography:\n";
530 2 : log<<citations;
531 2 : log<<"Please read and cite where appropriate!\n";
532 62 : }
533 : }
534 :
535 2350 : void PlumedMain::readInputWords(const std::vector<std::string> & words) {
536 2350 : plumed_assert(initialized);
537 2350 : if(words.empty())return;
538 2350 : else if(words[0]=="ENDPLUMED") return;
539 2350 : else if(words[0]=="_SET_SUFFIX") {
540 3 : plumed_assert(words.size()==2);
541 3 : setSuffix(words[1]);
542 : } else {
543 2347 : std::vector<std::string> interpreted(words);
544 2347 : Tools::interpretLabel(interpreted);
545 2347 : Action* action=actionRegister().create(ActionOptions(*this,interpreted));
546 2347 : if(!action) {
547 0 : log<<"ERROR\n";
548 0 : log<<"I cannot understand line:";
549 0 : for(unsigned i=0; i<interpreted.size(); ++i) log<<" "<<interpreted[i];
550 0 : log<<"\n";
551 0 : exit(1);
552 : };
553 2347 : action->checkRead();
554 2347 : actionSet.push_back(action);
555 : };
556 :
557 2350 : pilots=actionSet.select<ActionPilot*>();
558 : }
559 :
560 : ////////////////////////////////////////////////////////////////////////
561 :
562 0 : void PlumedMain::exit(int c) {
563 0 : comm.Abort(c);
564 0 : }
565 :
566 2347 : Log& PlumedMain::getLog() {
567 2347 : return log;
568 : }
569 :
570 21467 : void PlumedMain::calc() {
571 21467 : prepareCalc();
572 21467 : performCalc();
573 21467 : }
574 :
575 21547 : void PlumedMain::prepareCalc() {
576 21547 : prepareDependencies();
577 21547 : shareData();
578 21547 : }
579 :
580 : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
581 : // here we have the main steps in "calc()"
582 : // they can be called individually, but the standard thing is to
583 : // traverse them in this order:
584 21691 : void PlumedMain::prepareDependencies() {
585 :
586 21691 : stopwatch.start("1 Prepare dependencies");
587 :
588 : // activate all the actions which are on step
589 : // activation is recursive and enables also the dependencies
590 : // before doing that, the prepare() method is called to see if there is some
591 : // new/changed dependency (up to now, only useful for dependences on virtual atoms,
592 : // which can be dynamically changed).
593 :
594 : // First switch off all actions
595 150080 : for(ActionSet::iterator p=actionSet.begin(); p!=actionSet.end(); ++p) {
596 128389 : (*p)->deactivate();
597 : //I think this is already done inside deactivate
598 : //(*p)->clearOptions();
599 : }
600 :
601 : // for optimization, an "active" flag remains false if no action at all is active
602 21691 : active=false;
603 80753 : for(unsigned i=0; i<pilots.size(); ++i) {
604 59062 : if(pilots[i]->onStep()) {
605 52546 : pilots[i]->activate();
606 52546 : active=true;
607 : }
608 : };
609 :
610 : // also, if one of them is the total energy, tell to atoms that energy should be collected
611 150080 : for(ActionSet::iterator p=actionSet.begin(); p!=actionSet.end(); ++p) {
612 128389 : if((*p)->isActive()) {
613 108738 : if((*p)->checkNeedsGradients()) (*p)->setOption("GRADIENTS");
614 : }
615 : }
616 :
617 21691 : stopwatch.stop("1 Prepare dependencies");
618 21691 : }
619 :
620 21547 : void PlumedMain::shareData() {
621 : // atom positions are shared (but only if there is something to do)
622 43094 : if(!active)return;
623 20064 : stopwatch.start("2 Sharing data");
624 20064 : if(atoms.getNatoms()>0) atoms.share();
625 20064 : stopwatch.stop("2 Sharing data");
626 : }
627 :
628 80 : void PlumedMain::performCalcNoUpdate() {
629 80 : waitData();
630 80 : justCalculate();
631 80 : backwardPropagate();
632 80 : }
633 :
634 21467 : void PlumedMain::performCalc() {
635 21467 : waitData();
636 21467 : justCalculate();
637 21467 : backwardPropagate();
638 21467 : update();
639 21467 : }
640 :
641 21619 : void PlumedMain::waitData() {
642 43238 : if(!active)return;
643 20136 : stopwatch.start("3 Waiting for data");
644 20136 : if(atoms.getNatoms()>0) atoms.wait();
645 20136 : stopwatch.stop("3 Waiting for data");
646 : }
647 :
648 21619 : void PlumedMain::justCalculate() {
649 43238 : if(!active)return;
650 20136 : stopwatch.start("4 Calculating (forward loop)");
651 20136 : bias=0.0;
652 20136 : work=0.0;
653 :
654 20136 : int iaction=0;
655 : // calculate the active actions in order (assuming *backward* dependence)
656 139620 : for(ActionSet::iterator p=actionSet.begin(); p!=actionSet.end(); ++p) {
657 119484 : if((*p)->isActive()) {
658 108240 : std::string actionNumberLabel;
659 108240 : if(detailedTimers) {
660 0 : Tools::convert(iaction,actionNumberLabel);
661 0 : actionNumberLabel="4A "+actionNumberLabel+" "+(*p)->getLabel();
662 0 : stopwatch.start(actionNumberLabel);
663 : }
664 108240 : ActionWithValue*av=dynamic_cast<ActionWithValue*>(*p);
665 108240 : ActionAtomistic*aa=dynamic_cast<ActionAtomistic*>(*p);
666 : {
667 108240 : if(av) av->clearInputForces();
668 108240 : if(av) av->clearDerivatives();
669 : }
670 : {
671 108240 : if(aa) aa->clearOutputForces();
672 108240 : if(aa) if(aa->isActive()) aa->retrieveAtoms();
673 : }
674 108240 : if((*p)->checkNumericalDerivatives()) (*p)->calculateNumericalDerivatives();
675 107762 : else (*p)->calculate();
676 : // This retrieves components called bias
677 108240 : if(av) bias+=av->getOutputQuantity("bias");
678 108240 : if(av) work+=av->getOutputQuantity("work");
679 108240 : if(av)av->setGradientsIfNeeded();
680 108240 : ActionWithVirtualAtom*avv=dynamic_cast<ActionWithVirtualAtom*>(*p);
681 108240 : if(avv)avv->setGradientsIfNeeded();
682 108240 : if(detailedTimers) stopwatch.stop(actionNumberLabel);
683 : }
684 119484 : iaction++;
685 : }
686 20136 : stopwatch.stop("4 Calculating (forward loop)");
687 : }
688 :
689 0 : void PlumedMain::justApply() {
690 0 : backwardPropagate();
691 0 : update();
692 0 : }
693 :
694 21547 : void PlumedMain::backwardPropagate() {
695 43094 : if(!active)return;
696 20064 : int iaction=0;
697 20064 : stopwatch.start("5 Applying (backward loop)");
698 : // apply them in reverse order
699 138990 : for(ActionSet::reverse_iterator p=actionSet.rbegin(); p!=actionSet.rend(); ++p) {
700 118926 : if((*p)->isActive()) {
701 :
702 107742 : std::string actionNumberLabel;
703 107742 : if(detailedTimers) {
704 0 : Tools::convert(iaction,actionNumberLabel);
705 0 : actionNumberLabel="5A "+actionNumberLabel+" "+(*p)->getLabel();
706 0 : stopwatch.start(actionNumberLabel);
707 : }
708 :
709 107742 : (*p)->apply();
710 107742 : ActionAtomistic*a=dynamic_cast<ActionAtomistic*>(*p);
711 : // still ActionAtomistic has a special treatment, since they may need to add forces on atoms
712 107742 : if(a) a->applyForces();
713 :
714 107742 : if(detailedTimers) stopwatch.stop(actionNumberLabel);
715 : }
716 118926 : iaction++;
717 : }
718 :
719 : // this is updating the MD copy of the forces
720 20064 : if(detailedTimers) stopwatch.start("5B Update forces");
721 20064 : if(atoms.getNatoms()>0) atoms.updateForces();
722 20064 : if(detailedTimers) stopwatch.stop("5B Update forces");
723 20064 : stopwatch.stop("5 Applying (backward loop)");
724 : }
725 :
726 21477 : void PlumedMain::update() {
727 42954 : if(!active)return;
728 :
729 19994 : stopwatch.start("6 Update");
730 : // update step (for statistics, etc)
731 19994 : updateFlags.push(true);
732 138680 : for(ActionSet::iterator p=actionSet.begin(); p!=actionSet.end(); ++p) {
733 118686 : (*p)->beforeUpdate();
734 118686 : if((*p)->isActive() && (*p)->checkUpdate() && updateFlagsTop()) (*p)->update();
735 : }
736 19994 : while(!updateFlags.empty()) updateFlags.pop();
737 19994 : if(!updateFlags.empty()) plumed_merror("non matching changes in the update flags");
738 : // Check that no action has told the calculation to stop
739 19994 : if(stopNow) {
740 3 : if(stopFlag) (*stopFlag)=1;
741 0 : else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)");
742 : }
743 :
744 : // flush by default every 10000 steps
745 : // hopefully will not affect performance
746 : // also if receive checkpointing signal
747 19994 : if(step%10000==0||doCheckPoint) {
748 326 : fflush();
749 326 : log.flush();
750 326 : for(ActionSet::const_iterator p=actionSet.begin(); p!=actionSet.end(); ++p) (*p)->fflush();
751 : }
752 19994 : stopwatch.stop("6 Update");
753 : }
754 :
755 1 : void PlumedMain::load(const std::string& ss) {
756 1 : if(DLLoader::installed()) {
757 1 : string s=ss;
758 1 : size_t n=s.find_last_of(".");
759 2 : string extension="";
760 2 : string base=s;
761 1 : if(n!=std::string::npos && n<s.length()-1) extension=s.substr(n+1);
762 1 : if(n!=std::string::npos && n<s.length()) base=s.substr(0,n);
763 1 : if(extension=="cpp") {
764 : // full path command, including environment setup
765 : // this will work even if plumed is not in the execution path or if it has been
766 : // installed with a name different from "plumed"
767 1 : string cmd=config::getEnvCommand()+" \""+config::getPlumedRoot()+"\"/scripts/mklib.sh "+s;
768 1 : log<<"Executing: "<<cmd;
769 1 : if(comm.Get_size()>0) log<<" (only on master node)";
770 1 : log<<"\n";
771 1 : if(comm.Get_rank()==0) system(cmd.c_str());
772 1 : comm.Barrier();
773 1 : base="./"+base;
774 : }
775 1 : s=base+"."+config::getSoExt();
776 1 : void *p=dlloader.load(s);
777 1 : if(!p) {
778 0 : log<<"ERROR\n";
779 0 : log<<"I cannot load library "<<ss<<"\n";
780 0 : log<<dlloader.error();
781 0 : log<<"\n";
782 0 : this->exit(1);
783 : }
784 1 : log<<"Loading shared library "<<s.c_str()<<"\n";
785 1 : log<<"Here is the new list of available actions\n";
786 2 : log<<actionRegister();
787 0 : } else plumed_merror("loading not enabled, please recompile with -D__PLUMED_HAS_DLOPEN");
788 1 : }
789 :
790 227 : double PlumedMain::getBias() const {
791 227 : return bias;
792 : }
793 :
794 0 : double PlumedMain::getWork() const {
795 0 : return work;
796 : }
797 :
798 34 : FILE* PlumedMain::fopen(const char *path, const char *mode) {
799 34 : std::string mmode(mode);
800 68 : std::string ppath(path);
801 68 : std::string suffix(getSuffix());
802 68 : std::string ppathsuf=ppath+suffix;
803 34 : FILE*fp=std::fopen(const_cast<char*>(ppathsuf.c_str()),const_cast<char*>(mmode.c_str()));
804 34 : if(!fp) fp=std::fopen(const_cast<char*>(ppath.c_str()),const_cast<char*>(mmode.c_str()));
805 34 : plumed_massert(fp,"file " + ppath + " cannot be found");
806 68 : return fp;
807 : }
808 :
809 34 : int PlumedMain::fclose(FILE*fp) {
810 34 : return std::fclose(fp);
811 : }
812 :
813 760 : std::string PlumedMain::cite(const std::string&item) {
814 760 : return citations.cite(item);
815 : }
816 :
817 779 : void PlumedMain::fflush() {
818 2030 : for(files_iterator p=files.begin(); p!=files.end(); ++p) {
819 1251 : (*p)->flush();
820 : }
821 779 : }
822 :
823 1124 : void PlumedMain::insertFile(FileBase&f) {
824 1124 : files.insert(&f);
825 1124 : }
826 :
827 1202 : void PlumedMain::eraseFile(FileBase&f) {
828 1202 : files.erase(&f);
829 1202 : }
830 :
831 2 : void PlumedMain::stop() {
832 2 : stopNow=true;
833 2 : }
834 :
835 288 : void PlumedMain::runJobsAtEndOfCalculation() {
836 2508 : for(ActionSet::iterator p=actionSet.begin(); p!=actionSet.end(); ++p) {
837 2220 : (*p)->runFinalJobs();
838 : }
839 288 : }
840 :
841 2523 : }
842 :
843 : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|