8#include <kernel/geometry/unit_cube_patch_generator.hpp>
9#include <control/domain/domain_control.hpp>
20 template<
typename DomainLevel_>
27 typedef typename BaseClass::LevelType LevelType;
28 typedef typename BaseClass::MeshType MeshType;
30 typedef typename BaseClass::MeshNodeType MeshNodeType;
36 int rank = comm_.
rank();
37 int nprocs = comm_.
size();
39 this->_layers.push_back(std::make_shared<LayerType>(comm_.
comm_dup(), 0));
40 this->_layer_levels.resize(std::size_t(1));
43 std::vector<int> ranks;
46 std::unique_ptr<MeshNodeType> mesh_node;
50 this->_layers.front()->set_neighbor_ranks(ranks);
55 lvl_min =
Math::max(lvl_max + lvl_min + 1, 0);
60 for(; lvl < lvl_min; ++lvl)
62 mesh_node = mesh_node->refine_unique();
66 this->_layer_levels.front().push_front(std::make_shared<LevelType>(lvl, std::move(mesh_node)));
73 this->_layer_levels.front().push_front(std::make_shared<LevelType>(++lvl,
74 this->_layer_levels.front().front()->get_mesh_node()->refine_unique()));
78 this->compile_virtual_levels();
83 template<
typename DomainLevel_>
90 typedef typename BaseClass::LevelType LevelType;
91 typedef typename BaseClass::MeshType MeshType;
96 static_assert(MeshType::shape_dim == 2,
"HierarchUnitCubeDomainControl works only for 2D meshes");
108 std::deque<int> ilvls;
111 ilvls.resize(lvls.size());
112 for(std::size_t i(0); i < lvls.size(); ++i)
114 if(!lvls.at(i).parse(ilvls.at(i)))
116 comm_.
print(std::cerr,
"ERROR: failed to parse '" + lvls.at(i) +
"' as level");
120 if(ilvls.size() < std::size_t(2))
127 static int _ilog4(
int x)
140 static int _2lvl2lexi(
int rank,
int size)
142 const int ls = _ilog4(size);
144 for(
int i(0); i < ls; ++i)
146 ix |= (rank >> (i+0)) & (1 << i);
147 iy |= (rank >> (i+1)) & (1 << i);
149 return iy*(1 << ls) + ix;
153 static void _lexi22lvl(std::vector<int>& ranks, std::map<int,int>& reranks,
int size)
155 const int ls = _ilog4(size);
156 for(
auto& rank : ranks)
158 const int ix = rank % (1 << ls);
159 const int iy = rank / (1 << ls);
161 for(
int i(0); i < ls; ++i)
163 rr |= (ix & (1 << i)) << (i+0);
164 rr |= (iy & (1 << i)) << (i+1);
166 reranks.insert(std::make_pair(rank, rr));
171 void _create(
const std::deque<int>& lvls)
173 const int log4n = _ilog4(this->_comm.
size());
174 XASSERTM(log4n >= 0,
"number of processes must be a power of 4");
179 _create_layers(log4n,
int(lvls.size())-1);
181 this->_layer_levels.resize(this->_layers.size());
184 for(std::size_t i(0); i < this->_layers.size(); ++i)
186 auto& layer = *this->_layers.at(i);
187 auto& laylevs = this->_layer_levels.at(i);
189 const int csize = layer.comm().size();
190 const int crank = _2lvl2lexi(layer.comm().rank(), csize);
192 std::vector<int> ranks;
193 std::map<int,int> reranks;
196 std::unique_ptr<MeshNodeType> mesh_node;
200 _lexi22lvl(ranks, reranks, csize);
203 mesh_node->rename_halos(reranks);
206 layer.set_neighbor_ranks(ranks);
209 laylevs.push_front(std::make_shared<LevelType>(base_lvl, mesh_node));
212 if(i > std::size_t(0))
214 std::shared_ptr<MeshNodeType> ref_node = std::shared_ptr<MeshNodeType>(laylevs.front()->get_mesh_node()->refine());
215 this->_create_child_meshparts(layer, ref_node);
216 laylevs.push_front(std::make_shared<LevelType>(base_lvl+1, ref_node));
219 const int head_lvl = laylevs.front()->get_level_index();
220 const int fin_lvl = lvls.at(i);
221 const int crs_lvl = lvls.at(i+1);
224 for(
int l(head_lvl); l < fin_lvl; ++l)
226 std::shared_ptr<MeshNodeType> ref_node = std::shared_ptr<MeshNodeType>(laylevs.front()->get_mesh_node()->refine());
227 laylevs.push_front(std::make_shared<LevelType>(l+1, ref_node));
231 for(
int l(base_lvl); l < crs_lvl; ++l)
238 this->compile_virtual_levels();
241 void _create_layers(
int ,
int nlayers)
244 this->_layers.push_back(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
247 for(
int i(0); (i+1) < nlayers; ++i)
256 const int rank = comm_c.
rank();
263 child.set_parent(std::move(comm_s), 0);
271 this->_layers.push_back(std::make_shared<DomainLayer>(std::move(comm_p), i+1));
275 void _create_child_meshparts(
const DomainLayer& , std::shared_ptr<MeshNodeType> mesh_node)
277 Index num_elems = mesh_node->get_mesh()->get_num_elements();
280 const Index num_entities[] = {4, 4, 1};
282 const Index ivert[4][4] =
289 const Index iedge[4][4] =
297 for(
int i(0); i < 4; ++i)
302 Index* iv = part->template get_target_set<0>().get_indices();
303 Index* ie = part->template get_target_set<1>().get_indices();
304 Index* iq = part->template get_target_set<2>().get_indices();
305 for(
int j(0); j < 4; ++j)
312 mesh_node->add_patch(i, part);
318 template<
typename DomainLevel_>
325 typedef typename BaseClass::LevelType LevelType;
326 typedef typename BaseClass::MeshType MeshType;
331 static_assert(MeshType::shape_dim == 2,
"HierarchUnitCubeDomainControl works only for 2D meshes");
343 std::deque<int> ilvls, ilyrs;
346 ilvls.resize(lvls.size());
347 ilyrs.resize(lvls.size(), 1);
348 for(std::size_t i(0); i < lvls.size(); ++i)
350 std::deque<String> parts = lvls.at(i).split_by_string(
":");
351 if(!parts.front().parse(ilvls.at(i)))
353 comm_.
print(std::cerr,
"ERROR: failed to parse '" + lvls.at(i) +
"' as level");
356 if((parts.size() > std::size_t(1)) && !parts.back().parse(ilyrs.at(i)))
358 comm_.
print(std::cerr,
"ERROR: failed to parse '" + lvls.at(i) +
"' as layer");
362 if(ilvls.size() < std::size_t(2))
368 _create(ilvls, ilyrs);
374 std::deque<int> ilvls, ilyrs;
377 ilvls.resize(lvls.size());
378 ilyrs.resize(lvls.size(), 1);
379 for(std::size_t i(0); i < lvls.size(); ++i)
381 std::deque<String> parts = lvls.at(i).split_by_string(
":");
382 if(!parts.front().parse(ilvls.at(i)))
384 comm_.
print(std::cerr,
"ERROR: failed to parse '" + lvls.at(i) +
"' as level");
387 if((parts.size() > std::size_t(1)) && !parts.back().parse(ilyrs.at(i)))
389 comm_.
print(std::cerr,
"ERROR: failed to parse '" + lvls.at(i) +
"' as layer");
393 if(ilvls.size() < std::size_t(2))
399 _create(ilvls, ilyrs);
402 std::deque<std::pair<int,int>> get_level_indices()
const
404 std::deque<std::pair<int,int>> lvs;
405 for(std::size_t i(0); i < this->_layer_levels.size(); ++i)
408 this->_layer_levels.at(i).front()->get_level_index(),
409 this->_layers.at(i)->comm().size()));
412 this->_layer_levels.back().back()->get_level_index(),
413 this->_layers.back()->comm().size()));
418 static int _ilog4(
int x)
431 static int _2lvl2lexi(
int rank,
int size)
433 const int ls = _ilog4(size);
435 for(
int i(0); i < ls; ++i)
437 ix |= (rank >> (i+0)) & (1 << i);
438 iy |= (rank >> (i+1)) & (1 << i);
440 return iy*(1 << ls) + ix;
444 static void _lexi22lvl(std::vector<int>& ranks, std::map<int,int>& reranks,
int size)
446 const int ls = _ilog4(size);
447 for(
auto& rank : ranks)
449 const int ix = rank % (1 << ls);
450 const int iy = rank / (1 << ls);
452 for(
int i(0); i < ls; ++i)
454 rr |= (ix & (1 << i)) << (i+0);
455 rr |= (iy & (1 << i)) << (i+1);
457 reranks.insert(std::make_pair(rank, rr));
462 void _create(
const std::deque<int>& lvls,
const std::deque<int>& lyrs)
464 const int log4n = _ilog4(this->_comm.
size());
465 XASSERTM(log4n >= 0,
"number of processes must be a power of 4");
468 XASSERT(lvls.size() == lyrs.size());
471 _create_layers(lyrs);
473 this->_layer_levels.resize(this->_layers.size());
476 for(std::size_t i(0); i < this->_layers.size(); ++i)
478 auto& layer = *this->_layers.at(i);
479 auto& laylevs = this->_layer_levels.at(i);
481 const int csize = layer.comm().size();
482 const int crank = _2lvl2lexi(layer.comm().rank(), csize);
484 std::vector<int> ranks;
485 std::map<int,int> reranks;
488 std::unique_ptr<MeshNodeType> mesh_node;
492 _lexi22lvl(ranks, reranks, csize);
495 mesh_node->rename_halos(reranks);
498 layer.set_neighbor_ranks(ranks);
501 laylevs.push_front(std::make_shared<LevelType>(base_lvl, std::move(mesh_node)));
504 if(i > std::size_t(0))
506 int children = this->_layers.at(i-1)->comm().size() / csize;
507 int crs_lvl = base_lvl;
508 for(
int nel(1); nel < children; nel *= 4)
513 laylevs.push_front(std::make_shared<LevelType>(++crs_lvl, laylevs.front()->get_mesh_node()->refine_unique()));
515 this->_create_child_meshparts(*laylevs.front()->get_mesh_node());
518 const int head_lvl = laylevs.front()->get_level_index();
519 const int fin_lvl = lvls.at(i);
520 const int crs_lvl = lvls.at(i+1);
523 for(
int l(head_lvl); l < fin_lvl; ++l)
527 laylevs.push_front(std::make_shared<LevelType>(l+1, laylevs.front()->get_mesh_node()->refine_unique()));
531 for(
int l(base_lvl); l < crs_lvl; ++l)
538 this->compile_virtual_levels();
541 void _create_layers(
const std::deque<int>& lyrs)
544 this->_layers.push_back(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
547 for(
int ilay(1); (ilay+1) <
int(lyrs.size()); ++ilay)
556 const int rank = comm_c.
rank();
559 const int nsib =
Math::sqr(1 << lyrs.at(std::size_t(ilay)));
567 child.set_parent(std::move(comm_s), 0);
575 this->_layers.push_back(std::make_shared<DomainLayer>(std::move(comm_p), ilay));
581 const Index num_elems = mesh_node.
get_mesh()->get_num_elements();
583 const Index num_entities[] = {4, 4, 1};
584 const auto& ivert = mesh_node.
get_mesh()->template get_index_set<2,0>();
585 const auto& iedge = mesh_node.
get_mesh()->template get_index_set<2,1>();
587 for(
Index i(0); i < num_elems; ++i)
589 std::unique_ptr<MeshPartType> part(
new MeshPartType(num_entities,
false));
592 Index* iv = part->template get_target_set<0>().get_indices();
593 Index* ie = part->template get_target_set<1>().get_indices();
594 Index* iq = part->template get_target_set<2>().get_indices();
596 for(
int j(0); j < 4; ++j)
603 mesh_node.
add_patch(
int(i), std::move(part));
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Domain control base-class template.
Comm comm_create_range_incl(int count, int first=0, int stride=1) const
Creates a new sub-communicator from a strided range of ranks.
int size() const
Returns the size of this communicator.
Comm comm_dup() const
Creates a copy of this communicator.
int rank() const
Returns the rank of this process in this communicator.
bool is_null() const
Checks whether this communicator is a null communicator.
void print(std::ostream &os, const String &msg, int root=0) const
Prints a message line to an output stream.
MeshType * get_mesh()
Returns the mesh of this node.
Class template for partial meshes.
Root mesh node class template.
MeshPartType * add_patch(int rank, std::unique_ptr< MeshPartType > patch_part)
Adds a patch mesh part to this mesh node.
static void abort(bool dump_call_stack=true)
FEAT abortion.
@ child
indicates that the level is a child level
T_ sqr(T_ x)
Returns the square of a value.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
std::uint64_t Index
Index data type.