LCOV - code coverage report
Current view: top level - core - Action.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 96 107 89.7 %
Date: 2026-11-12 10:48:31 Functions: 34 38 89.5 %

          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             : #ifndef __PLUMED_core_Action_h
      23             : #define __PLUMED_core_Action_h
      24             : #include <vector>
      25             : #include <string>
      26             : #include <set>
      27             : #include "tools/Keywords.h"
      28             : #include "tools/Tools.h"
      29             : #include "tools/Units.h"
      30             : #include "tools/Log.h"
      31             : 
      32             : namespace PLMD {
      33             : 
      34             : class PDB;
      35             : class PlumedMain;
      36             : class Communicator;
      37             : class ActionWithValue;
      38             : class ActionWithArguments;
      39             : class ActionAtomistic;
      40             : class ActionWithVirtualAtom;
      41             : class PbcAction;
      42             : class ActionToGetData;
      43             : class ActionToPutData;
      44             : class DomainDecomposition;
      45             : class ActionForInterface;
      46             : class ActionShortcut;
      47             : 
      48             : /// This class is used to bring the relevant information to the Action constructor.
      49             : /// Only Action and ActionRegister class can access to its content, which is
      50             : /// kept private to other classes, and may change in the future.
      51      110948 : class ActionOptions {
      52             :   friend class Action;
      53             :   friend class ActionRegister;
      54             : /// Reference to main PlumedMain object
      55             :   PlumedMain& plumed;
      56             : /// Input line which sets up the action
      57             :   std::vector<std::string> line;
      58             : /// The documentation for this action
      59             :   const Keywords& keys;
      60             :   static Keywords emptyKeys;
      61             :   std::string fullPath;
      62             : public:
      63             : /// Constructor
      64             :   ActionOptions(PlumedMain&p,const std::vector<std::string>&);
      65             :   ActionOptions(const ActionOptions&,const Keywords& keys);
      66             :   void setFullPath(const std::string & fullPath) {
      67             :     this->fullPath=fullPath;
      68       55473 :   }
      69             : };
      70             : 
      71             : /// Base class for all the input Actions.
      72             : /// The input Actions are more or less corresponding to the directives
      73             : /// in the plumed.dat file and are applied in order at each time-step.
      74             : class Action {
      75             :   friend class ActionShortcut;
      76             : 
      77             : /// Name of the directive in the plumed.dat file.
      78             :   const std::string name;
      79             : 
      80             : /// Label of the Action, as set with LABEL= in the plumed.dat file.
      81             :   std::string label;
      82             : 
      83             : /// Directive line.
      84             : /// This line is progressively erased during Action construction
      85             : /// so as to check if all the present keywords are correct.
      86             :   std::vector<std::string> line;
      87             : 
      88             : /// Update only after this time.
      89             :   double update_from;
      90             : 
      91             : /// Update only until this time.
      92             :   double update_until;
      93             : 
      94             : /// Save the timestep here
      95             :   double timestep;
      96             : 
      97             : protected:
      98             : /// Get the units that we are operating in
      99             :   const Units& getUnits() const;
     100             : /// Are we using natural units
     101             :   bool usingNaturalUnits()const;
     102             : /// Get the value of Boltzmann's constant
     103             :   double getKBoltzmann()const;
     104             : public:
     105             : 
     106             : /// Check if action should be updated.
     107             :   bool checkUpdate()const;
     108             : 
     109             : public:
     110             :   typedef std::vector<Action*> Dependencies;
     111             : 
     112             : private:
     113             : /// Actions on which this Action depends.
     114             :   Dependencies after;
     115             : 
     116             : /// Switch to activate Action on this step.
     117             :   bool active;
     118             : 
     119             : /// Option that you might have enabled
     120             :   std::set<std::string> options;
     121             : 
     122             :   bool restart;
     123             : 
     124             :   bool doCheckPoint;
     125             : 
     126             :   bool never_activate;
     127             : 
     128             : /// The set of default arguments that we are using
     129             :   std::string defaults;
     130             : public:
     131             : 
     132             : /// Reference to main plumed object
     133             :   PlumedMain& plumed;
     134             : 
     135             : /// Reference to the log stream
     136             :   Log& log;
     137             : 
     138             : /// Specify that this Action depends on another one
     139             :   void addDependency(Action*);
     140             : 
     141             : /// Check that this action does not depend on the action in the argument
     142             :   bool checkForDependency(Action*);
     143             : 
     144             : /// Clear the dependence list for this Action
     145             :   void clearDependencies();
     146             : 
     147             : /// Get the value of kBT by either reading the TEMP keyword
     148             : /// and multiplying the temperature by Boltzmann's constant
     149             : /// or get it fro the MD code
     150             :   double getkBT();
     151             : 
     152             : /// Return the present timestep
     153             :   long long int getStep()const;
     154             : 
     155             : /// Return the present time
     156             :   double getTime()const;
     157             : 
     158             : /// Return the timestep
     159             :   double getTimeStep()const;
     160             : 
     161             : /// Return true if we are doing a restart
     162             :   bool getRestart()const;
     163             : 
     164             : /// Return true if we are doing at a checkpoint step
     165             :   bool getCPT()const;
     166             : 
     167             : /// Just read one of the keywords and return the whole thing as a string
     168             :   std::string getKeyword(const std::string& key);
     169             : 
     170             : /// Parse one keyword as generic type
     171             :   template<class T>
     172             :   void parse(const std::string&key,T&t);
     173             : 
     174             : /// Parse one numbered keyword as generic type
     175             :   template<class T>
     176             :   bool parseNumbered(const std::string&key, const int no, T&t);
     177             : 
     178             : /// Parse one keyword as std::vector
     179             :   template<class T>
     180             :   void parseVector(const std::string&key,std::vector<T>&t);
     181             : 
     182             : /// Parse a vector with a number
     183             :   template<class T>
     184             :   bool parseNumberedVector(const std::string& key, const int no, std::vector<T>&t);
     185             : 
     186             : /// Parse one keyword as boolean flag
     187             :   void parseFlag(const std::string&key,bool&t);
     188             : 
     189             : /// Crash calculation and print documentation
     190             :   [[noreturn]] void error( const std::string & msg ) const;
     191             : 
     192             : /// Issue a warning
     193             :   void warning( const std::string & msg );
     194             : 
     195             : /// Exit with error code c
     196             :   void exit(int c=0);
     197             : 
     198             : ///
     199             :   std::set<FILE*> files;
     200             : 
     201             : public:
     202             : /// Standard constructor from ActionOptions
     203             :   explicit Action(const ActionOptions&);
     204             : /// Destructor
     205             :   virtual ~Action();
     206             : private:
     207             : /// Copy constructor is deleted
     208             :   Action(const Action&a) = delete;
     209             : /// Assignment operator is deleted
     210             :   Action& operator=(const Action&a) = delete;
     211             :   int replica_index;
     212             : public:
     213             : /// Check if Action was properly read.
     214             : /// This checks if Action::line is empty. It must be called after
     215             : /// a final Action has been initialized
     216             :   void checkRead();
     217             : 
     218             : /// This calculates any values that are constant and ensures
     219             : /// that we don't calculate these actions on every timestep
     220             :   void setupConstantValues( const bool& have_atoms );
     221             : 
     222             : /// Communicator of this replica: all the MPI processes running this PLUMED
     223             : /// instance (set by the MD code with setMPIComm). It is valid on every process.
     224             :   Communicator& comm;
     225             : 
     226             : /// Communicator between replicas, in multiple-replica simulations.
     227             : /// It holds one process per replica, namely process 0 of comm (set with
     228             : /// GREX setMPIIntercomm or setMPImultiSimComm).
     229             : /// It is valid only on process 0 of comm. On the other processes it is
     230             : /// MPI_COMM_SELF, so Get_size() returns 1 and Get_rank() returns 0 whatever
     231             : /// the number of replicas, and communication over it reaches no other replica.
     232             : /// Code that needs the number of replicas or the replica index on every
     233             : /// process must read them on process 0 of comm and broadcast them over comm:
     234             : /// \code
     235             : /// unsigned nrep=0, irep=0;
     236             : /// if(comm.Get_rank()==0) {
     237             : ///   nrep=multi_sim_comm.Get_size();
     238             : ///   irep=multi_sim_comm.Get_rank();
     239             : /// }
     240             : /// comm.Bcast(nrep,0);
     241             : /// comm.Bcast(irep,0);
     242             : /// \endcode
     243             : /// The same applies to communication over multi_sim_comm: do it on process 0
     244             : /// of comm, then broadcast the result over comm.
     245             : /// For how MD codes set up these communicators, see \ref mpireplicas.
     246             :   Communicator& multi_sim_comm;
     247             : 
     248             :   const Keywords& keywords;
     249             : /// Prepare an Action for calculation
     250             : /// This can be used by Action if they need some special preparation
     251             : /// before calculation. Typical case is for collective variables
     252             : /// which would like to change their list of requested atoms.
     253             : /// By default (if not overridden) does nothing.
     254             :   virtual void prepare();
     255             : 
     256             : /// Register all the relevant keywords for the action
     257             :   static void registerKeywords( Keywords& keys );
     258             : 
     259     1967381 :   virtual void lockRequests() {}
     260     1967381 :   virtual void unlockRequests() {}
     261             : 
     262             : /// Calculate an Action.
     263             : /// This method is called one or more times per step.
     264             : /// The set of all Actions is calculated in forward order.
     265             :   virtual void calculate()=0;
     266             : 
     267             : /// Apply an Action.
     268             : /// This method is called one time per step.
     269             : /// The set of all Actions is applied in backward order.
     270             :   virtual void apply()=0;
     271             : 
     272             : /// Before Update.
     273             : /// This is a special method that is called just
     274             : /// before the update() method. It can be used by
     275             : /// actions that want to do something irrespectively
     276             : /// of the fact that update() is active or not.
     277             : /// In other words, this is *always* called, even when action
     278             : /// is not active.
     279     5137401 :   virtual void beforeUpdate() {}
     280             : 
     281             : /// Update.
     282             : /// This method is called one time per step.
     283             : /// The set of all Actions is updated in forward order.
     284     1946225 :   virtual void update() {}
     285             : 
     286             : /// RunFinalJobs
     287             : /// This method is called once at the very end of the calculation.
     288             : /// The set of all Actions in run for the final time in forward order.
     289       46740 :   virtual void runFinalJobs() {}
     290             : 
     291             : /// Tell to the Action to flush open files
     292             :   void fflush();
     293             : 
     294             : /// Returns the label
     295             :   const std::string & getLabel()const;
     296             : 
     297             : /// Returns the name
     298             :   const std::string & getName()const;
     299             : 
     300             : /// Set action to active
     301             :   virtual void activate();
     302             : 
     303             : ///
     304             :   virtual void setOption(const std::string &s);
     305             : 
     306             :   virtual void clearOptions();
     307             : 
     308             : /// Set action to inactive
     309             :   virtual void deactivate();
     310             : 
     311             : /// Check if action is active
     312             :   bool isActive()const;
     313             : 
     314             : /// Check if an option is on
     315             :   bool isOptionOn(const std::string &s)const;
     316             : 
     317             : /// Return dependencies
     318             :   const Dependencies & getDependencies()const {
     319             :     return after;
     320             :   }
     321             : 
     322             : /// Check if numerical derivatives should be performed
     323      295999 :   virtual bool checkNumericalDerivatives()const {
     324      295999 :     return false;
     325             :   }
     326             : 
     327             : /// Check if the action needs gradient
     328     3353136 :   virtual bool checkNeedsGradients()const {
     329     3353136 :     return false;
     330             :   }
     331             : 
     332             : /// Perform calculation using numerical derivatives
     333             : /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
     334             : /// are doing.
     335             :   virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
     336             : 
     337             : /// Opens a file.
     338             : /// This is similar to plain fopen, but with some extra functionality.
     339             : /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
     340             : /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
     341             :   FILE *fopen(const char *path, const char *mode);
     342             : /// Closes a file opened with Action::fclose().
     343             :   int   fclose(FILE*fp);
     344             : 
     345             : /// Calculate the action given a pdb file as input.  This is used to initialize
     346             : /// things like distance from a point in CV map space given a pdb as an input file
     347             :   void calculateFromPDB( const PDB&  );
     348             : /// This is overwritten in ActionAtomistic so that we can read
     349             : /// the atoms from the pdb input file rather than taking them from the
     350             : /// MD code
     351           0 :   virtual void readAtomsFromPDB( const PDB&  ) {}
     352             : /// Check if we are on an exchange step
     353             :   bool getExchangeStep()const;
     354             : 
     355             : /// Cite a paper see PlumedMain::cite
     356             :   std::string cite(const std::string&s);
     357             : 
     358             : /// Get the defaults
     359             :   std::string getDefaultString() const ;
     360             : 
     361             : /// Set the timestep that is stored in the action to the correct value
     362             :   void resetStoredTimestep();
     363             : 
     364             : /// Get the info on what to calculate
     365             :   virtual std::string writeInGraph() const ;
     366             : /// Specialized casts, to make PlumedMain run faster
     367      307754 :   virtual ActionWithValue* castToActionWithValue() noexcept {
     368      307754 :     return nullptr;
     369             :   }
     370       80099 :   virtual ActionWithArguments* castToActionWithArguments() noexcept {
     371       80099 :     return nullptr;
     372             :   }
     373     2745568 :   virtual ActionAtomistic* castToActionAtomistic() noexcept {
     374     2745568 :     return nullptr;
     375             :   }
     376     4134724 :   virtual ActionWithVirtualAtom* castToActionWithVirtualAtom() noexcept {
     377     4134724 :     return nullptr;
     378             :   }
     379           0 :   virtual PbcAction* castToPbcAction() noexcept {
     380           0 :     return nullptr;
     381             :   }
     382     7348170 :   virtual ActionToPutData* castToActionToPutData() noexcept {
     383     7348170 :     return nullptr;
     384             :   }
     385           0 :   virtual ActionToGetData* castToActionToGetData() noexcept {
     386           0 :     return nullptr;
     387             :   }
     388        8926 :   virtual DomainDecomposition* castToDomainDecomposition() noexcept {
     389        8926 :     return nullptr;
     390             :   }
     391         659 :   virtual ActionForInterface* castToActionForInterface() noexcept {
     392         659 :     return nullptr;
     393             :   }
     394         100 :   virtual ActionShortcut* castToActionShortcut() noexcept {
     395         100 :     return nullptr;
     396             :   }
     397             : };
     398             : 
     399             : /////////////////////
     400             : // FAST INLINE METHODS
     401             : 
     402             : inline
     403             : const std::string & Action::getLabel()const {
     404   174974522 :   return label;
     405             : }
     406             : 
     407             : inline
     408             : const std::string & Action::getName()const {
     409   110256088 :   return name;
     410             : }
     411             : 
     412             : template<class T>
     413      154475 : void Action::parse(const std::string&key,T&t) {
     414             :   // Check keyword has been registered
     415      154475 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     416             : 
     417             :   // Now try to read the keyword
     418             :   std::string def;
     419      154475 :   bool present=Tools::findKeyword(line,key);
     420      154475 :   bool found=Tools::parse(line,key,t,replica_index);
     421      154475 :   if(present && !found) {
     422           6 :     error("keyword " + key +" could not be read correctly");
     423             :   }
     424             : 
     425             :   // If it isn't read and it is compulsory see if a default value was specified
     426      271579 :   if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
     427       24337 :     if( keywords.getDefaultValue(key,def) ) {
     428       18109 :       if( def.length()==0 || !Tools::convertNoexcept(def,t) ) {
     429           0 :         plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
     430             :       }
     431       36218 :       defaults += " " + key + "=" + def;
     432       12456 :     } else if( keywords.style(key,"compulsory") ) {
     433           3 :       error("keyword " + key + " is compulsory for this action");
     434             :     }
     435             :   }
     436      154472 : }
     437             : 
     438             : template<class T>
     439       51506 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
     440             :   // Check keyword has been registered
     441       51506 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     442       51506 :   if( !keywords.numbered(key) ) {
     443           0 :     error("numbered keywords are not allowed for " + key );
     444             :   }
     445             : 
     446             :   // Now try to read the keyword
     447             :   std::string num;
     448       51506 :   Tools::convert(no,num);
     449      103012 :   return Tools::parse(line,key+num,t,replica_index);
     450             : }
     451             : 
     452             : template<class T>
     453       89467 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
     454             :   // Check keyword has been registered
     455       89467 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     456       89467 :   unsigned size=t.size();
     457             :   bool skipcheck=false;
     458       89467 :   if(size==0) {
     459             :     skipcheck=true;
     460             :   }
     461             : 
     462             :   // Now try to read the keyword
     463             :   std::string def;
     464             :   T val;
     465       89467 :   bool present=Tools::findKeyword(line,key);
     466       89467 :   bool found=Tools::parseVector(line,key,t,replica_index);
     467       89467 :   if(present && !found) {
     468           2 :     error("keyword " + key +" could not be read correctly");
     469             :   }
     470             : 
     471             :   // Check vectors size is correct (not if this is atoms or ARG)
     472      178932 :   if( !keywords.style(key,"atoms") && found ) {
     473             : //     bool skipcheck=false;
     474             : //     if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
     475       57100 :     if( !skipcheck && t.size()!=size ) {
     476           6 :       error("vector read in for keyword " + key + " has the wrong size");
     477             :     }
     478             :   }
     479             : 
     480             :   // If it isn't read and it is compulsory see if a default value was specified
     481      120758 :   if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
     482        3637 :     if( keywords.getDefaultValue(key,def) ) {
     483        3528 :       if( def.length()==0 || !Tools::convertNoexcept(def,val) ) {
     484           0 :         plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
     485             :       } else {
     486        3528 :         if(t.size()>0) {
     487        5490 :           for(unsigned i=0; i<t.size(); ++i) {
     488        3589 :             t[i]=val;
     489             :           }
     490        3018 :           defaults += " " + key + "=" + def;
     491        3981 :           for(unsigned i=1; i<t.size(); ++i) {
     492        4944 :             defaults += "," + def;
     493             :           }
     494             :         } else {
     495        2019 :           t.push_back(val);
     496        4038 :           defaults += " " + key + "=" + def;
     497             :         }
     498             :       }
     499         218 :     } else if( keywords.style(key,"compulsory") ) {
     500           4 :       error("keyword " + key + " is compulsory for this action");
     501             :     }
     502       85826 :   } else if ( !found ) {
     503       13720 :     t.resize(0);
     504             :   }
     505       89463 : }
     506             : 
     507             : template<class T>
     508      196406 : bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
     509      196406 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     510      196406 :   if( !keywords.numbered(key) ) {
     511           0 :     error("numbered keywords are not allowed for " + key );
     512             :   }
     513             : 
     514      196406 :   unsigned size=t.size();
     515             :   bool skipcheck=false;
     516      196406 :   if(size==0) {
     517             :     skipcheck=true;
     518             :   }
     519             :   std::string num;
     520      196406 :   Tools::convert(no,num);
     521      196406 :   bool present=Tools::findKeyword(line,key);
     522      196406 :   bool found=Tools::parseVector(line,key+num,t,replica_index);
     523      196406 :   if(present && !found) {
     524           0 :     error("keyword " + key +" could not be read correctly");
     525             :   }
     526             : 
     527      392812 :   if(  keywords.style(key,"compulsory") ) {
     528         129 :     if (!skipcheck && found && t.size()!=size ) {
     529           0 :       error("vector read in for keyword " + key + num + " has the wrong size");
     530             :     }
     531      196277 :   } else if ( !found ) {
     532        1605 :     t.resize(0);
     533             :   }
     534      196406 :   return found;
     535             : }
     536             : 
     537             : inline
     538     5390098 : void Action::deactivate() {
     539             :   options.clear();
     540     5390098 :   active=false;
     541     5390098 : }
     542             : 
     543             : inline
     544             : bool Action::isActive()const {
     545   323702447 :   return active;
     546             : }
     547             : 
     548             : inline
     549     2074283 : bool Action::isOptionOn(const std::string &s)const {
     550     2074283 :   return options.count(s);
     551             : }
     552             : 
     553             : inline
     554             : bool Action::getRestart()const {
     555        4291 :   return restart;
     556             : }
     557             : 
     558             : inline
     559             : std::string Action::getDefaultString() const {
     560          32 :   return defaults;
     561             : }
     562             : 
     563             : }
     564             : #endif
     565             : 

Generated by: LCOV version 1.16