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());
classe Domaine_32_64 un Domaine est un maillage compose d'un ensemble d'elements geometriques de meme...
DoubleTab_t & les_sommets()
const Frontiere_t & frontiere(int i) const
const DoubleTab_t & coord_sommets() const
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
const IntTab_t & les_sommets() const
Renvoie le tableau des sommets de toutes les faces.
const Domaine_t & domaine() const
Renvoie le domaine associe a la frontiere.
const Nom & le_nom() const override
Donne le nom de l'Objet_U Methode a surcharger : renvoie "neant" dans cette implementation.
IntTab_t & les_sommets_des_faces()
Renvoie les sommets des faces de la frontiere.
const Faces_t & faces() const
Domaine_t & domaine(int i=0)
: Cette classe est un OWN_PTR mais l'objet pointe est partage entre plusieurs
class Nom Une chaine de caractere pour nommer les objets de TRUST
Un tableau de chaine de caracteres (VECT(Nom)).
static double precision_geom
: Un octree permettant de chercher dans l'espace des elements ou des points decrits par des coordonne...
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
static bool is_parallel()
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
static int me()
renvoie mon rang dans le groupe de communication courant.
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Cet interprete permet de reordonner les faces d'un bord periodique selon la convention utilisee dans ...
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)
Reordonne le tableau "faces" selon la convention des faces periodiques: D'abord les faces d'une extre...
static int check_faces_periodiques(const Frontiere_32_64< _SIZE_ > &frontiere, ArrOfDouble &vecteur_delta, ArrOfDouble &erreur, bool verbose=false)
essaie de verifier si les faces du bord num_bord sont ordonnees suivant la convention des faces perio...
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)
Construit la structure items_communs + espaces virtuels d'un tableau contenant des indices d'items ge...
_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