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 / Real(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[std::size_t(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 {
481 int index;
486
487 EntityReference() = default;
488 EntityReference(EntitySource s, int 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 {
559 return TopologyTemplate<Shape_, dim_>::references[std::size_t(idx)];
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(int idx) const
609 {
610 return TopologyTemplate<Shape_, dim_>::references[std::size_t(idx)];
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()(int idx) const
790 {
791 return _mapping.at(std::size_t(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)[std::size_t(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 int 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 int idx = 0;
1097 for(const auto& entity : Intern::internal_entities<EntityShape_, dim_>(tmplt.entities))
1098 {
1100
1101 for(std::size_t i(0); i < std::size_t(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[std::size_t(vertex)];
1143 entries.emplace_back(entity, EntityReference{EntitySource::ParentTopology, 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[std::size_t(vertex)] = vertices[std::size_t(FaceMapping::map(face, vertex))];
1162 }
1163 entries.emplace_back(entity, EntityReference{EntitySource::ParentTopology, 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, int 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 _type_adjustment_initialized[1] = true;
1479 }
1480 return _edge_type_adjustments.at(type);
1481 }
1482 else if constexpr(dim_ == 2)
1483 {
1484 if(!_type_adjustment_initialized[2])
1485 {
1486 _create_type_adjustments<Shape::Hypercube<dim_>>(faces());
1487 _type_adjustment_initialized[2] = true;
1488 }
1489 return _face_type_adjustments.at(type);
1490 }
1491 else if constexpr(dim_ == 3)
1492 {
1493 if(!_type_adjustment_initialized[3])
1494 {
1495 _create_type_adjustments<Shape::Hypercube<dim_>>(cells());
1496 _type_adjustment_initialized[3] = true;
1497 }
1498 return _cell_type_adjustments.at(type);
1499 }
1500 XABORTM("Unsupported template dimension!");
1501 }
1502
1503 template<int dim_>
1504 Real average_elements_per_marking()
1505 {
1506 RawTemplateMapByDim<dim_>* templates = nullptr;
1507
1508 if constexpr(dim_ == 1)
1509 {
1510 templates = &RawData_::raw_edges();
1511 }
1512 else if constexpr(dim_ == 2)
1513 {
1514 templates = &RawData_::raw_faces();
1515 }
1516 else if constexpr(dim_ == 3)
1517 {
1518 templates = &RawData_::raw_cells();
1519 }
1520 else
1521 {
1522 XABORTM("Unsupported dimension!");
1523 }
1524
1525 Index markings(0);
1526 std::size_t elements(0);
1527 for(const auto& [type, tmplt] : *templates)
1528 {
1529 markings += type.num_marked();
1530 elements += tmplt.entities.size();
1531 }
1532
1533 return Real(elements) / Real(markings);
1534 }
1535
1537 void stats()
1538 {
1539 std::array<Index, 4> maxima = {0, 0, 0, 0};
1540
1541 for(const auto& entry : edges())
1542 {
1543 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1544 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1545 }
1546 std::cout << "Edges:\n";
1547 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1548 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1549
1550 maxima = {0, 0, 0, 0};
1551 for(const auto& entry : faces())
1552 {
1553 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1554 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1555 maxima[2] = Math::max(maxima[2], entry.second.template num_entities<2>());
1556 }
1557 std::cout << "Faces:\n";
1558 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1559 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1560 std::cout << " Max Faces: " << stringify(unsigned(maxima[2])) << "\n";
1561
1562 maxima = {0, 0, 0, 0};
1563 for(const auto& entry : cells())
1564 {
1565 maxima[0] = Math::max(maxima[0], entry.second.template num_entities<0>());
1566 maxima[1] = Math::max(maxima[1], entry.second.template num_entities<1>());
1567 maxima[2] = Math::max(maxima[2], entry.second.template num_entities<2>());
1568 maxima[3] = Math::max(maxima[3], entry.second.template num_entities<3>());
1569 }
1570 std::cout << "Faces:\n";
1571 std::cout << " Max Vertices: " << stringify(unsigned(maxima[0])) << "\n";
1572 std::cout << " Max Edges: " << stringify(unsigned(maxima[1])) << "\n";
1573 std::cout << " Max Faces: " << stringify(unsigned(maxima[2])) << "\n";
1574 std::cout << " Max Cells: " << stringify(unsigned(maxima[3])) << "\n";
1575 }
1576
1577 private:
1579 template<int n_>
1580 Index _find_vertex(const std::vector<Tiny::Vector<Real, n_>>& vertices, const Tiny::Vector<Real, n_>& vertex)
1581 {
1582 auto pred = [&](auto v) { return Intern::is_same_vertex(vertex, v); };
1583 return Index(std::distance(vertices.begin(), std::find_if(vertices.begin(), vertices.end(), pred)));
1584 }
1585
1587 template<int dim_>
1589 {
1590 if constexpr(dim_ == 1)
1591 {
1592 return _edge_type_adjustments;
1593 }
1594 else if constexpr(dim_ == 2)
1595 {
1596 return _face_type_adjustments;
1597 }
1598 else if constexpr(dim_ == 3)
1599 {
1600 return _cell_type_adjustments;
1601 }
1602 XABORTM("Unsupported template dimension!");
1603 }
1604
1616 template<typename TemplateShape_, typename TopologyShape_, int dim_ = TopologyShape_::dimension - 1>
1619 const TemplateSearchSpace<TemplateShape_>& search_space,
1621 {
1622 static constexpr int num_entities = Shape::FaceTraits<TopologyShape_, dim_>::count;
1623 if constexpr(dim_ == 0)
1624 {
1625 auto& vertex_refs = topo.template get_references<0>();
1626 for(Index i(0); i < Index(num_entities); i++)
1627 {
1628 vertex_refs[i] = search_space.search_vertex(raw_entity.coords[i]);
1629 }
1630 }
1631 else
1632 {
1633 auto& refs = topo.template get_references<dim_>();
1634 for(int i(0); i < num_entities; i++)
1635 {
1636 refs[std::size_t(i)] = search_space.search(raw_entity.template face<dim_>(i));
1637 }
1638
1639 _build_topology<TemplateShape_, TopologyShape_, dim_ - 1>(raw_entity, search_space, topo);
1640 }
1641 }
1642
1653 template<typename TemplateShape_, int dim_ = TemplateShape_::dimension>
1655 const RawTemplate<TemplateShape_>& raw_template,
1658 {
1659 if constexpr(dim_ == 0)
1660 {
1661 for(const auto& vertex : Intern::internal_vertices(raw_template))
1662 {
1663 // Add vertex and its coefficients to template
1664 tmplt.get_vertices().push_back(vertex);
1665 tmplt.get_vertex_coefficients().push_back(Intern::vertex_coefficients<TemplateShape_>(vertex));
1666
1667 // Add entry to search space for building topologies later
1668 search_space.add_sibling_vertex(vertex, int(tmplt.get_vertices().size() - 1));
1669 }
1670 }
1671 else
1672 {
1673 _build_template<TemplateShape_, dim_ - 1>(raw_template, tmplt, search_space);
1674
1675 using TopologyShape = typename Shape::FaceTraits<TemplateShape_, dim_>::ShapeType;
1676
1677 auto& topologies = tmplt.template get_topologies<dim_>();
1678 for(const auto& entity : Intern::internal_entities<TemplateShape_, dim_>(raw_template.entities))
1679 {
1681 _build_topology<TemplateShape_, TopologyShape>(entity, search_space, topology);
1682 topologies.push_back(topology);
1683
1684 search_space.add_sibling(entity, int(topologies.size() - 1));
1685 }
1686 }
1687 }
1688
1728 template<typename TemplateShape_, int dim_ = TemplateShape_::dimension>
1731 const int orientation,
1732 const RefinementTemplate<TemplateShape_>& local_template,
1733 const TemplateSearchSpace<TemplateShape_>& local_search_space,
1734 const RefinementTemplate<TemplateShape_>& oriented_template,
1735 const TemplateSearchSpace<TemplateShape_>& oriented_search_space)
1736 {
1737
1739
1740 if constexpr(dim_ == 0)
1741 {
1742 OrientationMapping& vertex_mapping =
1743 _orientation_mappings.template get_mapping<TemplateShape_::dimension, 0>(oriented_type, orientation);
1744
1745 // For each vertex of the local template
1746 // * map it into the oriented frame of reference
1747 // * search for the corresponding vertex of the oriented template
1748 // * save the found index in the orientation mapping
1749 for(const VertexType& local_vertex : local_template.get_vertices())
1750 {
1751 VertexType oriented_vertex = Intern::orient_vertex<TemplateShape_>(local_vertex, orientation);
1752 Index mapped = _find_vertex(oriented_template.get_vertices(), oriented_vertex);
1753 vertex_mapping.get_mapping().emplace_back(mapped, 0);
1754 }
1755 }
1756 else
1757 {
1758 _fill_orientation_mappings<TemplateShape_, dim_ - 1>(
1759 oriented_type,
1760 orientation,
1761 local_template,
1762 local_search_space,
1763 oriented_template,
1764 oriented_search_space);
1765
1766 using CurrentShape = typename Shape::FaceTraits<TemplateShape_, dim_>::ShapeType;
1767 static constexpr int num_vertices = Shape::FaceTraits<CurrentShape, 0>::count;
1768
1769 OrientationMapping& mapping =
1770 _orientation_mappings.template get_mapping<TemplateShape_::dimension, dim_>(oriented_type, orientation);
1771
1772 for(const auto& local_topo : local_template.template get_topologies<dim_>())
1773 {
1774 // Collect local vertices from the search space
1775 std::array<VertexType, num_vertices> local = {};
1776
1777 const auto& local_refs = local_topo.template get_references<0>();
1778 for(std::size_t i(0); i < std::size_t(num_vertices); i++)
1779 {
1780 local[i] =
1781 Intern::orient_vertex<TemplateShape_>(local_search_space.vertex_by_reference(local_refs[i]), orientation);
1782 }
1783
1784 Index entity_idx = 0;
1785 for(const auto& oriented_topo : oriented_template.template get_topologies<dim_>())
1786 {
1787 // Collect oriented vertices from the oriented search space
1788 std::array<VertexType, num_vertices> oriented = {};
1789
1790 const auto& oriented_refs = oriented_topo.template get_references<0>();
1791 for(std::size_t i(0); i < std::size_t(num_vertices); i++)
1792 {
1793 oriented[i] = oriented_search_space.vertex_by_reference(oriented_refs[i]);
1794 }
1795
1796 // Compare local and oriented entities
1798 ent_local.coords = local;
1799
1801 ent_oriented.coords = oriented;
1802
1803 if(Intern::is_same_raw_entity(ent_local, ent_oriented))
1804 {
1805 // The entities are identical. This means local_topo and
1806 // oriented_topo are the same mesh element and we can save this
1807 // mapping in the orientation mapping. Additionally we can
1808 // pre-compute their relative orientation at this point, because
1809 // we know how both of these entities will be constructed in the
1810 // final mesh and how their parents are oriented relative to each
1811 // other.
1812 using CongruencySampler = Intern::CongruencySampler<CurrentShape>;
1813 int o = CongruencySampler::compare_with(
1814 ent_local.coords.data(),
1815 ent_oriented.coords.data(),
1816 Intern::is_same_vertex<TemplateShape_::dimension>);
1817
1818 mapping.get_mapping().emplace_back(entity_idx, o);
1819 break;
1820 }
1821 entity_idx++;
1822 }
1823 }
1824 }
1825 }
1826
1836 template<int dim_>
1838 {
1839 using TemplateShape = typename Shape::FaceTraits<Shape::Hypercube<dim_>, dim_>::ShapeType;
1840
1842
1843 // We require the full template search spaces to create orientation mappings with.
1844 std::unordered_map<RefinementTypeByDim<dim_>, TemplateSearchSpace<TemplateShape>> search_spaces;
1845
1846 for(const auto& entry : raw_templates)
1847 {
1849 TemplateSearchSpace<TemplateShape> search_space = _setup_search_space<Shape::Hypercube<dim_>>(entry.first);
1850
1851 _build_template(entry.second, tmplt, search_space);
1852
1853 result.insert({entry.first, tmplt});
1854 search_spaces.insert({entry.first, search_space});
1855 }
1856
1857 // We have now created all templates for this dimension.
1858 // Next, we create the corresponding orientation mappings.
1859
1860 // NOTE(mmuegge): _fill_orientation_mappings is fully dimension-generic,
1861 // apart from CongruencySamplers for higher dimensions. We thus disable
1862 // orientation mapping creation for all dimensions above 2
1863 if constexpr(dim_ <= 2)
1864 {
1865 for(const auto& entry : raw_templates)
1866 {
1867 RefinementTypeByDim<dim_> local_type = entry.first;
1868 auto& search_space = search_spaces[local_type];
1869
1870 for(int orientation = 0; orientation < Intern::orientations<Shape::Hypercube<dim_>>(); orientation++)
1871 {
1872 const RefinementTypeByDim<dim_> oriented_type = local_type.orient(orientation);
1873 auto& oriented_search_space = search_spaces[oriented_type];
1874
1875 const auto& local_tmplt = result.at(local_type);
1876 const auto& oriented_tmplt = result.at(oriented_type);
1877
1878 _fill_orientation_mappings<TemplateShape>(
1879 oriented_type,
1880 orientation,
1881 local_tmplt,
1882 search_space,
1883 oriented_tmplt,
1884 oriented_search_space);
1885 }
1886 }
1887 }
1888 return result;
1889 }
1890
1901 template<typename Shape_>
1903 {
1904 // Setup result.
1905 TemplateSearchSpace<Shape_> result = {};
1906
1907 // For faces and cells we also have to add the boundary edges and internal edges
1908 if constexpr(Shape_::dimension > 1)
1909 {
1910 static const constexpr int num_edges = Shape::FaceTraits<Shape_, 1>::count;
1911 for(int i(0); i < num_edges; ++i)
1912 {
1913 auto edge_type = type.template face_type<1>(i);
1914 result.add_boundary_entity(i, RawData_::raw_edges().at(edge_type));
1915 }
1916 }
1917
1918 // For cells, we have to add boundary faces and internal faces
1919 if constexpr(Shape_::dimension > 2)
1920 {
1921 static const constexpr int num_faces = Shape::FaceTraits<Shape_, 2>::count;
1922 for(int i(0); i < num_faces; ++i)
1923 {
1924 auto face_type = type.template face_type<2>(i);
1925 result.add_boundary_entity(i, RawData_::raw_faces().at(face_type));
1926 }
1927 }
1928
1929 result.add_topology();
1930
1931 return result;
1932 }
1933
1949 template<typename Shape_, typename TemplateMap_>
1950 void _create_type_adjustments(const TemplateMap_& available_templates)
1951 {
1952 auto& adjustments = type_adjustments<Shape_::dimension>();
1953
1954 static const constexpr int num_verts = Shape::FaceTraits<Shape_, 0>::count;
1955 for(Index type(0); type < (1 << num_verts); ++type)
1956 {
1957 auto type_marking = VertexMarking<Shape_>(type);
1958
1959 std::size_t closest_count = num_verts;
1960 auto closest_marking = VertexMarking<Shape_>::all_marked();
1961
1962 for(auto& entry : available_templates)
1963 {
1964 VertexMarking<Shape_> entry_marking(entry.first.to_vertex_marking());
1965
1966 // Is the current type a subtype of this type?
1967 if(!entry_marking.covers(type_marking))
1968 {
1969 continue;
1970 }
1971 std::size_t distance = type_marking.distance(entry_marking);
1972
1973 if(distance < closest_count)
1974 {
1975 closest_count = distance;
1976 closest_marking = entry_marking;
1977 }
1978 }
1979
1980 // Found the type that requires the least changes
1981 // Next, determine exact required changes
1982
1983 auto& adjustment = adjustments.at(type);
1984 for(int i(0); i < num_verts; ++i)
1985 {
1986 if(closest_marking.is_vertex_marked(i) && !type_marking.is_vertex_marked(i))
1987 {
1988 adjustment[std::size_t(i)] = 1;
1989 }
1990 }
1991 }
1992 }
1993 };
1994} // 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.
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::pair< Index, int > operator()(int idx) const
Apply operator.
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.
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.
std::pair< Index, int > correct_for_orientation(RefinementTypeByDim< dim_ > type, int orientation, int idx)
Correct an index for orientation.
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.
void add_sibling_vertex(const Tiny::Vector< Real, num_coords > &vertex, int idx)
Add a sibling vertex to the search space.
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.
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, int 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.
void add_sibling(const RawEntity< Shape__, num_coords_ > &entity, int idx)
Add a sibling entity to the 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.
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:993
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