LCOV - code coverage report
Current view: top level - core - Action.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 133 172 77.3 %
Date: 2026-05-20 14:28:06 Functions: 25 30 83.3 %

          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 "Action.h"
      23             : #include "ActionWithValue.h"
      24             : #include "PlumedMain.h"
      25             : #include "tools/Log.h"
      26             : #include "tools/Exception.h"
      27             : #include "Atoms.h"
      28             : #include "ActionSet.h"
      29             : #include <iostream>
      30             : 
      31             : namespace PLMD {
      32             : 
      33             : Keywords ActionOptions::emptyKeys;
      34             : 
      35       14556 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
      36       14556 :   plumed(p),
      37       14556 :   line(l),
      38       14556 :   keys(emptyKeys) {
      39       14556 : }
      40             : 
      41       14554 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
      42       14554 :   plumed(ao.plumed),
      43       14554 :   line(ao.line),
      44       14554 :   keys(keys) {
      45       14554 : }
      46             : 
      47       15715 : void Action::registerKeywords( Keywords& keys ) {
      48       15715 :   plumed_assert( keys.size()==0 );
      49       31430 :   keys.add( "hidden", "LABEL", "a label for the action so that its output can be referenced in the input to other actions.  Actions with scalar output are referenced using their label only.  Actions with vector output must have a separate label for every component.  Individual components are then referred to using label.component" );
      50       31430 :   keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
      51       31430 :   keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
      52       31430 :   keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
      53       15715 : }
      54             : 
      55       14554 : Action::Action(const ActionOptions&ao):
      56       14554 :   name(ao.line[0]),
      57       14554 :   line(ao.line),
      58       14554 :   update_from(std::numeric_limits<double>::max()),
      59       14554 :   update_until(std::numeric_limits<double>::max()),
      60       14554 :   active(false),
      61       14554 :   restart(ao.plumed.getRestart()),
      62       14554 :   doCheckPoint(ao.plumed.getCPT()),
      63       14554 :   plumed(ao.plumed),
      64       14554 :   log(plumed.getLog()),
      65       14554 :   comm(plumed.comm),
      66       14554 :   multi_sim_comm(plumed.multi_sim_comm),
      67       14554 :   keywords(ao.keys) {
      68             :   line.erase(line.begin());
      69       14554 :   log.printf("Action %s\n",name.c_str());
      70             : 
      71       14554 :   if(comm.Get_rank()==0) {
      72        8103 :     replica_index=multi_sim_comm.Get_rank();
      73             :   }
      74       14554 :   comm.Bcast(replica_index,0);
      75             : 
      76       29108 :   if ( keywords.exists("LABEL") ) {
      77       28680 :     parse("LABEL",label);
      78             :   }
      79             : 
      80       14554 :   if(label.length()==0) {
      81             :     std::string s;
      82        2539 :     Tools::convert(plumed.getActionSet().size(),s);
      83        5078 :     label="@"+s;
      84             :   }
      85       14554 :   if( plumed.getActionSet().selectWithLabel<Action*>(label) ) {
      86           0 :     error("label " + label + " has been already used");
      87             :   }
      88       14554 :   log.printf("  with label %s\n",label.c_str());
      89       29108 :   if ( keywords.exists("UPDATE_FROM") ) {
      90        3638 :     parse("UPDATE_FROM",update_from);
      91             :   }
      92       14554 :   if(update_from!=std::numeric_limits<double>::max()) {
      93           3 :     log.printf("  only update from time %f\n",update_from);
      94             :   }
      95       29108 :   if ( keywords.exists("UPDATE_UNTIL") ) {
      96        3638 :     parse("UPDATE_UNTIL",update_until);
      97             :   }
      98       14554 :   if(update_until!=std::numeric_limits<double>::max()) {
      99           3 :     log.printf("  only update until time %f\n",update_until);
     100             :   }
     101       29108 :   if ( keywords.exists("RESTART") ) {
     102        1918 :     std::string srestart="AUTO";
     103        1917 :     parse("RESTART",srestart);
     104        1917 :     if( plumed.parseOnlyMode() ) {
     105           0 :       restart=false;
     106        1917 :     } else if(srestart=="YES") {
     107          93 :       restart=true;
     108        1824 :     } else if(srestart=="NO") {
     109          22 :       restart=false;
     110        1802 :     } else if(srestart=="AUTO") {
     111             :       // do nothing, this is the default
     112             :     } else {
     113           2 :       error("RESTART should be either YES, NO, or AUTO");
     114             :     }
     115             :   }
     116       14554 : }
     117             : 
     118       29106 : Action::~Action() {
     119       14553 :   if(files.size()!=0) {
     120           0 :     std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n";
     121             :   }
     122       29106 : }
     123             : 
     124          73 : FILE* Action::fopen(const char *path, const char *mode) {
     125             :   bool write(false);
     126         146 :   for(const char*p=mode; *p; p++)
     127          73 :     if(*p=='w' || *p=='a' || *p=='+') {
     128             :       write=true;
     129             :     }
     130             :   FILE* fp;
     131          73 :   if(write && comm.Get_rank()!=0) {
     132           0 :     fp=plumed.fopen("/dev/null",mode);
     133             :   } else {
     134          73 :     fp=plumed.fopen(path,mode);
     135             :   }
     136          73 :   files.insert(fp);
     137          73 :   return fp;
     138             : }
     139             : 
     140          91 : int Action::fclose(FILE*fp) {
     141             :   files.erase(fp);
     142          91 :   return plumed.fclose(fp);
     143             : }
     144             : 
     145       18307 : void Action::fflush() {
     146       18307 :   for(const auto & p : files) {
     147           0 :     std::fflush(p);
     148             :   }
     149       18307 : }
     150             : 
     151          33 : std::string Action::getKeyword(const std::string& key) {
     152             :   // Check keyword has been registered
     153          33 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     154             : 
     155             :   std::string outkey;
     156          33 :   if( Tools::getKey(line,key,outkey ) ) {
     157          33 :     return key + outkey;
     158             :   }
     159             : 
     160           0 :   if( keywords.style(key,"compulsory") ) {
     161           0 :     if( keywords.getDefaultValue(key,outkey) ) {
     162           0 :       if( outkey.length()==0 ) {
     163           0 :         error("keyword " + key + " has weird default value");
     164             :       }
     165           0 :       return key + "=" +  outkey;
     166             :     } else {
     167           0 :       error("keyword " + key + " is compulsory for this action");
     168             :     }
     169             :   }
     170           0 :   return "";
     171             : }
     172             : 
     173       41587 : void Action::parseFlag(const std::string&key,bool & t) {
     174             :   // Check keyword has been registered
     175       41587 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     176             :   // Check keyword is a flag
     177       83174 :   if(!keywords.style(key,"nohtml")) {
     178       80539 :     plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag");
     179             :   }
     180             : 
     181             :   // Read in the flag otherwise get the default value from the keywords object
     182       41587 :   if(!Tools::parseFlag(line,key,t)) {
     183       82864 :     if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
     184        2734 :       t=false;
     185       37331 :     } else if ( !keywords.getLogicalDefault(key,t) ) {
     186           0 :       log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() );
     187           0 :       plumed_error();
     188             :     }
     189             :   }
     190       41587 : }
     191             : 
     192     1084398 : void Action::addDependency(Action*action) {
     193     1084398 :   after.push_back(action);
     194     1084398 : }
     195             : 
     196     3236290 : void Action::activate() {
     197             : // preparation step is called only the first time an Action is activated.
     198             : // since it could change its dependences (e.g. in an ActionAtomistic which is
     199             : // accessing to a virtual atom), this is done just before dependencies are
     200             : // activated
     201     3236290 :   if(!active) {
     202     1665309 :     this->unlockRequests();
     203     1665309 :     prepare();
     204     1665309 :     this->lockRequests();
     205             :   } else {
     206             :     return;
     207             :   }
     208     3614066 :   for(const auto & p : after) {
     209     1948757 :     p->activate();
     210             :   }
     211     1665309 :   active=true;
     212             : }
     213             : 
     214         267 : void Action::setOption(const std::string &s) {
     215             : // This overloads the action and activate some options
     216         267 :   options.insert(s);
     217         448 :   for(const auto & p : after) {
     218         181 :     p->setOption(s);
     219             :   }
     220         267 : }
     221             : 
     222           0 : void Action::clearOptions() {
     223             : // This overloads the action and activate some options
     224             :   options.clear();
     225           0 : }
     226             : 
     227             : 
     228      189383 : void Action::clearDependencies() {
     229             :   after.clear();
     230      189383 : }
     231             : 
     232       28319 : void Action::checkRead() {
     233       28319 :   if(!line.empty()) {
     234           0 :     std::string msg="cannot understand the following words from the input line : ";
     235           0 :     for(unsigned i=0; i<line.size(); i++) {
     236           0 :       if(i>0) {
     237           0 :         msg = msg + ", ";
     238             :       }
     239           0 :       msg = msg + line[i];
     240             :     }
     241           0 :     error(msg);
     242             :   }
     243       28319 : }
     244             : 
     245     4613981 : long long int Action::getStep()const {
     246     4613981 :   return plumed.getStep();
     247             : }
     248             : 
     249     3029671 : double Action::getTime()const {
     250     3029671 :   return plumed.getAtoms().getTimeStep()*getStep();
     251             : }
     252             : 
     253       18180 : double Action::getTimeStep()const {
     254       18180 :   return plumed.getAtoms().getTimeStep();
     255             : }
     256             : 
     257             : 
     258             : 
     259           0 : void Action::exit(int c) {
     260           0 :   plumed.exit(c);
     261           0 : }
     262             : 
     263           0 : void Action::calculateNumericalDerivatives( ActionWithValue* a ) {
     264           0 :   plumed_merror("if you get here it means that you are trying to use numerical derivatives for a class that does not implement them");
     265             : }
     266             : 
     267      334901 : void Action::prepare() {
     268      334901 :   return;
     269             : }
     270             : 
     271          30 : [[noreturn]] void Action::error( const std::string & msg ) const {
     272          30 :   log.printf("ERROR in input to action %s with label %s : %s \n \n", name.c_str(), label.c_str(), msg.c_str() );
     273          90 :   plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
     274             : }
     275             : 
     276         139 : void Action::warning( const std::string & msg ) {
     277         139 :   log.printf("WARNING for action %s with label %s : %s \n", name.c_str(), label.c_str(), msg.c_str() );
     278         139 : }
     279             : 
     280           0 : void Action::calculateFromPDB( const PDB& pdb ) {
     281           0 :   activate();
     282           0 :   for(const auto & p : after) {
     283           0 :     ActionWithValue*av=dynamic_cast<ActionWithValue*>(p);
     284           0 :     if(av) {
     285           0 :       av->clearInputForces();
     286           0 :       av->clearDerivatives();
     287             :     }
     288           0 :     p->readAtomsFromPDB( pdb );
     289           0 :     p->calculate();
     290             :   }
     291           0 :   readAtomsFromPDB( pdb );
     292           0 :   calculate();
     293           0 : }
     294             : 
     295       30198 : bool Action::getExchangeStep()const {
     296       30198 :   return plumed.getExchangeStep();
     297             : }
     298             : 
     299          40 : std::string Action::cite(const std::string&s) {
     300          40 :   return plumed.cite(s);
     301             : }
     302             : 
     303             : /// Check if action should be updated.
     304     1657348 : bool Action::checkUpdate()const {
     305     1657348 :   double t=getTime();
     306     1657348 :   if(t<update_until && (update_from==std::numeric_limits<double>::max() || t>=update_from)) {
     307             :     return true;
     308             :   } else {
     309         510 :     return false;
     310             :   }
     311             : }
     312             : 
     313        1340 : bool Action::getCPT()const {
     314        1340 :   return plumed.getCPT();
     315             : }
     316             : 
     317             : }
     318             : 

Generated by: LCOV version 1.16