TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Domaine.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 <Domaine.h>
17#include <TRUSTList.h>
18#include <TRUSTTabs.h>
19#include <Sous_Domaine.h>
20#include <Scatter.h>
21#include <Poly_geom_base.h>
22#include <Octree.h>
23#include <Octree_Double.h>
24#include <Periodique.h>
25#include <Reordonner_faces_periodiques.h>
26#include <Frontiere_dis_base.h>
27#include <Frontiere.h>
28#include <Conds_lim.h>
29#include <NettoieNoeuds.h>
30#include <Polyedre.h>
31#include <TRUST_2_MED.h>
32#include <Comm_Group_MPI.h>
33#include <Option_Interpolation.h>
34#include <Array_tools.h>
35#include <Schema_Comm.h>
36#include <Interprete_bloc.h>
37#include <Extraire_surface.h>
38#include <Domaine_VF.h>
39#include <MD_Vector_std.h>
40#include <MD_Vector_seq.h>
41#include <Reorder_Mesh.h>
42#include <Perf_counters.h>
43
44Implemente_instanciable_sans_constructeur_32_64( Domaine_32_64, "Domaine", Domaine_base );
45// XD domaine domaine_base domaine INHERITS_BRACE Keyword to create a domain.
46// XD domaine_64 domaine_base domaine_64 INHERITS_BRACE Keyword to create a big (64b) domain.
47
48// Anonymous namespace for all local methods to this translation unit
49namespace
50{
51
52static double cached_memory = 0;
53
54template<class LIST_FRONTIERE>
55void check_frontiere(const LIST_FRONTIERE& list, const char *msg)
56{
57 int n = list.size();
58 if (!is_parallel_object(n))
59 {
60 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
63 }
64 for (int i = 0; i < n; i++)
65 {
66 const Nom& nom = list[i].le_nom();
67 Cerr << " Boundary " << msg << " : " << nom << finl;
68 if (!is_parallel_object(nom))
69 {
70 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
73 }
74 }
75}
76
77// S'il y a un proc qui a un type different de vide_OD, on type les faces sur tous
78// les processeurs avec ce type:
79template <class _SIZE_>
80void corriger_type(Faces_32_64<_SIZE_>& faces, const OWN_PTR(Elem_geom_base_32_64<_SIZE_>)& type_elem)
81{
82 Type_Face typ = faces.type_face();
83 const int pe = (faces.type_face() == Type_Face::vide_0D) ? Process::nproc() - 1 : Process::me();
84 const int min_pe = Process::mp_min(pe);
85 // Le processeur min_pe envoie son type a tous les autres
86 int typ_commun_i = static_cast<int>(typ);
87 envoyer_broadcast(typ_commun_i, min_pe);
88 Type_Face typ_commun = static_cast<Type_Face>(typ_commun_i);
89
90 if (typ_commun != typ)
91 {
92 if (typ != Type_Face::vide_0D)
93 {
94 Cerr << "Error in Domaine.cpp corriger_type: invalid boundary face type" << finl;
96 }
97 faces.typer(typ_commun);
98 int n = type_elem->nb_som_face();
99 faces.les_sommets().resize(0, n);
100 }
101}
102
103} // end anonymous namespace
104
105/*! @brief Reset the Domaine completely except for its name.
106 */
107template<typename _SZ_>
109{
110 sommets_.reset();
111 renum_som_perio_.reset();
113 mes_elems_.reset();
114 aretes_som_.reset();
115 elem_aretes_.reset();
116 mes_faces_bord_.vide();
117 mes_faces_raccord_.vide();
118 mes_bords_int_.vide();
119 mes_groupes_faces_.vide();
120 mes_faces_joint_.vide();
121 ind_faces_virt_bord_.reset();
122 cg_moments_.reset();
123 elem_virt_pe_num_.reset();
124 domaines_frontieres_.vide();
125 les_ss_domaines_.vide();
126
128 bords_a_imprimer_.vide();
129 bords_a_imprimer_sum_.vide();
130
131 bords_perio_.clear();
132
134 fichier_lu_ = Nom();
135
136#ifdef MEDCOUPLING_
137 mc_mesh_.nullify();
138 rmps.clear();
139#endif
140
141 volume_total_ = -1;
142}
143
144/*! @brief Ecrit la Domaine sur un flot de sortie.
145 *
146 * On ecrit le nom, le type des elements, les elements
147 * et les bords, les bords periodiques, les joints, les
148 * raccords et les bords internes.
149 *
150 * @param (Sortie& s) un flot de sortie
151 * @return (Sortie&) le flot de sortie modifie
152 */
153template<typename _SZ_>
155{
156 Cerr << "Writing of " << nb_som() << " nodes." << finl;
157#ifdef SORT_POUR_DEBOG
158 s.setf(ios::scientific);
159 s.precision(20);
160#endif
161 s << nom_ << finl;
162 s << sommets_;
163
164 // Now write what was formerly the "Zon-e-s" (before TRUST 1.9.2):
165 // Write them in the form of a list with a single element, for backward compat (Domains used to contain a list of Zon-e-s)
166 s << "{" << finl;
167 Cerr << "Writing of " << nb_elem() << " elements." << finl;
168 s << "DUMMY_ZONE" << finl; // really just to keep a name here for backward compat
169 s << elem_ << finl;
170 s << mes_elems_;
171 s << mes_faces_bord_;
172 s << mes_faces_joint_;
173 s << mes_faces_raccord_;
174 s << mes_bords_int_;
175 if (nb_groupes_faces() !=0)
176 {
177 s << finl << "groupes_faces" << finl;
178 s << mes_groupes_faces_;
179 }
180
181 // New in TRUST 1.9.8 - list of periodic boundaries are directly stored in Domain class
182 s << finl << "bords_perio" << finl;
183 s << bords_perio_;
184
185 s << "}" << finl;
186
187 return s;
188}
189
190/*! @brief See readOn_has_perio()
191 */
192template<typename _SZ_>
194{
195 bool dnu;
196 return readOn_has_perio(s, dnu);
197}
198
199/*! @brief Lit les objets constituant un Domaine a partir d'un flot d'entree.
200 *
201 * Une fois les objets
202 * lus on les associe au domaine.
203 *
204 * @param (Entree& s) un flot d'entree
205 * @param (bool& has_perio) set to True if periodic boundaries were read, false otherwise.
206 * @return (Entree&) le flot d'entree modifie
207 */
208template<typename _SZ_>
210{
211#ifdef SORT_POUR_DEBOG
212 s.setf(ios::scientific);
213 s.precision(20);
214#endif
215 has_perio = false;
216 // Ajout BM: reset de la structure (a pour effet de debloquer la structure parallele)
217 sommets_.reset();
218 renum_som_perio_.reset();
219 // ne pas faire reset du nom (deja lu)
220 // pour deformable je ne sais pas...
221
222 Nom tmp;
223 s >> tmp;
224 // Si le domaine n'est pas nomme, on prend celui lu
225 if (nom_=="??") nom_=tmp;
226 Cerr << "Reading domain " << le_nom() << finl;
227 s >> sommets_;
228 // PL : pas tout a fait exact le nombre affiche de sommets, on compte plusieurs fois les sommets des joints...
229 trustIdType nbsom = mp_sum(sommets_.dimension(0));
230 Cerr << " Number of nodes: " << nbsom << finl;
231
232 // Reading element description (what was fomerly the "domaine" part) - this used to be a list so check for '{ }'
233 Nom acc;
234 s >> acc;
235 assert (acc == "{");
236 read_former_domaine(s, has_perio);
238
240 {
242 nbsom = mp_sum(sommets_.dimension(0));
243 Cerr << " Number of nodes after node-cleanup: " << nbsom << finl;
244 }
245
246 // On initialise les descripteurs "sequentiels" (attention, cela bloque le resize des tableaux sommets et elements !)
249 return s;
250}
251
252
253/*! @brief read what was (before TRUST 1.9.2) the "domaine" part from the input stream
254 * i.e. (roughly) the element description.
255 *
256 * @param read_perio set to True if periodic boundaries were read in the domain (from TRUST 1.9.8)
257 */
258template<typename _SZ_>
260{
261 Nom dnu, acc;
262 read_perio = false;
263 Cerr << " Reading part of domain " << le_nom() << finl;
264 s >> dnu; // Name of the Domaine, now unused ...
265 s >> elem_;
266 mes_elems_.reset();
267 s >> mes_elems_;
268 mes_faces_bord_.vide();
269 s >> mes_faces_bord_;
270 mes_faces_joint_.vide();
271 s >> mes_faces_joint_;
272 mes_faces_raccord_.vide();
274 mes_bords_int_.vide();
275 s >> mes_bords_int_;
276 mes_groupes_faces_.vide();
277 s >> acc;
278 if (acc == "groupes_faces")
279 {
281 s >> acc;
282 }
283 // Tries to read list of periodic boundaries:
284 bords_perio_.clear();
285 if (acc == "bords_perio")
286 {
287 s >> bords_perio_;
288 s >> acc;
289 read_perio = true;
290 }
291 if (acc != "}")
292 Process::exit( "misformatted domain file : One expected a closing bracket } to end. ");
293}
294
295template<class LIST_FRONTIERE>
296void check_frontiere(const LIST_FRONTIERE& list, const char *msg)
297{
298 int n = list.size();
299 if (!is_parallel_object(n))
300 {
301 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
303 }
304 for (int i = 0; i < n; i++)
305 {
306 const Nom& nom = list[i].le_nom();
307 Cerr << " Boundary " << msg << " : " << nom << finl;
308 if (!is_parallel_object(nom))
309 {
310 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
312 }
313 }
314}
315
316template<class LIST_FRONTIERE>
317void check_frontiere_own_ptr(const LIST_FRONTIERE& list, const char *msg)
318{
319 int n = list.size();
320 if (!is_parallel_object(n))
321 {
322 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
324 }
325 for (int i = 0; i < n; i++)
326 {
327 const Nom& nom = list[i]->le_nom();
328 Cerr << " Boundary " << msg << " : " << nom << finl;
329 if (!is_parallel_object(nom))
330 {
331 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
333 }
334 }
335}
336
337
338/*! @brief associate the read objects to the domaine and check that the reading objects are coherent
339 */
340template<typename _SZ_>
342{
343 // remplacer Type_Face::vide_0D par le bon type pour les procs qui n'ont pas de faces de bord:
344 {
345 int i;
346 int n = nb_front_Cl();
347 for (i = 0; i < n; i++)
348 ::corriger_type(frontiere(i).faces(), type_elem());
349 }
350
351 if (mes_faces_bord_.size() == 0 && mes_faces_raccord_.size() == 0 && Process::is_sequential())
352 Cerr << "Warning, the reread domaine " << nom_ << " has no defined boundaries (none boundary or connector)." << finl;
353
354 mes_faces_bord_.associer_domaine(*this);
355 mes_faces_joint_.associer_domaine(*this);
356 mes_faces_raccord_.associer_domaine(*this);
357 mes_bords_int_.associer_domaine(*this);
358 mes_groupes_faces_.associer_domaine(*this);
359 elem_->associer_domaine(*this);
361
362 const trustIdType nb_elem = mp_sum(mes_elems_.dimension(0));
363 Cerr << " Number of elements: " << nb_elem << finl;
364
365 // Verifications sanitaires:
366 // On doit avoir le meme nombre de frontieres et les memes noms sur tous les procs
367 ::check_frontiere(mes_faces_bord_, "(Bord)");
368 ::check_frontiere_own_ptr(mes_faces_raccord_, "(Raccord)");
369 ::check_frontiere(mes_bords_int_, "(Bord_Interne)");
370 ::check_frontiere(mes_groupes_faces_, "(Groupe_Faces)");
371}
372
373/*! @brief Cherche les numeros (indices) des elements contenants les sommets specifies par le parametre "sommets".
374 *
375 * Utilise:
376 * ArrOfInt_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleTab&,ArrOfInt_t&) const
377 *
378 * @param (IntTab& sommets) le tableau des numeros des sommets dont on cherche les elements correspondants
379 * @param (ArrOfInt_t& elem_) le tableau contenant les numeros des elements contenant les sommets specifies
380 * @return (ArrOfInt_t&) le tableau des numeros des sommets dont on cherche les elements correspondants
381 */
382template<typename _SZ_>
384{
385 int i, j, k;
386 const DoubleTab_t& les_coord = sommets_;
387 int sz_sommets = sommets.dimension(0);
388 DoubleTab xg(sz_sommets, Objet_U::dimension);
389 for (i = 0; i < sz_sommets; i++)
390 for (j = 0; j < nb_som_elem(); j++)
391 for (k = 0; k < Objet_U::dimension; k++)
392 xg(i, k) += les_coord(sommets(i, j), k);
393
394 xg /= (double)nb_som_elem();
395 return chercher_elements(xg, elem, reel);
396}
397
398/*! @brief Recherche des elements contenant les points dont les coordonnees sont specifiees.
399 *
400 * @param (DoubleTab& positions) les coordonnees des points dont on veut connaitre l'element correspondant
401 * @param (ArrOfInt_t& elements) le tableau des numeros des elements contenant les points specifies
402 * @return (ArrOfInt_t&) le tableau des numeros des elements contenant les points specifies
403 */
404template<typename _SZ_>
405typename Domaine_32_64<_SZ_>::SmallArrOfTID_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleTab& positions, SmallArrOfTID_t& elements, int reel) const
406{
407 bool set_cache = false;
408 // PL: On devrait faire un appel a chercher_elements(x,y,z,elem) si positions.dimension(0)=1 ...
409 if (!deformable() && positions.dimension(0) > 1)
410 {
411 set_cache = true;
412 if (!deriv_octree_ || !deriv_octree_->construit())
413 {
414 // Vide le cache
415 cached_elements_.reset();
416 cached_positions_.reset();
417 }
418 else
419 {
420 // Recherche dans le cache:
421 for (int i = 0; i < cached_positions_.size(); i++)
422 if (sameDoubleTab(positions, cached_positions_[i]))
423 {
424 int size = cached_positions_[i].dimension(0);
425 if (elements.size_array() != size)
426 elements.resize_tab(size);
427 elements = cached_elements_[i];
428 // elements.ref_array(cached_elements_[i]); // Non Provoque un assert (ex Sondes.data) et en parallele aussi, normal elements est modifie dans les sondes....
429 return elements;
430 }
431 }
432 }
433 const OctreeRoot_t& octree = construit_octree(reel);
434 int sz = positions.dimension(0);
435 const int dim = positions.dimension_int(1);
436 // resize_tab est virtuelle, si c'est un Vect ou un Tab elle appelle le
437 // resize de la classe derivee:
438 elements.resize_tab(sz, RESIZE_OPTIONS::NOCOPY_NOINIT);
439 double y = 0, z = 0;
440 for (int i = 0; i < sz; i++)
441 {
442 double x = positions(i, 0);
443 if (dim > 1)
444 y = positions(i, 1);
445 if (dim > 2)
446 z = positions(i, 2);
447 elements[i] = octree.rang_elem(x, y, z);
448 }
449 if (set_cache)
450 {
451 // Securite car vu sur un calcul FT (cache qui augmente indefiniment, nombre de particules variables...)
452 // if (cached_memory>1e8) // 100Mo/proc
453 if (cached_positions_.size()>100) // Change heuristic cause 100Mo on GPU is tiny !
454 {
455 // Vide le cache
456 Cerr << "Warning, cache flushed in Domaine_32_64<_SZ_>::chercher_elements() cause too much lines used !" << finl;
457 cached_elements_.reset();
458 cached_positions_.reset();
459 cached_memory = 0;
460 }
461 else
462 {
463 // Met en cache
464 cached_positions_.add(positions);
465 cached_elements_.add(elements);
466 // Send cached arrays to device:
467 int last = cached_positions_.size();
468 mapToDevice(cached_positions_[last-1]);
469 mapToDevice(cached_elements_[last-1]);
470 cached_memory += (double)(positions.size_array() * sizeof(double));
471 cached_memory += (double)(elements.size_array() * sizeof(int));
472 if (cached_memory > 1e7) // 10Mo
473 {
474 Cerr << 2 * cached_positions_.size() << " arrays cached in memory for Domaine_32_64<_SZ_>::chercher_elements(...): ";
475 if (cached_memory < 1e6)
476 Cerr << int(cached_memory / 1024) << " KBytes" << finl;
477 else
478 Cerr << int(cached_memory / 1024 / 1024) << " MBytes" << finl;
479 }
480 }
481 }
482 return elements;
483}
484
485/*! @brief Recherche des elements contenant les points dont les coordonnees sont specifiees.
486 *
487 * @param (DoubleVect_t<_SZ_>& positions) les coordonnees du point dont on veut connaitre l'element correspondant
488 * @param (ArrOfInt_t& elements) le tableau des numeros des elements contenant les points specifies
489 * @return (ArrOfInt_t&) le tableau des numeros des elements contenant les points specifies
490 */
491template<typename _SZ_>
492typename Domaine_32_64<_SZ_>::SmallArrOfTID_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleVect& positions, SmallArrOfTID_t& elements, int reel) const
493{
494 int n = positions.size();
495 if (n != dimension)
496 {
497 Cerr << "Domaine_32_64::chercher_elements(const DoubleVect& positions, ArrOfInt& elements, int reel) const -> Coding is made to copy a doublevect(dimesnion) in a DoubleTab(1,dimension)" << finl;
498 Cerr << "But, it comes with a DoubleVect of size " << n << " instead of " << dimension << finl;
499 assert(0);
501 }
502 DoubleTab positions2(1, n);
503 for (int ii = 0; ii < n; ii++)
504 positions2(0, ii) = positions(ii);
505 return chercher_elements(positions2, elements, reel);
506}
507
508
509/*! @brief Renvoie -1 si face n'est pas une face de bord interne Renvoie le numero de la face dupliquee sinon.
510 *
511 * @param (int face) le numero de la face de bord interne a chercher
512 * @return (int) -1 si la face specifiee n'est pas une face de bord interne le numero de la face dupliquee sinon
513 * @throws erreur TRUST (face non trouvee)
514 */
515template<typename _SZ_>
517{
518 if ((face) >= nb_faces_frontiere())
519 return -1;
521 if ((face) < compteur)
522 return -1;
523
524 for (const auto& itr : mes_bords_int_)
525 {
526 const Faces_32_64<_SZ_>& les_faces = itr.faces();
527 int_t nbf = les_faces.nb_faces();
528 if (face < nbf + compteur)
529 {
530 nbf /= 2;
531 if ((face - compteur) < nbf)
532 return face + nbf;
533 else
534 return face - nbf;
535 }
536 compteur += (2 * nbf);
537 }
538
539 Cerr << "TRUST error in Domaine_32_64<_SZ_>::face_bords_interne_conjuguee " << finl;
541 return -1;
542}
543
544/*! @brief Concatene les bords de meme nom et ceci pour: les bords, les bords periodiques, les bords internes et les groupes de faces.
545 */
546template<typename _SZ_>
548{
549 {
550 // Les Bords
551 auto& list = mes_faces_bord_.get_stl_list();
552
553 // first loop over list elements
554 for (auto it = list.begin(); it != list.end(); ++it)
555 {
556 Frontiere_t& front = *it;
557 front.associer_domaine(*this); // Au cas ou le domaine de la frontiere n'est pas la bonne domaine
558 Journal() << "Domaine_32_64<_SZ_>::comprimer() bord : " << front.le_nom() << finl;
559
560 // second loop over list elements, starting from an incremented position
561 for (auto it2 = std::next(it); it2 != list.end(); )
562 {
563 Frontiere_t& front2 = *it2;
564 if (front.le_nom() == front2.le_nom())
565 {
566 Journal() << "On agglomere le bord : " << front.le_nom() << finl;
567 front.add(front2);
568 it2 = list.erase(it2);
569 }
570 else
571 ++it2;
572
573 Journal() << front.le_nom() << " est associee a : " << front.domaine().le_nom() << finl;
574 }
575 }
576 }
577
578 {
579 // Les Bords Internes :
580 auto& list = mes_bords_int_.get_stl_list();
581 for (auto it = list.begin(); it != list.end(); ++it)
582 {
583 Frontiere_t& front = *it;
584 for (auto it2 = std::next(it); it2 != list.end(); )
585 {
586 Frontiere_t& front2 = *it2;
587 if (front.le_nom() == front2.le_nom())
588 {
589 front.add(front2);
590 it2 = list.erase(it2);
591 }
592 else
593 ++it2;
594 }
595 }
596 }
597
598 {
599 // Les Groupes de faces :
600 auto& list = mes_groupes_faces_.get_stl_list();
601 for (auto it = list.begin(); it != list.end(); ++it)
602 {
603 Frontiere_t& front = *it;
604 for (auto it2 = std::next(it); it2 != list.end(); )
605 {
606 Frontiere_t& front2 = *it2;
607 if (front.le_nom() == front2.le_nom())
608 {
609 front.add(front2);
610 it2 = list.erase(it2);
611 }
612 else
613 ++it2;
614 }
615 }
616 }
617
618 {
619 // Les Raccords
620 auto& list = mes_faces_raccord_.get_stl_list();
621 for (auto it = list.begin(); it != list.end(); ++it)
622 {
623 Frontiere_t& front = (*it).valeur();
624 Journal() << "Raccord : " << front.le_nom() << finl;
625 for (auto it2 = std::next(it); it2 != list.end(); )
626 {
627 Frontiere_t& front2 = (*it2).valeur();
628 if (front.le_nom() == front2.le_nom())
629 {
630 front.add(front2);
631 it2 = list.erase(it2);
632 }
633 else
634 ++it2;
635 }
636 }
637 }
638 return 1;
639}
640
641/*! @brief Renvoie le rang de l'element contenant le point dont les coordonnees sont specifiees.
642 *
643 * @param (double x) coordonnee en X
644 * @param (double y) coordonnee en Y
645 * @param (double z) coordonnee en Z
646 * @return (int) le rang de l'element contenant le point dont les coordonnees sont specifiees.
647 */
648template<typename _SZ_>
649typename Domaine_32_64<_SZ_>::int_t Domaine_32_64<_SZ_>::chercher_elements(double x, double y, double z, int reel) const
650{
651
652 const OctreeRoot_t& octree = construit_octree(reel);
653 return octree.rang_elem(x, y, z);
654}
655
656/*! @brief
657 *
658 * @param (DoubleTab& pos)
659 * @param (ArrOfInt_t& som)
660 * @return (ArrOfInt_t&)
661 */
662template<typename _SZ_>
664{
665 const OctreeRoot_t& octree = construit_octree(reel);
666 octree.rang_sommet(pos, som);
667 return som;
668}
669
670/*! @brief
671 *
672 * @param (DoubleTab& pos)
673 * @param (IntTab& aretes_som) la definition des aretes par leurs sommets
674 * @return (ArrOfInt_t& aretes) Liste des aretes trouvees
675 */
676template<typename _SZ_>
678{
679 const OctreeRoot_t& octree = construit_octree(reel);
680 octree.rang_arete(pos, aretes);
681 return aretes;
682}
683
684/*! @brief
685 *
686 * @param (double x) coordonnee en X
687 * @param (double y) coordonnee en Y
688 * @param (double z) coordonnee en Z
689 */
690template<typename _SZ_>
691typename Domaine_32_64<_SZ_>::int_t Domaine_32_64<_SZ_>::chercher_sommets(double x, double y, double z, int reel) const
692{
693 const OctreeRoot_t& octree = construit_octree(reel);
694 return octree.rang_sommet(x, y, z);
695}
696
697/*! Construction du tableau elem_virt_pe_num_ a partir du tableau mes_elems
698* (on se sert des espaces distants et virtuels de mes_elems).
699* Algorithme non optimal en memoire : on duplique mes_elems alors qu'on a
700* besoin que d'un tableau a deux colonnes.
701* Voir Domaine.h : elem_virt_pe_num_
702*/
703template<typename _SZ_>
708
709template<typename _SZ_>
711{
712 IntTab_t tableau_echange(mes_elems_);
713 assert(tableau_echange.dimension(1) >= 2);
714 const int_t n = nb_elem();
715 const int_t n_virt = nb_elem_tot() - n;
716 const int moi = me();
717 for (int_t i = 0; i < n; i++)
718 {
719 tableau_echange(i, 0) = moi;
720 tableau_echange(i, 1) = i;
721 }
722 tableau_echange.echange_espace_virtuel();
723
724 elem_virt_pe_num_cpy.resize(n_virt, 2);
725 for (int_t i = 0; i < n_virt; i++)
726 {
727 elem_virt_pe_num_cpy(i, 0) = tableau_echange(n + i, 0);
728 elem_virt_pe_num_cpy(i, 1) = tableau_echange(n + i, 1);
729 }
730}
731
732
733/*! @brief Calcule le centre de gravite du domaine
734 */
735template<typename _SZ_>
737{
738 c = 0;
739 // Volumes computed cause stored in Domaine_VF and so not available in Domaine...
740 DoubleVect_t volumes;
741 DoubleVect_t inverse_volumes;
742 calculer_volumes(volumes, inverse_volumes);
743 DoubleTab_t xp;
745 double volume = 0;
746 for (int_t i = 0; i < nb_elem(); i++)
747 for (int j = 0; j < dimension; j++)
748 {
749 c[j] += xp(i, j) * volumes(i);
750 volume += volumes(i);
751 }
752 // Cas de Domaine vide:
753 if (volume > 0)
754 c /= volume;
755 cg_moments_ = c;
756 volume_total_ = mp_somme_vect(volumes);
757}
758
759/*! @brief Calcule les volumes des elements du domaine.
760 *
761 * @param (DoubleVect& volumes) le tableau contenant les volumes des elements du domaine
762 */
763template<typename _SZ_>
765{
766 if (!volumes.get_md_vector())
767 creer_tableau_elements(volumes, RESIZE_OPTIONS::NOCOPY_NOINIT);
768 elem_->calculer_volumes(volumes); // Dimensionne et calcule le DoubleVect volumes
769 // Check and fill inverse_volumes
770 if (!inverse_volumes.get_md_vector())
771 creer_tableau_elements(inverse_volumes, RESIZE_OPTIONS::NOCOPY_NOINIT);
772 int_t size = volumes.size_totale();
773 for (int_t i = 0; i < size; i++)
774 {
775 double v = volumes(i);
776 if (v <= 0.)
777 {
778 Cerr << "Volume[" << i << "]=" << v << finl;
779 Cerr << "Several volumes of the mesh are not positive." << finl;
780 Cerr << "Something is wrong in the mesh..." << finl;
782 }
783 inverse_volumes(i) = 1. / v;
784 }
785}
786
787/*! @brief Calcule les centres de gravites des aretes du domaine.
788 *
789 * @param (DoubleTab& xa) le tableau contenant les centres de gravites des aretes du domaine
790 */
791template<typename _SZ_>
793{
794 const DoubleTab_t& coord = sommets_;
795 // Calcule les centres de gravite des aretes reelles seulement
797 for (int_t i = 0; i < nb_aretes(); i++)
798 for (int j = 0; j < dimension; j++)
799 xa(i, j) = 0.5 * (coord(aretes_som_(i, 0), j) + coord(aretes_som_(i, 1), j));
800}
801
802template<typename _SZ_>
803void Domaine_32_64<_SZ_>::rang_elems_sommet(SmallArrOfTID_t& elems, double x, double y, double z) const
804{
805 const OctreeRoot_t& octree = construit_octree();
806 octree.rang_elems_sommet(elems, x, y, z);
807}
808
809template<typename _SZ_>
811{
812 if (deriv_octree_)
813 deriv_octree_.detach();
814}
815
816template<typename _SZ_>
818{
819 if (!deriv_octree_)
820 deriv_octree_.typer("OctreeRoot");
821 OctreeRoot_t& octree = deriv_octree_.valeur();
822 if (!octree.construit())
823 {
824 octree.associer_Domaine(*this);
825 octree.construire();
826 }
827 return octree;
828}
829
830/*! @brief construction de l'octree si pas deja fait
831 */
832template<typename _SZ_>
834{
835 if (!deriv_octree_)
836 deriv_octree_.typer("OctreeRoot");
837 OctreeRoot_t& octree = deriv_octree_.valeur();
838 if (!octree.construit() || (reel != octree.reel()))
839 {
840 octree.associer_Domaine(*this);
841 octree.construire(reel);
842 }
843 return octree;
844}
845
846/*! @brief creation d'un tableau parallele de valeurs aux elements.
847 *
848 * Voir MD_Vector_tools::creer_tableau_distribue()
849 */
850template<typename _SZ_>
852{
853 const MD_Vector& md = md_vector_elements();
855}
856
857/*! @brief renvoie le descripteur parallele des tableaux aux elements du domaine
858 */
859template<typename _SZ_>
861{
862 const MD_Vector& md = mes_elems_.get_md_vector();
863 if (!md)
864 {
865 Cerr << "Internal error in Domaine_32_64<_SZ_>::md_vector_elements(): descriptor for elements not initialized\n"
866 << " You might use a buggy Domain constructor that does not build descriptors,\n"
867 << " Use the following syntax to finish the domain construction\n"
868 << " Scatter ; " << le_nom() << finl;
870 }
871 // Pour l'instant je prends le descripteur dans le tableau mes_elems, mais on
872 // pourrait en stocker une copie dans le domaine si ca a un interet...
873 return md;
874}
875
876template<typename _SZ_>
878{
879 assert(volume_total_ >= 0.); // Pas calcule ???
880 return volume_total_;
881}
882
883template<typename _SZ_>
885{
886 DoubleTab BB(dimension, 2);
887 int_t nbsom=sommets_.dimension(0);
888 for (int j=0; j<dimension; j++)
889 {
890 double min_=0.5*DMAXFLOAT;
891 double max_=-0.5*DMAXFLOAT;
892 for (int_t i=0; i<nbsom; i++)
893 {
894 double c = sommets_(i,j);
895 min_ = (c < min_ ? c : min_);
896 max_ = (c > max_ ? c : max_);
897 }
898 BB(j,0) = min_;
899 BB(j,1) = max_;
900 }
901 return BB;
902}
903
904/*! @brief Ajoute des noeuds (ou sommets) au domaine (sans verifier les doublons)
905 *
906 * @param (DoubleTab& soms) le tableau contenant les coordonnees des noeuds a ajouter au domaine
907 */
908template<typename _SZ_>
910{
911 int_t oldsz=sommets_.dimension(0);
912 int_t ajoutsz=soms.dimension(0);
913 int dim = soms.dimension_int(1);
914 sommets_.resize(oldsz+ajoutsz,dim);
915 for(int_t i=0; i<ajoutsz; i++)
916 for(int k=0; k<dim; k++)
917 sommets_(oldsz+i,k)=soms(i,k) ;
918}
919
920/*! @brief Ajoute des noeuds au domaine avec elimination des noeuds double au retour nums contient les nouveaux numeros des noeuds de soms
921 *
922 * apres elimination des doublons.
923 *
924 * @param (DoubleTab& soms) le tableau contenant les coordonnees des noeuds a ajouter au domaine
925 * @param (IntVect& nums) le tableau des nouveaux numeros apres ajout des nouveaux noeuds et elimination des doublons.
926 * @throws des noeuds double ont ete trouve
927 */
928template<typename _SZ_>
930{
931 int_t oldsz = sommets_.dimension(0);
932 int_t ajoutsz = soms.dimension(0);
933 int dim = soms.dimension_int(1);
934 nums.resize(ajoutsz);
935 nums=-1;
936 if(oldsz!=0)
937 {
938 assert(dim==sommets_.dimension(1));
940 octree.build_nodes(les_sommets(), 0 /* ne pas inclure les sommets virtuels */);
941
942 int compteur=0;
943 ArrOfDouble tab_coord(dim);
944 ArrOfInt_t liste_sommets;
945 for(int_t i=0; i< ajoutsz; i++)
946 {
947 for (int j = 0; j < dim; j++)
948 tab_coord[j] = soms(i,j);
949 octree.search_elements_box(tab_coord, epsilon_, liste_sommets);
950 octree.search_nodes_close_to(tab_coord, les_sommets(), liste_sommets, epsilon_);
951 const int_t nb_sommets_proches = liste_sommets.size_array();
952 if (nb_sommets_proches == 0)
953 {
954 // Aucun sommet du premier domaine n'est proche du sommet i.
955 // Garder i.
956 }
957 else if (nb_sommets_proches == 1)
958 {
959 // Un sommet est confondu avec le sommet i a epsilon_ pres.
960 // Ne pas garder le sommet
961 nums(i) = liste_sommets[0];
962 compteur++;
963 }
964 else
965 {
966 // Plusieurs sommets du domaine initial sont dans un rayon de epsilon.
967 // epsilon est trop grand.
968 Cerr << "Error : several nodes of the domain 1 are within radius epsilon="
969 << epsilon_ << " of point " << tab_coord << ". We must reduce epsilon. " << finl;
971 }
972 }
973 Cerr << compteur << " double nodes were found \n";
974 sommets_.resize(oldsz+ajoutsz-compteur,dim);
975 compteur=0;
976 for(int_t i =0; i<ajoutsz; i++)
977 if(nums(i)==-1)
978 {
979 nums(i)=oldsz+compteur;
980 compteur++;
981 for(int k=0; k<dim; k++)
982 sommets_(nums(i),k)=soms(i,k) ;
983 }
984 }
985 else
986 {
987 sommets_=soms;
988 // if som has a descriptor, delete it:
989 sommets_.set_md_vector(MD_Vector());
990 for(int_t i=0; i<ajoutsz; i++)
991 nums(i)=i;
992 }
993}
994
995/*! @brief Cree un tableau ayant une "ligne" par sommet du maillage.
996 *
997 * Voir MD_Vector_tools::creer_tableau_distribue()
998 */
999template<typename _SZ_>
1001{
1002 const MD_Vector& md = md_vector_sommets();
1004}
1005
1006
1007/*! @brief only read vertices from the stream s
1008 */
1009template<typename _SZ_>
1011{
1012 // Ajout BM: reset de la structure (a pour effet de debloquer la structure parallele)
1013 sommets_.reset();
1014 renum_som_perio_.reset();
1015
1016 Nom tmp;
1017 s >> tmp;
1018 // Si le domaine n'est pas nomme, on prend celui lu
1019 if (nom_=="??") nom_=tmp;
1020 Cerr << "Reading vertices for domain " << le_nom() << finl;
1021 s >> sommets_;
1022}
1023
1024
1025/*! @brief Ecriture des noms des bords sur un flot de sortie
1026 *
1027 * Ecrit les noms des: bords, bords periodiques, raccords et groupes de faces.
1028 *
1029 * @param (Sortie& os) un flot de sortie
1030 */
1031template <typename _SZ_>
1033{
1034 // Les Bords
1035 for (const auto &itr : mes_faces_bord_)
1036 os << itr.le_nom() << finl;
1037
1038 // Les Raccords :
1039 for (const auto &itr : mes_faces_raccord_)
1040 os << itr->le_nom() << finl;
1041
1042 // Les Bords Internes :
1043 for (const auto &itr : mes_bords_int_)
1044 os << itr.le_nom() << finl;
1045
1046 // Les Groupes de faces :
1047 for (const auto &itr : mes_groupes_faces_)
1048 os << itr.le_nom() << finl;
1049}
1050
1051template <typename _SZ_>
1053{
1054 int i = 0;
1055 for (const auto &itr : mes_faces_bord_)
1056 {
1057 if (itr.le_nom() == un_nom)
1058 return i;
1059 ++i;
1060 }
1061
1062 for (const auto &itr : mes_faces_raccord_)
1063 {
1064 if (itr->le_nom() == un_nom)
1065 return i;
1066 ++i;
1067 }
1068
1069 for (const auto &itr : mes_bords_int_)
1070 {
1071 if (itr.le_nom() == un_nom)
1072 return i;
1073 ++i;
1074 }
1075
1076 for (const auto &itr : mes_groupes_faces_)
1077 {
1078 if (itr.le_nom() == un_nom)
1079 return i;
1080 ++i;
1081 }
1082 Cerr << "Domaine_32_64<_SZ_>::rang_frontiere(): We have not found a boundary with name " << un_nom << finl;
1083 Process::exit();
1084 return -1;
1085}
1086
1087template <typename _SZ_>
1089{
1090 int i = rang_frontiere(un_nom);
1091 return frontiere(i);
1092}
1093
1094template <typename _SZ_>
1096{
1097 int i = rang_frontiere(un_nom);
1098 return frontiere(i);
1099}
1100
1101template <typename _SZ_>
1103{
1104 Journal() << "Domaine_32_64<_SZ_>::fixer_premieres_faces_frontiere()" << finl;
1105 int_t compteur = 0;
1106 for (auto &itr : mes_faces_bord_)
1107 {
1108 itr.fixer_num_premiere_face(compteur);
1109 compteur += itr.nb_faces();
1110 Journal() << "Le bord " << itr.le_nom() << " commence a la face : " << itr.num_premiere_face() << finl;
1111 }
1112 for (auto &itr : mes_faces_raccord_)
1113 {
1114 itr->fixer_num_premiere_face(compteur);
1115 compteur += itr->nb_faces();
1116 Journal() << "Le raccord " << itr->le_nom() << " commence a la face : " << itr->num_premiere_face() << finl;
1117 }
1118 if (std::is_same<_SZ_, int>::value)
1119 for (auto &itr : mes_faces_joint_)
1120 {
1121 itr.fixer_num_premiere_face((int)compteur);
1122 compteur += itr.nb_faces();
1123 Journal() << "Le joint " << itr.le_nom() << " commence a la face : " << itr.num_premiere_face() << finl;
1124 }
1125 for (auto &itr : mes_groupes_faces_)
1126 itr.fixer_num_premiere_face(-1);
1127}
1128
1129
1130template<typename _SZ_>
1131template<typename _BORD_TYP_>
1132void Domaine_32_64<_SZ_>::correct_type_single_border_type(std::list<_BORD_TYP_>& list)
1133{
1134 // first loop over list elements
1135 for (auto it = list.begin(); it != list.end(); ++it)
1136 {
1137 Frontiere_t& front = *it;
1138 if (front.faces().type_face() == Type_Face::vide_0D)
1139 {
1140 // second loop over list elements, starting from an incremented position
1141 for (auto it2 = std::next(it); it2 != list.end();)
1142 {
1143 Frontiere_t& front2 = *it2;
1144 if (front.le_nom() == front2.le_nom())
1145 {
1146 front.faces().typer(front2.faces().type_face());
1147 break;
1148 }
1149 else
1150 ++it2;
1151 }
1152 }
1153 }
1154}
1155
1156/*! @brief Correcting type of borders if they were empty before merge (ie equal to vide_0D)
1157 *
1158 * Difference with corriger_type is that we don't want to delete faces inside borders afterwards.
1159 * Int version handles joints, not the 64b one.
1160 */
1161template<typename _SZ_>
1163{
1164 correct_type_single_border_type(mes_faces_bord_.get_stl_list());
1165 correct_type_single_border_type(mes_bords_int_.get_stl_list());
1166 correct_type_single_border_type(mes_faces_raccord_.get_stl_list());
1167 correct_type_single_border_type(mes_groupes_faces_.get_stl_list());
1168}
1169
1170
1171template<>
1173{
1174 correct_type_single_border_type(mes_faces_bord_.get_stl_list());
1175 correct_type_single_border_type(mes_bords_int_.get_stl_list());
1176 correct_type_single_border_type(mes_faces_raccord_.get_stl_list());
1177 correct_type_single_border_type(mes_groupes_faces_.get_stl_list());
1178 // The joints - only for 32b Domaine:
1179 correct_type_single_border_type(mes_faces_joint_.get_stl_list());
1180}
1181
1182
1183template<typename _SZ_>
1185{
1186 Cerr << "==============================================" << finl;
1187 Cerr << "The extreme coordinates of the domain " << le_nom() << " are:" << finl;
1188 // Il n'existe pas de recherche du min et du max dans DoubleTab donc je code:
1189 DoubleTab BB = getBoundingBox();
1190 ArrOfDouble bb_min(dimension), bb_max(dimension);
1191 for (int j=0; j<dimension; j++)
1192 {
1193 bb_min[j] = BB(j,0);
1194 bb_max[j] = BB(j,1);
1195 }
1198 for (int j=0; j<dimension; j++)
1199 {
1200 if (j==0) Cerr << "x ";
1201 if (j==1) Cerr << "y ";
1202 if (j==2) Cerr << "z ";
1203 Cerr << "is between " << bb_min[j] << " and " << bb_max[j] << finl;
1204 }
1205 Cerr << "==============================================" << finl;
1206 // We recompute volumes (cause stored in Domaine_VF and so not available from Domaine...):
1207 DoubleVect_t volumes;
1208 DoubleVect_t inverse_volumes;
1209 calculer_volumes(volumes,inverse_volumes);
1210 Cerr << "==============================================" << finl;
1211 Cerr << "The volume cells of the domain " << le_nom() << " are:" << finl;
1212 const int_t i_vmax = imax_array(volumes);
1213 const int_t i_vmin = imin_array(volumes);
1214 const double vmin_local = (i_vmin < 0) ? 1e40 : volumes[i_vmin];
1215 const double vmax_local = (i_vmax < 0) ? -1e40 : volumes[i_vmax];
1216 const double volmin = mp_min(vmin_local);
1217 const double volmax = mp_max(vmax_local);
1218 double volume_total = mp_somme_vect(volumes);
1219 const int_t nbe = nb_elem();
1220 double volmoy = volume_total / Process::mp_sum_as_double(nbe);
1221 Cerr << "sum(volume cells)= " << volume_total << finl;
1222 Cerr << "mean(volume cells)= " << volmoy << finl;
1223 Cerr << "min(volume cells)= " << volmin << finl;
1224 Cerr << "max(volume cells)= " << volmax << finl;
1225 if (volmin*1000<volmoy)
1226 {
1227 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1228 Cerr << "Warning, a cell volume is more than 1000 times smaller than the average cell volume. Check your mesh." << finl;
1229 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1230 }
1231 Cerr << "==============================================" << finl;
1232}
1233
1234/*! @brief Merge another Domaine into this, without considering vertices which are handled separately
1235 */
1236template<typename _SZ_>
1238{
1239 Cerr << " Merging elem info for domain "<< nom_ << " with " << dom2.nom_ << finl;
1240
1241 // Prepare type if first merge:
1242 if (!elem_)
1243 elem_ = dom2.elem_;
1244
1245 // Prepare correct initial elem size if first merge
1246 if (nb_elem() == 0)
1247 les_elems().resize(0, dom2.les_elems().dimension_int(1));
1248
1249 int_t sz1 = les_elems().dimension(0);
1250 int_t sz2 = dom2.les_elems().dimension(0);
1251 int nb_ccord = les_elems().dimension_int(1);
1252 IntTab_t& elems1 = les_elems();
1253 IntTab_t& elems2 = dom2.les_elems();
1254 elems1.resize(sz1+sz2, nb_ccord);
1255 for(int_t i=0; i<sz2; i++)
1256 for(int j=0; j<nb_ccord; j++)
1257 elems1(sz1+i,j)=elems2(i,j);
1258
1259 dom2.faces_bord().associer_domaine(*this);
1260 faces_bord().add(dom2.faces_bord());
1261
1262 // Take care of the joints only in 32 bits instance when this is called by Scatter
1263 dom2.faces_joint().associer_domaine(*this);
1264 faces_joint().add(dom2.faces_joint());
1265
1266 dom2.faces_raccord().associer_domaine(*this);
1267 faces_raccord().add(dom2.faces_raccord());
1268
1269 dom2.bords_int().associer_domaine(*this);
1270 bords_int().add(dom2.bords_int());
1271
1272 dom2.groupes_faces().associer_domaine(*this);
1273 groupes_faces().add(dom2.groupes_faces());
1274
1275 // Add periodic boundary names if not already there:
1276 auto& bp = bords_perio();
1277 const auto& bp2 = dom2.bords_perio();
1278 for (const auto &b : bp2)
1279 {
1280 if (bp.rang(b) < 0)
1281 bp.add(b);
1282 }
1283
1285 comprimer();
1288}
1289
1290/*! @brief Association d'un Sous_Domaine au Domaine.
1291 *
1292 * L'interface permet de passer n'importe quel
1293 * Objet_U mais ne gere (dynamiquement) que
1294 * l'association d'un objet derivant Sous_Domaine.
1295 *
1296 * @param (Objet_U& ob) l'objet a associer
1297 * @return (int) 1 si l'association a reussie 0 sinon (l'objet n'etait pas derive Sous_Domaine)
1298 */
1299template<typename _SZ_>
1301{
1302 if( sub_type(Sous_Domaine_t, ob))
1303 {
1304 add(ref_cast(Sous_Domaine_t, ob));
1305 ob.associer_(*this);
1306 return 1;
1307 }
1308 return 0;
1309}
1310
1311/*! @brief Initialize the renumerotation array for periodicity
1312 */
1313template<typename _SZ_>
1315{
1316 const int_t nb_s = sommets_.dimension(0);
1317 IntTab_t renum(nb_s);
1318 for (int_t i = 0; i < nb_s; i++)
1319 renum[i] = i;
1321}
1322
1323
1324/*! @brief Build the MEDCoupling mesh corresponding to the TRUST mesh.
1325 */
1326template<typename _SZ_>
1328{
1329#ifdef MEDCOUPLING_
1330 Cerr << "Domaine: Creating a MEDCouplingUMesh object for the domain '" << le_nom() << "'" << finl;
1331
1332 using MEDCoupling::DataArrayInt;
1333 using MEDCoupling::DataArrayDouble;
1334
1335 // Initialize mesh
1336 Nom type_ele = elem_->que_suis_je();
1337 int mesh_dim;
1338 INTERP_KERNEL::NormalizedCellType cell_type = type_geo_trio_to_type_medcoupling(type_ele, mesh_dim);
1339 MCAuto<MEDCouplingUMesh>& mc_mesh = virt ? mc_mesh_virt_ : mc_mesh_;
1340 mc_mesh = MEDCouplingUMesh::New(nom_.getChar(), mesh_dim);
1341
1342 //
1343 // Nodes
1344 //
1345 int_t nnodes = sommets_.dimension(0);
1346 MCAuto<DataArrayDouble> coord(DataArrayDouble::New());
1347 if (nnodes==0)
1348 coord->alloc(0, Objet_U::dimension);
1349 else
1350 // Avoid deep copy of vertices:
1351 coord->useArray(sommets_.addr(), false, MEDCoupling::DeallocType::CPP_DEALLOC, nnodes, Objet_U::dimension);
1352
1353 coord->setInfoOnComponent(0, "x");
1354 coord->setInfoOnComponent(1, "y");
1355 if (Objet_U::dimension == 3) coord->setInfoOnComponent(2, "z");
1356 mc_mesh->setCoords(coord);
1357
1358 //
1359 // Connectivity
1360 //
1361 int_t ncells = virt ? mes_elems_.dimension_tot(0) : mes_elems_.dimension(0);
1362 int nverts = (int)mes_elems_.dimension(1);
1363
1364 // Connectivite TRUST -> MED
1365 IntTab_t les_elems2(mes_elems_);
1366 conn_trust_to_med(les_elems2, type_ele, true);
1367
1368 mc_mesh->allocateCells(ncells);
1369 if (cell_type == INTERP_KERNEL::NORM_POLYHED)
1370 {
1371 // Polyedron is special, see page 10:
1372 // http://trac.lecad.si/vaje/chrome/site/doc8.3.0/extra/Normalisation_pour_le_couplage_de_codes.pdf
1373 const Polyedre_32_64<_SZ_>& poly = ref_cast(Polyedre_32_64<_SZ_>, elem_.valeur());
1374 ArrOfInt_t nodes_glob;
1375 poly.remplir_Nodes_glob(nodes_glob, les_elems2);
1376 const ArrOfInt_t& facesIndex = poly.getFacesIndex();
1377 const ArrOfInt_t& polyhedronIndex = poly.getPolyhedronIndex();
1378 assert(ncells <= polyhedronIndex.size_array() - 1);
1379
1380 for (int_t i = 0; i < ncells; i++)
1381 {
1382 int size = 0;
1383 for (int_t face = polyhedronIndex[i]; face < polyhedronIndex[i + 1]; face++)
1384 size += (int)(facesIndex[face + 1] - facesIndex[face] + 1);
1385 size--; // No -1 at the end of the cell
1386 ArrOfTID cell_def(size); // ArrOfTID whatever the template parameter, since TID == mcIdType.
1387 size = 0;
1388 for (int_t face = polyhedronIndex[i]; face < polyhedronIndex[i + 1]; face++)
1389 {
1390 for (int_t node = facesIndex[face]; node < facesIndex[face + 1]; node++)
1391 cell_def[size++] = nodes_glob[node];
1392 if (size < cell_def.size_array())
1393 // Add -1 to mark the end of a face:
1394 cell_def[size++] = -1;
1395 }
1396 mc_mesh->insertNextCell(cell_type, cell_def.size_array(), cell_def.addr());
1397 }
1398 }
1399 else
1400 {
1401 // Other cells:
1402 if (std::is_same<_SZ_, trustIdType>::value) // 64b version of the Domaine, or TRUST compiled in 32b
1403 {
1404 // We can directly point into les_elems2, types are compatible
1405 for (int_t i = 0; i < ncells; i++)
1406 {
1407 int nvertices = nverts;
1408 // Polygons don't have a constant number of vertices - need to discard -1 values:
1409 for (int j = nverts-1; j >= 0 && les_elems2(i, j) < 0; j--) nvertices--;
1410 // Brutal pointer cast below, just so that the compiler does not complain when instanciating for _SZ_ = int:
1411 mc_mesh->insertNextCell(cell_type, nvertices, (trustIdType *)(les_elems2.addr() + i * nverts));
1412 }
1413 }
1414 else
1415 {
1416 // Need to upcast from int to mcIdType:
1417 for (int_t i = 0; i < ncells; i++)
1418 {
1419 ArrOfTID cell_def(nverts);
1420 int j = 0;
1421 for (; j<nverts && les_elems2(i, j) >= 0; j++)
1422 cell_def[j] = (trustIdType)les_elems2(i, j);
1423 mc_mesh->insertNextCell(cell_type, j, cell_def.addr()); // j is the final numb of vertices
1424 }
1425 }
1426 }
1427 *(virt ? &mc_mesh_virt_ready_ : &mc_mesh_ready_) = true;
1428
1429#endif // MEDCOUPLING_
1430}
1431
1432
1433template<typename _SZ_>
1434void Domaine_32_64<_SZ_>::prepare_rmp_with(const Domaine_32_64& other_domain, bool virt) const
1435{
1436#ifdef MEDCOUPLING_
1437 using namespace MEDCoupling;
1438
1439 // Retrieve mesh upfront to possibly build them if they were not already:
1440 get_mc_mesh();
1441 const MEDCouplingUMesh* oth_msh = other_domain.get_mc_mesh(virt);
1442
1443 Cerr << "Building remapper between " << le_nom() << " (" << (int)mc_mesh_->getSpaceDimension() << "D) mesh with " << (int)mc_mesh_->getNumberOfCells()
1444 << " cells and " << other_domain.le_nom() << " (" << (int)oth_msh->getSpaceDimension() << "D) mesh with "
1445 << (int)oth_msh->getNumberOfCells() << " cells" << finl;
1446 rmps[&other_domain].prepare(oth_msh, mc_mesh_, "P0P0");
1447 Cerr << "remapper prepared with " << rmps.at(&other_domain).getNumberOfColsOfMatrix() << " columns in matrix, with max value = " << rmps.at(&other_domain).getMaxValueInCrudeMatrix() << finl;
1448#else
1449 Process::exit("Domaine_32_64<_SZ_>::prepare_rmp_with should not be called since it requires a TRUST version compiled with MEDCoupling !");
1450#endif
1451}
1452
1453template <typename _SIZE_>
1454void Domaine_32_64<_SIZE_>::prepare_dec_with(const Domaine_32_64& other_domain, MEDCouplingFieldDouble *dist, MEDCouplingFieldDouble *loc) const
1455{
1456#if defined(MEDCOUPLING_) && defined(MPI_)
1457 using namespace MEDCoupling;
1458
1459 Perf_counters::time_point t0 = statistics().start_clock();
1460 Cerr << "Building DEC of nature" << MEDCouplingNatureOfField::GetRepr(dist->getNature())
1461 << "from " << other_domain.le_nom() << " (" << Process::mp_sum(dist->getMesh()->getNumberOfCells())
1462 << " cells) to " << le_nom() << " (" << Process::mp_sum(loc->getMesh()->getNumberOfCells()) << " cells) : ";
1463 std::set<int> pcs;
1464 for (int i=0; i<Process::nproc(); i++) pcs.insert(i);
1465 /* a bit technical */
1466 decs.emplace(std::piecewise_construct,
1467 std::forward_as_tuple(&other_domain, dist->getNature()),
1468 std::forward_as_tuple(pcs, ref_cast(Comm_Group_MPI,PE_Groups::current_group()).get_trio_u_world()));
1469 OverlapDEC& dec = decs.at({ &other_domain, dist->getNature()});
1470 dec.setWorkSharingAlgo(Option_Interpolation::SHARING_ALGO);
1471 dec.attachSourceLocalField(dist);
1472 dec.attachTargetLocalField(loc);
1473 dec.synchronize();
1474
1475 Cerr << statistics().compute_time(t0) << " s" << finl;
1476#else
1477 Process::exit("Domaine::prepare_dec_with() should not be called since it requires a TRUST version compiled with MEDCoupling and MPI!");
1478#endif
1479}
1480
1481#ifdef MEDCOUPLING_
1482
1483template <typename _SIZE_>
1484MEDCoupling::MEDCouplingRemapper* Domaine_32_64<_SIZE_>::get_remapper(const Domaine_32_64& other_domain, bool virt) const
1485{
1486 if (!rmps.count(&other_domain))
1487 prepare_rmp_with(other_domain, virt);
1488 return &rmps.at(&other_domain);
1489}
1490
1491#ifdef MPI_
1492template <typename _SIZE_>
1493MEDCoupling::OverlapDEC* Domaine_32_64<_SIZE_>::get_dec(const Domaine_32_64& other_domain, MEDCouplingFieldDouble *dist, MEDCouplingFieldDouble *loc) const
1494{
1495 if (!decs.count({ &other_domain, dist->getNature() } ))
1496 prepare_dec_with(other_domain, dist, loc);
1497 return &decs.at({ &other_domain, dist->getNature() });
1498}
1499#endif
1500
1501#endif
1502
1503
1504/*! @brief Fills the Domaine from a list of Domaine objects by aggregating them.
1505 *
1506 * See Mailler for example
1507 */
1508template <typename _SIZE_>
1509void Domaine_32_64<_SIZE_>::fill_from_list(std::list<Domaine_32_64*>& lst)
1510{
1511 Cerr << "Filling domain from list of domains in progress... " << finl;
1513 Process::exit("Error in Domaine_32_64<_SIZE_>::fill_from_list() : compression prohibited in parallel mode");
1514 if (lst.size() == 0)
1515 Process::exit("Error in Domaine_32_64<_SIZE_>::fill_from_list() : compression prohibited in parallel mode");
1516
1517 for(auto& elem: lst)
1518 elem->comprimer();
1519
1520#ifndef NDEBUG
1521 Domaine_32_64& fst_dom = *lst.front();
1522 Nom typ_elem = fst_dom.type_elem()->que_suis_je();
1523#endif
1524 for(auto& it: lst)
1525 {
1526 Domaine_32_64& dom2 = *it;
1527 Cerr << " Concatenating Domains "<< nom_ << " and " << dom2.nom_ << finl;;
1528 // Check single geometrical type:
1529 assert(typ_elem == dom2.type_elem()->que_suis_je());
1530 // Handle nodes:
1531 IntVect_t les_nums;
1532 // Copy sommets to this
1533 ajouter(dom2.sommets_, les_nums); // les_nums: out parameter
1534 // Renumber current Domaine to prepare addition of elements
1535 dom2.renum(les_nums);
1536 // Merge elem info:
1538 }
1539
1540 Cerr << "Filling from list - End!" << finl;
1541}
1542
1543/*! @brief Renumerotation des noeuds et des elements presents dans les items communs des joints
1544*
1545* Le noeud de numero k devient le noeud de numero Les_Nums[k] l'element de
1546* numero e devient l'element de numero e+elem_offset
1547*
1548* @param (IntVect& Les_Nums) le vecteur contenant la nouvelle numerotation Nouveau_numero_noeud_i = Les_Nums[Ancien_numero_noeud_i]
1549*/
1550template <typename _SIZE_>
1552{
1553 for (int i_joint = 0; i_joint < nb_joints(); i_joint++)
1554 {
1555 ArrOfInt_t& sommets_communs = mes_faces_joint_[i_joint].set_joint_item(JOINT_ITEM::SOMMET).set_items_communs();
1556 for (int_t index = 0; index < sommets_communs.size_array(); index++)
1557 sommets_communs[index] = Les_Nums[sommets_communs[index]];
1558
1559 ArrOfInt_t& elements_distants = mes_faces_joint_[i_joint].set_joint_item(JOINT_ITEM::ELEMENT).set_items_distants();
1560 elements_distants += elem_offset;
1561 }
1562}
1563
1564/*! @brief Concatene les joints de meme nom
1565 *
1566 */
1567template <typename _SIZE_>
1569{
1570 auto& list = mes_faces_joint_.get_stl_list();
1571 for (auto it = list.begin(); it != list.end(); ++it)
1572 {
1573 Frontiere_t& front = *it;
1574 for (auto it2 = std::next(it); it2 != list.end();)
1575 {
1576 Frontiere_t& front2 = *it2;
1577 if (front.le_nom() == front2.le_nom())
1578 {
1579 front.add(front2);
1580 it2 = list.erase(it2);
1581 }
1582 else
1583 ++it2;
1584 }
1585 }
1586 return 1;
1587}
1588
1589
1590/////////////////////////////////////////////////
1591//// Methods only used in the 32 bits version
1592/////////////////////////////////////////////////
1593
1594namespace // Anonymous namespace - only 32 bits stuff here
1595{
1596
1597/*! @brief Cette methode permet de faire un echange espace virtuel d'un tableau aux aretes sans passer par le descripteur des aretes.
1598 *
1599 * On utilise le tableau elem_aretes et l'echange
1600 * espace virtuel des elements
1601 *
1602 */
1603void echanger_tableau_aretes(const IntTab& elem_aretes, int nb_aretes_reelles, ArrOfInt& tab_aretes)
1604{
1605 const int moi = Process::me();
1606
1607 const int nb_elem = elem_aretes.dimension(0);
1608 const int nb_elem_tot = elem_aretes.dimension_tot(0);
1609 const int nb_aretes_elem = elem_aretes.dimension(1);
1610 int i;
1611
1612 // **********************
1613 // I) Echange pour mettre a jour les items communs
1614 // Algo un peu complique pour mettre a jour les items communs: pour chaque arete reele,
1615 // la valeur de tab_aretes doit etre egale a la valeur initiale de tab_arete donnee par
1616 // le processeur de rang le plus petit parmi ceux qui partagent l'arete (c'est a dire
1617 // les processeurs qui ont un element adjacent a cette arete).
1618
1619 // Tableau permettant de connaitre le processeur proprietaire d'une arete reele
1620 ArrOfInt pe_arete(nb_aretes_reelles);
1621 pe_arete = moi;
1622 // Tableau qui donne, pour chaque element, le processeur proprietaire
1623 IntVect pe_elem(nb_elem_tot);
1624 pe_elem = moi; // initialise avec "moi"
1625 {
1626 pe_elem.set_md_vector(elem_aretes.get_md_vector());
1627 pe_elem.echange_espace_virtuel();
1628 // On range dans pe_arete le numero du plus petit processeur proprietaire des
1629 // elements adjacents a cette arete
1630 // Inutile de parcourir les elements reels, on va trouver pe_elem[i]==moi...
1631 // Si l'arete se trouve sur un processeur de rang inferieur, on lui attribue
1632 for (i = nb_elem; i < nb_elem_tot; i++)
1633 for (int pe = pe_elem[i], j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1634 if (a < nb_aretes_reelles && pe_arete[a] > pe)
1635 pe_arete[a] = pe;
1636 }
1637 // On suppose que l'espace virtuel des elements contient au moins une couche d'elements virtuels
1638 // (tous les voisins des elements reels par des sommets) alors les aretes reelles sont
1639 // echangees (pas encore les aretes virtuelles)
1640 // Dans ce cas, pe_arete est maintenant correctement rempli pour les aretes reelles.
1641
1642 IntTab tmp;
1643 tmp.copy(elem_aretes, RESIZE_OPTIONS::NOCOPY_NOINIT); // copier uniquement la structure
1644
1645 // Copier tab_aretes dans la structure tmp (on sait echanger tmp, pas tab_aretes)
1646 for (i = 0; i < nb_elem; i++)
1647 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1648 tmp(i, j) = tab_aretes[a];
1649
1650 // 2) Echange du tableau
1652
1653 // 3) On reverse dans la partie reelle de tab_aretes les valeurs prises dans tmp:
1654 // pour une arete partagee par plusieurs procs, c'est le proc de rang le plus petit
1655 // qui donne la valeur
1656 // Inutile de parcourir les elements reels, la valeur ne changerait pas
1657 for (i = nb_elem; i < nb_elem_tot; i++)
1658 for (int pe = pe_elem[i], j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1659 if (a < nb_aretes_reelles && pe_arete[a] == pe)
1660 tab_aretes[a] = tmp(i, j);
1661
1662 // tab_aretes contient maintenant des valeurs correctes pour toutes les aretes reeles
1663 // (les items communs sont a jour). On fait encore un echange en passant par tmp pour
1664 // mettre a jour les items virtuels:
1665
1666 // ******************
1667 // II) echange pour mettre a jour l'espace virtuel des aretes
1668
1669 // Copier encore une fois tab_aretes dans la structure tmp
1670 for (i = 0; i < nb_elem; i++)
1671 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1672 tmp(i, j) = tab_aretes[a];
1673
1674 // Echange du tableau
1676 // Recopie de tmp dans tab_aretes
1677 for (i = nb_elem; i < nb_elem_tot; i++)
1678 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1679 tab_aretes[a] = tmp(i, j);
1680}
1681
1682} // end anonymous namespace
1683
1684/*! Selection d'un item unique (sommet, face ...) parmi une liste (item_possible)
1685* afin d'assurer le parallelisme de certains algorithmes
1686* La selection est faite en testant la distance entre les coordonnees (coord_possible)
1687* localisant ces items par rapport aux coordonnes (coord_ref) d'un point de reference.
1688* L'item retenu est celui qui presente la distance minimum par rapport au point de reference.
1689* S'il reste plusieurs items se trouvant a la meme distance du point de reference
1690* alors on repete le test en translatant le point de reference
1691*/
1692template <>
1693int Domaine_32_64<int>::identifie_item_unique(IntList& item_possible, DoubleTab& coord_possible, const DoubleVect& coord_ref)
1694{
1695 int it_selection = -1;
1696 DoubleTab decentre_face(4, Objet_U::dimension);
1697 decentre_face = 0.;
1698 for (int t = 1; t < 4; t++)
1699 for (int dir = 0; dir < Objet_U::dimension; dir++)
1700 if (dir == (t - 1))
1701 decentre_face(t, dir) = 1.;
1702 // decentre_face(0,0:dim)={0,0,0}
1703 // decentre_face(1,0:dim)={1,0,0}
1704 // decentre_face(2,0:dim)={0,1,0}
1705 // decentre_face(3,0:dim)={0,0,1}
1706
1707 //Au premier passage (t=0) pas de translation effectuee
1708 DoubleVect dist;
1709 assert(item_possible.size() != 0);
1710 int t = 0;
1711 while ((item_possible.size() != 1) && (t < 4))
1712 {
1713 double distmin = DMAXFLOAT;
1714 int size_initiale = item_possible.size();
1715 dist.resize(size_initiale);
1716 dist = 0.;
1717
1718 for (int ind_it = 0; ind_it < size_initiale; ind_it++)
1719 {
1720 for (int dir = 0; dir < Objet_U::dimension; dir++)
1721 dist[ind_it] += (coord_possible(ind_it, dir) - (coord_ref(dir) + decentre_face(t, dir))) * (coord_possible(ind_it, dir) - (coord_ref(dir) + decentre_face(t, dir)));
1722 if (dist[ind_it] <= distmin)
1723 distmin = dist[ind_it];
1724 }
1725
1726 int ind_it = 0;
1727 int nb_it_suppr = 0;
1728 while (ind_it < size_initiale)
1729 {
1730 if (!est_egal(dist[ind_it], distmin))
1731 {
1732 int ind_it_suppr = ind_it - nb_it_suppr;
1733 int it_suppr = item_possible[ind_it_suppr];
1734 item_possible.suppr(it_suppr);
1735
1736 int size_actuelle = item_possible.size();
1737 for (int ind = ind_it_suppr; ind < size_actuelle; ind++)
1738 for (int dir = 0; dir < dimension; dir++)
1739 coord_possible(ind, dir) = coord_possible(ind + 1, dir);
1740 coord_possible.resize(size_actuelle, dimension, RESIZE_OPTIONS::COPY_NOINIT);
1741 nb_it_suppr++;
1742 }
1743 ind_it++;
1744 }
1745 t++;
1746 }
1747 if (item_possible.size() == 1)
1748 it_selection = item_possible[0];
1749 else
1750 {
1751 Cerr << "Domaine::identifie_item_unique()" << finl;
1752 Cerr << "An item has not been found among the list." << finl;
1753 Cerr << "Please contact TRUST support." << finl;
1754 Process::exit();
1755 }
1756 return it_selection;
1757}
1758
1759template <typename _SIZE_>
1760int Domaine_32_64<_SIZE_>::identifie_item_unique(IntList& item_possible, DoubleTab& coord_possible, const DoubleVect& coord_ref)
1761{
1762 assert(false);
1763 throw;
1764}
1765
1766/*! @brief Methode appelee par Domaine_VF::discretiser().
1767 *
1768 * Construction du descripteur pour les faces de bord
1769 * Remplissage de ind_faces_virt_bord et des tableaux get_faces_virt() des frontieres
1770 * a partir du descripteur parallele des faces.
1771 * Note B.M.: le fait d'avoir mis les faces dans le Domaine_VF, les aretes dans le Domaine,
1772 * certaines parties des proprietes des faces de bord dans le Domaine_VF et d'autres dans le Domaine
1773 * fait que l'initialisation passe par des chemins un peu tordus... il faudra nettoyer ca.
1774 *
1775 */
1776template <>
1777void Domaine_32_64<int>::init_faces_virt_bord(const MD_Vector& md_vect_faces, MD_Vector& md_vect_faces_front)
1778{
1779 if (Process::is_sequential()) // Much simpler in this case:
1780 {
1781 ind_faces_virt_bord_.resize_array(0);
1783 md_vect_faces_front.copy(mdseq);
1784
1785 // Constructrion des MD_Vector_seq de chaque frontiere:
1786 const int nb_frontieres = nb_front_Cl() + nb_groupes_faces();
1787 for (int i_frontiere = 0; i_frontiere < nb_frontieres; i_frontiere++)
1788 {
1789 Frontiere& front = frontiere(i_frontiere);
1790 IntTab& faces_sommets_frontiere = front.les_sommets_des_faces();
1791 // Certains problemes ont plusieurs objets Domaine_VF attaches a la meme Domaine (rayonnement)
1792 // Si on est deja passe par ici, ne pas refaire le travail:
1793 if (faces_sommets_frontiere.get_md_vector())
1794 continue;
1795 const int nb_faces_front = front.nb_faces();
1796 // Construction d'un descripteur contenant le sous-ensemble des faces de cette frontiere
1797 MD_Vector md_frontiere;
1798 MD_Vector_seq mdseq_front(nb_faces_front);
1799 md_frontiere.copy(mdseq_front);
1800 faces_sommets_frontiere.set_md_vector(md_frontiere);
1801 }
1802
1803 return;
1804 }
1805
1806 // ***************************************
1807 // 1) Construction des structures de tableaux pour toutes les faces de bord
1808 // (faces de 0 a nb_faces_frontiere())
1809 const int nb_faces_fr = nb_faces_frontiere();
1810 // Marquage des faces de bord (-1=>pas une face de bord, 0=>face de bord)
1811 IntVect vect_renum;
1812 MD_Vector_tools::creer_tableau_distribue(md_vect_faces, vect_renum, RESIZE_OPTIONS::NOCOPY_NOINIT);
1813 vect_renum = -1;
1814 for (int i = 0; i < nb_faces_fr; i++)
1815 vect_renum[i] = 0;
1816 vect_renum.echange_espace_virtuel();
1817
1818 // Creation du descripteur pour les faces de bord (par extraction d'un sous ensemble du descripteur
1819 // des faces). On utilise la numerotation par defaut dans l'ordre croissant:
1820 MD_Vector_tools::creer_md_vect_renum_auto(vect_renum, md_vect_faces_front);
1821
1822 // Remplissage du tableau ind_faces_virt_bord. C'est juste la partie virtuelle du tableau renum.
1823 // (la partie reelle est triviale: c'est une numerotation contigue de 0 a nb_faces_frontiere()
1824 const int nb_faces = vect_renum.size();
1825 const int nb_faces_tot = vect_renum.size_totale();
1826 const int nb_faces_virt = nb_faces_tot - nb_faces;
1827 ind_faces_virt_bord_.resize_array(nb_faces_virt, RESIZE_OPTIONS::NOCOPY_NOINIT);
1828 for (int i = 0; i < nb_faces_virt; i++)
1829 ind_faces_virt_bord_[i] = vect_renum[nb_faces + i];
1830
1831 // **************************************
1832 // 2) Construction des structures de tableaux pour chaque frontiere
1833
1834 // Remplissage des tableaux
1835 // frontiere(i).get_faces_virt() pour 0 <= i < nb_front_Cl()
1836 // Ce tableau contient les indices dans la Domaine_VF des faces virtuelles
1837 // qui sont sur la frontiere i.
1838 // Calcul de l'espace virtuel des faces de chaque frontiere
1839
1840 // Nombre de frontieres:
1841 const int nb_frontieres = nb_front_Cl();
1842 int i_frontiere;
1843 // Remplissage des tableaux get_faces_virt():
1844 // et constructrion des MD_Vector de chaque frontiere (associe au tableau des faces)
1845 for (i_frontiere = 0; i_frontiere < nb_frontieres; i_frontiere++)
1846 {
1847 Frontiere& front = frontiere(i_frontiere);
1848 IntTab& faces_sommets_frontiere = front.les_sommets_des_faces();
1849 // Certains problemes ont plusieurs objets Domaine_VF attaches a la meme Domaine (rayonnement)
1850 // Si on est deja passe par ici, ne pas refaire le travail:
1851 if (faces_sommets_frontiere.get_md_vector())
1852 continue;
1853 //les tableaux faces_sommets_frontiere doivent faire la meme largeur sur tous les procs avant echange
1854 int nb_som_faces = Process::mp_max(faces_sommets_frontiere.dimension(1));
1855 if (faces_sommets_frontiere.dimension(1) < nb_som_faces)
1856 {
1857 IntTab fsf_old;
1858 fsf_old = faces_sommets_frontiere;
1859 faces_sommets_frontiere.resize(fsf_old.dimension_tot(0), nb_som_faces);
1860 faces_sommets_frontiere = -1;
1861 for (int i = 0, j; i < fsf_old.dimension_tot(0); i++)
1862 for (j = 0; j < fsf_old.dimension(1); j++)
1863 faces_sommets_frontiere(i, j) = fsf_old(i, j);
1864 }
1865
1866 vect_renum = -1;
1867 const int i_premiere_face = front.num_premiere_face();
1868 const int nb_faces_front = front.nb_faces();
1869 // Marquage des faces de cette frontiere
1870 for (int i = i_premiere_face; i < i_premiere_face + nb_faces_front; i++)
1871 vect_renum[i] = 0;
1872 vect_renum.echange_espace_virtuel();
1873 // Construction d'un descripteur contenant le sous-ensemble des faces de cette frontiere
1874 MD_Vector md_frontiere;
1875 MD_Vector_tools::creer_md_vect_renum_auto(vect_renum, md_frontiere);
1876
1877 // Creation de l'espace virtuel des faces de la frontiere
1878 // (c'est ici qu'on associe le descripteur md_frontiere au tableau des faces)
1879 const MD_Vector& md_sommets = les_sommets().get_md_vector();
1880 Scatter::construire_espace_virtuel_traduction(md_frontiere, /* tableau indexe par des numeros de faces de bord */
1881 md_sommets, /* contenant des indices de sommets du domaine */
1882 faces_sommets_frontiere, /* tableau a traiter */
1883 1 /* erreur fatale: si un sommet est manquant, c'est une erreur */);
1884
1885 // On recupere dans renum l'indice renumerote de chaque face:
1886 // on extrait les indices des faces virtuelles de cette frontiere
1887 ArrOfInt& tab = front.get_faces_virt();
1888 assert(faces_sommets_frontiere.dimension(0) == nb_faces_front);
1889 const int nb_faces_tot_frontiere = faces_sommets_frontiere.dimension_tot(0);
1890 const int nb_faces_virt_frontiere = nb_faces_tot_frontiere - nb_faces_front;
1891 tab.resize_array(nb_faces_virt_frontiere);
1892 const int ndebut = nb_faces; // nombre de faces du Domaine !
1893 const int nfin = nb_faces_tot; // idem !
1894 for (int i = ndebut; i < nfin; i++)
1895 {
1896 const int j = vect_renum[i];
1897 if (j >= 0)
1898 {
1899 assert(j >= nb_faces_front && j < nb_faces_tot_frontiere);
1900 // La face i est virtuelle et sur cette frontiere
1901 tab[j - nb_faces_front] = i;
1902 }
1903 }
1904 }
1905}
1906
1907template <typename _SIZE_>
1908void Domaine_32_64<_SIZE_>::init_faces_virt_bord(const MD_Vector& md_vect_faces, MD_Vector& md_vect_faces_front)
1909{
1910 assert(false);
1911 throw;
1912}
1913
1914/*! Version de creer_aretes compatible avec les polyedres
1915 */
1916template <>
1918{
1919 const IntTab& elem_som = les_elems();
1920 // Nombre d'elements reels:
1921 const int nbelem = elem_som.dimension(0);
1922 // Les elements virtuels sont deja construits:
1923 const int nbelem_tot = elem_som.dimension_tot(0);
1924
1925 aretes_som_.resize(0, 2);
1926 bool is_poly = sub_type(Poly_geom_base, type_elem().valeur());
1927
1928 std::vector<std::vector<int> > v_e_a(nbelem_tot); //liste des aretes de chaque element
1929 int nb_aretes_reelles = 0, i;
1930 int j;
1931 {
1932 // Une liste chainee pour retrouver, pour chaque sommet, la liste des aretes
1933 // attachees a ce sommet. Le tableau est de meme taille que Aretes_som.dimension(0)
1934 // chaine_aretes_sommets[i] contient l'indice de la prochaine arete attachee au
1935 // meme sommet ou -1 si c'est la derniere
1936 ArrOfInt chaine_aretes_sommets;
1937 // Indice de la premiere arete attachee a chaque sommet dans chaine_aretes_sommets
1938 ArrOfInt premiere_arete_som(nb_som_tot());
1939 premiere_arete_som = -1;
1940
1941 std::map<std::array<double, 3>, std::array<int, 2> > aretes_loc; //aretes de l'element considere : aretes_loc[{xa, ya, za}] = { s1, s2}
1942 //l'utilisation d'un map permet de s'assurer que les aretes soient dans le meme ordre sur tous les procs!
1943 for (int i_elem = 0; i_elem < nbelem_tot; aretes_loc.clear(), i_elem++)
1944 {
1945 /* 1. on retrouve les aretes de l'element en iterant sur ses faces */
1946 const Elem_geom_base& elem_g = ref_cast(Elem_geom_base, type_elem().valeur());
1947 IntTab f_e_r;
1948 if (is_poly)
1949 {
1950 const Poly_geom_base& poly_g = ref_cast(Poly_geom_base, type_elem().valeur());
1951 poly_g.get_tab_faces_sommets_locaux(f_e_r, i_elem);
1952 }
1953 else
1954 elem_g.get_tab_faces_sommets_locaux(f_e_r);
1955
1956 for (i = 0; i < f_e_r.dimension(0) && f_e_r(i, 0) >= 0; i++)
1957 for (j = 0; j < f_e_r.dimension(1) && f_e_r(i, j) >= 0; j++)
1958 {
1959 int s1 = elem_som(i_elem, f_e_r(i, j)), s2 = elem_som(i_elem, f_e_r(i, j + 1 < f_e_r.dimension(1) && f_e_r(i, j + 1) >= 0 ? j + 1 : 0));
1960 std::array<double, 3> key;
1961 for (int l = 0; l < 3; l++)
1962 key[l] = (sommets_(s1, l) + sommets_(s2, l)) / 2;
1963 aretes_loc[key] = {{ std::min(s1, s2), std::max(s1, s2) }};
1964 }
1965
1966 for (auto &&kv : aretes_loc)
1967 {
1968 //a-t-on deja vu cette arete ?
1969 int k = premiere_arete_som[kv.second[0]];
1970 while (k >= 0 && (aretes_som_(k, 0) != kv.second[0] || aretes_som_(k, 1) != kv.second[1]))
1971 k = chaine_aretes_sommets[k];
1972 if (k < 0) //on n'a pas encore trouve l'arete -> maj de premiere_arete_som et chaine_arete_sommets
1973 {
1974 // L'arete n'existe pas encore
1975 k = chaine_aretes_sommets.size_array();
1976 assert(k == aretes_som_.dimension(0));
1977 aretes_som_.append_line(kv.second[0], kv.second[1]);
1978 // Insertion de l'arete en tete de la liste chainee
1979 int old_head = premiere_arete_som[kv.second[0]];
1980 // Indice de la nouvelle arete
1981 int new_head = chaine_aretes_sommets.size_array();
1982 chaine_aretes_sommets.append_array(old_head);
1983 premiere_arete_som[kv.second[0]] = new_head;
1984 }
1985 v_e_a[i_elem].push_back(k); //ajout de l'arete a la liste des aretes de l'element
1986 }
1987 if (i_elem == nbelem - 1)
1988 {
1989 // On vient de finir les aretes reelles
1990 nb_aretes_reelles = aretes_som_.dimension(0);
1991 }
1992 }
1993 }
1994 /* remplissage du tableau elem_aretes a l'aide de v_e_a */
1995 int nb_aretes_elem = 0;
1996 for (i = 0; i < nbelem_tot; i++)
1997 nb_aretes_elem = std::max(nb_aretes_elem, (int) v_e_a[i].size());
1998 nb_aretes_elem = mp_max(nb_aretes_elem);
1999 elem_aretes_.resize(0, nb_aretes_elem);
2000 creer_tableau_elements(elem_aretes_, RESIZE_OPTIONS::NOCOPY_NOINIT);
2001 for (i = 0, elem_aretes_ = -1; i < nbelem_tot; i++)
2002 for (j = 0; j < (int) v_e_a[i].size(); j++)
2003 elem_aretes_(i, j) = v_e_a[i][j];
2004
2005 // Ajuste la taille du tableau Aretes_som
2006 const int n_aretes_tot = aretes_som_.dimension(0); // attention, nb_aretes_tot est une methode !
2007 aretes_som_.append_line(-1, -1); // car le resize suivant ne fait quelque chose que si on change de taille
2008 aretes_som_.resize(n_aretes_tot, 2);
2009
2010 Journal() << "Domaine " << le_nom() << " nb_aretes=" << nb_aretes_reelles << " nb_aretes_tot=" << n_aretes_tot << finl;
2011
2012 // Construction du descripteur parallele
2013 {
2014 // Pour chaque arete, indice du processeur proprietaire de l'arete
2015 const int moi = Process::me();
2016 ArrOfInt pe_aretes(n_aretes_tot);
2017 pe_aretes = moi;
2018 echanger_tableau_aretes(elem_aretes_, nb_aretes_reelles, pe_aretes);
2019
2020 // Pour chaque arete, indice de l'arete sur le processeur proprietaire
2021 ArrOfInt indice_aretes_owner;
2022 indice_aretes_owner.resize_array(n_aretes_tot, RESIZE_OPTIONS::NOCOPY_NOINIT);
2023 for (i = 0; i < nb_aretes_reelles; i++)
2024 indice_aretes_owner[i] = i;
2025 echanger_tableau_aretes(elem_aretes_, nb_aretes_reelles, indice_aretes_owner);
2026
2027 // Construction de pe_voisins
2028 ArrOfInt pe_voisins;
2029 for (i = 0; i < n_aretes_tot; i++)
2030 if (pe_aretes[i] != moi)
2031 pe_voisins.append_array(pe_aretes[i]);
2032
2033 ArrOfInt liste_pe;
2034 reverse_send_recv_pe_list(pe_voisins, liste_pe);
2035
2036 // On concatene les deux listes.
2037 for (i = 0; i < liste_pe.size_array(); i++)
2038 pe_voisins.append_array(liste_pe[i]);
2039 array_trier_retirer_doublons(pe_voisins);
2040
2041 int nb_voisins = pe_voisins.size_array();
2042 ArrOfInt indices_pe(nproc());
2043 indices_pe = -1;
2044 for (i = 0; i < nb_voisins; i++)
2045 indices_pe[pe_voisins[i]] = i;
2046
2047 ArrsOfInt aretes_communes_to_recv(nb_voisins);
2048 ArrsOfInt blocs_aretes_virt(nb_voisins);
2049 ArrsOfInt aretes_to_send(nb_voisins);
2050 // Parcours des aretes: recherche des aretes a recevoir d'un autre processeur.
2051 // Aretes reeles (items communs)
2052 for (i = 0; i < nb_aretes_reelles; i++)
2053 {
2054 const int pe = pe_aretes[i];
2055 if (pe != moi)
2056 {
2057 const int indice_pe = indices_pe[pe];
2058 if (indice_pe < 0)
2059 {
2060 Cerr << "Error: indice_pe=" << indice_pe << " shouldn't be negative in Domaine_32_64<_SZ_>::creer_aretes." << finl;
2061 Cerr << "It is a TRUST bug on this mesh with the Pa discretization, contact support." << finl;
2062 Cerr << "You could also try another partitioned mesh to get around this issue." << finl;
2063 Process::exit();
2064 }
2065 // Je recois cette arete d'un autre proc
2066 const int indice_distant = indice_aretes_owner[i];
2067 aretes_to_send[indice_pe].append_array(indice_distant); // indice sur le pe voisin
2068 aretes_communes_to_recv[indice_pe].append_array(i); // indice local de l'arete
2069 }
2070 }
2071// Aretes virtuelles
2072 for (i = nb_aretes_reelles; i < n_aretes_tot; i++)
2073 {
2074 const int pe = pe_aretes[i];
2075 assert(pe < nproc() && pe != moi);
2076 const int indice_pe = indices_pe[pe];
2077 if (indice_pe < 0)
2078 {
2079 Cerr << "Error: indice_pe=" << indice_pe << " shouldn't be negative in Domaine_32_64<_SZ_>::creer_aretes." << finl;
2080 Cerr << "It is a TRUST bug on this mesh with the Pa discretization, contact support." << finl;
2081 Cerr << "You could also try another partitioned mesh to get around this issue." << finl;
2082 Process::exit();
2083 }
2084 const int indice_distant = indice_aretes_owner[i];
2085 aretes_to_send[indice_pe].append_array(indice_distant); // indice sur le pe voisin
2086 MD_Vector_base::append_item_to_blocs(blocs_aretes_virt[indice_pe], i);
2087 }
2088 {
2089 Schema_Comm schema;
2090 schema.set_send_recv_pe_list(pe_voisins, pe_voisins);
2091 schema.begin_comm();
2092 // On empile le tableau aretes_to_send et le nombre d'aretes commune avec ce pe:
2093 for (i = 0; i < nb_voisins; i++)
2094 schema.send_buffer(pe_voisins[i]) << aretes_to_send[i];
2096 // Reception
2097 for (i = 0; i < nb_voisins; i++)
2098 schema.recv_buffer(pe_voisins[i]) >> aretes_to_send[i];
2099 schema.end_comm();
2100 }
2101
2102 MD_Vector md;
2103 // Construit l'objet descripteur
2105 {
2106 MD_Vector_std md_aretes(n_aretes_tot, nb_aretes_reelles, pe_voisins, aretes_to_send, aretes_communes_to_recv, blocs_aretes_virt);
2107 md.copy(md_aretes);
2108 }
2109 else
2110 {
2111 MD_Vector_seq md_aretes(n_aretes_tot);
2112 md.copy(md_aretes);
2113 }
2114 Cerr << "Total number of edges = " << md->get_nb_items_tot() << finl;
2115
2116 // Attache le descripteur au tableau
2117 aretes_som_.set_md_vector(md);
2118 }
2119}
2120
2121template <typename _SIZE_>
2123{
2124 assert(false);
2125 throw;
2126}
2127
2128/*! Creation des domaines frontieres (appele lors de la discretisation)
2129 * Actuellement une liste statique de Domaines ou l'on a besoin pour
2130 * chaque domaine de connaitre le premier element
2131 */
2132template <>
2134{
2135 const Nom expr_elements("1");
2136 const Nom expr_faces("1");
2137 int nb_frontieres = nb_front_Cl();
2138 domaines_frontieres_.vide();
2139
2140 for (int i=0; i<nb_frontieres; i++)
2141 {
2142 // Nom de la frontiere
2143 Noms nom_frontiere(1);
2144 nom_frontiere[0]=frontiere(i).le_nom();
2145 // Nom du domaine surfacique que l'on va construire
2146 Nom nom_domaine_surfacique=le_nom();
2147 nom_domaine_surfacique+="_boundaries_";
2148 nom_domaine_surfacique+=frontiere(i).le_nom();
2149 // Creation
2150 Cerr << "Creating a surface domain named " << nom_domaine_surfacique << " for the boundary " << nom_frontiere[0] << " of the domain " << le_nom() << finl;
2151
2153 if (interp.objet_global_existant(nom_domaine_surfacique))
2154 {
2155 Cerr << "Domain " << nom_domaine_surfacique
2156 << " already exists, writing to this object." << finl;
2157
2158 Domaine& dom_new = ref_cast(Domaine, interprete().objet(nom_domaine_surfacique));
2160 }
2161 else
2162 {
2163 DerObjU ob;
2164 ob.typer("Domaine");
2165 interp.ajouter(nom_domaine_surfacique, ob);
2166 }
2167 Domaine& dom_new = ref_cast(Domaine, interprete().objet(nom_domaine_surfacique));
2168
2169 Extraire_surface::extraire_surface(dom_new,*this,nom_domaine_surfacique,domaine_vf,expr_elements,expr_faces,0,nom_frontiere);
2170 OBS_PTR(Domaine)& ref_dom_new=domaines_frontieres_.add(OBS_PTR(Domaine)());
2171 ref_dom_new=dom_new;
2172 }
2173}
2174
2175template <typename _SIZE_>
2177{
2178 assert(false);
2179 throw;
2180}
2181
2182
2183/*! @brief Renumerotation des noeuds: Le noeud de numero k devient le noeud de numero Les_Nums[k]
2184 *
2185 * @param (IntVect& Les_Nums) le vecteur contenant la nouvelle numerotation Nouveau_numero_noeud_i = Les_Nums[Ancien_numero_noeud_i]
2186 */
2187template <typename _SIZE_>
2189{
2190 int_t dim0 = mes_elems_.dimension(0);
2191 int dim1 = mes_elems_.dimension_int(1);
2192
2193 for (int_t i = 0; i < dim0; i++)
2194 for (int j = 0; j < dim1; j++)
2195 mes_elems_(i, j) = Les_Nums[mes_elems_(i, j)];
2196
2197 for (int i = 0; i < nb_bords(); i++)
2198 mes_faces_bord_(i).renum(Les_Nums);
2199 for (int i = 0; i < nb_joints(); i++)
2200 mes_faces_joint_(i).renum(Les_Nums);
2201 for (int i = 0; i < nb_raccords(); i++)
2202 mes_faces_raccord_(i)->renum(Les_Nums);
2203 for (int i = 0; i < nb_frontieres_internes(); i++)
2204 mes_bords_int_(i).renum(Les_Nums);
2205 for (int i = 0; i < nb_groupes_faces(); i++)
2206 mes_groupes_faces_(i).renum(Les_Nums);
2207}
2208
2209template<>
2211{
2212 // Sanity check - make sure that the periodic BC are put on a periodic boundary
2213 // (the opposite is allowed, eventhough it is probably stupid: a non periodic BC on a periodic boundary)
2214 const int nb_bords = les_cl.size();
2215 const Noms& bords_per = this->bords_perio();
2216 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
2217 {
2218 if (sub_type(Periodique, les_cl[n_bord].valeur()))
2219 {
2220 const Nom& nom_b =les_cl[n_bord]->frontiere_dis().frontiere().le_nom();
2221 if(bords_per.rang(nom_b) < 0)
2222 {
2223 Cerr << "ERROR: you have put a periodic boundary condition on a boundary ('" << nom_b << "') which is not periodic." << finl;
2224 Cerr << "Use the keyword: declarer_bord_perio { domaine " << le_nom() << " bord " << nom_b << " }" << finl;
2225 Cerr << "after the loading of the domain to declare this boundary as being periodic." << finl;
2226 Process::exit();
2227 }
2228 }
2229 }
2230
2232 1 /* Calculer les valeurs pour les sommets virtuels */);
2233}
2234
2235
2236template<typename _SZ_>
2238{
2239 assert(false);
2240 throw;
2241}
2242
2243
2244
2245/////////////////////////////////////////////////
2246//// Template instanciations
2247/////////////////////////////////////////////////
2248
2249template class Domaine_32_64<int>;
2250#if INT_is_64_ == 2
2251template class Domaine_32_64<trustIdType>;
2252#endif
Empty class used as a base for all the arrays.
Definition Array_base.h:41
void associer_domaine(const Domaine_t &)
Associe un domaine a tous les bords de la liste.
Definition Bords.cpp:32
void associer_domaine(const Domaine_t &)
Associe un domaine a tous les objets Bord_Interne de la liste.
: Classe Comm_Group_MPI, derivee de la classe abstraite Comm_Group.
classe Conds_lim Cette classe represente un vecteur de conditions aux limites.
Definition Conds_lim.h:32
classe Domaine_32_64 un Domaine est un maillage compose d'un ensemble d'elements geometriques de meme...
Definition Domaine.h:62
int_t nb_faces_bords_int() const
Definition Domaine.h:174
IntVect_T< _SIZE_ > IntVect_t
Definition Domaine.h:72
void calculer_mon_centre_de_gravite(ArrOfDouble &c)
Calcule le centre de gravite du domaine.
Definition Domaine.cpp:736
double volume_total() const
Definition Domaine.cpp:877
IntTab_t aretes_som_
Definition Domaine.h:394
void construire_elem_virt_pe_num()
Definition Domaine.cpp:704
IntTab_t elem_aretes_
Definition Domaine.h:396
Bords_Internes_t mes_bords_int_
Definition Domaine.h:416
virtual void clear()
Reset the Domaine completely except for its name.
Definition Domaine.cpp:108
ArrOfInt_t renum_som_perio_
Definition Domaine.h:389
void rang_elems_sommet(SmallArrOfTID_t &elems, double x, double y=0, double z=0) const
Definition Domaine.cpp:803
int nb_front_Cl() const
Definition Domaine.h:236
const OWN_PTR(Elem_geom_base_32_64< _SIZE_ >) &type_elem() const
Definition Domaine.h:102
Frontiere_32_64< _SIZE_ > Frontiere_t
Definition Domaine.h:90
virtual const MD_Vector & md_vector_sommets() const
Definition Domaine.h:369
Joints_t mes_faces_joint_
Definition Domaine.h:421
int nb_som_elem() const
Renvoie le nombre de sommets des elements geometriques constituants le domaine.
Definition Domaine.h:474
int_t nb_elem_tot() const
Definition Domaine.h:132
void creer_aretes()
Definition Domaine.cpp:2122
ArrOfDouble cg_moments_
Definition Domaine.h:407
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
SmallArrOfTID_T< _SIZE_ > SmallArrOfTID_t
Definition Domaine.h:74
DoubleTab_T< _SIZE_ > DoubleTab_t
Definition Domaine.h:77
const OctreeRoot_t & construit_octree() const
Definition Domaine.cpp:817
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
creation d'un tableau parallele de valeurs aux elements.
Definition Domaine.cpp:851
void creer_mes_domaines_frontieres(const Domaine_VF &domaine_vf)
Definition Domaine.cpp:2176
SmallArrOfTID_t & chercher_aretes(const DoubleTab &pos, SmallArrOfTID_t &arr, int reel=0) const
Definition Domaine.cpp:677
void calculer_centres_gravite(DoubleTab_t &xp) const
Calcule les centres de gravites des elements du domaine.
Definition Domaine.h:503
int_t nb_faces_frontiere() const
Renvoie le nombre de faces frontiere du domaine (somme des nombres de bords, de raccords et de bords ...
Definition Domaine.h:488
Raccords_t mes_faces_raccord_
Definition Domaine.h:415
Bords_t mes_faces_bord_
Definition Domaine.h:414
static int identifie_item_unique(IntList &item_possible, DoubleTab &coord_possible, const DoubleVect &coord_ref)
Definition Domaine.cpp:1760
virtual void calculer_volumes(DoubleVect_t &volumes, DoubleVect_t &inv_volumes) const
Calcule les volumes des elements du domaine.
Definition Domaine.cpp:764
void init_faces_virt_bord(const MD_Vector &md_vect_faces, MD_Vector &md_vect_faces_bord)
Definition Domaine.cpp:1908
DoubleTab_t & les_sommets()
Definition Domaine.h:113
void set_renum_som_perio(IntTab_t &renum)
Definition Domaine.h:283
int rang_frontiere(const Nom &) const
Definition Domaine.cpp:1052
void fill_from_list(std::list< Domaine_32_64 * > &lst)
Fills the Domaine from a list of Domaine objects by aggregating them.
Definition Domaine.cpp:1509
Entree & readOn_has_perio(Entree &s, bool &has_perio)
Lit les objets constituant un Domaine a partir d'un flot d'entree.
Definition Domaine.cpp:209
Bords_t & faces_bord()
Definition Domaine.h:198
ArrOfInt_T< _SIZE_ > ArrOfInt_t
Definition Domaine.h:71
int associer_(Objet_U &) override
Association d'un Sous_Domaine au Domaine.
Definition Domaine.cpp:1300
const Frontiere_t & frontiere(int i) const
Definition Domaine.h:539
int nb_frontieres_internes() const
Definition Domaine.h:235
ArrOfInt_t ind_faces_virt_bord_
Definition Domaine.h:399
int nb_joints() const
Definition Domaine.h:259
void add(const Sous_Domaine_t &sd)
Definition Domaine.h:294
DoubleTab getBoundingBox() const
Definition Domaine.cpp:884
_SIZE_ int_t
Definition Domaine.h:70
Raccords_t & faces_raccord()
Definition Domaine.h:253
IntTab_t & les_elems()
Definition Domaine.h:129
int_t nb_elem() const
Definition Domaine.h:131
void fixer_premieres_faces_frontiere()
Definition Domaine.cpp:1102
void init_renum_perio()
Initialize the renumerotation array for periodicity.
Definition Domaine.cpp:1314
Sous_Domaine_32_64< _SIZE_ > Sous_Domaine_t
Definition Domaine.h:83
void merge_wo_vertices_with(Domaine_32_64 &z)
Merge another Domaine into this, without considering vertices which are handled separately.
Definition Domaine.cpp:1237
void construire_renum_som_perio(const Conds_lim &, const Domaine_dis_base &)
Definition Domaine.cpp:2237
void renum(const IntVect_t &nums)
Renumerotation des noeuds: Le noeud de numero k devient le noeud de numero Les_Nums[k].
Definition Domaine.cpp:2188
void invalide_octree()
Definition Domaine.cpp:810
void read_former_domaine(Entree &s, bool &read_perio)
read what was (before TRUST 1.9.2) the "domaine" part from the input stream i.e. (roughly) the elemen...
Definition Domaine.cpp:259
Bords_Internes_t & bords_int()
Definition Domaine.h:213
void read_vertices(Entree &s)
only read vertices from the stream s
Definition Domaine.cpp:1010
Groupes_Faces_t mes_groupes_faces_
Definition Domaine.h:418
int nb_bords() const
Definition Domaine.h:192
OctreeRoot_32_64< _SIZE_ > OctreeRoot_t
Definition Domaine.h:82
int_t nb_aretes() const
Renvoie le nombre d'aretes reelles.
Definition Domaine.h:143
Noms bords_perio_
List of periodic boundaries - this is filled by Interprete 'Declarer_bord_perio'.
Definition Domaine.h:425
DoubleTab_t sommets_
Definition Domaine.h:386
SmallArrOfTID_t & chercher_sommets(const DoubleTab &pos, SmallArrOfTID_t &som, int reel=0) const
Definition Domaine.cpp:663
void calculer_centres_gravite_aretes(DoubleTab_t &xa) const
Calcule les centres de gravites des aretes du domaine.
Definition Domaine.cpp:792
void check_domaine()
associate the read objects to the domaine and check that the reading objects are coherent
Definition Domaine.cpp:341
DoubleVect_T< _SIZE_ > DoubleVect_t
Definition Domaine.h:76
IntTab_t elem_virt_pe_num_
Definition Domaine.h:403
void correct_type_of_borders_after_merge()
Correcting type of borders if they were empty before merge (ie equal to vide_0D).
Definition Domaine.cpp:1162
void build_mc_mesh(bool virt=false) const
Build the MEDCoupling mesh corresponding to the TRUST mesh.
Definition Domaine.cpp:1327
void renum_joint_common_items(const IntVect_t &nums, const int_t elem_offset)
Renumerotation des noeuds et des elements presents dans les items communs des joints.
Definition Domaine.cpp:1551
int_t face_bords_interne_conjuguee(int_t face) const
Renvoie -1 si face n'est pas une face de bord interne Renvoie le numero de la face dupliquee sinon.
Definition Domaine.cpp:516
SmallArrOfTID_t & indice_elements(const IntTab &som, SmallArrOfTID_t &elem, int reel=0) const
Cherche les numeros (indices) des elements contenants les sommets specifies par le parametre "sommets...
Definition Domaine.cpp:383
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Cree un tableau ayant une "ligne" par sommet du maillage.
Definition Domaine.cpp:1000
virtual const MD_Vector & md_vector_elements() const
renvoie le descripteur parallele des tableaux aux elements du domaine
Definition Domaine.cpp:860
Joints_t & faces_joint()
Definition Domaine.h:265
IntTab_t mes_elems_
Definition Domaine.h:391
int_t nb_som_tot() const
Definition Domaine.h:123
double coord(int_t i, int j) const
Definition Domaine.h:110
void ajouter(const DoubleTab_t &soms)
Ajoute des noeuds (ou sommets) au domaine (sans verifier les doublons).
Definition Domaine.cpp:909
int nb_groupes_faces() const
Definition Domaine.h:220
void ecrire_noms_bords(Sortie &) const
Ecriture des noms des bords sur un flot de sortie.
Definition Domaine.cpp:1032
Groupes_Faces_t & groupes_faces()
Definition Domaine.h:224
IntTab_T< _SIZE_ > IntTab_t
Definition Domaine.h:73
void imprimer() const
Definition Domaine.cpp:1184
int comprimer()
Concatene les bords de meme nom et ceci pour: les bords, les bords periodiques, les bords internes et...
Definition Domaine.cpp:547
int nb_raccords() const
Definition Domaine.h:247
const Noms & bords_perio() const
Definition Domaine.h:278
int comprimer_joints()
Concatene les joints de meme nom.
Definition Domaine.cpp:1568
class Domaine_VF
Definition Domaine_VF.h:44
Base class for domains description. This class holds all the data shared by all domains and not sensi...
int moments_a_imprimer_
Nom nom_
Domaine name.
bool deformable() const
double volume_total_
Volume total du domaine (somme sur tous les processeurs).
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
classe Domaine_dis_base Cette classe est la base de la hierarchie des domaines discretisees.
Classe Elem_geom_base Cette classe est la classe de base pour la definition d'elements.
virtual int nb_som_face(int=0) const =0
Nb of vertices for one face of the element.
virtual int get_tab_faces_sommets_locaux(IntTab &faces_som_local) const
remplit le tableau faces_som_local(i,j) qui donne pour 0 <= i < nb_faces() et 0 <= j < nb_som_face(i)...
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
static void extraire_surface(Domaine &domaine_surfacique, const Domaine &domaine_volumique, const Nom &nom_domaine_surfacique, const Domaine_VF &domaine_vf, const Nom &expr_elements, const Nom &expr_faces, bool avec_les_bords, const Noms &noms_des_bords)
Classe Faces Faces decrit un ensemble de faces par leur type (point ,segment, triangle ou quadrangle)...
Definition Faces.h:50
void typer(const Motcle &)
Type les faces.
Definition Faces.cpp:390
int_t nb_faces() const
Definition Faces.h:66
const IntTab_t & les_sommets() const
Renvoie le tableau des sommets de toutes les faces.
Definition Faces.h:74
Type_Face type_face() const
Definition Faces.h:65
const ArrOfInt_t & get_faces_virt() const
Definition Frontiere.h:69
const Domaine_t & domaine() const
Renvoie le domaine associe a la frontiere.
int_t num_premiere_face() const
Definition Frontiere.h:67
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
Definition Frontiere.h:49
int_t nb_faces() const
Renvoie le nombre de faces de la frontiere.
Definition Frontiere.h:59
void associer_domaine(const Domaine_t &)
Associe la frontiere au domaine dont elle depend.
Definition Frontiere.cpp:63
IntTab_t & les_sommets_des_faces()
Renvoie les sommets des faces de la frontiere.
void add(const Frontiere_32_64 &)
Ajoute les sommets (et faces) de la frontiere passee en parametre a l'objet (Frontiere_32_64).
void associer_domaine(const Domaine_t &)
Associe un domaine a tous les objets Groupe_Faces de la liste.
Interprete un bloc d'instructions dans le jeu de donnees.
Objet_U & ajouter(const Nom &nom, DerObjU &object_to_add)
Ajoute l'objet ob a la liste des objets de l'interprete, et nomme l'objet avec nom.
static int objet_global_existant(const Nom &nom)
renvoie un drapeau indiquant si un objet de ce nom existe dans inteprete_courant() ou l'un de ses par...
static Interprete_bloc & interprete_courant()
renvoie l'interprete_bloc en train d'etre lu dans le jeu de donnees.
void associer_domaine(const Domaine_t &)
Associe un domaine a tous les joints de la liste.
Definition Joints.cpp:33
virtual int get_nb_items_tot() const
static void append_item_to_blocs(ArrOfInt &blocs, int item)
methode outil pour ajouter un item a un tableau du genre "blocs" contenant des series de blocs.
Dummy parallel descriptor used for sequential computations.
C'est le plus simple des descripteurs, utilise pour les tableaux de valeurs aux sommets,...
static void creer_md_vect_renum_auto(IntVect &flags_renum, MD_Vector &md_vect)
Idem que creer_md_vect_renum() mais cree une numerotation par defaut.
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
transforme v en un tableau parallele ayant la structure md.
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
Definition MD_Vector.h:48
void copy(const MD_Vector_base &)
construction d'un objet MD_Vector par copie d'un objet existant.
Definition MD_Vector.cpp:26
static void nettoie(Domaine_t &)
static int NettoiePasNoeuds
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const Nom & le_nom() const override
Renvoie *this;.
Definition Nom.cpp:563
Un tableau de chaine de caracteres (VECT(Nom)).
Definition Noms.h:26
int rang(const char *const ch) const
Definition Noms.cpp:65
Objet_U * typer(const char *nom_type)
Essaie de creer une instance du type "type".
friend class Entree
Definition Objet_U.h:76
virtual int associer_(Objet_U &)
Associe l'Objet_U a un autre Objet_U Methode virtuelle a surcharger.
Definition Objet_U.cpp:201
const Interprete & interprete() const
Definition Objet_U.cpp:212
static int dimension
Definition Objet_U.h:99
friend class Sortie
Definition Objet_U.h:75
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
static double precision_geom
Definition Objet_U.h:86
Objet_U()
Constructeur par defaut : attribue un numero d'identifiant unique a l'objet (object_id_),...
Definition Objet_U.cpp:55
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
int_t rang_sommet(double x, double y=0, double z=0) const
Definition Octree.cpp:702
int_t rang_elem(double x, double y=0, double z=0) const
Definition Octree.cpp:808
void construire(int reel=0)
Definition Octree.cpp:627
void rang_elems_sommet(SmallArrOfTID_t &, double x, double y=0, double z=0) const
Definition Octree.cpp:1003
int construit() const
Renvoie vrai si le domaine associe a l'octree est non nulle.
Definition Octree.cpp:1032
int reel() const
Definition Octree.h:147
int_t rang_arete(double x, double y=0, double z=0) const
Definition Octree.cpp:760
void associer_Domaine(const Domaine_t &d)
Definition Octree.h:143
: Un octree permettant de chercher dans l'espace des elements ou des points decrits par des coordonne...
static int_t search_nodes_close_to(double x, double y, double z, const DoubleTab_t &coords, ArrOfInt_t &node_list, double epsilon)
Methode hors classe Cherche parmi les sommets de la liste node_list ceux qui sont a une.
void build_nodes(const DoubleTab_t &coords, const bool include_virtual, const double epsilon=0.)
construit un octree contenant les points de coordonnees coords.
int_t search_elements_box(double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, ArrOfInt_t &elements) const
cherche tous les elements ou points ayant potentiellement une intersection non vide avec la boite don...
static const Comm_Group & current_group()
renvoie une reference au groupe de processeurs actif courant
Definition PE_Groups.h:65
std::chrono::time_point< clock > time_point
classe Periodique Cette classe represente une condition aux limites periodique.
Definition Periodique.h:31
int get_tab_faces_sommets_locaux(IntTab &faces_som_local) const override=0
remplit le tableau faces_som_local(i,j) qui donne pour 0 <= i < nb_faces() et 0 <= j < nb_som_face(i)...
Classe Polyedre Cette represente l'element geometrique Polyedre.
Definition Polyedre.h:29
const ArrOfInt_t & getPolyhedronIndex() const
Definition Polyedre.h:69
void remplir_Nodes_glob(ArrOfInt_t &Nodes_glob, const IntTab_t &les_elems) const
Definition Polyedre.cpp:439
const ArrOfInt_t & getFacesIndex() const
Definition Polyedre.h:75
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:196
static double mp_min(double)
Definition Process.cpp:386
static double mp_max(double)
Definition Process.cpp:376
static bool is_parallel()
Definition Process.cpp:110
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 double mp_sum_as_double(int v)
Definition Process.h:99
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 void mp_min_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:199
static bool is_sequential()
Definition Process.cpp:115
void associer_domaine(const Domaine_t &)
Associe un domaine a tous les raccords de la liste.
Definition Raccords.cpp:31
static void renum_som_perio(const Domaine_32_64< int > &dom, ArrOfInt_T< int > &renum_som_perio, bool calculer_espace_virtuel)
static void init_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Create parallel descriptors for the vertex and element arrays of the domain (necessary because Scatte...
Definition Scatter.cpp:2742
static void construire_espace_virtuel_traduction(const MD_Vector &md_indice, const MD_Vector &md_valeur, IntTab &tableau, const int error_is_fatal=1)
Construit la structure items_communs + espaces virtuels d'un tableau contenant des indices d'items ge...
Definition Scatter.cpp:1624
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Definition Scatter.cpp:2757
void echange_taille_et_messages() const
Cette methode lance l'echange de donnees entre tous les processeurs.
Sortie & send_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y entasser des donnees a envoyer.
void end_comm() const
Vide les buffers et libere les ressources: on a fini de lire les donnees recues dans les buffers.
Entree & recv_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y lire les donnees recues.
void begin_comm() const
Reserve les buffers de comm pour une nouvelle communication.
void set_send_recv_pe_list(const ArrOfInt &send_pe_list, const ArrOfInt &recv_pe_list, const int me_to_me=0)
Definit la liste des processeurs a qui on va envoyer et de qui on va recevoir des donnees.
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual void precision(int)
Definition Sortie.cpp:40
virtual void setf(IOS_FORMAT)
Definition Sortie.cpp:34
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
_TYPE_ * addr()
virtual void resize_tab(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void suppr(_TYPE_)
Supprime un element contenu dans la liste.
int size() const
Definition TRUSTList.h:68
void set_md_vector(const MD_Vector &) override
Definition TRUSTTab.tpp:673
int dimension_int(int d) const
Definition TRUSTTab.tpp:152
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:469
_SIZE_ dimension_tot(int) const override
Definition TRUSTTab.tpp:160
void copy(const TRUSTTab &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTTab.tpp:622
_SIZE_ dimension(int d) const
Definition TRUSTTab.tpp:133
_SIZE_ size() const
Definition TRUSTVect.tpp:45
_SIZE_ size_totale() const
Definition TRUSTVect.tpp:61
void resize(_SIZE_, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTVect.tpp:91
virtual const MD_Vector & get_md_vector() const
Definition TRUSTVect.h:123
virtual void echange_espace_virtuel(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")