8#include "kernel/util/string.hpp"
9#include "kernel/util/tiny_algebra.hpp"
11#include <kernel/shape.hpp>
13#include <kernel/util/slotmap.hpp>
19namespace FEAT::Geometry::Intern
50 inline bool operator<(Layer lhs, Layer rhs)
52 return lhs.idx < rhs.idx;
55 inline bool operator>(Layer lhs, Layer rhs)
57 return lhs.idx > rhs.idx;
60 inline bool operator<=(Layer lhs, Layer rhs)
62 return lhs.idx <= rhs.idx;
65 inline bool operator>=(Layer lhs, Layer rhs)
67 return lhs.idx >= rhs.idx;
126 inline bool operator!=(
const ElementKey<dim_>& lhs,
const ElementKey<dim_>& rhs)
128 return !(lhs == rhs);
132 inline std::ostream& operator<<(std::ostream& stream,
const ElementKey<dim_> key)
137 <<
", generation = " <<
stringify(key.generation)
138 <<
", layer = Layer {" <<
stringify(key.layer.idx)
139 <<
"}, is_permanent = " <<
stringify(key.is_permanent) <<
" }";
143 using VertexKey = ElementKey<0>;
144 using EdgeKey = ElementKey<1>;
145 using FaceKey = ElementKey<2>;
146 using CellKey = ElementKey<3>;
171 return lhs.key == rhs.key && lhs.orientation == rhs.orientation;
175 inline bool operator!=(
const OrientedElement<dim_>& lhs,
const OrientedElement<dim_>& rhs)
177 return !(lhs == rhs);
194 template<
typename TemplateSet_,
typename Shape_,
int dim_ = Shape_::dimension>
198 static constexpr int max_children = TemplateSet_::template max_children<Shape_::dimension, dim_>();
203 template<
int query_dim_>
204 std::array<ElementKey<query_dim_>, TemplateSet_::template max_children<Shape_::dimension, query_dim_>()>& by_dim()
206 static_assert(query_dim_ <= Shape_::dimension);
211 template<
int query_dim_>
212 const std::array<ElementKey<query_dim_>, TemplateSet_::template max_children<Shape_::dimension, query_dim_>()>& by_dim()
const
214 static_assert(query_dim_ <= Shape_::dimension);
236 template<
typename TemplateSet_,
typename Shape_>
240 static constexpr int max_children = TemplateSet_::template max_children<Shape_::dimension, 0>();
245 template<
int query_dim_>
246 std::array<ElementKey<query_dim_>, TemplateSet_::template max_children<Shape_::dimension, query_dim_>()>& by_dim()
248 static_assert(query_dim_ == 0);
253 template<
int query_dim_>
254 const std::array<ElementKey<query_dim_>, TemplateSet_::template max_children<Shape_::dimension, query_dim_>()>& by_dim()
const
256 static_assert(query_dim_ == 0);
270 template<
typename Shape_,
int dim_ = Shape_::dimension - 1>
273 static_assert(dim_ >= 0);
281 template<
int key_dim_>
284 static_assert(key_dim_ < Shape_::dimension);
290 template<
int query_dim_>
293 static_assert(query_dim_ < Shape_::dimension);
298 template<
int query_dim_>
301 static_assert(query_dim_ < Shape_::dimension);
306 template<
int query_dim_>
309 static_assert(query_dim_ <= Shape_::dimension);
315 template<
typename Shape_>
324 template<
int key_dim_>
327 static_assert(key_dim_ == 0);
333 template<
int query_dim_>
336 static_assert(query_dim_ == 0);
341 template<
int query_dim_>
344 static_assert(query_dim_ == 0);
349 template<
int query_dim_>
352 static_assert(query_dim_ == 0);
365 template<
typename TemplateSet_,
typename Shape_>
368 static_assert(Shape_::dimension > 0);
370 using TemplateSet = TemplateSet_;
372 using RefinementType =
typename TemplateSet::template RefinementTypeByDim<Shape_::dimension>;
399 static constexpr int num_neighbors =
Shape::FaceTraits<Shape_, Shape_::dimension - 1>::count;
400 std::array<Intern::ElementKey<Shape_::dimension>, num_neighbors> neighbors;
410 template<
typename VertexType>
446 template<
typename TemplateSet_,
typename MeshShape_,
typename VertexType_,
int element_dim_ = MeshShape_::dimension>
475 template<
typename Shape_>
479 key.is_permanent =
true;
492 template<
typename Shape_>
496 key.is_permanent =
false;
508 if constexpr(dim_ == 0)
534 if constexpr(dim_ == 0)
553 if constexpr(dim_ == 0)
613 static_assert(dim_ >= 1);
634 static_assert(dim_ >= 1);
658 template<
typename TemplateSet_,
typename MeshShape_,
typename VertexType_>
659 class MeshLayer<TemplateSet_, MeshShape_, VertexType_, 0>
673 return _vertices.
insert(vertex);
683 _vertices.
erase(key);
691 return _vertices.
size();
711 return _vertices.bytes();
719 return _vertices[key];
727 return _vertices[key];
750 template<
typename MeshShape_,
typename TemplateSet_,
typename VertexType_>
757 using CoordType =
typename VertexType_::ValueType;
798 static constexpr int num_coords = VertexType::n;
824 return (*
this)[key].type;
847 std::array<Index, 4> num_erased = {};
848 if constexpr(dim_ > 0)
853 auto& entity = (*this)[key];
855 _erase_children<typename Shape::FaceTraits<MeshShape_, dim_>::ShapeType, dim_>(entity.type, entity.children);
860 num_erased[dim_] += 1;
909 template<
typename Shape_>
924 bool is_permanent = element.
type.is_zero_refinement();
928 key =
_layers[layer.
idx].insert_permanent(element);
932 key =
_layers[layer.
idx].insert_transient(element);
971 template<
typename VisitorType_,
int dim_>
974 VisitorType_& visitor,
978 auto& root = (*this)[root_key];
981 if(root.layer > max_depth)
987 if(order == IterationOrder::PreOrder)
992 if constexpr(dim_ > 0)
994 _walk_subtree_children<typename Shape::FaceTraits<MeshShape_, dim_>::ShapeType>(root, visitor, max_depth);
998 if(order == IterationOrder::PostOrder)
1019 template<
typename VisitorType_>
1030 if constexpr(MeshShape_::dimension >= 0)
1032 for(
auto entry : root_layer.vertices())
1038 if constexpr(MeshShape_::dimension >= 1)
1040 for(
auto entry : root_layer.template permanent_entities<1>())
1044 for(
auto entry : root_layer.template transient_entities<1>())
1050 if constexpr(MeshShape_::dimension >= 2)
1052 for(
auto entry : root_layer.template permanent_entities<2>())
1056 for(
auto entry : root_layer.template transient_entities<2>())
1062 if constexpr(MeshShape_::dimension >= 3)
1064 for(
auto entry : root_layer.template permanent_entities<3>())
1068 for(
auto entry : root_layer.template transient_entities<3>())
1087 return _num_entities<0>(layer);
1091 return _num_entities<1>(layer);
1095 return _num_entities<2>(layer);
1099 return _num_entities<3>(layer);
1101 XABORTM(
"unsupported dimension in MeshStorage::num_entities");
1117 result += layer.template num_permanent_entities<dim_>();
1118 result += layer.template num_transient_entities<dim_>();
1129 static constexpr int shape_dim = MeshShape_::dimension;
1130 static constexpr int num_facets =
Shape::FaceTraits<MeshShape_, shape_dim - 1>::count;
1148 std::cout <<
"Recalculating neighbors\n";
1159 std::vector<std::vector<Util::SecondaryMap<std::array<ElementKey<shape_dim>, 2>,
ElementKey<shape_dim - 1>>>>
1162 std::vector<std::vector<Util::SecondaryMap<std::array<ElementKey<shape_dim>, 2>,
ElementKey<shape_dim - 1>>>>
1167 permanent_facet_neighbors[i].resize(
num_layers());
1168 transient_facet_neighbors[i].resize(
num_layers());
1172 auto determine_facet_neighbors = [&](
Layer layer,
auto slotmap_entry)
1183 element_key.
layer = layer;
1184 element_key.
is_permanent = slotmap_entry.value.type.is_zero_refinement();
1187 for(
int facet_idx = 0; facet_idx < num_facets; facet_idx++)
1190 auto key = slotmap_entry.value.topology.template key_by_dim<shape_dim - 1>(facet_idx).key;
1193 if(key.is_permanent && !permanent_facet_neighbors[layer.
idx][key.layer.idx].contains_key(key))
1198 if(!key.is_permanent && !transient_facet_neighbors[layer.
idx][key.layer.idx].contains_key(key))
1203 auto& neighbors = key.is_permanent ? permanent_facet_neighbors[layer.
idx][key.layer.idx][key] : transient_facet_neighbors[layer.
idx][key.layer.idx][key];
1207 neighbors[0] = element_key;
1211 neighbors[1] = element_key;
1215 XABORTM(
"Facet has more than two neighbors!");
1221 auto determine_neighbors = [&](
Layer layer,
auto slotmap_entry)
1223 auto& element = slotmap_entry.value;
1226 for(
int facet_idx = 0; facet_idx < num_facets; facet_idx++)
1229 auto key = slotmap_entry.value.topology.template key_by_dim<shape_dim - 1>(facet_idx).key;
1240 element_key.
layer = layer;
1241 element_key.is_permanent = slotmap_entry.value.type.is_zero_refinement();
1244 auto& candidates = key.is_permanent ? permanent_facet_neighbors[layer.
idx][key.layer.idx][key] : transient_facet_neighbors[layer.
idx][key.layer.idx][key];
1245 if(candidates[0] == element_key)
1247 element.neighbors[std::size_t(facet_idx)] = candidates[1];
1249 else if(candidates[1] == element_key)
1251 element.neighbors[std::size_t(facet_idx)] = candidates[0];
1259 for(
auto entry :
_layers[i].
template permanent_entities<shape_dim>())
1261 determine_facet_neighbors(
Layer{i}, entry);
1263 for(
auto entry :
_layers[i].
template transient_entities<shape_dim>())
1265 determine_facet_neighbors(
Layer{i}, entry);
1271 for(
auto entry :
_layers[i].
template permanent_entities<shape_dim>())
1273 determine_neighbors(
Layer{i}, entry);
1275 for(
auto entry :
_layers[i].
template transient_entities<shape_dim>())
1277 determine_neighbors(
Layer{i}, entry);
1321 for(
auto entry : layer.vertices())
1323 entry.value.set_mat_vec_mul(rot, entry.value - origin) += offset;
1351 Index next_vertex_index = 0;
1352 Index next_edge_index = 0;
1353 Index next_face_index = 0;
1354 Index next_cell_index = 0;
1358 if constexpr(MeshShape_::dimension >= 0)
1362 for(
auto entry : layer.vertices())
1364 entry.value.index = next_vertex_index++;
1368 if constexpr(MeshShape_::dimension >= 1)
1370 _index_layer<1>(layer, next_edge_index);
1373 if constexpr(MeshShape_::dimension >= 2)
1375 _index_layer<2>(layer, next_face_index);
1378 if constexpr(MeshShape_::dimension >= 3)
1380 _index_layer<3>(layer, next_cell_index);
1404 ASSERTM(layer.
idx <
_layers.size(),
"Trying to retrieve vertex of non-existing mesh layer!");
1421 for(
Index layer_idx = 0; layer_idx <= layer.
idx; layer_idx++)
1425 if(idx < current_layer.num_vertices())
1427 return current_layer.vertices().data()[idx];
1429 idx -= current_layer.num_vertices();
1432 XABORTM(
"Tried retrieving non-existent vertex index from AdaptiveMeshStorage!");
1450 return const_cast<AdaptiveVertexType&
>(std::as_const(*this).get_vertex_by_index(layer, idx));
1467 ASSERTM(layer.
idx <
_layers.size(),
"Trying to retrieve entity of non-existing mesh layer!");
1476 for(
Index layer_idx = 0; layer_idx <= layer.
idx; layer_idx++)
1480 if(idx < current_layer.template num_permanent_entities<dim_>())
1482 return current_layer.template permanent_entities<dim_>().data()[idx];
1484 idx -= current_layer.template num_permanent_entities<dim_>();
1488 if(idx < current_layer.template num_transient_entities<dim_>())
1490 return current_layer.template transient_entities<dim_>().data()[idx];
1493 XABORTM(
"Trying to retrieve non-exisiting element from AdaptiveMeshStorage");
1523 static constexpr int shape_dim = MeshShape_::dimension;
1527 auto& element = get_by_index<shape_dim>(layer, element_idx);
1530 return get_index(element.neighbors[neighbor_idx]);
1551 return (*
this)[key].index;
1566 return (*
this)[oriented_key.key].index;
1601 return (*
this)[ref.key];
1606 return (*
this)[ref.key];
1613 return (*
this)[ref.key];
1619 return (*
this)[ref.key];
1627 std::size_t total = 0;
1630 total += layer.bytes();
1647 if constexpr(dim_ > MeshShape_::dimension)
1656 for(
Index layer_idx = 0; layer_idx <= layer.
idx; layer_idx++)
1658 result +=
_layers[layer_idx].template num_permanent_entities<dim_>();
1660 result +=
_layers[layer.
idx].template num_transient_entities<dim_>();
1666 template<
typename Shape_,
int dim_ = Shape_::dimension>
1667 std::array<Index, 4> _erase_children(
1668 typename TemplateSet::template RefinementTypeByDim<Shape_::dimension>
type,
1671 if constexpr(dim_ >= 0)
1673 auto result = _erase_children<Shape_, dim_ - 1>(
type, children);
1675 auto& array = children.template by_dim<dim_>();
1676 for(
Index i(0); i < TemplateSet::template num_children<Shape_::dimension, dim_>(
type); i++)
1678 std::array<Index, 4> num_erased =
erase(array[i]);
1680 result[0] += num_erased[0];
1681 result[1] += num_erased[1];
1682 result[2] += num_erased[2];
1683 result[3] += num_erased[3];
1694 template<
typename Shape_,
int dim_ = Shape_::dimension,
typename VisitorType>
1695 void _walk_subtree_children(
const AdaptiveElement<TemplateSet, Shape_>& root, VisitorType& visitor, Layer max_depth)
const
1697 if constexpr(dim_ >= 0)
1699 _walk_subtree_children<Shape_, dim_ - 1>(root, visitor, max_depth);
1701 const auto& children = root.
children.template by_dim<dim_>();
1702 for(
Index i = 0; i < TemplateSet::template num_children<Shape_::dimension, dim_>(root.type); i++)
1718 while(
_layers.size() <= new_top_layer)
1736 for(
auto entry : layer.template permanent_entities<dim_>())
1738 entry.value.index = next_permanent_index++;
1742 Index next_transient_index = next_permanent_index;
1748 for(
auto entry : layer.template transient_entities<dim_>())
1750 entry.value.index = next_transient_index++;
1757 template<
int sm_,
int sn_,
int sv_>
1768 template<
int sm_,
int sn_,
int sv_>
1779 template<
int sm_,
int sn_,
int sv_>
#define ASSERT(expr)
Debug-Assertion macro definition.
#define XABORTM(msg)
Abortion macro definition with custom message.
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
Storage class for AdaptiveMeshes.
VertexKey insert(const AdaptiveVertexType &vertex)
Insert a vertex into the storage.
void fill_neighbors()
Determines neighboring elements for all mesh elements.
void _index_layer(MeshLayerType &layer, Index &next_permanent_index)
Assigns indexes to all elemens of a layer.
ElementKey< Shape_::dimension > insert(const AdaptiveElement< TemplateSet, Shape_ > &element)
Insert an adaptive element into the storage.
AdaptiveElementByDim< dim_ > & operator[](ElementKey< dim_ > key)
Retrieve element by key.
VertexKey insert(VertexType vertex, Layer layer)
Insert a vertex into the storage.
VertexType_ VertexType
Type of vertices in this mesh.
Index num_total_entities() const
Returns the total number of all mesh elements in the storage.
static void _aux_rot_mat(Tiny::Matrix< CoordType, 3, 3, sm_, sn_ > &r, const Tiny::Vector< CoordType, 3, sv_ > &a)
Helper for transform method.
void transform(const VertexType &origin, const VertexType &angles, const VertexType &offset)
Applies a "proper rigid" transformation onto the mesh vertices.
AdaptiveElementByDim< dim_ > & operator[](OrientedElement< dim_ > ref)
Retrieve element by oriented reference.
AdaptiveElementByDim< dim_ > & get_by_index(Layer layer, Index idx)
Retrieves an element of the mesh by its layer and index.
const AdaptiveVertexType & get_vertex_by_index(Layer layer, Index idx) const
Retrieves a vertex of the mesh by its layer and index.
static void _aux_rot_mat(Tiny::Matrix< CoordType, 2, 2, sm_, sn_ > &r, const Tiny::Vector< CoordType, 2, sv_ > &a)
Helper for transform method.
Index num_entities(Layer layer, int dim) const
Returns the number of mesh elements of the given dimension on the given layer.
std::size_t bytes() const
Returns the number of bytes used by this class.
AdaptiveVertexType & operator[](VertexKey key)
Retrieve vertex by key.
static void _aux_rot_mat(Tiny::Matrix< CoordType, 1, 1, sm_, sn_ > &r, const Tiny::Vector< CoordType, 1, sv_ > &)
Helper for transform method.
Index get_neighbor(Layer layer, Index element_idx, Index neighbor_idx) const
Returns the index of the n-th neighbor of the given element.
void walk_tree(VisitorType_ &visitor, Layer max_depth, IterationOrder order=IterationOrder::PreOrder) const
Index get_index(OrientedElement< dim_ > oriented_key) const
Get the numeric mesh index of the element pointed to by key.
void _add_mesh_layers(Index new_top_layer)
Adds additional mesh layers, such that.
void reindex()
Re-indexes the storage.
const AdaptiveElementByDim< dim_ > & operator[](ElementKey< dim_ > key) const
Retrieve element by key.
static const constexpr ElementKey< MeshShape_::dimension > neighbor_sentinel
Sentinel key for non-existing neighbors, e.g. for boundary elements.
const AdaptiveElementByDim< dim_ > & get_by_index(Layer layer, Index idx) const
Retrieves an element of the mesh by its layer and index.
Index _num_entities(Layer layer) const
Returns the number of mesh elements of the given dimension on the given layer.
Index num_layers() const
Return the number of layers in this mesh.
bool _is_indexed
Indicates whether this mesh has been indexed since the last modification.
TemplateSet_ TemplateSet
Template set to be used for refinement.
std::vector< MeshLayerType > _layers
List of MeshLayers for this mesh.
bool _has_neighbors
Indicates whether neighbors have been calculated for this mesh.
AdaptiveVertex< VertexType > AdaptiveVertexType
Adaptive vertex type.
TemplateSet::template RefinementTypeByDim< dim > type(ElementKey< dim > key)
Get refinement type of element.
void walk_subtree(ElementKey< dim_ > root_key, VisitorType_ &visitor, Layer max_depth, IterationOrder order=IterationOrder::PreOrder) const
const AdaptiveVertexType & operator[](VertexKey key) const
Retrieve vertex by key.
AdaptiveVertexType & get_vertex_by_index(Layer layer, Index idx)
Retrieves a vertex of the mesh by its layer and index.
std::array< Index, 4 > erase(ElementKey< dim_ > key)
Erases an element and all its children from the storage.
Index get_index(ElementKey< dim_ > key) const
Get the numeric mesh index of the element pointed to by key.
void erase(ElementKey< 0 > key)
Erase a vertex from this layer.
Util::SlotMap< AdaptiveVertex< VertexType_ >, ElementKey< 0 > > _vertices
SlotMap for this layers vertices.
ElementKey< 0 > insert_vertex(const AdaptiveVertex< VertexType_ > &vertex)
Insert a vertex into this layer.
AdaptiveVertex< VertexType_ > & get_vertex(ElementKey< 0 > key)
Retrieve a reference to the AdaptiveVertex pointed to by key.
Util::SlotMap< AdaptiveVertex< VertexType_ >, ElementKey< 0 > > & vertices()
Vertex SlotMap accessor.
const Util::SlotMap< AdaptiveVertex< VertexType_ >, ElementKey< 0 > > & vertices() const
Vertex SlotMap accessor.
const AdaptiveVertex< VertexType_ > & get_vertex(ElementKey< 0 > key) const
Retrieve a reference to the AdaptiveVertex pointed to by key.
Index num_vertices() const
Returns the number of vertices in this layer.
std::size_t bytes() const
Returns the number of bytes used by this layer.
Storage class for a single layer of the adaptive mesh.
Util::SlotMap< AdaptiveElementType, ElementKeyType > _permanent_entities
Slotmap for permanent mesh elements.
Index num_permanent_entities() const
Get number of permanent entities of dimension dim_ in this layer.
Index num_transient_entities() const
Get number of transient entities of dimension dim_ in this layer.
ElementKey< Shape_::dimension > insert_transient(const AdaptiveElement< TemplateSet_, Shape_ > &element)
Insert a transient element into this layer.
std::size_t bytes() const
Returns number of bytes used by this layer.
AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType > & get(ElementKey< dim_ > key)
Retrieve the AdaptiveElement belonging to the given key.
const AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType > & get(ElementKey< dim_ > key) const
Retrieve the AdaptiveElement belonging to the given key.
typename Shape::FaceTraits< MeshShape_, element_dim_ >::ShapeType ShapeType
Shape type of entities stored in this layer of dimension element_dim_.
const Util::SlotMap< AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType >, ElementKey< dim_ > > & transient_entities() const
Transient element SlotMap accessor.
void erase(ElementKey< dim_ > key)
Erase an element from this layer.
Util::SlotMap< AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType >, ElementKey< dim_ > > & permanent_entities()
Permanent element SlotMap accessor.
Util::SlotMap< AdaptiveElementType, ElementKeyType > _transient_entities
Slotmap for transient mesh elements.
ElementKey< Shape_::dimension > insert_permanent(const AdaptiveElement< TemplateSet_, Shape_ > &element)
Insert a permanent element into this layer.
const Util::SlotMap< AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType >, ElementKey< dim_ > > & permanent_entities() const
Permanent element SlotMap accessor.
Util::SlotMap< AdaptiveElement< TemplateSet_, typename Shape::FaceTraits< MeshShape_, dim_ >::ShapeType >, ElementKey< dim_ > > & transient_entities()
Transient element SlotMap accessor.
Tiny Matrix class template.
CUDA_HOST_DEVICE Matrix & set_rotation_3d(T_ yaw, T_ pitch, T_ roll)
Sets this matrix to a 3D yaw-pitch-roll rotation matrix.
CUDA_HOST_DEVICE Matrix & set_rotation_2d(T_ angle)
Sets this matrix to a 2D rotation matrix.
CUDA_HOST_DEVICE Matrix & set_identity()
Sets this matrix to the identity matrix.
Tiny Vector class template.
High-performance associative container.
Key insert(V &&value)
Insert value into the SlotMap.
void erase(const Key &key)
Remove a key from the SlotMap.
Index size() const
Retrieve current size of the SlotMap.
@ other
generic/other permutation strategy
String stringify(const T_ &item)
Converts an item into a String.
std::uint64_t Index
Index data type.
Layer layer
The elements layer.
Index index
The elements mesh index.
ElementChildren< TemplateSet_, Shape_ > children
Child element references.
RefinementType type
The elements refinement type.
ElementTopology< Shape_ > topology
Surrounding element references.
VertexType vertex
Vertex coordinates.
Layer last_changed
Depth the vertex was last used as a parent vertex.
Index index
This elements index in the mesh layers it is a part of.
Layer layer
This elements depth in the refinement tree.
std::array< Intern::ElementKey< 0 >, max_children > children
Children of dimension 0.
Children of a mesh element.
static constexpr int max_children
Maximum number of children of dimension dim_.
std::array< Intern::ElementKey< dim_ >, max_children > children
Children of dimension dim_.
SlotMap key for use by the AdaptiveMeshStorage class.
Layer layer
Element Layer.
std::uint32_t index
Index into the SlotMaps' slots. See SlotMapKey for details.
std::uint32_t generation
Generation of this key. See SlotMapKey for details.
bool is_permanent
Element Kind.
std::array< OrientedElement< 0 >, num_entities > entities
Surrounding entities at dimension dim_.
Surrounding elements of a mesh element.
static constexpr int num_entities
Number of surrounding elements at dimension dim_.
std::array< OrientedElement< dim_ >, num_entities > entities
Surrounding entities at dimension dim_.
Newtype wrapper for mesh layers.
Index idx
Index of the layer.
Orientation-aware reference to another mesh element.
Face traits tag struct template.