1 #include "quantities/Particle.h"
2 #include "quantities/Quantity.h"
3 #include "quantities/Storage.h"
4 
5 NAMESPACE_SPH_BEGIN
6 
7 struct ParticleVisitor {
8     FlatMap<QuantityId, Particle::InternalQuantityData>& data;
9 
10     template <typename TValue>
visitParticleVisitor11     void visit(const QuantityId id, const Quantity& q, const Size idx) {
12         const auto& values = q.getAll<TValue>();
13         switch (q.getOrderEnum()) {
14         case OrderEnum::SECOND:
15             data[id].d2t = values[2][idx];
16             SPH_FALLTHROUGH
17         case OrderEnum::FIRST:
18             data[id].dt = values[1][idx];
19             SPH_FALLTHROUGH
20         case OrderEnum::ZERO:
21             data[id].value = values[0][idx];
22             break;
23         default:
24             NOT_IMPLEMENTED;
25         }
26     }
27 };
28 
29 
Particle(const Storage & storage,const Size idx)30 Particle::Particle(const Storage& storage, const Size idx)
31     : idx(idx) {
32     for (ConstStorageElement i : storage.getQuantities()) {
33         quantities.insert(i.id, InternalQuantityData{});
34 
35         ParticleVisitor visitor{ quantities };
36         dispatch(i.quantity.getValueEnum(), visitor, i.id, i.quantity, idx);
37     }
38 }
39 
Particle(const QuantityId id,const Dynamic & value,const Size idx)40 Particle::Particle(const QuantityId id, const Dynamic& value, const Size idx)
41     : idx(idx) {
42     quantities.insert(id, InternalQuantityData{});
43     quantities[id].value = value;
44 }
45 
Particle(const Particle & other)46 Particle::Particle(const Particle& other) {
47     *this = other;
48 }
49 
Particle(Particle && other)50 Particle::Particle(Particle&& other) {
51     *this = std::move(other);
52 }
53 
operator =(const Particle & other)54 Particle& Particle::operator=(const Particle& other) {
55     quantities = other.quantities.clone();
56     material = other.material.clone();
57     idx = other.idx;
58     return *this;
59 }
60 
operator =(Particle && other)61 Particle& Particle::operator=(Particle&& other) {
62     quantities = std::move(other.quantities);
63     material = std::move(other.material);
64     idx = other.idx;
65     return *this;
66 }
67 
addValue(const QuantityId id,const Dynamic & value)68 Particle& Particle::addValue(const QuantityId id, const Dynamic& value) {
69     if (!quantities.contains(id)) {
70         quantities.insert(id, InternalQuantityData{});
71     }
72     quantities[id].value = value;
73     return *this;
74 }
75 
addDt(const QuantityId id,const Dynamic & value)76 Particle& Particle::addDt(const QuantityId id, const Dynamic& value) {
77     if (!quantities.contains(id)) {
78         quantities.insert(id, InternalQuantityData{});
79     }
80     quantities[id].dt = value;
81     return *this;
82 }
83 
addD2t(const QuantityId id,const Dynamic & value)84 Particle& Particle::addD2t(const QuantityId id, const Dynamic& value) {
85     if (!quantities.contains(id)) {
86         quantities.insert(id, InternalQuantityData{});
87     }
88     quantities[id].d2t = value;
89     return *this;
90 }
91 
addParameter(const BodySettingsId id,const Dynamic & value)92 Particle& Particle::addParameter(const BodySettingsId id, const Dynamic& value) {
93     if (!material.contains(id)) {
94         material.insert(id, NOTHING);
95     }
96     material[id] = value;
97     return *this;
98 }
99 
100 
getValue(const QuantityId id) const101 Dynamic Particle::getValue(const QuantityId id) const {
102     Optional<const InternalQuantityData&> quantity = quantities.tryGet(id);
103     SPH_ASSERT(quantity);
104     return quantity->value;
105 }
106 
getDt(const QuantityId id) const107 Dynamic Particle::getDt(const QuantityId id) const {
108     Optional<const InternalQuantityData&> quantity = quantities.tryGet(id);
109     SPH_ASSERT(quantity);
110     return quantity->dt;
111 }
112 
getD2t(const QuantityId id) const113 Dynamic Particle::getD2t(const QuantityId id) const {
114     Optional<const InternalQuantityData&> quantity = quantities.tryGet(id);
115     SPH_ASSERT(quantity);
116     return quantity->d2t;
117 }
118 
getParameter(const BodySettingsId id) const119 Dynamic Particle::getParameter(const BodySettingsId id) const {
120     Optional<const Dynamic&> value = material.tryGet(id);
121     SPH_ASSERT(value);
122     return value.value();
123 }
124 
125 
QuantityIterator(const ActIterator iterator,Badge<Particle>)126 Particle::QuantityIterator::QuantityIterator(const ActIterator iterator, Badge<Particle>)
127     : iter(iterator) {}
128 
operator ++()129 Particle::QuantityIterator& Particle::QuantityIterator::operator++() {
130     ++iter;
131     return *this;
132 }
133 
operator *() const134 Particle::QuantityData Particle::QuantityIterator::operator*() const {
135     const InternalQuantityData& internal = iter->value();
136     DynamicId type;
137     if (internal.value) {
138         type = internal.value.getType();
139         SPH_ASSERT(internal.dt.empty() || internal.dt.getType() == type);
140         SPH_ASSERT(internal.d2t.empty() || internal.d2t.getType() == type);
141     } else if (internal.dt) {
142         type = internal.dt.getType();
143         SPH_ASSERT(internal.d2t.empty() || internal.d2t.getType() == type);
144     } else {
145         SPH_ASSERT(internal.d2t);
146         type = internal.d2t.getType();
147     }
148     return { iter->key(), type, internal.value, internal.dt, internal.d2t };
149 }
150 
operator !=(const QuantityIterator & other) const151 bool Particle::QuantityIterator::operator!=(const QuantityIterator& other) const {
152     return iter != other.iter;
153 }
154 
QuantitySequence(const Particle & particle)155 Particle::QuantitySequence::QuantitySequence(const Particle& particle)
156     : first(particle.quantities.begin(), {})
157     , last(particle.quantities.end(), {}) {}
158 
begin() const159 Particle::QuantityIterator Particle::QuantitySequence::begin() const {
160     return first;
161 }
162 
end() const163 Particle::QuantityIterator Particle::QuantitySequence::end() const {
164     return last;
165 }
166 
getQuantities() const167 Particle::QuantitySequence Particle::getQuantities() const {
168     return QuantitySequence(*this);
169 }
170 
171 
ParamIterator(const ActIterator iterator,Badge<Particle>)172 Particle::ParamIterator::ParamIterator(const ActIterator iterator, Badge<Particle>)
173     : iter(iterator) {}
174 
operator ++()175 Particle::ParamIterator& Particle::ParamIterator::operator++() {
176     ++iter;
177     return *this;
178 }
179 
operator *() const180 Particle::ParamData Particle::ParamIterator::operator*() const {
181     return { iter->key(), iter->value() };
182 }
183 
operator !=(const ParamIterator & other) const184 bool Particle::ParamIterator::operator!=(const ParamIterator& other) const {
185     return iter != other.iter;
186 }
187 
188 
ParamSequence(const Particle & particle)189 Particle::ParamSequence::ParamSequence(const Particle& particle)
190     : first(particle.material.begin(), {})
191     , last(particle.material.end(), {}) {}
192 
begin() const193 Particle::ParamIterator Particle::ParamSequence::begin() const {
194     return first;
195 }
196 
end() const197 Particle::ParamIterator Particle::ParamSequence::end() const {
198     return last;
199 }
200 
getParameters() const201 Particle::ParamSequence Particle::getParameters() const {
202     return ParamSequence(*this);
203 }
204 
205 NAMESPACE_SPH_END
206