LCOV - code coverage report
Current view: top level - core - ActionWithValue.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 114 124 91.9 %
Date: 2020-11-18 11:20:57 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        3179 : void ActionWithValue::registerKeywords(Keywords& keys) {
      30        6358 :   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             :                                  "label followed by a dot and the name of the quantity required from the list below.");
      35        9537 :   keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically");
      36        3179 : }
      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         891 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) {
      44        1782 :   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             :                                  "dot and the name of the quantity required from the list below.");
      47         891 : }
      48             : 
      49         415 : void ActionWithValue::useCustomisableComponents(Keywords& keys) {
      50         830 :   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             :                                  "following quantities will always be output");
      53         415 : }
      54             : 
      55        3024 : ActionWithValue::ActionWithValue(const ActionOptions&ao):
      56             :   Action(ao),
      57             :   noderiv(true),
      58        6048 :   numericalDerivatives(false)
      59             : {
      60        8824 :   if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives);
      61        3024 :   if(numericalDerivatives) log.printf("  using numerical derivatives\n");
      62        3024 : }
      63             : 
      64        3024 : ActionWithValue::~ActionWithValue() {
      65      108582 :   for(unsigned i=0; i<values.size(); ++i)delete values[i];
      66        3024 : }
      67             : 
      68      147518 : void ActionWithValue::clearInputForces() {
      69     1999772 :   for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce();
      70      147518 : }
      71             : 
      72      150273 : void ActionWithValue::clearDerivatives() {
      73      150273 :   unsigned nt = OpenMP::getNumThreads();
      74      450159 :   #pragma omp parallel num_threads(nt)
      75             :   {
      76             :     #pragma omp for
      77      730964 :     for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives();
      78             :   }
      79      150273 : }
      80             : 
      81             : // -- These are the routine for copying the value pointers to other classes -- //
      82             : 
      83     2553115 : bool ActionWithValue::exists( const std::string& name ) const {
      84   230444009 :   for(unsigned i=0; i<values.size(); ++i) {
      85    75136623 :     if (values[i]->name==name) return true;
      86             :   }
      87             :   return false;
      88             : }
      89             : 
      90       24033 : Value* ActionWithValue::copyOutput( const std::string& name ) const {
      91    32331063 :   for(unsigned i=0; i<values.size(); ++i) {
      92    10785032 :     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       20140 :   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         111 :   values.push_back(new Value(this,getLabel(), false ) );
     108          37 : }
     109             : 
     110        1682 : void ActionWithValue::addValueWithDerivatives() {
     111        1682 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     112        5046 :   values.push_back(new Value(this,getLabel(), true ) );
     113        1682 : }
     114             : 
     115        1262 : void ActionWithValue::setNotPeriodic() {
     116        1262 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     117        2524 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     118        2524 :   values[0]->min=0; values[0]->max=0;
     119        1262 :   values[0]->setupPeriodicity();
     120        1262 : }
     121             : 
     122         457 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) {
     123         457 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     124         914 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     125         457 :   values[0]->setDomain( min, max );
     126         457 : }
     127             : 
     128    15299144 : 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    15299144 :   return values[0];
     132             : }
     133             : 
     134             : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- //
     135             : 
     136       22216 : void ActionWithValue::addComponent( const std::string& name ) {
     137       22216 :   if( !keywords.outputComponentExists(name,true) ) {
     138         432 :     warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     139             :             "registerKeywords as described in the developer docs.");
     140             :   }
     141       88864 :   std::string thename; thename=getLabel() + "." + name;
     142    55978778 :   for(unsigned i=0; i<values.size(); ++i) {
     143    55934346 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     144    37289564 :     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             :                    "Remove the line addComponent(\"bias\") from your bias.");
     146    37289564 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name");
     147             :   }
     148       44432 :   values.push_back(new Value(this,thename, false ) );
     149       44432 :   std::string msg="  added component to this action:  "+thename+" \n";
     150       44432 :   log.printf(msg.c_str());
     151       22216 : }
     152             : 
     153       10243 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) {
     154       10243 :   if( !keywords.outputComponentExists(name,true) ) {
     155           3 :     warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     156             :             "registerKeywords as described in the developer doc.");
     157             :   }
     158       40972 :   std::string thename; thename=getLabel() + "." + name;
     159     7309805 :   for(unsigned i=0; i<values.size(); ++i) {
     160     7289319 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     161     4859546 :     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             :                    "Remove the line addComponentWithDerivatives(\"bias\") from your bias.");
     163     4859546 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name");
     164             :   }
     165       20486 :   values.push_back(new Value(this,thename, true ) );
     166       20486 :   std::string msg="  added component to this action:  "+thename+" \n";
     167       20486 :   log.printf(msg.c_str());
     168       10243 : }
     169             : 
     170     2522295 : int ActionWithValue::getComponent( const std::string& name ) const {
     171     5044590 :   plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value");
     172    10089180 :   std::string thename; thename=getLabel() + "." + name;
     173   166822377 :   for(unsigned i=0; i<values.size(); ++i) {
     174    56448224 :     if (values[i]->name==thename) return i;
     175             :   }
     176           0 :   plumed_merror("there is no component with name " + name);
     177             :   return -1;
     178             : }
     179             : 
     180           0 : std::string ActionWithValue::getComponentsList( ) const {
     181             :   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             :   std::vector<std::string> complist;
     190      635463 :   for(unsigned i=0; i<values.size(); ++i) {
     191      211295 :     complist.push_back(values[i]->name);
     192             :   }
     193         789 :   return complist;
     194             : }
     195             : 
     196       29333 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) {
     197       29333 :   int kk=getComponent(name);
     198       87999 :   values[kk]->min=0; values[kk]->max=0;
     199       29333 :   values[kk]->setupPeriodicity();
     200       29333 : }
     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         160 :   values[kk]->setDomain(min,max);
     205          80 : }
     206             : 
     207      147518 : void ActionWithValue::setGradientsIfNeeded() {
     208      295036 :   if(isOptionOn("GRADIENTS")) {
     209        1164 :     for(unsigned i=0; i<values.size(); i++) values[i]->setGradients();
     210             :   }
     211      147518 : }
     212             : 
     213     3491500 : void ActionWithValue::turnOnDerivatives() {
     214             :   // Turn on the derivatives
     215     3491500 :   noderiv=false;
     216             :   // Resize the derivatives
     217 16417849908 :   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    17443649 :   for(unsigned i=0; i<getDependencies().size(); ++i) {
     220     3486883 :     ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] );
     221     3486883 :     if(vv) vv->turnOnDerivatives();
     222             :   }
     223     3491500 : }
     224             : 
     225     2492882 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) {
     226     2492882 :   int kk=getComponent(name);
     227     4985764 :   return values[kk];
     228             : }
     229             : 
     230      469777 : Value* ActionWithValue::getPntrToComponent( int n ) {
     231             :   plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     232      939554 :   return values[n];
     233             : }
     234             : 
     235             : }

Generated by: LCOV version 1.13