FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
raw_refinement_templates.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8#include <kernel/geometry/intern/adaptive_refinement_utils.hpp>
9#include <kernel/shape.hpp>
10#include <kernel/util/tiny_algebra.hpp>
11#include <kernel/geometry/intern/face_index_mapping.hpp>
13
14#include <array>
15#include <vector>
16
17namespace FEAT::Geometry
18{
19 template<typename Shape_, int num_coords_ = Shape_::dimension>
20 struct RawEntity
21 {
22 static const constexpr int num_coords = num_coords_;
23 static const constexpr int num_vertices = Shape::FaceTraits<Shape_, 0>::count;
24
26
27 std::array<Tiny::Vector<Real, num_coords>, num_vertices> coords;
28
29 template<typename... Vector>
30 explicit RawEntity(Vector... vectors) : coords{vectors...}
31 {
32 }
33
34 template<int dim_>
36 {
37 using Mapping = Intern::FaceIndexMapping<Shape_, dim_, 0>;
38 using SubShape = typename Shape::FaceTraits<Shape_, dim_>::ShapeType;
39 static constexpr const int num_verts = Shape::FaceTraits<SubShape, 0>::count;
40
42
43 for(int i(0); i < num_verts; ++i)
44 {
45 result.coords.at(std::size_t(i)) = coords[std::size_t(Mapping::map(idx, i))];
46 }
47
48 return result;
49 }
50 };
51
52 template<typename Shape_, int num_coords_>
53 std::ostream& operator<<(std::ostream& stream, const RawEntity<Shape_, num_coords_>& entity)
54 {
55 stream << "RawEntity<" << Shape_::name() << ", " << stringify(num_coords_) << "> { coords: [ ";
56 for(const auto& vertex : entity.coords)
57 {
58 stream << stringify(vertex) << ", ";
59 }
60 stream << "]}";
61 return stream;
62 }
63
64 template<typename Shape_>
66 {
68
69 using VertexType = typename EntityType::VertexType;
70
71 std::vector<RawEntity<Shape_>> entities;
72
73 template<typename... Vector>
74 RawTemplate& add_entity(Vector... vectors)
75 {
76 entities.emplace_back(vectors...);
77 return *this;
78 }
79
80 RawTemplate& add_entity(const std::array<VertexType, Shape::FaceTraits<Shape_, 0>::count>& vertices)
81 {
82 RawEntity<Shape_> entity;
83 entity.coords = vertices;
84 entities.push_back(entity);
85
86 return *this;
87 }
88
89 RawTemplate& axis_aligned(const VertexType& a, const VertexType& b)
90 {
91 static_assert(Shape_::dimension <= 3);
92
93 static constexpr int num_verts = Shape::FaceTraits<Shape_, 0>::count;
94
95 static std::array<std::array<Real, 3>, 8> coeffs {{
96 {0, 0, 0},
97 {1, 0, 0},
98 {0, 1, 0},
99 {1, 1, 0},
100 {0, 0, 1},
101 {1, 0, 1},
102 {0, 1, 1},
103 {1, 1, 1},
104 }};
105
106 VertexType diff = b - a;
107
108 std::array<VertexType, num_verts> vertices;
109 for(int i(0); i < num_verts; ++i)
110 {
111 auto& c = coeffs[std::size_t(i)];
112 VertexType v = a;
113 for(int j(0); j < Shape_::dimension; ++j)
114 {
115 v[j] += c[std::size_t(j)] * diff[j];
116 }
117 for (int j(0); j < v.n; ++j)
118 {
119 ASSERTM(v[j] >= 0.0 && v[j] <= 1.0, "Invalid vertex in axis_aligned");
120 }
121 vertices[std::size_t(i)] = v;
122 }
123 add_entity(vertices);
124
125 return *this;
126 }
127
128 RawTemplate& grid(std::array<Index, Shape_::dimension> size, VertexType stepsize)
129 {
130 std::array<Index, Shape_::dimension> coords = {};
131 _grid(size, stepsize, 0, coords);
132 return *this;
133 }
134
142 {
143 typedef typename std::vector<RawEntity<Shape_>>::difference_type DiffType;
144 const EntityType parent = entities[face];
145 entities.erase(entities.begin() + DiffType(face));
146
147 for(const EntityType& entity : tmplt.entities)
148 {
149 EntityType mapped{};
150
151 for(Index i(0); i < entity.coords.size(); ++i)
152 {
153 const auto coeffs = Intern::vertex_coefficients<Shape_>(entity.coords[i]);
154 mapped.coords[i] = Intern::interpolate(parent.coords, coeffs);
155 }
156 entities.push_back(mapped);
157 }
158
159 return *this;
160 }
161
162 private:
163 void _grid(
164 const std::array<Index, Shape_::dimension>& size,
165 VertexType stepsize,
166 int dim,
167 std::array<Index, Shape_::dimension>& coords)
168 {
169 if (dim == Shape_::dimension)
170 {
171 VertexType v;
172 for (int i = 0; i < Shape_::dimension; ++i)
173 {
174 v[i] = typename VertexType::ValueType(coords[std::size_t(i)]) * stepsize[i];
175 }
176 axis_aligned(v, v + stepsize);
177 }
178 else
179 {
180 for(Index i(0); i < size[std::size_t(dim)]; i++)
181 {
182 coords[std::size_t(dim)] = i;
183 _grid(size, stepsize, dim + 1, coords);
184 }
185 }
186 }
187 };
188
189
190 template<typename Shape_, typename FnVert, typename FnEntity>
191 static RawTemplate<Shape_> transform_template_vertices(FnVert vertex_transform, FnEntity entity_transform, RawTemplate<Shape_>& tmplt)
192 {
193
194 RawTemplate<Shape_> result;
195 for(auto& entity : tmplt.entities)
196 {
197 RawEntity<Shape_> new_entity;
198
199 for(std::size_t i(0); i < std::size_t(entity.num_vertices); ++i)
200 {
201 new_entity.coords.at(i) = vertex_transform(entity.coords.at(i));
202 }
203
204 entity_transform(new_entity);
205 result.entities.push_back(new_entity);
206 }
207 return result;
208 }
209
213 template<typename Shape_>
215 {
216 static_assert(Shape_::dimension == 2, "rotate_template_2d called for non 2D template!");
217
218 // Rotate vertex 90 degrees counterclockwise around (0.5, 0.5)
219 auto rotate = [](Tiny::Vector<Real, 2> vertex)
220 {
221 return Tiny::Vector<Real, 2>{-vertex[1] + 1, vertex[0]};
222 };
223
224 auto rotate_indices = [](RawEntity<Shape_>& entity)
225 {
226 entity.coords = Intern::rotate_arraylike_2d(entity.coords);
227 };
228
229 return transform_template_vertices(rotate, rotate_indices, tmplt);
230 }
231
239 template<typename Shape_>
241 {
242 static_assert(Shape_::dimension == 3, "rotate_template_2d called for non 2D template!");
243
244 auto rotate = [](Tiny::Vector<Real, 3> vertex)
245 {
246 return Tiny::Vector<Real, 3>{vertex[0], -vertex[2] + 1, vertex[1]};
247 };
248
249 auto rotate_indices = [](RawEntity<Shape_>& entity)
250 {
251 entity.coords = Intern::rotate_arraylike_xaxis(entity.coords);
252 };
253
254 return transform_template_vertices(rotate, rotate_indices, tmplt);
255 }
256
264 template<typename Shape_>
266 {
267 static_assert(Shape_::dimension == 3, "rotate_template_2d called for non 2D template!");
268
269 auto rotate = [](Tiny::Vector<Real, 3> vertex)
270 {
271 return Tiny::Vector<Real, 3>{vertex[2], vertex[1], -vertex[0] + 1};
272 };
273
274 auto rotate_indices = [](RawEntity<Shape_>& entity)
275 {
276 entity.coords = Intern::rotate_arraylike_yaxis(entity.coords);
277 };
278
279 return transform_template_vertices(rotate, rotate_indices, tmplt);
280 }
281
289 template<typename Shape_>
291 {
292 static_assert(Shape_::dimension == 3, "rotate_template_2d called for non 2D template!");
293
294 auto rotate = [](Tiny::Vector<Real, 3> vertex)
295 {
296 return Tiny::Vector<Real, 3>{-vertex[1] + 1, vertex[0], vertex[2]};
297 };
298
299 auto rotate_indices = [](RawEntity<Shape_>& entity)
300 {
301 entity.coords = Intern::rotate_arraylike_zaxis(entity.coords);
302 };
303
304 return transform_template_vertices(rotate, rotate_indices, tmplt);
305 }
306
307
308 template<typename TemplateMap, typename RefinementType_>
309 int create_2dtemplate_rotations(TemplateMap& map, const RefinementType_& base_type)
310 {
311 // Count base template towards created templates
312 int templates_created = 1;
313
314 RefinementType_ type = base_type;
315 auto tmplt = map[type];
316
317 for(int i = 0; i < 4; i++)
318 {
319 if(map.find(type) == map.end())
320 {
321 map[type] = tmplt;
322 templates_created += 1;
323 }
324
325 type = type.rotate_2d();
326 tmplt = rotate_template_2d(tmplt);
327 }
328
329 return templates_created;
330 }
331
332 template<typename TemplateMap, typename RefinementType_>
333 int create_3dtemplate_rotations(TemplateMap& map, const RefinementType_& base_type)
334 {
335 enum class Rotation : std::uint8_t
336 {
337 None,
338 X,
339 Y,
340 };
341
342 static constexpr std::array<Rotation, 6> rotations = {{
343 Rotation::None,
344 Rotation::X,
345 Rotation::Y,
346 Rotation::X,
347 Rotation::Y,
348 Rotation::X,
349 }};
350
351 // Count base template towards created templates
352 int templates_created = 1;
353
354 RefinementType_ outer_type = base_type;
355 auto outer_template = map[outer_type];
356
357 for(std::size_t outer_rotation(0); outer_rotation < 6u; outer_rotation++)
358 {
359 const Rotation next_outer_rotation = rotations[outer_rotation];
360 if (next_outer_rotation == Rotation::X)
361 {
362 outer_type = outer_type.rotate_xaxis();
363 outer_template = rotate_template_xaxis(outer_template);
364 }
365 else if (next_outer_rotation == Rotation::Y)
366 {
367 outer_type = outer_type.rotate_yaxis();
368 outer_template = rotate_template_yaxis(outer_template);
369 }
370
371 RefinementType_ inner_type = outer_type;
372 auto inner_template = outer_template;
373 for(int inner_rotation(0); inner_rotation < 4; inner_rotation++)
374 {
375 if(map.find(inner_type) == map.end())
376 {
377 map[inner_type] = inner_template;
378 templates_created += 1;
379 }
380
381 inner_type = inner_type.rotate_zaxis();
382 inner_template = rotate_template_zaxis(inner_template);
383 }
384 }
385 return templates_created;
386 }
387} // namespace FEAT::Geometry
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
Definition: assertion.hpp:230
Tiny Vector class template.
Geometry namespace.
static RawTemplate< Shape_ > rotate_template_yaxis(RawTemplate< Shape_ > &tmplt)
Rotates a raw template 90 degrees counterclockwise around the y-axis.
static RawTemplate< Shape_ > rotate_template_zaxis(RawTemplate< Shape_ > &tmplt)
Rotates a raw template 90 degrees counterclockwise around the z-axis.
static RawTemplate< Shape_ > rotate_template_2d(RawTemplate< Shape_ > &tmplt)
Rotates a raw template 90 degrees counterclockwise around (0.5, 0.5)
static RawTemplate< Shape_ > rotate_template_xaxis(RawTemplate< Shape_ > &tmplt)
Rotates a raw template 90 degrees counterclockwise around the x-axis.
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:993
std::uint64_t Index
Index data type.
RawTemplate & recurse(Index face, const RawTemplate &tmplt)
Recursively applies a template to a face of this template.
Face traits tag struct template.
Definition: shape.hpp:106