Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2013-2018 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 158 : 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 : /// Recalculate one of the base quantities
91 : virtual void recalculateStoredQuantity( const unsigned& myelm, MultiValue& myvals );
92 : /// Set a hard cutoff on the weight of an element
93 : void setHardCutoffOnWeight( const double& mytol );
94 : /// Add an action that uses this data
95 : void addActionThatUses( ActionWithVessel* actionThatUses );
96 : /// Return the number of components in the vector
97 1459 : unsigned getNumberOfComponents() const { return vecsize; }
98 : /// Get the values of all the components in the vector
99 : void retrieveSequentialValue( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const ;
100 : void retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector<double>& values ) const ;
101 : double retrieveWeightWithIndex( const unsigned& myelem ) const ;
102 : /// Get the derivatives for one of the components in the vector
103 : virtual void retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals );
104 : /// Do all resizing of data
105 : virtual void resize();
106 : ///
107 84 : virtual std::string description() { return ""; }
108 : /// Get the number of derivatives for the ith value
109 : unsigned getNumberOfDerivatives( const unsigned& );
110 : /// Get the size of the derivative list
111 : unsigned getSizeOfDerivativeList() const ;
112 : /// This stores the data when not using lowmem
113 : virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector<double>& buffer, std::vector<unsigned>& der_index ) const ;
114 : /// Final step in gathering data
115 : virtual void finish( const std::vector<double>& buffer );
116 : /// Is a particular stored value active at the present time
117 : bool storedValueIsActive( const unsigned& iatom ) const ;
118 : /// Set the active values
119 : void setActiveValsAndDerivatives( const std::vector<unsigned>& der_index );
120 : /// Activate indexes (this is used at end of chain rule)
121 0 : virtual void activateIndices( ActionWithVessel* ) {}
122 : /// Forces on vectors should always be applied elsewhere
123 388 : virtual bool applyForce(std::vector<double>&) { return false; }
124 : /// Get the number of data users
125 : unsigned getNumberOfDataUsers() const ;
126 : /// Get one of the ith data user
127 : ActionWithVessel* getDataUser( const unsigned& );
128 : /// Set the number of tempory multivalues we need
129 : void resizeTemporyMultiValues( const unsigned& nvals );
130 : /// Return a tempory multi value - we do this so as to avoid vector resizing
131 : MultiValue& getTemporyMultiValue( const unsigned& ind );
132 : };
133 :
134 : inline
135 : bool StoreDataVessel::weightHasDerivatives() {
136 : return getAction()->weightHasDerivatives;
137 : }
138 :
139 : inline
140 : bool StoreDataVessel::usingLowMem() {
141 : return getAction()->lowmem;
142 : }
143 :
144 : inline
145 : unsigned StoreDataVessel::getNumberOfDerivativeSpacesPerComponent() const {
146 : return nspace;
147 : }
148 :
149 : inline
150 28492 : bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const {
151 28492 : if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false;
152 28492 : unsigned jatom = getStoreIndex( iatom );
153 : plumed_dbg_assert( jatom<getNumberOfStoredValues() );
154 28492 : return local_buffer[jatom*vecsize*nspace]>epsilon;
155 : }
156 :
157 : inline
158 1024 : unsigned StoreDataVessel::getSizeOfDerivativeList() const {
159 1024 : return active_der.size();
160 : }
161 :
162 : inline
163 288494 : unsigned StoreDataVessel::getNumberOfStoredValues() const {
164 288494 : return getAction()->nactive_tasks;
165 : }
166 :
167 : inline
168 1479243 : unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const {
169 1479243 : if( getAction()->nactive_tasks==getAction()->getFullNumberOfTasks() ) return ind;
170 :
171 : // Binary search for required element - faster scaling than sequential search
172 36841 : unsigned l=0, r=getAction()->nactive_tasks-1;
173 332915 : for(unsigned i=0; i<getAction()->nactive_tasks; ++i) {
174 332915 : plumed_assert( l<=r );
175 332915 : unsigned m = std::floor( (l + r)/2 );
176 332915 : if( ind==getAction()->indexOfTaskInFullList[m] ) return m;
177 296074 : else if( getAction()->indexOfTaskInFullList[m]<ind ) l=m+1;
178 146044 : else if( getAction()->indexOfTaskInFullList[m]>ind ) r=m-1;
179 : }
180 0 : plumed_merror("requested task is not active");
181 : }
182 :
183 : inline
184 79002 : void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ) {
185 79002 : getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals );
186 79002 : }
187 :
188 : inline
189 520 : unsigned StoreDataVessel::getNumberOfDataUsers() const {
190 520 : return userActions.size();
191 : }
192 :
193 : inline
194 18 : ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ) {
195 18 : plumed_dbg_assert( idata<userActions.size() ); return userActions[idata];
196 : }
197 :
198 : }
199 : }
200 : #endif
201 :
202 :
|