1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2    Copyright (c) 2014-2021 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_tools_MultiValue_h
23 #define __PLUMED_tools_MultiValue_h
24 
25 #include <vector>
26 #include "Exception.h"
27 #include "DynamicList.h"
28 
29 namespace PLMD {
30 
31 class MultiValue {
32 private:
33 /// Used to ensure rapid accumulation of derivatives
34   DynamicList<unsigned> hasDerivatives;
35 /// Values of quantities
36   std::vector<double> values;
37 /// Number of derivatives per value
38   unsigned nderivatives;
39 /// Derivatives
40   std::vector<double> derivatives;
41 /// Tempory value
42   double tmpval;
43 /// Tempory vector of derivatives (used for calculating quotients
44   std::vector<double> tmpder;
45 /// Logical to check if any derivatives were set
46   bool atLeastOneSet;
47 /// This is a fudge to save on vector resizing in MultiColvar
48   std::vector<unsigned> indices, sort_indices;
49   std::vector<Vector> tmp_atoms;
50 public:
51   MultiValue( const unsigned&, const unsigned& );
52   void resize( const unsigned&, const unsigned& );
53 ///
54   std::vector<unsigned>& getIndices();
55   std::vector<unsigned>& getSortIndices();
56   std::vector<Vector>& getAtomVector();
57 /// Get the number of values in the stash
58   unsigned getNumberOfValues() const ;
59 /// Get the number of derivatives in the stash
60   unsigned getNumberOfDerivatives() const ;
61 /// Set value numbered
62   void setValue( const unsigned&,  const double& );
63 /// Add value numbered
64   void addValue( const unsigned&,  const double& );
65 /// Add derivative
66   void addDerivative( const unsigned&, const unsigned&, const double& );
67 /// Add to the tempory value
68   void addTemporyValue( const double& val );
69 /// Add tempory derivatives - this is used for calculating quotients
70   void addTemporyDerivative( const unsigned& jder, const double& der );
71 /// Set the value of the derivative
72   void setDerivative( const unsigned& ival, const unsigned& jder, const double& der);
73 /// Return the ith value
74   double get( const unsigned& ) const ;
75 /// Return a derivative value
76   double getDerivative( const unsigned&, const unsigned& ) const ;
77 /// Get one of the tempory derivatives
78   double getTemporyDerivative( const unsigned& jder ) const ;
79 /// Clear all values
80   void clearAll();
81 /// Clear the tempory derivatives
82   void clearTemporyDerivatives();
83 /// Clear a value
84   void clear( const unsigned& );
85 /// Functions for accessing active list
86   bool updateComplete();
87   void emptyActiveMembers();
88   void putIndexInActiveArray( const unsigned & );
89   void updateIndex( const unsigned& );
90   void sortActiveList();
91   void completeUpdate();
92   void updateDynamicList();
93   bool isActive( const unsigned& ind ) const ;
94 ///
95   unsigned getNumberActive() const ;
96 ///
97   unsigned getActiveIndex( const unsigned& ) const ;
98 /// Transfer derivatives to buffer
99   void chainRule( const unsigned&, const unsigned&, const unsigned&, const unsigned&, const double&, const unsigned&, std::vector<double>& buffer );
100 ///
101   void copyValues( MultiValue& ) const ;
102 ///
103   void copyDerivatives( MultiValue& );
104 ///
105   void quotientRule( const unsigned& nder, const unsigned& oder );
106 };
107 
108 inline
getNumberOfValues()109 unsigned MultiValue::getNumberOfValues() const {
110   return values.size();
111 }
112 
113 inline
getNumberOfDerivatives()114 unsigned MultiValue::getNumberOfDerivatives() const {
115   return nderivatives; //derivatives.ncols();
116 }
117 
118 inline
get(const unsigned & ival)119 double MultiValue::get( const unsigned& ival ) const {
120   plumed_dbg_assert( ival<=values.size() );
121   return values[ival];
122 }
123 
124 inline
setValue(const unsigned & ival,const double & val)125 void MultiValue::setValue( const unsigned& ival,  const double& val) {
126   plumed_dbg_assert( ival<=values.size() );
127   values[ival]=val;
128 }
129 
130 inline
addValue(const unsigned & ival,const double & val)131 void MultiValue::addValue( const unsigned& ival,  const double& val) {
132   plumed_dbg_assert( ival<=values.size() );
133   values[ival]+=val;
134 }
135 
136 inline
addDerivative(const unsigned & ival,const unsigned & jder,const double & der)137 void MultiValue::addDerivative( const unsigned& ival, const unsigned& jder, const double& der) {
138   plumed_dbg_assert( ival<=values.size() && jder<nderivatives ); atLeastOneSet=true;
139   hasDerivatives.activate(jder); derivatives[nderivatives*ival+jder] += der;
140 }
141 
142 inline
addTemporyValue(const double & val)143 void MultiValue::addTemporyValue( const double& val ) {
144   tmpval += val;
145 }
146 
147 inline
addTemporyDerivative(const unsigned & jder,const double & der)148 void MultiValue::addTemporyDerivative( const unsigned& jder, const double& der ) {
149   plumed_dbg_assert( jder<nderivatives ); atLeastOneSet=true;
150   hasDerivatives.activate(jder); tmpder[jder] += der;
151 }
152 
153 
154 inline
setDerivative(const unsigned & ival,const unsigned & jder,const double & der)155 void MultiValue::setDerivative( const unsigned& ival, const unsigned& jder, const double& der) {
156   plumed_dbg_assert( ival<=values.size() && jder<nderivatives ); atLeastOneSet=true;
157   hasDerivatives.activate(jder); derivatives[nderivatives*ival+jder]=der;
158 }
159 
160 
161 inline
getDerivative(const unsigned & ival,const unsigned & jder)162 double MultiValue::getDerivative( const unsigned& ival, const unsigned& jder ) const {
163   plumed_dbg_assert( jder<nderivatives && hasDerivatives.isActive(jder) );
164   return derivatives[nderivatives*ival+jder];
165 }
166 
167 inline
getTemporyDerivative(const unsigned & jder)168 double MultiValue::getTemporyDerivative( const unsigned& jder ) const {
169   plumed_dbg_assert( jder<nderivatives && hasDerivatives.isActive(jder) );
170   return tmpder[jder];
171 }
172 
173 inline
updateComplete()174 bool MultiValue::updateComplete() {
175   return hasDerivatives.updateComplete();
176 }
177 
178 inline
emptyActiveMembers()179 void MultiValue::emptyActiveMembers() {
180   hasDerivatives.emptyActiveMembers();
181 }
182 
183 inline
putIndexInActiveArray(const unsigned & ind)184 void MultiValue::putIndexInActiveArray( const unsigned& ind ) {
185   hasDerivatives.putIndexInActiveArray( ind );
186 }
187 
188 inline
updateIndex(const unsigned & ind)189 void MultiValue::updateIndex( const unsigned& ind ) {
190   if( hasDerivatives.isActive(ind) ) hasDerivatives.putIndexInActiveArray( ind );
191 }
192 
193 inline
sortActiveList()194 void MultiValue::sortActiveList() {
195   hasDerivatives.sortActiveList();
196 }
197 
198 inline
completeUpdate()199 void MultiValue::completeUpdate() {
200   hasDerivatives.completeUpdate();
201 }
202 
203 inline
getNumberActive()204 unsigned MultiValue::getNumberActive() const {
205   return hasDerivatives.getNumberActive();
206 }
207 
208 inline
getActiveIndex(const unsigned & ind)209 unsigned MultiValue::getActiveIndex( const unsigned& ind ) const {
210   plumed_dbg_assert( ind<hasDerivatives.getNumberActive() );
211   return hasDerivatives[ind];
212 }
213 
214 inline
updateDynamicList()215 void MultiValue::updateDynamicList() {
216   if( atLeastOneSet ) hasDerivatives.updateActiveMembers();
217 }
218 
219 inline
getIndices()220 std::vector<unsigned>& MultiValue::getIndices() {
221   return indices;
222 }
223 
224 inline
getSortIndices()225 std::vector<unsigned>& MultiValue::getSortIndices() {
226   return sort_indices;
227 }
228 
229 inline
getAtomVector()230 std::vector<Vector>& MultiValue::getAtomVector() {
231   return tmp_atoms;
232 }
233 
234 inline
isActive(const unsigned & ind)235 bool MultiValue::isActive( const unsigned& ind ) const {
236   return hasDerivatives.isActive( ind );
237 }
238 
239 }
240 #endif
241