15#include <MaillerParallel.h>
20#include <TRUSTArrays.h>
22#include <Reordonner_faces_periodiques.h>
24#include <Schema_Comm.h>
25#include <Octree_Double.h>
26#include <Faces_builder.h>
27#include <Connectivite_som_elem.h>
28#include <Static_Int_Lists.h>
29#include <communications.h>
31#include <Array_tools.h>
34#include <Perf_counters.h>
54 void add_bloc(Domaine& domaine,
const ArrsOfDouble& coord_ijk)
const;
70 void add_faces(Domaine& domaine,
const Nom& nombord,
int offset_sommets,
int dir,
int cote_max)
const;
77 Cerr <<
"Error : not enough nodes in a block, increase mesh size or decrease processor count" << finl;
82 const int old_nb_som = domaine.les_sommets().dimension(0);
84 DoubleTab& sommets = domaine.les_sommets();
86 sommets.
resize(old_nb_som + nsom, dim);
88 int index = old_nb_som;
96 sommets(index, 0) = coord_ijk[0][i];
97 sommets(index, 1) = coord_ijk[1][j];
99 sommets(index, 2) = coord_ijk[2][k];
108 IntTab& elements = domaine.les_elems();
109 const int nb_som_par_element = 8;
114 const int dz = dy *
nb_som(1);
119 const int nb_elem_old = domaine.les_elems().dimension(0);
120 const int nbelem = nx * ny * nz;
121 elements.
resize(nb_elem_old + nbelem, nb_som_par_element);
123 int index = nb_elem_old;
125 for (k = 0; k < nz; k++)
127 for (j = 0; j < ny; j++)
129 for (i = 0; i < nx; i++)
131 int n = old_nb_som + k * dz + j * dy + i * dx;
132 elements(index, 0) = n;
133 elements(index, 1) = n + dx;
134 elements(index, 2) = n + dy;
135 elements(index, 3) = n + dx + dy;
136 elements(index, 4) = n + dz;
137 elements(index, 5) = n + dz + dx;
138 elements(index, 6) = n + dz + dy;
139 elements(index, 7) = n + dz + dx + dy;
146 for (
int dir = 0; dir < 3; dir++)
157 int nfaces1, nfaces2;
158 int increment1, increment2;
174 increment_dir =
nb_som(0);
185 offset_sommets += increment_dir * (
nb_som(dir)-1);
187 IntTab& faces = domaine.frontiere(nombord).faces().les_sommets();
188 int count = faces.dimension(0);
189 domaine.frontiere(nombord).faces().dimensionner(count + nfaces1 * nfaces2);
190 for (
int i = 0; i < nfaces2; i++)
192 int sommet = offset_sommets;
193 for (
int j = 0; j < nfaces1; j++)
195 faces(count, 0) = sommet;
196 faces(count, 1) = sommet + increment1;
197 faces(count, 2) = sommet + increment2;
198 faces(count, 3) = sommet + increment1 + increment2;
199 sommet += increment1;
202 offset_sommets += increment2;
206static int bbox_intersection(
const DoubleTab& bboxes,
int i,
int j,
double epsilon)
209 for (
int k = 0; k < dim; k++)
211 double min1 = bboxes(i, k) - epsilon;
212 double max1 = bboxes(i, dim+k) + epsilon;
213 double min2 = bboxes(j, k);
214 double max2 = bboxes(j, dim+k);
215 if (min1 > max2 || max1 < min2)
229void find_matching_coordinates(
const DoubleTab& coords,
239 DoubleTab bounding_boxes(nproc, dim*2);
241 const double big_val = 1.e36;
242 ArrOfDouble min_coord(dim);
244 ArrOfDouble max_coord(dim);
247 for (i = 0; i < ncoord; i++)
249 for (j = 0; j < dim; j++)
251 const double x = coords(i, j);
252 if (x > max_coord[j])
254 if (x < min_coord[j])
259 for (i = 0; i < nproc; i++)
261 for (j = 0; j < dim; j++)
263 bounding_boxes(i, j) = min_coord[j];
264 bounding_boxes(i, j+dim) = max_coord[j];
267 envoyer_all_to_all(bounding_boxes, bounding_boxes);
272 for (i = 0; i < nproc; i++)
273 if (i != moi && bbox_intersection(bounding_boxes, moi, i, epsilon))
279 Octree_Double octree;
287 for (ipe = 0; ipe < all_pe.
size_array(); ipe++)
290 const int pe = all_pe[ipe];
291 const double xmin = bounding_boxes(pe, 0) - epsilon;
292 const double ymin = bounding_boxes(pe, 1) - epsilon;
293 const double zmin = (dim == 3) ? bounding_boxes(pe, 2) - epsilon : -epsilon;
294 const double xmax = bounding_boxes(pe, dim) + epsilon;
295 const double ymax = bounding_boxes(pe, dim+1) + epsilon;
296 const double zmax = (dim == 3) ? bounding_boxes(pe, dim+2) + epsilon : epsilon;
301 for (i = 0; i < n; i++)
303 const int som = nodes_list[i];
304 const double x = coords(som, 0);
305 const double y = coords(som, 1);
306 const double z = (dim==3) ? coords(som, 2) : 0;
308 if (x>=xmin && x<=xmax && y>=ymin && y<=ymax && z>=zmin && z<=zmax)
310 buffer << x << y << z;
315 for (ipe = 0; ipe < all_pe.
size_array(); ipe++)
317 const int pe = all_pe[ipe];
319 ArrOfInt& resu = match[pe];
325 buffer >> x >> y >> z;
330 x+epsilon, y+epsilon, z+epsilon, nodes_list);
336 Cerr <<
"Error in automatic joint builder: more than one node within epsilon tolerance\n"
337 <<
" node coord = " << x <<
" " << y <<
" " << z <<
" tolerance= " << epsilon << finl;
354static void find_joint_faces(
const Domaine& domaine, IntTab& faces)
356 Static_Int_Lists som_elem;
357 const IntTab& elements = domaine.les_elems();
358 const int nb_som = domaine.nb_som();
359 construire_connectivite_som_elem(nb_som, elements, som_elem, 0 );
360 const int nb_som_faces = domaine.type_elem()->nb_som_face();
361 faces.
resize(0, nb_som_faces);
363 IntTab faces_element_reference;
364 domaine.type_elem()->get_tab_faces_sommets_locaux(faces_element_reference);
365 const int nb_faces_elem = faces_element_reference.
dimension(0);
367 const int nb_elem = elements.
dimension(0);
368 ArrOfBit boundary_faces(nb_elem * nb_faces_elem);
370 ArrOfInt une_face(nb_som_faces);
371 ArrOfInt liste_elements;
373 const int nb_boundaries = domaine.nb_front_Cl();
374 for (
int i_boundary = 0; i_boundary < nb_boundaries; i_boundary++)
376 const IntTab& faces_front = domaine.frontiere(i_boundary).faces().les_sommets();
377 const int nb_faces_bord = faces_front.
dimension(0);
378 for (
int j = 0; j < nb_faces_bord; j++)
380 for (
int k = 0; k < nb_som_faces; k++)
381 une_face[k] = faces_front(j, k);
382 find_adjacent_elements(som_elem, une_face, liste_elements);
385 Cerr <<
"Error in MaillerParallel::find_joint_faces: boundary face ArrOfInt=" << une_face
386 <<
" does not have exactly 1 neighbour element: " << liste_elements;
389 const int elem = liste_elements[0];
391 boundary_faces.setbit(elem * nb_faces_elem + face_locale);
395 for (
int elem = 0; elem < nb_elem; elem++)
397 for (
int face_locale = 0; face_locale < nb_faces_elem; face_locale++)
399 if (boundary_faces[elem * nb_faces_elem + face_locale])
402 for (i = 0; i < nb_som_faces; i++)
404 const int sommet_local = faces_element_reference(face_locale, i);
405 une_face[i] = elements(elem, sommet_local);
407 find_adjacent_elements(som_elem, une_face, liste_elements);
412 for (i = 0; i < nb_som_faces; i++)
413 faces(n, i) = une_face[i];
417 Process::Journal() <<
"Domain " << domaine.le_nom() <<
" has " << faces.
dimension(0) <<
" undeclared boundary faces candidates for joint faces" << finl;
420static void auto_build_joints(Domaine& domaine,
const int epaisseur_joint)
422 const double epsilon = 1e-10;
426 find_joint_faces(domaine, faces);
428 const DoubleTab& sommets = domaine.les_sommets();
433 ArrOfInt boundary_nodes_index;
434 boundary_nodes_index = faces;
435 array_trier_retirer_doublons(boundary_nodes_index);
436 const int ncoord = boundary_nodes_index.
size_array();
439 coord.
resize(ncoord, dim, RESIZE_OPTIONS::NOCOPY_NOINIT);
440 for (i = 0; i < ncoord; i++)
442 const int som = boundary_nodes_index[i];
443 for (j = 0; j < dim; j++)
444 coord(i, j) = sommets(som, j);
447 find_matching_coordinates(coord, match, epsilon);
449 for (
int pe = 0; pe < match.
size(); pe++)
451 const ArrOfInt& list = match[pe];
455 Joint& joint = domaine.faces_joint().add(Joint());
460 joint.
faces().
typer(domaine.type_elem()->type_face());
462 sommets_joint.
resize_array(n, RESIZE_OPTIONS::NOCOPY_NOINIT);
463 for (i = 0; i < n; i++)
464 sommets_joint[i] = boundary_nodes_index[list[i]];
466 Process::Journal() <<
"Joint sommets with pe " << pe <<
" has " << n <<
" nodes" << finl;
474 const int nb_som_faces = faces.
dimension(1);
475 DoubleTab coord(nfaces, dim);
476 const double facteur = 1. / (double)nb_som_faces;
477 for (i = 0; i < nfaces; i++)
479 for (j = 0; j < nb_som_faces; j++)
481 const int som = faces(i,j);
482 for (
int k = 0; k < dim; k++)
483 coord(i, k) += sommets(som, k) * facteur;
487 find_matching_coordinates(coord, match, epsilon);
489 for (
int pe = 0; pe < match.
size(); pe++)
491 const ArrOfInt& list = match[pe];
495 OBS_PTR(Joint) ref_joint;
497 for (ii = 0; ii < domaine.faces_joint().size(); ii++)
499 Joint& joint = domaine.faces_joint()[ii];
508 Joint& joint = domaine.faces_joint().
add(Joint());
513 joint.
faces().
typer(domaine.type_elem()->type_face());
516 Faces& les_faces = ref_joint->faces();
519 for (ii = 0; ii < n; ii++)
521 const int num_face = list[ii];
522 for (j = 0; j < nb_som_faces; j++)
523 faces_sommets(ii, j) = faces(num_face, j);
525 Process::Journal() <<
"Joint faces with pe " << pe <<
" has " << n <<
" faces" << finl;
537 Cerr <<
"Error: MaillerParallel is only coded for dimension 3" << finl;
545 int epaisseur_joint = -1;
546 bool perio[3] = {
false,
false,
false};
547 Noms fonctions_coord(3);
548 Noms nom_bords_min(3);
549 Noms nom_bords_max(3);
550 nom_bords_min[0] =
"xmin";
551 nom_bords_min[1] =
"ymin";
552 nom_bords_min[2] =
"zmin";
553 nom_bords_max[0] =
"xmax";
554 nom_bords_max[1] =
"ymax";
555 nom_bords_max[2] =
"zmax";
556 Noms fichier_coord(3);
579 param.
ajouter(
"function_coord_x", &fonctions_coord[0]);
583 param.
ajouter(
"function_coord_y", &fonctions_coord[1]);
585 param.
ajouter(
"function_coord_z", &fonctions_coord[2]);
587 param.
ajouter(
"file_coord_x", &fichier_coord[0]);
589 param.
ajouter(
"file_coord_y", &fichier_coord[1]);
591 param.
ajouter(
"file_coord_z", &fichier_coord[2]);
593 param.
ajouter(
"boundary_xmin", &nom_bords_min[0]);
597 param.
ajouter(
"boundary_xmax", &nom_bords_max[0]);
599 param.
ajouter(
"boundary_ymin", &nom_bords_min[1]);
601 param.
ajouter(
"boundary_ymax", &nom_bords_max[1]);
603 param.
ajouter(
"boundary_zmin", &nom_bords_min[2]);
605 param.
ajouter(
"boundary_zmax", &nom_bords_max[2]);
607 param.
ajouter(
"mapping", &mapping);
611 ArrsOfDouble coord_ijk(3);
612 for (
int dir=0; dir<3; dir++)
614 const int n = nb_noeuds[dir];
615 ArrOfDouble& coord = coord_ijk[dir];
617 Cerr <<
"Building coordinates for direction " << dir << finl;
618 if (fonctions_coord[dir] !=
"??")
620 Nom chaine = fonctions_coord[dir];
621 Cerr <<
" Interpreting expression " << chaine << finl;
631 for (
int i = 0; i < n; i++)
633 p.
setVar(0, (
double) i / (
double) (nb_noeuds[dir]-1));
635 if (i > 0 && coord[i] <= coord[i-1])
637 Cerr <<
"Error in fonctions_coord parameter " << chaine <<
" : must be strictly increasing" << finl;
641 Cerr <<
" Build mesh covering [ " << coord[0] <<
" , " << coord[n-1] <<
" ]" << finl;
643 else if (fichier_coord[dir] !=
"??")
645 Cerr <<
" Reading file " << fichier_coord[dir] << finl;
649 for (
int i = 0; i < n; i++)
652 envoyer_broadcast(coord, 0);
653 Cerr <<
" Found mesh covering [ " << coord[0] <<
" , " << coord[n-1] <<
" ]" << finl;
657 Cerr <<
" Uniform mesh covering [0,1]" << finl;
658 for (
int i = 0; i < n; i++)
660 coord[i] = (double) i / (
double)(n-1);
666 if(!sub_type(Domaine, obj))
668 Cerr <<
"obj : " << nom_domaine <<
" is not an object of type Domaine !" << finl;
672 Domaine& domaine = ref_cast(Domaine, obj);
679 Cerr <<
"MaillerParallel::construire_domaine wrong dimension for nb_noeuds : nb_noeuds=" << nb_noeuds << finl;
686 Cerr <<
"MaillerParallel::construire_domaine wrong dimension for nb_noeuds : nb_noeuds=" << nb_noeuds << finl;
693 for (
int i = 0; i < dim; i++)
697 Cerr <<
"MaillerParallel::construire_domaine decoupage does not match nproc" << finl;
702 statistics().begin_count(STD_COUNTERS::parallel_meshing,statistics().get_last_opened_counter_level()+1);
704 ArrOfInt i_proc(dim);
711 for (i = 0; i < dim; i++)
714 const int n_parties = decoupage[i];
716 i_proc[i] = reste % n_parties;
717 reste = reste / n_parties;
724 Cerr <<
"Error: processor mapping should be of dimension " <<
Process::nproc() <<
" x 3" << finl;
727 i_proc[0] = mapping(numproc,0);
728 i_proc[1] = mapping(numproc,1);
729 i_proc[2] = mapping(numproc,2);
733 ArrOfInt i_premier_element(dim);
735 ArrOfInt nb_elements(dim);
738 for (i = 0; i < dim; i++)
740 const int nb_elem_tot = nb_noeuds[i] - 1;
741 i_premier_element[i] = nb_elem_tot * i_proc[i] / decoupage[i];
742 const int i_dernier_element = nb_elem_tot * (i_proc[i] + 1) / decoupage[i] - 1;
743 nb_elements[i] = i_dernier_element - i_premier_element[i] + 1;
745 if (perio[i] && decoupage[i] > 1)
747 int decalage = nb_elem_tot / decoupage[i] / 2;
748 i_premier_element[i] -= decalage;
753 Elem_geom& elem = domaine.type_elem();
757 elem.typer(
"Hexaedre");
760 Cerr <<
"MaillerParallel::construire_domaine error" << finl;
763 elem->associer_domaine(domaine);
766 Bords& bords = domaine.faces_bord();
769 for (
int dir = 0; dir < 3; dir++)
772 if (dir == 0) nomdir =
"x";
773 else if (dir == 1) nomdir =
"y";
779 bords.add(Bord()).nommer(data.
bord_xmin_[dir]);
781 domaine.bords_perio().add(data.
bord_xmin_[dir]);
785 bords.add(Bord()).nommer(data.
bord_xmin_[dir]);
786 bords.add(Bord()).nommer(data.
bord_xmax_[dir]);
793 for (
int i = 0; i < 3; i++)
795 if (i_premier_element[i] < 0)
800 for (num_bord = 0; num_bord < bords.size(); num_bord++)
802 Bord& bord = bords[num_bord];
804 bord.
faces().
typer(domaine.type_elem()->type_face());
810 for (ibloc[0] = 0; ibloc[0] < nblocs[0]; ibloc[0]++)
812 for (ibloc[1] = 0; ibloc[1] < nblocs[1]; ibloc[1]++)
814 for (ibloc[2] = 0; ibloc[2] < nblocs[2]; ibloc[2]++)
819 for (
int dir = 0; dir < 3; dir++)
821 data.
xmin_[dir] = i_premier_element[dir];
822 data.
xmax_[dir] = i_premier_element[dir] + nb_elements[dir] + 1;
842 for (
int d = 0; d < 3; d++)
847 dir[d] = coord_ijk[d][nb_noeuds[d]-1] - coord_ijk[d][0];
848 IntTab& faces = domaine.bord(nom_bords_min[d]).faces().les_sommets();
856 auto_build_joints(domaine, epaisseur_joint);
858 double maxtime =
mp_max(statistics().get_time_since_last_open(STD_COUNTERS::parallel_meshing));
859 statistics().end_count(STD_COUNTERS::parallel_meshing);
861 Cerr <<
"Ending of the construction of the domaines, time:" << maxtime << finl;
865 statistics().begin_count(STD_COUNTERS::parallel_meshing,statistics().get_last_opened_counter_level()+1);
868 maxtime =
mp_max(statistics().get_time_since_last_open(STD_COUNTERS::parallel_meshing));
869 statistics().end_count(STD_COUNTERS::parallel_meshing);
870 Cerr <<
"Scatter::construire_correspondance_sommets_par_coordonnees fin, time:"
872 statistics().begin_count(STD_COUNTERS::parallel_meshing,statistics().get_last_opened_counter_level()+1);
875 maxtime =
mp_max(statistics().get_time_since_last_open(STD_COUNTERS::parallel_meshing));
876 statistics().end_count(STD_COUNTERS::parallel_meshing);
877 Cerr <<
"Scatter::construire_structures_paralleles, time:" << maxtime << finl;
884 domaine.nommer(domaine.le_nom());
886 Cerr <<
"MaillerParallel::construire_domaine : end" << finl;
File for reading. This class is to the C++ ifstream class what the Entree class is to the.
Class defining operators and methods for all reading operation in an input flow (file,...
void typer(const Motcle &)
Sets the type of the faces.
int_t dimensionner(int_t)
(Re-)sizes the faces. The neighbors are resized accordingly.
const IntTab_t & les_sommets() const
Returns the array of vertices of all faces.
static int chercher_face_element(const IntTab_t &elem_som, const IntTab &faces_element_ref, const SmallArrOfTID_t &une_face, const int_t elem)
void nommer(const Nom &) override
Gives a name to the boundary.
void associer_domaine(const Domaine_t &)
Associates the boundary to the domain it belongs to.
const Faces_t & faces() const
void add(const Frontiere_32_64 &)
Adds the vertices (and faces) of the given boundary to this object (Frontiere_32_64).
Base class for "interpreter" objects.
static Objet_U & objet(const Nom &)
See Interprete_bloc::objet_global(). BM: the Interprete class is not the best place for this.
void affecte_epaisseur(int ep)
void affecte_PEvoisin(int num)
Joint_Items_t & set_joint_item(JOINT_ITEM type)
Returns the joint information for a given geometric item type, for filling the structures.
ArrOfInt_t & set_items_communs()
Returns the items_communs_ array for filling.
Entree & interpreter(Entree &is) override
class Nom: a character string for naming TRUST objects.
An array of character strings (VECT(Nom)).
const Nom & que_suis_je() const
Returns the string identifying the class.
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
static double precision_geom
Objet_U()
Default constructor: assigns a unique identifier to the object (object_id_) and registers the object ...
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
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.
Helper class to factorize the readOn method of Objet_U classes.
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
int lire_avec_accolades(Entree &is)
Alias of lire_avec_accolades_depuis.
class Parser_U Version of the Parser class, deriving from Objet_U.
void setVar(const char *sv, double val)
void setString(const std::string &s)
void addVar(const char *v)
static double mp_max(double)
static Sortie & Journal(int message_level=0)
Returns a static Sortie object used as an event journal.
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
static void barrier()
Synchronizes all processors in the current group (waits until all processors have reached the barrier...
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
static int je_suis_maitre()
Returns 1 if on the master processor of the current group (i.e. me() == 0), 0 otherwise.
static int reordonner_faces_periodiques(const Domaine_32_64< int > &domaine, IntTab_T< int > &faces, const ArrOfDouble &direction_perio, const double epsilon)
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...
static void construire_structures_paralleles(Domaine &dom)
Builds the parallel structures of the domain (determination of distant elements as a function of join...
static void calculer_renum_items_communs(Joints &joints, const JOINT_ITEM type_item)
Assumes that each joint[i].joint_item(type_item).items_communs() contains the local indices of common...
static void construire_correspondance_sommets_par_coordonnees(Domaine &dom, bool allow_resize=false)
Builds the joint_item(JOINT_ITEM::SOMMET).items_communs arrays for all joints of the domain dom.
static void trier_les_joints(Joints &joints)
Sort joints by increasing neighbor proc number.
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.
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
void resize_dim0(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension(int d) const
void add_faces(Domaine &domaine, const Nom &nombord, int offset_sommets, int dir, int cote_max) const
void add_bloc(Domaine &domaine, const ArrsOfDouble &coord_ijk) const