LCOV - code coverage report
Current view: top level - core - Action.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 121 155 78.1 %
Date: 2024-10-11 08:09:47 Functions: 25 31 80.6 %

          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       14107 : ActionOptions::ActionOptions(PlumedMain&p,const std::vector<std::string>&l):
      36       14107 :   plumed(p),
      37       14107 :   line(l),
      38       14107 :   keys(emptyKeys)
      39             : {
      40       14107 : }
      41             : 
      42       14105 : ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys):
      43       14105 :   plumed(ao.plumed),
      44       14105 :   line(ao.line),
      45       14105 :   keys(keys)
      46             : {
      47       14105 : }
      48             : 
      49       14388 : void Action::registerKeywords( Keywords& keys ) {
      50       14388 :   plumed_assert( keys.size()==0 );
      51       28776 :   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" );
      52       28776 :   keys.reserve("optional","UPDATE_FROM","Only update this action from this time");
      53       28776 :   keys.reserve("optional","UPDATE_UNTIL","Only update this action until this time");
      54       28776 :   keys.reserve("optional","RESTART","allows per-action setting of restart (YES/NO/AUTO)");
      55       14388 : }
      56             : 
      57       14105 : Action::Action(const ActionOptions&ao):
      58       14105 :   name(ao.line[0]),
      59       14105 :   line(ao.line),
      60       14105 :   update_from(std::numeric_limits<double>::max()),
      61       14105 :   update_until(std::numeric_limits<double>::max()),
      62       14105 :   active(false),
      63       14105 :   restart(ao.plumed.getRestart()),
      64       14105 :   doCheckPoint(ao.plumed.getCPT()),
      65       14105 :   plumed(ao.plumed),
      66       14105 :   log(plumed.getLog()),
      67       14105 :   comm(plumed.comm),
      68       14105 :   multi_sim_comm(plumed.multi_sim_comm),
      69       28210 :   keywords(ao.keys)
      70             : {
      71             :   line.erase(line.begin());
      72       14105 :   log.printf("Action %s\n",name.c_str());
      73             : 
      74       14105 :   if(comm.Get_rank()==0) {
      75        7691 :     replica_index=multi_sim_comm.Get_rank();
      76             :   }
      77       14105 :   comm.Bcast(replica_index,0);
      78             : 
      79       42128 :   if ( keywords.exists("LABEL") ) { parse("LABEL",label); }
      80             : 
      81       14105 :   if(label.length()==0) {
      82        2289 :     std::string s; Tools::convert(plumed.getActionSet().size(),s);
      83        4578 :     label="@"+s;
      84             :   }
      85       14105 :   if( plumed.getActionSet().selectWithLabel<Action*>(label) ) error("label " + label + " has been already used");
      86       14105 :   log.printf("  with label %s\n",label.c_str());
      87       29847 :   if ( keywords.exists("UPDATE_FROM") ) parse("UPDATE_FROM",update_from);
      88       14105 :   if(update_from!=std::numeric_limits<double>::max()) log.printf("  only update from time %f\n",update_from);
      89       29847 :   if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until);
      90       14105 :   if(update_until!=std::numeric_limits<double>::max()) log.printf("  only update until time %f\n",update_until);
      91       28210 :   if ( keywords.exists("RESTART") ) {
      92        1683 :     std::string srestart="AUTO";
      93        3364 :     parse("RESTART",srestart);
      94        1682 :     if(srestart=="YES") restart=true;
      95        1601 :     else if(srestart=="NO")  restart=false;
      96        1579 :     else if(srestart=="AUTO") {
      97             :       // do nothing, this is the default
      98           2 :     } else error("RESTART should be either YES, NO, or AUTO");
      99             :   }
     100       14105 : }
     101             : 
     102       14104 : Action::~Action() {
     103       14104 :   if(files.size()!=0) {
     104           0 :     std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n";
     105             :   }
     106       14104 : }
     107             : 
     108          73 : FILE* Action::fopen(const char *path, const char *mode) {
     109             :   bool write(false);
     110         146 :   for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true;
     111             :   FILE* fp;
     112          73 :   if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode);
     113          73 :   else      fp=plumed.fopen(path,mode);
     114          73 :   files.insert(fp);
     115          73 :   return fp;
     116             : }
     117             : 
     118          91 : int Action::fclose(FILE*fp) {
     119             :   files.erase(fp);
     120          91 :   return plumed.fclose(fp);
     121             : }
     122             : 
     123       17862 : void Action::fflush() {
     124       17862 :   for(const auto & p : files) {
     125           0 :     std::fflush(p);
     126             :   }
     127       17862 : }
     128             : 
     129          33 : std::string Action::getKeyword(const std::string& key) {
     130             :   // Check keyword has been registered
     131          33 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     132             : 
     133             :   std::string outkey;
     134          33 :   if( Tools::getKey(line,key,outkey ) ) return key + outkey;
     135             : 
     136           0 :   if( keywords.style(key,"compulsory") ) {
     137           0 :     if( keywords.getDefaultValue(key,outkey) ) {
     138           0 :       if( outkey.length()==0 ) error("keyword " + key + " has weird default value");
     139           0 :       return key + "=" +  outkey;
     140             :     } else {
     141           0 :       error("keyword " + key + " is compulsory for this action");
     142             :     }
     143             :   }
     144           0 :   return "";
     145             : }
     146             : 
     147       40532 : void Action::parseFlag(const std::string&key,bool & t) {
     148             :   // Check keyword has been registered
     149       40532 :   plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered");
     150             :   // Check keyword is a flag
     151       81064 :   if(!keywords.style(key,"nohtml")) {
     152       78530 :     plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag");
     153             :   }
     154             : 
     155             :   // Read in the flag otherwise get the default value from the keywords object
     156       40532 :   if(!Tools::parseFlag(line,key,t)) {
     157       80858 :     if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) {
     158        2634 :       t=false;
     159       72956 :     } else if ( !keywords.getLogicalDefault(key,t) ) {
     160           0 :       log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() );
     161           0 :       plumed_error();
     162             :     }
     163             :   }
     164       40532 : }
     165             : 
     166     1083801 : void Action::addDependency(Action*action) {
     167     1083801 :   after.push_back(action);
     168     1083801 : }
     169             : 
     170     3205166 : void Action::activate() {
     171             : // preparation step is called only the first time an Action is activated.
     172             : // since it could change its dependences (e.g. in an ActionAtomistic which is
     173             : // accessing to a virtual atom), this is done just before dependencies are
     174             : // activated
     175     3205166 :   if(!active) {
     176     1642451 :     this->unlockRequests();
     177     1642451 :     prepare();
     178     1642451 :     this->lockRequests();
     179             :   } else return;
     180     3577516 :   for(const auto & p : after) p->activate();
     181     1642451 :   active=true;
     182             : }
     183             : 
     184         267 : void Action::setOption(const std::string &s) {
     185             : // This overloads the action and activate some options
     186         267 :   options.insert(s);
     187         448 :   for(const auto & p : after) p->setOption(s);
     188         267 : }
     189             : 
     190           0 : void Action::clearOptions() {
     191             : // This overloads the action and activate some options
     192             :   options.clear();
     193           0 : }
     194             : 
     195             : 
     196      188987 : void Action::clearDependencies() {
     197             :   after.clear();
     198      188987 : }
     199             : 
     200           0 : std::string Action::getDocumentation()const {
     201           0 :   return std::string("UNDOCUMENTED ACTION");
     202             : }
     203             : 
     204       27486 : void Action::checkRead() {
     205       27486 :   if(!line.empty()) {
     206           0 :     std::string msg="cannot understand the following words from the input line : ";
     207           0 :     for(unsigned i=0; i<line.size(); i++) {
     208           0 :       if(i>0) msg = msg + ", ";
     209           0 :       msg = msg + line[i];
     210             :     }
     211           0 :     error(msg);
     212             :   }
     213       27486 : }
     214             : 
     215     4498338 : long int Action::getStep()const {
     216     4498338 :   return plumed.getStep();
     217             : }
     218             : 
     219     2939688 : double Action::getTime()const {
     220     2939688 :   return plumed.getAtoms().getTimeStep()*getStep();
     221             : }
     222             : 
     223       16248 : double Action::getTimeStep()const {
     224       16248 :   return plumed.getAtoms().getTimeStep();
     225             : }
     226             : 
     227             : 
     228             : 
     229           0 : void Action::exit(int c) {
     230           0 :   plumed.exit(c);
     231           0 : }
     232             : 
     233           0 : void Action::calculateNumericalDerivatives( ActionWithValue* a ) {
     234           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");
     235             : }
     236             : 
     237      316711 : void Action::prepare() {
     238      316711 :   return;
     239             : }
     240             : 
     241          30 : [[noreturn]] void Action::error( const std::string & msg ) const {
     242          30 :   log.printf("ERROR in input to action %s with label %s : %s \n \n", name.c_str(), label.c_str(), msg.c_str() );
     243          90 :   plumed_merror("ERROR in input to action " + name + " with label " + label + " : " + msg );
     244             : }
     245             : 
     246         129 : void Action::warning( const std::string & msg ) {
     247         129 :   log.printf("WARNING for action %s with label %s : %s \n", name.c_str(), label.c_str(), msg.c_str() );
     248         129 : }
     249             : 
     250           0 : void Action::calculateFromPDB( const PDB& pdb ) {
     251           0 :   activate();
     252           0 :   for(const auto & p : after) {
     253           0 :     ActionWithValue*av=dynamic_cast<ActionWithValue*>(p);
     254           0 :     if(av) { av->clearInputForces(); av->clearDerivatives(); }
     255           0 :     p->readAtomsFromPDB( pdb );
     256           0 :     p->calculate();
     257             :   }
     258           0 :   readAtomsFromPDB( pdb );
     259           0 :   calculate();
     260           0 : }
     261             : 
     262       28109 : bool Action::getExchangeStep()const {
     263       28109 :   return plumed.getExchangeStep();
     264             : }
     265             : 
     266          40 : std::string Action::cite(const std::string&s) {
     267          40 :   return plumed.cite(s);
     268             : }
     269             : 
     270             : /// Check if action should be updated.
     271     1634506 : bool Action::checkUpdate()const {
     272     1634506 :   double t=getTime();
     273     1634506 :   if(t<update_until && (update_from==std::numeric_limits<double>::max() || t>=update_from)) return true;
     274         510 :   else return false;
     275             : }
     276             : 
     277        1091 : bool Action::getCPT()const {
     278        1091 :   return plumed.getCPT();
     279             : }
     280             : 
     281             : }
     282             : 

Generated by: LCOV version 1.15