MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
maia::grid::hilbert Namespace Reference

Namespaces

namespace  detail_
 

Functions

template<MInt nDim, typename FloatType , typename IdType >
IdType index (const FloatType *const x, const IdType level)
 Return Hilbert index for given location and level in 2D or 3D. More...
 
template<MInt nDim, typename FloatType , typename IdType >
MBool coordinatesToTreeId (IdType &treeId, const FloatType *const x, const IdType level, const FloatType *const centerOfGravity, FloatType const lengthOnLevel0)
 
template<MInt nDim, typename FloatType , typename IdType >
void treeIdToCoordinates (FloatType *const x, const IdType treeId, const IdType level, const FloatType *const centerOfGravity, const FloatType lengthOnLevel0)
 

Function Documentation

◆ coordinatesToTreeId()

template<MInt nDim, typename FloatType , typename IdType >
MBool maia::grid::hilbert::coordinatesToTreeId ( IdType &  treeId,
const FloatType *const  x,
const IdType  level,
const FloatType *const  centerOfGravity,
FloatType const  lengthOnLevel0 
)
Author
Lennart
Date

Definition at line 188 of file hilbert.h.

192 {
193 // Check that level is at least 0
194 ASSERT(level >= 0, "Level must be at least zero");
195
196 // Check for integer overflow ("- 1" to account for signed integers, cast to
197 // avoid "unsigned/signed comparison" warning)
198 ASSERT(nDim * level <= CHAR_BIT * static_cast<IdType>(sizeof(IdType)) - 1, "Integer overflow: level too large");
199
200 MBool exists = true;
201 treeId = 0;
202 for(IdType k = 0; k < nDim; k++) {
203 if(x[k] < centerOfGravity[k] - 0.5 * lengthOnLevel0 || x[k] > centerOfGravity[k] + 0.5 * lengthOnLevel0) {
204 exists = false;
205 }
206 }
207 if(!exists) {
208 treeId = std::numeric_limits<IdType>::is_signed ? -1 : ~0;
209 } else {
210 IdType bitCount = 0;
211 IdType coord[3];
212 constexpr IdType id2 = (IdType)2;
213 for(IdType k = 0; k < nDim; k++) {
214 coord[k] = (IdType)((x[k] - centerOfGravity[k] + 0.5 * lengthOnLevel0) * FPOW2(level) / lengthOnLevel0);
215 }
216 for(IdType lvl = level - 1; lvl >= 0; lvl--) {
217 for(IdType k = 0; k < nDim; k++) {
218 IdType bit = (coord[k] / (IdType)IPOW2(lvl)) % id2;
219 treeId |= bit << bitCount;
220 bitCount++;
221 }
222 }
223 }
224 return exists;
225}
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
bool MBool
Definition: maiatypes.h:58

◆ index()

template<MInt nDim, typename FloatType , typename IdType >
IdType maia::grid::hilbert::index ( const FloatType *const  x,
const IdType  level 
)
Author
Michael Schlottke (mic) mic@a.nosp@m.ia.r.nosp@m.wth-a.nosp@m.ache.nosp@m.n.de, Peter Philippen
Date
2014-12-08
Template Parameters
nDimDimension for which the Hilbert index should be generated.
FloatTypeThe floating point type for the coordinates.
IdTypeThe integer type that should be used for the index.
Parameters
[in]xPointer to nDim coordinates for which the index is calculated. The coordinates must be within the unit square (2D, [0,1]x[0,1])/unit cube (3D, [0,1]x[0,1]x[0,1]).
[in]levelRefinement level (not Hilbert level) for which the index should be calculated.
Returns
The calculated Hilbert index.

The algorithms used here are taken from

Peter Philippen. Investigation of two different domain decompositioning
methods for a cartesian flow solver. Studienarbeit, 2009.

The original implementation is by Peter, it was only simplified (no recursion!) and its robustness against bad input parameters increased. Also, the original implementation did not have any comments.

This is the basic idea:

  • determine the quadrant/octant of the unit hypercube in which the point is located
  • calculate its Hilbert index and multiply with the level weight
  • mirror/scale/translate quadrant/octant to new unit hypercube
  • repeat from beginning

Definition at line 165 of file hilbert.h.

165 {
166 // Check that level is at least 0
167 ASSERT(level >= 0, "Level must be at least zero");
168
169 // Check for integer overflow ("- 1" to account for signed integers, cast to
170 // avoid "unsigned/signed comparison" warning)
171 ASSERT(nDim * level <= CHAR_BIT * static_cast<IdType>(sizeof(IdType)) - 1, "Integer overflow: level too large");
172
173 // Assert that coordinates are in unit hypercube
174 ASSERT(x[0] >= 0.0 && x[0] <= 1.0, "Coordinate 0 out of bounds.");
175 ASSERT(x[1] >= 0.0 && x[1] <= 1.0, "Coordinate 1 out of bounds.");
176 IF_CONSTEXPR(nDim == 3) { ASSERT(x[2] >= 0.0 && x[2] <= 1.0, "Coordinate 2 out of bounds."); }
177
178 // Call template function
179 return detail_::Impl<nDim, FloatType, IdType>::f(x, level);
180}

◆ treeIdToCoordinates()

template<MInt nDim, typename FloatType , typename IdType >
void maia::grid::hilbert::treeIdToCoordinates ( FloatType *const  x,
const IdType  treeId,
const IdType  level,
const FloatType *const  centerOfGravity,
const FloatType  lengthOnLevel0 
)
Author
Lennart
Date

Definition at line 232 of file hilbert.h.

236 {
237 // Check that level is at least 0
238 ASSERT(level >= 0, "Level must be at least zero");
239
240 // Check for integer overflow ("- 1" to account for signed integers, cast to
241 // avoid "unsigned/signed comparison" warning)
242 ASSERT(nDim * level <= CHAR_BIT * static_cast<IdType>(sizeof(IdType)) - 1, "Integer overflow: level too large");
243
244 IdType bitCount = 0;
245 constexpr IdType id1 = (IdType)1;
246 for(IdType j = 0; j < nDim; j++) {
247 x[j] = centerOfGravity[j];
248 }
249 for(IdType lvl = 1; lvl <= level; lvl++) {
250 for(IdType j = 0; j < nDim; j++) {
251 IdType tmpBit = (treeId >> bitCount) & id1;
252 x[j] += (tmpBit ? 1.0 : -1.0) * lengthOnLevel0 * FFPOW2(lvl + 1);
253 bitCount++;
254 }
255 }
256}
constexpr MFloat FFPOW2(MInt x)