MaMiCo 1.2
Loading...
Searching...
No Matches
CellIndex.h
1#pragma once
2
3#include <iostream>
4#include <iterator>
5#include <string_view>
6#include <type_traits>
7
8#include "tarch/la/Vector.h"
9
10namespace coupling {
11namespace indexing {
12
24enum class IndexTrait { vector, local, md2macro, noGhost };
25namespace TraitOperations {
26
31template <IndexTrait t1> constexpr bool is_same(const IndexTrait& t2) { return t1 == t2; }
32
45template <IndexTrait t1, IndexTrait t2, IndexTrait... rest> constexpr bool is_ordered() {
46 if constexpr (sizeof...(rest) == 0) {
47 return t1 < t2;
48 } else {
49 return t1 < t2 and is_ordered<t2, rest...>();
50 }
51}
52
53} // namespace TraitOperations
54
71template <unsigned int dim, IndexTrait... traits> class CellIndex;
72
76template <unsigned int dim> using BaseIndex = CellIndex<dim, IndexTrait::vector>;
77
78// TODO: refactor as member functions
79template <unsigned int dim, IndexTrait... traits> unsigned int convertToScalar(const CellIndex<dim, traits...>&);
80
81template <unsigned int dim, IndexTrait... traits> tarch::la::Vector<dim, int> convertToVector(const CellIndex<dim, traits...>&);
82} // namespace indexing
83} // namespace coupling
84
85template <unsigned int dim, coupling::indexing::IndexTrait... traits> class coupling::indexing::CellIndex {
86public:
97 static constexpr bool checkIndexTraitOrder() {
98 if constexpr (sizeof...(traits) > 1) {
99 return coupling::indexing::TraitOperations::is_ordered<traits...>();
100 } else {
101 return true;
102 }
103 }
104 static_assert(checkIndexTraitOrder(), "Invalid order in IndexTrait parameter pack! Correct oder: "
105 "IndexTrait::vector < IndexTrait::local < IndexTrait::md2macro "
106 "< IndexTrait::noGhost");
107
111 using value_T = std::conditional_t<(coupling::indexing::TraitOperations::is_same<coupling::indexing::IndexTrait::vector>(traits) or ...),
112 tarch::la::Vector<dim, int>, unsigned int>;
113
117 CellIndex() = default;
118 CellIndex(const CellIndex& ci) = default;
119 explicit CellIndex(const value_T& i) : _index(i) {}
120
129 template <coupling::indexing::IndexTrait... converted_traits> operator CellIndex<dim, converted_traits...>() const;
130
138 value_T get() const { return _index; } // TODO: why (value_T) cast?
139
146 if constexpr (std::is_same_v<value_T, tarch::la::Vector<dim, int>>) {
147 ++_index[0];
148 if (_index[0] == (int)numberCellsInDomain[0]) {
149 _index[0] = 0;
150 ++_index[1];
151 if (_index[1] == (int)numberCellsInDomain[1]) {
152 _index[1] = 0;
153 if constexpr (dim == 3)
154 ++_index[2];
155 }
156 }
157 } else
158 ++_index;
159
160 return *this;
161 }
162
168 if constexpr (std::is_same_v<value_T, tarch::la::Vector<dim, int>>) {
169 --_index[0];
170 if (_index[0] < 0) {
171 _index[0] = numberCellsInDomain[0] - 1;
172 --_index[1];
173 if (_index[1] < 0) {
174 _index[1] = numberCellsInDomain[1] - 1;
175 if constexpr (dim == 3)
176 --_index[2];
177 }
178 }
179 } else
180 --_index;
181
182 return *this;
183 }
184
185 /*
186 * Any two indices fulfill some relation iff the unsigned integers underlying
187 * their CellIndex<dim, {}> equivalents fulfill that relation. Note that this
188 * is different than what the static member 'contains(...)' does.
189 *
190 * @param CellIndex index to compare this index to
191 */
192 bool operator==(const CellIndex& i) const { return _index == i.get(); }
193 bool operator!=(const CellIndex& i) const { return not(i == *this); }
194 bool operator<(const CellIndex& i) const { return convertToScalar<dim, traits...>(*this) < convertToScalar<dim, traits...>(i); };
195 bool operator<=(const CellIndex& i) const { return convertToScalar<dim, traits...>(*this) <= convertToScalar<dim, traits...>(i); };
196 bool operator>(const CellIndex& i) const { return convertToScalar<dim, traits...>(*this) > convertToScalar<dim, traits...>(i); };
197 bool operator>=(const CellIndex& i) const { return convertToScalar<dim, traits...>(*this) >= convertToScalar<dim, traits...>(i); };
198
203 static void setDomainParameters() {
204 auto cellnum = upperBoundary.get() - lowerBoundary.get() + tarch::la::Vector<dim, int>{1};
205 for (unsigned int d = 0; d < dim; d++)
206 cellnum[d] = std::max(0, cellnum[d]);
208
210 for (unsigned int d = 0; d < dim; d++)
212
214 for (unsigned int d = 1; d < dim; d++)
215 divFactor[d] = divFactor[d - 1] * (numberCellsInDomain[d - 1]);
216 divisionFactor = divFactor;
217 }
218
227 static bool contains(const coupling::indexing::BaseIndex<dim>& index) {
228 for (unsigned int d = 0; d < dim; d++) {
229 if (index.get()[d] < CellIndex::lowerBoundary.get()[d])
230 return false;
231 if (index.get()[d] > CellIndex::upperBoundary.get()[d])
232 return false;
233 }
234
235 return true;
236 }
237
238 tarch::la::Vector<dim, double> getCellMidPoint() const {
239 BaseIndex<dim> globalIndex{*this};
240 tarch::la::Vector<dim, double> cellMidPoint(IndexingService<dim>::getInstance().getGlobalMDDomainOffset() -
241 0.5 * IndexingService<dim>::getInstance().getCouplingCellSize());
242 for (unsigned int d = 0; d < dim; d++)
243 cellMidPoint[d] += ((double)(globalIndex.get()[d])) * IndexingService<dim>::getInstance().getCouplingCellSize()[d];
244 return cellMidPoint;
245 }
246
252 static BaseIndex<dim> lowerBoundary;
258 static BaseIndex<dim> upperBoundary;
259
265
270 static unsigned int linearNumberCellsInDomain;
271
277
278 class IndexIterator {
279 public:
280 IndexIterator(CellIndex x) : _idx(x) {}
281 IndexIterator(const IndexIterator& a) : _idx(a._idx) {}
282
283 const CellIndex& operator*() const { return _idx; }
284 const CellIndex* operator->() const { return &_idx; }
285
286 // Prefix increment
287 IndexIterator& operator++() {
288 ++_idx;
289 return *this;
290 }
291
292 // Postfix increment
293 IndexIterator operator++(int) {
294 IndexIterator tmp = *this;
295 ++(*this);
296 return tmp;
297 }
298
299 friend bool operator==(const IndexIterator& a, const IndexIterator& b) { return a._idx == b._idx; };
300 friend bool operator!=(const IndexIterator& a, const IndexIterator& b) { return a._idx != b._idx; };
301
302 private:
303 CellIndex _idx;
304 };
305 static IndexIterator begin() {
306 // if constexpr is neccessary here (otherwise benchmark performance breaks, due to runtime if)
307 if constexpr (std::is_same_v<unsigned int, value_T>) {
308 // If this CellIndex is scalar and if the domain is empty, then lowerBoundary can not be converted to CellIndex
309 // Thus we have to return something else as an iterator for the empty domain
311 return IndexIterator(CellIndex{});
312 else
313 return IndexIterator(lowerBoundary);
314 } else
315 return IndexIterator(lowerBoundary);
316 }
317 static IndexIterator end() {
318 // Todo: This if-else branching is quite slow? (~factor 2)
320 return begin();
321 else
322 return ++IndexIterator(upperBoundary);
323 }
324
325 static const char TNAME[];
326
327private:
328 value_T _index;
329
330 template <coupling::indexing::IndexTrait T1, coupling::indexing::IndexTrait... other_traits> CellIndex<dim, other_traits...> getScalarCellIndex(int value) {
331 static_assert(T1 == coupling::indexing::IndexTrait::vector);
332 return CellIndex<dim, other_traits...>(value);
333 }
334};
335
336// Include implementation
337#include "CellIndex.cpph"
Definition CellIndex.h:85
static constexpr bool checkIndexTraitOrder()
Definition CellIndex.h:97
static void setDomainParameters()
Definition CellIndex.h:203
static bool contains(const coupling::indexing::BaseIndex< dim > &index)
Definition CellIndex.h:227
CellIndex & operator--()
Definition CellIndex.h:167
std::conditional_t<(coupling::indexing::TraitOperations::is_same< coupling::indexing::IndexTrait::vector >(traits) or ...), tarch::la::Vector< dim, int >, unsigned int > value_T
Definition CellIndex.h:111
CellIndex & operator++()
Definition CellIndex.h:145
value_T get() const
Definition CellIndex.h:138
Definition Vector.h:24
everything necessary for coupling operations, is defined in here
Definition AdditiveMomentumInsertion.h:15