9#include <kernel/util/dist.hpp>
10#include <kernel/util/dist_file_io.hpp>
11#include <kernel/util/stop_watch.hpp>
12#include <kernel/runtime.hpp>
13#include <kernel/util/simple_arg_parser.hpp>
14#include <kernel/util/property_map.hpp>
15#include <kernel/util/statistics.hpp>
16#include <kernel/geometry/mesh_node.hpp>
17#include <kernel/geometry/mesh_file_reader.hpp>
18#include <kernel/geometry/partition_set.hpp>
19#include <kernel/geometry/parti_2lvl.hpp>
20#include <kernel/geometry/parti_iterative.hpp>
21#include <kernel/geometry/parti_parmetis.hpp>
22#include <kernel/geometry/parti_zoltan.hpp>
23#include <kernel/geometry/common_factories.hpp>
24#include <kernel/geometry/patch_mesh_factory.hpp>
25#include <kernel/geometry/patch_meshpart_factory.hpp>
26#include <kernel/geometry/patch_meshpart_splitter.hpp>
27#include <kernel/geometry/cgal.hpp>
28#include <kernel/geometry/voxel_map.hpp>
30#include <control/domain/parti_domain_control_base.hpp>
48 template<
typename DomainLevel_>
56 using typename BaseClass::MeshType;
58 using typename BaseClass::MeshNodeType;
86 slag_level = std::make_shared<DomainLevel_>(_lvl_idx, std::move(slag_node));
95 template<
typename DomainLevel_>
103 using typename BaseClass::LevelType;
107 using typename BaseClass::MeshType;
186 this->_keep_voxel_map =
true;
223 XASSERTM(
shape_dim == 2,
"invalid dimension: this function can only be called for 2D domains!");
236 _bbox_max[0] = x_max;
238 _bbox_max[1] = y_max;
246 Index n = vtx.get_num_vertices();
247 for(
Index i(0); i < n; ++i)
249 vtx[i][0] = x_min + (x_max - x_min) * vtx[i][0];
250 vtx[i][1] = y_min + (y_max - y_min) * vtx[i][1];
256 this->_create_stage = 1;
290 XASSERTM(
shape_dim == 3,
"invalid dimension: this function can only be called for 3D domains!");
306 _bbox_max[0] = x_max;
308 _bbox_max[1] = y_max;
310 _bbox_max[2] = z_max;
318 Index n = vtx.get_num_vertices();
319 for(
Index i(0); i < n; ++i)
321 vtx[i][0] = x_min + (x_max - x_min) * vtx[i][0];
322 vtx[i][1] = y_min + (y_max - y_min) * vtx[i][1];
323 vtx[i][2] = z_min + (z_max - z_min) * vtx[i][2];
329 this->_create_stage = 1;
335 MeshNodeType& set_base_mesh(std::unique_ptr<MeshNodeType>&& mesh_node)
342 for(std::size_t k = 0; k < std::size_t(
shape_dim); ++k)
354 Index n = vtx.get_num_vertices();
355 for(
Index i(0); i < n; ++i)
360 _bbox_max[k] =
Math::max(_bbox_max[k], vtx[i][k]);
367 this->_create_stage = 1;
370 this->_unstructered_mesh =
true;
387 this->_voxel_map->set_out_of_bounds_value(
value);
411 XASSERTM(this->_create_stage >= 1,
"invalid creation stage; create the base-mesh first");
412 XASSERTM(this->_create_stage <= 1,
"invalid creation stage: voxel map already set");
414 this->_watch_create_voxel_map.
start();
415#ifdef FEAT_COMPILER_CLANG
418 this->_voxel_map = std::make_unique<Geometry::VoxelMap>();
421 this->_voxel_map->compute_map(this->_comm, masker,
true);
422 this->_watch_create_voxel_map.
stop();
425 this->_create_stage = 2;
449 template<
typename Lambda_>
452 XASSERTM(this->_create_stage >= 1,
"invalid creation stage; create the base-mesh first");
453 XASSERTM(this->_create_stage <= 1,
"invalid creation stage: voxel map already set");
455 this->_watch_create_voxel_map.
start();
456#ifdef FEAT_COMPILER_CLANG
459 this->_voxel_map = std::make_unique<Geometry::VoxelMap>();
463 this->_voxel_map->compute_map_from_lambda_2d(this->_comm, std::forward<Lambda_>(lambda),
true);
465 this->_voxel_map->compute_map_from_lambda_3d(this->_comm, std::forward<Lambda_>(lambda),
true);
466 this->_watch_create_voxel_map.
stop();
469 this->_create_stage = 2;
494 XASSERTM(this->_create_stage >= 1,
"invalid creation stage; create the base-mesh first");
495 XASSERTM(this->_create_stage <= 1,
"invalid creation stage: voxel map already set");
497 this->_watch_create_voxel_map.
start();
498#ifdef FEAT_COMPILER_CLANG
501 this->_voxel_map = std::make_unique<Geometry::VoxelMap>();
504 this->_voxel_map->compute_map_from_chart(this->_comm, chart, invert,
true);
505 this->_watch_create_voxel_map.
stop();
508 this->_create_stage = 2;
534 std::stringstream sstr;
564 XASSERTM(this->_create_stage >= 1,
"invalid creation stage; create the base-mesh first");
565 XASSERTM(this->_create_stage <= 1,
"invalid creation stage: voxel map already set");
570 this->_watch_create_voxel_map.
start();
572#ifdef FEAT_COMPILER_CLANG
575 this->_voxel_map = std::make_unique<Geometry::VoxelMap>();
578 this->_voxel_map->compute_map_from_off_3d(this->_comm, is, invert,
true);
580 this->_watch_create_voxel_map.
stop();
583 this->_create_stage = 2;
597 XASSERTM(this->_create_stage >= 1,
"invalid creation stage; create the base-mesh first");
598 XASSERTM(this->_create_stage <= 1,
"invalid creation stage: voxel map already set");
600 this->_watch_create_voxel_map.
start();
602#ifdef FEAT_COMPILER_CLANG
605 this->_voxel_map = std::make_unique<Geometry::VoxelMap>();
609 this->_watch_create_voxel_map.
stop();
612 this->_create_stage = 2;
628 XASSERTM(this->_voxel_map,
"voxel map not created yet");
629 return this->_voxel_map->write(filename);
640 XASSERTM(this->_create_stage >= 2,
"invalid creation stage; create the base-mesh and voxel map first");
641 XASSERTM(this->_create_stage <= 2,
"invalid creation stage: domain hierarchy already created");
643 this->_watch_create_hierarchy.
start();
647 if(this->_comm.
size() == 1)
671 this->compile_virtual_levels();
673 this->_watch_create_hierarchy.
stop();
677 this->_watch_create_voxel_map.
elapsed() + this->_watch_create_hierarchy.
elapsed();
680 this->_create_stage = 3;
684 if(!this->_keep_voxel_map)
685 this->_voxel_map.reset();
697 return this->_watch_create_voxel_map;
703 return this->_watch_create_hierarchy;
725 XASSERTM(this->_create_stage == 3,
"domain level hierarchy has to be created before the vertex mask can be computed");
726 XASSERT(level < this->size_physical());
728 const auto& vtx = this->at(level)->get_mesh().get_vertex_set();
729 const Index nv = vtx.get_num_vertices();
730 std::vector<int> mask(nv, 0);
732 for(
Index i(0); i < nv; ++i)
733 mask[i] = this->_voxel_map->check_point_nearest(vtx[i]);
753 XASSERT(level < this->size_physical());
763 for(
auto it = this->_layer_levels.begin(); it != this->_layer_levels.end(); ++it)
765 if(it != this->_layer_levels.begin())
767 for(
auto jt = it->begin(); jt != it->end(); ++jt)
769 msg +=
" " +
stringify((*jt)->get_level_index());
773 if((*jt)->slag_level)
774 ((msg +=
"<[") +=
stringify((*jt)->slag_level->get_mesh().get_num_elements()).pad_front(4)) +=
"]";
789 virtual void create(
const std::deque<String>& filenames,
String dirpath =
"")
792 ASSERTM(
false,
"Thou shall not arrive here!");
806 ASSERTM(
false,
"Thou shall not arrive here!");
815 virtual void create(std::unique_ptr<MeshNodeType>&)
818 ASSERTM(
false,
"Thou shall not arrive here!");
829 this->_voxel_map->set_bounding_box_2d(this->_bbox_min[0], this->_bbox_max[0], this->_bbox_min[1], this->_bbox_max[1]);
831 this->_voxel_map->set_bounding_box_3d(this->_bbox_min[0], this->_bbox_max[0],
832 this->_bbox_min[1], this->_bbox_max[1], this->_bbox_min[2], this->_bbox_max[2]);
835 if(resolution >
Real(0))
837 this->_voxel_map->set_resolution(resolution);
842 XABORTM(
"Required to provide resolution for voxel map");
847 Real base_res = (this->_bbox_max[0] - this->_bbox_min[0]) /
Real(this->_base_slices[0]);
849 base_res =
Math::min(base_res, this->_bbox_max[i] - this->_bbox_min[i]) /
Real(this->_base_slices[std::size_t(i)]);
871 const Index num_elems = mesh.get_num_elements();
874 std::vector<Index> masked_elems;
875 masked_elems.reserve(num_elems);
878 const auto& vtx = mesh.get_vertex_set();
879 const auto& verts_at_elem = mesh.template get_index_set<shape_dim, 0>();
885 for(
Index ielem(0); ielem < num_elems; ++ielem)
895 elbox_min = elbox_max = vtx[verts_at_elem(ielem, 0)];
896 for(
int j(1); j < verts_at_elem.num_indices; ++j)
898 const auto& v = vtx[verts_at_elem(ielem, j)];
904 if(this->_voxel_map->check_box(elbox_min, elbox_max))
905 masked_elems.push_back(ielem);
930 const Index num_elems = mesh.get_num_elements();
933 const Index elems_per_rank = num_elems/num_procs +
Index((num_elems%num_procs)>0u);
936 std::vector<Index> masked_elems;
937 masked_elems.reserve(elems_per_rank);
940 const auto& vtx = mesh.get_vertex_set();
941 const auto& verts_at_elem = mesh.template get_index_set<shape_dim, 0>();
947 for(
Index ielem = cur_rank*elems_per_rank; ielem <
Math::min((cur_rank+1u)*elems_per_rank, num_elems); ++ielem)
957 elbox_min = elbox_max = vtx[verts_at_elem(ielem, 0)];
958 for(
int j(1); j < verts_at_elem.num_indices; ++j)
960 const auto& v = vtx[verts_at_elem(ielem, j)];
966 if(this->_voxel_map->check_box(elbox_min, elbox_max))
967 masked_elems.push_back(ielem);
971 std::vector<int> recv_sizes(num_procs);
972 recv_sizes.at(cur_rank) = int(masked_elems.size());
974 sibling_comm.
allgather(recv_sizes.data(), 1, recv_sizes.data(), 1);
977 std::vector<Index> gathered_mask(std::size_t(std::accumulate(recv_sizes.begin(), recv_sizes.end(), 0)), 0u);
980 std::vector<int> displacements;
981 displacements.reserve(recv_sizes.size());
982 std::exclusive_scan(recv_sizes.begin(), recv_sizes.end(), std::back_inserter(displacements), 0);
985 sibling_comm.
allgatherv(masked_elems.data(), masked_elems.size(), gathered_mask.data(), recv_sizes.data(), displacements.data());
988 return gathered_mask;
1006 const Index num_elems = mesh.get_num_elements();
1009 std::vector<WeightType> weights(num_elems, 0.0);
1012 const auto& vtx = mesh.get_vertex_set();
1013 const auto& verts_at_elem = mesh.template get_index_set<shape_dim, 0>();
1019 for(
Index ielem(0); ielem < num_elems; ++ielem)
1029 elbox_min = elbox_max = vtx[verts_at_elem(ielem, 0)];
1030 for(
int j(1); j < verts_at_elem.num_indices; ++j)
1032 const auto& v = vtx[verts_at_elem(ielem, j)];
1038 weights[ielem] = this->_voxel_map->sample_box(elbox_min, elbox_max);
1062 XASSERTM(mesh_node.
get_halo_map().empty(),
"This function must not be used for partitioned mesh nodes!");
1086 const auto* prod_comm = is_child ? &ancestor.
progeny_comm :
nullptr;
1117 const std::map<int, std::unique_ptr<MeshPartType>>& base_halo_map = base_mesh_node.
get_halo_map();
1120 if(base_halo_map.empty())
1124 const std::size_t num_halos = base_halo_map.size();
1130 std::vector<int> halo_ranks;
1131 std::vector<std::size_t> halo_send_sizes;
1132 for(
auto it = base_halo_map.begin(); it != base_halo_map.end(); ++it)
1135 halo_ranks.push_back(it->first);
1138 halo_send_sizes.push_back(halo_splitter.add_halo(it->first, *it->second));
1142 std::vector<std::size_t> halo_recv_sizes(num_halos);
1143 std::vector<std::vector<Index>> halo_send_data(num_halos), halo_recv_data(num_halos);
1149 const int layer_idx = is_child ? ancestor.
layer_p : ancestor.
layer;
1152 for(std::size_t i(0); i < num_halos; ++i)
1155 if(halo_send_sizes.at(i) > std::size_t(0))
1156 halo_send_data.at(i) = halo_splitter.serialize_split_halo(halo_ranks[i], -1);
1163 const Dist::Comm& layer_comm = this->_layers.at(std::size_t(layer_idx))->comm();
1166 for(std::size_t i(0); i < num_halos; ++i)
1169 halo_recv_reqs[i] = layer_comm.
irecv(&halo_recv_sizes[i], std::size_t(1), halo_ranks[i]);
1172 halo_send_reqs[i] = layer_comm.
isend(&halo_send_sizes[i], std::size_t(1), halo_ranks[i]);
1176 halo_recv_reqs.wait_all();
1180 for(std::size_t i(0); i < num_halos; ++i)
1183 if(halo_recv_sizes[i] >
Index(0))
1186 halo_recv_data.at(i).resize(halo_recv_sizes[i]);
1187 halo_recv_reqs[i] = layer_comm.
irecv(halo_recv_data.at(i).data(), halo_recv_sizes.at(i), halo_ranks[i]);
1191 if(halo_send_sizes.at(i) >
Index(0))
1194 halo_send_reqs[i] = layer_comm.
isend(halo_send_data.at(i).data(), halo_send_sizes.at(i), halo_ranks[i]);
1199 halo_recv_reqs.wait_all();
1212 for(std::size_t i(0); i < num_halos; ++i)
1213 halo_recv_data.at(i).resize(halo_recv_sizes[i]);
1217 for(std::size_t i(0); i < num_halos; ++i)
1219 if(halo_recv_sizes[i] > std::size_t(0))
1238 std::vector<std::array<Index, shape_dim+1>> halo_send_intsec_sizes(num_halos), halo_recv_intsec_sizes(num_halos);
1241 for(std::size_t i(0); i < num_halos; ++i)
1244 if(halo_recv_sizes.at(i) ==
Index(0))
1248 if(!halo_splitter.intersect_split_halo(halo_ranks[i], halo_recv_data.at(i), 0u))
1252 std::unique_ptr<MeshPartType> split_halo = halo_splitter.make_unique();
1256 halo_send_intsec_sizes[i][
Index(j)] = split_halo->get_num_entities(j);
1259 patch_mesh_node.
add_halo(halo_ranks[i], std::move(split_halo));
1263 if((ancestor.
layer_p >= 0) || (!is_child && (ancestor.
layer >= 0)))
1266 const LayerType& layer = *this->_layers.at(std::size_t(is_child ? ancestor.
layer_p : ancestor.
layer));
1269 for(std::size_t i(0); i < num_halos; ++i)
1271 halo_recv_reqs[i] = layer.comm().
irecv(halo_recv_intsec_sizes.at(i).data(), std::size_t(
shape_dim+1), halo_ranks[i]);
1272 halo_send_reqs[i] = layer.comm().
isend(halo_send_intsec_sizes.at(i).data(), std::size_t(
shape_dim+1), halo_ranks[i]);
1276 halo_recv_reqs.wait_all();
1280 for(std::size_t i(0); i < num_halos; ++i)
1284 if(halo_recv_intsec_sizes[i][
Index(j)] != halo_send_intsec_sizes[i][
Index(j)])
1286 String msg =
"Inconsistent deslagged halo size between process ";
1288 msg +=
" and neighbor with layer rank ";
1311 const auto& verts_at_elem = base_node.get_mesh()->template get_index_set<MeshType::shape_dim, 0>();
1320 #ifdef FEAT_DEBUG_MODE
1321 std::cout <<
"Unstructered Layering Computation not implemented yet!";
1339 XASSERT(slag_part !=
nullptr);
1340 const Geometry::TargetSet& slag_target = slag_part->template get_target_set<MeshType::shape_dim>();
1343 const Index num_colors =
Index(1) << MeshType::shape_dim;
1351 if constexpr(MeshType::shape_dim == 1)
1353 for(
Index i(0); i < num_elems; ++i)
1354 colors[i] = slag_target[i] & 1;
1356 else if constexpr(MeshType::shape_dim == 2)
1358 for(
Index i(0); i < num_elems; ++i)
1360 Index iel = slag_target[i];
1361 Index ix = iel % this->_base_slices[0];
1362 Index iy = iel / this->_base_slices[0];
1363 colors[i] = (ix & 1) | ((iy & 1) << 1);
1366 else if constexpr(MeshType::shape_dim == 3)
1368 for(
Index i(0); i < num_elems; ++i)
1370 Index iel = slag_target[i];
1371 Index ix = iel % this->_base_slices[0];
1372 Index iy = (iel / this->_base_slices[0]) % this->_base_slices[1];
1373 Index iz = iel / (this->_base_slices[0] * this->_base_slices[1]);
1374 colors[i] = (ix & 1) | ((iy & 1) << 1) | ((iz & 1) << (1 << 1));
1394 XASSERT(slag_part !=
nullptr);
1395 const Geometry::TargetSet& slag_target = slag_part->template get_target_set<MeshType::shape_dim>();
1398 const Index num_colors =
Index(1) << MeshType::shape_dim;
1406 for(
Index i(0); i < num_elems; ++i)
1407 colors[i] = slag_target[i] % num_colors;
1431 XASSERT(patch_part !=
nullptr);
1432 const Geometry::TargetSet& patch_target = patch_part->template get_target_set<MeshType::shape_dim>();
1443 for(
Index i(0); i < num_elems; ++i)
1444 colors[i] = parent_coloring[patch_target[i]];
1462 XASSERT(slag_part !=
nullptr);
1463 const Geometry::TargetSet& slag_target = slag_part->template get_target_set<MeshType::shape_dim>();
1473 denom *= this->_base_slices[
Index(j)];
1476 std::vector<Index> aux(max_layers, 0u);
1477 for(
Index i(0); i < num_elems; ++i)
1478 ++aux[slag_target[i] / denom];
1481 Index num_layers = 0u;
1482 for(
Index i(0); i < max_layers; ++i)
1484 Index k = num_layers;
1493 for(
Index i(0); i < num_elems; ++i)
1494 layers[i] = aux[slag_target[i] / denom];
1516 XASSERT(slag_part !=
nullptr);
1517 const Geometry::TargetSet& slag_target = slag_part->template get_target_set<MeshType::shape_dim>();
1525 std::vector<Index> aux(max_layers, 0u);
1526 for(
Index i(0); i < num_elems; ++i)
1529 ++aux[(coarse_layering[qux >> 1] << 1) | (qux & 1)];
1533 Index num_layers = 0u;
1534 for(
Index i(0); i < max_layers; ++i)
1536 Index k = num_layers;
1545 for(
Index i(0); i < num_elems; ++i)
1548 layers[i] = aux[(coarse_layering[qux >> 1] << 1) | (qux & 1)];
1575 XASSERT(patch_part !=
nullptr);
1576 const Geometry::TargetSet& patch_target = patch_part->template get_target_set<MeshType::shape_dim>();
1584 std::vector<Index> aux(max_layers, 0u);
1585 for(
Index i(0); i < num_elems; ++i)
1586 ++aux[parent_layering[patch_target[i]]];
1589 Index num_layers = 0u;
1590 for(
Index i(0); i < max_layers; ++i)
1592 Index k = num_layers;
1601 for(
Index i(0); i < num_elems; ++i)
1602 layers[i] = aux[parent_layering[patch_target[i]]];
1621 this->push_layer(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
1631 std::unique_ptr<MeshNodeType> base_slag_node = std::move(base_mesh_node);
1640 for(; lvl < ancestor.desired_level_min; ++lvl)
1642 base_slag_node = base_mesh_node->refine_unique(this->
_adapt_mode);
1651 base_coloring = this->_compute_unstructered_coloring(*base_mesh_node);
1669 auto refined_node = base_mesh_node->refine_unique(this->
_adapt_mode);
1672 std::shared_ptr<LevelType> level_ptr = std::make_shared<LevelType>(lvl, std::move(base_mesh_node),
1673 std::move(base_slag_node), std::move(base_coloring), std::move(base_layering));
1674 this->push_level_front(0, level_ptr);
1677 base_slag_node = std::move(refined_node);
1687 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(base_mesh_node),
1688 std::move(base_slag_node), std::move(base_coloring), std::move(base_layering)));
1694#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
1705 std::shared_ptr<LayerType> layer = std::make_shared<LayerType>(this->_comm.
comm_dup(), 0);
1706 this->push_layer(layer);
1715 std::unique_ptr<MeshNodeType> base_slag_node = std::move(base_mesh_node);
1736 base_slag_node = base_mesh_node->refine_unique(this->
_adapt_mode);
1755 std::vector<int> neighbor_ranks;
1756 std::unique_ptr<MeshNodeType> patch_mesh_node(
1757 base_mesh_node->extract_patch(neighbor_ranks, ancestor.
parti_graph, this->_comm.rank()));
1761 if(lvl == ancestor.desired_level_min)
1768 layer->set_neighbor_ranks(neighbor_ranks);
1771 std::unique_ptr<MeshNodeType> patch_slag_node;
1774 for(; lvl < ancestor.desired_level_min; ++lvl)
1777 patch_slag_node = patch_mesh_node->refine_unique(this->
_adapt_mode);
1783 if(patch_coloring.
empty())
1794 auto refined_node = patch_mesh_node->refine_unique(this->
_adapt_mode);
1797 std::shared_ptr<LevelType> level_ptr = std::make_shared<LevelType>(lvl, std::move(patch_mesh_node),
1798 std::move(patch_slag_node), std::move(patch_coloring), std::move(patch_layering));
1801 this->push_level_front(0, level_ptr);
1804 patch_slag_node = std::move(refined_node);
1814 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(patch_mesh_node),
1815 std::move(patch_slag_node), std::move(patch_coloring), std::move(patch_layering)));
1839 std::unique_ptr<MeshNodeType> parent_slag_node;
1840 std::unique_ptr<MeshNodeType> parent_mesh_node = this->
_deslag_mesh_node(*base_mesh_node);
1846 base_mesh_node.reset();
1849 for(std::size_t slayer = this->
_ancestry.size(); slayer > std::size_t(0); )
1852 const bool is_base_layer = (slayer == this->
_ancestry.size());
1860 int parent_min_lvl = -1;
1867 this->
_check_parti(ancestor, *parent_mesh_node, is_base_layer);
1905 auto refined_node = parent_mesh_node->refine_unique(this->
_adapt_mode);
1908 std::shared_ptr<LevelType> level_ptr;
1911 if((ancestor.
layer_p >= 0) && (parent_min_lvl >= 0) && (lvl >= parent_min_lvl))
1913 level_ptr = std::make_shared<LevelType>(lvl, std::move(parent_mesh_node),
1914 std::move(parent_slag_node), std::move(parent_coloring), std::move(parent_layering));
1915 this->push_level_front(ancestor.
layer_p, level_ptr);
1919 parent_slag_node = std::move(refined_node);
1920 parent_mesh_node = this->
_deslag_mesh_node(*parent_slag_node, ancestor, !is_base_layer);
1923 level_ptr ? level_ptr->element_layering : parent_layering);
1933 std::vector<int> neighbor_ranks;
1934 std::unique_ptr<MeshNodeType> patch_mesh_node(
1944 std::unique_ptr<MeshNodeType> patch_slag_node;
1949 std::map<int,int> halo_map;
1950 for(
auto& i : neighbor_ranks)
1955 patch_mesh_node->rename_halos(halo_map);
1962 for(
int i(1); i < ancestor.
num_parts; ++i)
1964 parent_mesh_node->create_patch_meshpart(ancestor.
parti_graph, i);
1979 XASSERTM(lvl == global_level_min,
"INTERNAL ERROR");
2007 if(ancestor.
layer >= 0)
2010 this->_layers.at(std::size_t(ancestor.
layer))->set_neighbor_ranks(neighbor_ranks);
2016 else if(parent_min_lvl < 0)
2020 this->
_chosen_levels.push_front(std::make_pair(parent_min_lvl, 0));
2025 std::shared_ptr<LevelType> level_ptr;
2030 this->push_level_front(ancestor.
layer_p, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node),
2031 std::move(parent_slag_node), std::move(parent_coloring), std::move(parent_layering)));
2035 parent_slag_node = std::move(patch_slag_node);
2036 parent_mesh_node = std::move(patch_mesh_node);
2037 parent_coloring = std::move(patch_coloring);
2038 parent_layering = std::move(patch_layering);
2046 for(; lvl < desired_level_max; ++lvl)
2049 auto refined_node = parent_mesh_node->refine_unique(this->
_adapt_mode);
2052 std::shared_ptr<LevelType> level_ptr = std::make_shared<LevelType>(lvl, std::move(parent_mesh_node),
2053 std::move(parent_slag_node), std::move(parent_coloring), std::move(parent_layering));
2057 this->push_level_front(0, level_ptr);
2060 parent_slag_node = std::move(refined_node);
2070 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node),
2071 std::move(parent_slag_node), std::move(parent_coloring), std::move(parent_layering)));
#define XABORTM(msg)
Abortion macro definition with custom message.
#define ASSERTM(expr, msg)
Debug-Assertion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Coloring object implementation.
bool empty() const
Checks whether the coloring is empty.
Index * get_coloring()
Returns the coloring array.
Index get_num_colors() const
Returns the number of colors.
Adjacency Graph implementation.
bool _keep_base_levels
keep base-mesh levels on root process?
Dist::Comm progeny_comm
Progeny communicator.
int desired_level_max
the desired minimum and maximum refinement levels for this layer
int parti_level
the refinement level on which the patch is to be partitioned
String parti_info
a string containing some information about the chosen partitioning
bool parti_found
specifies whether a partitioning was found
int num_procs
the number of processes that participate in this layer
Adjacency::Graph parti_graph
this is the actual elements-at-rank partitioning graph
int progeny_group
Progeny group of this process.
int layer_p
the index of the parent layer or -1, if this process is not part of the parent layer
int layer
the index of the layer that this ancestor object belongs to
int num_parts
the number of partitions for each patch of the parent layer
int progeny_child
Which direct child this process belongs to in its progeny group.
Base-Class for Hierarchical Domain Control implementations.
std::deque< std::pair< int, int > > _desired_levels
desired level deque
int _required_elems_per_rank
required number of elements per rank for a-posteriori partitioning
std::deque< std::pair< int, int > > _chosen_levels
chosen level deque
virtual void _create_ancestry_scattered()
Creates the layers for a multi-layered domain control in a scattered fashion.
Real WeightType
weight type for partitioner element weights; always Real
std::deque< Ancestor > _ancestry
the partition ancestry deque
Geometry::RootMeshNode< MeshType > MeshNodeType
our root mesh node type
LevelType::PartType MeshPartType
our mesh-part type
virtual void _create_ancestry_single()
Creates the ancestry for a single layer (or a single process)
Geometry::AdaptMode _adapt_mode
the adapt mode for refinement
int get_desired_level_max() const
Returns the desired maximum refinement level.
bool _was_created
specifies whether the domain control was already created
virtual bool _check_parti(Ancestor &ancestor, const MeshNodeType &mesh_node, bool is_base_layer)
Checks for an appropriate partitioning strategy.
bool _support_multi_layered
support multi-layered hierarchy?
virtual bool _apply_parti(Ancestor &ancestor, MeshNodeType &base_mesh_node)
Applies an a-posteriori partitioner.
virtual void _create_multi_layers_scattered()
Creates the layers for a multi-layered domain control in a scattered fashion.
virtual void _split_basemesh_halos(const Ancestor &ancestor, const MeshNodeType &base_mesh_node, MeshNodeType &patch_mesh_node, std::vector< int > &neighbor_ranks)
Splits the base-mesh halos and computes the inter-patch-mesh halos.
Hierarchical partitioned Voxel Domain Control.
void create_voxel_map_from_off(std::istream &is, bool invert, Real resolution)
Creates a voxel map based on a surface triangulation stored in an OFF file.
Adjacency::Coloring _extract_patch_coloring(const MeshNodeType &slag_node, const Adjacency::Coloring &parent_coloring, int child_rank) const
Extracts a patch coloring from the parent mesh coloring.
Adjacency::Coloring _compute_base_mesh_coloring(const MeshNodeType &slag_node) const
Computes the coloring for the unpartitioned base mesh.
virtual void _create_multi_layered(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a multi-layered mesh hierarchy.
std::unique_ptr< MeshNodeType > _base_mesh_node
the input base-mesh node on level 0
virtual std::unique_ptr< MeshNodeType > _deslag_mesh_node(MeshNodeType &mesh_node)
Deslags an unpartitioned mesh node including its mesh-parts.
std::vector< Index > _gather_masked_elements(const MeshType &mesh) const
Gather a vector of element indices that intersect the masked domain.
Geometry::VoxelMap::WriteResult write_voxel_map(const String &filename)
Writes the voxel map to a voxel map file.
void create_hierarchy()
Creates the domain level hierarchy.
bool _unstructered_mesh
specifies whether we use a non voxel base mesh
const StopWatch & get_watch_voxel_map() const
Returns a const reference to the StopWatch that measures the voxel-map creation phase.
Geometry::RootMeshNode< MeshType > MeshNodeType
our root mesh node type
static constexpr int shape_dim
shape dimension
void _precreate_voxel_map(Real resolution)
Pre-creates the voxel map by setting the bounding box and resolution.
Control::Domain::PartiDomainControlBase< DomainLevel_ > BaseClass
our base class
virtual void create(Geometry::MeshFileReader &)
Creates a domain control from a MeshFileReader.
const StopWatch & get_watch_hierarchy() const
Returns a const reference to the StopWatch that measures the base-mesh creation phase.
Adjacency::Coloring _compute_refined_mesh_layering(const MeshNodeType &slag_node, const Adjacency::Coloring &coarse_layering) const
Computes the layering for a refined mesh.
virtual void create(std::unique_ptr< MeshNodeType > &)
Creates a domain control from a base-mesh node.
Tiny::Vector< CoordType, shape_dim > _bbox_min
the bounding box of the structured domain
bool _keep_voxel_map
specifies whether to keep the voxel map after hierarchy creation
StopWatch _watch_create_base_mesh
a bunch of stop-watches
void create_voxel_map_from_lambda(Lambda_ &&lambda, Real resolution)
Creates a voxel map based on a lambda expression.
Adjacency::Coloring _compute_refined_mesh_coloring(const MeshNodeType &slag_node) const
Computes the coloring for a refined mesh.
MeshNodeType & create_base_mesh_2d(Index num_x, Index num_y, CoordType x_min, CoordType x_max, CoordType y_min, CoordType y_max)
Creates a 2D structured rectangle base mesh and returns its base-mesh node.
int _create_stage
creation stage to keep track what has already been initialized
void create_voxel_map(Geometry::VoxelMasker< CoordType, shape_dim > &masker, Real resolution=Real(0))
Creates a voxel map based on a VoxelMasker object.
virtual void create(const std::deque< String > &filenames, String dirpath="")
Creates a domain control from a list of filenames.
std::vector< WeightType > _gather_element_weights(const MeshType &mesh) const
Gathers the element slag weights for a given mesh.
const StopWatch & get_watch_base_mesh() const
Returns a const reference to the StopWatch that measures the base-mesh creation phase.
MeshType::CoordType CoordType
coordinate type
void set_voxel_map_out_of_bounds_balue(bool value)
Sets the out-of-bounds value for the voxel map.
std::vector< int > gather_vertex_voxel_map(Index level) const
Gathers the vertex voxel map on a given domain level.
virtual std::unique_ptr< MeshNodeType > _deslag_mesh_node(MeshNodeType &mesh_node, const Ancestor &ancestor, bool is_child)
Deslags a (potentially partitioned) mesh node including its mesh-parts and halos.
virtual void _create_single_layered(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a single-layered mesh hierarchy.
virtual ~VoxelDomainControl()
virtual destructor
std::vector< WeightType > gather_element_voxel_weights(Index level) const
Gathers the element voxel map weights on a given domain level.
std::array< Index, shape_dim > _base_slices
number of element slices on base mesh level 0
Adjacency::Coloring _extract_patch_layering(const MeshNodeType &slag_node, const Adjacency::Coloring &parent_layering, int child_rank) const
Extracts a patch layering from the parent mesh layering.
VoxelDomainControl(const Dist::Comm &comm_, bool support_multi_layered)
Constructor.
Adjacency::Coloring _compute_base_mesh_layering(const MeshNodeType &slag_node) const
Computes the element layering for the unpartitioned base mesh.
MeshNodeType & create_base_mesh_3d(Index num_x, Index num_y, Index num_z, CoordType x_min, CoordType x_max, CoordType y_min, CoordType y_max, CoordType z_min, CoordType z_max)
Creates a 3D structured cuboid base mesh and returns its base-mesh node.
void create_voxel_map_from_chart(const Geometry::Atlas::ChartBase< MeshType > &chart, bool invert, Real resolution)
Creates a voxel map based on a chart.
Geometry::VoxelMap::ReadResult read_voxel_map(const String &filename)
Reads the voxel map from a voxel map file.
virtual void _create_single_process(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a single-layered mesh hierarchy for a single process.
const Geometry::VoxelMap & get_voxel_map() const
Returns a const reference to the internal voxel map.
void keep_voxel_map()
Instructs the domain controller to keep the voxel map after hierarchy creation.
void create_voxel_map_from_off(const String &filename, bool invert, Real resolution)
Creates a voxel map based on a surface triangulation stored in an OFF file.
std::vector< Index > _gather_masked_elements(const MeshType &mesh, const Dist::Comm &sibling_comm) const
Gather a vector of element indices that intersect the masked domain in a copperative manner.
std::unique_ptr< Geometry::VoxelMap > _voxel_map
the voxel map
virtual void _deslag_patch_halos(MeshNodeType &patch_mesh_node, const MeshNodeType &base_mesh_node, const Ancestor &ancestor, bool is_child)
Deslags the halos of a patch mesh node.
String dump_slag_layer_levels() const
Debugging function: Returns a string containing encoded slag layer level information.
Wrapper class for domain levels for VoxelDomainControl.
Adjacency::Coloring element_layering
element layering (stored as coloring)
DomainLevel_ BaseClass
our base-class; the actual domain level
std::shared_ptr< DomainLevel_ > slag_level
attachable slag level
Adjacency::Coloring element_coloring
element coloring
void bcast(void *buffer, std::size_t count, const Datatype &datatype, int root) const
Blocking broadcast.
void allreduce(const void *sendbuf, void *recvbuf, std::size_t count, const Datatype &datatype, const Operation &op) const
Blocking All-Reduce.
int size() const
Returns the size of this communicator.
Request irecv(void *buffer, std::size_t count, const Datatype &datatype, int source, int tag=0) const
Nonblocking Receive.
Request isend(const void *buffer, std::size_t count, const Datatype &datatype, int dest, int tag=0) const
Nonblocking Send.
Comm comm_dup() const
Creates a copy of this communicator.
void allgatherv(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, const int *recvcounts, const int *displs, const Datatype &recvtype) const
Blocking gather-to-all.
int rank() const
Returns the rank of this process in this communicator.
void allgather(const void *sendbuf, std::size_t sendcount, const Datatype &sendtype, void *recvbuf, std::size_t recvcount, const Datatype &recvtype) const
Blocking gather-to-all.
Communication Request vector class.
void wait_all()
Blocks until all active requests are fulfilled.
static void read_common(std::stringstream &stream, const String &filename, const Dist::Comm &comm, int root_rank=0)
Reads a common text file for all ranks.
MeshType * get_mesh()
Returns the mesh of this node.
Class template for partial meshes.
Base-Mesh Patch Halo splitter.
std::unique_ptr< RootMeshNode > extract_patch(std::vector< Index > &&elements, bool split_meshparts, bool split_halos, bool split_patches)
Extracts a patch from the root mesh as a new mesh node.
const MeshPartType * get_patch(int rank) const
Returns a patch meshpart for a given child.
static std::unique_ptr< RootMeshNode > make_unique(std::unique_ptr< MeshType > mesh, MeshAtlasType *atlas=nullptr)
Creates a new RootMeshNode on the heap and returns a unique pointer to it.
const std::map< int, std::unique_ptr< MeshPartType > > & get_halo_map() const
void add_halo(int rank, std::unique_ptr< MeshPartType > halo_part)
Adds a halo mesh part to this mesh node.
Structured unit-cube mesh factory.
Index get_num_entities() const
Returns the number of entities.
helper class for read function result
helper class for write function result
Interface for voxel masker for the VoxelMap class.
Math Limits class template.
static double toe_partition
time of partitioning in seconds, needs initialization
double elapsed() const
Returns the total elapsed time in seconds.
void start()
Starts the stop-watch.
void stop()
Stops the stop-watch and increments elapsed time.
String class implementation.
String pad_front(size_type len, char c=' ') const
Pads the front of the string up to a desired length.
Tiny Vector class template.
@ transpose
Render-Transpose mode.
@ injectify
Render-Injectified mode.
const Operation op_min(MPI_MIN)
Operation wrapper for MPI_MIN.
const Operation op_max(MPI_MAX)
Operation wrapper for MPI_MAX.
void minimax(T_ x, T_ &a, T_ &b)
Updates the minimum and maximum.
T_ min(T_ a, T_ b)
Returns the minimum of two values.
T_ max(T_ a, T_ b)
Returns the maximum of two values.
double Real
Real data type.
String stringify(const T_ &item)
Converts an item into a String.
@ value
specifies whether the space should supply basis function values
std::uint64_t Index
Index data type.