LCOV - code coverage report
Current view: top level - core - Action.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 78 86 90.7 %
Date: 2026-03-30 13:16:06 Functions: 25 26 96.2 %

          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/Log.h"
      30             : 
      31             : namespace PLMD {
      32             : 
      33             : class PDB;
      34             : class PlumedMain;
      35             : class Communicator;
      36             : class ActionWithValue;
      37             : 
      38             : /// This class is used to bring the relevant information to the Action constructor.
      39             : /// Only Action and ActionRegister class can access to its content, which is
      40             : /// kept private to other classes, and may change in the future.
      41       29102 : class ActionOptions {
      42             :   friend class Action;
      43             :   friend class ActionRegister;
      44             : /// Reference to main PlumedMain object
      45             :   PlumedMain& plumed;
      46             : /// Input line which sets up the action
      47             :   std::vector<std::string> line;
      48             : /// The documentation for this action
      49             :   const Keywords& keys;
      50             :   static Keywords emptyKeys;
      51             : public:
      52             : /// Constructor
      53             :   ActionOptions(PlumedMain&p,const std::vector<std::string>&);
      54             :   ActionOptions(const ActionOptions&,const Keywords& keys);
      55             : };
      56             : 
      57             : /// Base class for all the input Actions.
      58             : /// The input Actions are more or less corresponding to the directives
      59             : /// in the plumed.dat file and are applied in order at each time-step.
      60             : class Action {
      61             :   friend class ActionShortcut;
      62             : 
      63             : /// Name of the directive in the plumed.dat file.
      64             :   const std::string name;
      65             : 
      66             : /// Label of the Action, as set with LABEL= in the plumed.dat file.
      67             :   std::string label;
      68             : 
      69             : /// Directive line.
      70             : /// This line is progressively erased during Action construction
      71             : /// so as to check if all the present keywords are correct.
      72             :   std::vector<std::string> line;
      73             : 
      74             : /// Update only after this time.
      75             :   double update_from;
      76             : 
      77             : /// Update only until this time.
      78             :   double update_until;
      79             : 
      80             : public:
      81             : 
      82             : /// Check if action should be updated.
      83             :   bool checkUpdate()const;
      84             : 
      85             : public:
      86             :   typedef std::vector<Action*> Dependencies;
      87             : 
      88             : private:
      89             : /// Actions on which this Action depends.
      90             :   Dependencies after;
      91             : 
      92             : /// Switch to activate Action on this step.
      93             :   bool active;
      94             : 
      95             : /// Option that you might have enabled
      96             :   std::set<std::string> options;
      97             : 
      98             :   bool restart;
      99             : 
     100             :   bool doCheckPoint;
     101             : 
     102             : /// The set of default arguments that we are using
     103             :   std::string defaults;
     104             : public:
     105             : 
     106             : /// Reference to main plumed object
     107             :   PlumedMain& plumed;
     108             : 
     109             : /// Reference to the log stream
     110             :   Log& log;
     111             : 
     112             : /// Specify that this Action depends on another one
     113             :   void addDependency(Action*);
     114             : 
     115             : /// Clear the dependence list for this Action
     116             :   void clearDependencies();
     117             : 
     118             : /// Return the present timestep
     119             :   long long int getStep()const;
     120             : 
     121             : /// Return the present time
     122             :   double getTime()const;
     123             : 
     124             : /// Return the timestep
     125             :   double getTimeStep()const;
     126             : 
     127             : /// Return true if we are doing a restart
     128             :   bool getRestart()const;
     129             : 
     130             : /// Return true if we are doing at a checkpoint step
     131             :   bool getCPT()const;
     132             : 
     133             : /// Just read one of the keywords and return the whole thing as a string
     134             :   std::string getKeyword(const std::string& key);
     135             : 
     136             : /// Parse one keyword as generic type
     137             :   template<class T>
     138             :   void parse(const std::string&key,T&t);
     139             : 
     140             : /// Parse one numbered keyword as generic type
     141             :   template<class T>
     142             :   bool parseNumbered(const std::string&key, const int no, T&t);
     143             : 
     144             : /// Parse one keyword as std::vector
     145             :   template<class T>
     146             :   void parseVector(const std::string&key,std::vector<T>&t);
     147             : 
     148             : /// Parse a vector with a number
     149             :   template<class T>
     150             :   bool parseNumberedVector(const std::string& key, const int no, std::vector<T>&t);
     151             : 
     152             : /// Parse one keyword as boolean flag
     153             :   void parseFlag(const std::string&key,bool&t);
     154             : 
     155             : /// Crash calculation and print documentation
     156             :   [[noreturn]] void error( const std::string & msg ) const;
     157             : 
     158             : /// Issue a warning
     159             :   void warning( const std::string & msg );
     160             : 
     161             : /// Exit with error code c
     162             :   void exit(int c=0);
     163             : 
     164             : ///
     165             :   std::set<FILE*> files;
     166             : 
     167             : public:
     168             : /// Standard constructor from ActionOptions
     169             :   explicit Action(const ActionOptions&);
     170             : /// Destructor
     171             :   virtual ~Action();
     172             : private:
     173             : /// Copy constructor is deleted
     174             :   Action(const Action&a) = delete;
     175             : /// Assignment operator is deleted
     176             :   Action& operator=(const Action&a) = delete;
     177             :   int replica_index;
     178             : public:
     179             : /// Check if Action was properly read.
     180             : /// This checks if Action::line is empty. It must be called after
     181             : /// a final Action has been initialized
     182             :   void checkRead();
     183             : 
     184             :   Communicator& comm;
     185             :   Communicator& multi_sim_comm;
     186             : 
     187             :   const Keywords& keywords;
     188             : /// Prepare an Action for calculation
     189             : /// This can be used by Action if they need some special preparation
     190             : /// before calculation. Typical case is for collective variables
     191             : /// which would like to change their list of requested atoms.
     192             : /// By default (if not overridden) does nothing.
     193             :   virtual void prepare();
     194             : 
     195             : /// Register all the relevant keywords for the action
     196             :   static void registerKeywords( Keywords& keys );
     197             : 
     198      945438 :   virtual void lockRequests() {}
     199      945438 :   virtual void unlockRequests() {}
     200             : 
     201             : /// Calculate an Action.
     202             : /// This method is called one or more times per step.
     203             : /// The set of all Actions is calculated in forward order.
     204             :   virtual void calculate()=0;
     205             : 
     206             : /// Apply an Action.
     207             : /// This method is called one time per step.
     208             : /// The set of all Actions is applied in backward order.
     209             :   virtual void apply()=0;
     210             : 
     211             : /// Before Update.
     212             : /// This is a special method that is called just
     213             : /// before the update() method. It can be used by
     214             : /// actions that want to do something irrespectively
     215             : /// of the fact that update() is active or not.
     216             : /// In other words, this is *always* called, even when action
     217             : /// is not active.
     218     1832747 :   virtual void beforeUpdate() {}
     219             : 
     220             : /// Update.
     221             : /// This method is called one time per step.
     222             : /// The set of all Actions is updated in forward order.
     223      423906 :   virtual void update() {}
     224             : 
     225             : /// RunFinalJobs
     226             : /// This method is called once at the very end of the calculation.
     227             : /// The set of all Actions in run for the final time in forward order.
     228       13754 :   virtual void runFinalJobs() {}
     229             : 
     230             : /// Tell to the Action to flush open files
     231             :   void fflush();
     232             : 
     233             : /// Returns the label
     234             :   const std::string & getLabel()const;
     235             : 
     236             : /// Returns the name
     237             :   const std::string & getName()const;
     238             : 
     239             : /// Set action to active
     240             :   virtual void activate();
     241             : 
     242             : ///
     243             :   virtual void setOption(const std::string &s);
     244             : 
     245             :   virtual void clearOptions();
     246             : 
     247             : /// Set action to inactive
     248             :   virtual void deactivate();
     249             : 
     250             : /// Check if action is active
     251             :   bool isActive()const;
     252             : 
     253             : /// Check if an option is on
     254             :   bool isOptionOn(const std::string &s)const;
     255             : 
     256             : /// Return dependencies
     257             :   const Dependencies & getDependencies()const {
     258             :     return after;
     259             :   }
     260             : 
     261             : /// Check if numerical derivatives should be performed
     262      266712 :   virtual bool checkNumericalDerivatives()const {
     263      266712 :     return false;
     264             :   }
     265             : 
     266             : /// Check if the action needs gradient
     267     1656525 :   virtual bool checkNeedsGradients()const {
     268     1656525 :     return false;
     269             :   }
     270             : 
     271             : /// Perform calculation using numerical derivatives
     272             : /// N.B. only pass an ActionWithValue to this routine if you know exactly what you
     273             : /// are doing.
     274             :   virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL );
     275             : 
     276             : /// Opens a file.
     277             : /// This is similar to plain fopen, but with some extra functionality.
     278             : /// * When opened for writing, processors other than the one with rank 0 just open /dev/null
     279             : /// * PlumedMain::fopen is used, so that other tricks may appear (see \ref PlumedMain::fopen)
     280             :   FILE *fopen(const char *path, const char *mode);
     281             : /// Closes a file opened with Action::fclose().
     282             :   int   fclose(FILE*fp);
     283             : 
     284             : /// Calculate the action given a pdb file as input.  This is used to initialize
     285             : /// things like distance from a point in CV map space given a pdb as an input file
     286             :   void calculateFromPDB( const PDB&  );
     287             : /// This is overwritten in ActionAtomistic so that we can read
     288             : /// the atoms from the pdb input file rather than taking them from the
     289             : /// MD code
     290           0 :   virtual void readAtomsFromPDB( const PDB&  ) {}
     291             : /// Check if we are on an exchange step
     292             :   bool getExchangeStep()const;
     293             : 
     294             : /// Cite a paper see PlumedMain::cite
     295             :   std::string cite(const std::string&s);
     296             : 
     297             : /// Get the defaults
     298             :   std::string getDefaultString() const ;
     299             : };
     300             : 
     301             : /////////////////////
     302             : // FAST INLINE METHODS
     303             : 
     304             : inline
     305             : const std::string & Action::getLabel()const {
     306    62885292 :   return label;
     307             : }
     308             : 
     309             : inline
     310             : const std::string & Action::getName()const {
     311        7743 :   return name;
     312             : }
     313             : 
     314             : template<class T>
     315       63199 : void Action::parse(const std::string&key,T&t) {
     316             :   // Check keyword has been registered
     317       63199 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     318             : 
     319             :   // Now try to read the keyword
     320             :   std::string def;
     321       63199 :   bool present=Tools::findKeyword(line,key);
     322       63199 :   bool found=Tools::parse(line,key,t,replica_index);
     323       63199 :   if(present && !found) {
     324           6 :     error("keyword " + key +" could not be read correctly");
     325             :   }
     326             : 
     327             :   // If it isn't read and it is compulsory see if a default value was specified
     328      144840 :   if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
     329        8534 :     if( keywords.getDefaultValue(key,def) ) {
     330        3023 :       if( def.length()==0 || !Tools::convertNoexcept(def,t) ) {
     331           0 :         plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
     332             :       }
     333        6046 :       defaults += " " + key + "=" + def;
     334       11022 :     } else if( keywords.style(key,"compulsory") ) {
     335           3 :       error("keyword " + key + " is compulsory for this action");
     336             :     }
     337             :   }
     338       63196 : }
     339             : 
     340             : template<class T>
     341        5534 : bool Action::parseNumbered(const std::string&key, const int no, T&t) {
     342             :   // Check keyword has been registered
     343        5534 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     344        5534 :   if( !keywords.numbered(key) ) {
     345           0 :     error("numbered keywords are not allowed for " + key );
     346             :   }
     347             : 
     348             :   // Now try to read the keyword
     349             :   std::string num;
     350        5534 :   Tools::convert(no,num);
     351       11068 :   return Tools::parse(line,key+num,t,replica_index);
     352             : }
     353             : 
     354             : template<class T>
     355       30962 : void Action::parseVector(const std::string&key,std::vector<T>&t) {
     356             :   // Check keyword has been registered
     357       30962 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     358       30962 :   unsigned size=t.size();
     359             :   bool skipcheck=false;
     360       30962 :   if(size==0) {
     361             :     skipcheck=true;
     362             :   }
     363             : 
     364             :   // Now try to read the keyword
     365             :   std::string def;
     366             :   T val;
     367       30962 :   bool present=Tools::findKeyword(line,key);
     368       30962 :   bool found=Tools::parseVector(line,key,t,replica_index);
     369       30962 :   if(present && !found) {
     370           2 :     error("keyword " + key +" could not be read correctly");
     371             :   }
     372             : 
     373             :   // Check vectors size is correct (not if this is atoms or ARG)
     374       61922 :   if( !keywords.style(key,"atoms") && found ) {
     375             : //     bool skipcheck=false;
     376             : //     if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); }
     377       13806 :     if( !skipcheck && t.size()!=size ) {
     378           6 :       error("vector read in for keyword " + key + " has the wrong size");
     379             :     }
     380             :   }
     381             : 
     382             :   // If it isn't read and it is compulsory see if a default value was specified
     383       44776 :   if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) {
     384        1108 :     if( keywords.getDefaultValue(key,def) ) {
     385        1006 :       if( def.length()==0 || !Tools::convertNoexcept(def,val) ) {
     386           0 :         plumed_error() <<"ERROR in action "<<name<<" with label "<<label<<" : keyword "<<key<<" has weird default value";
     387             :       } else {
     388        1006 :         if(t.size()>0) {
     389        1645 :           for(unsigned i=0; i<t.size(); ++i) {
     390        1016 :             t[i]=val;
     391             :           }
     392        1250 :           defaults += " " + key + "=" + def;
     393        1020 :           for(unsigned i=1; i<t.size(); ++i) {
     394         790 :             defaults += "," + def;
     395             :           }
     396             :         } else {
     397         381 :           t.push_back(val);
     398         762 :           defaults += " " + key + "=" + def;
     399             :         }
     400             :       }
     401         204 :     } else if( keywords.style(key,"compulsory") ) {
     402           4 :       error("keyword " + key + " is compulsory for this action");
     403             :     }
     404       29850 :   } else if ( !found ) {
     405        6253 :     t.resize(0);
     406             :   }
     407       30958 : }
     408             : 
     409             : template<class T>
     410        4031 : bool Action::parseNumberedVector(const std::string&key, const int no, std::vector<T>&t) {
     411        4031 :   plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
     412        4031 :   if( !keywords.numbered(key) ) {
     413           0 :     error("numbered keywords are not allowed for " + key );
     414             :   }
     415             : 
     416        4031 :   unsigned size=t.size();
     417             :   bool skipcheck=false;
     418        4031 :   if(size==0) {
     419             :     skipcheck=true;
     420             :   }
     421             :   std::string num;
     422        4031 :   Tools::convert(no,num);
     423        4031 :   bool present=Tools::findKeyword(line,key);
     424        4031 :   bool found=Tools::parseVector(line,key+num,t,replica_index);
     425        4031 :   if(present && !found) {
     426           0 :     error("keyword " + key +" could not be read correctly");
     427             :   }
     428             : 
     429        8062 :   if(  keywords.style(key,"compulsory") ) {
     430          90 :     if (!skipcheck && found && t.size()!=size ) {
     431           0 :       error("vector read in for keyword " + key + num + " has the wrong size");
     432             :     }
     433        3941 :   } else if ( !found ) {
     434        1110 :     t.resize(0);
     435             :   }
     436        4031 :   return found;
     437             : }
     438             : 
     439             : inline
     440     1850592 : void Action::deactivate() {
     441             :   options.clear();
     442     1850592 :   active=false;
     443     1850592 : }
     444             : 
     445             : inline
     446             : bool Action::isActive()const {
     447     7962946 :   return active;
     448             : }
     449             : 
     450             : inline
     451     1412151 : bool Action::isOptionOn(const std::string &s)const {
     452     1412151 :   return options.count(s);
     453             : }
     454             : 
     455             : inline
     456             : bool Action::getRestart()const {
     457        3846 :   return restart;
     458             : }
     459             : 
     460             : inline
     461             : std::string Action::getDefaultString() const {
     462           0 :   return defaults;
     463             : }
     464             : 
     465             : }
     466             : #endif
     467             : 

Generated by: LCOV version 1.16