LCOV - code coverage report
Current view: top level - core - ActionWithValue.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 120 133 90.2 %
Date: 2019-08-13 10:39:37 Functions: 26 31 83.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2019 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 "ActionWithValue.h"
      23             : #include "tools/Exception.h"
      24             : #include "tools/OpenMP.h"
      25             : 
      26             : using namespace std;
      27             : namespace PLMD {
      28             : 
      29        3169 : void ActionWithValue::registerKeywords(Keywords& keys) {
      30             :   keys.setComponentsIntroduction("By default the value of the calculated quantity can be referenced elsewhere in the "
      31             :                                  "input file by using the label of the action.  Alternatively this Action can be used "
      32             :                                  "to calculate the following quantities by employing the keywords listed "
      33             :                                  "below.  These quanties can be referenced elsewhere in the input by using this Action's "
      34        3169 :                                  "label followed by a dot and the name of the quantity required from the list below.");
      35        3169 :   keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically");
      36        3169 : }
      37             : 
      38           0 : void ActionWithValue::noAnalyticalDerivatives(Keywords& keys) {
      39           0 :   keys.remove("NUMERICAL_DERIVATIVES");
      40           0 :   keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used");
      41           0 : }
      42             : 
      43         890 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) {
      44             :   keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can "
      45             :                                  "be referenced elsewhere in the input by using this Action's label followed by a "
      46         890 :                                  "dot and the name of the quantity required from the list below.");
      47         890 : }
      48             : 
      49         414 : void ActionWithValue::useCustomisableComponents(Keywords& keys) {
      50             :   keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the "
      51             :                                  "actions input file.  However, in addition to these customizable components the "
      52         414 :                                  "following quantities will always be output");
      53         414 : }
      54             : 
      55        3014 : ActionWithValue::ActionWithValue(const ActionOptions&ao):
      56             :   Action(ao),
      57             :   noderiv(true),
      58        3014 :   numericalDerivatives(false)
      59             : {
      60        3014 :   if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives);
      61        3014 :   if(numericalDerivatives) log.printf("  using numerical derivatives\n");
      62        3014 : }
      63             : 
      64        6028 : ActionWithValue::~ActionWithValue() {
      65        3014 :   for(unsigned i=0; i<values.size(); ++i)delete values[i];
      66        3014 : }
      67             : 
      68      147360 : void ActionWithValue::clearInputForces() {
      69      147360 :   for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce();
      70      147360 : }
      71             : 
      72      150115 : void ActionWithValue::clearDerivatives() {
      73      150115 :   unsigned nt = OpenMP::getNumThreads();
      74      448218 :   #pragma omp parallel num_threads(nt)
      75             :   {
      76      299341 :     #pragma omp for
      77      727077 :     for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives();
      78             :   }
      79      150115 : }
      80             : 
      81             : // -- These are the routine for copying the value pointers to other classes -- //
      82             : 
      83     2553069 : bool ActionWithValue::exists( const std::string& name ) const {
      84    77665304 :   for(unsigned i=0; i<values.size(); ++i) {
      85    75136402 :     if (values[i]->name==name) return true;
      86             :   }
      87     2529070 :   return false;
      88             : }
      89             : 
      90       24025 : Value* ActionWithValue::copyOutput( const std::string& name ) const {
      91    10785024 :   for(unsigned i=0; i<values.size(); ++i) {
      92    10785024 :     if (values[i]->name==name) return values[i];
      93             :   }
      94           0 :   plumed_merror("there is no pointer with name " + name);
      95             :   return NULL;
      96             : }
      97             : 
      98       10070 : Value* ActionWithValue::copyOutput( const unsigned& n ) const {
      99       10070 :   plumed_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     100       10070 :   return values[n];
     101             : }
     102             : 
     103             : // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- //
     104             : 
     105          37 : void ActionWithValue::addValue() {
     106          37 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     107          37 :   values.push_back(new Value(this,getLabel(), false ) );
     108          37 : }
     109             : 
     110        1678 : void ActionWithValue::addValueWithDerivatives() {
     111        1678 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     112        1678 :   values.push_back(new Value(this,getLabel(), true ) );
     113        1678 : }
     114             : 
     115        1262 : void ActionWithValue::setNotPeriodic() {
     116        1262 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     117        1262 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     118        1262 :   values[0]->min=0; values[0]->max=0;
     119        1262 :   values[0]->setupPeriodicity();
     120        1262 : }
     121             : 
     122         453 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) {
     123         453 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     124         453 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     125         453 :   values[0]->setDomain( min, max );
     126         453 : }
     127             : 
     128    15298556 : Value* ActionWithValue::getPntrToValue() {
     129             :   plumed_dbg_massert(values.size()==1,"The number of components is not equal to one");
     130             :   plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default");
     131    15298556 :   return values[0];
     132             : }
     133             : 
     134             : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- //
     135             : 
     136       22215 : void ActionWithValue::addComponent( const std::string& name ) {
     137       22215 :   if( !keywords.outputComponentExists(name,true) ) {
     138         288 :     warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     139         144 :             "registerKeywords as described in the developer docs.");
     140             :   }
     141       22215 :   std::string thename; thename=getLabel() + "." + name;
     142    18666996 :   for(unsigned i=0; i<values.size(); ++i) {
     143    18644781 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     144    18644781 :     plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n"
     145           0 :                    "Remove the line addComponent(\"bias\") from your bias.");
     146    18644781 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name");
     147             :   }
     148       22215 :   values.push_back(new Value(this,thename, false ) );
     149       44430 :   std::string msg="  added component to this action:  "+thename+" \n";
     150       44430 :   log.printf(msg.c_str());
     151       22215 : }
     152             : 
     153       10242 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) {
     154       10242 :   if( !keywords.outputComponentExists(name,true) ) {
     155           2 :     warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     156           1 :             "registerKeywords as described in the developer doc.");
     157             :   }
     158       10242 :   std::string thename; thename=getLabel() + "." + name;
     159     2440015 :   for(unsigned i=0; i<values.size(); ++i) {
     160     2429773 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     161     2429773 :     plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n"
     162           0 :                    "Remove the line addComponentWithDerivatives(\"bias\") from your bias.");
     163     2429773 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name");
     164             :   }
     165       10242 :   values.push_back(new Value(this,thename, true ) );
     166       20484 :   std::string msg="  added component to this action:  "+thename+" \n";
     167       20484 :   log.printf(msg.c_str());
     168       10242 : }
     169             : 
     170     2522248 : int ActionWithValue::getComponent( const std::string& name ) const {
     171     2522248 :   plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value");
     172     2522259 :   std::string thename; thename=getLabel() + "." + name;
     173    56448192 :   for(unsigned i=0; i<values.size(); ++i) {
     174    56448203 :     if (values[i]->name==thename) return i;
     175             :   }
     176           0 :   plumed_merror("there is no component with name " + name);
     177     2522287 :   return -1;
     178             : }
     179             : 
     180           0 : std::string ActionWithValue::getComponentsList( ) const {
     181           0 :   std::string complist;
     182           0 :   for(unsigned i=0; i<values.size(); ++i) {
     183           0 :     complist+=values[i]->name+" ";
     184             :   }
     185           0 :   return complist;
     186             : }
     187             : 
     188         789 : std::vector<std::string> ActionWithValue::getComponentsVector( ) const {
     189         789 :   std::vector<std::string> complist;
     190      212084 :   for(unsigned i=0; i<values.size(); ++i) {
     191      211295 :     complist.push_back(values[i]->name);
     192             :   }
     193         789 :   return complist;
     194             : }
     195             : 
     196       29331 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) {
     197       29331 :   int kk=getComponent(name);
     198       29331 :   values[kk]->min=0; values[kk]->max=0;
     199       29331 :   values[kk]->setupPeriodicity();
     200       29331 : }
     201             : 
     202          80 : void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) {
     203          80 :   int kk=getComponent(name);
     204          80 :   values[kk]->setDomain(min,max);
     205          80 : }
     206             : 
     207      147360 : void ActionWithValue::setGradientsIfNeeded() {
     208      147360 :   if(isOptionOn("GRADIENTS")) {
     209         402 :     for(unsigned i=0; i<values.size(); i++) values[i]->setGradients();
     210             :   }
     211      147360 : }
     212             : 
     213     3491495 : void ActionWithValue::turnOnDerivatives() {
     214             :   // Turn on the derivatives
     215     3491495 :   noderiv=false;
     216             :   // Resize the derivatives
     217     3491495 :   for(unsigned i=0; i<values.size(); ++i) values[i]->resizeDerivatives( getNumberOfDerivatives() );
     218             :   // And turn on the derivatives in all actions on which we are dependent
     219     6978376 :   for(unsigned i=0; i<getDependencies().size(); ++i) {
     220     3486881 :     ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] );
     221     3486881 :     if(vv) vv->turnOnDerivatives();
     222             :   }
     223     3491495 : }
     224             : 
     225     2492843 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) {
     226     2492843 :   int kk=getComponent(name);
     227     2492878 :   return values[kk];
     228             : }
     229             : 
     230      468840 : Value* ActionWithValue::getPntrToComponent( int n ) {
     231             :   plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     232      468840 :   return values[n];
     233             : }
     234             : 
     235             : }

Generated by: LCOV version 1.13