TrioCFD 1.9.9_beta
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// If there is a proc with a type different from vide_OD, set the face type on all
78// processors to that 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 // Processor min_pe broadcasts its type to all others
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 Writes the Domain to an output stream.
145 *
146 * Writes the name, element type, elements,
147 * boundaries, periodic boundaries, joints,
148 * connections and internal boundaries.
149 *
150 * @param (Sortie& s) an output stream
151 * @return (Sortie&) the modified output stream
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 Reads the objects constituting a Domain from an input stream.
200 *
201 * Once the objects are read they are associated to the domain.
202 *
203 * @param (Entree& s) an input stream
204 * @param (bool& has_perio) set to True if periodic boundaries were read, false otherwise.
205 * @return (Entree&) the modified input stream
206 */
207template<typename _SZ_>
209{
210#ifdef SORT_POUR_DEBOG
211 s.setf(ios::scientific);
212 s.precision(20);
213#endif
214 has_perio = false;
215 // BM addition: reset the structure (this has the effect of unlocking the parallel structure)
216 sommets_.reset();
217 renum_som_perio_.reset();
218 // do not reset the name (already read)
219 // for deformable I don't know...
220
221 Nom tmp;
222 s >> tmp;
223 // If the domain is not yet named, use the name that was read
224 if (nom_=="??") nom_=tmp;
225 Cerr << "Reading domain " << le_nom() << finl;
226 s >> sommets_;
227 // PL : not quite exact the number of nodes displayed, joint nodes are counted multiple times...
228 trustIdType nbsom = mp_sum(sommets_.dimension(0));
229 Cerr << " Number of nodes: " << nbsom << finl;
230
231 // Reading element description (what was fomerly the "domaine" part) - this used to be a list so check for '{ }'
232 Nom acc;
233 s >> acc;
234 assert (acc == "{");
235 read_former_domaine(s, has_perio);
237
239 {
241 nbsom = mp_sum(sommets_.dimension(0));
242 Cerr << " Number of nodes after node-cleanup: " << nbsom << finl;
243 }
244
245 // Initialize the "sequential" descriptors (warning: this blocks the resize of the vertex and element arrays!)
248 return s;
249}
250
251
252/*! @brief read what was (before TRUST 1.9.2) the "domaine" part from the input stream
253 * i.e. (roughly) the element description.
254 *
255 * @param read_perio set to True if periodic boundaries were read in the domain (from TRUST 1.9.8)
256 */
257template<typename _SZ_>
259{
260 Nom dnu, acc;
261 read_perio = false;
262 Cerr << " Reading part of domain " << le_nom() << finl;
263 s >> dnu; // Name of the Domaine, now unused ...
264 s >> elem_;
265 mes_elems_.reset();
266 s >> mes_elems_;
267 mes_faces_bord_.vide();
268 s >> mes_faces_bord_;
269 mes_faces_joint_.vide();
270 s >> mes_faces_joint_;
271 mes_faces_raccord_.vide();
273 mes_bords_int_.vide();
274 s >> mes_bords_int_;
275 mes_groupes_faces_.vide();
276 s >> acc;
277 if (acc == "groupes_faces")
278 {
280 s >> acc;
281 }
282 // Tries to read list of periodic boundaries:
283 bords_perio_.clear();
284 if (acc == "bords_perio")
285 {
286 s >> bords_perio_;
287 s >> acc;
288 read_perio = true;
289 }
290 if (acc != "}")
291 Process::exit( "misformatted domain file : One expected a closing bracket } to end. ");
292}
293
294template<class LIST_FRONTIERE>
295void check_frontiere(const LIST_FRONTIERE& list, const char *msg)
296{
297 int n = list.size();
298 if (!is_parallel_object(n))
299 {
300 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
302 }
303 for (int i = 0; i < n; i++)
304 {
305 const Nom& nom = list[i].le_nom();
306 Cerr << " Boundary " << msg << " : " << nom << finl;
307 if (!is_parallel_object(nom))
308 {
309 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
311 }
312 }
313}
314
315template<class LIST_FRONTIERE>
316void check_frontiere_own_ptr(const LIST_FRONTIERE& list, const char *msg)
317{
318 int n = list.size();
319 if (!is_parallel_object(n))
320 {
321 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
323 }
324 for (int i = 0; i < n; i++)
325 {
326 const Nom& nom = list[i]->le_nom();
327 Cerr << " Boundary " << msg << " : " << nom << finl;
328 if (!is_parallel_object(nom))
329 {
330 Cerr << " Fatal error: processors don't have the same number of boundaries " << msg << finl;
332 }
333 }
334}
335
336
337/*! @brief associate the read objects to the domaine and check that the reading objects are coherent
338 */
339template<typename _SZ_>
341{
342 // replace Type_Face::vide_0D with the correct type for processors that have no boundary faces:
343 {
344 int i;
345 int n = nb_front_Cl();
346 for (i = 0; i < n; i++)
347 ::corriger_type(frontiere(i).faces(), type_elem());
348 }
349
350 if (mes_faces_bord_.size() == 0 && mes_faces_raccord_.size() == 0 && Process::is_sequential())
351 Cerr << "Warning, the reread domaine " << nom_ << " has no defined boundaries (none boundary or connector)." << finl;
352
353 mes_faces_bord_.associer_domaine(*this);
354 mes_faces_joint_.associer_domaine(*this);
355 mes_faces_raccord_.associer_domaine(*this);
356 mes_bords_int_.associer_domaine(*this);
357 mes_groupes_faces_.associer_domaine(*this);
358 elem_->associer_domaine(*this);
360
361 const trustIdType nb_elem = mp_sum(mes_elems_.dimension(0));
362 Cerr << " Number of elements: " << nb_elem << finl;
363
364 // Sanity checks:
365 // All processors must have the same number of boundaries and the same names
366 ::check_frontiere(mes_faces_bord_, "(Bord)");
367 ::check_frontiere_own_ptr(mes_faces_raccord_, "(Raccord)");
368 ::check_frontiere(mes_bords_int_, "(Bord_Interne)");
369 ::check_frontiere(mes_groupes_faces_, "(Groupe_Faces)");
370}
371
372/*! @brief Searches the indices of elements containing the vertices specified by the "sommets" parameter.
373 *
374 * Uses:
375 * ArrOfInt_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleTab&,ArrOfInt_t&) const
376 *
377 * @param (IntTab& sommets) the array of vertex indices whose containing elements are searched
378 * @param (ArrOfInt_t& elem_) the array containing the indices of elements containing the specified vertices
379 * @return (ArrOfInt_t&) the array of vertex indices whose containing elements are searched
380 */
381template<typename _SZ_>
383{
384 int i, j, k;
385 const DoubleTab_t& les_coord = sommets_;
386 int sz_sommets = sommets.dimension(0);
387 DoubleTab xg(sz_sommets, Objet_U::dimension);
388 for (i = 0; i < sz_sommets; i++)
389 for (j = 0; j < nb_som_elem(); j++)
390 for (k = 0; k < Objet_U::dimension; k++)
391 xg(i, k) += les_coord(sommets(i, j), k);
392
393 xg /= (double)nb_som_elem();
394 return chercher_elements(xg, elem, reel);
395}
396
397/*! @brief Searches for the elements containing the points whose coordinates are specified.
398 *
399 * @param (DoubleTab& positions) the coordinates of the points whose containing element is sought
400 * @param (ArrOfInt_t& elements) the array of indices of the elements containing the specified points
401 * @return (ArrOfInt_t&) the array of indices of the elements containing the specified points
402 */
403template<typename _SZ_>
404typename Domaine_32_64<_SZ_>::SmallArrOfTID_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleTab& positions, SmallArrOfTID_t& elements, int reel) const
405{
406 bool set_cache = false;
407 // PL: We should call chercher_elements(x,y,z,elem) if positions.dimension(0)=1 ...
408 if (!deformable() && positions.dimension(0) > 1)
409 {
410 set_cache = true;
411 if (!deriv_octree_ || !deriv_octree_->construit())
412 {
413 // Flush the cache
414 cached_elements_.reset();
415 cached_positions_.reset();
416 }
417 else
418 {
419 // Search in the cache:
420 for (int i = 0; i < cached_positions_.size(); i++)
421 if (sameDoubleTab(positions, cached_positions_[i]))
422 {
423 int size = cached_positions_[i].dimension(0);
424 if (elements.size_array() != size)
425 elements.resize_tab(size);
426 elements = cached_elements_[i];
427 // elements.ref_array(cached_elements_[i]); // No - triggers an assert (ex Sondes.data) and also in parallel, elements is modified in probes....
428 return elements;
429 }
430 }
431 }
432 const OctreeRoot_t& octree = construit_octree(reel);
433 int sz = positions.dimension(0);
434 const int dim = positions.dimension_int(1);
435 // resize_tab is virtual; if it is a Vect or a Tab it calls the resize
436 // method of the derived class:
437 elements.resize_tab(sz, RESIZE_OPTIONS::NOCOPY_NOINIT);
438 double y = 0, z = 0;
439 for (int i = 0; i < sz; i++)
440 {
441 double x = positions(i, 0);
442 if (dim > 1)
443 y = positions(i, 1);
444 if (dim > 2)
445 z = positions(i, 2);
446 elements[i] = octree.rang_elem(x, y, z);
447 }
448 if (set_cache)
449 {
450 // Safety measure: observed on an FT calculation (cache growing indefinitely, variable number of particles...)
451 // if (cached_memory>1e8) // 100Mo/proc
452 if (cached_positions_.size()>100) // Change heuristic cause 100Mo on GPU is tiny !
453 {
454 // Flush the cache
455 Cerr << "Warning, cache flushed in Domaine_32_64<_SZ_>::chercher_elements() cause too much lines used !" << finl;
456 cached_elements_.reset();
457 cached_positions_.reset();
458 cached_memory = 0;
459 }
460 else
461 {
462 // Store in cache
463 cached_positions_.add(positions);
464 cached_elements_.add(elements);
465 // Send cached arrays to device:
466 int last = cached_positions_.size();
467 mapToDevice(cached_positions_[last-1]);
468 mapToDevice(cached_elements_[last-1]);
469 cached_memory += (double)(positions.size_array() * sizeof(double));
470 cached_memory += (double)(elements.size_array() * sizeof(int));
471 if (cached_memory > 1e7) // 10Mo
472 {
473 Cerr << 2 * cached_positions_.size() << " arrays cached in memory for Domaine_32_64<_SZ_>::chercher_elements(...): ";
474 if (cached_memory < 1e6)
475 Cerr << int(cached_memory / 1024) << " KBytes" << finl;
476 else
477 Cerr << int(cached_memory / 1024 / 1024) << " MBytes" << finl;
478 }
479 }
480 }
481 return elements;
482}
483
484/*! @brief Searches for the elements containing the points whose coordinates are specified.
485 *
486 * @param (DoubleVect_t<_SZ_>& positions) the coordinates of the point whose containing element is sought
487 * @param (ArrOfInt_t& elements) the array of indices of the elements containing the specified points
488 * @return (ArrOfInt_t&) the array of indices of the elements containing the specified points
489 */
490template<typename _SZ_>
491typename Domaine_32_64<_SZ_>::SmallArrOfTID_t& Domaine_32_64<_SZ_>::chercher_elements(const DoubleVect& positions, SmallArrOfTID_t& elements, int reel) const
492{
493 int n = positions.size();
494 if (n != dimension)
495 {
496 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;
497 Cerr << "But, it comes with a DoubleVect of size " << n << " instead of " << dimension << finl;
498 assert(0);
500 }
501 DoubleTab positions2(1, n);
502 for (int ii = 0; ii < n; ii++)
503 positions2(0, ii) = positions(ii);
504 return chercher_elements(positions2, elements, reel);
505}
506
507
508/*! @brief Returns -1 if face is not an internal boundary face, or the index of the duplicated face otherwise.
509 *
510 * @param (int face) the index of the internal boundary face to search for
511 * @return (int) -1 if the specified face is not an internal boundary face, or the index of the duplicated face otherwise
512 * @throws TRUST error (face not found)
513 */
514template<typename _SZ_>
516{
517 if ((face) >= nb_faces_frontiere())
518 return -1;
520 if ((face) < compteur)
521 return -1;
522
523 for (const auto& itr : mes_bords_int_)
524 {
525 const Faces_32_64<_SZ_>& les_faces = itr.faces();
526 int_t nbf = les_faces.nb_faces();
527 if (face < nbf + compteur)
528 {
529 nbf /= 2;
530 if ((face - compteur) < nbf)
531 return face + nbf;
532 else
533 return face - nbf;
534 }
535 compteur += (2 * nbf);
536 }
537
538 Cerr << "TRUST error in Domaine_32_64<_SZ_>::face_bords_interne_conjuguee " << finl;
540 return -1;
541}
542
543/*! @brief Merges boundaries with the same name for: boundaries, periodic boundaries, internal boundaries and face groups.
544 */
545template<typename _SZ_>
547{
548 {
549 // Boundaries
550 auto& list = mes_faces_bord_.get_stl_list();
551
552 // first loop over list elements
553 for (auto it = list.begin(); it != list.end(); ++it)
554 {
555 Frontiere_t& front = *it;
556 front.associer_domaine(*this); // In case the boundary's domain is not the correct one
557 Journal() << "Domaine_32_64<_SZ_>::comprimer() bord : " << front.le_nom() << finl;
558
559 // second loop over list elements, starting from an incremented position
560 for (auto it2 = std::next(it); it2 != list.end(); )
561 {
562 Frontiere_t& front2 = *it2;
563 if (front.le_nom() == front2.le_nom())
564 {
565 Journal() << "Merging boundary: " << front.le_nom() << finl;
566 front.add(front2);
567 it2 = list.erase(it2);
568 }
569 else
570 ++it2;
571
572 Journal() << front.le_nom() << " is associated with: " << front.domaine().le_nom() << finl;
573 }
574 }
575 }
576
577 {
578 // Internal boundaries:
579 auto& list = mes_bords_int_.get_stl_list();
580 for (auto it = list.begin(); it != list.end(); ++it)
581 {
582 Frontiere_t& front = *it;
583 for (auto it2 = std::next(it); it2 != list.end(); )
584 {
585 Frontiere_t& front2 = *it2;
586 if (front.le_nom() == front2.le_nom())
587 {
588 front.add(front2);
589 it2 = list.erase(it2);
590 }
591 else
592 ++it2;
593 }
594 }
595 }
596
597 {
598 // Face groups:
599 auto& list = mes_groupes_faces_.get_stl_list();
600 for (auto it = list.begin(); it != list.end(); ++it)
601 {
602 Frontiere_t& front = *it;
603 for (auto it2 = std::next(it); it2 != list.end(); )
604 {
605 Frontiere_t& front2 = *it2;
606 if (front.le_nom() == front2.le_nom())
607 {
608 front.add(front2);
609 it2 = list.erase(it2);
610 }
611 else
612 ++it2;
613 }
614 }
615 }
616
617 {
618 // Connections
619 auto& list = mes_faces_raccord_.get_stl_list();
620 for (auto it = list.begin(); it != list.end(); ++it)
621 {
622 Frontiere_t& front = (*it).valeur();
623 Journal() << "Raccord : " << front.le_nom() << finl;
624 for (auto it2 = std::next(it); it2 != list.end(); )
625 {
626 Frontiere_t& front2 = (*it2).valeur();
627 if (front.le_nom() == front2.le_nom())
628 {
629 front.add(front2);
630 it2 = list.erase(it2);
631 }
632 else
633 ++it2;
634 }
635 }
636 }
637 return 1;
638}
639
640/*! @brief Returns the index of the element containing the point whose coordinates are specified.
641 *
642 * @param (double x) X coordinate
643 * @param (double y) Y coordinate
644 * @param (double z) Z coordinate
645 * @return (int) the index of the element containing the point whose coordinates are specified.
646 */
647template<typename _SZ_>
648typename Domaine_32_64<_SZ_>::int_t Domaine_32_64<_SZ_>::chercher_elements(double x, double y, double z, int reel) const
649{
650
651 const OctreeRoot_t& octree = construit_octree(reel);
652 return octree.rang_elem(x, y, z);
653}
654
655/*! @brief
656 *
657 * @param (DoubleTab& pos)
658 * @param (ArrOfInt_t& som)
659 * @return (ArrOfInt_t&)
660 */
661template<typename _SZ_>
663{
664 const OctreeRoot_t& octree = construit_octree(reel);
665 octree.rang_sommet(pos, som);
666 return som;
667}
668
669/*! @brief
670 *
671 * @param (DoubleTab& pos)
672 * @param (IntTab& aretes_som) the definition of edges by their vertices
673 * @return (ArrOfInt_t& aretes) list of edges found
674 */
675template<typename _SZ_>
677{
678 const OctreeRoot_t& octree = construit_octree(reel);
679 octree.rang_arete(pos, aretes);
680 return aretes;
681}
682
683/*! @brief
684 *
685 * @param (double x) X coordinate
686 * @param (double y) Y coordinate
687 * @param (double z) Z coordinate
688 */
689template<typename _SZ_>
690typename Domaine_32_64<_SZ_>::int_t Domaine_32_64<_SZ_>::chercher_sommets(double x, double y, double z, int reel) const
691{
692 const OctreeRoot_t& octree = construit_octree(reel);
693 return octree.rang_sommet(x, y, z);
694}
695
696/*! Builds the elem_virt_pe_num_ array from the mes_elems array
697* (using the distant and virtual spaces of mes_elems).
698* Non-optimal memory algorithm: mes_elems is duplicated whereas only
699* a two-column array is needed.
700* See Domaine.h: elem_virt_pe_num_
701*/
702template<typename _SZ_>
707
708template<typename _SZ_>
710{
711 IntTab_t tableau_echange(mes_elems_);
712 assert(tableau_echange.dimension(1) >= 2);
713 const int_t n = nb_elem();
714 const int_t n_virt = nb_elem_tot() - n;
715 const int moi = me();
716 for (int_t i = 0; i < n; i++)
717 {
718 tableau_echange(i, 0) = moi;
719 tableau_echange(i, 1) = i;
720 }
721 tableau_echange.echange_espace_virtuel();
722
723 elem_virt_pe_num_cpy.resize(n_virt, 2);
724 for (int_t i = 0; i < n_virt; i++)
725 {
726 elem_virt_pe_num_cpy(i, 0) = tableau_echange(n + i, 0);
727 elem_virt_pe_num_cpy(i, 1) = tableau_echange(n + i, 1);
728 }
729}
730
731
732/*! @brief Computes the center of gravity of the domain
733 */
734template<typename _SZ_>
736{
737 c = 0;
738 // Volumes computed cause stored in Domaine_VF and so not available in Domaine...
739 DoubleVect_t volumes;
740 DoubleVect_t inverse_volumes;
741 calculer_volumes(volumes, inverse_volumes);
742 DoubleTab_t xp;
744 double volume = 0;
745 for (int_t i = 0; i < nb_elem(); i++)
746 for (int j = 0; j < dimension; j++)
747 {
748 c[j] += xp(i, j) * volumes(i);
749 volume += volumes(i);
750 }
751 // Case of an empty Domain:
752 if (volume > 0)
753 c /= volume;
754 cg_moments_ = c;
755 volume_total_ = mp_somme_vect(volumes);
756}
757
758/*! @brief Computes the volumes of the domain elements.
759 *
760 * @param (DoubleVect& volumes) the array containing the volumes of the domain elements
761 */
762template<typename _SZ_>
764{
765 if (!volumes.get_md_vector())
766 creer_tableau_elements(volumes, RESIZE_OPTIONS::NOCOPY_NOINIT);
767 elem_->calculer_volumes(volumes); // Sizes and computes the DoubleVect volumes
768 // Check and fill inverse_volumes
769 if (!inverse_volumes.get_md_vector())
770 creer_tableau_elements(inverse_volumes, RESIZE_OPTIONS::NOCOPY_NOINIT);
771 int_t size = volumes.size_totale();
772 for (int_t i = 0; i < size; i++)
773 {
774 double v = volumes(i);
775 if (v <= 0.)
776 {
777 Cerr << "Volume[" << i << "]=" << v << finl;
778 Cerr << "Several volumes of the mesh are not positive." << finl;
779 Cerr << "Something is wrong in the mesh..." << finl;
781 }
782 inverse_volumes(i) = 1. / v;
783 }
784}
785
786/*! @brief Computes the centers of gravity of the domain edges.
787 *
788 * @param (DoubleTab& xa) the array containing the centers of gravity of the domain edges
789 */
790template<typename _SZ_>
792{
793 const DoubleTab_t& coord = sommets_;
794 // Computes the centers of gravity of real edges only
796 for (int_t i = 0; i < nb_aretes(); i++)
797 for (int j = 0; j < dimension; j++)
798 xa(i, j) = 0.5 * (coord(aretes_som_(i, 0), j) + coord(aretes_som_(i, 1), j));
799}
800
801template<typename _SZ_>
802void Domaine_32_64<_SZ_>::rang_elems_sommet(SmallArrOfTID_t& elems, double x, double y, double z) const
803{
804 const OctreeRoot_t& octree = construit_octree();
805 octree.rang_elems_sommet(elems, x, y, z);
806}
807
808template<typename _SZ_>
810{
811 if (deriv_octree_)
812 deriv_octree_.detach();
813}
814
815template<typename _SZ_>
817{
818 if (!deriv_octree_)
819 deriv_octree_.typer("OctreeRoot");
820 OctreeRoot_t& octree = deriv_octree_.valeur();
821 if (!octree.construit())
822 {
823 octree.associer_Domaine(*this);
824 octree.construire();
825 }
826 return octree;
827}
828
829/*! @brief Build the octree if not already done
830 */
831template<typename _SZ_>
833{
834 if (!deriv_octree_)
835 deriv_octree_.typer("OctreeRoot");
836 OctreeRoot_t& octree = deriv_octree_.valeur();
837 if (!octree.construit() || (reel != octree.reel()))
838 {
839 octree.associer_Domaine(*this);
840 octree.construire(reel);
841 }
842 return octree;
843}
844
845/*! @brief Creates a parallel array of values at elements.
846 *
847 * See MD_Vector_tools::creer_tableau_distribue()
848 */
849template<typename _SZ_>
851{
852 const MD_Vector& md = md_vector_elements();
854}
855
856/*! @brief Returns the parallel descriptor of element arrays of the domain
857 */
858template<typename _SZ_>
860{
861 const MD_Vector& md = mes_elems_.get_md_vector();
862 if (!md)
863 {
864 Cerr << "Internal error in Domaine_32_64<_SZ_>::md_vector_elements(): descriptor for elements not initialized\n"
865 << " You might use a buggy Domain constructor that does not build descriptors,\n"
866 << " Use the following syntax to finish the domain construction\n"
867 << " Scatter ; " << le_nom() << finl;
869 }
870 // For now the descriptor is taken from the mes_elems array, but we could
871 // store a copy in the domain if that would be useful...
872 return md;
873}
874
875template<typename _SZ_>
877{
878 assert(volume_total_ >= 0.); // Not computed yet ???
879 return volume_total_;
880}
881
882template<typename _SZ_>
884{
885 DoubleTab BB(dimension, 2);
886 int_t nbsom=sommets_.dimension(0);
887 for (int j=0; j<dimension; j++)
888 {
889 double min_=0.5*DMAXFLOAT;
890 double max_=-0.5*DMAXFLOAT;
891 for (int_t i=0; i<nbsom; i++)
892 {
893 double c = sommets_(i,j);
894 min_ = (c < min_ ? c : min_);
895 max_ = (c > max_ ? c : max_);
896 }
897 BB(j,0) = min_;
898 BB(j,1) = max_;
899 }
900 return BB;
901}
902
903/*! @brief Adds nodes (or vertices) to the domain (without checking for duplicates)
904 *
905 * @param (DoubleTab& soms) the array containing the coordinates of the nodes to add to the domain
906 */
907template<typename _SZ_>
909{
910 int_t oldsz=sommets_.dimension(0);
911 int_t ajoutsz=soms.dimension(0);
912 int dim = soms.dimension_int(1);
913 sommets_.resize(oldsz+ajoutsz,dim);
914 for(int_t i=0; i<ajoutsz; i++)
915 for(int k=0; k<dim; k++)
916 sommets_(oldsz+i,k)=soms(i,k) ;
917}
918
919/*! @brief Adds nodes to the domain with elimination of duplicate nodes. On return, nums contains the new indices of the nodes from soms
920 *
921 * after elimination of duplicates.
922 *
923 * @param (DoubleTab& soms) the array containing the coordinates of the nodes to add to the domain
924 * @param (IntVect& nums) the array of new indices after adding new nodes and eliminating duplicates.
925 * @throws duplicate nodes were found
926 */
927template<typename _SZ_>
929{
930 int_t oldsz = sommets_.dimension(0);
931 int_t ajoutsz = soms.dimension(0);
932 int dim = soms.dimension_int(1);
933 nums.resize(ajoutsz);
934 nums=-1;
935 if(oldsz!=0)
936 {
937 assert(dim==sommets_.dimension(1));
939 octree.build_nodes(les_sommets(), 0 /* do not include virtual vertices */);
940
941 int compteur=0;
942 ArrOfDouble tab_coord(dim);
943 ArrOfInt_t liste_sommets;
944 for(int_t i=0; i< ajoutsz; i++)
945 {
946 for (int j = 0; j < dim; j++)
947 tab_coord[j] = soms(i,j);
948 octree.search_elements_box(tab_coord, epsilon_, liste_sommets);
949 octree.search_nodes_close_to(tab_coord, les_sommets(), liste_sommets, epsilon_);
950 const int_t nb_sommets_proches = liste_sommets.size_array();
951 if (nb_sommets_proches == 0)
952 {
953 // No vertex of the first domain is close to vertex i.
954 // Keep i.
955 }
956 else if (nb_sommets_proches == 1)
957 {
958 // One vertex coincides with vertex i within epsilon_.
959 // Do not keep the vertex
960 nums(i) = liste_sommets[0];
961 compteur++;
962 }
963 else
964 {
965 // Several vertices of the initial domain are within radius epsilon.
966 // epsilon is too large.
967 Cerr << "Error : several nodes of the domain 1 are within radius epsilon="
968 << epsilon_ << " of point " << tab_coord << ". We must reduce epsilon. " << finl;
970 }
971 }
972 Cerr << compteur << " double nodes were found \n";
973 sommets_.resize(oldsz+ajoutsz-compteur,dim);
974 compteur=0;
975 for(int_t i =0; i<ajoutsz; i++)
976 if(nums(i)==-1)
977 {
978 nums(i)=oldsz+compteur;
979 compteur++;
980 for(int k=0; k<dim; k++)
981 sommets_(nums(i),k)=soms(i,k) ;
982 }
983 }
984 else
985 {
986 sommets_=soms;
987 // if som has a descriptor, delete it:
988 sommets_.set_md_vector(MD_Vector());
989 for(int_t i=0; i<ajoutsz; i++)
990 nums(i)=i;
991 }
992}
993
994/*! @brief Creates an array with one "row" per mesh vertex.
995 *
996 * See MD_Vector_tools::creer_tableau_distribue()
997 */
998template<typename _SZ_>
1000{
1001 const MD_Vector& md = md_vector_sommets();
1003}
1004
1005
1006/*! @brief only read vertices from the stream s
1007 */
1008template<typename _SZ_>
1010{
1011 // BM addition: reset the structure (this has the effect of unlocking the parallel structure)
1012 sommets_.reset();
1013 renum_som_perio_.reset();
1014
1015 Nom tmp;
1016 s >> tmp;
1017 // If the domain is not yet named, use the name that was read
1018 if (nom_=="??") nom_=tmp;
1019 Cerr << "Reading vertices for domain " << le_nom() << finl;
1020 s >> sommets_;
1021}
1022
1023
1024/*! @brief Writes the boundary names to an output stream.
1025 *
1026 * Writes the names of: boundaries, periodic boundaries, connections and face groups.
1027 *
1028 * @param (Sortie& os) an output stream
1029 */
1030template <typename _SZ_>
1032{
1033 // Boundaries
1034 for (const auto &itr : mes_faces_bord_)
1035 os << itr.le_nom() << finl;
1036
1037 // Connections:
1038 for (const auto &itr : mes_faces_raccord_)
1039 os << itr->le_nom() << finl;
1040
1041 // Internal boundaries:
1042 for (const auto &itr : mes_bords_int_)
1043 os << itr.le_nom() << finl;
1044
1045 // Face groups:
1046 for (const auto &itr : mes_groupes_faces_)
1047 os << itr.le_nom() << finl;
1048}
1049
1050template <typename _SZ_>
1052{
1053 int i = 0;
1054 for (const auto &itr : mes_faces_bord_)
1055 {
1056 if (itr.le_nom() == un_nom)
1057 return i;
1058 ++i;
1059 }
1060
1061 for (const auto &itr : mes_faces_raccord_)
1062 {
1063 if (itr->le_nom() == un_nom)
1064 return i;
1065 ++i;
1066 }
1067
1068 for (const auto &itr : mes_bords_int_)
1069 {
1070 if (itr.le_nom() == un_nom)
1071 return i;
1072 ++i;
1073 }
1074
1075 for (const auto &itr : mes_groupes_faces_)
1076 {
1077 if (itr.le_nom() == un_nom)
1078 return i;
1079 ++i;
1080 }
1081 Cerr << "Domaine_32_64<_SZ_>::rang_frontiere(): We have not found a boundary with name " << un_nom << finl;
1082 Process::exit();
1083 return -1;
1084}
1085
1086template <typename _SZ_>
1088{
1089 int i = rang_frontiere(un_nom);
1090 return frontiere(i);
1091}
1092
1093template <typename _SZ_>
1095{
1096 int i = rang_frontiere(un_nom);
1097 return frontiere(i);
1098}
1099
1100template <typename _SZ_>
1102{
1103 Journal() << "Domaine_32_64<_SZ_>::fixer_premieres_faces_frontiere()" << finl;
1104 int_t compteur = 0;
1105 for (auto &itr : mes_faces_bord_)
1106 {
1107 itr.fixer_num_premiere_face(compteur);
1108 compteur += itr.nb_faces();
1109 Journal() << "Boundary " << itr.le_nom() << " starts at face: " << itr.num_premiere_face() << finl;
1110 }
1111 for (auto &itr : mes_faces_raccord_)
1112 {
1113 itr->fixer_num_premiere_face(compteur);
1114 compteur += itr->nb_faces();
1115 Journal() << "Connection " << itr->le_nom() << " starts at face: " << itr->num_premiere_face() << finl;
1116 }
1117 if (std::is_same<_SZ_, int>::value)
1118 for (auto &itr : mes_faces_joint_)
1119 {
1120 itr.fixer_num_premiere_face((int)compteur);
1121 compteur += itr.nb_faces();
1122 Journal() << "Joint " << itr.le_nom() << " starts at face: " << itr.num_premiere_face() << finl;
1123 }
1124 for (auto &itr : mes_groupes_faces_)
1125 itr.fixer_num_premiere_face(-1);
1126}
1127
1128
1129template<typename _SZ_>
1130template<typename _BORD_TYP_>
1131void Domaine_32_64<_SZ_>::correct_type_single_border_type(std::list<_BORD_TYP_>& list)
1132{
1133 // first loop over list elements
1134 for (auto it = list.begin(); it != list.end(); ++it)
1135 {
1136 Frontiere_t& front = *it;
1137 if (front.faces().type_face() == Type_Face::vide_0D)
1138 {
1139 // second loop over list elements, starting from an incremented position
1140 for (auto it2 = std::next(it); it2 != list.end();)
1141 {
1142 Frontiere_t& front2 = *it2;
1143 if (front.le_nom() == front2.le_nom())
1144 {
1145 front.faces().typer(front2.faces().type_face());
1146 break;
1147 }
1148 else
1149 ++it2;
1150 }
1151 }
1152 }
1153}
1154
1155/*! @brief Correcting type of borders if they were empty before merge (ie equal to vide_0D)
1156 *
1157 * Difference with corriger_type is that we don't want to delete faces inside borders afterwards.
1158 * Int version handles joints, not the 64b one.
1159 */
1160template<typename _SZ_>
1162{
1163 correct_type_single_border_type(mes_faces_bord_.get_stl_list());
1164 correct_type_single_border_type(mes_bords_int_.get_stl_list());
1165 correct_type_single_border_type(mes_faces_raccord_.get_stl_list());
1166 correct_type_single_border_type(mes_groupes_faces_.get_stl_list());
1167}
1168
1169
1170template<>
1172{
1173 correct_type_single_border_type(mes_faces_bord_.get_stl_list());
1174 correct_type_single_border_type(mes_bords_int_.get_stl_list());
1175 correct_type_single_border_type(mes_faces_raccord_.get_stl_list());
1176 correct_type_single_border_type(mes_groupes_faces_.get_stl_list());
1177 // The joints - only for 32b Domaine:
1178 correct_type_single_border_type(mes_faces_joint_.get_stl_list());
1179}
1180
1181
1182template<typename _SZ_>
1184{
1185 Cerr << "==============================================" << finl;
1186 Cerr << "The extreme coordinates of the domain " << le_nom() << " are:" << finl;
1187 // There is no min/max search method in DoubleTab so it is coded here:
1188 DoubleTab BB = getBoundingBox();
1189 ArrOfDouble bb_min(dimension), bb_max(dimension);
1190 for (int j=0; j<dimension; j++)
1191 {
1192 bb_min[j] = BB(j,0);
1193 bb_max[j] = BB(j,1);
1194 }
1197 for (int j=0; j<dimension; j++)
1198 {
1199 if (j==0) Cerr << "x ";
1200 if (j==1) Cerr << "y ";
1201 if (j==2) Cerr << "z ";
1202 Cerr << "is between " << bb_min[j] << " and " << bb_max[j] << finl;
1203 }
1204 Cerr << "==============================================" << finl;
1205 // We recompute volumes (cause stored in Domaine_VF and so not available from Domaine...):
1206 DoubleVect_t volumes;
1207 DoubleVect_t inverse_volumes;
1208 calculer_volumes(volumes,inverse_volumes);
1209 Cerr << "==============================================" << finl;
1210 Cerr << "The volume cells of the domain " << le_nom() << " are:" << finl;
1211 const int_t i_vmax = imax_array(volumes);
1212 const int_t i_vmin = imin_array(volumes);
1213 const double vmin_local = (i_vmin < 0) ? 1e40 : volumes[i_vmin];
1214 const double vmax_local = (i_vmax < 0) ? -1e40 : volumes[i_vmax];
1215 const double volmin = mp_min(vmin_local);
1216 const double volmax = mp_max(vmax_local);
1217 double volume_total = mp_somme_vect(volumes);
1218 const int_t nbe = nb_elem();
1219 double volmoy = volume_total / Process::mp_sum_as_double(nbe);
1220 Cerr << "sum(volume cells)= " << volume_total << finl;
1221 Cerr << "mean(volume cells)= " << volmoy << finl;
1222 Cerr << "min(volume cells)= " << volmin << finl;
1223 Cerr << "max(volume cells)= " << volmax << finl;
1224 if (volmin*1000<volmoy)
1225 {
1226 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1227 Cerr << "Warning, a cell volume is more than 1000 times smaller than the average cell volume. Check your mesh." << finl;
1228 Cerr << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << finl;
1229 }
1230 Cerr << "==============================================" << finl;
1231}
1232
1233/*! @brief Merge another Domaine into this, without considering vertices which are handled separately
1234 */
1235template<typename _SZ_>
1237{
1238 Cerr << " Merging elem info for domain "<< nom_ << " with " << dom2.nom_ << finl;
1239
1240 // Prepare type if first merge:
1241 if (!elem_)
1242 elem_ = dom2.elem_;
1243
1244 // Prepare correct initial elem size if first merge
1245 if (nb_elem() == 0)
1246 les_elems().resize(0, dom2.les_elems().dimension_int(1));
1247
1248 int_t sz1 = les_elems().dimension(0);
1249 int_t sz2 = dom2.les_elems().dimension(0);
1250 int nb_ccord = les_elems().dimension_int(1);
1251 IntTab_t& elems1 = les_elems();
1252 IntTab_t& elems2 = dom2.les_elems();
1253 elems1.resize(sz1+sz2, nb_ccord);
1254 for(int_t i=0; i<sz2; i++)
1255 for(int j=0; j<nb_ccord; j++)
1256 elems1(sz1+i,j)=elems2(i,j);
1257
1258 dom2.faces_bord().associer_domaine(*this);
1259 faces_bord().add(dom2.faces_bord());
1260
1261 // Take care of the joints only in 32 bits instance when this is called by Scatter
1262 dom2.faces_joint().associer_domaine(*this);
1263 faces_joint().add(dom2.faces_joint());
1264
1265 dom2.faces_raccord().associer_domaine(*this);
1266 faces_raccord().add(dom2.faces_raccord());
1267
1268 dom2.bords_int().associer_domaine(*this);
1269 bords_int().add(dom2.bords_int());
1270
1271 dom2.groupes_faces().associer_domaine(*this);
1272 groupes_faces().add(dom2.groupes_faces());
1273
1274 // Add periodic boundary names if not already there:
1275 auto& bp = bords_perio();
1276 const auto& bp2 = dom2.bords_perio();
1277 for (const auto &b : bp2)
1278 {
1279 if (bp.rang(b) < 0)
1280 bp.add(b);
1281 }
1282
1284 comprimer();
1287}
1288
1289/*! @brief Associates a Sous_Domaine to the Domain.
1290 *
1291 * The interface accepts any Objet_U but only handles (dynamically) the
1292 * association of an object derived from Sous_Domaine.
1293 *
1294 * @param (Objet_U& ob) the object to associate
1295 * @return (int) 1 if the association succeeded, 0 otherwise (the object was not derived from Sous_Domaine)
1296 */
1297template<typename _SZ_>
1299{
1300 if( sub_type(Sous_Domaine_t, ob))
1301 {
1302 add(ref_cast(Sous_Domaine_t, ob));
1303 ob.associer_(*this);
1304 return 1;
1305 }
1306 return 0;
1307}
1308
1309/*! @brief Initialize the renumerotation array for periodicity
1310 */
1311template<typename _SZ_>
1313{
1314 const int_t nb_s = sommets_.dimension(0);
1315 IntTab_t renum(nb_s);
1316 for (int_t i = 0; i < nb_s; i++)
1317 renum[i] = i;
1319}
1320
1321
1322/*! @brief Build the MEDCoupling mesh corresponding to the TRUST mesh.
1323 */
1324template<typename _SZ_>
1326{
1327#ifdef MEDCOUPLING_
1328 Cerr << "Domaine: Creating a MEDCouplingUMesh object for the domain '" << le_nom() << "'" << finl;
1329
1330 using MEDCoupling::DataArrayInt;
1331 using MEDCoupling::DataArrayDouble;
1332
1333 // Initialize mesh
1334 Nom type_ele = elem_->que_suis_je();
1335 int mesh_dim;
1336 INTERP_KERNEL::NormalizedCellType cell_type = type_geo_trio_to_type_medcoupling(type_ele, mesh_dim);
1337 MCAuto<MEDCouplingUMesh>& mc_mesh = virt ? mc_mesh_virt_ : mc_mesh_;
1338 mc_mesh = MEDCouplingUMesh::New(nom_.getChar(), mesh_dim);
1339
1340 //
1341 // Nodes
1342 //
1343 int_t nnodes = sommets_.dimension(0);
1344 MCAuto<DataArrayDouble> coord(DataArrayDouble::New());
1345 if (nnodes==0)
1346 coord->alloc(0, Objet_U::dimension);
1347 else
1348 // Avoid deep copy of vertices:
1349 coord->useArray(sommets_.addr(), false, MEDCoupling::DeallocType::CPP_DEALLOC, nnodes, Objet_U::dimension);
1350
1351 coord->setInfoOnComponent(0, "x");
1352 coord->setInfoOnComponent(1, "y");
1353 if (Objet_U::dimension == 3) coord->setInfoOnComponent(2, "z");
1354 mc_mesh->setCoords(coord);
1355
1356 //
1357 // Connectivity
1358 //
1359 int_t ncells = virt ? mes_elems_.dimension_tot(0) : mes_elems_.dimension(0);
1360 int nverts = (int)mes_elems_.dimension(1);
1361
1362 // TRUST -> MED connectivity
1363 IntTab_t les_elems2(mes_elems_);
1364 conn_trust_to_med(les_elems2, type_ele, true);
1365
1366 mc_mesh->allocateCells(ncells);
1367 if (cell_type == INTERP_KERNEL::NORM_POLYHED)
1368 {
1369 // Polyedron is special, see page 10:
1370 // http://trac.lecad.si/vaje/chrome/site/doc8.3.0/extra/Normalisation_pour_le_couplage_de_codes.pdf
1371 const Polyedre_32_64<_SZ_>& poly = ref_cast(Polyedre_32_64<_SZ_>, elem_.valeur());
1372 ArrOfInt_t nodes_glob;
1373 poly.remplir_Nodes_glob(nodes_glob, les_elems2);
1374 const ArrOfInt_t& facesIndex = poly.getFacesIndex();
1375 const ArrOfInt_t& polyhedronIndex = poly.getPolyhedronIndex();
1376 assert(ncells <= polyhedronIndex.size_array() - 1);
1377
1378 for (int_t i = 0; i < ncells; i++)
1379 {
1380 int size = 0;
1381 for (int_t face = polyhedronIndex[i]; face < polyhedronIndex[i + 1]; face++)
1382 size += (int)(facesIndex[face + 1] - facesIndex[face] + 1);
1383 size--; // No -1 at the end of the cell
1384 ArrOfTID cell_def(size); // ArrOfTID whatever the template parameter, since TID == mcIdType.
1385 size = 0;
1386 for (int_t face = polyhedronIndex[i]; face < polyhedronIndex[i + 1]; face++)
1387 {
1388 for (int_t node = facesIndex[face]; node < facesIndex[face + 1]; node++)
1389 cell_def[size++] = nodes_glob[node];
1390 if (size < cell_def.size_array())
1391 // Add -1 to mark the end of a face:
1392 cell_def[size++] = -1;
1393 }
1394 mc_mesh->insertNextCell(cell_type, cell_def.size_array(), cell_def.addr());
1395 }
1396 }
1397 else
1398 {
1399 // Other cells:
1400 if (std::is_same<_SZ_, trustIdType>::value) // 64b version of the Domaine, or TRUST compiled in 32b
1401 {
1402 // We can directly point into les_elems2, types are compatible
1403 for (int_t i = 0; i < ncells; i++)
1404 {
1405 int nvertices = nverts;
1406 // Polygons don't have a constant number of vertices - need to discard -1 values:
1407 for (int j = nverts-1; j >= 0 && les_elems2(i, j) < 0; j--) nvertices--;
1408 // Brutal pointer cast below, just so that the compiler does not complain when instanciating for _SZ_ = int:
1409 mc_mesh->insertNextCell(cell_type, nvertices, (trustIdType *)(les_elems2.addr() + i * nverts));
1410 }
1411 }
1412 else
1413 {
1414 // Need to upcast from int to mcIdType:
1415 for (int_t i = 0; i < ncells; i++)
1416 {
1417 ArrOfTID cell_def(nverts);
1418 int j = 0;
1419 for (; j<nverts && les_elems2(i, j) >= 0; j++)
1420 cell_def[j] = (trustIdType)les_elems2(i, j);
1421 mc_mesh->insertNextCell(cell_type, j, cell_def.addr()); // j is the final numb of vertices
1422 }
1423 }
1424 }
1425 *(virt ? &mc_mesh_virt_ready_ : &mc_mesh_ready_) = true;
1426
1427#endif // MEDCOUPLING_
1428}
1429
1430
1431template<typename _SZ_>
1432void Domaine_32_64<_SZ_>::prepare_rmp_with(const Domaine_32_64& other_domain, bool virt) const
1433{
1434#ifdef MEDCOUPLING_
1435 using namespace MEDCoupling;
1436
1437 // Retrieve mesh upfront to possibly build them if they were not already:
1438 get_mc_mesh();
1439 const MEDCouplingUMesh* oth_msh = other_domain.get_mc_mesh(virt);
1440
1441 Cerr << "Building remapper between " << le_nom() << " (" << (int)mc_mesh_->getSpaceDimension() << "D) mesh with " << (int)mc_mesh_->getNumberOfCells()
1442 << " cells and " << other_domain.le_nom() << " (" << (int)oth_msh->getSpaceDimension() << "D) mesh with "
1443 << (int)oth_msh->getNumberOfCells() << " cells" << finl;
1444 rmps[&other_domain].prepare(oth_msh, mc_mesh_, "P0P0");
1445 Cerr << "remapper prepared with " << rmps.at(&other_domain).getNumberOfColsOfMatrix() << " columns in matrix, with max value = " << rmps.at(&other_domain).getMaxValueInCrudeMatrix() << finl;
1446#else
1447 Process::exit("Domaine_32_64<_SZ_>::prepare_rmp_with should not be called since it requires a TRUST version compiled with MEDCoupling !");
1448#endif
1449}
1450
1451template <typename _SIZE_>
1452void Domaine_32_64<_SIZE_>::prepare_dec_with(const Domaine_32_64& other_domain, MEDCouplingFieldDouble *dist, MEDCouplingFieldDouble *loc) const
1453{
1454#if defined(MEDCOUPLING_) && defined(MPI_)
1455 using namespace MEDCoupling;
1456
1457 Perf_counters::time_point t0 = statistics().start_clock();
1458 Cerr << "Building DEC of nature" << MEDCouplingNatureOfField::GetRepr(dist->getNature())
1459 << "from " << other_domain.le_nom() << " (" << Process::mp_sum(dist->getMesh()->getNumberOfCells())
1460 << " cells) to " << le_nom() << " (" << Process::mp_sum(loc->getMesh()->getNumberOfCells()) << " cells) : ";
1461 std::set<int> pcs;
1462 for (int i=0; i<Process::nproc(); i++) pcs.insert(i);
1463 /* a bit technical */
1464 decs.emplace(std::piecewise_construct,
1465 std::forward_as_tuple(&other_domain, dist->getNature()),
1466 std::forward_as_tuple(pcs, ref_cast(Comm_Group_MPI,PE_Groups::current_group()).get_trio_u_world()));
1467 OverlapDEC& dec = decs.at({ &other_domain, dist->getNature()});
1468 dec.setWorkSharingAlgo(Option_Interpolation::SHARING_ALGO);
1469 dec.attachSourceLocalField(dist);
1470 dec.attachTargetLocalField(loc);
1471 dec.synchronize();
1472
1473 Cerr << statistics().compute_time(t0) << " s" << finl;
1474#else
1475 Process::exit("Domaine::prepare_dec_with() should not be called since it requires a TRUST version compiled with MEDCoupling and MPI!");
1476#endif
1477}
1478
1479#ifdef MEDCOUPLING_
1480
1481template <typename _SIZE_>
1482MEDCoupling::MEDCouplingRemapper* Domaine_32_64<_SIZE_>::get_remapper(const Domaine_32_64& other_domain, bool virt) const
1483{
1484 if (!rmps.count(&other_domain))
1485 prepare_rmp_with(other_domain, virt);
1486 return &rmps.at(&other_domain);
1487}
1488
1489#ifdef MPI_
1490template <typename _SIZE_>
1491MEDCoupling::OverlapDEC* Domaine_32_64<_SIZE_>::get_dec(const Domaine_32_64& other_domain, MEDCouplingFieldDouble *dist, MEDCouplingFieldDouble *loc) const
1492{
1493 if (!decs.count({ &other_domain, dist->getNature() } ))
1494 prepare_dec_with(other_domain, dist, loc);
1495 return &decs.at({ &other_domain, dist->getNature() });
1496}
1497#endif
1498
1499#endif
1500
1501
1502/*! @brief Fills the Domaine from a list of Domaine objects by aggregating them.
1503 *
1504 * See Mailler for example
1505 */
1506template <typename _SIZE_>
1507void Domaine_32_64<_SIZE_>::fill_from_list(std::list<Domaine_32_64*>& lst)
1508{
1509 Cerr << "Filling domain from list of domains in progress... " << finl;
1511 Process::exit("Error in Domaine_32_64<_SIZE_>::fill_from_list() : compression prohibited in parallel mode");
1512 if (lst.size() == 0)
1513 Process::exit("Error in Domaine_32_64<_SIZE_>::fill_from_list() : compression prohibited in parallel mode");
1514
1515 for(auto& elem: lst)
1516 elem->comprimer();
1517
1518#ifndef NDEBUG
1519 Domaine_32_64& fst_dom = *lst.front();
1520 Nom typ_elem = fst_dom.type_elem()->que_suis_je();
1521#endif
1522 for(auto& it: lst)
1523 {
1524 Domaine_32_64& dom2 = *it;
1525 Cerr << " Concatenating Domains "<< nom_ << " and " << dom2.nom_ << finl;;
1526 // Check single geometrical type:
1527 assert(typ_elem == dom2.type_elem()->que_suis_je());
1528 // Handle nodes:
1529 IntVect_t les_nums;
1530 // Copy sommets to this
1531 ajouter(dom2.sommets_, les_nums); // les_nums: out parameter
1532 // Renumber current Domaine to prepare addition of elements
1533 dom2.renum(les_nums);
1534 // Merge elem info:
1536 }
1537
1538 Cerr << "Filling from list - End!" << finl;
1539}
1540
1541/*! @brief Renumbers the nodes and elements present in the common items of joints.
1542*
1543* Node number k becomes node number Les_Nums[k], and element number e becomes element number e+elem_offset.
1544*
1545* @param (IntVect& Les_Nums) the vector containing the new numbering: New_node_number_i = Les_Nums[Old_node_number_i]
1546*/
1547template <typename _SIZE_>
1549{
1550 for (int i_joint = 0; i_joint < nb_joints(); i_joint++)
1551 {
1552 ArrOfInt_t& sommets_communs = mes_faces_joint_[i_joint].set_joint_item(JOINT_ITEM::SOMMET).set_items_communs();
1553 for (int_t index = 0; index < sommets_communs.size_array(); index++)
1554 sommets_communs[index] = Les_Nums[sommets_communs[index]];
1555
1556 ArrOfInt_t& elements_distants = mes_faces_joint_[i_joint].set_joint_item(JOINT_ITEM::ELEMENT).set_items_distants();
1557 elements_distants += elem_offset;
1558 }
1559}
1560
1561/*! @brief Merges joints with the same name
1562 *
1563 */
1564template <typename _SIZE_>
1566{
1567 auto& list = mes_faces_joint_.get_stl_list();
1568 for (auto it = list.begin(); it != list.end(); ++it)
1569 {
1570 Frontiere_t& front = *it;
1571 for (auto it2 = std::next(it); it2 != list.end();)
1572 {
1573 Frontiere_t& front2 = *it2;
1574 if (front.le_nom() == front2.le_nom())
1575 {
1576 front.add(front2);
1577 it2 = list.erase(it2);
1578 }
1579 else
1580 ++it2;
1581 }
1582 }
1583 return 1;
1584}
1585
1586
1587/////////////////////////////////////////////////
1588//// Methods only used in the 32 bits version
1589/////////////////////////////////////////////////
1590
1591namespace // Anonymous namespace - only 32 bits stuff here
1592{
1593
1594/*! @brief This method performs a virtual space exchange of an edge array without going through the edge descriptor.
1595 *
1596 * The elem_aretes array and the virtual space exchange of elements are used.
1597 *
1598 */
1599void echanger_tableau_aretes(const IntTab& elem_aretes, int nb_aretes_reelles, ArrOfInt& tab_aretes)
1600{
1601 const int moi = Process::me();
1602
1603 const int nb_elem = elem_aretes.dimension(0);
1604 const int nb_elem_tot = elem_aretes.dimension_tot(0);
1605 const int nb_aretes_elem = elem_aretes.dimension(1);
1606 int i;
1607
1608 // **********************
1609 // I) Exchange to update common items
1610 // Slightly complex algorithm to update common items: for each real edge,
1611 // the value of tab_aretes must equal the initial value of tab_arete given by
1612 // the processor with the smallest rank among those sharing the edge (i.e.
1613 // processors that have an element adjacent to this edge).
1614
1615 // Array to identify the owner processor of a real edge
1616 ArrOfInt pe_arete(nb_aretes_reelles);
1617 pe_arete = moi;
1618 // Array giving, for each element, the owner processor
1619 IntVect pe_elem(nb_elem_tot);
1620 pe_elem = moi; // initialized with "me"
1621 {
1622 pe_elem.set_md_vector(elem_aretes.get_md_vector());
1623 pe_elem.echange_espace_virtuel();
1624 // Store in pe_arete the number of the smallest-rank owner processor among
1625 // the processors owning elements adjacent to this edge.
1626 // No need to iterate over real elements, we would find pe_elem[i]==moi...
1627 // If the edge is on a processor with a lower rank, assign it that rank
1628 for (i = nb_elem; i < nb_elem_tot; i++)
1629 for (int pe = pe_elem[i], j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1630 if (a < nb_aretes_reelles && pe_arete[a] > pe)
1631 pe_arete[a] = pe;
1632 }
1633 // Assuming the virtual element space contains at least one layer of virtual elements
1634 // (all neighbors of real elements through vertices), the real edges are exchanged
1635 // (virtual edges not yet).
1636 // In this case, pe_arete is now correctly filled for real edges.
1637
1638 IntTab tmp;
1639 tmp.copy(elem_aretes, RESIZE_OPTIONS::NOCOPY_NOINIT); // copy structure only
1640
1641 // Copy tab_aretes into the tmp structure (we can exchange tmp, not tab_aretes)
1642 for (i = 0; i < nb_elem; i++)
1643 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1644 tmp(i, j) = tab_aretes[a];
1645
1646 // 2) Exchange the array
1648
1649 // 3) Copy back into the real part of tab_aretes the values taken from tmp:
1650 // for an edge shared by several procs, the proc with the smallest rank
1651 // provides the value.
1652 // No need to iterate over real elements, the value would not change
1653 for (i = nb_elem; i < nb_elem_tot; i++)
1654 for (int pe = pe_elem[i], j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1655 if (a < nb_aretes_reelles && pe_arete[a] == pe)
1656 tab_aretes[a] = tmp(i, j);
1657
1658 // tab_aretes now contains correct values for all real edges
1659 // (common items are up to date). We do one more exchange via tmp to
1660 // update the virtual items:
1661
1662 // ******************
1663 // II) Exchange to update the virtual space of edges
1664
1665 // Copy tab_aretes into the tmp structure again
1666 for (i = 0; i < nb_elem; i++)
1667 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1668 tmp(i, j) = tab_aretes[a];
1669
1670 // Exchange the array
1672 // Copy tmp back into tab_aretes
1673 for (i = nb_elem; i < nb_elem_tot; i++)
1674 for (int j = 0, a; j < nb_aretes_elem && (a = elem_aretes(i, j)) >= 0; j++)
1675 tab_aretes[a] = tmp(i, j);
1676}
1677
1678} // end anonymous namespace
1679
1680/*! Selects a unique item (vertex, face ...) from a list (item_possible)
1681* in order to ensure the parallelism of certain algorithms.
1682* The selection is made by testing the distance between the coordinates (coord_possible)
1683* locating these items with respect to the coordinates (coord_ref) of a reference point.
1684* The retained item is the one with the minimum distance to the reference point.
1685* If several items remain at the same distance from the reference point,
1686* the test is repeated by translating the reference point.
1687*/
1688template <>
1689int Domaine_32_64<int>::identifie_item_unique(IntList& item_possible, DoubleTab& coord_possible, const DoubleVect& coord_ref)
1690{
1691 int it_selection = -1;
1692 DoubleTab decentre_face(4, Objet_U::dimension);
1693 decentre_face = 0.;
1694 for (int t = 1; t < 4; t++)
1695 for (int dir = 0; dir < Objet_U::dimension; dir++)
1696 if (dir == (t - 1))
1697 decentre_face(t, dir) = 1.;
1698 // decentre_face(0,0:dim)={0,0,0}
1699 // decentre_face(1,0:dim)={1,0,0}
1700 // decentre_face(2,0:dim)={0,1,0}
1701 // decentre_face(3,0:dim)={0,0,1}
1702
1703 //At the first pass (t=0) no translation is performed
1704 DoubleVect dist;
1705 assert(item_possible.size() != 0);
1706 int t = 0;
1707 while ((item_possible.size() != 1) && (t < 4))
1708 {
1709 double distmin = DMAXFLOAT;
1710 int size_initiale = item_possible.size();
1711 dist.resize(size_initiale);
1712 dist = 0.;
1713
1714 for (int ind_it = 0; ind_it < size_initiale; ind_it++)
1715 {
1716 for (int dir = 0; dir < Objet_U::dimension; dir++)
1717 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)));
1718 if (dist[ind_it] <= distmin)
1719 distmin = dist[ind_it];
1720 }
1721
1722 int ind_it = 0;
1723 int nb_it_suppr = 0;
1724 while (ind_it < size_initiale)
1725 {
1726 if (!est_egal(dist[ind_it], distmin))
1727 {
1728 int ind_it_suppr = ind_it - nb_it_suppr;
1729 int it_suppr = item_possible[ind_it_suppr];
1730 item_possible.suppr(it_suppr);
1731
1732 int size_actuelle = item_possible.size();
1733 for (int ind = ind_it_suppr; ind < size_actuelle; ind++)
1734 for (int dir = 0; dir < dimension; dir++)
1735 coord_possible(ind, dir) = coord_possible(ind + 1, dir);
1736 coord_possible.resize(size_actuelle, dimension, RESIZE_OPTIONS::COPY_NOINIT);
1737 nb_it_suppr++;
1738 }
1739 ind_it++;
1740 }
1741 t++;
1742 }
1743 if (item_possible.size() == 1)
1744 it_selection = item_possible[0];
1745 else
1746 {
1747 Cerr << "Domaine::identifie_item_unique()" << finl;
1748 Cerr << "An item has not been found among the list." << finl;
1749 Cerr << "Please contact TRUST support." << finl;
1750 Process::exit();
1751 }
1752 return it_selection;
1753}
1754
1755template <typename _SIZE_>
1756int Domaine_32_64<_SIZE_>::identifie_item_unique(IntList& item_possible, DoubleTab& coord_possible, const DoubleVect& coord_ref)
1757{
1758 assert(false);
1759 throw;
1760}
1761
1762/*! @brief Method called by Domaine_VF::discretiser().
1763 *
1764 * Builds the descriptor for boundary faces.
1765 * Fills ind_faces_virt_bord and the get_faces_virt() arrays of the boundaries
1766 * from the parallel descriptor of faces.
1767 * Note B.M.: having placed faces in Domaine_VF, edges in Domaine,
1768 * some face boundary properties in Domaine_VF and others in Domaine
1769 * makes the initialization follow somewhat convoluted paths... this should be cleaned up.
1770 *
1771 */
1772template <>
1773void Domaine_32_64<int>::init_faces_virt_bord(const MD_Vector& md_vect_faces, MD_Vector& md_vect_faces_front)
1774{
1775 if (Process::is_sequential()) // Much simpler in this case:
1776 {
1777 ind_faces_virt_bord_.resize_array(0);
1779 md_vect_faces_front.copy(mdseq);
1780
1781 // Build the MD_Vector_seq of each boundary:
1782 const int nb_frontieres = nb_front_Cl() + nb_groupes_faces();
1783 for (int i_frontiere = 0; i_frontiere < nb_frontieres; i_frontiere++)
1784 {
1785 Frontiere& front = frontiere(i_frontiere);
1786 IntTab& faces_sommets_frontiere = front.les_sommets_des_faces();
1787 // Some problems have multiple Domaine_VF objects attached to the same Domaine (radiation)
1788 // If we already went through here, don't redo the work:
1789 if (faces_sommets_frontiere.get_md_vector())
1790 continue;
1791 const int nb_faces_front = front.nb_faces();
1792 // Build a descriptor containing the subset of faces of this boundary
1793 MD_Vector md_frontiere;
1794 MD_Vector_seq mdseq_front(nb_faces_front);
1795 md_frontiere.copy(mdseq_front);
1796 faces_sommets_frontiere.set_md_vector(md_frontiere);
1797 }
1798
1799 return;
1800 }
1801
1802 // ***************************************
1803 // 1) Build array structures for all boundary faces
1804 // (faces from 0 to nb_faces_frontiere())
1805 const int nb_faces_fr = nb_faces_frontiere();
1806 // Mark boundary faces (-1=>not a boundary face, 0=>boundary face)
1807 IntVect vect_renum;
1808 MD_Vector_tools::creer_tableau_distribue(md_vect_faces, vect_renum, RESIZE_OPTIONS::NOCOPY_NOINIT);
1809 vect_renum = -1;
1810 for (int i = 0; i < nb_faces_fr; i++)
1811 vect_renum[i] = 0;
1812 vect_renum.echange_espace_virtuel();
1813
1814 // Create the descriptor for boundary faces (by extracting a subset of the face descriptor).
1815 // The default numbering in ascending order is used:
1816 MD_Vector_tools::creer_md_vect_renum_auto(vect_renum, md_vect_faces_front);
1817
1818 // Fill the ind_faces_virt_bord array. It is just the virtual part of the renum array.
1819 // (the real part is trivial: it is a contiguous numbering from 0 to nb_faces_frontiere())
1820 const int nb_faces = vect_renum.size();
1821 const int nb_faces_tot = vect_renum.size_totale();
1822 const int nb_faces_virt = nb_faces_tot - nb_faces;
1823 ind_faces_virt_bord_.resize_array(nb_faces_virt, RESIZE_OPTIONS::NOCOPY_NOINIT);
1824 for (int i = 0; i < nb_faces_virt; i++)
1825 ind_faces_virt_bord_[i] = vect_renum[nb_faces + i];
1826
1827 // **************************************
1828 // 2) Build array structures for each boundary
1829
1830 // Fill the arrays
1831 // frontiere(i).get_faces_virt() for 0 <= i < nb_front_Cl()
1832 // This array contains the indices in Domaine_VF of the virtual faces
1833 // that are on boundary i.
1834 // Compute the virtual space of faces for each boundary
1835
1836 // Number of boundaries:
1837 const int nb_frontieres = nb_front_Cl();
1838 int i_frontiere;
1839 // Fill the get_faces_virt() arrays:
1840 // and build the MD_Vector of each boundary (associated with the face array)
1841 for (i_frontiere = 0; i_frontiere < nb_frontieres; i_frontiere++)
1842 {
1843 Frontiere& front = frontiere(i_frontiere);
1844 IntTab& faces_sommets_frontiere = front.les_sommets_des_faces();
1845 // Some problems have multiple Domaine_VF objects attached to the same Domaine (radiation)
1846 // If we already went through here, don't redo the work:
1847 if (faces_sommets_frontiere.get_md_vector())
1848 continue;
1849 //the faces_sommets_frontiere arrays must have the same width on all procs before exchange
1850 int nb_som_faces = Process::mp_max(faces_sommets_frontiere.dimension(1));
1851 if (faces_sommets_frontiere.dimension(1) < nb_som_faces)
1852 {
1853 IntTab fsf_old;
1854 fsf_old = faces_sommets_frontiere;
1855 faces_sommets_frontiere.resize(fsf_old.dimension_tot(0), nb_som_faces);
1856 faces_sommets_frontiere = -1;
1857 for (int i = 0, j; i < fsf_old.dimension_tot(0); i++)
1858 for (j = 0; j < fsf_old.dimension(1); j++)
1859 faces_sommets_frontiere(i, j) = fsf_old(i, j);
1860 }
1861
1862 vect_renum = -1;
1863 const int i_premiere_face = front.num_premiere_face();
1864 const int nb_faces_front = front.nb_faces();
1865 // Mark the faces of this boundary
1866 for (int i = i_premiere_face; i < i_premiere_face + nb_faces_front; i++)
1867 vect_renum[i] = 0;
1868 vect_renum.echange_espace_virtuel();
1869 // Build a descriptor containing the subset of faces of this boundary
1870 MD_Vector md_frontiere;
1871 MD_Vector_tools::creer_md_vect_renum_auto(vect_renum, md_frontiere);
1872
1873 // Create the virtual space of boundary faces
1874 // (this is where the md_frontiere descriptor is associated with the face array)
1875 const MD_Vector& md_sommets = les_sommets().get_md_vector();
1876 Scatter::construire_espace_virtuel_traduction(md_frontiere, /* array indexed by boundary face numbers */
1877 md_sommets, /* containing vertex indices of the domain */
1878 faces_sommets_frontiere, /* array to process */
1879 1 /* fatal error: if a vertex is missing, it is an error */);
1880
1881 // Retrieve from renum the renumbered index of each face:
1882 // extract the indices of the virtual faces of this boundary
1883 ArrOfInt& tab = front.get_faces_virt();
1884 assert(faces_sommets_frontiere.dimension(0) == nb_faces_front);
1885 const int nb_faces_tot_frontiere = faces_sommets_frontiere.dimension_tot(0);
1886 const int nb_faces_virt_frontiere = nb_faces_tot_frontiere - nb_faces_front;
1887 tab.resize_array(nb_faces_virt_frontiere);
1888 const int ndebut = nb_faces; // number of faces in the Domain!
1889 const int nfin = nb_faces_tot; // idem!
1890 for (int i = ndebut; i < nfin; i++)
1891 {
1892 const int j = vect_renum[i];
1893 if (j >= 0)
1894 {
1895 assert(j >= nb_faces_front && j < nb_faces_tot_frontiere);
1896 // Face i is virtual and on this boundary
1897 tab[j - nb_faces_front] = i;
1898 }
1899 }
1900 }
1901}
1902
1903template <typename _SIZE_>
1904void Domaine_32_64<_SIZE_>::init_faces_virt_bord(const MD_Vector& md_vect_faces, MD_Vector& md_vect_faces_front)
1905{
1906 assert(false);
1907 throw;
1908}
1909
1910/*! Version of creer_aretes compatible with polyhedra
1911 */
1912template <>
1914{
1915 const IntTab& elem_som = les_elems();
1916 // Number of real elements:
1917 const int nbelem = elem_som.dimension(0);
1918 // Virtual elements are already built:
1919 const int nbelem_tot = elem_som.dimension_tot(0);
1920
1921 aretes_som_.resize(0, 2);
1922 bool is_poly = sub_type(Poly_geom_base, type_elem().valeur());
1923
1924 std::vector<std::vector<int> > v_e_a(nbelem_tot); //list of edges for each element
1925 int nb_aretes_reelles = 0, i;
1926 int j;
1927 {
1928 // A linked list to retrieve, for each vertex, the list of edges
1929 // attached to that vertex. The array has the same size as Aretes_som.dimension(0).
1930 // chaine_aretes_sommets[i] contains the index of the next edge attached to
1931 // the same vertex, or -1 if it is the last one.
1932 ArrOfInt chaine_aretes_sommets;
1933 // Index of the first edge attached to each vertex in chaine_aretes_sommets
1934 ArrOfInt premiere_arete_som(nb_som_tot());
1935 premiere_arete_som = -1;
1936
1937 std::map<std::array<double, 3>, std::array<int, 2> > aretes_loc; //edges of the current element: aretes_loc[{xa, ya, za}] = { s1, s2}
1938 //using a map ensures that edges are in the same order on all procs!
1939 for (int i_elem = 0; i_elem < nbelem_tot; aretes_loc.clear(), i_elem++)
1940 {
1941 /* 1. retrieve the edges of the element by iterating over its faces */
1942 const Elem_geom_base& elem_g = ref_cast(Elem_geom_base, type_elem().valeur());
1943 IntTab f_e_r;
1944 if (is_poly)
1945 {
1946 const Poly_geom_base& poly_g = ref_cast(Poly_geom_base, type_elem().valeur());
1947 poly_g.get_tab_faces_sommets_locaux(f_e_r, i_elem);
1948 }
1949 else
1950 elem_g.get_tab_faces_sommets_locaux(f_e_r);
1951
1952 for (i = 0; i < f_e_r.dimension(0) && f_e_r(i, 0) >= 0; i++)
1953 for (j = 0; j < f_e_r.dimension(1) && f_e_r(i, j) >= 0; j++)
1954 {
1955 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));
1956 std::array<double, 3> key;
1957 for (int l = 0; l < 3; l++)
1958 key[l] = (sommets_(s1, l) + sommets_(s2, l)) / 2;
1959 aretes_loc[key] = {{ std::min(s1, s2), std::max(s1, s2) }};
1960 }
1961
1962 for (auto &&kv : aretes_loc)
1963 {
1964 //have we already seen this edge ?
1965 int k = premiere_arete_som[kv.second[0]];
1966 while (k >= 0 && (aretes_som_(k, 0) != kv.second[0] || aretes_som_(k, 1) != kv.second[1]))
1967 k = chaine_aretes_sommets[k];
1968 if (k < 0) //edge not yet found -> update premiere_arete_som and chaine_arete_sommets
1969 {
1970 // The edge does not exist yet
1971 k = chaine_aretes_sommets.size_array();
1972 assert(k == aretes_som_.dimension(0));
1973 aretes_som_.append_line(kv.second[0], kv.second[1]);
1974 // Insert the edge at the head of the linked list
1975 int old_head = premiere_arete_som[kv.second[0]];
1976 // Index of the new edge
1977 int new_head = chaine_aretes_sommets.size_array();
1978 chaine_aretes_sommets.append_array(old_head);
1979 premiere_arete_som[kv.second[0]] = new_head;
1980 }
1981 v_e_a[i_elem].push_back(k); //add the edge to the element's edge list
1982 }
1983 if (i_elem == nbelem - 1)
1984 {
1985 // We have just finished the real edges
1986 nb_aretes_reelles = aretes_som_.dimension(0);
1987 }
1988 }
1989 }
1990 /* fill the elem_aretes array using v_e_a */
1991 int nb_aretes_elem = 0;
1992 for (i = 0; i < nbelem_tot; i++)
1993 nb_aretes_elem = std::max(nb_aretes_elem, (int) v_e_a[i].size());
1994 nb_aretes_elem = mp_max(nb_aretes_elem);
1995 elem_aretes_.resize(0, nb_aretes_elem);
1996 creer_tableau_elements(elem_aretes_, RESIZE_OPTIONS::NOCOPY_NOINIT);
1997 for (i = 0, elem_aretes_ = -1; i < nbelem_tot; i++)
1998 for (j = 0; j < (int) v_e_a[i].size(); j++)
1999 elem_aretes_(i, j) = v_e_a[i][j];
2000
2001 // Adjust the size of the Aretes_som array
2002 const int n_aretes_tot = aretes_som_.dimension(0); // note: nb_aretes_tot is a method!
2003 aretes_som_.append_line(-1, -1); // because the following resize only does something if the size changes
2004 aretes_som_.resize(n_aretes_tot, 2);
2005
2006 Journal() << "Domaine " << le_nom() << " nb_aretes=" << nb_aretes_reelles << " nb_aretes_tot=" << n_aretes_tot << finl;
2007
2008 // Build the parallel descriptor
2009 {
2010 // For each edge, index of the processor owning the edge
2011 const int moi = Process::me();
2012 ArrOfInt pe_aretes(n_aretes_tot);
2013 pe_aretes = moi;
2014 echanger_tableau_aretes(elem_aretes_, nb_aretes_reelles, pe_aretes);
2015
2016 // For each edge, index of the edge on the owning processor
2017 ArrOfInt indice_aretes_owner;
2018 indice_aretes_owner.resize_array(n_aretes_tot, RESIZE_OPTIONS::NOCOPY_NOINIT);
2019 for (i = 0; i < nb_aretes_reelles; i++)
2020 indice_aretes_owner[i] = i;
2021 echanger_tableau_aretes(elem_aretes_, nb_aretes_reelles, indice_aretes_owner);
2022
2023 // Build pe_voisins
2024 ArrOfInt pe_voisins;
2025 for (i = 0; i < n_aretes_tot; i++)
2026 if (pe_aretes[i] != moi)
2027 pe_voisins.append_array(pe_aretes[i]);
2028
2029 ArrOfInt liste_pe;
2030 reverse_send_recv_pe_list(pe_voisins, liste_pe);
2031
2032 // Concatenate the two lists.
2033 for (i = 0; i < liste_pe.size_array(); i++)
2034 pe_voisins.append_array(liste_pe[i]);
2035 array_trier_retirer_doublons(pe_voisins);
2036
2037 int nb_voisins = pe_voisins.size_array();
2038 ArrOfInt indices_pe(nproc());
2039 indices_pe = -1;
2040 for (i = 0; i < nb_voisins; i++)
2041 indices_pe[pe_voisins[i]] = i;
2042
2043 ArrsOfInt aretes_communes_to_recv(nb_voisins);
2044 ArrsOfInt blocs_aretes_virt(nb_voisins);
2045 ArrsOfInt aretes_to_send(nb_voisins);
2046 // Iterate over edges: look for edges to receive from another processor.
2047 // Real edges (common items)
2048 for (i = 0; i < nb_aretes_reelles; i++)
2049 {
2050 const int pe = pe_aretes[i];
2051 if (pe != moi)
2052 {
2053 const int indice_pe = indices_pe[pe];
2054 if (indice_pe < 0)
2055 {
2056 Cerr << "Error: indice_pe=" << indice_pe << " shouldn't be negative in Domaine_32_64<_SZ_>::creer_aretes." << finl;
2057 Cerr << "It is a TRUST bug on this mesh with the Pa discretization, contact support." << finl;
2058 Cerr << "You could also try another partitioned mesh to get around this issue." << finl;
2059 Process::exit();
2060 }
2061 // I receive this edge from another proc
2062 const int indice_distant = indice_aretes_owner[i];
2063 aretes_to_send[indice_pe].append_array(indice_distant); // index on the neighboring pe
2064 aretes_communes_to_recv[indice_pe].append_array(i); // local index of the edge
2065 }
2066 }
2067// Virtual edges
2068 for (i = nb_aretes_reelles; i < n_aretes_tot; i++)
2069 {
2070 const int pe = pe_aretes[i];
2071 assert(pe < nproc() && pe != moi);
2072 const int indice_pe = indices_pe[pe];
2073 if (indice_pe < 0)
2074 {
2075 Cerr << "Error: indice_pe=" << indice_pe << " shouldn't be negative in Domaine_32_64<_SZ_>::creer_aretes." << finl;
2076 Cerr << "It is a TRUST bug on this mesh with the Pa discretization, contact support." << finl;
2077 Cerr << "You could also try another partitioned mesh to get around this issue." << finl;
2078 Process::exit();
2079 }
2080 const int indice_distant = indice_aretes_owner[i];
2081 aretes_to_send[indice_pe].append_array(indice_distant); // index on the neighboring pe
2082 MD_Vector_base::append_item_to_blocs(blocs_aretes_virt[indice_pe], i);
2083 }
2084 {
2085 Schema_Comm schema;
2086 schema.set_send_recv_pe_list(pe_voisins, pe_voisins);
2087 schema.begin_comm();
2088 // Push the aretes_to_send array and the number of edges shared with this pe:
2089 for (i = 0; i < nb_voisins; i++)
2090 schema.send_buffer(pe_voisins[i]) << aretes_to_send[i];
2092 // Receive
2093 for (i = 0; i < nb_voisins; i++)
2094 schema.recv_buffer(pe_voisins[i]) >> aretes_to_send[i];
2095 schema.end_comm();
2096 }
2097
2098 MD_Vector md;
2099 // Build the descriptor object
2101 {
2102 MD_Vector_std md_aretes(n_aretes_tot, nb_aretes_reelles, pe_voisins, aretes_to_send, aretes_communes_to_recv, blocs_aretes_virt);
2103 md.copy(md_aretes);
2104 }
2105 else
2106 {
2107 MD_Vector_seq md_aretes(n_aretes_tot);
2108 md.copy(md_aretes);
2109 }
2110 Cerr << "Total number of edges = " << md->get_nb_items_tot() << finl;
2111
2112 // Attach the descriptor to the array
2113 aretes_som_.set_md_vector(md);
2114 }
2115}
2116
2117template <typename _SIZE_>
2119{
2120 assert(false);
2121 throw;
2122}
2123
2124/*! Creation of boundary domains (called during discretisation).
2125 * Currently a static list of Domains where we need to know
2126 * the first element for each domain.
2127 */
2128template <>
2130{
2131 const Nom expr_elements("1");
2132 const Nom expr_faces("1");
2133 int nb_frontieres = nb_front_Cl();
2134 domaines_frontieres_.vide();
2135
2136 for (int i=0; i<nb_frontieres; i++)
2137 {
2138 // Name of the boundary
2139 Noms nom_frontiere(1);
2140 nom_frontiere[0]=frontiere(i).le_nom();
2141 // Name of the surface domain to be built
2142 Nom nom_domaine_surfacique=le_nom();
2143 nom_domaine_surfacique+="_boundaries_";
2144 nom_domaine_surfacique+=frontiere(i).le_nom();
2145 // Creation
2146 Cerr << "Creating a surface domain named " << nom_domaine_surfacique << " for the boundary " << nom_frontiere[0] << " of the domain " << le_nom() << finl;
2147
2149 if (interp.objet_global_existant(nom_domaine_surfacique))
2150 {
2151 Cerr << "Domain " << nom_domaine_surfacique
2152 << " already exists, writing to this object." << finl;
2153
2154 Domaine& dom_new = ref_cast(Domaine, interprete().objet(nom_domaine_surfacique));
2156 }
2157 else
2158 {
2159 DerObjU ob;
2160 ob.typer("Domaine");
2161 interp.ajouter(nom_domaine_surfacique, ob);
2162 }
2163 Domaine& dom_new = ref_cast(Domaine, interprete().objet(nom_domaine_surfacique));
2164
2165 Extraire_surface::extraire_surface(dom_new,*this,nom_domaine_surfacique,domaine_vf,expr_elements,expr_faces,0,nom_frontiere);
2166 OBS_PTR(Domaine)& ref_dom_new=domaines_frontieres_.add(OBS_PTR(Domaine)());
2167 ref_dom_new=dom_new;
2168 }
2169}
2170
2171template <typename _SIZE_>
2173{
2174 assert(false);
2175 throw;
2176}
2177
2178
2179/*! @brief Renumbering of nodes: node number k becomes node number Les_Nums[k]
2180 *
2181 * @param (IntVect& Les_Nums) vector containing the new numbering: New_node_number_i = Les_Nums[Old_node_number_i]
2182 */
2183template <typename _SIZE_>
2185{
2186 int_t dim0 = mes_elems_.dimension(0);
2187 int dim1 = mes_elems_.dimension_int(1);
2188
2189 for (int_t i = 0; i < dim0; i++)
2190 for (int j = 0; j < dim1; j++)
2191 mes_elems_(i, j) = Les_Nums[mes_elems_(i, j)];
2192
2193 for (int i = 0; i < nb_bords(); i++)
2194 mes_faces_bord_(i).renum(Les_Nums);
2195 for (int i = 0; i < nb_joints(); i++)
2196 mes_faces_joint_(i).renum(Les_Nums);
2197 for (int i = 0; i < nb_raccords(); i++)
2198 mes_faces_raccord_(i)->renum(Les_Nums);
2199 for (int i = 0; i < nb_frontieres_internes(); i++)
2200 mes_bords_int_(i).renum(Les_Nums);
2201 for (int i = 0; i < nb_groupes_faces(); i++)
2202 mes_groupes_faces_(i).renum(Les_Nums);
2203}
2204
2205template<>
2207{
2208 // Sanity check - make sure that the periodic BC are put on a periodic boundary
2209 // (the opposite is allowed, eventhough it is probably stupid: a non periodic BC on a periodic boundary)
2210 const int nb_bords = les_cl.size();
2211 const Noms& bords_per = this->bords_perio();
2212 for (int n_bord = 0; n_bord < nb_bords; n_bord++)
2213 {
2214 if (sub_type(Periodique, les_cl[n_bord].valeur()))
2215 {
2216 const Nom& nom_b =les_cl[n_bord]->frontiere_dis().frontiere().le_nom();
2217 if(bords_per.rang(nom_b) < 0)
2218 {
2219 Cerr << "ERROR: you have put a periodic boundary condition on a boundary ('" << nom_b << "') which is not periodic." << finl;
2220 Cerr << "Use the keyword: declarer_bord_perio { domaine " << le_nom() << " bord " << nom_b << " }" << finl;
2221 Cerr << "after the loading of the domain to declare this boundary as being periodic." << finl;
2222 Process::exit();
2223 }
2224 }
2225 }
2226
2228 1 /* Compute values for virtual vertices */);
2229}
2230
2231
2232template<typename _SZ_>
2234{
2235 assert(false);
2236 throw;
2237}
2238
2239
2240
2241/////////////////////////////////////////////////
2242//// Template instanciations
2243/////////////////////////////////////////////////
2244
2245template class Domaine_32_64<int>;
2246#if INT_is_64_ == 2
2247template class Domaine_32_64<trustIdType>;
2248#endif
Empty class used as a base for all the arrays.
Definition Array_base.h:41
void associer_domaine(const Domaine_t &)
Associates a domain to all boundaries in the list.
Definition Bords.cpp:32
void associer_domaine(const Domaine_t &)
Associates a domain to all Bord_Interne objects in the list.
: Class Comm_Group_MPI, derived from the abstract class Comm_Group.
class Conds_lim This class represents a vector of boundary conditions.
Definition Conds_lim.h:32
class Domaine_32_64 A Domain is a mesh composed of a set of geometric elements of the same type.
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)
Computes the center of gravity of the domain.
Definition Domaine.cpp:735
double volume_total() const
Definition Domaine.cpp:876
IntTab_t aretes_som_
Definition Domaine.h:394
void construire_elem_virt_pe_num()
Definition Domaine.cpp:703
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:802
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
Returns the number of vertices of the geometric elements that make up the domain.
Definition Domaine.h:474
int_t nb_elem_tot() const
Definition Domaine.h:132
void creer_aretes()
Definition Domaine.cpp:2118
ArrOfDouble cg_moments_
Definition Domaine.h:407
SmallArrOfTID_t & chercher_elements(const DoubleTab &pos, SmallArrOfTID_t &elem, int reel=0) const
Searches for the elements containing the points whose coordinates are specified.
Definition Domaine.cpp:404
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:816
virtual void creer_tableau_elements(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates a parallel array of values at elements.
Definition Domaine.cpp:850
void creer_mes_domaines_frontieres(const Domaine_VF &domaine_vf)
Definition Domaine.cpp:2172
SmallArrOfTID_t & chercher_aretes(const DoubleTab &pos, SmallArrOfTID_t &arr, int reel=0) const
Definition Domaine.cpp:676
void calculer_centres_gravite(DoubleTab_t &xp) const
Calculates the centers of gravity of the domain elements.
Definition Domaine.h:503
int_t nb_faces_frontiere() const
Returns the number of boundary faces of the domain (sum of boundaries, connections,...
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:1756
virtual void calculer_volumes(DoubleVect_t &volumes, DoubleVect_t &inv_volumes) const
Computes the volumes of the domain elements.
Definition Domaine.cpp:763
void init_faces_virt_bord(const MD_Vector &md_vect_faces, MD_Vector &md_vect_faces_bord)
Definition Domaine.cpp:1904
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:1051
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:1507
Entree & readOn_has_perio(Entree &s, bool &has_perio)
Reads the objects constituting a Domain from an input stream.
Definition Domaine.cpp:208
Bords_t & faces_bord()
Definition Domaine.h:198
ArrOfInt_T< _SIZE_ > ArrOfInt_t
Definition Domaine.h:71
int associer_(Objet_U &) override
Associates a Sous_Domaine to the Domain.
Definition Domaine.cpp:1298
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:883
_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:1101
void init_renum_perio()
Initialize the renumerotation array for periodicity.
Definition Domaine.cpp:1312
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:1236
void construire_renum_som_perio(const Conds_lim &, const Domaine_dis_base &)
Definition Domaine.cpp:2233
void renum(const IntVect_t &nums)
Renumbering of nodes: node number k becomes node number Les_Nums[k].
Definition Domaine.cpp:2184
void invalide_octree()
Definition Domaine.cpp:809
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:258
Bords_Internes_t & bords_int()
Definition Domaine.h:213
void read_vertices(Entree &s)
only read vertices from the stream s
Definition Domaine.cpp:1009
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
Returns the number of real edges.
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:662
void calculer_centres_gravite_aretes(DoubleTab_t &xa) const
Computes the centers of gravity of the domain edges.
Definition Domaine.cpp:791
void check_domaine()
associate the read objects to the domaine and check that the reading objects are coherent
Definition Domaine.cpp:340
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:1161
void build_mc_mesh(bool virt=false) const
Build the MEDCoupling mesh corresponding to the TRUST mesh.
Definition Domaine.cpp:1325
void renum_joint_common_items(const IntVect_t &nums, const int_t elem_offset)
Renumbers the nodes and elements present in the common items of joints.
Definition Domaine.cpp:1548
int_t face_bords_interne_conjuguee(int_t face) const
Returns -1 if face is not an internal boundary face, or the index of the duplicated face otherwise.
Definition Domaine.cpp:515
SmallArrOfTID_t & indice_elements(const IntTab &som, SmallArrOfTID_t &elem, int reel=0) const
Searches the indices of elements containing the vertices specified by the "sommets" parameter.
Definition Domaine.cpp:382
virtual void creer_tableau_sommets(Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT) const
Creates an array with one "row" per mesh vertex.
Definition Domaine.cpp:999
virtual const MD_Vector & md_vector_elements() const
Returns the parallel descriptor of element arrays of the domain.
Definition Domaine.cpp:859
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)
Adds nodes (or vertices) to the domain (without checking for duplicates).
Definition Domaine.cpp:908
int nb_groupes_faces() const
Definition Domaine.h:220
void ecrire_noms_bords(Sortie &) const
Writes the boundary names to an output stream.
Definition Domaine.cpp:1031
Groupes_Faces_t & groupes_faces()
Definition Domaine.h:224
IntTab_T< _SIZE_ > IntTab_t
Definition Domaine.h:73
void imprimer() const
Definition Domaine.cpp:1183
int comprimer()
Merges boundaries with the same name for: boundaries, periodic boundaries, internal boundaries and fa...
Definition Domaine.cpp:546
int nb_raccords() const
Definition Domaine.h:247
const Noms & bords_perio() const
Definition Domaine.h:278
int comprimer_joints()
Merges joints with the same name.
Definition Domaine.cpp:1565
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_
Total volume of the domain (sum over all processors).
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
class Domaine_dis_base This class is the base of the hierarchy of discretized domains.
Class Elem_geom_base This class is the base class for the definition of 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
Fills faces_som_local(i,j) giving for 0 <= i < nb_faces() and 0 <= j < nb_som_face(i) the local verte...
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)
Class Faces Faces describes a set of faces by their type (point, segment, triangle or quadrangle),...
Definition Faces.h:50
void typer(const Motcle &)
Sets the type of the faces.
Definition Faces.cpp:382
int_t nb_faces() const
Definition Faces.h:66
const IntTab_t & les_sommets() const
Returns the array of vertices of all 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
Returns the domain associated with the boundary (const version).
int_t num_premiere_face() const
Definition Frontiere.h:67
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
Definition Frontiere.h:49
int_t nb_faces() const
Returns the number of faces of the boundary.
Definition Frontiere.h:59
void associer_domaine(const Domaine_t &)
Associates the boundary to the domain it belongs to.
Definition Frontiere.cpp:63
IntTab_t & les_sommets_des_faces()
Returns the vertices of the boundary faces.
void add(const Frontiere_32_64 &)
Adds the vertices (and faces) of the given boundary to this object (Frontiere_32_64).
void associer_domaine(const Domaine_t &)
Associates a domain to all Groupe_Faces objects in the list.
Interprets a block of instructions in the data set.
Objet_U & ajouter(const Nom &nom, DerObjU &object_to_add)
Adds object ob to the interpreter's object list and names it with nom.
static int objet_global_existant(const Nom &nom)
Returns a flag indicating whether an object with this name exists in interprete_courant() or one of i...
static Interprete_bloc & interprete_courant()
Returns the Interprete_bloc currently being read from the data set.
void associer_domaine(const Domaine_t &)
Associates a domain with all joints in the list.
Definition Joints.cpp:33
virtual int get_nb_items_tot() const
static void append_item_to_blocs(ArrOfInt &blocs, int item)
Helper method to append an item to a "blocs"-type array containing series of blocks.
Dummy parallel descriptor used for sequential computations.
This is the simplest descriptor, used for arrays of values at vertices, elements, faces,...
static void creer_md_vect_renum_auto(IntVect &flags_renum, MD_Vector &md_vect)
Same as creer_md_vect_renum() but creates a default numbering.
static void creer_tableau_distribue(const MD_Vector &, Array_base &, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Transforms v into a parallel array having the structure md.
: This class is an OWN_PTR but the pointed object is shared among multiple
Definition MD_Vector.h:48
void copy(const MD_Vector_base &)
Constructs an MD_Vector object by copying an existing object.
Definition MD_Vector.cpp:26
static void nettoie(Domaine_t &)
static int NettoiePasNoeuds
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
const Nom & le_nom() const override
Returns *this.
Definition Nom.cpp:555
An array of character strings (VECT(Nom)).
Definition Noms.h:26
int rang(const char *const ch) const
Definition Noms.cpp:65
Objet_U * typer(const char *nom_type)
Tries to create an instance of type "type".
friend class Entree
Definition Objet_U.h:71
virtual int associer_(Objet_U &)
Associates the Objet_U with another Objet_U. Virtual method to override.
Definition Objet_U.cpp:200
const Interprete & interprete() const
Definition Objet_U.cpp:211
static int dimension
Definition Objet_U.h:94
friend class Sortie
Definition Objet_U.h:70
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static double precision_geom
Definition Objet_U.h:81
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
Definition Objet_U.cpp:54
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
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
Returns true if the domain associated with the octree is non-null.
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
: An octree allowing to search in space for elements or points described by real-valued coordinates.
static int_t search_nodes_close_to(double x, double y, double z, const DoubleTab_t &coords, ArrOfInt_t &node_list, double epsilon)
Non-member method. Searches among the vertices in node_list for those within a distance.
void build_nodes(const DoubleTab_t &coords, const bool include_virtual, const double epsilon=0.)
builds an octree containing the points with coordinates coords.
int_t search_elements_box(double xmin, double ymin, double zmin, double xmax, double ymax, double zmax, ArrOfInt_t &elements) const
searches for all elements or points potentially having a non-empty intersection with the given box.
static const Comm_Group & current_group()
Returns a reference to the current active processor group.
Definition PE_Groups.h:64
std::chrono::time_point< clock > time_point
class Periodique This class represents a periodic boundary condition.
Definition Periodique.h:31
int get_tab_faces_sommets_locaux(IntTab &faces_som_local) const override=0
Fills faces_som_local(i,j) giving for 0 <= i < nb_faces() and 0 <= j < nb_som_face(i) the local verte...
Class Polyedre: represents the Polyedre geometric element.
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:428
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:197
static double mp_min(double)
Definition Process.cpp:391
static double mp_max(double)
Definition Process.cpp:379
static bool is_parallel()
Definition Process.cpp:108
static Sortie & Journal(int message_level=0)
Returns a static Sortie object used as an event journal.
Definition Process.cpp:592
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static double mp_sum(double)
Computes the sum of x over all processors in the current group.
Definition Process.cpp:145
static double mp_sum_as_double(int v)
Definition Process.h:97
static void barrier()
Synchronizes all processors in the current group (waits until all processors have reached the barrier...
Definition Process.cpp:133
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
static void mp_min_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:200
static bool is_sequential()
Definition Process.cpp:113
void associer_domaine(const Domaine_t &)
Associates a domain with all connectors in the list.
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:2739
static void construire_espace_virtuel_traduction(const MD_Vector &md_indice, const MD_Vector &md_valeur, IntTab &tableau, const int error_is_fatal=1)
Builds the items_communs + virtual space structure of an array containing indices of geometric items,...
Definition Scatter.cpp:1621
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
Method used by interpreters that modify the domain (sequential), destroys the descriptors of vertices...
Definition Scatter.cpp:2754
void echange_taille_et_messages() const
Launches the data exchange between all processors.
Sortie & send_buffer(int num_PE) const
Returns the buffer corresponding to processor num_PE to stack data to send.
void end_comm() const
Clears the buffers and releases resources: reading of received data from buffers is complete.
Entree & recv_buffer(int num_PE) const
Returns the buffer corresponding to processor num_PE to read received data.
void begin_comm() const
Reserves communication buffers for a new communication.
void set_send_recv_pe_list(const ArrOfInt &send_pe_list, const ArrOfInt &recv_pe_list, const int me_to_me=0)
Defines the list of processors to send data to and receive data from.
Base class for output streams.
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")