MaMiCo 1.2
Loading...
Searching...
No Matches
Datastructures.h
1// This file is part of the Mamico project. For conditions of distribution
2// and use, please see the copyright notice in Mamico's main folder
3
4#pragma once
5
6#include <memory>
7
8namespace coupling {
9
14namespace filtering {
15
16/***
17 * Quantities<dim>[0] := mass
18 * Quantities<dim>[1..dim] := momentum
19 */
20template <unsigned int dim> using Quantities = tarch::la::Vector<dim + 1, double>;
21
22/***
23 * Spacetime window of data, i.e. 4D field of T
24 */
25template <unsigned int dim, typename T> class Field;
26
27/***
28 * Spacetime window of flow quantities
29 */
30template <unsigned int dim> using Flowfield = Field<dim, Quantities<dim>>;
31
32/***
33 * includes local flowfield, and mean and standard deviation of quantities
34 */
35template <unsigned int dim> class Patch;
36
37/***
38 * similar to patch, but
39 * does not store local flowfield, but accesses basefield for distance
40 * computation
41 */
42template <unsigned int dim> class PatchView;
43
44/***
45 * Spacetime window of patches
46 */
47template <unsigned int dim> using Patchfield = Field<dim, Patch<dim>>;
48// using Patchfield = Field<dim, PatchView<dim>>;
49
50} // namespace filtering
51} // namespace coupling
52
53/***
54 * Spacetime window of data, i.e. 4D field of T
55 */
56template <unsigned int dim, typename T> class coupling::filtering::Field {
57public:
58 Field(const tarch::la::Vector<dim, unsigned int>& spatialSize, const unsigned int& temporalSize)
59 : _spatialSize(spatialSize), _temporalSize(temporalSize), _scalarSize(computeScalarSize(spatialSize, temporalSize)),
60 _data(std::allocator_traits<std::allocator<T>>::allocate(allo, _scalarSize)) {}
61
62 template <class... Args> void construct(const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t, Args&&... args) {
63 std::allocator_traits<std::allocator<T>>::construct(allo, _data + idx(pos, t), std::forward<Args>(args)...);
64 }
65
66 void destroy(const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t) {
67 std::allocator_traits<std::allocator<T>>::destroy(allo, _data + idx(pos, t));
68 }
69
70 T& operator()(const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t) { return _data[idx(pos, t)]; }
71
72 const T& operator()(const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t) const { return _data[idx(pos, t)]; }
73
74 T& operator[](unsigned int pos) {
75#ifdef NLM_DEBUG
76 if (pos < 0 || pos > _scalarSize - 1) {
77 std::cout << "ERROR Field T& operator[](int pos): pos out of range!" << std::endl;
78 std::cout << "pos=" << pos << ", _scalarSize=" << _scalarSize << std::endl;
79 exit(EXIT_FAILURE);
80 }
81#endif
82 return _data[pos];
83 }
84
85 const T& operator[](unsigned int pos) const {
86#ifdef NLM_DEBUG
87 if (pos < 0 || pos > _scalarSize - 1) {
88 std::cout << "ERROR Field T& operator[](int pos): pos out of range!" << std::endl;
89 std::cout << "pos=" << pos << ", _scalarSize=" << _scalarSize << std::endl;
90 exit(EXIT_FAILURE);
91 }
92#endif
93 return _data[pos];
94 }
95
96 ~Field() { std::allocator_traits<std::allocator<T>>::deallocate(allo, _data, _scalarSize); }
97
98 unsigned int getScalarSize() const { return _scalarSize; }
99
100 const tarch::la::Vector<dim, unsigned int>& getSpatialSize() const { return _spatialSize; }
101
102 unsigned int getTemporalSize() const { return _temporalSize; }
103
104 void print() {
105 for (unsigned int i = 0; i < _scalarSize; i++) {
106 std::cout << "Field elem " << i << " = " << _data[i] << std::endl;
107 }
108 }
109
110private:
111 unsigned int computeScalarSize(const tarch::la::Vector<dim, unsigned int>& spatialSize, const unsigned int& temporalSize) const {
112 unsigned int res = spatialSize[0];
113 for (unsigned int d = 1; d < dim; d++) {
114 res *= (spatialSize[d]);
115 }
116 res *= temporalSize;
117 return res;
118 }
119
120 unsigned int idx(const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t) const {
121#ifdef NLM_DEBUG
122 for (unsigned int d = 0; d < dim; d++) {
123 if (pos[d] < 0 || pos[d] > _spatialSize[d] - 1) {
124 std::cout << "ERROR Field idx(): pos out of range!" << std::endl;
125 std::cout << "pos=" << pos << ", _spatialSize=" << _spatialSize << std::endl;
126 exit(EXIT_FAILURE);
127 }
128 }
129 if (t < 0 || t > _temporalSize - 1) {
130 std::cout << "ERROR Field idx(): t out of range!" << std::endl;
131 std::cout << "t=" << t << ", _temporalSize=" << _temporalSize << std::endl;
132 exit(EXIT_FAILURE);
133 }
134#endif
135 unsigned int idx = 0, step = 1;
136 for (unsigned int d = 0; d < dim; d++) {
137 idx += pos[d] * step;
138 step *= _spatialSize[d];
139 }
140 idx += t * step;
141 return idx;
142 }
143
144 static std::allocator<T> allo;
145 const tarch::la::Vector<dim, unsigned int> _spatialSize;
146 const unsigned int _temporalSize;
147 const unsigned int _scalarSize;
148 T* const _data;
149
150 friend class coupling::filtering::Patch<dim>; // patches need direct access to
151 // their field's _data for
152 // memory efficiency
153};
154
155template <unsigned int dim, typename T> std::allocator<T> coupling::filtering::Field<dim, T>::allo;
156
157/***
158 * includes local flowfield, and mean and standard deviation of quantities
159 */
160template <unsigned int dim> class coupling::filtering::Patch {
161public:
162 Patch(const tarch::la::Vector<dim, unsigned int>& spatialSize, const unsigned int& temporalSize, const Flowfield<dim>& basefield,
163 const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t)
164 : _flowfield(spatialSize, temporalSize), _localMean(0.0), _localStandardDeviation(0.0) {
165 fillFromBasefield(basefield, pos, t);
166 computeLocalMean();
167 computeLocalStandardDeviation();
168 }
169
170 double distance(const coupling::filtering::Patch<dim>& other) {
171 unsigned int size = _flowfield.getScalarSize() * (dim + 1);
172
173 double* const my_data = reinterpret_cast<double* const>(_flowfield._data);
174 double* const other_data = reinterpret_cast<double* const>(other._flowfield._data);
175
176 double res = 0;
177 for (unsigned int i = 0; i < size; i += 1) {
178 double diff(my_data[i] - other_data[i]);
179 res += diff * diff;
180 }
181 return res;
182 }
183
184 ~Patch() {}
185
186 void print() { _flowfield.print(); }
187
188private:
189 inline unsigned int posmod(int i, int n) { return (i % n + n) % n; }
190
191 void fillFromBasefield(const Flowfield<dim>& basefield, const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t) {
192 static_assert(dim == 2 || dim == 3, "ERROR filtering::Patch::fillFromBasefield only implemented "
193 "for 2D and 3D");
194
196 for (unsigned int d = 0; d < dim; d++) {
197 center[d] = _flowfield.getSpatialSize()[d] / 2;
198 }
199
201 unsigned int local_t(0);
203 unsigned int base_t(0);
204
205 for (int offset_t = 0; offset_t > -(int)_flowfield.getTemporalSize(); offset_t--) {
206 local_t = posmod(offset_t, _flowfield.getTemporalSize());
207 base_t = posmod(t + offset_t, basefield.getTemporalSize());
208 for (int offset_x = -(int)(_flowfield.getSpatialSize()[0]) / 2; offset_x <= (int)(_flowfield.getSpatialSize()[0]) / 2; offset_x++) {
209 local_pos[0] = center[0] + offset_x;
210 base_pos[0] = pos[0] + offset_x;
211 for (int offset_y = -(int)(_flowfield.getSpatialSize()[1]) / 2; offset_y <= (int)(_flowfield.getSpatialSize()[1]) / 2; offset_y++) {
212 local_pos[1] = center[1] + offset_y;
213 base_pos[1] = pos[1] + offset_y;
214 if constexpr (dim == 3) {
215 for (int offset_z = -(int)(_flowfield.getSpatialSize()[2]) / 2; offset_z <= (int)(_flowfield.getSpatialSize()[2]) / 2; offset_z++) {
216 local_pos[2] = center[2] + offset_z;
217 base_pos[2] = pos[2] + offset_z;
218 _flowfield(local_pos, local_t) = basefield(base_pos, base_t);
219 }
220 } else {
221 _flowfield(local_pos, local_t) = basefield(base_pos, base_t);
222 }
223 }
224 }
225 }
226 }
227
228 void computeLocalMean() {
229 for (unsigned int i = 0; i < _flowfield.getScalarSize(); i++)
230 _localMean += _flowfield[i];
231 _localMean = _localMean * (1.0 / _flowfield.getScalarSize());
232 }
233
234 void computeLocalStandardDeviation() {
235 for (unsigned int i = 0; i < _flowfield.getScalarSize(); i++) {
236 Quantities<dim> diff = _localMean - _flowfield[i];
237 _localStandardDeviation += tarch::la::dot(diff, diff);
238 }
239 _localStandardDeviation = sqrt(_localStandardDeviation / _flowfield.getScalarSize());
240 }
241
242 Flowfield<dim> _flowfield;
243 Quantities<dim> _localMean;
244 double _localStandardDeviation;
245};
246
247/***
248 * similar to patch, but does not store local flowfield,
249 * accesses basefield for distance computation
250 */
251template <unsigned int dim> class coupling::filtering::PatchView {
252public:
253 PatchView(const tarch::la::Vector<dim, unsigned int>& spatialSize, const unsigned int& temporalSize, const Flowfield<dim>& basefield,
254 const tarch::la::Vector<dim, unsigned int>& pos, const unsigned int& t)
255 : _spatialSize(spatialSize), _temporalSize(temporalSize), _basefield(basefield), _pos(pos), _t(t) {}
256
257 double distance(const coupling::filtering::PatchView<dim>& other) const {
258 double res = 0;
259
261 unsigned int base_t(0);
262
263 for (int offset_t = 0; offset_t > -(int)_temporalSize; offset_t--) {
264 base_t = posmod(_t + offset_t, _basefield.getTemporalSize());
265 for (int offset_x = -(int)(_spatialSize[0]) / 2; offset_x <= (int)(_spatialSize[0]) / 2; offset_x++) {
266 base_pos[0] = _pos[0] + offset_x;
267 for (int offset_y = -(int)(_spatialSize[1]) / 2; offset_y <= (int)(_spatialSize[1]) / 2; offset_y++) {
268 base_pos[1] = _pos[1] + offset_y;
269 if constexpr (dim == 3) {
270 for (int offset_z = -(int)(_spatialSize[2]) / 2; offset_z <= (int)(_spatialSize[2]) / 2; offset_z++) {
271 base_pos[2] = _pos[2] + offset_z;
272 // TODO: this is not correct. fix me
273 auto diff(_basefield(base_pos, base_t) - _basefield(base_pos + other._pos - _pos, posmod(base_t + other._t - _t, _basefield.getTemporalSize())));
274 res += diff[0] * diff[0];
275 }
276 } else {
277 auto diff(_basefield(base_pos, base_t) - other._basefield(base_pos, base_t));
278 res += tarch::la::dot(diff, diff);
279 }
280 }
281 }
282 }
283 return res;
284 }
285
286private:
287 inline unsigned int posmod(int i, int n) const { return (i % n + n) % n; }
288
289 const tarch::la::Vector<dim, unsigned int> _spatialSize;
290 const unsigned int _temporalSize;
291 const Flowfield<dim>& _basefield;
293 const unsigned int _t;
294};
Definition Datastructures.h:56
Definition Datastructures.h:251
Definition Datastructures.h:160
Definition Vector.h:24
Definition FilterPipeline.h:21
everything necessary for coupling operations, is defined in here
Definition AdditiveMomentumInsertion.h:15