LCOV - code coverage report
Current view: top level - core - Value.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 44 46 95.7 %
Date: 2026-03-30 13:16:06 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    44392773 : void Value::applyPeriodicity() {
     159    44392773 :   if(periodicity==periodic) {
     160    30707608 :     value=min+difference(min,value);
     161    30707608 :     if(value<min) {
     162    14872392 :       value+=max_minus_min;
     163             :     }
     164             :   }
     165    44392773 : }
     166             : 
     167             : inline
     168             : void product( const Value& val1, const Value& val2, Value& valout ) {
     169             :   plumed_assert( val1.derivatives.size()==val2.derivatives.size() );
     170             :   if( valout.derivatives.size()!=val1.derivatives.size() ) {
     171             :     valout.resizeDerivatives( val1.derivatives.size() );
     172             :   }
     173             :   valout.value_set=false;
     174             :   valout.clearDerivatives();
     175             :   double u=val1.value;
     176             :   double v=val2.value;
     177             :   for(unsigned i=0; i<val1.derivatives.size(); ++i) {
     178             :     valout.addDerivative(i, u*val2.derivatives[i] + v*val1.derivatives[i] );
     179             :   }
     180             :   valout.set( u*v );
     181             : }
     182             : 
     183             : inline
     184             : void quotient( const Value& val1, const Value& val2, Value* valout ) {
     185             :   plumed_assert( val1.derivatives.size()==val2.derivatives.size() );
     186             :   if( valout->derivatives.size()!=val1.derivatives.size() ) {
     187             :     valout->resizeDerivatives( val1.derivatives.size() );
     188             :   }
     189             :   valout->value_set=false;
     190             :   valout->clearDerivatives();
     191             :   double u=val1.get();
     192             :   double v=val2.get();
     193             :   for(unsigned i=0; i<val1.getNumberOfDerivatives(); ++i) {
     194             :     valout->addDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) );
     195             :   }
     196             :   valout->chainRule( 1/(v*v) );
     197             :   valout->set( u / v );
     198             : }
     199             : 
     200             : inline
     201             : void Value::set(double v) {
     202    44381919 :   value_set=true;
     203    44381919 :   value=v;
     204    44192936 :   applyPeriodicity();
     205    42557058 : }
     206             : 
     207             : inline
     208             : void Value::add(double v) {
     209             :   value_set=true;
     210             :   value+=v;
     211             :   applyPeriodicity();
     212             : }
     213             : 
     214             : inline
     215             : double Value::get()const {
     216     3248012 :   return value;
     217             : }
     218             : 
     219             : inline
     220             : bool Value::valueHasBeenSet() const {
     221           0 :   return value_set;
     222             : }
     223             : 
     224             : inline
     225             : const std::string& Value::getName()const {
     226     8676977 :   return name;
     227             : }
     228             : 
     229             : inline
     230      378648 : unsigned Value::getNumberOfDerivatives() const {
     231      378648 :   plumed_massert(hasDeriv,"the derivatives array for this value has zero size");
     232      378648 :   return derivatives.size();
     233             : }
     234             : 
     235             : inline
     236             : double Value::getDerivative(const unsigned n) const {
     237             :   plumed_dbg_massert(n<derivatives.size(),"you are asking for a derivative that is out of bounds");
     238    20376386 :   return derivatives[n];
     239             : }
     240             : 
     241             : inline
     242             : bool Value::hasDerivatives() const {
     243       13276 :   return hasDeriv;
     244             : }
     245             : 
     246             : inline
     247             : void Value::resizeDerivatives(int n) {
     248  4102753188 :   if(hasDeriv) {
     249  2053106339 :     derivatives.resize(n);
     250             :   }
     251             : }
     252             : 
     253             : inline
     254             : void Value::addDerivative(unsigned i,double d) {
     255             :   plumed_dbg_massert(i<derivatives.size(),"derivative is out of bounds");
     256    23202491 :   derivatives[i]+=d;
     257          10 : }
     258             : 
     259             : inline
     260             : void Value::setDerivative(unsigned i, double d) {
     261             :   plumed_dbg_massert(i<derivatives.size(),"derivative is out of bounds");
     262       63116 :   derivatives[i]=d;
     263             : }
     264             : 
     265             : inline
     266         434 : void Value::chainRule(double df) {
     267       18368 :   for(unsigned i=0; i<derivatives.size(); ++i) {
     268       17934 :     derivatives[i]*=df;
     269             :   }
     270         434 : }
     271             : 
     272             : inline
     273             : void Value::clearInputForce() {
     274     2104624 :   hasForce=false;
     275     2104624 :   inputForce=0.0;
     276             : }
     277             : 
     278             : inline
     279             : void Value::clearDerivatives() {
     280        2523 :   value_set=false;
     281             :   std::fill(derivatives.begin(), derivatives.end(), 0);
     282             : }
     283             : 
     284             : inline
     285             : void Value::addForce(double f) {
     286             :   plumed_dbg_massert(hasDerivatives(),"forces can only be added to values with derivatives");
     287      194130 :   hasForce=true;
     288      194130 :   inputForce+=f;
     289        2623 : }
     290             : 
     291             : inline
     292             : double Value::getForce() const {
     293        4985 :   return inputForce;
     294             : }
     295             : /// d2-d1
     296             : inline
     297   155961574 : double Value::difference(double d1,double d2)const {
     298   155961574 :   if(periodicity==notperiodic) {
     299    90591338 :     return d2-d1;
     300    65370236 :   } else if(periodicity==periodic) {
     301    65370236 :     double s=(d2-d1)*inv_max_minus_min;
     302             :     // remember: pbc brings the difference in a range of -0.5:0.5
     303    65370236 :     s=Tools::pbc(s);
     304    65370236 :     return s*max_minus_min;
     305             :   } else {
     306           0 :     plumed_merror("periodicity should be set to compute differences");
     307             :   }
     308             : }
     309             : 
     310             : inline
     311        3173 : double Value::bringBackInPbc(double d1)const {
     312        3173 :   return min+max_minus_min/2.+difference(min+max_minus_min/2., d1);
     313             : }
     314             : 
     315             : inline
     316             : double Value::difference(double d)const {
     317   119526971 :   return difference(get(),d);
     318             : }
     319             : 
     320             : inline
     321             : double Value::getMaxMinusMin()const {
     322             :   plumed_dbg_assert( periodicity==periodic );
     323         518 :   return max_minus_min;
     324             : }
     325             : 
     326             : }
     327             : 
     328             : #endif
     329             : 

Generated by: LCOV version 1.16