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