LCOV - code coverage report
Current view: top level - core - ActionWithValue.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 111 127 87.4 %
Date: 2019-08-13 10:15:31 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        3757 : 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 quantities can be referenced elsewhere in the input by using this Action's "
      34        7514 :                                  "label followed by a dot and the name of the quantity required from the list below.");
      35       11271 :   keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically");
      36        3757 : }
      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        1052 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) {
      44             :   keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quantities can "
      45             :                                  "be referenced elsewhere in the input by using this Action's label followed by a "
      46        2104 :                                  "dot and the name of the quantity required from the list below.");
      47        1052 : }
      48             : 
      49         183 : 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 the components that can be customized the "
      52         366 :                                  "following quantities will always be output");
      53         183 : }
      54             : 
      55        3579 : ActionWithValue::ActionWithValue(const ActionOptions&ao):
      56             :   Action(ao),
      57             :   noderiv(true),
      58        7158 :   numericalDerivatives(false)
      59             : {
      60       10297 :   if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives);
      61        3579 :   if(numericalDerivatives) log.printf("  using numerical derivatives\n");
      62        3579 : }
      63             : 
      64        3579 : ActionWithValue::~ActionWithValue() {
      65             : // empty destructor to delete unique_ptr
      66        3579 : }
      67             : 
      68      389626 : void ActionWithValue::clearInputForces() {
      69     2226958 :   for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce();
      70      389626 : }
      71             : 
      72      392386 : void ActionWithValue::clearDerivatives() {
      73      392386 :   unsigned nt = OpenMP::getNumThreads();
      74     1175191 :   #pragma omp parallel num_threads(nt)
      75             :   {
      76             :     #pragma omp for
      77      782805 :     for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives();
      78             :   }
      79      392386 : }
      80             : 
      81             : // -- These are the routine for copying the value pointers to other classes -- //
      82             : 
      83    10284026 : bool ActionWithValue::exists( const std::string& name ) const {
      84   197545472 :   for(unsigned i=0; i<values.size(); ++i) {
      85    88514048 :     if (values[i]->name==name) return true;
      86             :   }
      87             :   return false;
      88             : }
      89             : 
      90       25340 : Value* ActionWithValue::copyOutput( const std::string& name ) const {
      91    22617536 :   for(unsigned i=0; i<values.size(); ++i) {
      92    11308768 :     if (values[i]->name==name) return values[i].get();
      93             :   }
      94           0 :   plumed_merror("there is no pointer with name " + name);
      95             :   return NULL;
      96             : }
      97             : 
      98       10303 : Value* ActionWithValue::copyOutput( const unsigned& n ) const {
      99       20606 :   plumed_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     100       10303 :   return values[n].get();
     101             : }
     102             : 
     103             : // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- //
     104             : 
     105          55 : void ActionWithValue::addValue() {
     106          55 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     107          55 :   values.emplace_back(new Value(this,getLabel(), false ) );
     108          55 : }
     109             : 
     110        1942 : void ActionWithValue::addValueWithDerivatives() {
     111        1942 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     112        1942 :   values.emplace_back(new Value(this,getLabel(), true ) );
     113        1942 : }
     114             : 
     115        1464 : void ActionWithValue::setNotPeriodic() {
     116        1464 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     117        2928 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     118        2928 :   values[0]->min=0; values[0]->max=0;
     119        1464 :   values[0]->setupPeriodicity();
     120        1464 : }
     121             : 
     122         533 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) {
     123         533 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     124        1066 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     125         533 :   values[0]->setDomain( min, max );
     126         533 : }
     127             : 
     128    15766034 : 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    15766034 :   return values[0].get();
     132             : }
     133             : 
     134             : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- //
     135             : 
     136       22597 : void ActionWithValue::addComponent( const std::string& name ) {
     137       22597 :   if( !keywords.outputComponentExists(name,true) ) {
     138           0 :     plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     139           0 :                   "registerKeywords as described in the developer docs.");
     140             :   }
     141       67791 :   std::string thename; thename=getLabel() + "." + name;
     142    37339284 :   for(unsigned i=0; i<values.size(); ++i) {
     143    55941135 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     144    18647045 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename);
     145    37294090 :     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"
     146           0 :                    "Remove the line addComponent(\"bias\") from your bias.");
     147             :   }
     148       22597 :   values.emplace_back(new Value(this,thename, false ) );
     149       45194 :   std::string msg="  added component to this action:  "+thename+" \n";
     150       22597 :   log.printf(msg.c_str());
     151       22597 : }
     152             : 
     153       10529 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) {
     154       10529 :   if( !keywords.outputComponentExists(name,true) ) {
     155           0 :     plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     156           0 :                   "registerKeywords as described in the developer doc.");
     157             :   }
     158       31587 :   std::string thename; thename=getLabel() + "." + name;
     159     4883098 :   for(unsigned i=0; i<values.size(); ++i) {
     160     7293060 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     161     2431020 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename);
     162     4862040 :     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"
     163           0 :                    "Remove the line addComponentWithDerivatives(\"bias\") from your bias.");
     164             :   }
     165       10529 :   values.emplace_back(new Value(this,thename, true ) );
     166       21058 :   std::string msg="  added component to this action:  "+thename+" \n";
     167       10529 :   log.printf(msg.c_str());
     168       10529 : }
     169             : 
     170    10251982 : int ActionWithValue::getComponent( const std::string& name ) const {
     171    10251982 :   plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value");
     172    30755988 :   std::string thename; thename=getLabel() + "." + name;
     173   126924434 :   for(unsigned i=0; i<values.size(); ++i) {
     174    63462217 :     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         990 : std::vector<std::string> ActionWithValue::getComponentsVector( ) const {
     189             :   std::vector<std::string> complist;
     190      441256 :   for(unsigned i=0; i<values.size(); ++i) {
     191      219638 :     complist.push_back(values[i]->name);
     192             :   }
     193         990 :   return complist;
     194             : }
     195             : 
     196       29990 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) {
     197       29990 :   int kk=getComponent(name);
     198       89970 :   values[kk]->min=0; values[kk]->max=0;
     199       29990 :   values[kk]->setupPeriodicity();
     200       29990 : }
     201             : 
     202          90 : void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) {
     203          90 :   int kk=getComponent(name);
     204         180 :   values[kk]->setDomain(min,max);
     205          90 : }
     206             : 
     207      389626 : void ActionWithValue::setGradientsIfNeeded() {
     208      779252 :   if(isOptionOn("GRADIENTS")) {
     209        1590 :     for(unsigned i=0; i<values.size(); i++) values[i]->setGradients();
     210             :   }
     211      389626 : }
     212             : 
     213     3492091 : void ActionWithValue::turnOnDerivatives() {
     214             :   // Turn on the derivatives
     215     3492091 :   noderiv=false;
     216             :   // Resize the derivatives
     217  8212422892 :   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    10466541 :   for(unsigned i=0; i<getDependencies().size(); ++i) {
     220     3487225 :     ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] );
     221     3487225 :     if(vv) vv->turnOnDerivatives();
     222             :   }
     223     3492091 : }
     224             : 
     225    10221908 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) {
     226    10221908 :   int kk=getComponent(name);
     227    20443884 :   return values[kk].get();
     228             : }
     229             : 
     230      774974 : Value* ActionWithValue::getPntrToComponent( int n ) {
     231             :   plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     232     1549948 :   return values[n].get();
     233             : }
     234             : 
     235             : }

Generated by: LCOV version 1.14