LCOV - code coverage report
Current view: top level - core - Value.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 41 43 95.3 %
Date: 2024-10-11 08:09:47 Functions: 5 5 100.0 %

          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             : #ifndef __PLUMED_core_Value_h
      23             : #define __PLUMED_core_Value_h
      24             : 
      25             : #include <vector>
      26             : #include <string>
      27             : #include <map>
      28             : #include "tools/Exception.h"
      29             : #include "tools/Tools.h"
      30             : #include "tools/AtomNumber.h"
      31             : #include "tools/Vector.h"
      32             : 
      33             : namespace PLMD {
      34             : 
      35             : class ActionWithValue;
      36             : 
      37             : /// \ingroup TOOLBOX
      38             : /// A class for holding the value of a function together with its derivatives.
      39             : /// Typically, an  object of type PLMD::ActionWithValue will contain one
      40             : /// object of type PLUMD::Value that will be named after the label.  If the
      41             : /// PLMD::ActionWithValue is part of a class that calculates multiple components
      42             : /// then the class will contain multiple that will be called label.component-name
      43             : /// This class is used to pass information between different PLMD::Action
      44             : /// objects.  However, if you find a use for a tempory PLMD::Value in some method
      45             : /// you are implementing please feel free to use it.
      46             : class Value {
      47             :   friend class ActionWithValue;
      48             : /// This copies the contents of a value into a second value (just the derivatives and value)
      49             :   friend void copy( const Value& val1, Value& val2 );
      50             : /// This copies the contents of a value into a second value (but second value is a pointer)
      51             :   friend void copy( const Value& val, Value* val2 );
      52             : /// This adds some derivatives onto the value
      53             :   friend void add( const Value& val1, Value* valout );
      54             : /// This calculates val1*val2 and sorts out the derivatives
      55             :   friend void product( const Value& val1, const Value& val2, Value& valout );
      56             : /// This calculates va1/val2 and sorts out the derivatives
      57             :   friend void quotient( const Value& val1, const Value& val2, Value* valout );
      58             : private:
      59             : /// The action in which this quantity is calculated
      60             :   ActionWithValue* action;
      61             : /// Had the value been set
      62             :   bool value_set;
      63             : /// The value of the quantity
      64             :   double value;
      65             : /// The force acting on this quantity
      66             :   double inputForce;
      67             : /// A flag telling us we have a force acting on this quantity
      68             :   bool hasForce;
      69             : /// The derivatives of the quantity stored in value
      70             :   std::vector<double> derivatives;
      71             :   std::map<AtomNumber,Vector> gradients;
      72             : /// The name of this quantiy
      73             :   std::string name;
      74             : /// Does this quanity have derivatives
      75             :   bool hasDeriv;
      76             : /// Is this quantity periodic
      77             :   enum {unset,periodic,notperiodic} periodicity;
      78             : /// Various quantities that describe the domain of this value
      79             :   std::string str_min, str_max;
      80             :   double min,max;
      81             :   double max_minus_min;
      82             :   double inv_max_minus_min;
      83             : /// Complete the setup of the periodicity
      84             :   void setupPeriodicity();
      85             : // bring value within PBCs
      86             :   void applyPeriodicity();
      87             : public:
      88             : /// A constructor that can be used to make Vectors of values
      89             :   Value();
      90             : /// A constructor that can be used to make Vectors of named values
      91             :   explicit Value(const std::string& name);
      92             : /// A constructor that is used throughout the code to setup the value poiters
      93             :   Value(ActionWithValue* av, const std::string& name, const bool withderiv);
      94             : /// Set the value of the function
      95             :   void set(double);
      96             : /// Add something to the value of the function
      97             :   void add(double);
      98             : /// Get the value of the function
      99             :   double get() const;
     100             : /// Find out if the value has been set
     101             :   bool valueHasBeenSet() const;
     102             : /// Check if the value is periodic
     103             :   bool isPeriodic() const;
     104             : /// Set the function not periodic
     105             :   void setNotPeriodic();
     106             : /// Set the domain of the function
     107             :   void setDomain(const std::string&, const std::string&);
     108             : /// Get the domain of the quantity
     109             :   void getDomain(std::string&,std::string&) const;
     110             : /// Get the domain of the quantity
     111             :   void getDomain(double&,double&) const;
     112             : /// Get the name of the quantity
     113             :   const std::string& getName() const;
     114             : /// Check whether or not this particular quantity has derivatives
     115             :   bool hasDerivatives()const;
     116             : /// Get the number of derivatives that this particular value has
     117             :   unsigned getNumberOfDerivatives() const;
     118             : /// Set the number of derivatives
     119             :   void resizeDerivatives(int n);
     120             : /// Set all the derivatives to zero
     121             :   void clearDerivatives();
     122             : /// Add some derivative to the ith component of the derivatives array
     123             :   void addDerivative(unsigned i,double d);
     124             : /// Set the value of the ith component of the derivatives array
     125             :   void setDerivative(unsigned i, double d);
     126             : /// Apply the chain rule to the derivatives
     127             :   void chainRule(double df);
     128             : /// Get the derivative with respect to component n
     129             :   double getDerivative(const unsigned n) const;
     130             : /// Clear the input force on the variable
     131             :   void clearInputForce();
     132             : /// Add some force on this value
     133             :   void  addForce(double f);
     134             : /// Get the value of the force on this colvar
     135             :   double getForce() const ;
     136             : /// Apply the forces to the derivatives using the chain rule (if there are no forces this routine returns false)
     137             :   bool applyForce( std::vector<double>& forces ) const ;
     138             : /// Calculate the difference between the instantaneous value of the function and some other point: other_point-inst_val
     139             :   double difference(double)const;
     140             : /// Calculate the difference between two values of this function: d2 -d1
     141             :   double difference(double d1,double d2)const;
     142             : /// This returns the pointer to the action where this value is calculated
     143             :   ActionWithValue* getPntrToAction();
     144             : /// Bring back one value into the correct pbc if needed, else give back the value
     145             :   double bringBackInPbc(double d1)const;
     146             : /// Get the difference between max and minimum of domain
     147             :   double getMaxMinusMin()const;
     148             : /// This sets up the gradients
     149             :   void setGradients();
     150             :   static double projection(const Value&,const Value&);
     151             : };
     152             : 
     153             : void copy( const Value& val1, Value& val2 );
     154             : void copy( const Value& val1, Value* val2 );
     155             : void add( const Value& val1, Value* valout );
     156             : 
     157             : inline
     158    44362470 : void Value::applyPeriodicity() {
     159    44362470 :   if(periodicity==periodic) {
     160    30706139 :     value=min+difference(min,value);
     161    30706139 :     if(value<min)value+=max_minus_min;
     162             :   }
     163    44362470 : }
     164             : 
     165             : inline
     166             : void product( const Value& val1, const Value& val2, Value& valout ) {
     167             :   plumed_assert( val1.derivatives.size()==val2.derivatives.size() );
     168             :   if( valout.derivatives.size()!=val1.derivatives.size() ) valout.resizeDerivatives( val1.derivatives.size() );
     169             :   valout.value_set=false;
     170             :   valout.clearDerivatives();
     171             :   double u=val1.value;
     172             :   double v=val2.value;
     173             :   for(unsigned i=0; i<val1.derivatives.size(); ++i) {
     174             :     valout.addDerivative(i, u*val2.derivatives[i] + v*val1.derivatives[i] );
     175             :   }
     176             :   valout.set( u*v );
     177             : }
     178             : 
     179             : inline
     180             : void quotient( const Value& val1, const Value& val2, Value* valout ) {
     181             :   plumed_assert( val1.derivatives.size()==val2.derivatives.size() );
     182             :   if( valout->derivatives.size()!=val1.derivatives.size() ) valout->resizeDerivatives( val1.derivatives.size() );
     183             :   valout->value_set=false;
     184             :   valout->clearDerivatives();
     185             :   double u=val1.get();
     186             :   double v=val2.get();
     187             :   for(unsigned i=0; i<val1.getNumberOfDerivatives(); ++i) {
     188             :     valout->addDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) );
     189             :   }
     190             :   valout->chainRule( 1/(v*v) ); valout->set( u / v );
     191             : }
     192             : 
     193             : inline
     194             : void Value::set(double v) {
     195    44351760 :   value_set=true;
     196    44351760 :   value=v;
     197    44162997 :   applyPeriodicity();
     198    42537046 : }
     199             : 
     200             : inline
     201             : void Value::add(double v) {
     202             :   value_set=true;
     203             :   value+=v;
     204             :   applyPeriodicity();
     205             : }
     206             : 
     207             : inline
     208             : double Value::get()const {
     209     3224447 :   return value;
     210             : }
     211             : 
     212             : inline
     213             : bool Value::valueHasBeenSet() const {
     214           0 :   return value_set;
     215             : }
     216             : 
     217             : inline
     218             : const std::string& Value::getName()const {
     219     8263808 :   return name;
     220             : }
     221             : 
     222             : inline
     223      329575 : unsigned Value::getNumberOfDerivatives() const {
     224      329575 :   plumed_massert(hasDeriv,"the derivatives array for this value has zero size");
     225      329575 :   return derivatives.size();
     226             : }
     227             : 
     228             : inline
     229             : double Value::getDerivative(const unsigned n) const {
     230             :   plumed_dbg_massert(n<derivatives.size(),"you are asking for a derivative that is out of bounds");
     231    19967312 :   return derivatives[n];
     232             : }
     233             : 
     234             : inline
     235             : bool Value::hasDerivatives() const {
     236       13272 :   return hasDeriv;
     237             : }
     238             : 
     239             : inline
     240             : void Value::resizeDerivatives(int n) {
     241  4102750470 :   if(hasDeriv) derivatives.resize(n);
     242             : }
     243             : 
     244             : inline
     245             : void Value::addDerivative(unsigned i,double d) {
     246             :   plumed_dbg_massert(i<derivatives.size(),"derivative is out of bounds");
     247    22368600 :   derivatives[i]+=d;
     248          10 : }
     249             : 
     250             : inline
     251             : void Value::setDerivative(unsigned i, double d) {
     252             :   plumed_dbg_massert(i<derivatives.size(),"derivative is out of bounds");
     253       63116 :   derivatives[i]=d;
     254             : }
     255             : 
     256             : inline
     257         434 : void Value::chainRule(double df) {
     258       18368 :   for(unsigned i=0; i<derivatives.size(); ++i) derivatives[i]*=df;
     259         434 : }
     260             : 
     261             : inline
     262             : void Value::clearInputForce() {
     263     2081053 :   hasForce=false;
     264     2081053 :   inputForce=0.0;
     265             : }
     266             : 
     267             : inline
     268             : void Value::clearDerivatives() {
     269        2523 :   value_set=false;
     270             :   std::fill(derivatives.begin(), derivatives.end(), 0);
     271             : }
     272             : 
     273             : inline
     274             : void Value::addForce(double f) {
     275             :   plumed_dbg_massert(hasDerivatives(),"forces can only be added to values with derivatives");
     276      188450 :   hasForce=true;
     277      188450 :   inputForce+=f;
     278        2623 : }
     279             : 
     280             : inline
     281             : double Value::getForce() const {
     282        4823 :   return inputForce;
     283             : }
     284             : /// d2-d1
     285             : inline
     286   155957424 : double Value::difference(double d1,double d2)const {
     287   155957424 :   if(periodicity==notperiodic) {
     288    90588656 :     return d2-d1;
     289    65368768 :   } else if(periodicity==periodic) {
     290    65368768 :     double s=(d2-d1)*inv_max_minus_min;
     291             :     // remember: pbc brings the difference in a range of -0.5:0.5
     292    65368768 :     s=Tools::pbc(s);
     293    65368768 :     return s*max_minus_min;
     294           0 :   } else plumed_merror("periodicity should be set to compute differences");
     295             : }
     296             : 
     297             : inline
     298        3173 : double Value::bringBackInPbc(double d1)const {
     299        3173 :   return min+max_minus_min/2.+difference(min+max_minus_min/2., d1);
     300             : }
     301             : 
     302             : inline
     303             : double Value::difference(double d)const {
     304   119526971 :   return difference(get(),d);
     305             : }
     306             : 
     307             : inline
     308             : double Value::getMaxMinusMin()const {
     309             :   plumed_dbg_assert( periodicity==periodic );
     310         518 :   return max_minus_min;
     311             : }
     312             : 
     313             : }
     314             : 
     315             : #endif
     316             : 

Generated by: LCOV version 1.15