Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-2020 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 367 : 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 3287 : 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 128 : 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 957 : 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 65536 : bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const { 153 65536 : if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false; 154 53771 : unsigned jatom = getStoreIndex( iatom ); 155 : plumed_dbg_assert( jatom<getNumberOfStoredValues() ); 156 107542 : 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 632109 : unsigned StoreDataVessel::getNumberOfStoredValues() const { 166 632109 : return getAction()->nactive_tasks; 167 : } 168 : 169 : inline 170 1557046 : unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const { 171 3114092 : 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 203356 : getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals ); 193 : } 194 : 195 : inline 196 : unsigned StoreDataVessel::getNumberOfDataUsers() const { 197 225 : 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 :