LCOV - code coverage report
Current view: top level - core - PlumedMain.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 456 521 87.5 %
Date: 2019-08-13 10:15:31 Functions: 33 35 94.3 %

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

Generated by: LCOV version 1.14