FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
index_calculator.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/geometry/intern/index_representative.hpp>
10#include <kernel/geometry/intern/face_index_mapping.hpp>
11#include <kernel/geometry/index_set.hpp>
13
14// includes, system
15#include <set>
16#include <vector>
17
18namespace FEAT
19{
20 namespace Geometry
21 {
29 template<typename Shape_>
31 {
32 public:
35
38 {
39 public:
40 Index idx[num_indices];
41
43 {
44 for(int i(0); i < num_indices; ++i)
45 idx[i] = Index(0);
46 }
47
48 IndexVector(const IndexVector& iv)
49 {
50 for(int i(0); i < num_indices; ++i)
51 idx[i] = iv[i];
52 }
53
54 Index& operator[](int i)
55 {
56 return idx[i];
57 }
58
59 const Index& operator[](int i) const
60 {
61 return idx[i];
62 }
63
64 bool operator<(const IndexVector& other) const
65 {
66 // Lexicographical comparison ignoring the first entry
67 for(int i(1); i < num_indices; ++i)
68 {
69 if (idx[i] < other[i])
70 {
71 return true;
72 }
73 else if (idx[i] > other[i])
74 {
75 return false;
76 }
77 }
78 return false;
79 }
80
81 }; // class IndexTree::IndexVector
82
83 private:
85 typedef std::set<IndexVector> RepSet;
87 typedef std::vector<RepSet> RepSetVector;
88
91
92 public:
99 explicit IndexTree(Index num_vertices) :
100 _rep_set_vec(num_vertices)
101 {
102 }
103
105 virtual ~IndexTree()
106 {
107 }
108
110 int get_num_indices() const
111 {
113 }
114
117 {
118 XASSERT(i < _rep_set_vec.size());
119 return Index(_rep_set_vec.at(i).size());
120 }
121
123 Index get_index(Index i, Index j, int k) const
124 {
125 typename RepSet::const_iterator iter = _rep_set_vec[i].begin();
126 std::advance(iter, (typename std::iterator_traits<decltype(iter)>::difference_type)j);
127 return (*iter)[k];
128 }
129
146 template<typename IndexVectorType_>
147 std::pair<bool,Index> find(const IndexVectorType_& index_vector) const
148 {
149 // calculate representative
150 IndexVector representative;
151 Intern::IndexRepresentative<Shape_>::compute(representative, index_vector);
152
153 // get the corresponding representative set
154 const RepSet& rep_set = _rep_set_vec[representative[0]];
155
156 // try to find the representative
157 typename RepSet::const_iterator iter = rep_set.find(representative);
158 if(iter == rep_set.end())
159 return std::make_pair(false, Index(0));
160 else
161 return std::make_pair(true, Index((*iter)[0]));
162 }
163
173 template<typename IndexVectorType_>
174 void insert(const IndexVectorType_& index_vector, Index id)
175 {
176 // calculate representative
177 IndexVector representative;
178 Intern::IndexRepresentative<Shape_>::compute(representative, index_vector);
179
180 // insert representative
181 Index first_index = representative[0];
182 ASSERTM(first_index < _rep_set_vec.size(), "index out-of-range");
183
184 representative[0] = id;
185 _rep_set_vec[first_index].insert(representative);
186 }
187
194 template<typename IndexSet_>
195 void parse(const IndexSet_& index_set)
196 {
197 static_assert(int(IndexSet_::num_indices) == int(num_indices), "index count mismatch");
198
199 // fetch number of entities
200 const Index num_entities = index_set.get_num_entities();
201
202 // loop over all entities
203 for(Index i(0); i < num_entities; ++i)
204 {
205 // insert the index vector
206 insert(index_set[i], i);
207 }
208 }
209
221 {
222 Index cur_id = 0;
223
224 // loop over all index vector sets
225 Index n = Index(_rep_set_vec.size());
226 for(Index i(0); i < n; ++i)
227 {
228 typename RepSet::iterator it(_rep_set_vec[i].begin());
229 typename RepSet::iterator jt(_rep_set_vec[i].end());
230 for(; it != jt; ++it, ++cur_id)
231 {
232 // The RepSet is an std::set and its elements cannot be modified as this might screw up the ordering.
233 // As we specifically abuse the 0th entry in each set element for saving an index and exclude that
234 // from the comparison operator, it is ok to cast away the const qualifier and modify the 0th entry.
235 const_cast<IndexVector&>(*it)[0] = cur_id;
236 }
237 }
238
239 // return total number of index vectors
240 return cur_id;
241 }
242
244 static String name()
245 {
246 return "IndexTree<" + Shape_::name() + ">";
247 }
248 }; // class IndexTree
249
250
257 template<
258 typename Shape_,
259 int face_dim_>
261 {
262 public:
267
268 public:
294 template<
295 typename IndexSetIn_,
296 typename IndexSetOut_>
297 static bool compute(
298 const IndexTreeType& index_tree,
299 const IndexSetIn_& index_set_in,
300 IndexSetOut_& index_set_out)
301 {
302 // index vector reference
303 typedef typename IndexSetIn_::IndexTupleType IndexTupleTypeIn;
304 typedef Intern::FaceIndexMapping<Shape_, face_dim_, 0> FimType;
305
306 // fetch number of shapes
307 const Index num_entities = index_set_in.get_num_entities();
308
309 typename IndexTreeType::IndexVector current_face_indices;
310
311 // loop over all shapes
312 for(Index i(0); i < num_entities; ++i)
313 {
314 // get vertex-index-vector of shape i
315 const IndexTupleTypeIn& current_cell_in = index_set_in[i];
316
317 // loop over all cells of shape i
318 for(int j(0); j < IndexSetOut_::num_indices; ++j)
319 {
320 // get the vertex-index-vector of cell j:
321 // loop over all indices of the cell-vertex-vector
322 for(int k(0); k < IndexTreeType::num_indices; ++k)
323 {
324 current_face_indices[k] = current_cell_in[FimType::map(j, k)];
325 }
326
327 // try to find the index of the vector within the tree
328 std::pair<bool, Index> bi = index_tree.find(current_face_indices);
329 if(!bi.first)
330 return false;
331 index_set_out[i][j] = bi.second;
332 }
333 }
334
335 // okay, all index vectors found
336 return true;
337 }
338
342 template<typename IndexSetIn_, typename IndexSetOut_>
343 static void compute_vertex_subshape( const IndexSetIn_& index_set_in, IndexSetOut_& index_set_out)
344 {
345 // Type for shape to vertex@subshape mapping
346 typedef Intern::FaceIndexMapping<Shape_, face_dim_, 0> FimType;
347 // Number of shapes
348 const Index num_shapes(index_set_in.get_num_entities());
349 // Number of verticex
350 const Index num_verts(index_set_in.get_index_bound());
351 // Number of vertices per subshape
352 const int num_verts_subshape(Shape::FaceTraits<FaceType,0>::count);
353 // Number of subshapes per shape, i.e. a Simplex<3> has four Simplex<2> as subshapes
354 const int num_subshapes_shape(Shape::FaceTraits<Shape_,face_dim_>::count);
355
356 // For every vertex, the IndexTree saves which subshapes it is contained in
357 IndexTreeType my_index_tree(num_verts);
358 // This saves the global vertex numbers in the current subshape
359 typename IndexTreeType::IndexVector current_face_indices;
360
361 // Generate the IndexTree of subshapes
362 for(Index k(0); k < num_shapes; ++k)
363 {
364 for(int l(0); l < num_subshapes_shape; ++l)
365 {
366 // Get the ith index in the current subshape from the subshape to index mapping for shape k
367 for(int i(0); i < num_verts_subshape; ++i)
368 current_face_indices[i] = index_set_in[k][FimType::map(l,i)];
369
370 // Insert the current subshape into the IndexTree. We need to give an id as 2nd argument, this does not
371 // get used in any way
372 my_index_tree.insert(current_face_indices, num_verts+1);
373 }
374 }
375
376 // Enumerate the subshape entities. my_index_tree[i] is the set of all subshapes having i as first vertex.
377 // Each set k of those consists of IndexVectors v, where v[0] is the index of the subshape in the subshape
378 // numbering and the subsequent entries are the vertex numbers.
379 const Index num_subshapes(my_index_tree.enumerate());
380
381 // The output IndexSet has num_subshapes entities and the maximum index is the number of vertices
382 IndexSetOut_ my_index_set(num_subshapes, num_verts);
383 index_set_out = std::move(my_index_set);
384
385 for(Index i(0); i < num_verts; ++i)
386 {
387 // Size of the ith set in the IndexTree
388 Index n = my_index_tree.get_set_size(i);
389
390 // Iterate over the set
391 for(Index j(0); j < n; ++j)
392 {
393 // This is the index of the subshape
394 Index my_index = my_index_tree.get_index(i, j, 0);
395 index_set_out[my_index][0] = i;
396
397 // Iterate over the IndexVector that the set element j represents
398 // Skip index 0 as this is contains the index of the subshape in the subshape numbering
399 for(int k(1); k < IndexTreeType::num_indices; ++k)
400 index_set_out[my_index][k] = my_index_tree.get_index(i, j, k);
401 }
402
403 }
404 return;
405 }
406
408 static String name()
409 {
410 return "IndexCalculator<" + Shape_::name() + "," + stringify(face_dim_) + ">";
411 }
412 }; // class IndexCalculator
413
415 namespace Intern
416 {
417 template<typename Shape_, int face_dim_, int cell_dim_ = Shape_::dimension>
418 struct RisbHelper
419 {
420 typedef typename Shape::FaceTraits<Shape_, cell_dim_>::ShapeType CellType;
421 typedef typename Shape::FaceTraits<Shape_, face_dim_>::ShapeType FaceType;
422
423 static void compute(IndexSetHolder<Shape_>& ish, IndexTree<FaceType>& idx_tree)
424 {
425 // recurse down
426 RisbHelper<Shape_, face_dim_, cell_dim_ - 1>::compute(ish, idx_tree);
427
428 // create an index calculator
429 IndexCalculator<CellType, face_dim_>::compute(
430 idx_tree,
431 ish.template get_index_set<cell_dim_, 0>(),
432 ish.template get_index_set<cell_dim_, face_dim_>());
433 }
434 };
435
436 template<typename Shape_, int face_dim_>
437 struct RisbHelper<Shape_, face_dim_, face_dim_>
438 {
439 typedef typename Shape::FaceTraits<Shape_, face_dim_>::ShapeType FaceType;
440
441 static void compute(IndexSetHolder<Shape_>&, IndexTree<FaceType>&)
442 {
443 // dummy
444 }
445 };
446
459 template<typename Shape_, int face_dim_ = Shape_::dimension - 1>
460 struct RisbWrapper
461 {
462 typedef typename Shape::FaceTraits<Shape_, face_dim_>::ShapeType FaceType;
463 static constexpr int num_verts = Shape::FaceTraits<FaceType, 0>::count;
464
475 static void wrap(IndexSetHolder<Shape_>& ish)
476 {
477 auto& vert_at_subshape_index_set(ish.template get_index_set<face_dim_,0>());
478
479 // Check if vertex@subshape information is present (needed later on) and compute it if necessary
480 if(vert_at_subshape_index_set.get_num_entities() == 0)
481 {
482 IndexCalculator<Shape_, face_dim_>::compute_vertex_subshape(
483 ish.template get_index_set<Shape_::dimension, 0>(), vert_at_subshape_index_set);
484
485 // Update dimensions of other IndexSets in the IndexSetHolder
486 IndexSetHolderDimensionUpdater<Shape_::dimension, Shape_::dimension-face_dim_>::update(ish);
487 }
488
489 // recurse down
490 RisbWrapper<Shape_, face_dim_ - 1>::wrap(ish);
491
492 // get vertices-at-face index set
493 IndexSet<num_verts>& vert_adj(vert_at_subshape_index_set);
494
495 // build an index-tree from it
496 IndexTree<FaceType> idx_tree(vert_adj.get_index_bound());
497 idx_tree.parse(vert_adj);
498
499 // Call the helper. This in turn calls IndexCalculater::compute, which needs vertex\@shape and
500 // vertex@subshape information for all subshapes.
501 RisbHelper<Shape_, face_dim_>::compute(ish, idx_tree);
502 }
503 }; // RisbWrapper<Shape_, face_dim_>
504
505 template<typename Shape_>
506 struct RisbWrapper<Shape_, 0>
507 {
508 static void wrap(IndexSetHolder<Shape_>& /*ish*/)
509 {
510 // dummy
511 }
512 }; // RisbWrapper<Shape_, 0>
513 } // namespace Intern
515
523 template<typename Shape_>
525 {
526 public:
528 static void compute(IndexSetHolder<Shape_>& index_set_holder)
529 {
530 Intern::RisbWrapper<Shape_>::wrap(index_set_holder);
531 }
532 };
533 } // namespace Geometry
534} // namespace FEAT
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
Definition: assertion.hpp:230
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
Calculates the missing index sets if the vertex-at-shape index sets are given.
static void compute_vertex_subshape(const IndexSetIn_ &index_set_in, IndexSetOut_ &index_set_out)
For given vertex@shape information, numbers subshapes and calculates vertex@subshape.
IndexTree< FaceType > IndexTreeType
Type for the IndexTree containing vertex@subshape information.
Shape::FaceTraits< Shape_, face_dim_ >::ShapeType FaceType
Type of the subshape to calculate the missing information at.
static bool compute(const IndexTreeType &index_tree, const IndexSetIn_ &index_set_in, IndexSetOut_ &index_set_out)
Calculates an index set from vertex@shape information.
static String name()
Returns the class name.
Stores the index representatives of an index set.
RepSetVector _rep_set_vec
representative set vector
std::set< IndexVector > RepSet
Set of IndexVector representatives.
void parse(const IndexSet_ &index_set)
Parses an index set into the tree.
int get_num_indices() const
returns number of indices of an index-representative
static constexpr int num_indices
number of indices per index vector
void insert(const IndexVectorType_ &index_vector, Index id)
Inserts an index vector's representative into the index tree.
static String name()
Returns the class name.
Index get_index(Index i, Index j, int k) const
returns the value of the k-th component of the j-th index-representative in the i-th set
virtual ~IndexTree()
Destructor.
Index enumerate()
Enumerates the index vector representatives.
IndexTree(Index num_vertices)
Constructor.
Index get_set_size(Index i) const
returns size of the i-th representative set
std::vector< RepSet > RepSetVector
Vector of IV rep sets.
std::pair< bool, Index > find(const IndexVectorType_ &index_vector) const
Searches for an index vector within the tree.
Builder for redundant index sets.
static void compute(IndexSetHolder< Shape_ > &index_set_holder)
Routine that does the actual work.
String class implementation.
Definition: string.hpp:46
@ other
generic/other permutation strategy
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
std::uint64_t Index
Index data type.
Face traits tag struct template.
Definition: shape.hpp:106