FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
conformal_mesh.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/geometry/factory.hpp>
10#include <kernel/geometry/mesh_permutation.hpp>
11#include <kernel/geometry/intern/facet_neighbors.hpp>
12#include <kernel/geometry/intern/standard_index_refiner.hpp>
13#include <kernel/geometry/intern/standard_vertex_refiner.hpp>
14#include <kernel/geometry/index_calculator.hpp>
15#include <kernel/geometry/facet_flipper.hpp>
16#include <kernel/util/math.hpp>
17
18// includes, system
19#include <memory>
20
21namespace FEAT
22{
23 namespace Geometry
24 {
38 template<
39 typename Shape_,
40 int num_coords_ = Shape_::dimension,
41 typename Coord_ = Real>
43 {
44 static_assert(num_coords_ >= Shape_::dimension, "invalid number of coordinates");
45
46 public:
48 typedef Shape_ ShapeType;
49
51 typedef Coord_ CoordType;
52
55
58
60 typedef IndexSetHolder<ShapeType> IndexSetHolderType;
61
63 static constexpr int shape_dim = ShapeType::dimension;
65 static constexpr int world_dim = VertexSetType::num_coords;
66
68 static constexpr bool is_structured = false;
69
72
82 template<
83 int cell_dim_,
84 int face_dim_>
85 struct IndexSet
86 {
87 static_assert(cell_dim_ <= shape_dim, "invalid cell dimension");
88 static_assert(face_dim_ < cell_dim_, "invalid face/cell dimension");
89 static_assert(face_dim_ >= 0, "invalid face dimension");
90
93 <
95 <
97 face_dim_
98 >
99 ::count
101 }; // struct IndexSet<...>
102
104 typedef typename IndexSet<shape_dim, shape_dim-1>::Type NeighborSetType;
105
106 protected:
109
112
115
118
121
122 public:
130 explicit ConformalMesh(const Index num_entities[]) :
131 _vertex_set(num_entities[0]),
132 _index_set_holder(num_entities),
133 _neighbors(num_entities[shape_dim]),
135 {
136 for(int i(0); i <= shape_dim; ++i)
137 {
138 //XASSERTM(num_entities[i] > 0, "Number of entities must not be zero!");
139 _num_entities[i] = num_entities[i];
140 }
141 }
142
150 _vertex_set(factory.get_num_entities(0)),
151 _index_set_holder(Intern::NumEntitiesWrapper<shape_dim>(factory).num_entities),
152 _neighbors(Intern::NumEntitiesWrapper<shape_dim>(factory).num_entities[shape_dim]),
154 {
155 // Compute entity counts
156 Intern::NumEntitiesWrapper<shape_dim>::apply(factory, _num_entities);
157
158 // fill vertex set
159 factory.fill_vertex_set(_vertex_set);
160
161 // fill index sets
162 factory.fill_index_sets(_index_set_holder);
163
164 // Recompute entity counts. This is mainly for the MeshStreamerFactory, as complete information about the
165 // number of edges/faces might not be known until after fill_index_sets is called
166 Intern::NumEntitiesWrapper<shape_dim>::apply(factory, _num_entities);
167
168 // Fill neighbor information. This needs facet at cell information, so it needs to be called after
169 // fill_index_sets() etc.
171 }
172
179 {
180 for(int i(0); i <= shape_dim; ++i)
181 {
182 _num_entities[i] = other.get_num_entities(i);
183 }
184 }
185
188 {
189 // avoid self-move
190 if(this == &other)
191 return *this;
192
193 _vertex_set = std::forward<VertexSetType>(other._vertex_set);
194 _index_set_holder = std::forward<IndexSetHolderType>(other._index_set_holder);
195 _neighbors = std::forward<NeighborSetType>(other._neighbors);
196 _permutation = std::forward<MeshPermutationType>(other._permutation);
197
198 for(int i(0); i <= shape_dim; ++i)
199 {
200 _num_entities[i] = other.get_num_entities(i);
201 }
202
203 return *this;
204 }
205
207 ConformalMesh(const ConformalMesh&) = delete;
208
211
214 {
215 }
216
224 {
225 for(int i(0); i <= shape_dim; ++i)
226 this->_num_entities[i] = other._num_entities[i];
227 this->_vertex_set = other._vertex_set.clone();
228 this->_index_set_holder.clone(other._index_set_holder);
229 this->_neighbors = other._neighbors.clone();
230 this->_permutation.clone(other._permutation);
231 }
232
235 {
236 ConformalMesh mesh(this->_num_entities);
237 mesh._vertex_set = this->_vertex_set.clone();
238 mesh._index_set_holder.clone(this->_index_set_holder);
239 mesh._neighbors = this->_neighbors.clone();
240 mesh._permutation.clone(this->_permutation);
241 return mesh;
242 }
243
245 std::size_t bytes() const
246 {
247 return _vertex_set.bytes() + _index_set_holder.bytes() + _neighbors.bytes() + _permutation.bytes();
248 }
249
259 Index get_num_entities(int dim) const
260 {
261 XASSERT(dim >= 0);
262 XASSERT(dim <= shape_dim);
263 return _num_entities[dim];
264 }
265
271 {
272 return _num_entities[0];
273 }
274
280 {
281 return _num_entities[shape_dim];
282 }
283
289 bool is_permuted() const
290 {
291 return !this->_permutation.empty();
292 }
293
298 {
299 return this->_permutation;
300 }
301
320 {
321 // make sure that we don't already have a permutation
322 XASSERTM(this->_permutation.empty(), "mesh is already permuted!");
323
324 // create the permutation
325 this->_permutation.create(strategy, this->_index_set_holder, this->_vertex_set);
326
327 // permute vertex set
328 this->_vertex_set.permute(this->_permutation.get_perm(0));
329
330 // permute index sets
331 this->_index_set_holder.permute(this->_permutation.get_perms(), this->_permutation.get_inv_perms());
332
333 // rebuild neighbor index set
335 }
336
354 {
355 // make sure that we don't already have a permutation
356 XASSERTM(this->_permutation.empty(), "mesh is already permuted!");
357
358 // check the dimensions
359 XASSERTM(mesh_perm.validate_sizes(this->_num_entities) == 0, "mesh permutation has invalid size!");
360
361 // save the permutation
362 this->_permutation = std::forward<MeshPermutationType>(mesh_perm);
363
364 // permute vertex set
365 this->_vertex_set.permute(this->_permutation.get_perm(0));
366
367 // permute index sets
368 this->_index_set_holder.permute(this->_permutation.get_perms(), this->_permutation.get_inv_perms());
369
370 // rebuild neighbor index set
372 }
373
383 {
384 // no coloring?
385 const std::vector<Index>& coloring = this->get_mesh_permutation().get_element_coloring();
386 if(coloring.empty())
387 return true;
388
389 // get vertices-at-element index set
390 const auto& verts_at_elem = this->template get_index_set<shape_dim, 0>();
391
392 // render transpose
393 Adjacency::Graph elems_at_vert(Adjacency::RenderType::transpose, verts_at_elem);
394
395 // loop over all color blocks
396 for(std::size_t icol(0); icol+1u < coloring.size(); ++icol)
397 {
398 // get the bounds of our current color block
399 const Index iel_beg = coloring[icol];
400 const Index iel_end = coloring[icol+1u];
401
402 // loop over all elements in the current color block
403 for(Index iel(iel_beg); iel < iel_end; ++iel)
404 {
405 // loop over all vertices adjacent to this element
406 for(int ivt(0); ivt < verts_at_elem.num_indices; ++ivt)
407 {
408 // loop over all elements adjacent to this vertex
409 const Index ivtx = verts_at_elem(iel, ivt);
410 for(auto it = elems_at_vert.image_begin(ivtx); it != elems_at_vert.image_end(ivtx); ++it)
411 {
412 // two adjacent element must not be in the same color block
413 if((iel_beg <= *it) && (*it < iel_end) && (*it != iel))
414 return false; // invalid coloring
415 }
416 }
417 }
418 } // next color block
419
420 // ok, coloring is valid
421 return true;
422 }
423
433 {
434 // no layering?
435 const std::vector<Index>& layering = this->get_mesh_permutation().get_element_layering();
436 if(layering.empty())
437 return true;
438
439 // get vertices-at-element index set
440 const auto& verts_at_elem = this->template get_index_set<shape_dim, 0>();
441
442 // render transpose
443 Adjacency::Graph elems_at_vert(Adjacency::RenderType::transpose, verts_at_elem);
444
445 // loop over all layers
446 for(std::size_t ilay(0); ilay+1u < layering.size(); ++ilay)
447 {
448 // get the bounds of our current layer
449 const Index iel_beg = layering[ilay];
450 const Index iel_end = layering[ilay+1u];
451
452 // get the lower bound for valid neighbors of our current layer = beginning of previous layer
453 const Index iel_lower = layering[Math::max(ilay, std::size_t(1)) - 1u];
454
455 // get the upper bound for valid neighbors of our current layer = end of next layer
456 const Index iel_upper = layering[Math::min(ilay+2u, layering.size()-1u)];
457
458 // loop over all elements in the current layer
459 for(Index iel(iel_beg); iel < iel_end; ++iel)
460 {
461 // loop over all vertices adjacent to this element
462 for(int ivt(0); ivt < verts_at_elem.num_indices; ++ivt)
463 {
464 // loop over all elements adjacent to this vertex
465 const Index ivtx = verts_at_elem(iel, ivt);
466 for(auto it = elems_at_vert.image_begin(ivtx); it != elems_at_vert.image_end(ivtx); ++it)
467 {
468 // adjacent element outside of adjacent layers?
469 if(!((iel_lower <= *it) && (*it < iel_upper)))
470 return false; // invalid layer
471 }
472 }
473 }
474 } // next color block
475
476 // ok, layering is valid
477 return true;
478 }
479
482 {
483 // Facet at cell index set
484 auto& facet_idx = get_index_set<shape_dim, shape_dim -1>();
485
486 XASSERTM(get_num_entities(shape_dim-1) == facet_idx.get_index_bound(), "mesh num_entities / index_set num_entities mismatch");
487
488 if(_neighbors.get_num_indices() == Index(0))
490
491 Intern::FacetNeighbors::compute(_neighbors, facet_idx);
492 }
493
496 {
497 return _neighbors;
498 }
499
501 const typename IndexSet<shape_dim, shape_dim-1>::Type& get_neighbors() const
502 {
503 return _neighbors;
504 }
505
508 {
509 return _vertex_set;
510 }
511
514 {
515 return _vertex_set;
516 }
517
530 template<
531 int cell_dim_,
532 int face_dim_>
534 {
535 return _index_set_holder.template get_index_set_wrapper<cell_dim_>().template get_index_set<face_dim_>();
536 }
537
539 template<
540 int cell_dim_,
541 int face_dim_>
543 {
544 return _index_set_holder.template get_index_set_wrapper<cell_dim_>().template get_index_set<face_dim_>();
545 }
546
548 IndexSetHolderType& get_index_set_holder()
549 {
550 return _index_set_holder;
551 }
552
553 const IndexSetHolderType& get_index_set_holder() const
554 {
555 return _index_set_holder;
556 }
557
558 IndexSetHolderType* get_topology()
559 {
560 return &_index_set_holder;
561 }
562
563 const IndexSetHolderType* get_topology() const
564 {
565 return &_index_set_holder;
566 }
568
576 {
578 NumEntitiesExtractor<shape_dim>::set_num_entities(_index_set_holder, _num_entities);
579 this->fill_neighbors();
581 }
582
590 {
591 Geometry::FacetFlipper<ShapeType>::reorient(this->_index_set_holder);
592 }
593
620 void transform(const VertexType& origin, const VertexType& angles, const VertexType& offset)
621 {
622 _vertex_set.transform(origin, angles, offset);
623 }
624
630 static String name()
631 {
632 return "ConformalMesh<"+Shape_::name()+","+stringify(num_coords_)+">";
633 }
634 }; // class ConformalMesh<...>
635
636 /* ************************************************************************************************************* */
637
643 template<
644 typename Shape_,
645 int num_coords_,
646 typename CoordType_>
647 class Factory< ConformalMesh<Shape_, num_coords_, CoordType_> >
648 {
649 public:
652
657
658 public:
660 virtual ~Factory()
661 {
662 }
663
673 virtual Index get_num_entities(int dim) = 0;
674
681 virtual void fill_vertex_set(VertexSetType& vertex_set) = 0;
682
689 virtual void fill_index_sets(IndexSetHolderType& index_set_holder) = 0;
690
697 {
698 return MeshType(*this);
699 }
700
706 std::unique_ptr<MeshType> make_unique()
707 {
708 return std::unique_ptr<MeshType>(new MeshType(*this));
709 }
710 }; // class Factory<ConformalMesh<...>>
711
712 /* ************************************************************************************************************* */
713
719 template<
720 typename Shape_,
721 int num_coords_,
722 typename CoordType_>
723 class StandardRefinery<ConformalMesh<Shape_, num_coords_, CoordType_> > :
724 public Factory< ConformalMesh<Shape_, num_coords_, CoordType_> >
725 {
726 public:
735
737 static constexpr int shape_dim = ShapeType::dimension;
738
739 protected:
743 Index _num_entities_coarse[shape_dim + 1];
745 Index _num_entities_fine[shape_dim + 1];
746
747 public:
754 explicit StandardRefinery(const MeshType& coarse_mesh) :
755 _coarse_mesh(coarse_mesh)
756 {
757 // get number of entities in coarse mesh
758 for(int i(0); i <= shape_dim; ++i)
759 {
760 _num_entities_fine[i] = coarse_mesh.get_num_entities(i);
761 _num_entities_coarse[i] = coarse_mesh.get_num_entities(i);
762 }
763
764 // calculate number of entities in fine mesh
765 Intern::EntityCountWrapper<Intern::StandardRefinementTraits, ShapeType>::query(_num_entities_fine);
766 }
767
770 {
771 }
772
782 virtual Index get_num_entities(int dim) override
783 {
784 return _num_entities_fine[dim];
785 }
786
793 virtual void fill_vertex_set(VertexSetType& vertex_set) override
794 {
795 // refine vertices
796 Intern::StandardVertexRefineWrapper<ShapeType, VertexSetType>
797 ::refine(vertex_set, _coarse_mesh.get_vertex_set(), _coarse_mesh.get_index_set_holder());
798 }
799
806 virtual void fill_index_sets(IndexSetHolderType& index_set_holder) override
807 {
808 // refine indices
809 Intern::IndexRefineWrapper<ShapeType>
810 ::refine(index_set_holder, _num_entities_coarse, _coarse_mesh.get_index_set_holder());
811 }
812 }; // class StandardRefinery<ConformalMesh<...>,Nil>
813
814#ifdef FEAT_EICKT
815 extern template class ConformalMesh<Shape::Simplex<2>, 2, Real>;
816 extern template class ConformalMesh<Shape::Simplex<3>, 3, Real>;
817 extern template class ConformalMesh<Shape::Hypercube<2>, 2, Real>;
818 extern template class ConformalMesh<Shape::Hypercube<3>, 3, Real>;
819
820 extern template class StandardRefinery<ConformalMesh<Shape::Simplex<2>, 2, Real>>;
821 extern template class StandardRefinery<ConformalMesh<Shape::Simplex<3>, 3, Real>>;
822 extern template class StandardRefinery<ConformalMesh<Shape::Hypercube<2>, 2, Real>>;
823 extern template class StandardRefinery<ConformalMesh<Shape::Hypercube<3>, 3, Real>>;
824#endif // FEAT_EICKT
825 } // namespace Geometry
826} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Adjacency Graph implementation.
Definition: graph.hpp:34
ImageIterator image_begin(Index domain_node) const
Returns an iterator for the first adjacent image node.
Definition: graph.hpp:958
ImageIterator image_end(Index domain_node) const
Returns an iterator for the first position past the last adjacent image node.
Definition: graph.hpp:966
Conformal mesh class template.
bool validate_element_coloring() const
Validates the element coloring.
MeshPermutationType _permutation
mesh permutation (if permuted)
const MeshPermutationType & get_mesh_permutation() const
Returns a reference to the underlying mesh permutation object.
ConformalMesh(Factory< ConformalMesh > &factory)
Factory constructor.
Index get_num_entities(int dim) const
Returns the number of entities.
static constexpr int shape_dim
shape dimension
void transform(const VertexType &origin, const VertexType &angles, const VertexType &offset)
Applies a "proper rigid" transformation onto the mesh.
const VertexSetType & get_vertex_set() const
Returns a reference to the vertex set of the mesh.
IndexSet< shape_dim, shape_dim-1 >::Type & get_neighbors()
IndexSet< shape_dim, shape_dim-1 >::Type NeighborSetType
index set type for storing neighbor adjacency information
ConformalMesh(const Index num_entities[])
Constructor.
VertexSet< num_coords_, Coord_ > VertexSetType
Vertex set type.
ConformalMesh(ConformalMesh &&other)
move constructor
static constexpr bool is_structured
this mesh is not structured
ConformalMesh & operator=(const ConformalMesh &)=delete
delete copy-assign operator
static constexpr int world_dim
world dimension
Index get_num_elements() const
Returns the number of elements.
NeighborSetType _neighbors
Information about cells sharing a facet.
void deduct_topology_from_top()
Deducts the topology from the Vertex-At-Shape index set.
void create_permutation(PermutationStrategy strategy)
Creates a mesh permutation based on one of the standard permutation strategies.
const IndexSet< shape_dim, shape_dim-1 >::Type & get_neighbors() const
IndexSet< cell_dim_, face_dim_ >::Type & get_index_set()
Returns the reference to an index set.
ConformalMesh & operator=(ConformalMesh &&other)
move-assignment operator
VertexSetType _vertex_set
the vertex set of the mesh
IndexSetHolder< ShapeType > IndexSetHolderType
index set holder type
MeshPermutation< ShapeType > MeshPermutationType
mesh permutation type
Coord_ CoordType
Coordinate type.
bool is_permuted() const
Checks whether the mesh is permuted.
void set_permutation(MeshPermutationType &&mesh_perm)
Sets a custom mesh permutation for this mesh.
VertexSetType::VertexType VertexType
Vertex type.
void reorient_boundary_facets()
Ensures that all boundary facets are positively oriented.
virtual ~ConformalMesh()
virtual destructor
const IndexSet< cell_dim_, face_dim_ >::Type & get_index_set() const
Returns the reference to an index set.
static String name()
Returns the name of the class.
void clone(const ConformalMesh &other)
Clones another conformal mesh object into this object.
bool validate_element_layering() const
Validates the element layering.
Index get_num_vertices() const
Returns the number of vertices.
ConformalMesh(const ConformalMesh &)=delete
delete copy constructor
ConformalMesh clone() const
Index _num_entities[shape_dim+1]
number of entities for each shape dimension
IndexSetHolderType _index_set_holder
the index sets of the mesh
VertexSetType & get_vertex_set()
Returns a reference to the vertex set of the mesh.
void fill_neighbors()
Fills the neighbor index set.
static void reorient(IndexSetHolder< Shape_ > &ish)
Reorients the boundary facets in the index set holder to be positive.
std::unique_ptr< MeshType > make_unique()
Creates a new mesh on the heap and returns a unique pointer to it.
virtual void fill_index_sets(IndexSetHolderType &index_set_holder)=0
Fills the index sets.
ConformalMesh< Shape_, num_coords_, CoordType_ > MeshType
mesh typedef
virtual Index get_num_entities(int dim)=0
Returns the number of entities.
virtual void fill_vertex_set(VertexSetType &vertex_set)=0
Fills the vertex set.
Mesh Factory class template.
Definition: factory.hpp:33
Conformal Index-Set class template.
Definition: index_set.hpp:82
Mesh permutation class template.
void clone(const MeshPermutation &other)
Clones another mesh permutation object into this object.
const std::vector< Index > & get_element_layering() const
Returns a const reference to the element layering vector.
const PermArray & get_perms() const
bool empty() const
Checks whether this permutation is empty.
const std::vector< Index > & get_element_coloring() const
Returns a const reference to the element coloring vector.
void create(PermutationStrategy strategy, const IndexSetHolder< Shape_ > &ish, const VertexSet< num_coords_, Coord_ > &vtx)
Creates a mesh permutation for a conformal mesh.
const Adjacency::Permutation & get_perm(int dim=shape_dim) const
Returns a const reference to a (forward) permutation.
static void compute(IndexSetHolder< Shape_ > &index_set_holder)
Routine that does the actual work.
ConformalMesh< Shape_, num_coords_, CoordType_ > MeshType
mesh type
virtual void fill_vertex_set(VertexSetType &vertex_set) override
Fills the vertex set of the refined mesh.
virtual void fill_index_sets(IndexSetHolderType &index_set_holder) override
Fills the index sets of the refined mesh.
virtual Index get_num_entities(int dim) override
Returns the number of entities of the refined mesh.
Standard Refinery class template.
Definition: factory.hpp:58
String class implementation.
Definition: string.hpp:46
Tiny Vector class template.
@ transpose
Render-Transpose mode.
PermutationStrategy
Mesh permutation strategy enumeration.
@ other
generic/other permutation strategy
T_ min(T_ a, T_ b)
Returns the minimum of two values.
Definition: math.hpp:123
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
FEAT namespace.
Definition: adjactor.hpp:12
double Real
Real data type.
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
std::uint64_t Index
Index data type.
Index set type class template.
FEAT::Geometry::IndexSet< Shape::FaceTraits< typename Shape::FaceTraits< ShapeType, cell_dim_ >::ShapeType, face_dim_ >::count > Type
index set type
Fixed-Sized Vertex Set class template.
Definition: vertex_set.hpp:37
static constexpr int num_coords
number of coordinates per vertex
Definition: vertex_set.hpp:42
void permute(const Adjacency::Permutation &perm, bool invert=false)
Applies a permutation onto this vertex set.
Definition: vertex_set.hpp:264
std::size_t bytes() const
Definition: vertex_set.hpp:145
VertexSet clone() const
Definition: vertex_set.hpp:127
void transform(const VertexType &origin, const VertexType &angles, const VertexType &offset)
Applies a "proper rigid" transformation onto the vertex set.
Definition: vertex_set.hpp:242
Face traits tag struct template.
Definition: shape.hpp:106