FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
patch_halo_splitter.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/conformal_mesh.hpp>
9#include <kernel/geometry/mesh_part.hpp>
10#include <kernel/adjacency/graph.hpp>
11
12#include <vector>
13
14namespace FEAT
15{
16 namespace Geometry
17 {
19 namespace Intern
20 {
21 template<typename Shape_, int shape_dim_ = Shape_::dimension>
22 class PatchInvMapWrapper;
23
24 template<typename Shape_>
25 class PatchHaloSplitPart;
26 } // namespace Intern
28
32 template<typename Mesh_>
34
43 template<typename Shape_, int num_coords_, typename Coord_>
44 class PatchHaloSplitter<ConformalMesh<Shape_, num_coords_, Coord_>> :
45 public Geometry::Factory<Geometry::MeshPart<Geometry::ConformalMesh<Shape_, num_coords_, Coord_>>>
46 {
47 public:
49 typedef Shape_ ShapeType;
51 static constexpr int shape_dim = ShapeType::dimension;
56
57 protected:
58 typedef Intern::PatchHaloSplitPart<ShapeType> SplitHaloType;
64 std::vector<std::vector<Index>> _patch_inv_map;
66 std::map<int, std::shared_ptr<SplitHaloType>> _split_halos;
67
69 std::vector<std::vector<Index>> _isect_halo_idx;
70
71 public:
81 explicit PatchHaloSplitter(const MeshType& base_mesh, const MeshPartType& patch_mesh_part) :
82 _base_mesh(base_mesh),
83 _patch_mesh_part(patch_mesh_part),
84 _patch_inv_map(std::size_t(shape_dim+1)),
85 _isect_halo_idx(std::size_t(shape_dim+1))
86 {
87 // allocate inverse patch mapping
88 _patch_inv_map.resize(std::size_t(shape_dim+1));
89 for(int dim(0); dim <= shape_dim; ++dim)
90 {
91 _patch_inv_map.at(std::size_t(dim)).resize(_base_mesh.get_num_entities(dim), ~Index(0));
92 }
93 // build inverse patch mapping
94 Intern::PatchInvMapWrapper<ShapeType>::build(_patch_inv_map, patch_mesh_part.get_target_set_holder());
95 }
96
110 std::size_t add_halo(int halo_rank, const MeshPartType& halo)
111 {
112 // create new split halo object
113 auto sh = std::make_shared<SplitHaloType>();
114
115 // If the following function returns false, then this patch is not adjacent to that halo
116 if(!sh->split(_patch_inv_map, halo.get_target_set_holder()))
117 return std::size_t(0);
118
119 // okay, store halo and return split size
120 return _split_halos.emplace(halo_rank, sh).first->second->size();
121 }
122
135 std::vector<Index> serialize_split_halo(int halo_rank, int child_rank) const
136 {
137 const auto it = _split_halos.find(halo_rank);
138 XASSERT(it != _split_halos.end());
139
140 std::vector<Index> buffer;
141 it->second->serialize(buffer, child_rank);
142 return buffer;
143 }
144
161 bool intersect_split_halo(int halo_rank, const std::vector<Index>& buffer, const Index buffer_offset)
162 {
163 // clear all intersection indices
164 for(auto& x : _isect_halo_idx)
165 x.clear();
166
167 const auto it = _split_halos.find(halo_rank);
168 if(it == _split_halos.end())
169 return false;
170
171 // try to intersect
172 return it->second->intersect(_isect_halo_idx, buffer, std::size_t(buffer_offset));
173 }
174
175 /* *************************************************************************************** */
176 /* F A C T O R Y I N T E R F A C E I M P L E M E N T A T I O N */
177 /* *************************************************************************************** */
178
179 virtual Index get_num_entities(int dim) override
180 {
181 return Index(_isect_halo_idx.at(std::size_t(dim)).size());
182 }
183
184 virtual void fill_attribute_sets(typename MeshPartType::AttributeSetContainer& /*attribute_container*/) override
185 {
186 // no attributes for halo mesh-parts
187 }
188
189 virtual void fill_index_sets(std::unique_ptr<typename MeshPartType::IndexSetHolderType>& index_set_holder) override
190 {
191 XASSERT(index_set_holder.get() == nullptr);
192 // no index sets for halo mesh-parts
193 }
194
195 virtual void fill_target_sets(typename MeshPartType::TargetSetHolderType& target_set_holder) override
196 {
197 Intern::PatchInvMapWrapper<ShapeType>::fill(target_set_holder, _isect_halo_idx);
198 }
199 }; // class PatchHaloSplitter<ConformalMesh<...>>
200
202 namespace Intern
203 {
204 //template<int shape_dim_>
205 class PatchInvMap
206 {
207 public:
208 static void build(std::vector<Index>& pim, const TargetSet& ts)
209 {
210 for(Index i(0); i < ts.get_num_entities(); ++i)
211 pim[ts[i]] = i;
212 }
213
214 static bool split(std::vector<Index>& shi, std::vector<Index>& spi, const std::vector<Index>& pim, const TargetSet& ts)
215 {
216 shi.reserve(ts.get_num_entities());
217 spi.reserve(ts.get_num_entities());
218
219 for(Index i(0); i < ts.get_num_entities(); ++i)
220 {
221 const Index patch_idx = pim[ts[i]];
222 if(patch_idx != ~Index(0))
223 {
224 spi.push_back(patch_idx);
225 shi.push_back(i);
226 }
227 }
228
229 return !spi.empty();
230 }
231
232 static void fill(TargetSet& trg, const std::vector<Index>& idx)
233 {
234 const Index n = trg.get_num_entities();
235 XASSERT(n == Index(idx.size()));
236 for(Index i(0); i < n; ++i)
237 trg[i] = idx[std::size_t(i)];
238 }
239 }; // class PatchInvMap
240
241 template<typename Shape_, int shape_dim_>
242 class PatchInvMapWrapper
243 {
244 public:
245 static_assert(shape_dim_ > 0, "invalid shape dimension");
246 static void build(std::vector<std::vector<Index>>& pim, const TargetSetHolder<Shape_>& tsh)
247 {
248 PatchInvMapWrapper<Shape_, shape_dim_-1>::build(pim, tsh);
249 PatchInvMap::build(pim.at(std::size_t(shape_dim_)), tsh.template get_target_set<shape_dim_>());
250 }
251
252 static bool split(
253 std::vector<std::vector<Index>>& shi, std::vector<std::vector<Index>>& spi,
254 const std::vector<std::vector<Index>>& pim, const TargetSetHolder<Shape_>& tsh)
255 {
256 bool have = PatchInvMapWrapper<Shape_, shape_dim_-1>::split(shi, spi, pim, tsh);
257 const std::size_t k = std::size_t(shape_dim_);
258 return PatchInvMap::split(shi.at(k), spi.at(k), pim.at(k), tsh.template get_target_set<shape_dim_>()) || have;
259 }
260
261 static void fill(TargetSetHolder<Shape_>& tsh, const std::vector<std::vector<Index>>& idx)
262 {
263 PatchInvMapWrapper<Shape_, shape_dim_-1>::fill(tsh, idx);
264 PatchInvMap::fill(tsh.template get_target_set<shape_dim_>(), idx.at(std::size_t(shape_dim_)));
265 }
266 };
267
268 template<typename Shape_>
269 class PatchInvMapWrapper<Shape_, 0>
270 {
271 public:
272 static void build(std::vector<std::vector<Index>>& pim, const TargetSetHolder<Shape_>& tsh)
273 {
274 PatchInvMap::build(pim.at(std::size_t(0)), tsh.template get_target_set<0>());
275 }
276 static bool split(
277 std::vector<std::vector<Index>>& shi, std::vector<std::vector<Index>>& spi,
278 const std::vector<std::vector<Index>>& pim, const TargetSetHolder<Shape_>& tsh)
279 {
280 const std::size_t k = std::size_t(0);
281 return PatchInvMap::split(shi.at(k), spi.at(k), pim.at(k), tsh.template get_target_set<0>());
282 }
283
284 static void fill(TargetSetHolder<Shape_>& tsh, const std::vector<std::vector<Index>>& idx)
285 {
286 PatchInvMap::fill(tsh.template get_target_set<0>(), idx.at(std::size_t(0)));
287 }
288 };
289
290 template<typename Shape_>
291 class PatchHaloSplitPart
292 {
293 protected:
294 static constexpr int shape_dim = Shape_::dimension;
295
297 std::vector<std::vector<Index>> _halo_idx;
299 std::vector<std::vector<Index>> _patch_idx;
300
301 public:
302 explicit PatchHaloSplitPart()
303 {
304 std::size_t sdim = std::size_t(shape_dim+1);
305 _halo_idx.resize(sdim);
306 _patch_idx.resize(sdim);
307 }
308
309 bool split(const std::vector<std::vector<Index>>& pim, const TargetSetHolder<Shape_>& tsh)
310 {
311 return PatchInvMapWrapper<Shape_>::split(_halo_idx, _patch_idx, pim, tsh);
312 }
313
314 std::size_t size() const
315 {
316 std::size_t s = std::size_t(0);
317 for(const auto& x : _halo_idx)
318 s += x.size();
319
320 // s == 0 ==> patch and halo are disjoint
321 return s == std::size_t(0) ? s : ++s + _halo_idx.size();
322 }
323
324 void serialize(std::vector<Index>& buffer, int child_rank)
325 {
326 const std::size_t s = this->size();
327 if(this->size() == std::size_t(0))
328 return;
329
330 if(buffer.capacity() < buffer.size() + s)
331 buffer.reserve(buffer.size() + s);
332
333 buffer.push_back(Index(child_rank));
334
335 for(std::size_t i(0); i < _halo_idx.size(); ++i)
336 buffer.push_back(Index(_halo_idx.at(i).size()));
337
338 for(std::size_t i(0); i < _halo_idx.size(); ++i)
339 {
340 const std::vector<Index>& v = _halo_idx.at(i);
341 for(std::size_t j(0); j < v.size(); ++j)
342 buffer.push_back(v[j]);
343 }
344 }
345
346 bool intersect(std::vector<std::vector<Index>>& isect, const std::vector<Index>& other, const std::size_t offset) const
347 {
348 // offset of first index within other halo
349 std::size_t off = offset + std::size_t(shape_dim+2);
350
351 bool ret = false;
352
353 // compute offsets from sizes
354 for(std::size_t i(0); i <= std::size_t(shape_dim); ++i)
355 {
356 // get index counts
357 const std::size_t n_1 = _halo_idx.at(i).size();
358 const std::size_t n_2 = other.at(offset+i+1u);
359
360 // get the minimum of both
361 const std::size_t n_min = Math::min(n_1, n_2);
362 if(n_min == std::size_t(0))
363 {
364 off += n_2;
365 continue;
366 }
367
368 // get my halo indices
369 const Index* idx_1 = _halo_idx.at(i).data();
370 const Index* idx_2 = &other.data()[off];
371 const Index* idx_p = _patch_idx.at(i).data();
372
373 // intersect idx_1 and idx_2
374 std::vector<Index>& idx = isect.at(i);
375 idx.reserve(n_min);
376 for(std::size_t j_1(0), j_2(0); (j_1 < n_1) && (j_2 < n_2); )
377 {
378 if(idx_1[j_1] < idx_2[j_2])
379 ++j_1;
380 else if(idx_1[j_1] > idx_2[j_2])
381 ++j_2;
382 else
383 {
384 // match; store halo index w.r.t. patch
385 idx.push_back(idx_p[j_1]);
386 ++j_1;
387 ++j_2;
388 ret = true;
389 }
390 }
391
392 off += n_2;
393 }
394
395 // okay
396 return ret;
397 }
398 };
399 } // namespace Intern
401
402 } // namespace Geometry
403} // namespace FEAT
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
Conformal mesh class template.
Index get_num_entities(int dim) const
Returns the number of entities.
Mesh Factory class template.
Definition: factory.hpp:33
Class template for partial meshes.
Definition: mesh_part.hpp:90
const MeshPartType & _patch_mesh_part
The MeshPart identifying this patch.
std::vector< Index > serialize_split_halo(int halo_rank, int child_rank) const
Serializes a split halo into a buffer.
std::map< int, std::shared_ptr< SplitHaloType > > _split_halos
split halos
PatchHaloSplitter(const MeshType &base_mesh, const MeshPartType &patch_mesh_part)
Creates the halo splitter.
bool intersect_split_halo(int halo_rank, const std::vector< Index > &buffer, const Index buffer_offset)
Intersects a foreign split halo with the split halo of this patch.
std::size_t add_halo(int halo_rank, const MeshPartType &halo)
Adds a base-mesh halo to the splitter and returns the required buffer size.
Geometry::ConformalMesh< Shape_, num_coords_, Coord_ > MeshType
The mesh type.
std::vector< std::vector< Index > > _isect_halo_idx
intersected halo indices
std::vector< std::vector< Index > > _patch_inv_map
inverse patch mapping
Base-Mesh Patch Halo splitter.
@ other
generic/other permutation strategy
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.