15#include <Reordonner_faces_periodiques.h>
18#include <Octree_Double.h>
25 Cerr <<
"You need to use the Declarer_bord_perio keyword on the periodic boundaries." << finl;
26 Cerr <<
"See the reference manual to use this keyword on your data file." << finl;
29template <
typename _SIZE_>
30inline void calculer_vecteur_2faces(
const DoubleTab_T<_SIZE_>& coord,
31 const IntTab_T<_SIZE_>& faces,
41 for (
int j = 0; j < nb_som_faces; j++)
43 const _SIZE_ sommet1 = faces(i_face1, j),
44 sommet2 = faces(i_face2, j);
45 for (
int compo = 0; compo < dim; compo++)
46 vect[compo] += coord(sommet2, compo) - coord(sommet1, compo);
52template <
typename _SIZE_>
53double local_norme_vect(
const DoubleVect_T<_SIZE_>& dv)
63template <
typename _SIZE_>
70 const MD_Vector& md_sommets = domaine.les_sommets().get_md_vector();
78 Cerr <<
"Reordonner_faces_periodiques::renum_som_perio() was invoked from a parallel environment with" << finl;
79 Cerr <<
"a 64b object. Did you use 'Domaine_64' keyword instead of 'Domaine' after a Scatter keyword??" << finl;
86template<
typename _SIZE_>
89 using DoubleTab_t = DoubleTab_T<_SIZE_>;
90 using IntTab_t = IntTab_T<_SIZE_>;
91 using ArrOfDouble_t = ArrOfDouble_T<_SIZE_>;
95 const int dim =
static_cast<int>(sommets.dimension(1));
98 const Frontiere_t& front = dom.
frontiere(bord);
99 const int_t nb_faces = front.nb_faces();
102 const IntTab_t& faces = front.faces().les_sommets();
103 const int nb_som_face =
static_cast<int>(faces.dimension(1));
104 DoubleTab_t normale(1, dim);
105 IntTab_t une_face(1, nb_som_face);
106 for (
int i = 0; i < nb_som_face; i++)
107 une_face(0, i) = faces(0, i);
108 dom.type_elem()->calculer_normales(une_face, normale);
109 normale /= local_norme_vect<_SIZE_>(normale);
111 ArrOfDouble_t delta(nb_faces);
112 ArrOfDouble vect(dim);
113 for (
int_t i = 1; i < nb_faces; i++)
115 calculer_vecteur_2faces<_SIZE_>(sommets, faces, 0, i, vect);
117 for (
int j = 0; j < dim; j++)
118 x += vect[j] * normale(0,j);
121 const double min = min_array(delta);
122 const double max = max_array(delta);
123 double facteur = (std::fabs(min) > std::fabs(max)) ? min : max;
124 for (
int i = 0; i < dim; i++)
125 direction_perio[i] = normale(0, i) * facteur;
126 Cerr <<
"Periodicity direction for " << dom.
le_nom() <<
"/" << bord <<
" " << direction_perio;
137template<
typename _SIZE_>
139 IntTab_T<_SIZE_>& faces,
140 const ArrOfDouble& direction_perio,
141 const double epsilon)
146 using IntTab_t = IntTab_T<_SIZE_>;
147 using DoubleTab_t = DoubleTab_T<_SIZE_>;
148 using ArrOfInt_t = ArrOfInt_T<_SIZE_>;
152 const int nb_som_faces =
static_cast<int>(faces.
dimension(1));
155 DoubleTab_t centres(nb_faces, 3);
157 const DoubleTab_t& coord =
domaine.les_sommets();
158 const double inv_nb_som = 1. / (double) nb_som_faces;
159 for (
int_t i = 0; i < nb_faces; i++)
161 for (
int j = 0; j < nb_som_faces; j++)
163 const int_t sommet = faces(i, j);
164 for (
int k = 0; k < dim; k++)
165 centres(i, k) += coord(sommet, k) * inv_nb_som;
171 Octree_Double_t octree;
172 octree.build_nodes(centres, 0 );
178 ArrOfInt_t renum_faces(nb_faces);
180 ArrOfInt_t nodes_list;
182 ArrOfDouble coord(dim);
184 for (
int_t i_face = 0; i_face < nb_faces; i_face++)
186 if (renum_faces[i_face] >= 0)
191 for (facteur = -1.; facteur < 1.5; facteur += 2.)
193 for (
int i = 0; i < dim; i++)
194 coord[i] = centres(i_face, i) + facteur * direction_perio[i];
195 octree.search_elements_box(coord, epsilon, nodes_list);
196 i_face2 = octree.search_nodes_close_to(coord, centres, nodes_list, epsilon);
202 if (renum_faces[i_face2] >= 0)
204 Cerr <<
"====================================================" << finl;
205 Cerr <<
"Error in reordonner_faces_periodiques: the face " << i_face
206 <<
" of " << centres(i_face,0) <<
" " << centres(i_face,1) <<
" "
207 << ((dim==3)?centres(i_face,2):0.)
208 <<
" center already has a face twin."
210 Cerr <<
"Possible problem: the boundary is not periodic. Check your mesh." << finl;
213 int_t f0 = (facteur > 0.) ? i_face : i_face2;
214 int_t f1 = (facteur > 0.) ? i_face2: i_face;
215 renum_faces[f0] = count;
216 renum_faces[f1] = count + nb_faces / 2;
221 Cerr <<
"====================================================" << finl;
222 Cerr <<
"Error in reordonner_faces_periodiques: the face " << i_face <<
" of " << centres(i_face,0) <<
" " << centres(i_face,1) <<
" "
223 << ((dim==3)?centres(i_face,2):0.) << finl;
224 Cerr <<
"center has no face twin into the specified direction in the list of faces." << finl;
229 const IntTab_t oldfaces(faces);
230 for (
int_t i = 0; i < nb_faces; i++)
232 const int_t new_i = renum_faces[i];
233 for (
int j = 0; j < nb_som_faces; j++)
234 faces(new_i, j) = oldfaces(i, j);
248template <
typename _SIZE_>
250 ArrOfDouble& vecteur_delta, ArrOfDouble& erreur,
253 using IntTab_t = IntTab_T<_SIZE_>;
254 using DoubleTab_t = DoubleTab_T<_SIZE_>;
263 Cerr <<
"Check periodic faces to the boundary : " << frontiere.
le_nom() << finl;
266 const int_t nb_faces = faces.dimension(0);
267 if (nb_faces % 2 != 0)
269 Cerr <<
"Error in Check_faces_periodiques to the boundary " << frontiere.
le_nom()
270 <<
"\n The number of faces is odd : " << nb_faces << finl;
271 Cerr <<
"You probably forgot to define periodicity on some boundaries during partition:" << finl;
272 Cerr <<
"Partition domain { ... periodique 1 " << frontiere.
le_nom() <<
" }" << finl;
273 Process::Process::exit();
275 const int_t n = nb_faces / 2;
280 vecteur_delta = -1.e37;
282 calculer_vecteur_2faces<_SIZE_>(coord, faces, 0, n, vecteur_delta);
286 ArrOfDouble vect(dim);
287 for (i = 0; i < n; i++)
289 calculer_vecteur_2faces<_SIZE_>(coord, faces, i, i+n, vect);
291 for (
int compo = 0; compo < dim; compo++)
292 erreur[compo] = std::max(erreur[compo], std::fabs(vecteur_delta[compo] - vect[compo]));
297 for (i = 0; i < dim; i++)
298 maxerr = std::max(maxerr, erreur[i]);
302 Cerr <<
" Delta vector = [ ";
303 for (i = 0; i < dim; i++) Cerr << vecteur_delta[i] <<
" ";
304 Cerr <<
"] error = [ ";
305 for (i = 0; i < dim; i++) Cerr << erreur[i] <<
" ";
312 Cerr <<
" This boundary is not detected as periodic (geometric error > precision_geom)" << finl;
314 if (
Process::is_parallel()) Cerr <<
"Or you forgot to define the periodic boundary in the Decouper keyword." << finl;
322template<
typename _SIZE_>
326 using IntTab_t = IntTab_T<_SIZE_>;
327 using DoubleTab_t = DoubleTab_T<_SIZE_>;
329 const Noms& liste_bords_periodiques =
domaine.bords_perio();
331 IntTab_t renum(nb_som);
332 for (
int_t i = 0; i < nb_som; i++)
335 const DoubleTab_t& coord =
domaine.coord_sommets();
336 const int dim = coord.dimension_int(1);
340 for (
auto& itr : liste_bords_periodiques)
342 const Nom& nom_bord = itr;
353 const int_t nb_faces = faces_sommets.dimension(0) / 2;
355 for (
int_t i_face = 0; i_face < nb_faces; i_face++)
357 for (
int i_som = 0; i_som < nb_som_face; i_som++)
359 const int_t sommet = faces_sommets(i_face, i_som);
366 const int_t i_face_opposee = i_face + nb_faces;
367 int_t sommet_opp = -1;
369 for (; i_som_opp < nb_som_face; i_som_opp++)
371 sommet_opp = faces_sommets(i_face_opposee, i_som_opp);
375 double epsilon = std::fabs((coord(sommet_opp, i) - coord(sommet, i)) - delta[i]);
382 if (i_som_opp >= nb_som_face)
384 Cerr <<
"[PE" <<
Process::me() <<
"] Error in Reordonner_faces_periodiques::renum_som_perio\n"
385 <<
" An opposite node has not been found\n"
386 <<
" Boundary " << nom_bord <<
"\n Face 1: " << i_face <<
"\n Node: " << sommet << finl;
387 Cerr <<
" May be you should define the periodic boundary " << nom_bord << finl;
391 renum[sommet_opp] = sommet;
398 for (
int_t i = 0; i < nb_som; i++)
402 while (j != renum[j])
409 ::build_trad_space(
domaine, renum);
412 assert(renum.dimension_tot(0) ==
domaine.nb_som_tot());
class Domaine_32_64 A Domain is a mesh composed of a set of geometric elements of the same type.
DoubleTab_t & les_sommets()
const Frontiere_t & frontiere(int i) const
const DoubleTab_t & coord_sommets() const
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
const IntTab_t & les_sommets() const
Returns the array of vertices of all faces.
const Domaine_t & domaine() const
Returns the domain associated with the boundary (const version).
const Nom & le_nom() const override
Returns the name of the Objet_U. Virtual method to override: returns "neant" in this implementation.
IntTab_t & les_sommets_des_faces()
Returns the vertices of the boundary faces.
const Faces_t & faces() const
Domaine_t & domaine(int i=0)
: This class is an OWN_PTR but the pointed object is shared among multiple
class Nom: a character string for naming TRUST objects.
An array of character strings (VECT(Nom)).
static double precision_geom
: An octree allowing to search in space for elements or points described by real-valued coordinates.
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
static bool is_parallel()
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.
This interpreter reorders the faces of a periodic boundary according to the convention used in the pa...
static void chercher_direction_perio(ArrOfDouble &direction_perio, const Domaine_32_64< _SIZE_ > &dom, const Nom &bord)
static int reordonner_faces_periodiques(const Domaine_32_64< _SIZE_ > &domaine, IntTab_T< _SIZE_ > &faces, const ArrOfDouble &direction_perio, const double epsilon)
Reorders the "faces" array according to the periodic face convention: First the faces of one end,...
static int check_faces_periodiques(const Frontiere_32_64< _SIZE_ > &frontiere, ArrOfDouble &vecteur_delta, ArrOfDouble &erreur, bool verbose=false)
Tries to verify whether the faces on boundary num_bord are ordered according to the periodic face con...
static void renum_som_perio(const Domaine_32_64< _SIZE_ > &dom, ArrOfInt_T< _SIZE_ > &renum_som_perio, bool calculer_espace_virtuel)
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,...
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int dimension_int(int d) const
_SIZE_ dimension(int d) const
_SIZE_ size_reelle() const