LCOV - code coverage report
Current view: top level - core - ActionWithValue.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 111 124 89.5 %
Date: 2024-10-11 08:09:47 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 "ActionWithValue.h"
      23             : #include "tools/Exception.h"
      24             : #include "tools/OpenMP.h"
      25             : 
      26             : namespace PLMD {
      27             : 
      28        4328 : void ActionWithValue::registerKeywords(Keywords& keys) {
      29        4328 :   keys.setComponentsIntroduction("By default the value of the calculated quantity can be referenced elsewhere in the "
      30             :                                  "input file by using the label of the action.  Alternatively this Action can be used "
      31             :                                  "to calculate the following quantities by employing the keywords listed "
      32             :                                  "below.  These quantities can be referenced elsewhere in the input by using this Action's "
      33             :                                  "label followed by a dot and the name of the quantity required from the list below.");
      34        8656 :   keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically");
      35        4328 : }
      36             : 
      37           0 : void ActionWithValue::noAnalyticalDerivatives(Keywords& keys) {
      38           0 :   keys.remove("NUMERICAL_DERIVATIVES");
      39           0 :   keys.addFlag("NUMERICAL_DERIVATIVES",false,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used");
      40           0 : }
      41             : 
      42        1194 : void ActionWithValue::componentsAreNotOptional(Keywords& keys) {
      43        1194 :   keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quantities can "
      44             :                                  "be referenced elsewhere in the input by using this Action's label followed by a "
      45             :                                  "dot and the name of the quantity required from the list below.");
      46        1194 : }
      47             : 
      48         241 : void ActionWithValue::useCustomisableComponents(Keywords& keys) {
      49         241 :   keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the "
      50             :                                  "actions input file.  However, in addition to the components that can be customized the "
      51             :                                  "following quantities will always be output");
      52         241 : }
      53             : 
      54        4131 : ActionWithValue::ActionWithValue(const ActionOptions&ao):
      55             :   Action(ao),
      56        4131 :   noderiv(true),
      57        4131 :   numericalDerivatives(false)
      58             : {
      59       11924 :   if( keywords.exists("NUMERICAL_DERIVATIVES") ) parseFlag("NUMERICAL_DERIVATIVES",numericalDerivatives);
      60        4131 :   if(numericalDerivatives) log.printf("  using numerical derivatives\n");
      61        4131 : }
      62             : 
      63        4131 : ActionWithValue::~ActionWithValue() {
      64             : // empty destructor to delete unique_ptr
      65        4131 : }
      66             : 
      67     1389822 : void ActionWithValue::clearInputForces() {
      68     3470875 :   for(unsigned i=0; i<values.size(); i++) values[i]->clearInputForce();
      69     1389822 : }
      70             : 
      71     1392602 : void ActionWithValue::clearDerivatives() {
      72     1392602 :   unsigned nt = OpenMP::getNumThreads();
      73     1392602 :   #pragma omp parallel num_threads(nt)
      74             :   {
      75             :     #pragma omp for
      76             :     for(unsigned i=0; i<values.size(); i++) values[i]->clearDerivatives();
      77             :   }
      78     1392602 : }
      79             : 
      80             : // -- These are the routine for copying the value pointers to other classes -- //
      81             : 
      82    10661051 : bool ActionWithValue::exists( const std::string& name ) const {
      83   116533068 :   for(unsigned i=0; i<values.size(); ++i) {
      84   105897960 :     if (values[i]->name==name) return true;
      85             :   }
      86             :   return false;
      87             : }
      88             : 
      89       26102 : Value* ActionWithValue::copyOutput( const std::string& name ) const {
      90    11307760 :   for(unsigned i=0; i<values.size(); ++i) {
      91    11307760 :     if (values[i]->name==name) return values[i].get();
      92             :   }
      93           0 :   plumed_merror("there is no pointer with name " + name);
      94             : }
      95             : 
      96       10763 : Value* ActionWithValue::copyOutput( const unsigned& n ) const {
      97       10763 :   plumed_massert(n<values.size(),"you have requested a pointer that is out of bounds");
      98       10763 :   return values[n].get();
      99             : }
     100             : 
     101             : // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- //
     102             : 
     103          56 : void ActionWithValue::addValue() {
     104          56 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     105          56 :   values.emplace_back(Tools::make_unique<Value>(this,getLabel(), false ) );
     106          56 : }
     107             : 
     108        2317 : void ActionWithValue::addValueWithDerivatives() {
     109        2317 :   plumed_massert(values.empty(),"You have already added the default value for this action");
     110        2317 :   values.emplace_back(Tools::make_unique<Value>(this,getLabel(), true ) );
     111        2317 : }
     112             : 
     113        1697 : void ActionWithValue::setNotPeriodic() {
     114        1697 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     115        1697 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     116        1697 :   values[0]->min=0; values[0]->max=0;
     117        1697 :   values[0]->setupPeriodicity();
     118        1697 : }
     119             : 
     120         676 : void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) {
     121         676 :   plumed_massert(values.size()==1,"The number of components is not equal to one");
     122         676 :   plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default");
     123         676 :   values[0]->setDomain( min, max );
     124         676 : }
     125             : 
     126    16301774 : Value* ActionWithValue::getPntrToValue() {
     127             :   plumed_dbg_massert(values.size()==1,"The number of components is not equal to one");
     128             :   plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default");
     129    16301774 :   return values[0].get();
     130             : }
     131             : 
     132             : // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- //
     133             : 
     134       22633 : void ActionWithValue::addComponent( const std::string& name ) {
     135       22633 :   if( !keywords.outputComponentExists(name,true) ) {
     136           0 :     plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     137             :                   "registerKeywords as described in the developer docs.");
     138             :   }
     139       45266 :   std::string thename; thename=getLabel() + "." + name;
     140    18683668 :   for(unsigned i=0; i<values.size(); ++i) {
     141    18661035 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     142    18661035 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename);
     143    18661035 :     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"
     144             :                    "Remove the line addComponent(\"bias\") from your bias.");
     145             :   }
     146       22633 :   values.emplace_back(Tools::make_unique<Value>(this,thename, false ) );
     147       22633 :   std::string msg="  added component to this action:  "+thename+" \n";
     148       22633 :   log.printf(msg.c_str());
     149       22633 : }
     150             : 
     151       10710 : void ActionWithValue::addComponentWithDerivatives( const std::string& name ) {
     152       10710 :   if( !keywords.outputComponentExists(name,true) ) {
     153           0 :     plumed_merror("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in "
     154             :                   "registerKeywords as described in the developer doc.");
     155             :   }
     156       21420 :   std::string thename; thename=getLabel() + "." + name;
     157     2441407 :   for(unsigned i=0; i<values.size(); ++i) {
     158     2430697 :     plumed_massert(values[i]->name!=getLabel(),"Cannot mix single values with components");
     159     2430697 :     plumed_massert(values[i]->name!=thename,"there is already a value with this name: "+thename);
     160     2430697 :     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"
     161             :                    "Remove the line addComponentWithDerivatives(\"bias\") from your bias.");
     162             :   }
     163       10710 :   values.emplace_back(Tools::make_unique<Value>(this,thename, true ) );
     164       10710 :   std::string msg="  added component to this action:  "+thename+" \n";
     165       10710 :   log.printf(msg.c_str());
     166       10710 : }
     167             : 
     168    10628297 : int ActionWithValue::getComponent( const std::string& name ) const {
     169    10628297 :   plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value");
     170    21256594 :   std::string thename; thename=getLabel() + "." + name;
     171    64111312 :   for(unsigned i=0; i<values.size(); ++i) {
     172    64178768 :     if (values[i]->name==thename) return i;
     173             :   }
     174           0 :   plumed_merror("there is no component with name " + name);
     175             : }
     176             : 
     177           0 : std::string ActionWithValue::getComponentsList( ) const {
     178             :   std::string complist;
     179           0 :   for(unsigned i=0; i<values.size(); ++i) {
     180           0 :     complist+=values[i]->name+" ";
     181             :   }
     182           0 :   return complist;
     183             : }
     184             : 
     185        1354 : std::vector<std::string> ActionWithValue::getComponentsVector( ) const {
     186             :   std::vector<std::string> complist;
     187      220352 :   for(unsigned i=0; i<values.size(); ++i) {
     188      218998 :     complist.push_back(values[i]->name);
     189             :   }
     190        1354 :   return complist;
     191           0 : }
     192             : 
     193       30152 : void ActionWithValue::componentIsNotPeriodic( const std::string& name ) {
     194       30152 :   int kk=getComponent(name);
     195       30152 :   values[kk]->min=0; values[kk]->max=0;
     196       30152 :   values[kk]->setupPeriodicity();
     197       30152 : }
     198             : 
     199          92 : void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) {
     200          92 :   int kk=getComponent(name);
     201          92 :   values[kk]->setDomain(min,max);
     202          92 : }
     203             : 
     204     1389822 : void ActionWithValue::setGradientsIfNeeded() {
     205     2779644 :   if(isOptionOn("GRADIENTS")) {
     206         366 :     for(unsigned i=0; i<values.size(); i++) values[i]->setGradients();
     207             :   }
     208     1389822 : }
     209             : 
     210     3493078 : void ActionWithValue::turnOnDerivatives() {
     211             :   // Turn on the derivatives
     212     3493078 :   noderiv=false;
     213             :   // Resize the derivatives
     214  4106212105 :   for(unsigned i=0; i<values.size(); ++i) values[i]->resizeDerivatives( getNumberOfDerivatives() );
     215             :   // And turn on the derivatives in all actions on which we are dependent
     216     7085574 :   for(unsigned i=0; i<getDependencies().size(); ++i) {
     217     3592496 :     ActionWithValue* vv=dynamic_cast<ActionWithValue*>( getDependencies()[i] );
     218     3592496 :     if(vv) vv->turnOnDerivatives();
     219             :   }
     220     3493078 : }
     221             : 
     222    10598053 : Value* ActionWithValue::getPntrToComponent( const std::string& name ) {
     223    10598053 :   int kk=getComponent(name);
     224    10598053 :   return values[kk].get();
     225             : }
     226             : 
     227     2139071 : Value* ActionWithValue::getPntrToComponent( int n ) {
     228             :   plumed_dbg_massert(n<values.size(),"you have requested a pointer that is out of bounds");
     229     2139071 :   return values[n].get();
     230             : }
     231             : 
     232             : }

Generated by: LCOV version 1.15