TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
Partitionneur_Sous_Domaines.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
16#include <Partitionneur_Sous_Domaines.h>
17#include <Synonyme_info.h>
18#include <Domaine.h>
19#include <Sous_Domaines.h>
20#include <Param.h>
21#include <Interprete.h>
22
23Implemente_instanciable_sans_constructeur(Partitionneur_Sous_Domaines,"Partitionneur_Sous_Domaines",Partitionneur_base);
24// XD partitionneur_sous_domaines partitionneur_deriv partitionneur_sous_domaines INHERITS_BRACE This algorithm will
25// XD_CONT create one part for each specified subdomaine/domain. All elements contained in the first subdomaine/domain
26// XD_CONT are put in the first part, all remaining elements contained in the second subdomaine/domain in the second
27// XD_CONT part, etc... NL2 If all elements of the current domain are contained in the specified subdomaines/domain,
28// XD_CONT then N parts are created, otherwise, a supplemental part is created with the remaining elements. NL2 If no
29// XD_CONT subdomaine is specified, all subdomaines defined in the domain are used to split the mesh.
30Add_synonym(Partitionneur_Sous_Domaines, "Partitionneur_Sous_Zones");
31
32Partitionneur_Sous_Domaines::Partitionneur_Sous_Domaines()
33{
34}
35
36
38{
39 Cerr << "Partitionneur_Sous_Domaines::printOn invalid\n" << finl;
40 exit();
41 return os;
42}
43
44/*! @brief Format de lecture: (la liste de sous_domaines/domaines est optionnelle, N est le nombre d'entites lues)
45 *
46 * {
47 * [ Sous_domaines N nom_sous_domaine1 nom_sous_domaine2 nom_sous_domaine3 ... ]
48 * [ Domaines N nom_domaine1 nom_domaine2 ... ]
49 * }
50 *
51 */
53{
54 if (!ref_domaine_)
55 {
56 Cerr << " Error: the domain has not been associated" << finl;
58 }
59 param.ajouter("sous_zones",&noms_sous_domaines_); // XD attr sous_zones listchaine sous_zones OPT N SUBZONE_NAME_1
60 // XD_CONT SUBZONE_NAME_2 ...
61 param.ajouter("domaines",&noms_domaines_); // XD attr domaines listchaine domaines OPT N DOMAIN_NAME_1
62 // XD_CONT DOMAIN_NAME_2 ...
63}
64
65/*! @brief Premiere etape d'initialisation du partitionneur: on associe un domaine.
66 *
67 */
69{
70 ref_domaine_ = domaine;
71}
72
73/*! @brief Deuxieme etape d'initialisation: on definit les sous_domaines a utiliser.
74 *
75 * (on peut utiliser readOn a la place).
76 *
77 */
78void Partitionneur_Sous_Domaines::initialiser(const Noms& noms_sous_domaines)
79{
80 assert(ref_domaine_);
81 noms_sous_domaines_ = noms_sous_domaines;
82}
83
84/*! @brief Chaque sous-domaine de noms_sous_domaines_ definit les elements attribues a un processeur.
85 *
86 * Les processeurs sont attribues dans l'ordre d'apparition des
87 * sous-domaines/domaines dans le domaine (et non dans l'ordre d'apparition dans
88 * la liste de sous-domaines).
89 * Premier sous_domaine/domaine qui figure dans la liste => proc 0
90 * Element du deuxieme sous_domaine => proc 1
91 * ...
92 * Elements restants qui ne figurent dans aucun sous_domaine => sur un nouveau pe.
93 * Si un element figure dans plusieurs sous-domaines, c'est le premier sous_domaine
94 * qui gagne.
95 *
96 */
97void Partitionneur_Sous_Domaines::construire_partition(IntVect& elem_part, int& nb_parts_tot) const
98{
99 assert(ref_domaine_);
100 const Domaine& dom = ref_domaine_.valeur();
101 const int nb_elem = dom.nb_elem_tot();
102 elem_part.resize(nb_elem);
103 elem_part = -1;
104 if (noms_domaines_.size()!=0 && noms_sous_domaines_.size())
105 {
106 Cerr << "Can't mix sous_domaines and domaines yet in sous_domaines partitionner." << finl;
108 }
109 // Numero de processeur en cours d'attribution:
110 int pe = 0;
111 int count = 0;
112 if (noms_domaines_.size()!=0)
113 {
114 for (int i=0; i<noms_domaines_.size(); i++)
115 {
116 const Nom& nom_domaine = noms_domaines_[i];
117 if (!interprete().objet_existant(nom_domaine) || !sub_type(Domaine, interprete().objet(nom_domaine)))
118 {
119 // Contrairement au sous domaine, le domaine doit exister pour le moment
120 Cerr << "Domain " << nom_domaine << " is not existing." << finl;
122 // ToDo eventuellement liste de domaines dans des fichiers ex: DOM_0000.Zones, DOM_0001.Zones
123 }
124 const Domaine& domaine = ref_cast(Domaine, interprete().objet(nom_domaine));
125 DoubleTab domaine_xp;
126 domaine.calculer_centres_gravite(domaine_xp);
127 IntVect dom_cells_containing_domaine_cells;
128 dom.chercher_elements(domaine_xp, dom_cells_containing_domaine_cells);
129 Cerr << " Allocation of elements of the domain " << domaine.le_nom() << " to the processor " << pe << finl;
130 for (int cell = 0; cell < dom_cells_containing_domaine_cells.size(); cell++)
131 {
132 int elem = dom_cells_containing_domaine_cells[cell];
133 if (elem_part[elem] < 0)
134 {
135 count++;
136 elem_part[elem] = pe;
137 }
138 }
139 Cerr << " Number of elements attributed to the processor " << pe << " : " << count << finl;
140 pe++;
141 }
142 }
143 else
144 {
145 Noms noms_sous_domaines(noms_sous_domaines_);
146 // Si le nom du seul Sous_Domaine est une liste de Sous_Domaine, on les recupere toutes:
147 if (noms_sous_domaines_.size()==1 && sub_type(Sous_Domaines, Interprete::objet(noms_sous_domaines_[0])))
148 {
149 const Sous_Domaines& liste = ref_cast(Sous_Domaines, Interprete::objet(noms_sous_domaines_[0]));
150 noms_sous_domaines.dimensionner_force(liste.size());
151 for (int i=0; i<liste.size(); i++) noms_sous_domaines[i]=liste[i].le_nom();
152 }
153 const int nb_sous_domaines = dom.nb_ss_domaines();
154 const int toutes_sous_domaines = (noms_sous_domaines.size() == 0);
155 if (toutes_sous_domaines)
156 Cerr << " No subarea specified, we use all existing subareas." << finl;
157 for (int i_sous_domaine = 0; i_sous_domaine < nb_sous_domaines; i_sous_domaine++)
158 {
159 const Sous_Domaine& sous_domaine = dom.ss_domaine(i_sous_domaine);
160 const Nom& nom = sous_domaine.le_nom();
161 bool sous_domaine_trouvee = noms_sous_domaines.contient_(nom);
162 if (!toutes_sous_domaines && !sous_domaine_trouvee)
163 continue;
164
165 count = 0;
166 const int nb_elem_ssz = sous_domaine.nb_elem_tot();
167 for (int i = 0; i < nb_elem_ssz; i++)
168 {
169 const int elem = sous_domaine[i];
170 if (elem_part[elem] < 0)
171 {
172 count++;
173 elem_part[elem] = pe;
174 }
175 }
176 Cerr << " Allocation of " << count << " elements from the subarea " << nom << " to the processor " << pe << finl;
177 pe++;
178 }
179 }
180 count = 0;
181 for (int elem = 0; elem < nb_elem; elem++)
182 {
183 if (elem_part[elem] < 0)
184 {
185 count++;
186 elem_part[elem] = pe;
187 }
188 }
189 if (count>0) Cerr << " Allocation of the remaining " << count << " elements to the processor " << pe << finl;
190 /*
191 if (count==0)
192 {
193 Cerr << "Error! The last domaine will be empty with 0 elements. It is surely not what you want." << finl;
194 Cerr << "Check, your partition strategy." << finl;
195 Process::exit();
196 } */
197 if (ref_domaine_->bords_perio().size() > 0)
198 corriger_bords_avec_liste(dom, 0, elem_part);
199
200 // On ne corrige pas elem0 sur proc0 (cas test CouplageFluide_Pb1Pb2_VEF_CN)
201}
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
int_t nb_elem_tot() const
Definition Domaine.h:132
SmallArrOfTID_t & chercher_elements(const DoubleTab &pos, SmallArrOfTID_t &elem, int reel=0) const
Recherche des elements contenant les points dont les coordonnees sont specifiees.
Definition Domaine.cpp:405
int nb_ss_domaines() const
Definition Domaine.h:289
static Objet_U & objet(const Nom &)
Voir Interprete_bloc::objet_global() BM: la classe Interprete n'est pas le meilleur endroit pour cett...
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
int contient_(const char *const ch) const
Definition Noms.cpp:60
virtual void set_param(Param &) const
Definition Objet_U.h:135
const Interprete & interprete() const
Definition Objet_U.cpp:212
virtual const Nom & le_nom() const
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Objet_U.cpp:319
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
Partitionneur de domaine a partir de sous-domaines du domaine Voir construire_partition().
void associer_domaine(const Domaine &domaine) override
Premiere etape d'initialisation du partitionneur: on associe un domaine.
void initialiser(const Noms &noms_sous_domaines)
Deuxieme etape d'initialisation: on definit les sous_domaines a utiliser.
void construire_partition(IntVect &elem_part, int &nb_parts_tot) const override
Chaque sous-domaine de noms_sous_domaines_ definit les elements attribues a un processeur.
static void corriger_bords_avec_liste(const Domaine_t &dom, const int_t my_offset, BigIntVect_ &elem_part)
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Classe de base des flux de sortie.
Definition Sortie.h:52
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
int_t nb_elem_tot() const
Un vecteur de Sous_Domaine (VECT(Sous_Domaine)).
_SIZE_ size() const
Definition TRUSTVect.tpp:45
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91