LCOV - code coverage report
Current view: top level - core - PlumedMain.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 434 553 78.5 %
Date: 2018-12-19 07:49:13 Functions: 32 35 91.4 %

          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             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.13