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