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-03-30 13:16: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       14552 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
      36       14552 :   plumed(p),
      37       14552 :   line(l),
      38       14552 :   keys(emptyKeys) {
      39       14552 : }
      40             : 
      41       14550 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
      42       14550 :   plumed(ao.plumed),
      43       14550 :   line(ao.line),
      44       14550 :   keys(keys) {
      45       14550 : }
      46             : 
      47       15711 : void Action::registerKeywords( Keywords& keys ) {
      48       15711 :   plumed_assert( keys.size()==0 );
      49       31422 :   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       31422 :   keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
      51       31422 :   keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
      52       31422 :   keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
      53       15711 : }
      54             : 
      55       14550 : Action::Action(const ActionOptions&ao):
      56       14550 :   name(ao.line[0]),
      57       14550 :   line(ao.line),
      58       14550 :   update_from(std::numeric_limits<double>::max()),
      59       14550 :   update_until(std::numeric_limits<double>::max()),
      60       14550 :   active(false),
      61       14550 :   restart(ao.plumed.getRestart()),
      62       14550 :   doCheckPoint(ao.plumed.getCPT()),
      63       14550 :   plumed(ao.plumed),
      64       14550 :   log(plumed.getLog()),
      65       14550 :   comm(plumed.comm),
      66       14550 :   multi_sim_comm(plumed.multi_sim_comm),
      67       14550 :   keywords(ao.keys) {
      68             :   line.erase(line.begin());
      69       14550 :   log.printf("Action %s\n",name.c_str());
      70             : 
      71       14550 :   if(comm.Get_rank()==0) {
      72        8099 :     replica_index=multi_sim_comm.Get_rank();
      73             :   }
      74       14550 :   comm.Bcast(replica_index,0);
      75             : 
      76       29100 :   if ( keywords.exists("LABEL") ) {
      77       28672 :     parse("LABEL",label);
      78             :   }
      79             : 
      80       14550 :   if(label.length()==0) {
      81             :     std::string s;
      82        2537 :     Tools::convert(plumed.getActionSet().size(),s);
      83        5074 :     label="@"+s;
      84             :   }
      85       14550 :   if( plumed.getActionSet().selectWithLabel<Action*>(label) ) {
      86           0 :     error("label " + label + " has been already used");
      87             :   }
      88       14550 :   log.printf("  with label %s\n",label.c_str());
      89       29100 :   if ( keywords.exists("UPDATE_FROM") ) {
      90        3634 :     parse("UPDATE_FROM",update_from);
      91             :   }
      92       14550 :   if(update_from!=std::numeric_limits<double>::max()) {
      93           3 :     log.printf("  only update from time %f\n",update_from);
      94             :   }
      95       29100 :   if ( keywords.exists("UPDATE_UNTIL") ) {
      96        3634 :     parse("UPDATE_UNTIL",update_until);
      97             :   }
      98       14550 :   if(update_until!=std::numeric_limits<double>::max()) {
      99           3 :     log.printf("  only update until time %f\n",update_until);
     100             :   }
     101       29100 :   if ( keywords.exists("RESTART") ) {
     102        1916 :     std::string srestart="AUTO";
     103        1915 :     parse("RESTART",srestart);
     104        1915 :     if( plumed.parseOnlyMode() ) {
     105           0 :       restart=false;
     106        1915 :     } else if(srestart=="YES") {
     107          91 :       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       14550 : }
     117             : 
     118       29098 : Action::~Action() {
     119       14549 :   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       29098 : }
     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       18303 : void Action::fflush() {
     146       18303 :   for(const auto & p : files) {
     147           0 :     std::fflush(p);
     148             :   }
     149       18303 : }
     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       41585 : void Action::parseFlag(const std::string&key,bool & t) {
     174             :   // Check keyword has been registered
     175       41585 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     176             :   // Check keyword is a flag
     177       83170 :   if(!keywords.style(key,"nohtml")) {
     178       80535 :     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       41585 :   if(!Tools::parseFlag(line,key,t)) {
     183       82860 :     if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
     184        2734 :       t=false;
     185       37329 :     } 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       41585 : }
     191             : 
     192     1084396 : void Action::addDependency(Action*action) {
     193     1084396 :   after.push_back(action);
     194     1084396 : }
     195             : 
     196     3236286 : 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     3236286 :   if(!active) {
     202     1665305 :     this->unlockRequests();
     203     1665305 :     prepare();
     204     1665305 :     this->lockRequests();
     205             :   } else {
     206             :     return;
     207             :   }
     208     3614060 :   for(const auto & p : after) {
     209     1948755 :     p->activate();
     210             :   }
     211     1665305 :   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      189379 : void Action::clearDependencies() {
     229             :   after.clear();
     230      189379 : }
     231             : 
     232       28311 : void Action::checkRead() {
     233       28311 :   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       28311 : }
     244             : 
     245     4613973 : long long int Action::getStep()const {
     246     4613973 :   return plumed.getStep();
     247             : }
     248             : 
     249     3029665 : double Action::getTime()const {
     250     3029665 :   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      334899 : void Action::prepare() {
     268      334899 :   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     1657344 : bool Action::checkUpdate()const {
     305     1657344 :   double t=getTime();
     306     1657344 :   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