1 #pragma once 2 3 #include "objects/containers/FlatMap.h" 4 #include "objects/utility/Dynamic.h" 5 #include "system/Settings.h" 6 7 NAMESPACE_SPH_BEGIN 8 9 class Storage; 10 enum class QuantityId; 11 12 /// \brief Object holding information about single particle 13 /// 14 /// Particle can store all or some quantities of given particle. Unlike in \ref Storage, the \ref Particle 15 /// does not hold information about orders of the stored quantities, and it is possible to store derivatives 16 /// of quantities without having quantity values stored as well. 17 class Particle { 18 friend struct ParticleVisitor; 19 20 private: 21 Size idx; 22 23 struct InternalQuantityData { 24 Dynamic value; 25 Dynamic dt; 26 Dynamic d2t; 27 }; 28 29 FlatMap<QuantityId, InternalQuantityData> quantities; 30 31 FlatMap<BodySettingsId, Dynamic> material; 32 33 public: 34 /// \brief Default constructor, defined only for convenient usage in containers, etc. 35 /// 36 /// Particle has to be initialized using copy/move operator. 37 Particle() = default; 38 39 /// \brief Constructs object given its index in parent storage, containing no particle data. 40 /// 41 /// Quantity data can be added using functions \ref addValue, \ref addDt and \ref addD2t. Particle(const Size idx)42 explicit Particle(const Size idx) 43 : idx(idx) {} 44 45 /// \brief Constructs the object from storage, storing values of all quantities for given particle 46 /// 47 /// \param storage Storage containing the particle 48 /// \param idx Index of the particle 49 Particle(const Storage& storage, const Size idx); 50 51 /// \brief Constructs a particle with information about a single quantity value. 52 /// 53 /// Other quantity data can be added using functions \ref addValue, \ref addDt and \ref addD2t. 54 /// \param id Quantity ID of the quantity value 55 /// \param value Quantity value. Cannot be used to add derivatives. 56 /// \param idx Index of particle; although this constructor is not necessarily bound to a particle 57 /// storage, this represents index to storage associated with the particle. 58 Particle(const QuantityId id, const Dynamic& value, const Size idx); 59 60 Particle(const Particle& other); 61 62 Particle(Particle&& other); 63 64 Particle& operator=(const Particle& other); 65 66 Particle& operator=(Particle&& other); 67 68 /// \brief Adds another quantity value or updates the value of quantity previously stored. 69 /// 70 /// \param id Quantity ID of the quantity value 71 /// \param value New value of given quantity 72 /// \return Reference to itself, allowing to queue functions 73 Particle& addValue(const QuantityId id, const Dynamic& value); 74 75 /// \brief Adds another quantity derivative or updates the derivative of quantity previously stored. 76 /// 77 /// \param id Quantity ID of the quantity value 78 /// \param value New derivative of given quantity 79 /// \return Reference to itself, allowing to queue functions 80 Particle& addDt(const QuantityId id, const Dynamic& value); 81 82 /// \brief Adds another quantity 2nd derivative or updates the 2nd derivative of quantity previously 83 /// stored. 84 /// 85 /// \param id Quantity ID of the quantity value 86 /// \param value New 2nd derivative of given quantity 87 /// \return Reference to itself, allowing to queue functions 88 Particle& addD2t(const QuantityId id, const Dynamic& value); 89 90 /// \brief Adds another material parameter or updates the one stored previously. 91 /// 92 /// \param id ID of the material parameter 93 /// \param value Value of the material parameter 94 Particle& addParameter(const BodySettingsId id, const Dynamic& value); 95 96 /// \brief Returns the index of particle in the parent storage. getIndex()97 INLINE Size getIndex() const { 98 return idx; 99 } 100 101 /// \brief Retrieves a quantity value of the particle. 102 /// 103 /// If the particle doesn't hold value of quantity with given ID, returns unitialized (empty) value. 104 Dynamic getValue(const QuantityId id) const; 105 106 /// \brief Retrieves a quantity derivative of the particle. 107 /// 108 /// If the particle doesn't hold derivative of quantity with given ID, returns unitialized (empty) value. 109 Dynamic getDt(const QuantityId id) const; 110 111 /// \brief Retrieves a quantity 2nd derivative of the particle. 112 /// 113 /// If the particle doesn't hold 2nd derivative of quantity with given ID, returns unitialized (empty) 114 /// value. 115 Dynamic getD2t(const QuantityId id) const; 116 117 /// \brief Retrieves a material parameter of the particle. 118 /// 119 /// If the particle doesn't hold the parameter with given ID, returns unitialized (empty) value. 120 Dynamic getParameter(const BodySettingsId id) const; 121 122 /// \brief Stored info about a quantity. 123 /// 124 /// Note that not all values have to be initialized; if they are, however, all values have the same type. 125 struct QuantityData { 126 127 /// Quantity ID 128 QuantityId id; 129 130 /// Value type of the quantity 131 DynamicId type; 132 133 /// Quantity value 134 Dynamic value; 135 136 /// First derivative of the quantity 137 Dynamic dt; 138 139 /// Second derivative of the quantity 140 Dynamic d2t; 141 }; 142 143 /// \brief Iterator used to enumerate all stored quantities. 144 class QuantityIterator { 145 private: 146 using ActIterator = Iterator<const FlatMap<QuantityId, InternalQuantityData>::Element>; 147 148 ActIterator iter; 149 150 public: 151 /// \brief Constructs the iterator from internal type. 152 /// 153 /// Cannot be constructed directly, use \ref Particle::getQuantities instead. 154 QuantityIterator(const ActIterator iterator, Badge<Particle>); 155 156 /// Advances the iterator to next quantity. 157 QuantityIterator& operator++(); 158 159 /// Returns all data associated with currently referenced quantity. 160 QuantityData operator*() const; 161 162 /// Inequality operator 163 bool operator!=(const QuantityIterator& other) const; 164 }; 165 166 /// \brief Helper for enumerating all stored quantities. 167 class QuantitySequence { 168 private: 169 QuantityIterator first; 170 QuantityIterator last; 171 172 public: 173 /// \brief Creates a sequence of all quantities of given particle. 174 QuantitySequence(const Particle& particle); 175 176 /// \brief Returns iterator pointing to the first quantity. 177 QuantityIterator begin() const; 178 179 /// \brief Returns iterator pointing to the one-past-last quantity. 180 QuantityIterator end() const; 181 }; 182 183 /// \brief Returns a range for enumerating all stored quantities. 184 QuantitySequence getQuantities() const; 185 186 /// \brief Stored info about a material parameter. 187 struct ParamData { 188 189 /// Material parameter ID 190 BodySettingsId id; 191 192 /// Parameter value 193 Dynamic value; 194 }; 195 196 class ParamIterator { 197 private: 198 using ActIterator = Iterator<const FlatMap<BodySettingsId, Dynamic>::Element>; 199 200 ActIterator iter; 201 202 public: 203 /// \brief Constructs the iterator from internal type. 204 /// 205 /// Cannot be constructed directly, use \ref Particle::getParameters instead. 206 ParamIterator(const ActIterator iterator, Badge<Particle>); 207 208 /// Advances the iterator to next quantity. 209 ParamIterator& operator++(); 210 211 /// Returns all data associated with currently referenced parameter. 212 ParamData operator*() const; 213 214 /// Inequality operator 215 bool operator!=(const ParamIterator& other) const; 216 }; 217 218 /// \brief Helper for enumerating all stored parameters. 219 class ParamSequence { 220 private: 221 ParamIterator first; 222 ParamIterator last; 223 224 public: 225 /// \brief Creates a sequence of all material parameters of given particle. 226 ParamSequence(const Particle& particle); 227 228 /// \brief Returns iterator pointing to the first parameter. 229 ParamIterator begin() const; 230 231 /// \brief Returns iterator pointing to the one-past-last parameter. 232 ParamIterator end() const; 233 }; 234 235 /// \brief Returns a range for enumerating all stored parameters. 236 ParamSequence getParameters() const; 237 }; 238 239 NAMESPACE_SPH_END 240