16#include <Reorder_Mesh.h>
36constexpr unsigned int NB_BITS_2D = 32;
39constexpr unsigned int NB_BITS_3D = 21;
42constexpr uint32_t MAX_VAL_2D = std::numeric_limits<uint32_t>::max();
43constexpr uint32_t MAX_VAL_3D = (1 << NB_BITS_3D) - 1;
46using cube_pos_t = std::array<int8_t, 3>;
47using ar8_t = std::array<uint8_t, 8>;
48const ar8_t unit_hilbert = { 0,7,3,4,1,6,2,5 };
59uint64_t mortonCode(uint32_t x, uint32_t y, uint32_t z)
62 uint64_t xx=x, yy=y, zz=z;
64 for (
unsigned i = 0; i < ::NB_BITS_2D; i++)
66 result |= (xx & (1ULL << i)) << i;
67 result |= (yy & (1ULL << i)) << (i+1);
70 for (
unsigned i = 0; i < ::NB_BITS_3D; i++)
72 result |= (xx & (1ULL << i)) << (2*i);
73 result |= (yy & (1ULL << i)) << (2*i+1);
74 result |= (zz & (1ULL << i)) << (2*i+2);
85uint64_t hilbertCode_2D(uint32_t x, uint32_t y)
90 uint64_t mort = mortonCode(x,y,0.0);
92 const uint8_t ud[4] = {0, 3, 1, 2};
93 const uint8_t rl[4] = {3, 2, 0, 1};
94 unsigned int orient = 0;
96 for(
int i = NB_BITS_2D-1; i >= 0; i--)
99 uint64_t two_bits = (mort >> (2*i)) & 0b11;
100 uint8_t new_two_bits = 0b00;
104 new_two_bits = ud[two_bits];
107 new_two_bits = rl[two_bits];
110 new_two_bits = ud[3-two_bits];
113 new_two_bits = rl[3-two_bits];
118 result |= flip ? (0b11 - new_two_bits) : new_two_bits;
120 if (new_two_bits == 0b00) { orient = (orient+1) % 4; flip = !flip; }
121 if (new_two_bits == 0b11) { orient = (orient+3) % 4; flip = !flip; }
169uint64_t hilbertCode_3D(uint32_t x, uint32_t y, uint32_t z)
172 uint64_t mort = mortonCode(x,y,z);
175 auto compose = [](
const cube_pos_t& p1,
const cube_pos_t& p2) -> cube_pos_t
178 for (
int i = 0; i < 3; i++)
180 uint8_t idx = (uint8_t)(std::abs(p1[i])-1);
181 int8_t sig = p1[i] > 0 ? 1 : -1;
182 res[i] = (int8_t)(p2[idx]*sig);
187 auto apply_perm = [](
const cube_pos_t& perm,
const uint64_t& cod) -> uint8_t
189 std::array<uint8_t, 3> cod2;
190 cod2[0] = (uint8_t)(cod & 0b001);
191 cod2[1] = (uint8_t)((cod & 0b010) >> 1);
192 cod2[2] = (uint8_t)((cod & 0b100) >> 2);
194 std::array<uint8_t, 3> res;
196 for(
int i=0; i < 3; i++)
199 uint8_t idx = (uint8_t)(std::abs(v)-1);
200 int8_t mask = (v < 0) ? 0b1 : 0b0;
201 res[idx] = (uint8_t)(cod2[i] ^ mask);
203 return (uint8_t)(res[0] | (res[1] << 1) | (res[2] << 2));
206 cube_pos_t curr_perm = {1,2,3};
209 for(
int i = NB_BITS_3D-1; i >= 0; i--)
212 uint64_t three_bits = (mort >> (3*i)) & 0b111;
214 uint64_t new_three_bits = apply_perm(curr_perm, three_bits);
217 new_three_bits = unit_hilbert[new_three_bits];
219 uint64_t orig3b = new_three_bits;
222 new_three_bits = new_three_bits ^ 0b111;
224 result |= new_three_bits;
232 curr_perm = compose(curr_perm, {2,3,1});
235 curr_perm = compose(curr_perm, {-2,3,-1});
238 curr_perm = compose(curr_perm, {-3,2,1});
242 curr_perm = compose(curr_perm, {3,2,-1});
246 curr_perm = compose(curr_perm, {2,-1,3});
250 curr_perm = compose(curr_perm, {-2,1,3});
276 p.ajouter(
"algo", &
algo);
278 p.dictionnaire(
"none", 0);
279 p.dictionnaire(
"morton", 1);
280 p.dictionnaire(
"hilbert", 2);
282 p.ajouter_flag(
"dump", &
dump_);
293 p.lire_avec_accolades(is);
302template<
typename _SIZE_>
305 using int_t = _SIZE_;
306 using ArrOfInt_t = ArrOfInt_T<_SIZE_>;
307 using DoubleTab_t = DoubleTab_T<_SIZE_>;
310 if (
algo() == Reorder_Algo::None)
return;
313 Cerr <<
"****************************************************************" << finl;
315 std::string algon =
algo() == Reorder_Algo::Morton ?
"Morton" :
"Hilbert";
318 auto renum_tab_indices = [] (
auto& tab,
const auto& renum)
320 assert(tab.nb_dim() == 2);
322 for (int_t i = 0; i < tab.dimension(0); i++)
323 for (
int j = 0; j < tab.dimension(1); j++)
324 new_tab(renum(i), j) = tab(i, j);
327 auto renum_tab_values = [] (
auto& tab,
const auto& renum)
329 assert(tab.nb_dim()==2);
330 int_t sz_renum = renum.size_array();
331 for (int_t i=0; i<tab.dimension_tot(0); i++)
332 for (
int j=0; j<tab.dimension(1); j++)
335 if (val < 0 || val >= sz_renum)
continue;
336 tab(i,j) = renum(tab(i,j));
339 auto renum_vect_values = [] (
auto& vect,
const auto& renum)
341 for (int_t i=0; i<vect.size_array(); i++)
342 vect(i) = renum(vect(i));
344 auto compute_how_many = [] (ArrOfInt_t renum) -> int_t
347 for(int_t i = 0; i < renum.size_array(); i++)
348 if (renum[i] != i) cnt++;
353 ArrOfInt_t renum_nodes, renum_elems;
354 int_t nnodes=0, nelems=0;
358 Cerr <<
"[Reordering] mesh *nodes* using " << algon <<
" scheme ..." << finl;
360 nnodes = compute_how_many(renum_nodes);
367 renum_tab_values(dom.
les_elems(), renum_nodes);
372 renum_tab_values(dom.
raccord(i)->les_sommets_des_faces(), renum_nodes);
373 for (
int i=0; i<dom.
bords_int().size(); i++)
381 Cerr <<
"[Reordering] mesh *elements* using " << algon <<
" scheme ..." << finl;
391 nelems = compute_how_many(renum_elems);
395 renum_tab_indices(dom.
les_elems(), renum_elems);
396 renum_tab_indices(xp, renum_elems);
405 for (
int i=0; i<dom.domaines_frontieres().size(); i++)
411 if constexpr (std::is_same<_SIZE_, trustIdType>::value)
416 Cerr <<
"[Reordering] Updating joints and parallel structures ..." << finl;
423 ArrOfInt& ic = j.set_joint_item(JOINT_ITEM::SOMMET).set_items_communs();
424 renum_vect_values(ic, renum_nodes);
428 IntTab& soms = j.faces().les_sommets();
429 renum_tab_values(soms, renum_nodes);
432 IntTab& fv = j.faces().voisins();
433 renum_tab_values(fv, renum_elems);
458 Cerr <<
"[Reordering] " << nnodes <<
" nodes and " << nelems <<
" cells were permuted." << finl;
459 Cerr <<
"****************************************************************" << finl;
467template <
typename _SIZE_>
470 using int_t = _SIZE_;
476 if (nb_pts==0)
return;
479 std::array<double, 3> minV = { points(0,0), points(0,1), dim == 3 ? points(0,2) : 0.0 };
480 std::array<double, 3> maxV = minV;
482 for(int_t i = 0; i < nb_pts; i++)
483 for (
int j = 0; j < dim; j++)
485 if (points(i,j) < minV[j]) minV[j] = points(i,j);
486 if (points(i,j) > maxV[j]) maxV[j] = points(i,j);
491 auto quantize = [&](
double value,
double minVal,
double maxVal) -> uint32_t
493 const uint32_t MAX_VAL = dim == 2 ? MAX_VAL_2D : MAX_VAL_3D;
494 double normalized = maxVal == minVal ? 0 : (value - minVal) / (maxVal - minVal);
495 normalized = std::clamp(normalized, 0.0, 1.0);
496 return static_cast<uint32_t
>(std::round(normalized * MAX_VAL));
501 ArrOfInt_T<_SIZE_> new2old(nb_pts);
504 std::iota(new2old.
begin(), new2old.
end(), 0);
507 std::vector<uint64_t> codes(nb_pts);
509 for (int_t i = 0; i < nb_pts; i++)
511 uint32_t ax = quantize(points(i,0), minV[0], maxV[0]),
512 ay = quantize(points(i,1), minV[1], maxV[1]);
513 codes[i] = (
algo_ == Reorder_Algo::Morton) ? mortonCode(ax, ay, 0.0) : hilbertCode_2D(ax, ay);
516 for (int_t i = 0; i < nb_pts; i++)
518 uint32_t ax = quantize(points(i,0), minV[0], maxV[0]),
519 ay = quantize(points(i,1), minV[1], maxV[1]),
520 az = quantize(points(i,2), minV[2], maxV[2]);
521 codes[i] = (
algo_ == Reorder_Algo::Morton) ? mortonCode(ax, ay, az) : hilbertCode_3D(ax, ay, az);
525 std::sort(new2old.
begin(), new2old.
end(), [&](
int a,
int b)
527 return codes[a] < codes[b];
531 for (int_t i = 0; i < nb_pts; i++) renum[new2old[i]] = i;
534template<
typename _SIZE_>
539 std::ofstream outFile(filename);
540 if (!outFile.is_open())
541 throw std::runtime_error(
"Failed to open file: " + filename);
543 for (_SIZE_ i = 0; i < points.
dimension(0); i++)
546 outFile << points(i, j) <<
" ";
classe Domaine_32_64 un Domaine est un maillage compose d'un ensemble d'elements geometriques de meme...
Domaine_32_64 & domaine_frontiere(int i)
const Sous_Domaine_t & ss_domaine(int i) const
Groupe_Faces_t & groupe_faces(int i)
Bord_Interne_t & bords_interne(int i)
Raccord_t & raccord(int i)
void calculer_centres_gravite(DoubleTab_t &xp) const
Calcule les centres de gravites des elements du domaine.
DoubleTab_t & les_sommets()
int nb_ss_domaines() const
Raccords_t & faces_raccord()
Bords_Internes_t & bords_int()
Groupes_Faces_t & groupes_faces()
Class defining operators and methods for all reading operation in an input flow (file,...
IntTab_t & les_sommets_des_faces()
Renvoie les sommets des faces de la frontiere.
classe Objet_U Cette classe est la classe de base des Objets de TRUST
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Reorder_Mesh allows the user to trigger the renumbering of the mesh entities.
Reorder_Algo algo_
Reordering algorithm.
Reorder_Algo algo() const
void compute_renumbering(const DoubleTab_T< _SIZE_ > &points, ArrOfInt_T< _SIZE_ > &renum) const
void reorder_domain(Domaine_32_64< _SIZE_ > &dom) const
bool no_faces_
Whether to skip faces in reordering.
bool no_nodes_
Whether to skip vertices in reordering.
bool dump_
Whether to dump previous and new positions into text files.
bool no_elems_
Whether to skip elements in reordering.
void dump_to_file(const DoubleTab_T< _SIZE_ > &points, const std::string &filename) const
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)
Construction des structures paralleles du domaine et du domaine (determination des elements distants ...
static void construire_correspondance_sommets_par_coordonnees(Domaine &dom, bool allow_resize=false)
Construction des tableaux joint_item(JOINT_ITEM::SOMMET).items_communs de tous les joints du domaine(...
static void trier_les_joints(Joints &joints)
Sort joints by increasing neighbor proc number.
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Classe de base des flux de sortie.
const IntVect_t & les_elems() const
void resize(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
int dimension_int(int d) const
void resize(_SIZE_ n, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
_SIZE_ dimension(int d) const