1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 Copyright (c) 2013-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_vesselbase_StoreDataVessel_h
23 #define __PLUMED_vesselbase_StoreDataVessel_h
24
25 #include <string>
26 #include <cstring>
27 #include <vector>
28 #include "Vessel.h"
29
30 namespace PLMD {
31 namespace vesselbase {
32
33 /**
34 \ingroup TOOLBOX
35 Objects that inherit from FunctionVessel can be used (in tandem with PLMD::vesselbase::ActionWithVessel)
36 to store values and derivatives for a set of scalars or vectors that are calculated by a
37 PLMD::vesselbase::ActionWithVessel. Functions of these stored quantities can then be calculated in a
38 second step.
39 */
40
41 class StoreDataVessel : public Vessel {
42 friend class Moments;
43 private:
44 /// Do the quantities being stored in here need derivatives
45 bool hasderiv;
46 /// What is the maximum number of vectors we are going to
47 /// have to store when using lowmem option
48 unsigned max_lowmem_stash;
49 /// The size of the vector we are computing
50 unsigned vecsize;
51 /// The amount of data per vector element
52 unsigned nspace;
53 /// The currently active values
54 // std::vector<unsigned> active_val;
55 /// The active derivative elements
56 std::vector<unsigned> active_der;
57 /// The buffer
58 std::vector<double> local_buffer;
59 /// The actions that are going to use the stored data
60 std::vector<ActionWithVessel*> userActions;
61 /// We create a vector of tempory MultiValues here so as to avoid
62 /// lots of vector resizing
63 unsigned tmp_index;
64 std::vector<MultiValue> my_tmp_vals;
65 protected:
66 /// Is the weight differentiable
67 bool weightHasDerivatives();
68 /// Are we using low mem option
69 bool usingLowMem();
70 /// Finish the setup of the storage object by setting how much
71 /// data has to be stored
72 void completeSetup( const unsigned&, const unsigned& );
73 /// Return value of nspace
74 unsigned getNumberOfDerivativeSpacesPerComponent() const ;
75 /// Retrieve the values from the underlying ActionWithVessel
76 void storeValues( const unsigned&, MultiValue&, std::vector<double>& ) const ;
77 /// This stores the data we get from the calculation
78 void storeDerivatives( const unsigned&, MultiValue& myvals, std::vector<double>&, std::vector<unsigned>& ) const ;
79 /// Get the ibuf'th local derivative value
80 double getLocalDerivative( const unsigned& ibuf );
81 /// Set the ibuf'th local derivative value
82 void setLocalDerivative( const unsigned& ibuf, const double& val );
83 public:
84 static void registerKeywords( Keywords& keys );
85 explicit StoreDataVessel( const VesselOptions& );
86 /// Get the number of values that have been stored
87 virtual unsigned getNumberOfStoredValues() const ;
88 /// Get the index to store a particular index inside
89 unsigned getStoreIndex( const unsigned& ) const ;
90 /// Get the true index of a quantity from the index it is stored in
91 unsigned getTrueIndex( const unsigned& ) const ;
92 /// Recalculate one of the base quantities
93 void recalculateStoredQuantity( const unsigned& myelm, MultiValue& myvals );
94 /// Set a hard cutoff on the weight of an element
95 void setHardCutoffOnWeight( const double& mytol );
96 /// Add an action that uses this data
97 void addActionThatUses( ActionWithVessel* actionThatUses );
98 /// Return the number of components in the vector
getNumberOfComponents()99 unsigned getNumberOfComponents() const { return vecsize; }
100 /// Get the values of all the components in the vector
101 void retrieveSequentialValue( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const ;
102 void retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const ;
103 double retrieveWeightWithIndex( const unsigned& myelem ) const ;
104 /// Get the derivatives for one of the components in the vector
105 void retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals );
106 /// Do all resizing of data
107 void resize() override;
108 ///
description()109 std::string description() override { return ""; }
110 /// Get the number of derivatives for the ith value
111 unsigned getNumberOfDerivatives( const unsigned& );
112 /// Get the size of the derivative list
113 unsigned getSizeOfDerivativeList() const ;
114 /// This stores the data when not using lowmem
115 void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const override;
116 /// Final step in gathering data
117 void finish( const std::vector<double>& buffer ) override;
118 /// Is a particular stored value active at the present time
119 bool storedValueIsActive( const unsigned& iatom ) const ;
120 /// Set the active values
121 void setActiveValsAndDerivatives( const std::vector<unsigned>& der_index );
122 /// Activate indexes (this is used at end of chain rule)
activateIndices(ActionWithVessel *)123 virtual void activateIndices( ActionWithVessel* ) {}
124 /// Forces on vectors should always be applied elsewhere
applyForce(std::vector<double> &)125 bool applyForce(std::vector<double>&) override { return false; }
126 /// Get the number of data users
127 unsigned getNumberOfDataUsers() const ;
128 /// Get one of the ith data user
129 ActionWithVessel* getDataUser( const unsigned& );
130 /// Set the number of tempory multivalues we need
131 void resizeTemporyMultiValues( const unsigned& nvals );
132 /// Return a tempory multi value - we do this so as to avoid vector resizing
133 MultiValue& getTemporyMultiValue( const unsigned& ind );
134 };
135
136 inline
weightHasDerivatives()137 bool StoreDataVessel::weightHasDerivatives() {
138 return getAction()->weightHasDerivatives;
139 }
140
141 inline
usingLowMem()142 bool StoreDataVessel::usingLowMem() {
143 return getAction()->lowmem;
144 }
145
146 inline
getNumberOfDerivativeSpacesPerComponent()147 unsigned StoreDataVessel::getNumberOfDerivativeSpacesPerComponent() const {
148 return nspace;
149 }
150
151 inline
storedValueIsActive(const unsigned & iatom)152 bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const {
153 if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false;
154 unsigned jatom = getStoreIndex( iatom );
155 plumed_dbg_assert( jatom<getNumberOfStoredValues() );
156 return local_buffer[jatom*vecsize*nspace]>epsilon;
157 }
158
159 inline
getSizeOfDerivativeList()160 unsigned StoreDataVessel::getSizeOfDerivativeList() const {
161 return active_der.size();
162 }
163
164 inline
getNumberOfStoredValues()165 unsigned StoreDataVessel::getNumberOfStoredValues() const {
166 return getAction()->nactive_tasks;
167 }
168
169 inline
getStoreIndex(const unsigned & ind)170 unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const {
171 if( getAction()->nactive_tasks==getAction()->getFullNumberOfTasks() ) return ind;
172
173 // Binary search for required element - faster scaling than sequential search
174 unsigned l=0, r=getAction()->nactive_tasks-1;
175 for(unsigned i=0; i<getAction()->nactive_tasks; ++i) {
176 plumed_assert( l<=r );
177 unsigned m = std::floor( (l + r)/2 );
178 if( ind==getAction()->indexOfTaskInFullList[m] ) return m;
179 else if( getAction()->indexOfTaskInFullList[m]<ind ) l=m+1;
180 else if( getAction()->indexOfTaskInFullList[m]>ind ) r=m-1;
181 }
182 plumed_merror("requested task is not active");
183 }
184
185 inline
getTrueIndex(const unsigned & ind)186 unsigned StoreDataVessel::getTrueIndex( const unsigned& ind ) const {
187 return getAction()->indexOfTaskInFullList[ind];
188 }
189
190 inline
recalculateStoredQuantity(const unsigned & myelem,MultiValue & myvals)191 void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ) {
192 getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals );
193 }
194
195 inline
getNumberOfDataUsers()196 unsigned StoreDataVessel::getNumberOfDataUsers() const {
197 return userActions.size();
198 }
199
200 inline
getDataUser(const unsigned & idata)201 ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ) {
202 plumed_dbg_assert( idata<userActions.size() ); return userActions[idata];
203 }
204
205 }
206 }
207 #endif
208
209
210