FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
template_builder.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
9#include <kernel/geometry/intern/congruency_mapping.hpp>
10#include <kernel/geometry/intern/congruency_sampler.hpp>
11#include <kernel/geometry/intern/congruency_trafo.hpp>
12#include <kernel/geometry/intern/face_index_mapping.hpp>
13#include <kernel/geometry/raw_refinement_templates.hpp>
14#include <kernel/geometry/refinement_types.hpp>
15#include <kernel/shape.hpp>
17#include <kernel/util/string.hpp>
18#include <kernel/util/tiny_algebra.hpp>
19
20#include <algorithm>
21#include <array>
22#include <cstdint>
23#include <unordered_map>
24#include <vector>
25#include <iostream>
26
27namespace FEAT::Geometry
28{
29 namespace Intern
30 {
34 template<typename Shape_>
35 constexpr int orientations()
36 {
37 if constexpr(std::is_same_v<Shape_, Shape::Hypercube<1>>)
38 {
39 return 2;
40 }
41
42 if constexpr(std::is_same_v<Shape_, Shape::Hypercube<2>>)
43 {
44 return 8;
45 }
46
47 return 0;
48 }
49
58 template<int n_>
59 bool is_same_vertex(const Tiny::Vector<Real, n_>& a, const Tiny::Vector<Real, n_>& b)
60 {
61 bool is_same = true;
62
63 const Real tol = Math::pow(Math::eps<Real>(), Real(0.7));
64 for(int i(0); i < n_; ++i)
65 {
66 if(Math::abs(a[i] - b[i]) > tol)
67 {
68 is_same = false;
69 }
70 }
71
72 return is_same;
73 }
74
88 template<typename Shape_, int num_coords_ = Shape_::dimension>
89 bool is_same_raw_entity(const RawEntity<Shape_, num_coords_>& a, const RawEntity<Shape_, num_coords_>& b)
90 {
91 return std::is_permutation(a.coords.begin(), a.coords.end(), b.coords.begin(), Intern::is_same_vertex<num_coords_>);
92 }
93
102 template<typename Shape_, int num_coords_ = Shape_::dimension>
103 std::vector<Tiny::Vector<Real, num_coords_>> all_vertices(const std::vector<RawEntity<Shape_, num_coords_>>& entities)
104 {
105 std::vector<Tiny::Vector<Real, num_coords_>> vertices;
106
107 for(const auto& entity : entities)
108 {
109 for(const auto& vertex : entity.coords)
110 {
111 vertices.push_back(vertex);
112 }
113 }
114
115 return vertices;
116 }
117
129 template<int n_>
130 bool is_internal_vertex(Tiny::Vector<Real, n_> vertex)
131 {
132 const Real tol = Math::pow(Math::eps<Real>(), Real(0.7));
133
134 // A vertex is internal if all its coordinates are in (0, 1)
135 bool is_internal = true;
136 for(int i(0); i < n_; ++i)
137 {
138 if(vertex[i] < tol || (1 - tol) < vertex[i])
139 {
140 is_internal = false;
141 }
142 }
143 return is_internal;
144 }
145
158 template<typename Shape_, int num_coords_ = Shape_::dimension>
159 bool is_internal_entity(const RawEntity<Shape_, num_coords_>& entity)
160 {
161 Tiny::Vector<Real, num_coords_> centroid(0);
162 for(const auto& vertex : entity.coords)
163 {
164 centroid += vertex;
165 }
166 return is_internal_vertex((1.0 / entity.coords.size()) * centroid);
167 }
168
170 template<typename T_, typename Comp>
171 std::vector<T_> deduplicate(Comp comparison, const std::vector<T_>& list)
172 {
173 std::vector<T_> deduplicated;
174 for(const T_& current : list)
175 {
176 auto pred = [&](T_& t) { return comparison(current, t); };
177 bool is_new = !std::any_of(deduplicated.begin(), deduplicated.end(), pred);
178 if(is_new)
179 {
180 deduplicated.push_back(current);
181 }
182 }
183 return deduplicated;
184 }
185
187 template<typename T_, typename Predicate_>
188 std::vector<T_> filter(Predicate_ predicate, const std::vector<T_>& list)
189 {
190 std::vector<T_> filtered;
191 for(const T_& current : list)
192 {
193 if(predicate(current))
194 {
195 filtered.push_back(current);
196 }
197 }
198 return filtered;
199 }
200
202 template<typename Shape_>
203 std::vector<Tiny::Vector<Real, Shape_::dimension>> internal_vertices(const RawTemplate<Shape_>& tmplt)
204 {
205 std::vector<Tiny::Vector<Real, Shape_::dimension>> vertices;
206
207 for(const auto& entity : tmplt.entities)
208 {
209 for(const auto& vertex : entity.coords)
210 {
211 vertices.push_back(vertex);
212 }
213 }
214
215 vertices = filter([](auto vertex) { return is_internal_vertex(vertex); }, vertices);
216 vertices = deduplicate([](auto a, auto b) { return Intern::is_same_vertex(a, b); }, vertices);
217
218 return vertices;
219 }
220
222 template<typename Shape_, int face_dim_, int num_coords_ = Shape_::dimension>
223 std::vector<RawEntity<typename Shape::FaceTraits<Shape_, face_dim_>::ShapeType, num_coords_>>
224 internal_entities(const std::vector<RawEntity<Shape_, num_coords_>>& entities)
225 {
226 if constexpr(Shape_::dimension == face_dim_)
227 {
228 return entities;
229 }
230 else
231 {
232 static constexpr const int faces_per_entity = Shape::FaceTraits<Shape_, face_dim_>::count;
233
234 std::vector<RawEntity<typename Shape::FaceTraits<Shape_, face_dim_>::ShapeType, num_coords_>> result;
235
236 for(const auto& entity : entities)
237 {
238 for(int i(0); i < faces_per_entity; ++i)
239 {
240 result.push_back(entity.template face<face_dim_>(i));
241 }
242 }
243
244 result = filter([](auto& entity) { return is_internal_entity(entity); }, result);
245 result = deduplicate([](auto& a, auto& b) { return Intern::is_same_raw_entity(a, b); }, result);
246
247 return result;
248 }
249 }
250
252 template<typename Shape_>
253 static Tiny::Vector<Real, Shape_::dimension>
254 orient_vertex(const Tiny::Vector<Real, Shape_::dimension>& vertex, int orientation)
255 {
256 static constexpr int num_coords = Shape_::dimension;
257 using Trafo = Intern::CongruencyTrafo<Shape_>;
258
259 Tiny::Vector<Real, num_coords> offset(0.5);
260
261 Tiny::Matrix<Real, num_coords, num_coords> transform(0.0);
262 Tiny::Vector<Real, num_coords> unused(0.0);
263 Trafo::compute(transform, unused, orientation);
264
265 Tiny::Vector<Real, num_coords> result;
266 result.set_mat_vec_mult(transform, (vertex - offset));
267
268 return result + offset;
269 }
270
272 template<typename Shape_, int num_coords_ = Shape_::dimension>
273 static RawEntity<Shape_, num_coords_> orient_raw_entity(const RawEntity<Shape_, num_coords_>& entity, int orientation)
274 {
275 RawEntity<Shape_, num_coords_> result;
276 for(int i(0); i < entity.coords.size(); i++)
277 {
278 result.coords[i] = Intern::orient_vertex<Shape_>(entity.coords[i], orientation);
279 }
280 }
281
282
293 template<typename Shape_, int source_dim_>
295 {
296 };
297
299 template<>
300 struct VertexEmbedder<Shape::Quadrilateral, 1>
301 {
304
312 static TargetVertex embed(int elem, const SourceVertex& vertex)
313 {
314 switch(elem)
315 {
316 case 0:
317 return Tiny::Vector<Real, 2>{vertex[0], 0.0};
318 case 1:
319 return Tiny::Vector<Real, 2>{vertex[0], 1.0};
320 case 2:
321 return Tiny::Vector<Real, 2>{0.0, vertex[0]};
322 case 3:
323 return Tiny::Vector<Real, 2>{1.0, vertex[0]};
324 default:
325 XABORTM("Invalid face-edge index.");
326 }
327 }
328 };
329
331 template<>
332 struct VertexEmbedder<Shape::Hexahedron, 1>
333 {
336
344 static TargetVertex embed(int elem, const SourceVertex& vertex)
345 {
346 switch(elem)
347 {
348 case 0:
349 return Tiny::Vector<Real, 3>{vertex[0], 0.0, 0.0};
350 case 1:
351 return Tiny::Vector<Real, 3>{vertex[0], 1.0, 0.0};
352 case 2:
353 return Tiny::Vector<Real, 3>{vertex[0], 0.0, 1.0};
354 case 3:
355 return Tiny::Vector<Real, 3>{vertex[0], 1.0, 1.0};
356 case 4:
357 return Tiny::Vector<Real, 3>{0.0, vertex[0], 0.0};
358 case 5:
359 return Tiny::Vector<Real, 3>{1.0, vertex[0], 0.0};
360 case 6:
361 return Tiny::Vector<Real, 3>{0.0, vertex[0], 1.0};
362 case 7:
363 return Tiny::Vector<Real, 3>{1.0, vertex[0], 1.0};
364 case 8:
365 return Tiny::Vector<Real, 3>{0.0, 0.0, vertex[0]};
366 case 9:
367 return Tiny::Vector<Real, 3>{1.0, 0.0, vertex[0]};
368 case 10:
369 return Tiny::Vector<Real, 3>{0.0, 1.0, vertex[0]};
370 case 11:
371 return Tiny::Vector<Real, 3>{1.0, 1.0, vertex[0]};
372 default:
373 XABORTM("Invalid cell-edge index.");
374 }
375 }
376 };
377
379 template<>
380 struct VertexEmbedder<Shape::Hexahedron, 2>
381 {
384
392 static TargetVertex embed(int elem, const SourceVertex& vertex)
393 {
394 switch(elem)
395 {
396 case 0:
397 return Tiny::Vector<Real, 3>{vertex[0], vertex[1], 0.0};
398 case 1:
399 return Tiny::Vector<Real, 3>{vertex[0], vertex[1], 1.0};
400 case 2:
401 return Tiny::Vector<Real, 3>{vertex[0], 0.0, vertex[1]};
402 case 3:
403 return Tiny::Vector<Real, 3>{vertex[0], 1.0, vertex[1]};
404 case 4:
405 return Tiny::Vector<Real, 3>{0.0, vertex[0], vertex[1]};
406 case 5:
407 return Tiny::Vector<Real, 3>{1.0, vertex[0], vertex[1]};
408 default:
409 XABORTM("Invalid cell-edge index.");
410 }
411 }
412 };
413
415 template<typename Shape_>
416 std::array<Tiny::Vector<Real, Shape_::dimension>, Shape::FaceTraits<Shape_, 0>::count> topology_vertices()
417 {
418 static constexpr int num_coords = Shape_::dimension;
419 static constexpr int num_vertices = Shape::FaceTraits<Shape_, 0>::count;
420
421 std::array<Tiny::Vector<Real, num_coords>, num_vertices> vertices;
422
423 for(int i(0); i < num_vertices; i++)
424 {
425 // Build topology vertex from reference cell
427 for(int j(0); j < num_coords; ++j)
428 {
429 vertex[j] = 0.5 * (Shape::ReferenceCell<Shape_>::template vertex<Real>(i, j) + 1.0);
430 }
431 vertices[i] = vertex;
432 }
433
434 return vertices;
435 }
436
437 } // namespace Intern
438
440 // Refinement template data types
442
449 enum class EntitySource : std::uint8_t
450 {
452 Sibling,
455 };
456
458 inline std::ostream& operator<<(std::ostream& stream, EntitySource source)
459 {
460 static std::unordered_map<EntitySource, String> mapping{
461 {EntitySource::ParentTopology, "EntitySource::ParentTopology"},
462 {EntitySource::Sibling, "EntitySource::Sibling"},
463 {EntitySource::BoundaryEdge, "EntitySource::BoundaryEdge"},
464 {EntitySource::BoundaryFace, "EntitySource::BoundaryFace"},
465 };
466 stream << mapping[source];
467 return stream;
468 }
469
476 {
486
487 EntityReference() = default;
488 EntityReference(EntitySource s, Index i, int o, int e) : source(s), index(i), orientation(o), entity(e)
489 {
490 }
491
492 // Equals operator for EntityReferences
493 bool operator==(const EntityReference& rhs) const
494 {
495 return (source == rhs.source) && (index == rhs.index) && (orientation == rhs.orientation) &&
496 (entity == rhs.entity);
497 }
498
499 // Not-equals operator for EntityReferences
500 bool operator!=(const EntityReference& rhs) const
501 {
502 return !(*this == rhs);
503 }
504 };
505
507 inline std::ostream& operator<<(std::ostream& stream, const EntityReference& reference)
508 {
509 stream << "EntityReference {"
510 << "source: " << reference.source << ", index: " << stringify(reference.index)
511 << ", orientation: " << stringify(reference.orientation) << ", entity: " << stringify(reference.entity)
512 << "}";
513 return stream;
514 }
515
525 template<typename Shape_, int reference_dim_ = Shape_::dimension - 1>
526 struct TopologyTemplate : TopologyTemplate<Shape_, reference_dim_ - 1>
527 {
530
532 std::array<EntityReference, num_entities> references;
533
539 template<int dim_>
540 std::array<EntityReference, Shape::FaceTraits<Shape_, dim_>::count>& get_references()
541 {
543 }
544
550 template<int dim_>
551 const std::array<EntityReference, Shape::FaceTraits<Shape_, dim_>::count>& get_references() const
552 {
554 }
555
556 template<int dim_>
557 EntityReference get_reference(int idx) const
558 {
560 }
561 };
562
574 template<typename Shape_>
575 struct TopologyTemplate<Shape_, 0>
576 {
579
581 std::array<EntityReference, num_entities> references;
582
588 template<int dim_>
589 std::array<EntityReference, num_entities>& get_references()
590 {
591 static_assert(dim_ == 0, "invalid reference dimension");
592 return references;
593 }
594
600 template<int dim_>
601 const std::array<EntityReference, num_entities>& get_references() const
602 {
603 static_assert(dim_ == 0, "invalid reference dimension");
604 return references;
605 }
606
607 template<int dim_>
608 EntityReference get_reference(Index idx) const
609 {
611 }
612 };
613
625 template<typename Shape_, typename CoShape_ = Shape_>
627 : RefinementTemplate<Shape_, typename Shape::FaceTraits<CoShape_, CoShape_::dimension - 1>::ShapeType>
628 {
630 template<int dim_>
632
639 std::vector<TopologyTemplate<CoShape_>> topologies;
640
646 template<int dim_>
647 std::vector<TopologyTemplateByDim<dim_>>& get_topologies()
648 {
649 using QueryShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
651 }
652
658 template<int dim_>
659 const std::vector<TopologyTemplateByDim<dim_>>& get_topologies() const
660 {
661 using QueryShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
663 }
664
670 template<int dim_>
672 {
673 if constexpr(dim_ > Shape_::dimension)
674 {
675 return 0;
676 }
677 else if constexpr(dim_ > 0 && dim_ <= Shape_::dimension)
678 {
679 using QueryShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
681 }
682 else
683 {
684 using QueryShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
686 }
687 }
688 };
689
701 template<typename Shape_>
702 struct RefinementTemplate<Shape_, Shape::Vertex>
703 {
705 static constexpr int num_coefficients = Shape::FaceTraits<Shape_, 0>::count;
706
708 std::vector<Tiny::Vector<Real, Shape_::dimension>> vertices;
710 std::vector<std::array<Real, num_coefficients>> vertex_coefficients;
711
713 std::vector<Tiny::Vector<Real, Shape_::dimension>>& get_vertices()
714 {
715 return vertices;
716 }
717
719 const std::vector<Tiny::Vector<Real, Shape_::dimension>>& get_vertices() const
720 {
721 return vertices;
722 }
723
725 std::vector<std::array<Real, num_coefficients>>& get_vertex_coefficients()
726 {
727 return vertex_coefficients;
728 }
729
731 const std::vector<std::array<Real, num_coefficients>>& get_vertex_coefficients() const
732 {
733 return vertex_coefficients;
734 }
735
741 template<int dim_>
743 {
744 static_assert(dim_ == 0);
745
746 return vertices.size();
747 }
748 };
749
783 {
785 std::vector<std::pair<Index, int>> _mapping;
786
787 public:
789 std::pair<Index, int> operator()(Index idx) const
790 {
791 return _mapping.at(idx);
792 }
793
795 std::vector<std::pair<Index, int>>& get_mapping()
796 {
797 return _mapping;
798 }
799
801 const std::vector<std::pair<Index, int>>& get_mapping() const
802 {
803 return _mapping;
804 }
805 };
806
812 template<typename RawData_, typename Shape_, int dim_ = Shape_::dimension>
813 struct OrientationMappingWrapper : public OrientationMappingWrapper<RawData_, Shape_, dim_ - 1>
814 {
815 static constexpr int num_orientations = Intern::orientations<Shape_>();
816
817 template<typename S>
818 using RefinementTypeByShape = typename RawData_::template RefinementTypeByShape<S>;
819
820 std::unordered_map<RefinementTypeByShape<Shape_>, std::array<OrientationMapping, num_orientations>> mappings = {};
821
822 template<int n_>
823 OrientationMapping& get_mapping(RefinementTypeByShape<Shape_> type, int orientation)
824 {
825 static_assert(n_ <= dim_);
826
827 ASSERT(orientation < num_orientations);
828
830 if(mappings_n.find(type) == mappings_n.end())
831 {
832 mappings_n[type] = {};
833 }
834
835 return mappings_n.at(type)[orientation];
836 }
837
838 template<int n_>
839 const OrientationMapping& get_mapping(RefinementTypeByShape<Shape_> type, int orientation) const
840 {
841 static_assert(n_ <= dim_);
842
843 ASSERT(mappings.find(type) != mappings.end());
844 ASSERT(orientation < num_orientations);
845
847 return mappings_n.at(type)[orientation];
848 }
849 };
850
857 template<typename RawData_, typename Shape_>
858 struct OrientationMappingWrapper<RawData_, Shape_, 0>
859 {
860 static constexpr int num_orientations = Intern::orientations<Shape_>();
861
862 template<typename S>
863 using RefinementTypeByShape = typename RawData_::template RefinementTypeByShape<S>;
864
865 std::unordered_map<RefinementTypeByShape<Shape_>, std::array<OrientationMapping, num_orientations>> mappings = {};
866
867 template<int n_>
868 OrientationMapping& get_mapping(RefinementTypeByShape<Shape_> type, int orientation)
869 {
870 static_assert(n_ == 0);
871
872 ASSERT(mappings.find(type) != mappings.end());
873 ASSERT(orientation < num_orientations);
874
876 }
877
878 template<int n_>
879 const OrientationMapping& get_mapping(RefinementTypeByShape<Shape_> type, int orientation) const
880 {
881 static_assert(n_ == 0);
882
883 ASSERT(mappings.find(type) != mappings.end());
884 ASSERT(orientation < num_orientations);
885
887 }
888 };
889
895 template<typename RawData_, typename Shape_>
897 : OrientationMappingHolder<RawData_, typename Shape::FaceTraits<Shape_, Shape_::dimension - 1>::ShapeType>
898 {
900
901 template<int dim_>
902 using RefinementTypeByDim = typename RawData_::template RefinementTypeByDim<dim_>;
903
904 template<int dim_, int codim_>
906 get_mapping(RefinementTypeByDim<dim_> type, int orientation)
907 {
908 using DimShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
909 return OrientationMappingHolder<RawData_, DimShape>::wrapper.template get_mapping<codim_>(
910 type,
911 orientation);
912 }
913
914 template<int dim_, int codim_>
915 const OrientationMapping&
916 get_mapping(RefinementTypeByDim<dim_> type, int orientation) const
917 {
918 using DimShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
919 return OrientationMappingHolder<RawData_, DimShape>::wrapper.template get_mapping<codim_>(
920 type,
921 orientation);
922 }
923 };
924
931 template<typename RawData_>
932 struct OrientationMappingHolder<RawData_, Shape::Vertex>
933 {
934 };
935
942 template<typename Shape_, int num_coords_>
944 {
947
950
953 {
954 }
955 };
956
958 template<typename Shape_, int num_coords_>
959 std::ostream& operator<<(std::ostream& stream, const EntitySearchEntry<Shape_, num_coords_>& entry)
960 {
961 stream << "EntitySearchEntry<" << Shape_::name() << ", " << num_coords_ << "> { raw_entity: " << entry.raw_entity
962 << ", reference: " << entry.reference << " }";
963 return stream;
964 }
965
980 template<typename Shape_, int num_coords_ = Shape_::dimension>
982 : public TemplateSearchSpace<typename Shape::FaceTraits<Shape_, Shape_::dimension - 1>::ShapeType, num_coords_>
983 {
984 public:
986 using ShapeType = Shape_;
987
990 static const constexpr int num_coords = num_coords_;
991
993 using BaseClass =
994 TemplateSearchSpace<typename Shape::FaceTraits<Shape_, Shape_::dimension - 1>::ShapeType, num_coords_>;
995
997 template<int dim_>
999
1001 template<int dim_>
1003
1005 template<int dim_>
1006 std::vector<EntryByDim<dim_>>& entries()
1007 {
1008 static_assert(dim_ <= Shape_::dimension);
1009 static_assert(dim_ >= 0);
1010
1011 using DimShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
1013 }
1014
1016 template<int dim_>
1017 const std::vector<EntryByDim<dim_>>& entries() const
1018 {
1019 static_assert(dim_ <= Shape_::dimension);
1020 static_assert(dim_ >= 0);
1021
1022 using DimShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
1024 }
1025
1036 template<typename Shape__>
1038 {
1040 }
1041
1052 template<typename Shape__>
1054 {
1056 }
1057
1067 template<typename EntityShape_, int dim_ = EntityShape_::dimension>
1068 void add_boundary_entity(int parent_index, const RawTemplate<EntityShape_>& tmplt)
1069 {
1070 static_assert(EntityShape_::dimension <= ShapeType::dimension);
1071
1072 using DimShape = typename Shape::FaceTraits<EntityShape_, dim_>::ShapeType;
1074
1075 static constexpr int num_vertices = Shape::FaceTraits<DimShape, 0>::count;
1076
1077 EntitySource source = EntityShape_::dimension == 1 ? EntitySource::BoundaryEdge : EntitySource::BoundaryFace;
1078
1079 if constexpr(dim_ == 0)
1080 {
1081 auto& vertices = this->template entries<0>();
1082 Index vertex_index = 0;
1083 for(const auto& vertex : Intern::internal_vertices(tmplt))
1084 {
1085 RawEntity<Shape::Vertex, num_coords> entity(Embedder::embed(parent_index, vertex));
1086 vertices.emplace_back(entity, EntityReference{source, vertex_index++, 0, parent_index});
1087 }
1088 }
1089 else
1090 {
1091 add_boundary_entity<EntityShape_, dim_ - 1>(parent_index, tmplt);
1092
1093 auto& entries = this->template entries<dim_>();
1094
1095 // Add internal elements of dimension dim_ to search space
1096 Index idx = 0;
1097 for(const auto& entity : Intern::internal_entities<EntityShape_, dim_>(tmplt.entities))
1098 {
1100
1101 for(int i(0); i < num_vertices; i++)
1102 {
1103 embedded.coords[i] = Embedder::embed(parent_index, entity.coords[i]);
1104 }
1105 entries.emplace_back(embedded, EntityReference{source, idx++, 0, parent_index});
1106 }
1107 }
1108 }
1109
1117 template<int dim_ = ShapeType::dimension - 1>
1119 {
1120 static constexpr int num_vertices = Shape::FaceTraits<ShapeType, 0>::count;
1121
1122 std::array<Tiny::Vector<Real, num_coords>, num_vertices> vertices = Intern::topology_vertices<ShapeType>();
1123 _add_topology_rec(vertices);
1124 }
1125
1126
1127 protected:
1129 template<int dim_ = ShapeType::dimension - 1>
1132 {
1133 if constexpr(dim_ == 0)
1134 {
1135 static constexpr int num_vertices = Shape::FaceTraits<ShapeType, 0>::count;
1136
1137 auto& entries = this->template entries<0>();
1138
1139 for(int vertex(0); vertex < num_vertices; vertex++)
1140 {
1142 entity.coords[0] = vertices[vertex];
1143 entries.emplace_back(entity, EntityReference{EntitySource::ParentTopology, static_cast<Index>(vertex), 0, 0});
1144 }
1145 }
1146 else
1147 {
1148 using FaceShape = typename Shape::FaceTraits<ShapeType, dim_>::ShapeType;
1149 using FaceMapping = Intern::FaceIndexMapping<ShapeType, dim_, 0>;
1150
1151 static constexpr int num_faces = Shape::FaceTraits<ShapeType, dim_>::count;
1152 static constexpr int num_vertices = Shape::FaceTraits<FaceShape, 0>::count;
1153
1154 auto& entries = this->template entries<dim_>();
1155 for(int face(0); face < num_faces; face++)
1156 {
1158
1159 for(int vertex(0); vertex < num_vertices; vertex++)
1160 {
1161 entity.coords[vertex] = vertices[FaceMapping::map(face, vertex)];
1162 }
1163 entries.emplace_back(entity, EntityReference{EntitySource::ParentTopology, static_cast<Index>(face), 0, 0});
1164 }
1165
1166 _add_topology_rec<dim_ - 1>(vertices);
1167 }
1168 }
1169
1172 {
1173 auto comp = [&](auto entry) { return Intern::is_same_raw_entity(entry.raw_entity, entity); };
1174 auto it = std::find_if(_entries.begin(), _entries.end(), comp);
1175
1176 if(it == _entries.end())
1177 {
1178 std::cout << "Searching for entity " << entity << "\n";
1179 XABORTM("Entity not in search space");
1180 }
1181
1182 // We found a valid reference. Next we need to determine the orientation of entity,
1183 // as compared to the found reference.
1184 // Because the CongurencySampler can not directly compare vertices, we produce index-lists here.
1185 using CongruencySampler = Intern::CongruencySampler<Shape_>;
1186
1187 int orientation = CongruencySampler::compare_with(entity.coords.data(), it->raw_entity.coords.data(), Intern::is_same_vertex<num_coords_>);
1188 EntityReference ref = it->reference;
1189
1190 ref.orientation = orientation;
1191
1192 if constexpr(num_coords_ < 3)
1193 {
1194 // 3D or less templates should not produce boundary face references
1196 }
1197
1198 return ref;
1199 }
1200
1203 {
1204 _entries.push_back({entity, EntityReference{EntitySource::Sibling, idx, 0, 0}});
1205 }
1206
1208 std::vector<Entry> _entries;
1209 };
1210
1218 template<int num_coords_>
1220 {
1221 public:
1224
1227
1229 static const constexpr int num_coords = num_coords_;
1230
1232 template<int dim_>
1233 std::vector<Entry>& entries()
1234 {
1235 static_assert(dim_ == 0);
1236 return _entries;
1237 }
1238
1240 template<int dim_>
1241 const std::vector<Entry>& entries() const
1242 {
1243 static_assert(dim_ == 0);
1244
1245 return _entries;
1246 }
1247
1259 {
1260 for(const auto& entry : _entries)
1261 {
1262 if(Intern::is_same_vertex(vertex, entry.raw_entity.coords[0]))
1263 {
1264 return entry.reference;
1265 }
1266 }
1267 std::cout << "Vertex: " << vertex << " not found\n";
1268 XABORTM("Vertex not in search space");
1269 }
1270
1282 {
1283 _entries.push_back(
1285 }
1286
1295 {
1296 for(const auto& entry : _entries)
1297 {
1298 if(entry.reference == reference)
1299 {
1300 return entry.raw_entity.coords[0];
1301 }
1302 }
1303 XABORTM("EntifyReference not in search space!");
1304 }
1305
1307 std::vector<Entry> _entries;
1308 };
1309
1310
1321 template<class RawData_>
1323 {
1325 using MaxShape = typename RawData_::MaxShape;
1326
1328 template<int dim_>
1329 using RawTemplateMapByDim = typename RawData_::template TemplateMapByDim<dim_>;
1330
1332 using RawEdgeMap = typename RawData_::EdgeMap;
1334 using RawFaceMap = typename RawData_::FaceMap;
1336 using RawCellMap = typename RawData_::CellMap;
1337
1339 template<int dim_>
1340 using RefinementTypeByDim = typename RawData_::template RefinementTypeByDim<dim_>;
1341
1343 template<int dim_>
1345
1347 template<int dim_>
1348 using TemplateMapByDim = std::unordered_map<RefinementTypeByDim<dim_>, RefinementTemplate<Shape::Hypercube<dim_>>>;
1349
1356
1358 EdgeMap _edge_templates = {};
1360 FaceMap _face_templates = {};
1362 CellMap _cell_templates = {};
1363
1366
1368 std::array<std::array<std::uint64_t, 2>, 4> _edge_type_adjustments = {};
1370 std::array<std::array<std::uint64_t, 4>, 16> _face_type_adjustments = {};
1372 std::array<std::array<std::uint64_t, 8>, 256> _cell_type_adjustments = {};
1373
1375 std::array<bool, 4> _type_adjustment_initialized = {false, false, false, false};
1376
1379 {
1380 if(_edge_templates.empty())
1381 {
1382 _edge_templates = _build<1>(RawData_::raw_edges());
1383 }
1384 return _edge_templates;
1385 }
1386
1389 {
1390 if(_face_templates.empty())
1391 {
1392 _face_templates = _build<2>(RawData_::raw_faces());
1393 }
1394 return _face_templates;
1395 }
1396
1399 {
1400 if(_cell_templates.empty())
1401 {
1402 _cell_templates = _build<3>(RawData_::raw_cells());
1403 }
1404 return _cell_templates;
1405 }
1406
1407 public:
1408 template<int dim_>
1409 const RefinementTemplateByDim<dim_>& get_template(RefinementTypeByDim<dim_> type)
1410 {
1411 if constexpr(dim_ == 1)
1412 {
1413 return edges().at(type);
1414 }
1415 else if constexpr(dim_ == 2)
1416 {
1417 return faces().at(type);
1418 }
1419 else if constexpr(dim_ == 3)
1420 {
1421 return cells().at(type);
1422 }
1423 XABORTM("Unsupported template dimension!");
1424 }
1425
1426 template<int dim_>
1427 bool has_template(RefinementTypeByDim<dim_> type)
1428 {
1429 if constexpr(dim_ == 1)
1430 {
1431 return edges().find(type) != edges().end();
1432 }
1433 else if constexpr(dim_ == 2)
1434 {
1435 return faces().find(type) != faces().end();
1436 }
1437 else if constexpr(dim_ == 3)
1438 {
1439 return cells().find(type) != cells().end();
1440 }
1441 XABORTM("Unsupported template dimension!");
1442 }
1443
1447 template<int dim_, int codim_>
1448 std::pair<Index, int> correct_for_orientation(RefinementTypeByDim<dim_> type, int orientation, Index idx)
1449 {
1450 return _orientation_mappings.template get_mapping<dim_, codim_>(type, orientation)(idx);
1451 }
1452
1453 /*
1454 * \brief Accessor for type adjustments.
1455 *
1456 * \tparam dim_ Dimension to retrieve adjustments for
1457 *
1458 * \param[in] type Current markings of a mesh element
1459 *
1460 * \returns An array containing a delta of subdivision levels.
1461 *
1462 * A template set does not necessarily contain templates for all possible
1463 * markings of a mesh element. In that case the AdaptiveMesh corrects the
1464 * markings during the creation of the final refinement field. This method
1465 * supplies the necessary corrections.
1466 *
1467 * \note The adjustments will only ever add subdivision levels.
1468 */
1469 template<int dim_>
1470 const std::array<std::uint64_t, Shape::FaceTraits<Shape::Hypercube<dim_>, 0>::count>&
1471 type_adjustment(Index type)
1472 {
1473 if constexpr(dim_ == 1)
1474 {
1475 if(!_type_adjustment_initialized[1])
1476 {
1477 _create_type_adjustments<Shape::Hypercube<dim_>>(edges());
1478 }
1479 return _edge_type_adjustments.at(type);
1480 }
1481 else if constexpr(dim_ == 2)
1482 {
1483 if(!_type_adjustment_initialized[2])
1484 {
1485 _create_type_adjustments<Shape::Hypercube<dim_>>(faces());
1486 }
1487 return _face_type_adjustments.at(type);
1488 }
1489 else if constexpr(dim_ == 3)
1490 {
1491 if(!_type_adjustment_initialized[3])
1492 {
1493 _create_type_adjustments<Shape::Hypercube<dim_>>(cells());
1494 }
1495 return _cell_type_adjustments.at(type);
1496 }
1497 XABORTM("Unsupported template dimension!");
1498 }
1499
1501 void stats()
1502 {
1503 std::array<Index, 4> maxima = {0, 0, 0, 0};
1504
1505 for(const auto& entry : edges())
1506 {
1507 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1508 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1509 }
1510 std::cout << "Edges:\n";
1511 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1512 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1513
1514 maxima = {0, 0, 0, 0};
1515 for(const auto& entry : faces())
1516 {
1517 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1518 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1519 maxima[2] = Math::max(maxima[2], entry.second.template num_entities<2>());
1520 }
1521 std::cout << "Faces:\n";
1522 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1523 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1524 std::cout << " Max Faces: " << stringify(unsigned(maxima[2])) << "\n";
1525
1526 maxima = {0, 0, 0, 0};
1527 for(const auto& entry : cells())
1528 {
1529 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1530 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1531 maxima[2] = Math::max(maxima[2], entry.second.template num_entities<2>());
1532 maxima[3] = Math::max(maxima[3], entry.second.template num_entities<3>());
1533 }
1534 std::cout << "Faces:\n";
1535 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1536 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1537 std::cout << " Max Faces: " << stringify(unsigned(maxima[2])) << "\n";
1538 std::cout << " Max Cells: " << stringify(unsigned(maxima[3])) << "\n";
1539 }
1540
1541 private:
1543 template<int n_>
1544 Index _find_vertex(const std::vector<Tiny::Vector<Real, n_>>& vertices, const Tiny::Vector<Real, n_>& vertex)
1545 {
1546 auto pred = [&](auto v) { return Intern::is_same_vertex(vertex, v); };
1547 return std::distance(vertices.begin(), std::find_if(vertices.begin(), vertices.end(), pred));
1548 }
1549
1551 template<int dim_>
1553 {
1554 if constexpr(dim_ == 1)
1555 {
1556 return _edge_type_adjustments;
1557 }
1558 else if constexpr(dim_ == 2)
1559 {
1560 return _face_type_adjustments;
1561 }
1562 else if constexpr(dim_ == 3)
1563 {
1564 return _cell_type_adjustments;
1565 }
1566 XABORTM("Unsupported template dimension!");
1567 }
1568
1580 template<typename TemplateShape_, typename TopologyShape_, int dim_ = TopologyShape_::dimension - 1>
1583 const TemplateSearchSpace<TemplateShape_>& search_space,
1585 {
1586 static constexpr int num_entities = Shape::FaceTraits<TopologyShape_, dim_>::count;
1587 if constexpr(dim_ == 0)
1588 {
1589 auto& vertex_refs = topo.template get_references<0>();
1590 for(int i(0); i < num_entities; i++)
1591 {
1592 vertex_refs[i] = search_space.search_vertex(raw_entity.coords[i]);
1593 }
1594 }
1595 else
1596 {
1597 auto& refs = topo.template get_references<dim_>();
1598 for(int i(0); i < num_entities; i++)
1599 {
1600 refs[i] = search_space.search(raw_entity.template face<dim_>(i));
1601 }
1602
1603 _build_topology<TemplateShape_, TopologyShape_, dim_ - 1>(raw_entity, search_space, topo);
1604 }
1605 }
1606
1617 template<typename TemplateShape_, int dim_ = TemplateShape_::dimension>
1619 const RawTemplate<TemplateShape_>& raw_template,
1622 {
1623 if constexpr(dim_ == 0)
1624 {
1625 for(const auto& vertex : Intern::internal_vertices(raw_template))
1626 {
1627 // Add vertex and its coefficients to template
1628 tmplt.get_vertices().push_back(vertex);
1629 tmplt.get_vertex_coefficients().push_back(Intern::vertex_coefficients<TemplateShape_>(vertex));
1630
1631 // Add entry to search space for building topologies later
1632 search_space.add_sibling_vertex(vertex, tmplt.get_vertices().size() - 1);
1633 }
1634 }
1635 else
1636 {
1637 _build_template<TemplateShape_, dim_ - 1>(raw_template, tmplt, search_space);
1638
1639 using TopologyShape = typename Shape::FaceTraits<TemplateShape_, dim_>::ShapeType;
1640
1641 auto& topologies = tmplt.template get_topologies<dim_>();
1642 for(const auto& entity : Intern::internal_entities<TemplateShape_, dim_>(raw_template.entities))
1643 {
1645 _build_topology<TemplateShape_, TopologyShape>(entity, search_space, topology);
1646 topologies.push_back(topology);
1647
1648 search_space.add_sibling(entity, topologies.size() - 1);
1649 }
1650 }
1651 }
1652
1692 template<typename TemplateShape_, int dim_ = TemplateShape_::dimension>
1695 const int orientation,
1696 const RefinementTemplate<TemplateShape_>& local_template,
1697 const TemplateSearchSpace<TemplateShape_>& local_search_space,
1698 const RefinementTemplate<TemplateShape_>& oriented_template,
1699 const TemplateSearchSpace<TemplateShape_>& oriented_search_space)
1700 {
1701
1703
1704 if constexpr(dim_ == 0)
1705 {
1706 OrientationMapping& vertex_mapping =
1707 _orientation_mappings.template get_mapping<TemplateShape_::dimension, 0>(oriented_type, orientation);
1708
1709 // For each vertex of the local template
1710 // * map it into the oriented frame of reference
1711 // * search for the corresponding vertex of the oriented template
1712 // * save the found index in the orientation mapping
1713 for(const VertexType& local_vertex : local_template.get_vertices())
1714 {
1715 VertexType oriented_vertex = Intern::orient_vertex<TemplateShape_>(local_vertex, orientation);
1716 Index mapped = _find_vertex(oriented_template.get_vertices(), oriented_vertex);
1717 vertex_mapping.get_mapping().emplace_back(mapped, 0);
1718 }
1719 }
1720 else
1721 {
1722 _fill_orientation_mappings<TemplateShape_, dim_ - 1>(
1723 oriented_type,
1724 orientation,
1725 local_template,
1726 local_search_space,
1727 oriented_template,
1728 oriented_search_space);
1729
1730 using CurrentShape = typename Shape::FaceTraits<TemplateShape_, dim_>::ShapeType;
1731 static constexpr int num_vertices = Shape::FaceTraits<CurrentShape, 0>::count;
1732
1733 OrientationMapping& mapping =
1734 _orientation_mappings.template get_mapping<TemplateShape_::dimension, dim_>(oriented_type, orientation);
1735
1736 for(const auto& local_topo : local_template.template get_topologies<dim_>())
1737 {
1738 // Collect local vertices from the search space
1739 std::array<VertexType, num_vertices> local = {};
1740
1741 const auto& local_refs = local_topo.template get_references<0>();
1742 for(int i(0); i < num_vertices; i++)
1743 {
1744 local[i] =
1745 Intern::orient_vertex<TemplateShape_>(local_search_space.vertex_by_reference(local_refs[i]), orientation);
1746 }
1747
1748 Index entity_idx = 0;
1749 for(const auto& oriented_topo : oriented_template.template get_topologies<dim_>())
1750 {
1751 // Collect oriented vertices from the oriented search space
1752 std::array<VertexType, num_vertices> oriented = {};
1753
1754 const auto& oriented_refs = oriented_topo.template get_references<0>();
1755 for(int i(0); i < num_vertices; i++)
1756 {
1757 oriented[i] = oriented_search_space.vertex_by_reference(oriented_refs[i]);
1758 }
1759
1760 // Compare local and oriented entities
1762 ent_local.coords = local;
1763
1765 ent_oriented.coords = oriented;
1766
1767 if(Intern::is_same_raw_entity(ent_local, ent_oriented))
1768 {
1769 // The entities are identical. This means local_topo and
1770 // oriented_topo are the same mesh element and we can save this
1771 // mapping in the orientation mapping. Additionally we can
1772 // pre-compute their relative orientation at this point, because
1773 // we know how both of these entities will be constructed in the
1774 // final mesh and how their parents are oriented relative to each
1775 // other.
1776 using CongruencySampler = Intern::CongruencySampler<CurrentShape>;
1777 int o = CongruencySampler::compare_with(
1778 ent_local.coords.data(),
1779 ent_oriented.coords.data(),
1780 Intern::is_same_vertex<TemplateShape_::dimension>);
1781
1782 mapping.get_mapping().emplace_back(entity_idx, o);
1783 break;
1784 }
1785 entity_idx++;
1786 }
1787 }
1788 }
1789 }
1790
1800 template<int dim_>
1802 {
1803 using TemplateShape = typename Shape::FaceTraits<Shape::Hypercube<dim_>, dim_>::ShapeType;
1804
1806
1807 // We require the full template search spaces to create orientation mappings with.
1808 std::unordered_map<RefinementTypeByDim<dim_>, TemplateSearchSpace<TemplateShape>> search_spaces;
1809
1810 for(const auto& entry : raw_templates)
1811 {
1813 TemplateSearchSpace<TemplateShape> search_space = _setup_search_space<Shape::Hypercube<dim_>>(entry.first);
1814
1815 _build_template(entry.second, tmplt, search_space);
1816
1817 result.insert({entry.first, tmplt});
1818 search_spaces.insert({entry.first, search_space});
1819 }
1820
1821 // We have now created all templates for this dimension.
1822 // Next, we create the corresponding orientation mappings.
1823
1824 // NOTE(mmuegge): _fill_orientation_mappings is fully dimension-generic,
1825 // apart from CongruencySamplers for higher dimensions. We thus disable
1826 // orientation mapping creation for all dimensions above 2
1827 if constexpr(dim_ <= 2)
1828 {
1829 for(const auto& entry : raw_templates)
1830 {
1831 RefinementTypeByDim<dim_> local_type = entry.first;
1832 auto& search_space = search_spaces[local_type];
1833
1834 for(int orientation = 0; orientation < Intern::orientations<Shape::Hypercube<dim_>>(); orientation++)
1835 {
1836 const RefinementTypeByDim<dim_> oriented_type = local_type.orient(orientation);
1837 auto& oriented_search_space = search_spaces[oriented_type];
1838
1839 const auto& local_tmplt = result.at(local_type);
1840 const auto& oriented_tmplt = result.at(oriented_type);
1841
1842 _fill_orientation_mappings<TemplateShape>(
1843 oriented_type,
1844 orientation,
1845 local_tmplt,
1846 search_space,
1847 oriented_tmplt,
1848 oriented_search_space);
1849 }
1850 }
1851 }
1852 return result;
1853 }
1854
1865 template<typename Shape_>
1867 {
1868 // Setup result.
1869 TemplateSearchSpace<Shape_> result = {};
1870
1871 // For faces and cells we also have to add the boundary edges and internal edges
1872 if constexpr(Shape_::dimension > 1)
1873 {
1874 static const constexpr int num_edges = Shape::FaceTraits<Shape_, 1>::count;
1875 for(int i(0); i < num_edges; ++i)
1876 {
1877 auto edge_type = type.template face_type<1>(i);
1878 result.add_boundary_entity(i, RawData_::raw_edges().at(edge_type));
1879 }
1880 }
1881
1882 // For cells, we have to add boundary faces and internal faces
1883 if constexpr(Shape_::dimension > 2)
1884 {
1885 static const constexpr int num_faces = Shape::FaceTraits<Shape_, 2>::count;
1886 for(int i(0); i < num_faces; ++i)
1887 {
1888 auto face_type = type.template face_type<2>(i);
1889 result.add_boundary_entity(i, RawData_::raw_faces().at(face_type));
1890 }
1891 }
1892
1893 result.add_topology();
1894
1895 return result;
1896 }
1897
1913 template<typename Shape_, typename TemplateMap_>
1914 void _create_type_adjustments(const TemplateMap_& available_templates)
1915 {
1916 auto& adjustments = type_adjustments<Shape_::dimension>();
1917
1918 static const constexpr int num_verts = Shape::FaceTraits<Shape_, 0>::count;
1919 for(Index type(0); type < (1 << num_verts); ++type)
1920 {
1921 auto type_marking = VertexMarking<Shape_>(type);
1922
1923 std::size_t closest_count = num_verts;
1924 auto closest_marking = VertexMarking<Shape_>::all_marked();
1925
1926 for(auto& entry : available_templates)
1927 {
1928 VertexMarking<Shape_> entry_marking(entry.first.to_vertex_marking());
1929
1930 // Is the current type a subtype of this type?
1931 if(!entry_marking.covers(type_marking))
1932 {
1933 continue;
1934 }
1935 std::size_t distance = type_marking.distance(entry_marking);
1936
1937 if(distance < closest_count)
1938 {
1939 closest_count = distance;
1940 closest_marking = entry_marking;
1941 }
1942 }
1943
1944 // Found the type that requires the least changes
1945 // Next, determine exact required changes
1946
1947 auto& adjustment = adjustments.at(type);
1948 for(int i(0); i < num_verts; ++i)
1949 {
1950 if(closest_marking.is_vertex_marked(i) && !type_marking.is_vertex_marked(i))
1951 {
1952 adjustment[i] = 1;
1953 }
1954 }
1955 }
1956 }
1957 };
1958} // namespace FEAT::Geometry
#define ASSERT(expr)
Debug-Assertion macro definition.
Definition: assertion.hpp:229
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
FEAT Kernel base header.
Mapping between different orientations of a refinement template.
std::pair< Index, int > operator()(Index idx) const
Apply operator.
const std::vector< std::pair< Index, int > > & get_mapping() const
Const accessor for full orientation mapping.
std::vector< std::pair< Index, int > > _mapping
Index -> Index mapping.
std::vector< std::pair< Index, int > > & get_mapping()
Accessor for full orientation mapping.
Constructs RefinementTemplates from RawTemplates.
TemplateMapByDim< dim_ > _build(const RawTemplateMapByDim< dim_ > &raw_templates)
Build all templates of a certain dimension.
TemplateMapByDim< 1 > EdgeMap
Map type from refinement types to edge templates.
std::pair< Index, int > correct_for_orientation(RefinementTypeByDim< dim_ > type, int orientation, Index idx)
Correct an index for orientation.
const EdgeMap & edges()
Edge-template accessor.
typename RawData_::template TemplateMapByDim< dim_ > RawTemplateMapByDim
Accessor for raw template maps.
TemplateSearchSpace< Shape_ > _setup_search_space(RefinementTypeByDim< Shape_::dimension > type) const
Helper function for creating a search space with boundary and topology entities.
typename RawData_::CellMap RawCellMap
Map type from refinement types to raw cell templates.
void _build_topology(const RawEntity< TopologyShape_, TemplateShape_::dimension > &raw_entity, const TemplateSearchSpace< TemplateShape_ > &search_space, TopologyTemplate< TopologyShape_ > &topo)
Constructs a TopologyTemplate for the given RawEntity.
typename RawData_::template RefinementTypeByDim< dim_ > RefinementTypeByDim
Accessor for refinement types.
typename RawData_::FaceMap RawFaceMap
Map type from refinement types to raw face templates.
const FaceMap & faces()
Face-template accessor.
void _create_type_adjustments(const TemplateMap_ &available_templates)
Calculate adjustments of the subdivision levels.
std::unordered_map< RefinementTypeByDim< dim_ >, RefinementTemplate< Shape::Hypercube< dim_ > > > TemplateMapByDim
Accessor for template map types.
TemplateMapByDim< 3 > CellMap
Map type from refinement types to cell templates.
typename RawData_::MaxShape MaxShape
Maximum shape supported by the raw data.
Index _find_vertex(const std::vector< Tiny::Vector< Real, n_ > > &vertices, const Tiny::Vector< Real, n_ > &vertex)
Determines the index of a vertex in a list of vertices.
void stats()
print some stats about maximum children in the raw data
void _build_template(const RawTemplate< TemplateShape_ > &raw_template, RefinementTemplate< TemplateShape_ > &tmplt, TemplateSearchSpace< TemplateShape_ > &search_space)
Constructs a RefinementTemplate from the given RawTemplate.
typename RawData_::EdgeMap RawEdgeMap
Map type from refinement types to raw edge templates.
auto & type_adjustments()
dim-based accessor for type adjustment arrays
TemplateMapByDim< 2 > FaceMap
Map type from refinement types to face templates.
void _fill_orientation_mappings(const RefinementTypeByDim< TemplateShape_::dimension > &oriented_type, const int orientation, const RefinementTemplate< TemplateShape_ > &local_template, const TemplateSearchSpace< TemplateShape_ > &local_search_space, const RefinementTemplate< TemplateShape_ > &oriented_template, const TemplateSearchSpace< TemplateShape_ > &oriented_search_space)
Fill orientation mappings for a given template.
const CellMap & cells()
Cell-template accessor.
EntityReference search_vertex(const Tiny::Vector< Real, num_coords > &vertex) const
Search for a vertex in this search space.
std::vector< Entry > _entries
Vector of search space entries.
Tiny::Vector< Real, num_coords_ > vertex_by_reference(const EntityReference &reference) const
Search for a vertex given a EntityReference.
std::vector< Entry > & entries()
Accessor for search space entries.
void add_sibling_vertex(const Tiny::Vector< Real, num_coords > &vertex, Index idx)
Add a sibling vertex to the search space.
const std::vector< Entry > & entries() const
Const accessor for search space entries.
Mapping between RawEntities and EntityReferences.
EntityReference _search(const RawEntity< Shape_, num_coords_ > &entity) const
Inner search logic for the current shape.
void add_boundary_entity(int parent_index, const RawTemplate< EntityShape_ > &tmplt)
Adds boundary entities to the search space.
std::vector< EntryByDim< dim_ > > & entries()
Accessor for search space entries.
void _add_sibling(const RawEntity< Shape_, num_coords_ > &entity, Index idx)
Inner add_sibling logic for the current shape.
void add_topology()
Adds topology entities to a TemplateSearchSpace.
const std::vector< EntryByDim< dim_ > > & entries() const
Const accessor for search space entries.
EntityReference search(const RawEntity< Shape__, num_coords_ > &entity) const
Search for a RawEntity in this search space.
std::vector< Entry > _entries
Vector of search space entries.
void _add_topology_rec(const std::array< Tiny::Vector< Real, num_coords >, Shape::FaceTraits< ShapeType, 0 >::count > &vertices)
Helper-function for add_topology_to_search_space.
void add_sibling(const RawEntity< Shape__, num_coords_ > &entity, Index idx)
Add a sibling entity to the search space.
Tiny Vector class template.
Geometry namespace.
EntitySource
Enumeration of possible entity sources.
@ BoundaryEdge
Entity is part of a boundary edge, i.e. a child of one of the parents edges.
@ ParentTopology
Entity is part of the parents topology.
@ BoundaryFace
Entity is part of a boundary face, i.e. a child of one of the parents faces.
@ Sibling
Entity is a sibling in the refinement tree.
T_ abs(T_ x)
Returns the absolute value.
Definition: math.hpp:275
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
Definition: math.hpp:643
T_ max(T_ a, T_ b)
Returns the maximum of two values.
Definition: math.hpp:137
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.
Reference to another local mesh entity.
EntitySource source
Where to retrieve the entity from.
int entity
Index of boundary entity to retrieve entity from. Only set for boundary entities.
int orientation
Orientation of the retrieved entity relative to the retrieving entity. Only set for sibling entities.
Tuple of raw entity and corresponding reference.
EntityReference reference
EntityReference refering to the raw entity.
RawEntity< Shape_, num_coords_ > raw_entity
Raw entity.
EntitySearchEntry(RawEntity< Shape_, num_coords_ > ent, EntityReference ref)
Constructor.
static TargetVertex embed(int elem, const SourceVertex &vertex)
Embed an edge vertex into a Hexahedron.
static TargetVertex embed(int elem, const SourceVertex &vertex)
Embed a face vertex into a Hexahedron.
static TargetVertex embed(int elem, const SourceVertex &vertex)
Embed an edge vertex into a Quadrilateral.
Embeds a vertex of a lower dimensional shape in a higher dimensional shape.
Dimension-recursive container for OrientationMappingWrappers.
Dimension-recursive container for OrientationMappings.
std::vector< std::array< Real, num_coefficients > > & get_vertex_coefficients()
Vertex coefficient accessor.
const std::vector< Tiny::Vector< Real, Shape_::dimension > > & get_vertices() const
const Vertex-accessor
std::vector< Tiny::Vector< Real, Shape_::dimension > > vertices
Vertices added by this template.
Index num_entities() const
Returns the number of vertices in this template.
const std::vector< std::array< Real, num_coefficients > > & get_vertex_coefficients() const
const Vertex coefficient accessor
std::vector< std::array< Real, num_coefficients > > vertex_coefficients
Vertices added by this template. Precomputed as coefficients for linear interpolation.
std::vector< Tiny::Vector< Real, Shape_::dimension > > & get_vertices()
Vertex-accessor.
Template for refining a mesh entity.
std::vector< TopologyTemplate< CoShape_ > > topologies
Entities of shape CoShape_ added by this template.
Index num_entities() const
Returns the number of entities of dimension dim_ in this template.
const std::vector< TopologyTemplateByDim< dim_ > > & get_topologies() const
const TopologyTemplate accessor
std::vector< TopologyTemplateByDim< dim_ > > & get_topologies()
TopologyTemplate accessor.
const std::array< EntityReference, num_entities > & get_references() const
Const reference-array accessor.
std::array< EntityReference, num_entities > references
Array of vertex references.
std::array< EntityReference, num_entities > & get_references()
Reference-array accessor.
Construction rule for a single entities topology.
const std::array< EntityReference, Shape::FaceTraits< Shape_, dim_ >::count > & get_references() const
Const reference-array accessor.
std::array< EntityReference, num_entities > references
Array of references.
static constexpr int num_entities
Number of references of dimension reference_dim_.
std::array< EntityReference, Shape::FaceTraits< Shape_, dim_ >::count > & get_references()
Reference-array accessor.
Face traits tag struct template.
Definition: shape.hpp:106
Reference cell traits structure.
Definition: shape.hpp:230
Vertex shape tag struct.
Definition: shape.hpp:26