FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
facet_flipper.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
10#include <kernel/geometry/intern/congruency_sampler.hpp>
11#include <kernel/geometry/intern/congruency_mapping.hpp>
12#include <kernel/geometry/intern/face_index_mapping.hpp>
13#include <kernel/geometry/index_set.hpp>
14
15// includes, system
16#include <vector>
17
18namespace FEAT
19{
20 namespace Geometry
21 {
23 namespace Intern
24 {
25 template<typename Shape_>
26 class FacetCongruencySampler
27 {
28 public:
29 static constexpr int facet_dim = Shape_::dimension-1;
30 typedef typename Shape::FaceTraits<Shape_, facet_dim>::ShapeType FacetType;
31
32 template<typename Outer_>
33 class CompIndexMap
34 {
35 protected:
36 const Outer_& _outer;
37 int _idx;
38
39 public:
40 explicit CompIndexMap(const Outer_& outer, int idx) : _outer(outer), _idx(idx) {}
41
42 Index operator[](int i) const
43 {
44 return _outer[Geometry::Intern::FaceIndexMapping<Shape_, facet_dim, 0>::map(_idx,i)];
45 }
46 }; // class CompIndexMap
47
48 template<typename VertsAtFace_, typename VertsAtShape_, typename FacesAtShape_>
49 static int compare(const VertsAtFace_& verts_at_face, const VertsAtShape_& verts_at_shape,
50 const FacesAtShape_& faces_at_shape, const Index shape_idx, const int local_face)
51 {
52 CompIndexMap<typename VertsAtShape_::IndexTupleType> cim(verts_at_shape[shape_idx], local_face);
53 // get code and orientation
54 int code = CongruencySampler<FacetType>::compare(verts_at_face[faces_at_shape(shape_idx, local_face)], cim);
55 int loc_ori = CongruencySampler<FacetType>::orientation(code);
56 int ref_ori = Shape::ReferenceCell<Shape_>::facet_orientation(local_face);
57 return loc_ori * ref_ori;
58 }
59 }; // class FacetCongruencySampler<...>
60
61 template<typename Facet_, int codim_ = Facet_::dimension>
62 class FacetFlipRecurser
63 {
64 public:
65 static constexpr int subdim = Facet_::dimension - codim_;
66
67 static void flip(IndexSetWrapper<Facet_, Facet_::dimension-1>& isw, Index ifacet)
68 {
69 FacetFlipRecurser<Facet_, codim_-1>::flip(isw, ifacet);
70 auto& idx_set = isw.template get_index_set<subdim>();
71 Intern::CongruencyMapping<Facet_, subdim>::flip(idx_set[ifacet]);
72 }
73 };
74
75 template<typename Facet_>
76 class FacetFlipRecurser<Facet_, 0>
77 {
78 public:
79 template<typename ISW_>
80 static void flip(ISW_&, Index)
81 {
82 // nothing to do here
83 }
84 };
85 } // namespace Intern
87
93 template<typename Shape_>
95 {
96 public:
97 static_assert(Shape_::dimension > 1, "invalid shape dimension");
98
102 static void reorient(IndexSetHolder<Shape_>& ish)
103 {
104 static constexpr int shape_dim = Shape_::dimension;
105 typedef typename Shape::FaceTraits<Shape_, shape_dim-1>::ShapeType FacetType;
106
107 // get the three index sets:
108 auto& facet_isw = ish.template get_index_set_wrapper<shape_dim-1>();
109 const auto& verts_at_face = ish.template get_index_set<shape_dim-1, 0>();
110 const auto& faces_at_elem = ish.template get_index_set<shape_dim, shape_dim-1>();
111 const auto& verts_at_elem = ish.template get_index_set<shape_dim, 0>();
112
113 // get the counts
114 const Index num_faces = verts_at_face.get_num_entities();
115 const Index num_elems = verts_at_elem.get_num_entities();
116
117 // loop over all elements and determine all boundary facets
118 std::vector<int> nfaces(num_faces, 0);
119 for(Index ielem(0); ielem < num_elems; ++ielem)
120 {
121 for(int loc_face(0); loc_face < faces_at_elem.num_indices; ++loc_face)
122 {
123 ++nfaces.at(faces_at_elem(ielem, loc_face));
124 }
125 }
126
127 // loop over all elements again
128 for(Index ielem(0); ielem < num_elems; ++ielem)
129 {
130 // loop over all local facets of this element
131 for(int loc_face(0); loc_face < faces_at_elem.num_indices; ++loc_face)
132 {
133 // only consider boundary faces = faces with 1 adjacent element
134 const Index iface = faces_at_elem(ielem, loc_face);
135 if(nfaces.at(iface) > 1)
136 continue;
137
138 // get the local facet's orientation
139 int ori = Intern::FacetCongruencySampler<Shape_>::compare(
140 verts_at_face, verts_at_elem, faces_at_elem, ielem, loc_face);
141
142 // if the facet is oriented negatively, we have to flip it
143 if(ori == 1)
144 continue;
145
146 // orientation must be +1 or -1
147 XASSERTM(ori == -1, "invalid facet orientation");
148
149 // okay, we have to flip all indices of this facet
150 Intern::FacetFlipRecurser<FacetType>::flip(facet_isw, iface);
151 }
152 }
153 }
154 }; // class FacetFlipper
155 } // namespace Geometry
156} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Helper class for reorienting boundary facets to be positive.
static void reorient(IndexSetHolder< Shape_ > &ish)
Reorients the boundary facets in the index set holder to be positive.
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.
Face traits tag struct template.
Definition: shape.hpp:106