FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
boundary_computer.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/index_set.hpp>
10#include <kernel/geometry/target_set.hpp>
11
12// includes, system
13#include <vector>
14
15namespace FEAT
16{
17 namespace Geometry
18 {
20 namespace Intern
21 {
22 template<
23 typename Shape_,
24 // Note: The shape_dim_ parameter *must* always be equal to Shape_::dimension !
25 int shape_dim_ = Shape_::dimension,
26 int cell_dim_ = shape_dim_>
27 class BoundaryFaceComputer :
28 public BoundaryFaceComputer<Shape_, shape_dim_, cell_dim_-1>
29 {
30 public:
31 typedef BoundaryFaceComputer<Shape_, shape_dim_, cell_dim_-1> BaseClass;
32 typedef std::array<std::vector<int>, std::size_t(shape_dim_)> BndMasksType;
33 typedef std::array<std::vector<Index>, std::size_t(shape_dim_)> FaceIdxType;
34
35 protected:
36 template<typename ParentIndexSetHolder_>
37 void _compute_mask(const ParentIndexSetHolder_& index_set_holder, BndMasksType& bnd_masks, const std::vector<Index>& facets)
38 {
39 // In this function, we compute all (cell_dim_-1)-dimensional faces of the mesh, which
40 // are adjacent to at least one of the boundary facets given in the facets vector.
41
42 // get the mask for this face dimension
43 std::vector<int>& mask = bnd_masks.at(std::size_t(cell_dim_-1));
44
45 const auto& face_index_set = index_set_holder.template get_index_set<shape_dim_-1, cell_dim_-1>();
46
47 // allocate a temporary vector; this stores the number of cells adjacent to each facet
48 mask.clear();
49 mask.resize(face_index_set.get_index_bound(), 0);
50
51 // loop over all boundary facets
52 for(Index i(0); i < Index(facets.size()); ++i)
53 {
54 for(int j(0); j < face_index_set.get_num_indices(); ++j)
55 ++mask[face_index_set(facets[i], j)];
56 }
57
58 BaseClass::_compute_mask(index_set_holder, bnd_masks, facets);
59 }
60
61 void _compute_faces(const BndMasksType& bnd_masks, FaceIdxType& face_idx)
62 {
63 // get the mask for this face dimension
64 const std::vector<int>& mask = bnd_masks.at(std::size_t(cell_dim_-1));
65 std::vector<Index>& faces = face_idx.at(std::size_t(cell_dim_-1));
66
67 // count the number of boundary faces
68 Index count(0);
69 for(Index i(0); i < Index(mask.size()); ++i)
70 {
71 if(mask[i] != 0)
72 ++count;
73 }
74
75 // allocate boundary face sets
76 faces.reserve(count);
77 for(Index i(0); i < Index(mask.size()); ++i)
78 {
79 if(mask[i] != 0)
80 faces.push_back(i);
81 }
82
83 // call base-class
84 BaseClass::_compute_faces(bnd_masks, face_idx);
85 }
86
87 public:
88 void fill_target_sets(TargetSetHolder<Shape_>& target_set_holder, const FaceIdxType& face_idx)
89 {
90 const std::vector<Index>& faces = face_idx.at(std::size_t(cell_dim_-1)) ;
91
92 TargetSet& target_set = target_set_holder.template get_target_set<cell_dim_-1>();
93 XASSERTM(target_set.get_num_entities() == Index(faces.size()), "invalid target set size");
94
95 for(Index i(0); i < target_set.get_num_entities(); ++i)
96 target_set[i] = faces[i];
97
98 BaseClass::fill_target_sets(target_set_holder, face_idx);
99 }
100
101 Index build_halo_buffer(std::vector<int>& buffer, const BndMasksType& bnd_masks, const TargetSetHolder<Shape_>& halo_trg_holder)
102 {
103 Index offset = BaseClass::build_halo_buffer(buffer, bnd_masks, halo_trg_holder);
104 const TargetSet& target_set = halo_trg_holder.template get_target_set<cell_dim_-1>();
105 const std::vector<int>& mask = bnd_masks.at(std::size_t(cell_dim_-1));
106 for(Index i(0); i < target_set.get_num_entities(); ++i, ++offset)
107 buffer[offset] = mask[target_set[i]];
108 return offset;
109 }
110
111 Index mask_halo_buffer(BndMasksType& bnd_masks, const std::vector<int>& buffer, const TargetSetHolder<Shape_>& halo_trg_holder)
112 {
113 Index offset = BaseClass::mask_halo_buffer(bnd_masks, buffer, halo_trg_holder);
114 const TargetSet& target_set = halo_trg_holder.template get_target_set<cell_dim_-1>();
115 std::vector<int>& mask = bnd_masks.at(std::size_t(cell_dim_-1));
116 for(Index i(0); i < target_set.get_num_entities(); ++i, ++offset)
117 {
118 if(buffer[offset] != 0)
119 mask[target_set[i]] = 1;
120 }
121 return offset;
122 }
123 }; // class BoundaryFaceComputer<...>
124
125 // Specialization for cell_dim_ = shape_dim_-1
126 template<typename Shape_, int shape_dim_>
127 class BoundaryFaceComputer<Shape_, shape_dim_, shape_dim_> :
128 public BoundaryFaceComputer<Shape_, shape_dim_, shape_dim_-1>
129 {
130 typedef BoundaryFaceComputer<Shape_, shape_dim_, shape_dim_-1> BaseClass;
131 typedef std::array<std::vector<int>, std::size_t(shape_dim_)> BndMasksType;
132 typedef std::array<std::vector<Index>, std::size_t(shape_dim_)> FaceIdxType;
133
134 public:
135 template<typename ParentIndexSetHolder_>
136 void compute_all(const ParentIndexSetHolder_& index_set_holder, BndMasksType& bnd_masks, FaceIdxType& face_idx)
137 {
138 // get the mask for this face dimension
139 std::vector<int>& mask = bnd_masks.at(std::size_t(shape_dim_-1));
140 std::vector<Index>& faces = face_idx.at(std::size_t(shape_dim_-1));
141
142 // Phase 1:
143 // Compute all facets, i.e. (n-1)-dimensional faces, which reside on the boundary.
144 // We do this by computing how many cells are adjacent to a particular facet.
145 // If the number of cells is exactly 1, the facet is a boundary facet.
146
147 const auto& face_index_set = index_set_holder.template get_index_set<shape_dim_, shape_dim_-1>();
148
149 // allocate a temporary vector; this stores the number of cells adjacent to each facet
150 mask.clear();
151 mask.resize(face_index_set.get_index_bound(), 0);
152
153 // loop over all cells of the mesh
154 for(Index i(0); i < face_index_set.get_num_entities(); ++i)
155 {
156 // loop over all facets adjacent to the current cell and increments its counter by one
157 for(int j(0); j < face_index_set.get_num_indices(); ++j)
158 ++mask[face_index_set(i,j)];
159 }
160
161 // count the number of boundary facets
162 Index count(0);
163 for(Index i(0); i < Index(mask.size()); ++i)
164 {
165 // for each conformal mesh, a facet must be adjacent to either 1 (boundary facet) or 2 (inner facet) cells.
166 ASSERTM((mask[i] > 0) && (mask[i] < 3), "invalid number of cells at facet");
167 if(mask[i] == 1)
168 ++count;
169 }
170
171 // allocate boundary facet sets
172 faces.reserve(count);
173 for(Index i(0); i < Index(mask.size()); ++i)
174 {
175 if(mask[i] == 1)
176 faces.push_back(i);
177 }
178
179 // Phase 2:
180 // Compute all lower-dimensional faces adjacent to any of our boundary facets.
181 BaseClass::_compute_mask(index_set_holder, bnd_masks, face_idx.back());
182 BaseClass::_compute_faces(bnd_masks, face_idx);
183 }
184
185 template<typename ParentIndexSetHolder_>
186 void compute_masks(const ParentIndexSetHolder_& index_set_holder, BndMasksType& bnd_masks, FaceIdxType& face_idx, const std::vector<int>& facet_mask)
187 {
188 // get the mask for this face dimension
189 std::vector<int>& mask = bnd_masks.at(std::size_t(shape_dim_-1));
190 std::vector<Index>& faces = face_idx.at(std::size_t(shape_dim_-1));
191
192 // Phase 1:
193 // Compute all facets, i.e. (n-1)-dimensional faces, which reside on the boundary.
194 // We do this by computing how many cells are adjacent to a particular facet.
195 // If the number of cells is exactly 1, the facet is a boundary facet.
196
197 const auto& face_index_set = index_set_holder.template get_index_set<shape_dim_, shape_dim_-1>();
198
199 // allocate a temporary vector; this stores the number of cells adjacent to each facet
200 mask.clear();
201 mask.resize(face_index_set.get_index_bound(), 0);
202
203 // loop over all cells of the mesh
204 for(Index i(0); i < face_index_set.get_num_entities(); ++i)
205 {
206 // loop over all facets adjacent to the current cell and increments its counter by one
207 for(int j(0); j < face_index_set.get_num_indices(); ++j)
208 ++mask[face_index_set(i,j)];
209 }
210
211 // reset all masked facets to 0, so that they won't be part of the created boundary mesh part
212 XASSERTM(facet_mask.size() == mask.size(), "invalid mask vector size");
213 for(std::size_t i(0); i < mask.size(); ++i)
214 mask[i] = (facet_mask[i] != 0 ? 0 : mask[i]);
215
216 // count the number of boundary facets
217 Index count(0);
218 for(Index i(0); i < Index(mask.size()); ++i)
219 {
220 // for each conformal mesh, a facet must be adjacent to either 1 (boundary facet) or 2 (inner facet) cells.
221 ASSERTM((facet_mask[i] != 0) || ((mask[i] > 0) && (mask[i] < 3)), "invalid number of cells at facet");
222 if(mask[i] == 1)
223 ++count;
224 }
225
226 // allocate boundary face sets
227 faces.reserve(count);
228 for(Index i(0); i < Index(mask.size()); ++i)
229 {
230 if(mask[i] == 1)
231 faces.push_back(i);
232 }
233
234 BaseClass::_compute_mask(index_set_holder, bnd_masks, faces);
235 }
236
237 void compute_faces(const BndMasksType& bnd_masks, FaceIdxType& face_idx)
238 {
239 // Compute all lower-dimensional faces adjacent to any of our boundary facets.
240 BaseClass::_compute_faces(bnd_masks, face_idx);
241 }
242
243 void fill_target_sets(TargetSetHolder<Shape_>& target_set_holder, const FaceIdxType& face_idx)
244 {
245 const std::vector<Index>& faces = face_idx.at(std::size_t(shape_dim_-1));
246
247 TargetSet& target_set = target_set_holder.template get_target_set<shape_dim_-1>();
248 XASSERTM(target_set.get_num_entities() == Index(faces.size()), "invalid target set size");
249
250 for(Index i(0); i < target_set.get_num_entities(); ++i)
251 target_set[i] = faces[i];
252
253 BaseClass::fill_target_sets(target_set_holder, face_idx);
254 }
255
256 Index build_halo_buffer(std::vector<int>& buffer, const BndMasksType& bnd_masks, const TargetSetHolder<Shape_>& halo_trg_holder)
257 {
258 Index offset = BaseClass::build_halo_buffer(buffer, bnd_masks, halo_trg_holder);
259 const TargetSet& target_set = halo_trg_holder.template get_target_set<shape_dim_-1>();
260 const std::vector<int>& mask = bnd_masks.at(std::size_t(shape_dim_-1));
261 for(Index i(0); i < target_set.get_num_entities(); ++i, ++offset)
262 buffer[offset] = mask[target_set[i]];
263 return offset;
264 }
265
266 Index mask_halo_buffer(BndMasksType& bnd_masks, const std::vector<int>& buffer, const TargetSetHolder<Shape_>& halo_trg_holder)
267 {
268 Index offset = BaseClass::mask_halo_buffer(bnd_masks, buffer, halo_trg_holder);
269 const TargetSet& target_set = halo_trg_holder.template get_target_set<shape_dim_-1>();
270 std::vector<int>& mask = bnd_masks.at(std::size_t(shape_dim_-1));
271 for(Index i(0); i < target_set.get_num_entities(); ++i, ++offset)
272 {
273 if(buffer[offset] == 1)
274 mask[target_set[i]] = 1;
275 }
276 return offset;
277 }
278 }; // class BoundaryFaceComputer<...,shape_dim_,shape_dim_-1>
279
280 // This class is required to terminate the inheritance recursion of the class.
281 template<typename Shape_, int shape_dim_>
282 class BoundaryFaceComputer<Shape_, shape_dim_, 0>
283 {
284 protected:
285 typedef std::array<std::vector<int>, std::size_t(shape_dim_)> BndMasksType;
286 typedef std::array<std::vector<Index>, std::size_t(shape_dim_)> FaceIdxType;
287
288 template<typename ParentIndexSetHolder_>
289 void _compute_mask(const ParentIndexSetHolder_&, BndMasksType&, const std::vector<Index>&)
290 {
291 // dummy
292 }
293
294 void _compute_faces(const BndMasksType&, FaceIdxType&)
295 {
296 // dummy
297 }
298
299 public:
300 void fill_target_sets(TargetSetHolder<Shape_>&, const FaceIdxType&)
301 {
302 // dummy
303 }
304
305 Index build_halo_buffer(std::vector<int>&, const BndMasksType&, const TargetSetHolder<Shape_>&)
306 {
307 return 0u;
308 }
309
310 Index mask_halo_buffer(BndMasksType&, const std::vector<int>&, const TargetSetHolder<Shape_>&)
311 {
312 return 0u;
313 }
314 }; // class BoundaryFaceComputer<...,0>
315 } // namespace Intern
317 } // namespace Geometry
318} // namespace FEAT
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
Definition: assertion.hpp:230
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.