TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Descripteur_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 <Descripteur_FT.h>
17#include <Comm_Group.h>
18#include <TRUSTTabs.h>
19#include <communications.h>
20#include <Array_tools.h>
21#include <MD_Vector_std.h>
22
23Implemente_instanciable_sans_constructeur(Desc_Structure_FT,"Desc_Structure_FT",Objet_U);
24
25Implemente_instanciable_sans_constructeur(Descripteur_FT,"Descripteur_FT",Objet_U);
26
28 status_(OK)
29{
30 // Les tableaux sont initialises avec la taille maximale : nombre
31 // total de processeurs
32 const int n_proc = nproc();
33 // On reserve la memoire pour le maximum...
34 pe_voisins_.resize_array(n_proc);
35 pe_voisins_.resize_array(0);
36 elements_.dimensionner(n_proc);
37}
38
40{
41 const int n = nproc();
42 // Pour ne pas casser l'attribut smart resize:
43 for (int i = 0; i < n; i++)
44 elements_[i] = src.elements_[i];
45 pe_voisins_ = src.pe_voisins_;
46 return *this;
47}
48
50{
51 reset();
52 Nom motlu;
53 is >> motlu;
54 if (motlu != que_suis_je())
55 {
56 Cerr << "Erreur dans Descripteur_FT::readOn\n";
57 Cerr << " On attendait le motcle " << que_suis_je();
58 Cerr << "\n On a trouve " << motlu << finl;
60 }
61 is >> pe_voisins_;
62 int i;
63 const int nb_pe_voisins = pe_voisins_.size_array();
64 for (i = 0; i < nb_pe_voisins; i++)
65 {
66 int pe = pe_voisins_[i];
67 is >> elements_[pe];
68 }
69 return is;
70}
71
73{
74 const int nb_pe_voisins = pe_voisins_.size_array();
75 os << que_suis_je() << finl;
76 os << pe_voisins_;
77 int i;
78 for (i = 0; i < nb_pe_voisins; i++)
79 {
80 int pe = pe_voisins_[i];
81 os << elements_[pe];
82 }
83 return os;
84}
85
87{
88 int i;
89 const int n = elements_.size();
90 for (i = 0; i < n; i++)
91 {
92 elements_[i].resize_array(0);
93 }
94 pe_voisins_.resize_array(0);
95 status_ = OK;
96}
97
98/*! @brief Ajoute l'element au tableau du PE_voisin.
99 *
100 * renvoie le rang de l'element ajoute dans le tableau d'elements du PE.
101 *
102 */
103int Descripteur_FT::ajoute_element(int PE_voisin, int element)
104{
105 ArrOfInt& elements_voisins = elements_[PE_voisin];
106 int n = elements_voisins.size_array();
107 elements_voisins.append_array(element);
108 status_ = BAD;
109 return n;
110}
111/*! @brief Ajoute l'element au tableau du PE_voisin.
112 *
113 * renvoie la taiile du tableau d'elements du PE.
114 *
115 */
116int Descripteur_FT::ajoute_elements(int PE_voisin, const ArrOfInt& NVelements)
117{
118 ArrOfInt& elements_voisins = elements_[PE_voisin];
119 append_array_to_array(elements_voisins, NVelements);
120 status_ = BAD;
121 return elements_voisins.size_array();
122}
123
124/*! @brief Remplace la liste des elements par celle en parametre.
125 *
126 */
128 const ArrOfInt& new_elements)
129{
130 ArrOfInt& elements_voisins = elements_[PE_voisin];
131 elements_voisins = new_elements;
132 status_ = BAD;
133}
134
135/*! @brief Renvoie "pas zero" si l'element est deja dans le descripteur pour le pe donne, 0 sinon.
136 *
137 */
138int Descripteur_FT::contient_element(int pe, int element) const
139{
140 const ArrOfInt& elems = elements_[pe];
141 const int n = elems.size_array();
142 int i;
143 for (i = 0; i < n ; i++)
144 if (elems[i] == element) return 1;
145 return 0;
146}
147
148/*! @brief Calcule la liste des PEs dont la liste d'elements est non vide, tries dans l'ordre croissant de numero de PE.
149 *
150 * Le statut passe a OK.
151 *
152 */
154{
155 pe_voisins_.resize_array(0);
156 const int n = elements_.size();
157 // Boucle sur tous les PEs. Si la liste d'elements est non vide, on
158 // l'ajoute a la fin du tableau pe_voisins_.
159 for (int i = 0; i < n; i++)
160 if (elements_[i].size_array() > 0)
161 pe_voisins_.append_array(i);
162 status_ = OK;
163}
164
165/*! @brief Pour chaque PE du descripteur, et pour 0 <= i < elements_[pe].
166 *
167 * size_array() on considere l'element suivante:
168 * elem = elements_[pe][i]
169 * Si nouveau_pe[elem] >= 0, on retire elem du tableau elements_[pe]
170 * et on l'ajoute au tableau elements_retires.elements_[pe].
171 *
172 *
173 * @param (nouveau_pe) pour chaque element i (sommet ou facette), nouveau_pe[i] indique si l'element doit etre retire (nouveau_pe[i] >= 0) ou non (nouveau_pe[i] < 0) du descripteur Contrainte: la taille du tableau doit etre superieure au plus grand numero d'element stocke dans le descripteur.
174 * @param (elements_retires) descripteur contenant les elements retires.
175 */
176void Descripteur_FT::retirer_elements(const ArrOfInt& nouveau_pe,
177 Descripteur_FT& elements_retires)
178{
179 static ArrOfIntFT new_elements;
180
181 elements_retires.reset();
182
183 int index_pe, i;
184 int nb_voisins = pe_voisins_.size_array();
185 // Boucle sur les PEs du descripteur.
186 for (index_pe = 0; index_pe < nb_voisins; index_pe++)
187 {
188
189 int pe = pe_voisins_[index_pe];
190 const ArrOfInt& elements_voisins = elements_[pe];
191 ArrOfInt& elem_retires = elements_retires.elements_[pe];
192 new_elements.resize_array(0);
193 const int n = elements_voisins.size_array();
194 // Boucle sur les elements du descripteur
195 for (i = 0; i < n; i++)
196 {
197 const int element = elements_voisins[i];
198 const int new_pe = nouveau_pe[element];
199 if (new_pe < 0)
200 new_elements.append_array(element);
201 else
202 elem_retires.append_array(element);
203 }
204 // Remplace la liste d'elements du descripteur par la nouvelle liste
205 set_elements(pe, new_elements);
206 }
207 // Comme on a change les voisinages, on met a jour
209 elements_retires.calcul_liste_pe_voisins();
210}
211
212//******************************************************************************
213//******************************************************************************
214
215// Constructeur par defaut
216
221
223{
224 reset();
225 Nom motlu;
226 is >> motlu;
227 if (motlu != que_suis_je())
228 {
229 Cerr << "Erreur dans Desc_Structure_FT::readOn\n";
230 Cerr << " On attendait le motcle " << que_suis_je();
231 Cerr << "\n On a trouve " << motlu << finl;
233 }
234 is >> espace_distant_;
235 is >> espace_virtuel_;
236
237 check();
238 return is;
239}
240
242{
243 os << que_suis_je() << finl;
244 os << espace_distant_;
245 os << espace_virtuel_;
246 return os;
247}
248
249// Description : vide toutes les listes d'elements des descripteurs.
251{
252 espace_distant_.reset();
253 espace_virtuel_.reset();
254 status_md_ = BAD;
255}
256
257/*! @brief Renvoie une reference non-const a l'espace distant.
258 *
259 * Le statut du descripteur passe a BAD => il faudra recalculer le schema de com.
260 *
261 */
267
268/*! @brief Renvoie une reference const a l'espace distant.
269 *
270 * Le statut reste OK.
271 *
272 */
277
278/*! @brief Renvoie une reference non-const a l'espace virtuel.
279 *
280 * Le statut du descripteur passe a BAD => il faudra recalculer le schema de com.
281 *
282 */
288
289/*! @brief Renvoie une reference const a l'espace virtuel.
290 *
291 * Le statut reste OK.
292 *
293 */
298
299
300/*! @brief Verification de la coherence de la structure (graphe des voisins et taille des espaces virtuels et distants)
301 *
302 * On envoie tout au processeur 0.
303 *
304 */
306{
307 const int nb_proc = nproc();
308 int i;
309
310 // Pour etre sur d'arriver en meme temps ici:
311 barrier();
312
313 // Premiere etape du test: un element est
314 // * soit dans le tableau d'elements_ virtuels d'un unique pe,
315 // * soit dans un nombre quelconque de tableaux d'elements distants.
316 {
317 // Calcul du plus grand numero d'element mentionne dans les descripteurs
318 int max_num_element = 0;
319 {
320 const ArrOfInt& pe_list = espace_distant_.pe_voisins();
321 const int npe = pe_list.size_array();
322 for (i = 0; i < npe; i++)
323 {
324 const int pe_voisin = pe_list[i];
325 const int valeur_max = max_array(espace_distant_.elements(pe_voisin));
326 if (valeur_max > max_num_element)
327 max_num_element = valeur_max;
328 }
329 }
330 {
331 const ArrOfInt& pe_list = espace_virtuel_.pe_voisins();
332 const int npe = pe_list.size_array();
333 for (i = 0; i < npe; i++)
334 {
335 const int pe_voisin = pe_list[i];
336 const int valeur_max = max_array(espace_virtuel_.elements(pe_voisin));
337 if (valeur_max > max_num_element)
338 max_num_element = valeur_max;
339 }
340 }
341 ArrOfInt nb_tableaux_distants(max_num_element+1);
342 nb_tableaux_distants = 0;
343 // On compte le nombre de fois ou les elements apparaissent dans l'espace distant
344 {
345 const ArrOfInt& pe_list = espace_distant_.pe_voisins();
346 const int npe = pe_list.size_array();
347 for (i = 0; i < npe; i++)
348 {
349 const int pe_voisin = pe_list[i];
350 const ArrOfInt& elements = espace_distant_.elements(pe_voisin);
351 const int n = elements.size_array();
352 for (int j = 0; j < n; j++)
353 {
354 const int elem = elements[j];
355 ++nb_tableaux_distants[elem];
356 }
357 }
358 }
359 // On compte le nombre de fois ou les elements apparaissent dans l'espace virtuel
360 {
361 const ArrOfInt& pe_list = espace_virtuel_.pe_voisins();
362 const int npe = pe_list.size_array();
363 for (i = 0; i < npe; i++)
364 {
365 const int pe_voisin = pe_list[i];
366 const ArrOfInt& elements = espace_virtuel_.elements(pe_voisin);
367 const int n = elements.size_array();
368 for (int j = 0; j < n; j++)
369 {
370 const int elem = elements[j];
371 const int x = nb_tableaux_distants[elem];
372 if (x != 0)
373 {
374 // Soit l'element est dans un espace distant, soit il est dans un autre
375 // espace virtuel. Ca va pas.
376 Cerr << "(PE " << Process::me();
377 Cerr << ") l'element " << elem;
378 Cerr << " apparait dans ";
379 if (x > 0)
380 Cerr << " des espaces distants et un espace virtuel" << finl;
381 else
382 Cerr << " plusieurs espaces virtuels" << finl;
384 }
385 else
386 {
387 nb_tableaux_distants[elem] = -1;
388 }
389 }
390 }
391 }
392 }
393
394 VECT(IntTab) procs_distants(nb_proc);
395 VECT(IntTab) procs_virtuels(nb_proc);
396
397 // Tout le monde envoie ses descripteurs au processeur 0
398 {
399 // Construction d'un tableau : pour chaque pe voisin, numero du pe (colonne 0)
400 // et nombre d'elements a envoyer/recevoir (colonne 1)
401 int moi = me();
402 IntTab& procs_dist = procs_distants[moi];
403 const ArrOfInt& pe_distants = espace_distant_.pe_voisins();
404 int nb_procs_distants = pe_distants.size_array();
405 procs_dist.resize(nb_procs_distants, 2);
406 for (i = 0; i < nb_procs_distants; i++)
407 {
408 int pe_voisin = pe_distants[i];
409 procs_dist(i, 0) = pe_voisin;
410 procs_dist(i, 1) = espace_distant_.elements(pe_voisin).size_array();
411 }
412
413 IntTab& procs_virt = procs_virtuels[moi];
414 const ArrOfInt& pe_virtuels = espace_virtuel_.pe_voisins();
415 int nb_procs_virtuels = pe_virtuels.size_array();
416 procs_virt.resize(nb_procs_virtuels, 2);
417 for (i = 0; i < nb_procs_virtuels; i++)
418 {
419 int pe_voisin = pe_virtuels[i];
420 procs_virt(i, 0) = pe_voisin;
421 procs_virt(i, 1) = espace_virtuel_.elements(pe_voisin).size_array();
422 }
423 }
424
425 if (!je_suis_maitre())
426 {
427 int moi = me();
428 envoyer(procs_distants[moi], 0, 0);
429 envoyer(procs_virtuels[moi], 0, 1);
430 }
431 else
432 {
433 for (i = 1; i < nb_proc; i++)
434 {
435 recevoir(procs_distants[i], i, 0);
436 recevoir(procs_virtuels[i], i, 1);
437 }
438 }
439 // Le maitre reste tard le soir pour finir le travail
440 if (me() != 0)
441 return 1;
442
443 // On verifie que le nombre d'elements distants correspond bien
444 // au nombre d'elements virtuels du processeur voisin...
445
446 // Boucle sur les PEs,
447 // et pour chaque PE, boucle sur les voisins de l'espace distant.
448 // On cherche ce voisin dans l'espace virtuel du PE...
449 {
450 // Nombre de voisins deja parcourus dans les espaces virtuels...
451 ArrOfInt curseurs(nb_proc);
452 curseurs = 0;
453
454 for (i = 0; i < nb_proc; i++)
455 {
456
457 // La liste des voisins du proc i par l'espace distant
458 const IntTab& procs_dist = procs_distants[i];
459 int nb_pe_voisins = procs_dist.dimension(0);
460
461 for (int j = 0; j < nb_pe_voisins; j++)
462 {
463
464 int pe_voisin = procs_dist(j, 0);
465 int nb_elements = procs_dist(j, 1);
466 // On verifie que l'espace virtuel du pe_voisin correspond
467 const int index = curseurs[pe_voisin];
468 curseurs[pe_voisin]++;
469 const IntTab& procs_virt = procs_virtuels[pe_voisin];
470 if (index >= procs_virt.dimension(0) || procs_virt(index, 0) != i)
471 {
472 Cerr << "Descripteur_FT::check : erreur sur le graphe de voisinage.\n";
473 Cerr << " Les espaces distants et virtuels ne se correspondent pas.\n";
474 Cerr << pe_voisin << finl;
476 }
477 if (procs_virt(index, 1) != nb_elements)
478 {
479 Cerr << "Descripteur_FT::check : erreur sur une liste d'elements.\n";
480 Cerr << " Espace distant du PE " << i << " : PE voisin " << pe_voisin;
481 Cerr << ", nombre d'elements " << nb_elements;
482 Cerr << "\n Espace virtuel du PE " << pe_voisin << " : PE voisin " << i;
483 Cerr << ", nombre d'elements " << procs_virt(index, 1) << finl;
485 }
486 }
487 }
488 // On verifie que tous les espaces virtuels ont ete balayes
489 for (i = 0; i < nb_proc; i++)
490 {
491 const int n1 = curseurs[i];
492 const int n2 = procs_virtuels[i].dimension(0);
493 if (n1 < n2)
494 {
495 Cerr << "Descripteur_FT::check : erreur sur le graphe de voisinage.\n";
496 Cerr << " Les espaces distants et virtuels ne se correspondent pas." << finl;
498 }
499 }
500 }
501 return 1;
502}
503
504/*! @brief Correction des espaces distants et virtuels lors d'un changement de proprietaire (noeud ou facette).
505 *
506 * Les operations sont les suivantes :
507 * - sur l'ancien proprietaire de l'element, on retire l'element de l'espace distant.
508 * - sur le nouveau proprietaire, on ajoute l'element a l'espace distant, pour tous
509 * les PEs ou cet element est virtuel.
510 * - sur les PEs ou cet element est virtuel, on retire l'element de la liste
511 * d'elements virtuels de l'ancien PE et on l'ajoute a la fin de la liste d'elements
512 * virtuels du nouveau proprietaire.
513 * L'ordre d'ajout des elements dans les espaces distants et virtuels est identique
514 * pour que les espaces soient en correspondance.
515 *
516 *
517 * @param (nouveau_pe) tableau de taille nb_sommets ou nb_facettes, qui contient le numero du nouveau pe proprietaire, ou -1 si l'element ne change pas de main. L'espace virtuel de ce tableau doit etre a jour (echange_espace_virtuel realise).
518 */
519void Desc_Structure_FT::echanger_elements(const ArrOfInt& nouveau_pe)
520{
521 static Descripteur_FT elements_distants_retires;
522 static Descripteur_FT elements_virtuels_retires;
523 static Descripteur_FT elements_recus;
524 static Descripteur_FT elements_envoyes;
525 static ArrOfInt cles;
526
527 const int moi = me();
528
529 cles.resize_array(nouveau_pe.size_array());
530 cles = -1;
531
532 // On retire des espaces distants et virtuels les elements qui ont change de main.
533 // Chaque element est retire a la fois de l'espace distant et de l'espace virtuel,
534 // ces deux espaces restent donc en correspondance.
535 // De plus elements_distants_retires et elements_virtuels_retires sont aussi
536 // en correspondance.
537
538 espace_distant_.retirer_elements(nouveau_pe, elements_distants_retires);
539 espace_virtuel_.retirer_elements(nouveau_pe, elements_virtuels_retires);
540
541 // Traitement des elements_virtuels_retires. Pour chaque element:
542 // * soit le nouveau pe de l'element n'est pas moi : on cree un element virtuel
543 // * soit c'est moi qui le recoit : on ajoute l'element a la liste d'elements recus
544 // A la fin de ce traitement, elements_recus contient la liste de tous les elements
545 // qu'il faut ajouter a des espaces distants.
546 // On a ajoute a l'espace virtuel les elements virtuels->virtuels
547 // (qui etaient virtuels avant et qui sont virtuels apres).
548 {
549 const ArrOfInt& pe_voisins = elements_virtuels_retires.pe_voisins();
550 const int nb_voisins = pe_voisins.size_array();
551 for (int index_pe = 0; index_pe < nb_voisins; index_pe++)
552 {
553 const int pe_origine = pe_voisins[index_pe];
554 const ArrOfInt& elements = elements_virtuels_retires.elements(pe_origine);
555 const int nb_elements = elements.size_array();
556 for (int i = 0; i < nb_elements; i++)
557 {
558 const int element = elements[i];
559 int pe_destination = nouveau_pe[element];
560 if (pe_destination == moi)
561 {
562 elements_recus.ajoute_element(pe_origine, element);
563 }
564 else
565 {
566 espace_virtuel_.ajoute_element(pe_destination, element);
567 }
568 }
569 }
570 }
571 elements_recus.calcul_liste_pe_voisins();
572
573 // Remplissage d'un descripteur contenant, pour chaque PE, la liste des
574 // elements qu'on lui envoie (elements_envoyes). Ces elements sont les
575 // elements_distants_retires dont le nouveau_pe est le pe_distant.
576 // On remplit en meme temps la "cle" qui represente l'element transmis
577 // au pe destination. Cette cle est le rang de l'element dans
578 // elements_envoyes.elements(pe_destination).
579 // On ajoute a l'espace virtuel les elements reel->virtuel
580 // (qui etaient reels avant et qui sont virtuels maintenant).
581 {
582 const ArrOfInt& pe_voisins = elements_distants_retires.pe_voisins();
583 const int nb_voisins = pe_voisins.size_array();
584 for (int index_pe = 0; index_pe < nb_voisins; index_pe++)
585 {
586 const int pe_distant = pe_voisins[index_pe];
587 const ArrOfInt& elements = elements_distants_retires.elements(pe_distant);
588 const int nb_elements = elements.size_array();
589 for (int i = 0; i < nb_elements; i++)
590 {
591 const int element = elements[i];
592 const int pe_destination = nouveau_pe[element];
593 if (pe_destination == pe_distant)
594 {
595 const int cle = elements_envoyes.ajoute_element(pe_distant, element);
596 assert(cles[element] < 0);
597 cles[element] = cle;
598 // Cet ajout est symetrique de l'ajout (*) a la fin de la fonction:
599 espace_virtuel_.ajoute_element(pe_distant, element);
600 }
601 }
602 }
603 }
604 elements_envoyes.calcul_liste_pe_voisins();
605
606 // Traitement des espaces distants: il faut envoyer au nouveau proprietaire
607 // les numeros des PEs voisins pour chaque noeud qu'on lui envoie.
608 // Le noeud est repere par la "cle", car les descripteurs elements_envoyes
609 // et elements_recus sont en correspondance.
610 schema_comm_.set_send_recv_pe_list(elements_envoyes.pe_voisins(),
611 elements_recus.pe_voisins());
612
613 schema_comm_.begin_comm();
614 {
615 const ArrOfInt& pe_voisins = elements_distants_retires.pe_voisins();
616 const int nb_voisins = pe_voisins.size_array();
617 for (int index_pe = 0; index_pe < nb_voisins; index_pe++)
618 {
619 const int pe_distant = pe_voisins[index_pe];
620 const ArrOfInt& elements = elements_distants_retires.elements(pe_distant);
621 const int nb_elements = elements.size_array();
622 for (int i = 0; i < nb_elements; i++)
623 {
624 const int element = elements[i];
625 const int pe_destination = nouveau_pe[element];
626 if (pe_destination != pe_distant)
627 {
628 const int cle = cles[element];
629 assert(cle >= 0);
630 schema_comm_.send_buffer(pe_destination) << cle << pe_distant;
631 }
632 }
633 }
634 }
635 schema_comm_.echange_taille_et_messages();
636 // Recuperation des espaces distants :
637 // Si le processeur distant est moi, alors je mets le noeud dans l'espace
638 // distant du PE d'origine.
639 // On ajoute a l'espace distant les elements virtuel->virtuel
640 {
641 const ArrOfInt& pe_voisins = elements_recus.pe_voisins();
642 const int nb_voisins = pe_voisins.size_array();
643 for (int index_pe = 0; index_pe < nb_voisins; index_pe++)
644 {
645 const int pe_origine = pe_voisins[index_pe];
646 Entree& recv_buffer = schema_comm_.recv_buffer(pe_origine);
647 const ArrOfInt& elements = elements_recus.elements(pe_origine);
648 while (1)
649 {
650 int cle, pe_distant;
651 recv_buffer >> cle >> pe_distant;
652 if (recv_buffer.eof())
653 break;
654 const int element = elements[cle];
655 espace_distant_.ajoute_element(pe_distant, element);
656 }
657 }
658 }
659 schema_comm_.end_comm();
660
661 // Ajout (*) des elements virtuels->distants a l'espace distant
662 // (qui etaient virtuels et qui sont reels maintenant)
663 {
664 const ArrOfInt& pe_voisins = elements_virtuels_retires.pe_voisins();
665 const int nb_voisins = pe_voisins.size_array();
666 for (int index_pe = 0; index_pe < nb_voisins; index_pe++)
667 {
668 const int pe_distant = pe_voisins[index_pe];
669 const ArrOfInt& elements = elements_virtuels_retires.elements(pe_distant);
670 const int nb_elements = elements.size_array();
671 for (int i = 0; i < nb_elements; i++)
672 {
673 const int element = elements[i];
674 int pe_destination = nouveau_pe[element];
675 if (pe_destination == moi)
676 espace_distant_.ajoute_element(pe_distant, element);
677 }
678 }
679 }
680
681 espace_distant_.calcul_liste_pe_voisins();
682 espace_virtuel_.calcul_liste_pe_voisins();
684
685 status_md_ = BAD;
686 calcul_schema_comm(nouveau_pe.size_array());
687 cles.resize_array(0); // Libere la memoire du tableau
688}
689
690/*! @brief remplit le tableau qui donne pour chaque element le numero du pe proprietaire.
691 *
692 * Le tableau fourni doit avoir la bonne
693 * taille (nombre d'elements = sommets ou facettes par ex.)
694 * Ce tableau est rempli en utilisant l'espace virtuel (tous les elements
695 * sont a moi, sauf ceux qui sont dans l'espace virtuel).
696 *
697 */
698void Desc_Structure_FT::remplir_element_pe(ArrOfInt& element_pe) const
699{
700 // Tout est a moi ...
701 element_pe = me();
702
703 // ... sauf ce qui est dans les espaces virtuels
704 const ArrOfInt& pe_voisins = espace_virtuel_.pe_voisins();
705 const int nb_voisins = pe_voisins.size_array();
706 for (int i = 0; i < nb_voisins; i++)
707 {
708 const int pe = pe_voisins[i];
709 const ArrOfInt& elements = espace_virtuel_.elements(pe);
710 const int nb_elements = elements.size_array();
711 for (int j = 0; j < nb_elements; j++)
712 {
713 int element = elements[j];
714 element_pe[element] = pe;
715 }
716 }
717}
718
719void Desc_Structure_FT::calcul_schema_comm(const int nb_items_tot)
720{
721 const int n = nproc();
722 if (pe_voisins_.size_array() != n)
723 {
724 pe_voisins_.resize_array(n);
725 blocs_to_recv_.dimensionner(n);
726 for (int i = 0; i < n; i++)
727 pe_voisins_[i] = i;
728 }
729
730 const VECT(ArrOfInt) & items_to_send_ = espace_distant().all_elements();
731 const VECT(ArrOfInt) & items_to_recv_ = espace_virtuel().all_elements();
732
733 MD_Vector_std md(nb_items_tot,
734 -1, /* nb_items reels */
736 items_to_send_,
737 items_to_recv_,
738 blocs_to_recv_);
739
740 md_vector_.copy(md);
741
742 const ArrOfInt& send_procs = espace_distant().pe_voisins();
743 const ArrOfInt& recv_procs = espace_virtuel().pe_voisins();
744 schema_comm_.set_send_recv_pe_list(send_procs, recv_procs);
745 schema_comm_inverse_.set_send_recv_pe_list(recv_procs, send_procs);
746
747 status_md_ = OK;
748}
749
751{
752 assert(status_md_ == OK);
753 return schema_comm_;
754}
755
757{
758 assert(status_md_ == OK);
760}
761
766
771
776
781
783{
784 assert(status_md_ == OK);
785 IntVect& y = tmp_intvect_;
786 IntVect* intV = dynamic_cast<IntVect*>(&x);
787
788 if (intV) y.ref(*intV);
789 else y.ref_array(x);
790
793 y.reset();
794}
795
797{
798 assert(status_md_ == OK);
799 DoubleVect& y = tmp_doublevect_;
800 DoubleVect* doubleV = dynamic_cast<DoubleVect*>(&x);
801
802 if (doubleV) y.ref(*doubleV);
803 else y.ref_array(x);
804
807 y.reset();
808}
809
811{
812 assert(status_md_ == OK);
813 return md_vector_;
814}
static int check_enabled()
Definition Comm_Group.h:159
: class Desc_Structure_FT
void collecter_espace_virtuel(ArrOfDouble &tab, MD_Vector_tools::Operations_echange op) const
int check() const
Verification de la coherence de la structure (graphe des voisins et taille des espaces virtuels et di...
void echange_espace_virtuel(ArrOfDouble &tab) const
Descripteur_FT & espace_virtuel()
Renvoie une reference non-const a l'espace virtuel.
void echanger_elements(const ArrOfInt &nouveau_pe)
Correction des espaces distants et virtuels lors d'un changement de proprietaire (noeud ou facette).
VECT(ArrOfInt) blocs_to_recv_
DoubleVect tmp_doublevect_
const MD_Vector & get_md_vector() const
Descripteur_FT espace_virtuel_
Schema_Comm schema_comm_
Descripteur_FT & espace_distant()
Renvoie une reference non-const a l'espace distant.
void calcul_schema_comm(const int nb_items_tot)
const Schema_Comm & schema_comm() const
const Schema_Comm & schema_comm_inverse() const
enum Desc_Structure_FT::Status status_md_
Schema_Comm schema_comm_inverse_
Descripteur_FT espace_distant_
void remplir_element_pe(ArrOfInt &element_pe) const
remplit le tableau qui donne pour chaque element le numero du pe proprietaire.
: class Descripteur_FT Descripteur_FT stocke pour chaque PE une liste de numeros d'elements.
int contient_element(int pe, int element) const
Renvoie "pas zero" si l'element est deja dans le descripteur pour le pe donne, 0 sinon.
Descripteur_FT & operator=(const Descripteur_FT &)
void set_elements(int PE_voisin, const ArrOfInt &elements)
Remplace la liste des elements par celle en parametre.
void retirer_elements(const ArrOfInt &nouveau_pe, Descripteur_FT &elements_retires)
Pour chaque PE du descripteur, et pour 0 <= i < elements_[pe].
int ajoute_element(int PE_voisin, int element)
Ajoute l'element au tableau du PE_voisin.
const ArrOfInt & elements(int pe_voisin) const
Renvoie la liste des elements distants/virtuels du pe en parametre.
const ArrOfInt & pe_voisins() const
Renvoie la liste des PE pour lesquels la liste d'elements est non vide, dans l'ordre croissant des nu...
void calcul_liste_pe_voisins()
Calcule la liste des PEs dont la liste d'elements est non vide, tries dans l'ordre croissant de numer...
int ajoute_elements(int PE_voisin, const ArrOfInt &elements)
Ajoute l'element au tableau du PE_voisin.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
virtual int eof()
Definition Entree.cpp:256
C'est le plus simple des descripteurs, utilise pour les tableaux de valeurs aux sommets,...
static void echange_espace_virtuel(IntVect &, Operations_echange opt=ECHANGE_EV, IsExchangeBlocking is_exchange_blocking=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
friend class Entree
Definition Objet_U.h:76
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
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 void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
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
Classe de base des flux de sortie.
Definition Sortie.h:52
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
virtual void set_md_vector(const MD_Vector &)
void ref_array(TRUSTArray< _TYPE_, _SIZE_ > &, _SIZE_ start=0, _SIZE_ sz=-1) override
void reset() override
met l'objet dans l'etat obtenu par le constructeur par defaut.
Definition TRUSTVect.h:189
virtual void ref(const TRUSTVect &)