LCOV - code coverage report
Current view: top level - core - PlumedMain.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 957 1068 89.6 %
Date: 2026-11-12 10:48:31 Functions: 65 70 92.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "PlumedMain.h"
      23             : #include "ActionAtomistic.h"
      24             : #include "ActionPilot.h"
      25             : #include "ActionForInterface.h"
      26             : #include "ActionRegister.h"
      27             : #include "ActionSet.h"
      28             : #include "ActionWithValue.h"
      29             : #include "ActionWithVirtualAtom.h"
      30             : #include "ActionToGetData.h"
      31             : #include "ActionToPutData.h"
      32             : #include "CLToolMain.h"
      33             : #include "ExchangePatterns.h"
      34             : #include "GREX.h"
      35             : #include "DomainDecomposition.h"
      36             : #include "config/Config.h"
      37             : #include "tools/Citations.h"
      38             : #include "tools/Communicator.h"
      39             : #include "tools/DLLoader.h"
      40             : #include "tools/Exception.h"
      41             : #include "tools/IFile.h"
      42             : #include "tools/Log.h"
      43             : #include "tools/OpenMP.h"
      44             : #include "tools/Tools.h"
      45             : #include "tools/Stopwatch.h"
      46             : #include "tools/TypesafePtr.h"
      47             : #include "lepton/Exception.h"
      48             : #include "DataPassingTools.h"
      49             : #include "small_vector/small_vector.h"
      50             : #include <cstdlib>
      51             : #include <cstdio>
      52             : #include <cstring>
      53             : #include <set>
      54             : #include <exception>
      55             : #include <stdexcept>
      56             : #include <ios>
      57             : #include <new>
      58             : #include <typeinfo>
      59             : #include <iostream>
      60             : #include <algorithm>
      61             : #include <system_error>
      62             : #include <future>
      63             : #include <memory>
      64             : #include <functional>
      65             : #include <regex>
      66             : #include <any>
      67             : #include <optional>
      68             : #include <variant>
      69             : #include <filesystem>
      70             : 
      71             : namespace PLMD {
      72             : 
      73             : /// Small utility just used in this file to throw arbitrary exceptions
      74          61 : [[noreturn]] static void testThrow(const char* what) {
      75          61 :   auto words=Tools::getWords(what);
      76          61 :   plumed_assert(words.size()>0);
      77             : #define __PLUMED_THROW_NOMSG(type) if(words[0]==#type) throw type()
      78             : #define __PLUMED_THROW_MSG(type) if(words[0]==#type) throw type(what)
      79          62 :   __PLUMED_THROW_MSG(PLMD::ExceptionError);
      80          61 :   __PLUMED_THROW_MSG(PLMD::ExceptionDebug);
      81          60 :   __PLUMED_THROW_MSG(PLMD::Exception);
      82          59 :   __PLUMED_THROW_MSG(PLMD::lepton::Exception);
      83          57 :   __PLUMED_THROW_NOMSG(std::bad_exception);
      84          56 :   __PLUMED_THROW_NOMSG(std::bad_array_new_length);
      85          55 :   __PLUMED_THROW_NOMSG(std::bad_alloc);
      86          54 :   __PLUMED_THROW_NOMSG(std::bad_function_call);
      87          53 :   __PLUMED_THROW_NOMSG(std::bad_weak_ptr);
      88          52 :   __PLUMED_THROW_NOMSG(std::bad_cast);
      89          51 :   __PLUMED_THROW_NOMSG(std::bad_typeid);
      90          50 :   __PLUMED_THROW_NOMSG(std::bad_variant_access);
      91          49 :   __PLUMED_THROW_NOMSG(std::bad_optional_access);
      92          48 :   __PLUMED_THROW_NOMSG(std::bad_any_cast);
      93          47 :   __PLUMED_THROW_MSG(std::underflow_error);
      94          46 :   __PLUMED_THROW_MSG(std::overflow_error);
      95          45 :   __PLUMED_THROW_MSG(std::range_error);
      96          44 :   __PLUMED_THROW_MSG(std::runtime_error);
      97          43 :   __PLUMED_THROW_MSG(std::out_of_range);
      98          42 :   __PLUMED_THROW_MSG(std::length_error);
      99          41 :   __PLUMED_THROW_MSG(std::domain_error);
     100          40 :   __PLUMED_THROW_MSG(std::invalid_argument);
     101          39 :   __PLUMED_THROW_MSG(std::logic_error);
     102             : 
     103             : 
     104             : 
     105          38 :   if(words[0]=="std::system_error") {
     106           4 :     plumed_assert(words.size()>2);
     107             :     int error_code;
     108           4 :     Tools::convert(words[2],error_code);
     109           4 :     if(words[1]=="std::generic_category") {
     110           1 :       throw std::system_error(error_code,std::generic_category(),what);
     111             :     }
     112           3 :     if(words[1]=="std::system_category") {
     113           1 :       throw std::system_error(error_code,std::system_category(),what);
     114             :     }
     115           2 :     if(words[1]=="std::iostream_category") {
     116           1 :       throw std::system_error(error_code,std::iostream_category(),what);
     117             :     }
     118           1 :     if(words[1]=="std::future_category") {
     119           1 :       throw std::system_error(error_code,std::future_category(),what);
     120             :     }
     121             :   }
     122             : 
     123          34 :   if(words[0]=="std::filesystem::filesystem_error") {
     124             :     int error_code;
     125           3 :     plumed_assert(words.size()>2);
     126           3 :     Tools::convert(words[2],error_code);
     127             :     std::error_code x_error_code;
     128           3 :     if(words[1]=="std::generic_category") {
     129           3 :       x_error_code=::std::error_code(error_code,::std::generic_category());
     130             :     }
     131           3 :     if(words[1]=="std::system_category") {
     132           0 :       x_error_code=::std::error_code(error_code,::std::system_category());
     133             :     }
     134           3 :     if(words[1]=="std::iostream_category") {
     135           0 :       x_error_code=::std::error_code(error_code,::std::iostream_category());
     136             :     }
     137           3 :     if(words[1]=="std::future_category") {
     138           0 :       x_error_code=::std::error_code(error_code,::std::future_category());
     139             :     }
     140             : 
     141           3 :     if(words.size()<4) {
     142           2 :       throw std::filesystem::filesystem_error(what,x_error_code);
     143             :     }
     144           2 :     if(words.size()<5) {
     145           3 :       throw std::filesystem::filesystem_error(what,std::filesystem::path(words[3]),x_error_code);
     146             :     }
     147           4 :     throw std::filesystem::filesystem_error(what,std::filesystem::path(words[3]),std::filesystem::path(words[4]),x_error_code);
     148             :   }
     149             : 
     150             : #define __PLUMED_THROW_REGEX(name) if(words[1]=="std::regex_constants::error_" #name) throw std::regex_error(std::regex_constants::error_ ##name)
     151          31 :   if(words[0]=="std::regex_error") {
     152          13 :     plumed_assert(words.size()>1);
     153          13 :     __PLUMED_THROW_REGEX(collate);
     154          12 :     __PLUMED_THROW_REGEX(ctype);
     155          11 :     __PLUMED_THROW_REGEX(escape);
     156          10 :     __PLUMED_THROW_REGEX(backref);
     157           9 :     __PLUMED_THROW_REGEX(brack);
     158           8 :     __PLUMED_THROW_REGEX(paren);
     159           7 :     __PLUMED_THROW_REGEX(brace);
     160           6 :     __PLUMED_THROW_REGEX(badbrace);
     161           5 :     __PLUMED_THROW_REGEX(range);
     162           4 :     __PLUMED_THROW_REGEX(space);
     163           3 :     __PLUMED_THROW_REGEX(badrepeat);
     164           2 :     __PLUMED_THROW_REGEX(complexity);
     165           1 :     __PLUMED_THROW_REGEX(stack);
     166             :   }
     167             : 
     168             : #define __PLUMED_THROW_FUTURE(name) if(words[1]=="std::future_errc::" #name) throw std::future_error(::std::future_errc::name)
     169          18 :   if(words[0]=="std::future_error") {
     170           4 :     plumed_assert(words.size()>1);
     171           4 :     __PLUMED_THROW_FUTURE(broken_promise);
     172           3 :     __PLUMED_THROW_FUTURE(future_already_retrieved);
     173           2 :     __PLUMED_THROW_FUTURE(promise_already_satisfied);
     174           1 :     __PLUMED_THROW_FUTURE(no_state);
     175             :   }
     176             : 
     177          14 :   if(words[0]=="std::ios_base::failure") {
     178           1 :     int error_code=0;
     179           1 :     if(words.size()>2) {
     180           0 :       Tools::convert(words[2],error_code);
     181             :     }
     182           1 :     if(words.size()>1 && words[1]=="std::generic_category") {
     183           0 :       throw std::ios_base::failure(what,std::error_code(error_code,std::generic_category()));
     184             :     }
     185           1 :     if(words.size()>1 && words[1]=="std::system_category") {
     186           0 :       throw std::ios_base::failure(what,std::error_code(error_code,std::system_category()));
     187             :     }
     188           1 :     if(words.size()>1 && words[1]=="std::iostream_category") {
     189           0 :       throw std::ios_base::failure(what,std::error_code(error_code,std::iostream_category()));
     190             :     }
     191           1 :     if(words.size()>1 && words[1]=="std::future_category") {
     192           0 :       throw std::ios_base::failure(what,std::error_code(error_code,std::future_category()));
     193             :     }
     194           2 :     throw std::ios_base::failure(what);
     195             :   }
     196             : 
     197          13 :   if(words[0]=="int") {
     198           1 :     int value=0;
     199           1 :     if(words.size()>1) {
     200           0 :       Tools::convert(words[1],value);
     201             :     }
     202           1 :     throw value;
     203             :   }
     204             : 
     205          12 :   if(words[0]=="test_nested1") {
     206             :     try {
     207          12 :       throw Exception(std::string("inner ")+what);
     208           6 :     } catch(...) {
     209             :       try {
     210          18 :         std::throw_with_nested(Exception(std::string("middle ")+what));
     211           6 :       } catch(...) {
     212          18 :         std::throw_with_nested(Exception(std::string("outer ")+what));
     213           6 :       }
     214           6 :     }
     215             :   }
     216             : 
     217           6 :   if(words[0]=="test_nested2") {
     218             :     try {
     219           3 :       throw std::bad_alloc();
     220           3 :     } catch(...) {
     221             :       try {
     222           9 :         std::throw_with_nested(Exception(std::string("middle ")+what));
     223           3 :       } catch(...) {
     224           9 :         std::throw_with_nested(Exception(std::string("outer ")+what));
     225           3 :       }
     226           3 :     }
     227             :   }
     228             : 
     229           3 :   if(words[0]=="test_nested3") {
     230             :     try {
     231           2 :       throw "inner";
     232           2 :     } catch(...) {
     233             :       try {
     234           6 :         std::throw_with_nested(Exception(std::string("middle ")+what));
     235           2 :       } catch(...) {
     236           6 :         std::throw_with_nested(Exception(std::string("outer ")+what));
     237           2 :       }
     238           2 :     }
     239             :   }
     240             : 
     241           2 :   plumed_error() << "unknown exception " << what;
     242          61 : }
     243             : 
     244             : namespace {
     245             : /// This is an internal tool used to count how many PlumedMain objects have been created
     246             : /// and if they were correctly destroyed.
     247             : /// When using debug options, it leads to a crash
     248             : /// Otherwise, it just prints a message
     249             : class CountInstances {
     250             :   std::atomic<int> counter{};
     251             :   // private constructor to avoid direct usage
     252        6108 :   CountInstances() noexcept {}
     253        6108 :   ~CountInstances() {
     254        6108 :     if(counter!=0) {
     255           0 :       std::cerr<<"WARNING: internal inconsistency in allocated PlumedMain instances (" <<counter<< ")\n";
     256           0 :       std::cerr<<"Might be a consequence of incorrectly paired plumed_create/plumed_finalize in the C interface\n";
     257           0 :       std::cerr<<"Or it could be due to incorrect calls to std::exit, without properly destroying all PlumedMain objects\n";
     258             : #ifndef NDEBUG
     259             :       std::cerr<<"This is a debug build, so the warning will make PLUMED abort\n";
     260             :       std::abort();
     261             : #endif
     262             :     }
     263        6108 :   }
     264     1615692 :   static CountInstances & instance() {
     265     1615692 :     static CountInstances counter;
     266     1615692 :     return counter;
     267             :   }
     268             : public:
     269             :   /// Only access through these static functions
     270             :   /// The first call to increase() ensures the instance is constructed
     271             :   /// This should provide the correct construction and destruction order
     272             :   /// also in cases where the PlumedMain object is constructed in the
     273             :   /// constructor of a static object
     274      807846 :   static void increase() noexcept {
     275      807846 :     ++instance().counter;
     276      807846 :   }
     277             :   /// See increase()
     278      807846 :   static void decrease() noexcept {
     279      807846 :     --instance().counter;
     280      807846 :   }
     281             : };
     282             : 
     283             : }
     284             : 
     285             : 
     286      807846 : PlumedMain::PlumedMain():
     287      807846 :   datoms_fwd(*this),
     288             : // automatically write on log in destructor
     289      807846 :   stopwatch_fwd(log),
     290      807846 :   actionSet_fwd(*this),
     291      807846 :   passtools(DataPassingTools::create(sizeof(double))) {
     292      807846 :   passtools->usingNaturalUnits=false;
     293      807846 :   OpenMP::retainRuntime();
     294      807846 :   increaseReferenceCounter();
     295      807846 :   log.link(comm);
     296      807846 :   log.setLinePrefix("PLUMED: ");
     297             :   // this is at last so as to avoid inconsistencies if an exception is thrown
     298      807846 :   CountInstances::increase(); // noexcept
     299      807846 : }
     300             : 
     301             : // destructor needed to delete forward declarated objects
     302     1614654 : PlumedMain::~PlumedMain() {
     303      807846 :   CountInstances::decrease();
     304     4846038 : }
     305             : 
     306             : /////////////////////////////////////////////////////////////
     307             : //  MAIN INTERPRETER
     308             : 
     309             : #define CHECK_INIT(ini,word) plumed_assert(ini)<<"cmd(\"" << word << "\") should be only used after plumed initialization"
     310             : #define CHECK_NOTINIT(ini,word) plumed_assert(!(ini))<<"cmd(\"" << word << "\") should be only used before plumed initialization"
     311             : #define CHECK_NOTNULL(val,word) plumed_assert(val)<<"NULL pointer received in cmd(\"" << word << "\")"
     312             : 
     313             : 
     314     1931779 : void PlumedMain::cmd(std::string_view word,const TypesafePtr & val) {
     315             : 
     316             : // Enumerate all possible commands:
     317             :   enum {
     318             : #include "PlumedMainEnum.inc"
     319             :   };
     320             : 
     321             : // Static object (initialized once) containing the map of commands:
     322             :   const static Tools::FastStringUnorderedMap<int> word_map = {
     323             : #include "PlumedMainMap.inc"
     324     1931779 :   };
     325             : 
     326             :   try {
     327             : 
     328     1931779 :     auto ss=stopwatch.startPause();
     329             : 
     330             :     gch::small_vector<std::string_view> words;
     331     1931779 :     Tools::getWordsSimple(words,word);
     332             : 
     333     1931779 :     unsigned nw=words.size();
     334     1931779 :     if(nw==0) {
     335             :       // do nothing
     336             :     } else {
     337             :       int iword=-1;
     338             :       const auto it=word_map.find(words[0]);
     339     1931778 :       if(it!=word_map.end()) {
     340     1931771 :         iword=it->second;
     341             :       }
     342             : 
     343     1931771 :       switch(iword) {
     344      136729 :       case cmd_setBox:
     345      136729 :         CHECK_INIT(initialized,word);
     346      136729 :         CHECK_NOTNULL(val,word);
     347      136729 :         setInputValue( "Box", 0, 1, val );
     348      136728 :         break;
     349      140906 :       case cmd_setPositions:
     350      140906 :         CHECK_INIT(initialized,word);
     351      140906 :         setInputValue("posx", 0, 3, val );
     352      140906 :         setInputValue("posy", 1, 3, val );
     353      140906 :         setInputValue("posz", 2, 3, val );
     354      140906 :         break;
     355      140869 :       case cmd_setMasses:
     356      140869 :         CHECK_INIT(initialized,word);
     357      140869 :         setInputValue("Masses", 0, 1, val );
     358      140866 :         break;
     359       67667 :       case cmd_setCharges:
     360       67667 :         CHECK_INIT(initialized,word);
     361       67667 :         setInputValue("Charges", 0, 1, val);
     362       67667 :         break;
     363           1 :       case cmd_setPositionsX:
     364           1 :         CHECK_INIT(initialized,word);
     365           1 :         setInputValue("posx", 0, 1, val);
     366           1 :         break;
     367           1 :       case cmd_setPositionsY:
     368           1 :         CHECK_INIT(initialized,word);
     369           1 :         setInputValue("posy", 0, 1, val);
     370           1 :         break;
     371           1 :       case cmd_setPositionsZ:
     372           1 :         CHECK_INIT(initialized,word);
     373           1 :         setInputValue("posz", 0, 1, val);
     374           1 :         break;
     375      132993 :       case cmd_setVirial:
     376      132993 :         CHECK_INIT(initialized,word);
     377      132993 :         CHECK_NOTNULL(val,word);
     378      132993 :         setInputForce("Box",val);
     379      132975 :         break;
     380        7892 :       case cmd_setEnergy:
     381        7892 :         CHECK_INIT(initialized,word);
     382        7892 :         CHECK_NOTNULL(val,word);
     383        7892 :         if( name_of_energy!="" ) {
     384        3989 :           setInputValue( name_of_energy, 0, 1,  val );
     385             :         }
     386             :         break;
     387      140873 :       case cmd_setForces:
     388      140873 :         CHECK_INIT(initialized,word);
     389      140873 :         setInputForce("posx",val);
     390      140873 :         setInputForce("posy",val);
     391      140873 :         setInputForce("posz",val);
     392      140873 :         break;
     393           1 :       case cmd_setForcesX:
     394           1 :         CHECK_INIT(initialized,word);
     395           1 :         setInputForce("posx",val);
     396           1 :         break;
     397           1 :       case cmd_setForcesY:
     398           1 :         CHECK_INIT(initialized,word);
     399           1 :         setInputForce("posy",val);
     400           1 :         break;
     401           1 :       case cmd_setForcesZ:
     402           1 :         CHECK_INIT(initialized,word);
     403           1 :         setInputForce("posz",val);
     404           1 :         break;
     405      357689 :       case cmd_calc:
     406      357689 :         CHECK_INIT(initialized,word);
     407      357689 :         calc();
     408             :         break;
     409          99 :       case cmd_prepareDependencies:
     410          99 :         CHECK_INIT(initialized,word);
     411          99 :         prepareDependencies();
     412             :         break;
     413          84 :       case cmd_shareData:
     414          84 :         CHECK_INIT(initialized,word);
     415          84 :         shareData();
     416             :         break;
     417        6985 :       case cmd_prepareCalc:
     418        6985 :         CHECK_INIT(initialized,word);
     419        6985 :         prepareCalc();
     420             :         break;
     421          10 :       case cmd_performCalc:
     422          10 :         CHECK_INIT(initialized,word);
     423          10 :         performCalc();
     424             :         break;
     425        7045 :       case cmd_performCalcNoUpdate:
     426        7045 :         CHECK_INIT(initialized,word);
     427        7045 :         performCalcNoUpdate();
     428             :         break;
     429          10 :       case cmd_performCalcNoForces:
     430          10 :         CHECK_INIT(initialized,word);
     431          10 :         performCalcNoForces();
     432             :         break;
     433          79 :       case cmd_update:
     434          79 :         CHECK_INIT(initialized,word);
     435          79 :         update();
     436             :         break;
     437       92643 :       case cmd_setStep:
     438       92643 :         CHECK_INIT(initialized,word);
     439       92646 :         CHECK_NOTNULL(val,word);
     440       92640 :         step=val.get<int>();
     441       92639 :         startStep();
     442             :         break;
     443           0 :       case cmd_setStepLong:
     444           0 :         CHECK_INIT(initialized,word);
     445           0 :         CHECK_NOTNULL(val,word);
     446           0 :         step=val.get<long int>();
     447           0 :         startStep();
     448             :         break;
     449      272032 :       case cmd_setStepLongLong:
     450      272032 :         CHECK_INIT(initialized,word);
     451      272032 :         CHECK_NOTNULL(val,word);
     452      272032 :         step=val.get<long long int>();
     453      272032 :         startStep();
     454             :         break;
     455       46398 :       case cmd_setValue: {
     456       46398 :         CHECK_INIT(initialized,words[0]);
     457       46398 :         plumed_assert(nw==2);
     458       46398 :         setInputValue( std::string(words[1]), 0, 1, val );
     459             :       }
     460       46398 :       break;
     461             :       /* ADDED WITH API=7 */
     462           0 :       case cmd_setValueForces: {
     463           0 :         CHECK_INIT(initialized,words[0]);
     464           0 :         plumed_assert(nw==2);
     465           0 :         setInputForce( std::string(words[1]), val );
     466             :       }
     467           0 :       break;
     468             :       // words used less frequently:
     469        1194 :       case cmd_setAtomsNlocal:
     470        1194 :         CHECK_INIT(initialized,word);
     471        1194 :         CHECK_NOTNULL(val,word);
     472        4796 :         for(const auto & pp : inputs ) {
     473        3602 :           plumed_assert(pp);
     474        3602 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     475        3602 :           if( dd ) {
     476        1194 :             dd->setAtomsNlocal(val.get<int>());
     477             :           }
     478             :         }
     479             :         break;
     480        1040 :       case cmd_setAtomsGatindex:
     481        1040 :         CHECK_INIT(initialized,word);
     482        4182 :         for(const auto & pp : inputs ) {
     483        3142 :           plumed_assert(pp);
     484        3142 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     485        3142 :           if( dd ) {
     486        1040 :             dd->setAtomsGatindex(val,false);
     487             :           }
     488             :         }
     489             :         break;
     490           2 :       case cmd_setAtomsFGatindex:
     491           2 :         CHECK_INIT(initialized,word);
     492           6 :         for(const auto & pp : inputs ) {
     493           4 :           plumed_assert(pp);
     494           4 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     495           4 :           if( dd ) {
     496           2 :             dd->setAtomsGatindex(val,true);
     497             :           }
     498             :         }
     499             :         break;
     500         152 :       case cmd_setAtomsContiguous:
     501         152 :         CHECK_INIT(initialized,word);
     502         152 :         CHECK_NOTNULL(val,word);
     503         608 :         for(const auto & pp : inputs ) {
     504         456 :           plumed_assert(pp);
     505         456 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     506         456 :           if( dd ) {
     507         152 :             dd->setAtomsContiguous(val.get<int>());
     508             :           }
     509             :         }
     510             :         break;
     511         116 :       case cmd_createFullList:
     512         116 :         CHECK_INIT(initialized,word);
     513         116 :         CHECK_NOTNULL(val,word);
     514         553 :         for(const auto & pp : inputs ) {
     515         437 :           plumed_assert(pp);
     516         437 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     517         437 :           if( dd ) {
     518         116 :             dd->createFullList(val);
     519             :           }
     520             :         }
     521             :         break;
     522         116 :       case cmd_getFullList: {
     523         116 :         CHECK_INIT(initialized,word);
     524         116 :         CHECK_NOTNULL(val,word);
     525             :         unsigned nlists=0;
     526         553 :         for(const auto & pp : inputs ) {
     527         437 :           plumed_assert(pp);
     528         437 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     529         437 :           if( dd ) {
     530         116 :             dd->getFullList(val);
     531         116 :             nlists++;
     532             :           }
     533             :         }
     534         116 :         plumed_assert( nlists==1 );
     535             :       }
     536             :       break;
     537         116 :       case cmd_clearFullList:
     538         116 :         CHECK_INIT(initialized,word);
     539         553 :         for(const auto & pp : inputs ) {
     540         437 :           plumed_assert(pp);
     541         437 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     542         437 :           if( dd ) {
     543         116 :             dd->clearFullList();
     544             :           }
     545             :         }
     546             :         break;
     547             :       /* ADDED WITH API==6 */
     548         121 :       case cmd_getDataRank: {
     549         121 :         CHECK_INIT(initialized,words[0]);
     550         121 :         plumed_assert(nw==2 || nw==3);
     551         121 :         std::string vtype="";
     552         121 :         if( nw==3 ) {
     553           0 :           vtype=" TYPE="+std::string(words[2]);
     554             :         }
     555         363 :         readInputLine( "grab_" + std::string(words[1]) + ": GET ARG=" + std::string(words[1]) + vtype );
     556         242 :         ActionToGetData* as=actionSet.selectWithLabel<ActionToGetData*>("grab_"+std::string(words[1]));
     557         121 :         plumed_assert( as );
     558         121 :         as->get_rank( val );
     559             :       }
     560         121 :       break;
     561             :       /* ADDED WITH API==6 */
     562          57 :       case cmd_getDataShape: {
     563          57 :         CHECK_INIT(initialized,std::string(words[0]));
     564         114 :         ActionToGetData* as1=actionSet.selectWithLabel<ActionToGetData*>("grab_"+std::string(words[1]));
     565          57 :         plumed_assert( as1 );
     566          57 :         as1->get_shape( val );
     567             :       }
     568             :       break;
     569             :       /* ADDED WITH API==6 */
     570         121 :       case cmd_setMemoryForData: {
     571         121 :         CHECK_INIT(initialized,words[0]);
     572         121 :         plumed_assert(nw==2 || nw==3);
     573         242 :         ActionToGetData* as2=actionSet.selectWithLabel<ActionToGetData*>("grab_"+std::string(words[1]));
     574         121 :         plumed_assert( as2 );
     575         121 :         as2->set_memory( val );
     576             :       }
     577             :       break;
     578             :       /* ADDED WITH API==6 */
     579             :       case cmd_setErrorHandler: {
     580           0 :         if(val) {
     581           0 :           error_handler=*static_cast<const plumed_error_handler*>(val.get<const void*>());
     582             :         } else {
     583           0 :           error_handler.handler=NULL;
     584             :         }
     585             :       }
     586             :       break;
     587           0 :       case cmd_read:
     588           0 :         CHECK_INIT(initialized,word);
     589           0 :         if(val) {
     590           0 :           readInputFile(val.getCString());
     591             :         } else {
     592           0 :           readInputFile("plumed.dat");
     593             :         }
     594             :         break;
     595        1672 :       case cmd_readInputLine:
     596        1672 :         CHECK_INIT(initialized,word);
     597        1672 :         CHECK_NOTNULL(val,word);
     598        1672 :         readInputLine(val.getCString());
     599        1613 :         break;
     600           6 :       case cmd_readInputLines:
     601           6 :         CHECK_INIT(initialized,word);
     602           6 :         CHECK_NOTNULL(val,word);
     603           6 :         readInputLines(val.getCString());
     604           6 :         break;
     605           3 :       case cmd_clear: {
     606           3 :         CHECK_INIT(initialized,word);
     607             :         std::vector<int> natoms;
     608           7 :         for(const auto & pp : inputs ) {
     609           4 :           plumed_assert(pp);
     610           4 :           DomainDecomposition* dd=pp->castToDomainDecomposition();
     611           4 :           if ( dd ) {
     612           1 :             natoms.push_back( dd->getNumberOfAtoms() );
     613             :           }
     614             :         }
     615           3 :         actionSet.clearDelete();
     616             :         inputs.clear();
     617           4 :         for(unsigned i=0; i<natoms.size(); ++i) {
     618             :           std::string str_natoms;
     619           1 :           Tools::convert( natoms[i], str_natoms );
     620           3 :           readInputLine( MDEngine + ": DOMAIN_DECOMPOSITION NATOMS=" + str_natoms +
     621           2 :                          " VALUE1=posx UNIT1=length PERIODIC1=NO CONSTANT1=False ROLE1=x" +
     622           2 :                          " VALUE2=posy UNIT2=length PERIODIC2=NO CONSTANT2=False ROLE2=y" +
     623           2 :                          " VALUE3=posz UNIT3=length PERIODIC3=NO CONSTANT3=False ROLE3=z" +
     624           2 :                          " VALUE4=Masses UNIT4=mass PERIODIC4=NO CONSTANT4=True ROLE4=m" +
     625             :                          " VALUE5=Charges UNIT5=charge PERIODIC5=NO CONSTANT5=True ROLE5=q");
     626             : 
     627             :         }
     628           3 :         setUnits( passtools->usingNaturalUnits, passtools->units );
     629             :       }
     630           3 :       break;
     631             :       case cmd_getApiVersion:
     632          49 :         CHECK_NOTNULL(val,word);
     633          49 :         val.set(int(10));
     634             :         break;
     635             :       // commands which can be used only before initialization:
     636        1636 :       case cmd_init:
     637        1636 :         CHECK_NOTINIT(initialized,word);
     638        1636 :         init();
     639             :         break;
     640        1148 :       case cmd_setRealPrecision:
     641        1148 :         CHECK_NOTINIT(initialized,word);
     642        1148 :         CHECK_NOTNULL(val,word);
     643        2295 :         passtools=DataPassingTools::create(val.get<int>());
     644        1147 :         passtools->usingNaturalUnits=false;
     645        1147 :         break;
     646        1011 :       case cmd_setMDLengthUnits:
     647        1011 :         CHECK_NOTINIT(initialized,word);
     648        1011 :         CHECK_NOTNULL(val,word);
     649        1011 :         passtools->MDUnits.setLength(passtools->MD2double(val));
     650             :         break;
     651        1011 :       case cmd_setMDChargeUnits:
     652        1011 :         CHECK_NOTINIT(initialized,word);
     653        1011 :         CHECK_NOTNULL(val,word);
     654        1011 :         passtools->MDUnits.setCharge(passtools->MD2double(val));
     655             :         break;
     656        1011 :       case cmd_setMDMassUnits:
     657        1011 :         CHECK_NOTINIT(initialized,word);
     658        1011 :         CHECK_NOTNULL(val,word);
     659        1011 :         passtools->MDUnits.setMass(passtools->MD2double(val));
     660             :         break;
     661          45 :       case cmd_setMDEnergyUnits:
     662          45 :         CHECK_NOTINIT(initialized,word);
     663          45 :         CHECK_NOTNULL(val,word);
     664          45 :         passtools->MDUnits.setEnergy(passtools->MD2double(val));
     665             :         break;
     666           6 :       case cmd_setMDTimeUnits:
     667           6 :         CHECK_NOTINIT(initialized,word);
     668           6 :         CHECK_NOTNULL(val,word);
     669           6 :         passtools->MDUnits.setTime(passtools->MD2double(val));
     670             :         break;
     671           0 :       case cmd_setNaturalUnits:
     672             :         // set the boltzman constant for MD in natural units (kb=1)
     673             :         // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...)
     674             :         // use as cmd("setNaturalUnits")
     675           0 :         CHECK_NOTINIT(initialized,word);
     676           0 :         passtools->usingNaturalUnits=true;
     677           0 :         break;
     678          69 :       case cmd_setNoVirial: {
     679          69 :         CHECK_NOTINIT(initialized,word);
     680          69 :         ActionToPutData* ap=actionSet.selectWithLabel<ActionToPutData*>("Box");
     681          69 :         if( ap ) {
     682          53 :           ap->noforce=true;
     683             :         } else {
     684          16 :           ActionForInterface* af = actionSet.selectWithLabel<ActionForInterface*>(MDEngine);
     685          16 :           if( af ) {
     686           0 :             plumed_merror("setNoVirial should be called after number of atoms have been set");
     687             :           }
     688             :         }
     689             :       }
     690             :       break;
     691        1062 :       case cmd_setPlumedDat:
     692        1062 :         CHECK_NOTINIT(initialized,word);
     693        1062 :         CHECK_NOTNULL(val,word);
     694        1062 :         plumedDat=val.getCString();
     695             :         break;
     696         522 :       case cmd_setMPIComm:
     697         522 :         CHECK_NOTINIT(initialized,word);
     698         522 :         comm.Set_comm(val);
     699         524 :         for(const auto & pp : inputs ) {
     700           2 :           pp->Set_comm(comm);
     701             :         }
     702             :         break;
     703           0 :       case cmd_setMPIFComm:
     704           0 :         CHECK_NOTINIT(initialized,word);
     705           0 :         comm.Set_fcomm(val);
     706           0 :         for(const auto & pp : inputs ) {
     707           0 :           pp->Set_comm(comm);
     708             :         }
     709             :         break;
     710           0 :       case cmd_setMPImultiSimComm:
     711           0 :         CHECK_NOTINIT(initialized,word);
     712           0 :         multi_sim_comm.Set_comm(val);
     713             :         break;
     714        1618 :       case cmd_setNatoms: {
     715        1618 :         CHECK_NOTINIT(initialized,word);
     716        1618 :         CHECK_NOTNULL(val,word);
     717        1618 :         int natoms = val.get<int>();
     718             :         std::string str_natoms;
     719        1608 :         Tools::convert( natoms, str_natoms );
     720        1608 :         ActionForInterface* dd=actionSet.selectWithLabel<ActionForInterface*>(MDEngine);
     721        1608 :         if( !dd && natoms>0 )
     722        4599 :           readInputLine( MDEngine + ": DOMAIN_DECOMPOSITION NATOMS=" + str_natoms +  +
     723        3066 :                          " VALUE1=posx UNIT1=length PERIODIC1=NO CONSTANT1=False ROLE1=x" +
     724        3066 :                          " VALUE2=posy UNIT2=length PERIODIC2=NO CONSTANT2=False ROLE2=y" +
     725        3066 :                          " VALUE3=posz UNIT3=length PERIODIC3=NO CONSTANT3=False ROLE3=z" +
     726        3066 :                          " VALUE4=Masses UNIT4=mass PERIODIC4=NO CONSTANT4=True ROLE4=m" +
     727        3066 :                          " VALUE5=Charges UNIT5=charge PERIODIC5=NO CONSTANT5=True ROLE5=q", true );
     728             :       }
     729        1608 :       break;
     730        1362 :       case cmd_setTimestep: {
     731        1362 :         CHECK_NOTINIT(initialized,word);
     732        1362 :         CHECK_NOTNULL(val,word);
     733        1362 :         ActionToPutData* ts = actionSet.selectWithLabel<ActionToPutData*>("timestep");
     734        1362 :         if( !ts ) {
     735        1360 :           readInputLine("timestep: PUT UNIT=time PERIODIC=NO CONSTANT ROUND_TO_BASE_TEN", true);
     736        2720 :           ts = actionSet.selectWithLabel<ActionToPutData*>("timestep");
     737             :         }
     738        2724 :         if( !ts->setValuePointer("timestep", val ) ) {
     739           0 :           plumed_error();
     740             :         }
     741        1362 :         ts->updateUnits( passtools.get() );
     742             :       }
     743             :       break;
     744             :       /* ADDED WITH API==2 */
     745         220 :       case cmd_setKbT: {
     746         220 :         CHECK_NOTINIT(initialized,word);
     747         220 :         CHECK_NOTNULL(val,word);
     748         220 :         readInputLine("kBT: PUT CONSTANT PERIODIC=NO UNIT=energy", true);
     749         220 :         ActionToPutData* kb = actionSet.selectWithLabel<ActionToPutData*>("kBT");
     750         440 :         if( !kb->setValuePointer("kBT", val ) ) {
     751           0 :           plumed_error();
     752             :         }
     753         220 :         kb->updateUnits( passtools.get() );
     754             :       }
     755             :       break;
     756             :       /* ADDED WITH API==3 */
     757           8 :       case cmd_setRestart:
     758           8 :         CHECK_NOTINIT(initialized,word);
     759           8 :         CHECK_NOTNULL(val,word);
     760           8 :         if(val.get<int>()!=0) {
     761           2 :           restart=true;
     762             :         }
     763             :         break;
     764             :       /* ADDED WITH API==4 */
     765           0 :       case cmd_doCheckPoint:
     766           0 :         CHECK_INIT(initialized,word);
     767           0 :         CHECK_NOTNULL(val,word);
     768           0 :         doCheckPoint = false;
     769           0 :         if(val.get<int>()!=0) {
     770           0 :           doCheckPoint = true;
     771             :         }
     772             :         break;
     773             :       /* ADDED WITH API==6 */
     774             :       case cmd_setNumOMPthreads:
     775           3 :         CHECK_NOTNULL(val,word);
     776             :         {
     777           3 :           auto nt=val.get<unsigned>();
     778             :           if(nt==0) {
     779             :             nt=1;
     780             :           }
     781           3 :           OpenMP::setNumThreads(nt);
     782             :         }
     783             :         break;
     784             :       /* ADDED WITH API==10 */
     785             :       case cmd_setGpuDeviceId:
     786           0 :         CHECK_NOTNULL(val,word);
     787             :         {
     788           0 :           auto id=val.get<int>();
     789           0 :           if(id>=0) {
     790           0 :             gpuDeviceId=id;
     791             :           }
     792             :         }
     793             :         break;
     794             :       /* ADDED WITH API==6 */
     795             :       /* only used for testing */
     796             :       case cmd_throw:
     797          61 :         CHECK_NOTNULL(val,word);
     798          61 :         testThrow(val.getCString());
     799             :       /* ADDED WITH API==10 */
     800             :       case cmd_setNestedExceptions:
     801          31 :         CHECK_NOTNULL(val,word);
     802          31 :         if(val.get<int>()!=0) {
     803          30 :           nestedExceptions=true;
     804             :         } else {
     805           1 :           nestedExceptions=false;
     806             :         }
     807             :         break;
     808             :       /* STOP API */
     809        1083 :       case cmd_setMDEngine:
     810        1083 :         CHECK_NOTINIT(initialized,word);
     811        1083 :         CHECK_NOTNULL(val,word);
     812        1083 :         MDEngine=val.getCString();
     813             :         break;
     814        1051 :       case cmd_setLog:
     815        1051 :         CHECK_NOTINIT(initialized,word);
     816        1051 :         log.link(val.get<FILE*>());
     817             :         break;
     818         290 :       case cmd_setLogFile:
     819         290 :         CHECK_NOTINIT(initialized,word);
     820         290 :         CHECK_NOTNULL(val,word);
     821         290 :         log.open(val.getCString());
     822         290 :         break;
     823             :       // other commands that should be used after initialization:
     824      269225 :       case cmd_setStopFlag:
     825      269225 :         CHECK_INIT(initialized,word);
     826      269225 :         CHECK_NOTNULL(val,word);
     827      269225 :         val.get<int*>(); // just check type and discard pointer
     828      269224 :         stopFlag=val.copy();
     829      269224 :         break;
     830           0 :       case cmd_getExchangesFlag:
     831           0 :         CHECK_INIT(initialized,word);
     832           0 :         CHECK_NOTNULL(val,word);
     833           0 :         exchangePatterns.getFlag(*val.get<int*>()); // note: getFlag changes the value of the reference!
     834             :         break;
     835           0 :       case cmd_setExchangesSeed:
     836           0 :         CHECK_INIT(initialized,word);
     837           0 :         CHECK_NOTNULL(val,word);
     838           0 :         exchangePatterns.setSeed(val.get<int>());
     839             :         break;
     840           0 :       case cmd_setNumberOfReplicas:
     841           0 :         CHECK_INIT(initialized,word);
     842           0 :         CHECK_NOTNULL(val,word);
     843           0 :         exchangePatterns.setNofR(val.get<int>());
     844             :         break;
     845           0 :       case cmd_getExchangesList:
     846           0 :         CHECK_INIT(initialized,word);
     847           0 :         CHECK_NOTNULL(val,word);
     848           0 :         exchangePatterns.getList(val);
     849             :         break;
     850        1002 :       case cmd_runFinalJobs:
     851        1002 :         CHECK_INIT(initialized,word);
     852        1002 :         runJobsAtEndOfCalculation();
     853             :         break;
     854          96 :       case cmd_isEnergyNeeded: {
     855          96 :         CHECK_INIT(initialized,word);
     856          96 :         CHECK_NOTNULL(val,word);
     857          96 :         if( name_of_energy =="" ) {
     858          96 :           val.set(int(0));
     859             :         } else {
     860           0 :           ActionToPutData* ap=actionSet.selectWithLabel<ActionToPutData*>(name_of_energy);
     861           0 :           if(ap->isActive()) {
     862           0 :             val.set(int(1));
     863             :           } else {
     864           0 :             val.set(int(0));
     865             :           }
     866             :         }
     867             :       }
     868             :       break;
     869       72062 :       case cmd_getBias:
     870       72062 :         CHECK_INIT(initialized,word);
     871       72062 :         CHECK_NOTNULL(val,word);
     872       72062 :         plumedQuantityToMD( "energy", getBias(), val );
     873       72062 :         break;
     874             :       case cmd_checkAction:
     875           2 :         CHECK_NOTNULL(val,word);
     876           2 :         plumed_assert(nw==2);
     877           3 :         val.set(int(actionRegister().check(dlloader.getHandles(), std::string(words[1])) ? 1:0));
     878           2 :         break;
     879             :       case cmd_setExtraCV: {
     880          30 :         CHECK_NOTNULL(val,word);
     881          30 :         plumed_assert(nw==2);
     882          60 :         if( valueExists(std::string(words[1])) ) {
     883          60 :           setInputValue( std::string(words[1]), 0, 1, val );
     884             :         }
     885             :       }
     886             :       break;
     887             :       case cmd_setExtraCVForce: {
     888          30 :         CHECK_NOTNULL(val,word);
     889          30 :         plumed_assert(nw==2);
     890          60 :         if( valueExists(std::string(words[1])) ) {
     891          60 :           setInputForce( std::string(words[1]), val );
     892             :         }
     893             :       }
     894             :       break;
     895             :       /* ADDED WITH API==10 */
     896             :       case cmd_isExtraCVNeeded:
     897          10 :         CHECK_NOTNULL(val,word);
     898          10 :         plumed_assert(nw==2);
     899          10 :         val.set(int(0));
     900          56 :         for(const auto & p : inputs) {
     901          50 :           if( p->getLabel()==words[1] && p->isActive() ) {
     902           4 :             val.set(int(1));
     903             :             break;
     904             :           }
     905             :         }
     906             :         break;
     907        1445 :       case cmd_GREX:
     908        1445 :         if(!grex) {
     909         350 :           grex=Tools::make_unique<GREX>(*this);
     910             :         }
     911        1445 :         plumed_massert(grex,"error allocating grex");
     912             :         {
     913        1445 :           std::string kk=std::string(words[1]);
     914        1616 :           for(unsigned i=2; i<words.size(); i++) {
     915         342 :             kk+=" "+std::string(words[i]);
     916             :           }
     917        1445 :           grex->cmd(kk.c_str(),val);
     918             :         }
     919        1445 :         break;
     920       18790 :       case cmd_CLTool:
     921       18790 :         CHECK_NOTINIT(initialized,word);
     922       18790 :         if(!cltool) {
     923        6160 :           cltool=Tools::make_unique<CLToolMain>();
     924             :         }
     925             :         {
     926       18790 :           std::string kk(words[1]);
     927       18790 :           for(unsigned i=2; i<words.size(); i++) {
     928           0 :             kk+=" "+std::string(words[i]);
     929             :           }
     930       18790 :           cltool->cmd(kk.c_str(),val);
     931             :         }
     932       18790 :         break;
     933             :         break;
     934             :       /* ADDED WITH API==7 */
     935             :       case cmd_convert: {
     936             :         double v;
     937          57 :         plumed_assert(words.size()==2);
     938         297 :         if(Tools::convertNoexcept(std::string(words[1]),v)) {
     939          47 :           passtools->double2MD(v,val);
     940             :         }
     941             :       }
     942          57 :       break;
     943           7 :       default:
     944          14 :         plumed_error() << "cannot interpret cmd(\"" << word << "\"). check plumed developers manual to see the available commands.";
     945             :         break;
     946             :       }
     947             :     }
     948             : 
     949     1931962 :   } catch (...) {
     950         183 :     if(log.isOpen()) {
     951             :       try {
     952         109 :         log<<"\n################################################################################\n";
     953         109 :         log<<Tools::concatenateExceptionMessages();
     954         109 :         log<<"\n################################################################################\n";
     955         109 :         log.flush();
     956           0 :       } catch(...) {
     957             :         // ignore errors here.
     958             :         // in any case, we are rethrowing this below
     959           0 :       }
     960             :     }
     961         183 :     throw;
     962         183 :   }
     963     1931596 : }
     964             : 
     965             : ////////////////////////////////////////////////////////////////////////
     966             : 
     967        1636 : void PlumedMain::init() {
     968             : // check that initialization just happens once
     969        1636 :   initialized=true;
     970        1636 :   if(!log.isOpen()) {
     971         295 :     log.link(stdout);
     972             :   }
     973        1636 :   log<<"PLUMED is starting\n";
     974        4908 :   log<<"Version: "<<config::getVersionLong()<<" (git: "<<config::getVersionGit()<<") "
     975        6544 :      <<"compiled on " <<config::getCompilationDate() << " at " << config::getCompilationTime() << "\n";
     976        1636 :   log<<"Please cite these papers when using PLUMED ";
     977        3272 :   log<<cite("The PLUMED consortium, Nat. Methods 16, 670 (2019)");
     978        3272 :   log<<cite("Tribello, Bonomi, Branduardi, Camilloni, and Bussi, Comput. Phys. Commun. 185, 604 (2014)");
     979        1636 :   log<<"\n";
     980        1636 :   log<<"For further information see the PLUMED web page at http://www.plumed.org\n";
     981        1636 :   log<<"Root: "<<config::getPlumedRoot()<<"\n";
     982        1636 :   log<<"LibraryPath: "<<config::getLibraryPath()<<"\n";
     983        3272 :   log<<"For installed feature, see "<<config::getPlumedRoot() + "/src/config/config.txt\n";
     984        1636 :   log.printf("Molecular dynamics engine: %s\n",MDEngine.c_str());
     985        1636 :   log.printf("Precision of reals: %d\n",passtools->getRealPrecision());
     986        2868 :   log.printf("Running over %d %s\n",comm.Get_size(),(comm.Get_size()>1?"nodes":"node"));
     987        1636 :   log<<"Number of threads: "<<OpenMP::getNumThreads()<<"\n";
     988        1636 :   log<<"Cache line size: "<<OpenMP::getCachelineSize()<<"\n";
     989        6312 :   for(const auto & pp : inputs ) {
     990        4676 :     plumed_assert(pp);
     991        4676 :     DomainDecomposition* dd=pp->castToDomainDecomposition();
     992        4676 :     if ( dd ) {
     993        1532 :       log.printf("Number of atoms: %d\n",dd->getNumberOfAtoms());
     994             :     }
     995             :   }
     996        1636 :   if(grex) {
     997         350 :     log.printf("GROMACS-like replica exchange is on\n");
     998             :   }
     999        1636 :   log.printf("File suffix: %s\n",getSuffix().c_str());
    1000        1636 :   if(plumedDat.length()>0) {
    1001        1062 :     readInputFile(plumedDat);
    1002             :     plumedDat="";
    1003             :   }
    1004        1636 :   setUnits( passtools->usingNaturalUnits, passtools->units );
    1005        1636 :   ActionToPutData* ts = actionSet.selectWithLabel<ActionToPutData*>("timestep");
    1006        1636 :   if(ts) {
    1007        1360 :     log.printf("Timestep: %f\n",(ts->copyOutput(0))->get());
    1008             :   }
    1009        1636 :   ActionToPutData* kb = actionSet.selectWithLabel<ActionToPutData*>("kBT");
    1010        1636 :   if(kb) {
    1011         220 :     log.printf("KbT: %f\n",(kb->copyOutput(0))->get());
    1012             :   } else {
    1013        1416 :     log.printf("KbT has not been set by the MD engine\n");
    1014        1416 :     log.printf("It should be set by hand where needed\n");
    1015             :   }
    1016        1636 :   log<<"Relevant bibliography:\n";
    1017        1636 :   log<<citations;
    1018        1636 :   log<<"Please read and cite where appropriate!\n";
    1019        1636 :   log<<"Finished setup\n";
    1020        1636 : }
    1021             : 
    1022       56497 : void PlumedMain::setupInterfaceActions() {
    1023       56497 :   inputs.clear();
    1024       56497 :   std::vector<ActionForInterface*> ap=actionSet.select<ActionForInterface*>();
    1025      453199 :   for(unsigned i=0; i<ap.size(); ++i) {
    1026      396702 :     if( ap[i]->getName()=="ENERGY" || ap[i]->getDependencies().size()==0 ) {
    1027      151497 :       inputs.push_back( ap[i] );
    1028             :     }
    1029             :   }
    1030       56497 : }
    1031             : 
    1032        1085 : void PlumedMain::readInputFile(const std::string & str) {
    1033        1085 :   plumed_assert(initialized);
    1034        1085 :   log<<"FILE: "<<str<<"\n";
    1035        1085 :   IFile ifile;
    1036        1085 :   ifile.link(*this);
    1037        1085 :   ifile.open(str);
    1038        1085 :   ifile.allowNoEOL();
    1039        1085 :   readInputFile(ifile);
    1040        1085 :   log<<"END FILE: "<<str<<"\n";
    1041        1085 :   log.flush();
    1042             : 
    1043        1085 : }
    1044             : 
    1045        1091 : void PlumedMain::readInputFile(IFile & ifile) {
    1046             :   std::vector<std::string> words;
    1047       19932 :   while(Tools::getParsedLine(ifile,words) && !endPlumed) {
    1048       18841 :     readInputWords(words,false);
    1049             :   }
    1050        1091 :   endPlumed=false;
    1051        1091 :   pilots=actionSet.select<ActionPilot*>();
    1052        1091 :   setupInterfaceActions();
    1053        1091 : }
    1054             : 
    1055       14191 : void PlumedMain::readInputLine(const std::string & str, const bool& before_init) {
    1056       14191 :   if( !before_init ) {
    1057        1842 :     plumed_assert(initialized);
    1058             :   }
    1059       14191 :   if(str.empty()) {
    1060           0 :     return;
    1061             :   }
    1062       14191 :   std::vector<std::string> words=Tools::getWords(str);
    1063       14191 :   if( before_init ) {
    1064       12349 :     plumed_assert( citations.empty() );
    1065             :   }
    1066       14191 :   citations.clear();
    1067       14191 :   readInputWords(words,before_init);
    1068       14134 :   if(!citations.empty()) {
    1069          27 :     log<<"Relevant bibliography:\n";
    1070          27 :     log<<citations;
    1071          27 :     log<<"Please read and cite where appropriate!\n";
    1072             :   }
    1073       14191 : }
    1074             : 
    1075           6 : void PlumedMain::readInputLines(const std::string & str) {
    1076           6 :   plumed_assert(initialized);
    1077           6 :   if(str.empty()) {
    1078           0 :     return;
    1079             :   }
    1080             : 
    1081           6 :   log<<"FILE: (temporary)\n";
    1082             : 
    1083             :   // Open a temporary file
    1084           6 :   auto fp=std::tmpfile();
    1085           6 :   plumed_assert(fp);
    1086             : 
    1087             :   // make sure file is closed (and thus deleted) also if an exception occurs
    1088             :   auto deleter=[](auto fp) {
    1089           6 :     std::fclose(fp);
    1090             :   };
    1091             :   std::unique_ptr<FILE,decltype(deleter)> fp_deleter(fp,deleter);
    1092             : 
    1093           6 :   auto ret=std::fputs(str.c_str(),fp);
    1094           6 :   plumed_assert(ret!=EOF);
    1095             : 
    1096           6 :   std::rewind(fp);
    1097             : 
    1098           6 :   IFile ifile;
    1099           6 :   ifile.link(*this);
    1100           6 :   ifile.link(fp);
    1101           6 :   ifile.allowNoEOL();
    1102             : 
    1103           6 :   readInputFile(ifile);
    1104           6 :   log<<"END FILE: (temporary)\n";
    1105           6 : }
    1106             : 
    1107       55650 : void PlumedMain::readInputWords(const std::vector<std::string> & words, const bool& before_init) {
    1108       55650 :   if( !before_init ) {
    1109       43301 :     plumed_assert(initialized);
    1110             :   }
    1111       55650 :   if(words.empty()) {
    1112             :     return;
    1113       55478 :   } else if(words[0]=="_SET_SUFFIX") {
    1114           3 :     plumed_assert(words.size()==2);
    1115             :     setSuffix(words[1]);
    1116             :   } else {
    1117       55475 :     std::vector<std::string> interpreted(words);
    1118       55475 :     Tools::interpretLabel(interpreted);
    1119      110878 :     auto action=actionRegister().create(dlloader.getHandles(),ActionOptions(*this,interpreted));
    1120       55403 :     if(!action) {
    1121             :       std::string msg;
    1122             :       msg ="ERROR\nI cannot understand line:";
    1123           0 :       for(unsigned i=0; i<interpreted.size(); ++i) {
    1124           0 :         msg+=" "+interpreted[i];
    1125             :       }
    1126             :       msg+="\nMaybe a missing space or a typo?";
    1127           0 :       log << msg;
    1128           0 :       log.flush();
    1129           0 :       plumed_merror(msg);
    1130             :     }
    1131       55403 :     action->checkRead();
    1132       55403 :     actionSet.emplace_back(std::move(action));
    1133       55475 :   };
    1134             : 
    1135       55406 :   pilots=actionSet.select<ActionPilot*>();
    1136       55406 :   setupInterfaceActions();
    1137             : }
    1138             : 
    1139             : ////////////////////////////////////////////////////////////////////////
    1140             : 
    1141           0 : void PlumedMain::exit(int c) {
    1142           0 :   comm.Abort(c);
    1143           0 : }
    1144             : 
    1145       55473 : Log& PlumedMain::getLog() {
    1146       55473 :   return log;
    1147             : }
    1148             : 
    1149      357689 : void PlumedMain::calc() {
    1150      357689 :   prepareCalc();
    1151      357673 :   performCalc();
    1152      357671 : }
    1153             : 
    1154      364674 : void PlumedMain::prepareCalc() {
    1155      364674 :   prepareDependencies();
    1156      364674 :   shareData();
    1157      364658 : }
    1158             : 
    1159             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1160             : // here we have the main steps in "calc()"
    1161             : // they can be called individually, but the standard thing is to
    1162             : // traverse them in this order:
    1163      365001 : void PlumedMain::prepareDependencies() {
    1164             : 
    1165             : // Stopwatch is stopped when sw goes out of scope
    1166      365001 :   auto sw=stopwatch.startStop("1 Prepare dependencies");
    1167             : 
    1168             : // activate all the actions which are on step
    1169             : // activation is recursive and enables also the dependencies
    1170             : // before doing that, the prepare() method is called to see if there is some
    1171             : // new/changed dependency (up to now, only useful for dependences on virtual atoms,
    1172             : // which can be dynamically changed).
    1173             : 
    1174             : // First switch off all actions
    1175     5754068 :   for(const auto & p : actionSet) {
    1176     5389067 :     p->deactivate();
    1177             :   }
    1178             : 
    1179             : // for optimization, an "active" flag remains false if no action at all is active
    1180      365001 :   active=false;
    1181     1889631 :   for(unsigned i=0; i<pilots.size(); ++i) {
    1182     1524630 :     if(pilots[i]->onStep()) {
    1183     1429488 :       pilots[i]->activate();
    1184     1429488 :       active=true;
    1185             :     }
    1186             :   };
    1187             : 
    1188             : // This stops the driver calculation if there is not a read action
    1189      365001 :   if( !active && !inputsAreActive() ) {
    1190           2 :     stopFlag.set(int(1));
    1191             :   }
    1192             : 
    1193             : // also, if one of them is the total energy, tell to atoms that energy should be collected
    1194     5754068 :   for(const auto & p : actionSet) {
    1195     5389067 :     if(p->isActive()) {
    1196     3361967 :       if(p->checkNeedsGradients()) {
    1197         172 :         p->setOption("GRADIENTS");
    1198             :       }
    1199             :     }
    1200             :   }
    1201             : 
    1202      365001 : }
    1203             : 
    1204        1808 : bool PlumedMain::inputsAreActive() const {
    1205        5268 :   for(const auto & ip : inputs) {
    1206        5212 :     if( ip->onStep() ) {
    1207             :       return true;
    1208             :     }
    1209             :   }
    1210             :   return false;
    1211             : }
    1212             : 
    1213         114 : void PlumedMain::shareAll() {
    1214         456 :   for(const auto & ip : inputs) {
    1215         342 :     ip->shareAll();
    1216             :   }
    1217         114 : }
    1218             : 
    1219      364758 : void PlumedMain::shareData() {
    1220             : // atom positions are shared (but only if there is something to do)
    1221      364758 :   if(!active) {
    1222        1748 :     return;
    1223             :   }
    1224             : // Stopwatch is stopped when sw goes out of scope
    1225      363010 :   auto sw=stopwatch.startStop("2 Sharing data");
    1226     1127440 :   for(const auto & ip : inputs) {
    1227      764446 :     ip->share();
    1228             :   }
    1229      363010 : }
    1230             : 
    1231        7045 : void PlumedMain::performCalcNoUpdate() {
    1232        7045 :   waitData();
    1233        7045 :   justCalculate();
    1234        7045 :   backwardPropagate();
    1235        7045 :   resetInputs();
    1236        7045 : }
    1237             : 
    1238          10 : void PlumedMain::performCalcNoForces() {
    1239          10 :   waitData();
    1240          10 :   justCalculate();
    1241          10 : }
    1242             : 
    1243      357683 : void PlumedMain::performCalc() {
    1244      357683 :   waitData();
    1245      357683 :   justCalculate();
    1246      357683 :   backwardPropagate();
    1247      357681 :   update();
    1248      357681 :   resetInputs();
    1249      357681 : }
    1250             : 
    1251      364852 : void PlumedMain::waitData() {
    1252      364852 :   if(!active) {
    1253        1748 :     return;
    1254             :   }
    1255             : // Stopwatch is stopped when sw goes out of scope
    1256      363104 :   auto sw=stopwatch.startStop("3 Waiting for data");
    1257     1127852 :   for(const auto & ip : inputs) {
    1258             :     // shareData also starts the first-step domain exchange for inactive
    1259             :     // inputs, to initialize fixed masses and charges. Complete that exchange
    1260             :     // before clearing firststep, or later atomic actions receive stale data.
    1261      764748 :     if( (ip->isActive() || ip->firststep) && ip->hasBeenSet() ) {
    1262      325311 :       ip->wait();
    1263      439437 :     } else if( ip->isActive() ) {
    1264        8084 :       ip->warning("input requested but this quantity has not been set");
    1265             :     }
    1266             :   }
    1267      363104 : }
    1268             : 
    1269      364852 : void PlumedMain::justCalculate() {
    1270      364852 :   if(!active) {
    1271        1748 :     return;
    1272             :   }
    1273             : // Stopwatch is stopped when sw goes out of scope
    1274      363104 :   auto sw=stopwatch.startStop("4 Calculating (forward loop)");
    1275      363104 :   bias=0.0;
    1276      363104 :   work=0.0;
    1277             : 
    1278             :   // Check the input actions to determine if we need to calculate constants that
    1279             :   // depend on masses and charges
    1280             :   bool firststep=false;
    1281     1127852 :   for(const auto & ip : inputs) {
    1282      764748 :     if( ip->firststep ) {
    1283             :       firststep=true;
    1284             :     }
    1285             :   }
    1286      363104 :   if( firststep ) {
    1287        5938 :     for(const auto & ip : inputs) {
    1288        4450 :       ip->firststep=false;
    1289             :     }
    1290             :   }
    1291             : 
    1292             :   int iaction=0;
    1293             : // calculate the active actions in order (assuming *backward* dependence)
    1294     5720633 :   for(const auto & pp : actionSet) {
    1295             :     Action* p(pp.get());
    1296     5357529 :     plumed_assert(p);
    1297             :     try {
    1298     5357529 :       if(p->isActive()) {
    1299             : // Stopwatch is stopped when sw goes out of scope.
    1300             : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
    1301     3359972 :         Stopwatch::Handler sw;
    1302     3359972 :         if(detailedTimers) {
    1303        2481 :           auto actionNumberLabel=std::to_string(iaction);
    1304        2481 :           const unsigned m=actionSet.size();
    1305             :           unsigned k=0;
    1306             :           unsigned n=1;
    1307        7443 :           while(n<m) {
    1308        4962 :             n*=10;
    1309        4962 :             k++;
    1310             :           }
    1311        2481 :           auto spaces=std::string(k-actionNumberLabel.length(),' ');
    1312        2481 :           sw=stopwatch.startStop("4A " + spaces + actionNumberLabel+" "+p->getLabel());
    1313             :         }
    1314     3359972 :         ActionWithValue*av=p->castToActionWithValue();
    1315     3359972 :         ActionAtomistic*aa=p->castToActionAtomistic();
    1316             :         {
    1317     3359972 :           if(av) {
    1318     3063973 :             av->clearInputForces();
    1319             :           }
    1320     3359972 :           if(av) {
    1321     3063973 :             av->clearDerivatives();
    1322             :           }
    1323     3359972 :           if( av && av->calculateOnUpdate() ) {
    1324             :             continue ;
    1325             :           }
    1326             :         }
    1327             :         {
    1328     3355957 :           if(aa)
    1329      630092 :             if(aa->isActive()) {
    1330      630092 :               aa->retrieveAtoms();
    1331             :             }
    1332             :         }
    1333     3355957 :         if(p->checkNumericalDerivatives()) {
    1334         246 :           p->calculateNumericalDerivatives();
    1335             :         } else {
    1336     3355711 :           p->calculate();
    1337             :         }
    1338             :         // This retrieves components called bias
    1339     3355957 :         if(av) {
    1340     3059958 :           bias+=av->getOutputQuantity("bias");
    1341     3059958 :           work+=av->getOutputQuantity("work");
    1342     3059958 :           av->setGradientsIfNeeded();
    1343             :         }
    1344             :         // This makes all values that depend on the (fixed) masses and charges constant
    1345     3355957 :         if( firststep ) {
    1346       31263 :           p->setupConstantValues( true );
    1347             :         }
    1348     3355957 :         ActionWithVirtualAtom*avv=p->castToActionWithVirtualAtom();
    1349     3355957 :         if(avv) {
    1350       35094 :           avv->setGradientsIfNeeded();
    1351             :         }
    1352     3359972 :       }
    1353           0 :     } catch(...) {
    1354           0 :       plumed_error_nested() << "An error happened while calculating " << p->getLabel();
    1355           0 :     }
    1356     5353514 :     iaction++;
    1357             :   }
    1358      363104 : }
    1359             : 
    1360           0 : void PlumedMain::justApply() {
    1361           0 :   backwardPropagate();
    1362           0 :   update();
    1363           0 :   resetInputs();
    1364           0 : }
    1365             : 
    1366      364728 : void PlumedMain::backwardPropagate() {
    1367      364728 :   if(!active) {
    1368        1748 :     return;
    1369             :   }
    1370             :   int iaction=0;
    1371             : // Stopwatch is stopped when sw goes out of scope
    1372      362980 :   auto sw=stopwatch.startStop("5 Applying (backward loop)");
    1373             : // apply them in reverse order
    1374     5718167 :   for(auto pp=actionSet.rbegin(); pp!=actionSet.rend(); ++pp) {
    1375             :     const auto & p(pp->get());
    1376     5355189 :     if(p->isActive()) {
    1377             : 
    1378             : // Stopwatch is stopped when sw goes out of scope.
    1379             : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
    1380     3358296 :       Stopwatch::Handler sw;
    1381     3358296 :       if(detailedTimers) {
    1382        2481 :         auto actionNumberLabel=std::to_string(iaction);
    1383        2481 :         const unsigned m=actionSet.size();
    1384             :         unsigned k=0;
    1385             :         unsigned n=1;
    1386        7443 :         while(n<m) {
    1387        4962 :           n*=10;
    1388        4962 :           k++;
    1389             :         }
    1390        2481 :         auto spaces=std::string(k-actionNumberLabel.length(),' ');
    1391        2481 :         sw=stopwatch.startStop("5A " + spaces + actionNumberLabel+" "+p->getLabel());
    1392             :       }
    1393             : 
    1394     3358296 :       p->apply();
    1395     3358296 :     }
    1396     5355187 :     iaction++;
    1397             :   }
    1398             : 
    1399             : // Stopwatch is stopped when sw goes out of scope.
    1400             : // We explicitly declare a Stopwatch::Handler here to allow for conditional initialization.
    1401      362978 :   Stopwatch::Handler sw1;
    1402      362978 :   if(detailedTimers) {
    1403         113 :     sw1=stopwatch.startStop("5B Update forces");
    1404             :   }
    1405      362980 : }
    1406             : 
    1407      357760 : void PlumedMain::update() {
    1408      357760 :   if(!active) {
    1409        1748 :     return;
    1410             :   }
    1411             : 
    1412             : // Stopwatch is stopped when sw goes out of scope
    1413      356012 :   auto sw=stopwatch.startStop("6 Update");
    1414             : 
    1415             : // update step (for statistics, etc)
    1416      356012 :   updateFlags.push(true);
    1417     5493490 :   for(const auto & p : actionSet) {
    1418     5137478 :     p->beforeUpdate();
    1419     8400451 :     if(p->isActive() && p->checkUpdate() && updateFlagsTop()) {
    1420     3262953 :       ActionWithValue* av=dynamic_cast<ActionWithValue*>(p.get());
    1421     3262953 :       if( av && av->calculateOnUpdate() ) {
    1422        4015 :         p->prepare();
    1423        4015 :         p->calculate();
    1424             :       } else {
    1425     3258938 :         p->update();
    1426             :       }
    1427             :     }
    1428             :   }
    1429      712028 :   while(!updateFlags.empty()) {
    1430             :     updateFlags.pop();
    1431             :   }
    1432             :   if(!updateFlags.empty()) {
    1433             :     plumed_merror("non matching changes in the update flags");
    1434             :   }
    1435             : // Check that no action has told the calculation to stop
    1436      356012 :   if(stopNow) {
    1437          65 :     if(stopFlag) {
    1438          65 :       stopFlag.set(int(1));
    1439             :     } else {
    1440           0 :       plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)");
    1441             :     }
    1442             :   }
    1443             : 
    1444             : // flush by default every 10000 steps
    1445             : // hopefully will not affect performance
    1446             : // also if receive checkpointing signal
    1447      356012 :   if(step%10000==0||doCheckPoint) {
    1448        2290 :     fflush();
    1449        2290 :     log.flush();
    1450       69963 :     for(const auto & p : actionSet) {
    1451       67673 :       p->fflush();
    1452             :     }
    1453             :   }
    1454             : // invalidate the checkpoint status
    1455             : // this fix issues like #1428
    1456      356012 :   doCheckPoint = false;
    1457      356012 : }
    1458             : 
    1459          45 : void PlumedMain::load(const std::string& fileName) {
    1460          45 :   if(DLLoader::installed()) {
    1461          45 :     std::string libName=fileName;
    1462          45 :     size_t n=libName.find_last_of(".");
    1463          46 :     std::string extension="";
    1464          45 :     std::string base=libName;
    1465          45 :     if(n!=std::string::npos && n<libName.length()-1) {
    1466          90 :       extension=libName.substr(n+1);
    1467             :     }
    1468          45 :     if(n!=std::string::npos && n<libName.length()) {
    1469          90 :       base=libName.substr(0,n);
    1470             :     }
    1471             : 
    1472          45 :     if(extension=="cpp") {
    1473          50 :       libName="./"+base+"."+config::getVersionLong()+"."+config::getSoExt();
    1474             : // full path command, including environment setup
    1475             : // this will work even if plumed is not in the execution path or if it has been
    1476             : // installed with a name different from "plumed"
    1477          50 :       std::string cmd=config::getEnvCommand()+" \""+config::getPlumedRoot()+"\"/scripts/mklib.sh -n -o "+libName+" "+fileName;
    1478             : 
    1479          25 :       if(std::getenv("PLUMED_LOAD_ACTION_DEBUG")) {
    1480           0 :         log<<"Executing: "<<cmd;
    1481             :       } else {
    1482          25 :         log<<"Compiling: "<<fileName<<" to "<<libName;
    1483             :       }
    1484             : 
    1485          25 :       if(comm.Get_size()>0) {
    1486          25 :         log<<" (only on master node)";
    1487             :       }
    1488          25 :       log<<"\n";
    1489             : 
    1490             :       // On MPI process (intracomm), we use Get_rank to make sure a single process does the compilation
    1491             :       // Processes from multiple replicas might simultaneously do the compilation.
    1492          25 :       if(comm.Get_rank()==0) {
    1493          25 :         static Tools::CriticalSectionWithKey<std::string> section;
    1494             :         // This is only locking commands that are running with identical arguments.
    1495             :         // It is not necessary for correctness (a second mklib would just result in a no op since
    1496             :         // the library is already there, even if running simultaneously).
    1497             :         // It however decreases the system load if many threads are used.
    1498             :         auto s=section.startStop(cmd);
    1499          25 :         int ret=std::system(cmd.c_str());
    1500          25 :         if(ret!=0) {
    1501           2 :           plumed_error() <<"An error happened while executing command "<<cmd<<"\n";
    1502             :         }
    1503          25 :       }
    1504          24 :       comm.Barrier();
    1505             :     } else {
    1506          40 :       libName=base+"."+config::getSoExt();
    1507             :     }
    1508             : 
    1509             :     // If we have multiple threads (each holding a Plumed object), each of them
    1510             :     // will load the library, but each of them will only see actions registered
    1511             :     // from the owned library
    1512          44 :     auto *p=dlloader.load(libName);
    1513          45 :     log<<"Loading shared library "<<libName.c_str()<<" at "<<p<<"\n";
    1514          44 :     log<<"Here is the list of new actions\n";
    1515          44 :     log<<"\n";
    1516          88 :     for(const auto & a : actionRegister().getKeysWithDLHandle(p)) {
    1517          44 :       log<<a<<"\n";
    1518          44 :     }
    1519          44 :     log<<"\n";
    1520             :   } else {
    1521           0 :     plumed_error()<<"While loading library "<< fileName << " loading was not enabled, please check if dlopen was found at configure time";
    1522             :   }
    1523          44 : }
    1524             : 
    1525      364726 : void PlumedMain::resetInputs() {
    1526     1134413 :   for(const auto & ip : inputs) {
    1527      769687 :     if( ip->isActive() && ip->hasBeenSet() ) {
    1528      323465 :       ip->reset();
    1529             :     }
    1530             :   }
    1531      364726 : }
    1532             : 
    1533       72695 : double PlumedMain::getBias() const {
    1534       72695 :   return bias;
    1535             : }
    1536             : 
    1537         450 : double PlumedMain::getWork() const {
    1538         450 :   return work;
    1539             : }
    1540             : 
    1541          82 : FILE* PlumedMain::fopen(const char *path, const char *mode) {
    1542          82 :   std::string mmode(mode);
    1543          83 :   std::string ppath(path);
    1544          82 :   std::string suffix(getSuffix());
    1545          82 :   std::string ppathsuf=ppath+suffix;
    1546          82 :   FILE*fp=std::fopen(const_cast<char*>(ppathsuf.c_str()),const_cast<char*>(mmode.c_str()));
    1547          82 :   if(!fp) {
    1548           1 :     fp=std::fopen(const_cast<char*>(ppath.c_str()),const_cast<char*>(mmode.c_str()));
    1549             :   }
    1550          84 :   plumed_massert(fp,"file " + ppath + " cannot be found");
    1551          81 :   return fp;
    1552             : }
    1553             : 
    1554          99 : int PlumedMain::fclose(FILE*fp) {
    1555          99 :   return std::fclose(fp);
    1556             : }
    1557             : 
    1558        5553 : std::string PlumedMain::cite(const std::string&item) {
    1559        5553 :   return citations.cite(item);
    1560             : }
    1561             : 
    1562        2851 : void PlumedMain::fflush() {
    1563        6485 :   for(const auto  & p : files) {
    1564        3634 :     p->flush();
    1565             :   }
    1566        2851 : }
    1567             : 
    1568        5309 : void PlumedMain::insertFile(FileBase&f) {
    1569        5309 :   files.insert(&f);
    1570        5309 : }
    1571             : 
    1572        5620 : void PlumedMain::eraseFile(FileBase&f) {
    1573        5620 :   files.erase(&f);
    1574        5620 : }
    1575             : 
    1576          65 : void PlumedMain::stop() {
    1577          65 :   stopNow=true;
    1578          65 : }
    1579             : 
    1580        1002 : void PlumedMain::runJobsAtEndOfCalculation() {
    1581       48249 :   for(const auto & p : actionSet) {
    1582       47247 :     ActionWithValue* av=dynamic_cast<ActionWithValue*>(p.get());
    1583       47247 :     if( av && av->calculateOnUpdate() ) {
    1584         422 :       p->activate();
    1585             :     }
    1586             :   }
    1587       48249 :   for(const auto & p : actionSet) {
    1588       47247 :     ActionPilot* ap=dynamic_cast<ActionPilot*>(p.get());
    1589       47247 :     ActionWithValue* av=dynamic_cast<ActionWithValue*>(p.get());
    1590       47247 :     if( av && av->calculateOnUpdate() ) {
    1591         422 :       p->calculate();
    1592       46825 :     } else if( ap && !av && ap->getStride()==0 ) {
    1593          78 :       p->update();
    1594             :     } else {
    1595       46747 :       p->runFinalJobs();
    1596             :     }
    1597             :   }
    1598        1002 : }
    1599             : 
    1600     8808517 : unsigned PlumedMain::increaseReferenceCounter() noexcept {
    1601     8808517 :   return ++referenceCounter;
    1602             : }
    1603             : 
    1604     8807376 : unsigned PlumedMain::decreaseReferenceCounter() noexcept {
    1605     8807376 :   return --referenceCounter;
    1606             : }
    1607             : 
    1608          42 : unsigned PlumedMain::useCountReferenceCounter() const noexcept {
    1609          42 :   return referenceCounter;
    1610             : }
    1611             : 
    1612          60 : bool PlumedMain::valueExists( const std::string& name ) const {
    1613         240 :   for(const auto & p : inputs) {
    1614         240 :     if( p->getLabel()==name ) {
    1615             :       return true;
    1616             :     }
    1617             :   }
    1618             :   return false;
    1619             : }
    1620             : 
    1621      818403 : void PlumedMain::setInputValue( const std::string& name, const unsigned& start, const unsigned& stride, const TypesafePtr & val ) {
    1622             :   bool found=false;
    1623     1894997 :   for(const auto & pp : inputs) {
    1624     1894997 :     if( pp->setValuePointer( name, val ) ) {
    1625      818399 :       pp->setStart(name, start);
    1626      818399 :       pp->setStride(name, stride);
    1627             :       found=true;
    1628             :       break;
    1629             :     }
    1630             :   }
    1631           0 :   plumed_massert( found, "found no action to set named " + name );
    1632      818399 : }
    1633             : 
    1634      555645 : void PlumedMain::setInputForce( const std::string& name, const TypesafePtr & val ) {
    1635             :   bool found=false;
    1636     1249069 :   for(const auto & pp : inputs) {
    1637     1249069 :     if( pp->setForcePointer( name, val ) ) {
    1638             :       found=true;
    1639             :       break;
    1640             :     }
    1641             :   }
    1642      555627 :   plumed_massert( found, "found no action to set named " + name );
    1643      555627 : }
    1644             : 
    1645        1674 : void PlumedMain::setUnits( const bool& natural, const Units& u ) {
    1646        1674 :   passtools->usingNaturalUnits = natural;
    1647        1674 :   passtools->units=u;
    1648        1674 :   std::vector<ActionToPutData*> idata = actionSet.select<ActionToPutData*>();
    1649       12771 :   for(const auto & ip : idata) {
    1650       11097 :     ip->updateUnits( passtools.get() );
    1651             :   }
    1652       54327 :   for(const auto & p : actionSet ) {
    1653       52653 :     p->resetStoredTimestep();
    1654             :   }
    1655        1674 : }
    1656             : 
    1657      364671 : void PlumedMain::startStep() {
    1658     1134150 :   for(const auto & ip : inputs) {
    1659      769479 :     ip->resetForStepStart();
    1660             :   }
    1661      364671 : }
    1662             : 
    1663         114 : void PlumedMain::writeBinary(std::ostream&o)const {
    1664         456 :   for(const auto & ip : inputs) {
    1665         342 :     ip->writeBinary(o);
    1666             :   }
    1667         114 : }
    1668             : 
    1669         114 : void PlumedMain::readBinary(std::istream&i) {
    1670         456 :   for(const auto & ip : inputs) {
    1671         342 :     ip->readBinary(i);
    1672             :   }
    1673         114 : }
    1674             : 
    1675          40 : void PlumedMain::setEnergyValue( const std::string& name ) {
    1676          40 :   name_of_energy = name;
    1677          40 : }
    1678             : 
    1679       10990 : int PlumedMain::getRealPrecision() const {
    1680       10990 :   return passtools->getRealPrecision();
    1681             : }
    1682             : 
    1683        5271 : bool PlumedMain::usingNaturalUnits() const {
    1684        5271 :   return passtools->usingNaturalUnits;
    1685             : }
    1686             : 
    1687    14356855 : const Units& PlumedMain::getUnits() {
    1688    14356855 :   return passtools->units;
    1689             : }
    1690             : 
    1691           4 : PlumedMain::DeprecatedAtoms& PlumedMain::getAtoms() {
    1692           4 :   return datoms;
    1693             : }
    1694             : 
    1695       72233 : void PlumedMain::plumedQuantityToMD( const std::string& unit, const double& eng, const TypesafePtr & m) const {
    1696       72233 :   passtools->double2MD( eng/passtools->getUnitConversion(unit),m );
    1697       72233 : }
    1698             : 
    1699           0 : double PlumedMain::MDQuantityToPLUMED( const std::string& unit, const TypesafePtr & m) const {
    1700           0 :   double x=passtools->MD2double(m);
    1701           0 :   return x*passtools->getUnitConversion(unit);
    1702             : }
    1703             : 
    1704           1 : double PlumedMain::DeprecatedAtoms::getKBoltzmann() const {
    1705           1 :   if( plumed.usingNaturalUnits() ) {
    1706             :     return 1.0;
    1707             :   }
    1708           1 :   return kBoltzmann/plumed.getUnits().getEnergy();
    1709             : }
    1710             : 
    1711           1 : double PlumedMain::DeprecatedAtoms::getKbT() const {
    1712           1 :   ActionForInterface* kb=plumed.getActionSet().selectWithLabel<ActionForInterface*>("kBT");
    1713           1 :   if( kb ) {
    1714           1 :     return (kb->copyOutput(0))->get();
    1715             :   }
    1716             :   return 0.0;
    1717             : }
    1718             : 
    1719           1 : int PlumedMain::DeprecatedAtoms::getNatoms() const {
    1720           1 :   std::vector<ActionToPutData*> inputs=plumed.getActionSet().select<ActionToPutData*>();
    1721           1 :   for(const auto & pp : inputs ) {
    1722           2 :     if( pp->getRole()=="x" ) {
    1723           1 :       return (pp->copyOutput(0))->getShape()[0];
    1724             :     }
    1725             :   }
    1726             :   return 0;
    1727             : }
    1728             : 
    1729           1 : bool PlumedMain::DeprecatedAtoms::usingNaturalUnits() const {
    1730           1 :   return plumed.usingNaturalUnits();
    1731             : }
    1732             : 
    1733           0 : void PlumedMain::DeprecatedAtoms::setCollectEnergy(bool b) const {
    1734           0 :   plumed.readInputWords( Tools::getWords(plumed.MDEngine + "_energy: ENERGY"), false );
    1735           0 :   plumed.setEnergyValue( plumed.MDEngine + "_energy" );
    1736           0 : }
    1737             : 
    1738           0 : double PlumedMain::DeprecatedAtoms::getEnergy() const {
    1739           0 :   ActionToPutData* av = plumed.getActionSet().selectWithLabel<ActionToPutData*>( plumed.MDEngine + "_energy" );
    1740           0 :   return (av->copyOutput(0))->get();
    1741             : }
    1742             : 
    1743           5 : void PlumedMain::activateParseOnlyMode() {
    1744           5 :   doParseOnly=true;
    1745           5 : }
    1746             : 
    1747        2338 : bool PlumedMain::parseOnlyMode() const {
    1748        2338 :   return doParseOnly;
    1749             : }
    1750             : 
    1751          97 : void PlumedMain::getKeywordsForAction( const std::string& action, Keywords& keys ) const {
    1752          97 :   actionRegister().getKeywords( dlloader.getHandles(), action, keys );
    1753          97 : }
    1754             : 
    1755             : #ifdef __PLUMED_HAS_PYTHON
    1756             : // This is here to stop cppcheck throwing an error
    1757             : #endif
    1758             : 
    1759             : #ifdef __PLUMED_HAS_DLADDR
    1760             : // This is here to stop cppcheck throwing an error
    1761             : #endif
    1762             : 
    1763             : }
    1764             : 
    1765             : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Generated by: LCOV version 1.16