10#include <kernel/geometry/mesh_file_reader.hpp>
11#include <kernel/geometry/boundary_factory.hpp>
12#include <kernel/geometry/common_factories.hpp>
14#include <control/domain/parti_domain_control_base.hpp>
33 args.
support(
"parti-type",
"<types...>\n"
34 "Specifies which partitioner types are allowed to be used.\n"
35 "May contain the following types:\n"
36 "2level extern genetic metis naive zoltan"
38 args.
support(
"parti-extern-name",
"<names...>\n"
39 "Specifies the names of the allowed extern partitions."
41 args.
support(
"parti-rank-elems",
"<count>\n"
42 "Specifies the minimum number of elements per rank for a-posteriori partitioning."
44 args.
support(
"parti-genetic-time",
"<time-init> <time-mutate>\n"
45 "Specifies the time for initial distribution and mutation for the genetic partitioner."
60 template<
typename DomainLevel_>
68 using typename BaseClass::LevelType;
72 using typename BaseClass::MeshType;
142 auto it = args.
query(
"parti-extern-name");
166 auto parti_extern_name_p = pmap.
query(
"parti-extern-name");
167 if(parti_extern_name_p.second)
169 this->_extern_parti_names = parti_extern_name_p.first.split_by_whitespaces();
184 virtual void create(
const std::deque<String>& filenames,
String dirpath =
"")
193 this->
create(mesh_reader);
206 XASSERT(this->size_physical() == std::size_t(0));
207 XASSERT(this->size_virtual() == std::size_t(0));
227 virtual void create(std::unique_ptr<MeshNodeType> base_mesh_node)
232 this->
_create(std::move(base_mesh_node));
255 XASSERT(this->size_physical() == std::size_t(0));
256 XASSERT(this->size_virtual() == std::size_t(0));
267 base_mesh_node->add_mesh_part(
"bnd", bnd_factory.make_unique());
271 this->
create(std::move(base_mesh_node));
285 XASSERTM(!this->
_was_created,
"This function has to be called before domain control creation!");
286 _permutation_strategy = strategy;
305 for(std::size_t i(0); i < this->size_physical(); ++i)
307 this->at(i)->get_mesh_node()->create_permutation(this->_permutation_strategy);
348 virtual void _create(std::unique_ptr<MeshNodeType> base_mesh_node)
352 XASSERT(this->size_physical() == std::size_t(0));
353 XASSERT(this->size_virtual() == std::size_t(0));
359 if(this->_comm.
size() == 1)
383 this->compile_virtual_levels();
406 this->push_layer(std::make_shared<LayerType>(this->_comm.
comm_dup(), 0));
417 for(; lvl < ancestor.desired_level_min; ++lvl)
420 base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
431 auto refined_node = base_mesh_node->refine_unique(this->
_adapt_mode);
434 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
437 base_mesh_node = std::move(refined_node);
444 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
450#if defined(FEAT_HAVE_MPI) || defined(DOXYGEN)
461 std::shared_ptr<LayerType> layer = std::make_shared<LayerType>(this->_comm.
comm_dup(), 0);
462 this->push_layer(layer);
479 base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
485 XABORTM(
"Failed to find a suitable partitioning");
489 std::vector<int> neighbor_ranks;
490 std::unique_ptr<MeshNodeType> patch_mesh_node(
491 base_mesh_node->extract_patch(neighbor_ranks, ancestor.
parti_graph, this->_comm.rank()));
494 layer->set_neighbor_ranks(neighbor_ranks);
500 for(
int i(1); i < ancestor.
num_parts; ++i)
502 base_mesh_node->create_patch_meshpart(ancestor.
parti_graph, i);
507 for(; lvl < ancestor.desired_level_min; ++lvl)
510 patch_mesh_node = patch_mesh_node->refine_unique(this->
_adapt_mode);
514 base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
525 auto refined_node = patch_mesh_node->refine_unique(this->
_adapt_mode);
528 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(patch_mesh_node)));
531 patch_mesh_node = std::move(refined_node);
537 auto refined_base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
540 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
543 base_mesh_node = std::move(refined_base_mesh_node);
551 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(patch_mesh_node)));
555 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
576 XASSERTM(!keep_base || (this->
_ancestry.size() <= std::size_t(1)),
"cannot keep base levels for more than 2 domain layers (yet)");
583 std::unique_ptr<MeshNodeType> parent_mesh_node = std::move(base_mesh_node);
584 base_mesh_node.reset();
587 for(std::size_t slayer = this->
_ancestry.size(); slayer > std::size_t(0); )
590 const bool is_base_layer = (slayer == this->
_ancestry.size());
598 int parent_min_lvl = -1;
605 this->
_check_parti(ancestor, *parent_mesh_node, is_base_layer);
619 auto refined_node = parent_mesh_node->refine_unique(this->
_adapt_mode);
622 if((ancestor.
layer_p >= 0) && (parent_min_lvl >= 0) && (lvl >= parent_min_lvl))
624 this->push_level_front(ancestor.
layer_p, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node)));
628 parent_mesh_node = std::move(refined_node);
634 auto refined_base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
637 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
640 base_mesh_node = std::move(refined_base_mesh_node);
647 XABORTM(
"Failed to find a suitable partitioning");
651 std::vector<int> neighbor_ranks;
652 std::unique_ptr<MeshNodeType> patch_mesh_node(
658 std::map<int,int> halo_map;
659 for(
auto& i : neighbor_ranks)
664 patch_mesh_node->rename_halos(halo_map);
668 if((ancestor.
layer_p >= 0) || (keep_base && is_base_layer))
671 for(
int i(1); i < ancestor.
num_parts; ++i)
673 parent_mesh_node->create_patch_meshpart(ancestor.
parti_graph, i);
688 for(; lvl < global_level_min; ++lvl)
691 std::unique_ptr<MeshNodeType> coarse_mesh_node(std::move(parent_mesh_node));
692 parent_mesh_node = coarse_mesh_node->refine_unique(this->
_adapt_mode);
695 if((ancestor.
layer_p >= 0) && (parent_min_lvl >= 0) && (lvl >= parent_min_lvl))
698 coarse_mesh_node->clear_patches();
699 this->push_level_front(ancestor.
layer_p, std::make_shared<LevelType>(lvl, std::move(coarse_mesh_node)));
703 patch_mesh_node = patch_mesh_node->refine_unique(this->
_adapt_mode);
709 auto refined_base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
712 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
715 base_mesh_node = std::move(refined_base_mesh_node);
723 if(ancestor.
layer >= 0)
726 this->_layers.at(std::size_t(ancestor.
layer))->set_neighbor_ranks(neighbor_ranks);
732 else if(parent_min_lvl < 0)
736 this->
_chosen_levels.push_front(std::make_pair(parent_min_lvl, 0));
742 if(keep_base && is_base_layer)
744 XASSERT(base_mesh_node.get() ==
nullptr);
745 base_mesh_node = parent_mesh_node->clone_unique();
751 this->push_level_front(ancestor.
layer_p, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node)));
755 parent_mesh_node = std::move(patch_mesh_node);
763 for(; lvl < desired_level_max; ++lvl)
766 auto refined_node = parent_mesh_node->refine_unique(this->
_adapt_mode);
769 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node)));
772 parent_mesh_node = std::move(refined_node);
778 auto refined_base_mesh_node = base_mesh_node->refine_unique(this->
_adapt_mode);
781 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
784 base_mesh_node = std::move(refined_base_mesh_node);
789 this->push_level_front(0, std::make_shared<LevelType>(lvl, std::move(parent_mesh_node)));
796 this->_base_levels.push_front(std::make_shared<LevelType>(lvl, std::move(base_mesh_node)));
849 if(!this->_allow_parti_extern)
880 if(!this->_allow_parti_2level)
887 if(!partitioner.success())
893 ancestor.
parti_level = int(partitioner.parti_level());
894 ancestor.
parti_graph = partitioner.build_elems_at_rank();
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERT(expr)
Assertion macro definition.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Graph clone() const
Clones this graph.
bool _keep_base_levels
keep base-mesh levels on root process?
bool parti_apriori
specifies whether the chosen partitioning is an a-priori partitioning strategy
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
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.
virtual void _reset_parti_types()
Resets/disables all partitioner types.
std::deque< std::pair< int, int > > _desired_levels
desired level deque
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
virtual bool parse_args(SimpleArgParser &args)
Parses the partitioner options from an argument parser.
Geometry::RootMeshNode< MeshType > MeshNodeType
our root mesh node type
virtual bool _parse_parti_type(const String &type)
Parses a partitioner 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
bool _was_created
specifies whether the domain control was already created
virtual bool parse_property_map(const PropertyMap &pmap)
Parses the partitioner options from a PropertyMap.
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.
Recursively Partitioned Domain Control.
PartiDomainControl(const Dist::Comm &comm_, bool support_multi_layered)
Constructor.
bool _allow_parti_extern
allow extern partitioner?
virtual void _create(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a domain control from a base-mesh node.
virtual void create_rectilinear(Index num_elems_x, Index num_elems_y=0u, Index num_elems_z=0u)
Creates a domain control from a structured rectilinear base mesh.
virtual bool _parse_parti_type(const String &type) override
Parses a partitioner type.
virtual void _create_multi_layered(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a multi-layered mesh hierarchy.
Geometry::PermutationStrategy get_permutation_strategy() const
bool _allow_parti_2level
allow 2-level partitioner?
Geometry::PartitionSet _parti_set
the extern partition sets
Control::Domain::PartiDomainControlBase< DomainLevel_ > BaseClass
Our base class.
Geometry::PermutationStrategy _permutation_strategy
the permutation strategy for the mesh permutation
virtual void _create_single_process(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a single-layered mesh hierarchy for a single process.
virtual void _create_single_layered(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a single-layered mesh hierarchy.
virtual bool parse_args(SimpleArgParser &args) override
Parses the partitioner options from an argument parser.
bool _check_parti_2level(Ancestor &ancestor, const MeshNodeType &base_mesh_node)
Checks whether the 2-level partitioner can be applied.
virtual void create(Geometry::MeshFileReader &mesh_reader)
Creates a domain control from a MeshFileReader.
virtual void create(std::unique_ptr< MeshNodeType > base_mesh_node)
Creates a domain control from a base-mesh node.
virtual void create_mesh_permutations()
Creates the mesh permutations based on the chosen permutation strategy.
void set_permutation_strategy(Geometry::PermutationStrategy strategy)
Sets the permutation strategy for mesh permutation.
bool _check_parti_extern(Ancestor &ancestor)
Checks whether an extern partition is given.
virtual void create(const std::deque< String > &filenames, String dirpath="")
Creates a domain control from a list of filenames.
std::deque< String > _extern_parti_names
required partition name for extern partitioning
virtual void _reset_parti_types() override
Resets/disables all partitioner types.
virtual bool _check_parti(Ancestor &ancestor, const MeshNodeType &mesh_node, bool is_base_layer) override
Checks for an appropriate partitioning strategy.
virtual bool parse_property_map(const PropertyMap &pmap) override
Parses the partitioner options from a PropertyMap.
virtual ~PartiDomainControl()
virtual destructor
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.
Comm comm_dup() const
Creates a copy of this communicator.
int rank() const
Returns the rank of this process in this communicator.
BoundaryFactory implementation.
void add_mesh_files(const Dist::Comm &comm, const std::deque< String > &filenames, String dirpath="")
Adds a list of mesh files to the list of streams to be parsed.
void parse(MeshNodeLinker< RootMesh_ > &linker, RootMeshNode< RootMesh_ > &root_mesh_node, MeshAtlas< RootMesh_ > &mesh_atlas, PartitionSet *part_set=nullptr)
Parses the mesh file into a mesh node and a mesh atlas.
MeshType * get_mesh()
Returns the mesh of this node.
2-Level-Partitioner class template declaration
const Adjacency::Graph & get_patches() const
const Partition * find_partition(int size, const String &name="", int prio=0) const
Tries to find a suitable partition in the set.
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.
Structured unit-cube mesh factory.
A class organizing a tree of key-value pairs.
std::pair< String, bool > query(String key_path) const
Queries a value by its key path.
Simple argument parser implementation.
const std::pair< int, std::deque< String > > * query(const String &option) const
Query the parameters of an option.
void support(const String &option, const String &description=String())
Adds an option to the set of supported options.
static double toe_partition
time of partitioning in seconds, needs initialization
String class implementation.
int compare_no_case(const String &other) const
Compares two strings without regard to case.
double elapsed_now() const
Calculates the time elapsed between the time stamp and now.
void add_supported_pdc_args(SimpleArgParser &args)
Adds the supported arguments of the PartiDomainControl to an argument parser.
const Operation op_max(MPI_MAX)
Operation wrapper for MPI_MAX.
PermutationStrategy
Mesh permutation strategy enumeration.
@ none
no permutation strategy
T_ max(T_ a, T_ b)
Returns the maximum of two values.
std::uint64_t Index
Index data type.