TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Connex_components_FT.cpp
1/****************************************************************************
2* Copyright (c) 2015 - 2016, 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 <Connex_components_FT.h>
17#include <communications.h>
18#include <ArrOfBit.h>
19#include <Connectivite_som_elem.h>
20#include <Maillage_FT_Disc.h>
21#include <Connex_components.h>
22#include <Static_Int_Lists.h>
23#include <TRUSTArray.h>
24
25/*! @brief Calcul des ensembles connexes par sommets d'elements non "marques" (les elements sont relies entre eux par un graphe
26 *
27 * symetrique passant par les faces).
28 * Une portion de domaine connexe porte un numero 0 <= i < N
29 * unique et est delimite soit par un bord, soit par un element voisin "marque"
30 * par num_compo[elem] = -1.
31 * Cette methode est sequentielle (peut etre appelee sur un seul processeur)
32 *
33 * @param (elem_faces)
34 * @param (faces_elem)
35 * @param (num_compo)
36 * @param (include_virtual) -> set to zero by default.
37 */
38int search_connex_components_local_FT(const Maillage_FT_Disc& mesh, ArrOfInt& num_compo,
39 const int include_virtual)
40{
41
42 const int dimension=mesh.dimension;
43 const int nbelem = mesh.nb_facettes();
44 // Construction de la connectivite element-element (pour chaque facette, numeros des 2 ou 3 facettes voisines
45 // -1 si pas de voisin)
46
47 Static_Int_Lists som_elem;
48 const IntTab& facettes = mesh.facettes();
49 IntTab elems(nbelem, dimension);
50 int i, j, k;
51 for (i=0; i < nbelem; i++)
52 for (j=0; j < dimension; j++)
53 elems(i,j) = facettes(i,j);
54
55 construire_connectivite_som_elem(mesh.nb_sommets(), elems, som_elem, include_virtual);
56 assert(som_elem.get_nb_lists ()==mesh.nb_sommets());
57
58 for (i = 0; i < nbelem; i++)
59 if (num_compo[i] != -1)
60 num_compo[i] = -2;
61
62 int start_element = 0;
63 int num_compo_courant = 0;
64 ArrOfInt liste_elems;
65 ArrOfInt tmp_liste;
66 //const int nb_som_elem=dimension-1;
67 const int nb_som_elem=dimension;
68
69 do
70 {
71 // Cherche le prochain element non attribue a une composante connexe
72 while (start_element < nbelem && num_compo[start_element] >= -1)
73 start_element++;
74 if (start_element == nbelem)
75 break;
76 // Recherche des elements de la composante connexe a partir de cet element
77 liste_elems.resize_array(1);
78 liste_elems[0] = start_element;
79 num_compo[start_element] = num_compo_courant;
80 while (liste_elems.size_array() > 0)
81 {
82 tmp_liste.resize_array(0);
83 const int liste_elems_size = liste_elems.size_array();
84 for (int i_elem = 0; i_elem < liste_elems_size; i_elem++)
85 {
86 const int elem = liste_elems[i_elem];
87 // Ajout des voisins non attribues de cet element dans la liste a
88 // traiter a l'etape suivante
89 for (int j2 = 0; j2 < nb_som_elem; j2++)
90 {
91 const int mon_som= facettes(elem, j2);
92 const int nb_elem_som= som_elem.get_list_size(mon_som);
93 for(k=0; k< nb_elem_som; k++)
94 {
95 const int voisin= som_elem(mon_som,k);
96 if (voisin >= 0)
97 {
98 const int num = num_compo[voisin];
99 if (num == -2)
100 {
101 num_compo[voisin] = num_compo_courant;
102 tmp_liste.append_array(voisin);
103 }
104 }
105 }
106 }
107 }
108 liste_elems = tmp_liste;
109 }
110 num_compo_courant++;
111 }
112 while (1);
113 // Renvoie le nombre de composantes connexes locales trouvees
114 return num_compo_courant;
115}
116
117/*! @brief Recherche les composantes connexes d'un ensemble d'elements distribue sur tous les processeurs.
118 *
119 * Cette methode est parallele et doit etre appelee en
120 * meme temps sur tous les processeurs.
121 *
122 * @param (num_compo)
123 * @param (nb_local_components)
124 */
125int compute_global_connex_components_FT(const Maillage_FT_Disc& mesh, ArrOfInt& num_compo, int nb_local_components)
126{
127 const int nbelem_tot = num_compo.size_array();
128 int i;
129
130 // Transformation des indices locaux de composantes connexes en un indice global
131 // (on ajoute un decalage aux indices globaux avec mppartial_sum())
132 const int decalage = Process::check_int_overflow(Process::mppartial_sum(nb_local_components)); // nb of compo should remain relatively small!
133 const int nb_total_components = Process::check_int_overflow(Process::mp_sum(nb_local_components));
134 for (i = 0; i < nbelem_tot; i++)
135 if (num_compo[i] >= 0)
136 num_compo[i] += decalage;
137
138 // Pour trouver les correspondances entre un numero de composante locale et un
139 // numero de la meme composante sur le processeur voisin, on cree une copie du
140 // tableau num_compo sur laquelle on fait un echange_espace_virtuel(). Ainsi,
141 // sur les cases virtuelles du tableau, on a dans num_compo le numero de la
142 // composante locale et dans copie_compo le numero de cette meme composante sur
143 // le processeur proprietaire de l'element. Donc ces deux numeros designent
144 // la meme composante connexe.
145 ArrOfInt copie_compo(num_compo);
146 mesh.desc_facettes().echange_espace_virtuel(copie_compo);
147
148 // Recherche des equivalences entre les numeros des composantes locales et
149 // les numeros des composantes voisines. On construit un graphe dont les
150 // liens relient les composantes equivalentes.
151 // Tableau de marqeurs pour les equivalences deja trouvees.
152 // Dimensions = nb composantes locales * nb_composantes total
153 // (pour ne pas prendre en compte la meme composante plusieurs fois).
154 ArrOfBit markers(nb_local_components * nb_total_components);
155 markers = 0;
156 // Tableau de correspondances entre composantes connexes locales et distantes
157 IntTab graph;
158 int graph_size = 0;
159 // Parcours des elements virtuels uniquement
160 for (i = 0; i < nbelem_tot; i++)
161 {
162 if (!mesh.facette_virtuelle(i))
163 // Ne traiter que les facettes virtuelles:
164 continue;
165
166 int compo = num_compo[i];
167 if (compo < 0)
168 continue;
169 int compo2 = copie_compo[i];
170 // Index du couple compo2/compo dans le tableau markers
171 // Le tableau num_compo ne doit contenir que des composantes locales:
172 assert(compo >= decalage && compo - decalage < nb_local_components);
173 // compo2 est forcement une composante distante.
174 assert(compo2 < decalage || compo2 - decalage >= nb_local_components);
175 const int index = (compo - decalage) * nb_total_components + compo2;
176 if (!markers.testsetbit(index))
177 {
178 graph.resize(graph_size+1, 2);
179 // On met le plus petit numero de composante en colonne 0:
180 if (compo2 < compo)
181 {
182 int tmp = compo;
183 compo = compo2;
184 compo2 = tmp;
185 }
186 graph(graph_size, 0) = compo;
187 graph(graph_size, 1) = compo2;
188 graph_size++;
189 }
190 }
191
192 ArrOfInt renum;
194 {
195 // Reception des portions de graphe des autres processeurs
196 IntTab tmp;
197 const int nproc = Process::nproc();
198 int pe;
199 for (pe = 1; pe < nproc; pe++)
200 {
201 recevoir(tmp, pe, 54 /* tag */);
202 const int n2 = tmp.dimension(0);
203 graph.resize(graph_size + n2, 2);
204 for (int i2 = 0; i2 < n2; i2++)
205 {
206 graph(graph_size, 0) = tmp(i2, 0);
207 graph(graph_size, 1) = tmp(i2, 1);
208 graph_size++;
209 }
210 }
211 // Calcul des composantes connexes du graphe
212 renum.resize_array(nb_total_components);
213 const int n = compute_graph_connex_components(graph, renum);
214 Process::Journal() << "compute_global_connex_components: nb_components=" << n << finl;
215 // Envoi des composantes connexes aux autres processeurs
216 }
217 else
218 {
219 // Envoi du graphe local au processeur 0
220 envoyer(graph, 0, 54 /* tag */);
221 }
222
223 envoyer_broadcast(renum, 0 /* processeur source */);
224
225 // Renumerotation des composantes dans num_compo
226 for (i = 0; i < nbelem_tot; i++)
227 {
228 const int x = num_compo[i];
229 if (x >= 0)
230 {
231 const int new_x = renum[x];
232 num_compo[i] = new_x;
233 }
234 }
235 // Verification: si on fait un echange espace virtuel,
236 // cela ne doit par changer le numero des composantes
237 // connexes !
238
239 int nb_components = 0;
240 if (renum.size_array() > 0)
241 nb_components = max_array(renum) + 1;
242 return nb_components;
243}
244
void echange_espace_virtuel(ArrOfDouble &tab) const
: class Maillage_FT_Disc Cette classe decrit un maillage:
int nb_sommets() const
renvoie le nombre de sommets (reels et virtuels) (egal a sommets().
int nb_facettes() const
renvoie le nombre de facettes (reelles et virtuelles) (egal a facettes().
int facette_virtuelle(int i) const
Renvoie 0 si la facette m'appartient, 1 sinon.
const Desc_Structure_FT & desc_facettes() const
renvoie le descripteur des facettes (espace_distant/virtuel)
const IntTab & facettes() const
renvoie le tableau des facettes (reelles et virtuelles) dimension(0) = nombre de facettes,
static int dimension
Definition Objet_U.h:99
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static trustIdType mppartial_sum(trustIdType i)
Calul de la somme partielle de i sur les processeurs 0 a me()-1 (renvoie 0 sur le processeur 0).
Definition Process.cpp:396
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
int_t get_list_size(int_t i_liste) const
renvoie le nombre d'elements de la liste i
int_t get_nb_lists() const
renvoie le nombre de listes stockees
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133