TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Partitionneur_Parmetis.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15#include <Partitionneur_Parmetis.h>
16#include <Domaine.h>
17#include <Static_Int_Lists.h>
18#include <parmetis++.h>
19#include <Param.h>
20
21#include <communications.h>
22#include <Poly_geom_base.h>
23#include <Matrix_tools.h>
24#include <Matrice_Morse.h>
25#include <Array_tools.h>
26#include <Comm_Group_MPI.h>
27
28#include <Domain_Graph.h>
29#include <MD_Vector_tools.h>
30
31inline void not_implemented(const Nom& chaine)
32{
33 Cerr << chaine << " is not implemented yet to the PARMETIS API." << finl;
35}
36
37// XD partitionneur_parmetis partitionneur_deriv parmetis INHERITS_BRACE ParMETIS is the MPI-parallel counterpart of
38// XD_CONT METIS — same general-purpose mesh partitioning, run in parallel.
39Implemente_instanciable_sans_constructeur(Partitionneur_Parmetis,"Partitionneur_Parmetis",Partitionneur_base);
40
41Partitionneur_Parmetis::Partitionneur_Parmetis()
42{
43}
44
46{
47 Cerr << "Partitionneur_Parmetis::printOn invalid\n" << finl;
48 exit();
49 return os;
50}
51
53{
54 param.ajouter("nb_parts",&nb_parties_,Param::REQUIRED);
55 param.ajouter_flag("use_weights",&use_weights_); // XD attr use_weights rien use_weights OPT Weight element-element
56 // XD_CONT links in the graph to keep periodic opposite elements on the same processor. Same meaning as in metis;
57 // XD_CONT costs extra memory and time but is otherwise non-mandatory (a correction pass runs unconditionally).
58}
59
61{
62 if (nb_parties_ < 1 || nb_parties_ > 100000)
63 {
64 Process::exit("Partitionneur_Parmetis::validate_params: The following condition must be satisfied : 1 <= nb_parts <= 100000");
65 }
66}
67
72
73void Partitionneur_Parmetis::associer_domaine(const Domaine& domaine)
74{
75 ref_domaine_ = domaine;
76}
77
78/*! @brief @brief Computes the connectivity graph for parmetis, calls the partitioner and fills elem_part (for each element, the number of the part assigned to it).
79 *
80 */
81void Partitionneur_Parmetis::construire_partition(IntVect& elem_part, int& nb_parts_tot) const
82{
83#ifndef PARMETIS_
84 Cerr << "PARMETIS is not compiled with this version. Use another partition tool like Tranche." << finl;
86#else
87
88 if (!ref_domaine_)
89 {
90 Cerr << "Error in Partitionneur_Parmetis::construire_partition\n";
91 Cerr << " The domain has not been associated" << finl;
92 exit();
93 }
94 if (nb_parties_ <= 0)
95 {
96 Cerr << "Error in Partitionneur_Parmetis::construire_partition\n";
97 Cerr << " The parts number has not been initialized" << finl;
98 exit();
99 }
100
101 // Special case: if nb_parts == 1, METIS does nothing...
102 //ToDo: I don't know is that's the case with ParMetis
103 if (nb_parties_ == 1)
104 {
105
106 int nb_elem = ref_domaine_->nb_elem();
107 elem_part.resize_array(nb_elem);
108 elem_part = 0;
109 return;
110 }
111
112 if (ref_domaine_->nb_elem() == 0)
113 return;
114
115 Cerr << "Partitionneur_Parmetis::construire_partition" << finl;
116 Cerr << " Construction of graph connectivity..." << finl;
117 Static_Int_Lists graph_elements_perio;
118 //const Domaine& dom = ref_domaine_.valeur();
119 Domain_Graph graph;
120 graph.construire_graph_elem_elem(ref_domaine_.valeur(),
121 use_weights_,
122 graph_elements_perio);
123
124
125 std::vector<idx_t> partition(graph.nvtxs);
126
127 idx_t int_parts = nb_parties_;
128 idx_t edgecut = 0; // value returned by parmetis (total number of joint faces)
129 Cerr << " Call for PARMETIS" << finl;
130 idx_t options[3];
131 options[0] = 1; //personnalized options
132 options[1] = 111111111; // Maximum verbosity mode
133 options[2] = 0; //random seed
134
135 idx_t ncon=1;
136 real_t ubvec = 1.05f; //recommanded value
137 idx_t numflag = 0; //C numbering
138 std::vector<real_t> tpwgts(ncon*int_parts, (real_t)(1.0/nb_parties_)); //we want the weight to be equally distributed on each sub_somain
139 MPI_Comm comm = Comm_Group_MPI::get_trio_u_world();
140 int status = ParMETIS_V3_PartKway(graph.vtxdist.addr(), graph.xadj.addr(), graph.adjncy.addr(),
141 graph.vwgts.addr(), graph.ewgts.addr(), &graph.weightflag,
142 &numflag, &ncon, &int_parts, tpwgts.data(), &ubvec, options ,
143 &edgecut, partition.data(), &comm);
144 if (status != METIS_OK)
145 {
146 Cerr << "Call to PARMETIS failed." << finl;
147 if (status == METIS_ERROR) Cerr << "It seems there is a PARMETIS internal error." << finl;
148 Cerr << "Contact TRUST support." << finl;
149 exit();
150 }
151
152 Cerr << "Partitioning quality : edgecut = " << edgecut << finl;
153 Cerr << "-> It is roughly the total number of edges (faces) which will be shared by the processors." << finl;
154 Cerr << "-> The lesser this number is, the lesser the total volume of communication between processors." << finl;
155 Cerr << "-> You can increase nb_essais option (default 1) to try to reduce (but at a higher CPU cost) this number." << finl;
156 Cerr << "===============" << finl;
157
158 MD_Vector_tools::creer_tableau_distribue(ref_domaine_->md_vector_elements(), elem_part);
159 const int n = ref_domaine_->nb_elem();
160 for (int i = 0; i < n; i++)
161 elem_part[i] = static_cast<int>(partition[i]); // partition[i] is a a proc number...
162
163 // Correction of the partition for periodicity. (***)
164 if (graph_elements_perio.get_nb_lists() > 0)
165 {
166 Cerr << "Correction of the partition for the periodicity" << finl;
167 corriger_bords_avec_liste(ref_domaine_.valeur(),
168 0,
169 elem_part);
170 Cerr << " If this number is high, we can improve the splitting with the option use_weights\n"
171 << " but it takes more memory)" << finl;
172 }
173
174 Cerr << "Correction elem0 on processor 0" << finl;
175 corriger_elem0_sur_proc0(elem_part);
176 elem_part.echange_espace_virtuel();
177#endif
178}
179
Build the graph of the domain that the METIS/PARMETIS/PTSCOTCH libraries need.
ArrOfIdx_ vwgts
void construire_graph_elem_elem(const Domaine_32_64< _SIZE_ > &dom, bool use_weights, Static_Int_Lists_32_64< _SIZE_ > &graph_elements_perio)
ArrOfIdx_ ewgts
ArrOfIdx_ adjncy
ArrOfIdx_ vtxdist
ArrOfIdx_ xadj
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Transforms v into a parallel array having the structure md.
A character string (Nom) in uppercase.
Definition Motcle.h:26
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
virtual void set_param(Param &) const
Definition Objet_U.h:130
friend class Entree
Definition Objet_U.h:71
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
Partition of a domain into nb_parties balanced parts using the PARMETIS library.
void associer_domaine(const Domaine &domaine) override
void construire_partition(IntVect &elem_part, int &nb_parts_tot) const override
Computes the connectivity graph for parmetis, calls the partitioner and fills elem_part (for each ele...
void validate_params() const override
Called in the readOn of Objet_U_With_Params, after reading the params.
int lire_motcle_non_standard(const Motcle &, Entree &) override
Reads non-simple-type parameters of an Objet_U from an input stream.
int lire_motcle_non_standard(const Motcle &, Entree &) override
static void corriger_bords_avec_liste(const Domaine_t &dom, const int_t my_offset, BigIntVect_ &elem_part)
static void corriger_elem0_sur_proc0(BigIntVect_ &elem_part)
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
int_t get_nb_lists() const
Returns the number of stored lists.
_TYPE_ * addr()
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")