15#include <Partitionneur_Metis.h>
17#include <Static_Int_Lists.h>
21#include <communications.h>
22#include <Domain_Graph.h>
25inline void not_implemented(
const Nom& chaine)
27 Cerr << chaine <<
" is not implemented yet to the METIS API." << finl;
43template<
typename _SIZE_>
44_SIZE_ from_idx_t_to_SIZE(idx_t val)
46 assert(val < std::numeric_limits<_SIZE_>::max());
52template <
typename _SIZE_>
55 Cerr <<
"Partitionneur_Metis_32_64<_SIZE_>::printOn invalid\n" << finl;
61template <
typename _SIZE_>
65 param.
ajouter(
"nb_essais",&nb_essais_);
66 param.
ajouter_condition(
"(value_of_nb_parts_ge_1)_and_(value_of_nb_parts_le_100000)",
"The following condition must be satisfied : 1 <= nb_parties <= 100000");
83 param.
ajouter_flag(
"use_segment_to_build_connectivite_elem_elem",&use_segment_to_build_connectivite_elem_elem_);
86template <
typename _SIZE_>
91 Cerr <<
"WARNING! You're using a sequential algorithm on " << this->
nproc() <<
"processors " << finl;
92 Cerr <<
"Use PARMETIS for parallel domain cutting" << finl;
97 Cerr <<
" Algorithm PMETIS" << finl;
101 else if (mot==
"kmetis")
103 Cerr <<
" Algorithm KMETIS" << finl;
107 else if (mot==
"match_type")
109 not_implemented(mot);
112 else if (mot==
"initial_partition_type")
114 not_implemented(mot);
117 else if (mot==
"refinement_type")
119 not_implemented(mot);
132template <
typename _SIZE_>
136 Cerr <<
"METIS is not compiled with this version. Use another partition tool like Tranche." << finl;
141 Cerr <<
"Error in Partitionneur_Metis_32_64<_SIZE_>::construire_partition\n";
142 Cerr <<
" The domain has not been associated" << finl;
145 if (nb_parties_ <= 0)
147 Cerr <<
"Error in Partitionneur_Metis_32_64<_SIZE_>::construire_partition\n";
148 Cerr <<
" The parts number has not been initialized" << finl;
153 if (nb_parties_ == 1)
155 int_t nb_elem = ref_domaine_->nb_elem_tot();
156 if (use_segment_to_build_connectivite_elem_elem_)
157 nb_elem = ref_domaine_->nb_som();
158 elem_part.
resize(nb_elem);
163 if (ref_domaine_->nb_elem() == 0)
166 Cerr <<
"Partitionneur_Metis_32_64<_SIZE_>::construire_partition" << finl;
167 Cerr <<
" Construction of graph connectivity..." << finl;
171 if (!use_segment_to_build_connectivite_elem_elem_)
174 graph_elements_perio);
178 std::vector<idx_t> partition(graph.
nvtxs);
179 idx_t int_parts = nb_parties_;
186 Cerr <<
"===============" << finl;
187 Cerr <<
"Call for PMETIS" << finl;
188 Cerr <<
"===============" << finl;
190 idx_t options[METIS_NOPTIONS];
191 METIS_SetDefaultOptions(options);
197 options[METIS_OPTION_NCUTS]=nb_essais_;
198 options[METIS_OPTION_NUMBERING]=0;
199 options[METIS_OPTION_DBGLVL]=111111111;
204 int status = METIS_PartGraphRecursive(&graph.
nvtxs, &ncon, graph.
xadj.
addr(),
206 &int_parts,
nullptr,
nullptr, options,
207 &edgecut, partition.data());
208 if (status != METIS_OK)
210 Cerr <<
"Call to METIS failed." << finl;
211 if (status == METIS_ERROR_INPUT) Cerr <<
"It seems there is an input error." << finl;
212 if (status == METIS_ERROR_MEMORY) Cerr <<
"It seems it couldn't allocate enough memory." << finl;
213 if (status == METIS_ERROR) Cerr <<
"It seems there is a METIS internal error." << finl;
214 Cerr <<
"Contact TRUST support." << finl;
217 Cerr <<
"===============" << finl;
222 Cerr <<
" Call for KMETIS" << finl;
223 idx_t options[METIS_NOPTIONS];
224 METIS_SetDefaultOptions(options);
230 options[METIS_OPTION_NCUTS]=nb_essais_;
231 options[METIS_OPTION_NUMBERING]=0;
232 options[METIS_OPTION_DBGLVL]=111111111;
236 int status = METIS_PartGraphKway(&graph.
nvtxs, &ncon, graph.
xadj.
addr(),
238 &int_parts,
nullptr,
nullptr, options ,
239 &edgecut, partition.data());
240 if (status != METIS_OK)
242 Cerr <<
"Call to METIS failed." << finl;
243 if (status == METIS_ERROR_INPUT) Cerr <<
"It seems there is an input error." << finl;
244 if (status == METIS_ERROR_MEMORY) Cerr <<
"It seems it couldn't allocate enough memory." << finl;
245 if (status == METIS_ERROR) Cerr <<
"It seems there is a METIS internal error." << finl;
246 Cerr <<
"Contact TRUST support." << finl;
253 Cerr <<
"Internal error Partitionneur_Metis_32_64: not coded" << finl;
257 Cerr <<
"Partitioning quality : edgecut = " << edgecut << finl;
258 Cerr <<
"-> It is roughly the total number of edges (faces) which will be shared by the processors." << finl;
259 Cerr <<
"-> The lesser this number is, the lesser the total volume of communication between processors." << finl;
260 Cerr <<
"-> You can increase nb_essais option (default 1) to try to reduce (but at a higher CPU cost) this number." << finl;
261 Cerr <<
"===============" << finl;
263 const int_t n = from_idx_t_to_SIZE<_SIZE_>(graph.
nvtxs);
265 for (
int_t i = 0; i < n; i++)
266 elem_part[i] =
static_cast<int>(partition[i]);
271 Cerr <<
"Correction of the partition for the periodicity" << finl;
273 Cerr <<
" If this number is high, you can improve the splitting with the option use_weights\n"
274 <<
" but it takes more memory)" << finl;
277 if (!use_segment_to_build_connectivite_elem_elem_)
279 Cerr <<
"Correction elem0 on processor 0" << finl;
Build the graph of the domain that the METIS/PARMETIS/PTSCOTCH libraries need.
void construire_graph_elem_elem(const Domaine_32_64< _SIZE_ > &dom, bool use_weights, Static_Int_Lists_32_64< _SIZE_ > &graph_elements_perio)
void construire_graph_from_segment(const Domaine_32_64< _SIZE_ > &dom, bool use_weights)
A character string (Nom) in uppercase.
class Nom: a character string for naming TRUST objects.
virtual void set_param(Param &) const
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Helper class to factorize the readOn method of Objet_U classes.
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
void ajouter_condition(const char *condition, const char *message, const char *name=0)
Declare a post-read logical condition that must hold on the parameter values.
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
void ajouter_non_std(const char *keyword, const Objet_U *value, Param::Nature nat=Param::OPTIONAL)
Register a keyword handled by Objet_U::lire_motcle_non_standard.
Partition of a domain into nb_parties balanced parts using the METIS library.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
TRUSTVect< int, _SIZE_ > BigIntVect_
void construire_partition(BigIntVect_ &elem_part, int &nb_parts_tot) const override
Computes the connectivity graph for Metis, calls the partitioner and fills elem_part (for each elemen...
Base class for domain partitioners (for splitting a mesh before a parallel computation).
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
static void corriger_bords_avec_liste(const Domaine_t &dom, const int_t my_offset, BigIntVect_ &elem_part)
Computes the periodic element connectivity graphs and calls corriger_periodique_avec_graphe.
static void corriger_elem0_sur_proc0(BigIntVect_ &elem_part)
Corrects the partition so that element 0 of the initial domain is on the first sub-domain of the part...
static bool is_parallel()
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Base class for output streams.
This class allows storing lists of integers accessible in constant time.
int_t get_nb_lists() const
Returns the number of stored lists.
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)