Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2013-2019 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 328 : 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
99 3905 : 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 : virtual void resize();
108 : ///
109 111 : virtual std::string description() { 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 : virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const ;
116 : /// Final step in gathering data
117 : virtual void finish( const std::vector<double>& buffer );
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)
123 0 : virtual void activateIndices( ActionWithVessel* ) {}
124 : /// Forces on vectors should always be applied elsewhere
125 499 : virtual bool applyForce(std::vector<double>&) { 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
137 : bool StoreDataVessel::weightHasDerivatives() {
138 : return getAction()->weightHasDerivatives;
139 : }
140 :
141 : inline
142 : bool StoreDataVessel::usingLowMem() {
143 : return getAction()->lowmem;
144 : }
145 :
146 : inline
147 : unsigned StoreDataVessel::getNumberOfDerivativeSpacesPerComponent() const {
148 : return nspace;
149 : }
150 :
151 : inline
152 57466 : bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const {
153 57466 : if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false;
154 45701 : unsigned jatom = getStoreIndex( iatom );
155 : plumed_dbg_assert( jatom<getNumberOfStoredValues() );
156 91402 : return local_buffer[jatom*vecsize*nspace]>epsilon;
157 : }
158 :
159 : inline
160 : unsigned StoreDataVessel::getSizeOfDerivativeList() const {
161 : return active_der.size();
162 : }
163 :
164 : inline
165 606989 : unsigned StoreDataVessel::getNumberOfStoredValues() const {
166 606989 : return getAction()->nactive_tasks;
167 : }
168 :
169 : inline
170 1540774 : unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const {
171 3081548 : if( getAction()->nactive_tasks==getAction()->getFullNumberOfTasks() ) return ind;
172 :
173 : // Binary search for required element - faster scaling than sequential search
174 64159 : unsigned l=0, r=getAction()->nactive_tasks-1;
175 1328441 : for(unsigned i=0; i<getAction()->nactive_tasks; ++i) {
176 696300 : plumed_assert( l<=r );
177 696300 : unsigned m = std::floor( (l + r)/2 );
178 1392600 : if( ind==getAction()->indexOfTaskInFullList[m] ) return m;
179 632141 : else if( getAction()->indexOfTaskInFullList[m]<ind ) l=m+1;
180 302100 : else if( getAction()->indexOfTaskInFullList[m]>ind ) r=m-1;
181 : }
182 0 : plumed_merror("requested task is not active");
183 : }
184 :
185 : inline
186 : unsigned StoreDataVessel::getTrueIndex( const unsigned& ind ) const {
187 600 : return getAction()->indexOfTaskInFullList[ind];
188 : }
189 :
190 : inline
191 : void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ) {
192 203316 : getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals );
193 : }
194 :
195 : inline
196 : unsigned StoreDataVessel::getNumberOfDataUsers() const {
197 643 : return userActions.size();
198 : }
199 :
200 : inline
201 : ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ) {
202 98 : plumed_dbg_assert( idata<userActions.size() ); return userActions[idata];
203 : }
204 :
205 : }
206 : }
207 : #endif
208 :
209 :
|