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