TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Reorder_Mesh.cpp
1/****************************************************************************
2 * Copyright (c) 2025, 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 <Reorder_Mesh.h>
17#include <TRUSTTab.h>
18#include <Param.h>
19#include <Scatter.h>
20
21#include <vector>
22#include <algorithm>
23#include <cstdint>
24#include <cmath>
25#include <numeric>
26#include <fstream>
27
28Implemente_instanciable(Reorder_Mesh, "Reorder_Mesh", Objet_U);
29// XD reorder_mesh objet_u reorder_mesh BRACE Reordering option to be used in a discretisation : the geometrical
30// XD_CONT entities (nodes, elems, faces) of a mesh can be reordered to follow a Z-curve (Hilbert or Morton) improving
31// XD_CONT data locality in memory.
32
33namespace // Anonymous namespace
34{
35// Number of bits to partition a single dimension (x or y) in 2D:
36constexpr unsigned int NB_BITS_2D = 32;
37// Number of bits to partition a single dimension (x,y or z) in 3D:
38// -> NB: nb of bits for the quantization of each coordinate - 21*3=63 < 64 -> will fit in uint64_t
39constexpr unsigned int NB_BITS_3D = 21;
40
41// Maximal bitwise values for the binary quantization space:
42constexpr uint32_t MAX_VAL_2D = std::numeric_limits<uint32_t>::max(); // binary: 11111...11 (32 times)
43constexpr uint32_t MAX_VAL_3D = (1 << NB_BITS_3D) - 1; // binary: 00...0011...11 (eleven 0 and 21 ones)
44
45
46using cube_pos_t = std::array<int8_t, 3>; // 3 signed integers representing the orientation of the unit x,y,z trihedron
47using ar8_t = std::array<uint8_t, 8>;
48const ar8_t unit_hilbert = { 0,7,3,4,1,6,2,5 }; // initial indexing of the unit Hilbert 3D curve
49
50
51/**! Computation of the Morton code for a given point.
52 *
53 * The Morton code is 'just' the clever bitwise assembly of all the bits from the 3 coordinates.
54 * In 2D for example, if x = 0 1 0 1 1
55 * and y = 1 0 1 1 0
56 * the resutling code is c = 10 01 10 11 01
57 * where bits from x and y have been interleaved. Thus two points close in 2D space will also have close (numerical) Morton codes! So clever.
58 */
59uint64_t mortonCode(uint32_t x, uint32_t y, uint32_t z)
60{
61 uint64_t result = 0;
62 uint64_t xx=x, yy=y, zz=z;
63 if (Objet_U::dimension == 2)
64 for (unsigned i = 0; i < ::NB_BITS_2D; i++)
65 {
66 result |= (xx & (1ULL << i)) << i;
67 result |= (yy & (1ULL << i)) << (i+1);
68 }
69 else // dim 3
70 for (unsigned i = 0; i < ::NB_BITS_3D; i++)
71 {
72 result |= (xx & (1ULL << i)) << (2*i);
73 result |= (yy & (1ULL << i)) << (2*i+1);
74 result |= (zz & (1ULL << i)) << (2*i+2);
75 }
76 return result;
77}
78
79/**! Computation of the Hilbert code. Idea is similar as Morton, but this time points are organized along a Hilbert curve.
80 *
81 * See wikipedia for example for a nice picture.
82 * We proceed by swaping/flipping the bits of each 'slot' (2 bits in 2D, 3 bits in 3D) corresponding to each depth level
83 * of the Morton code. See hilbertCode_3D below which explains the spirit in more details.
84 */
85uint64_t hilbertCode_2D(uint32_t x, uint32_t y)
86{
87 assert(Objet_U::dimension == 2);
88
89 uint64_t result = 0;
90 uint64_t mort = mortonCode(x,y,0.0);
91
92 const uint8_t ud[4] = {0, 3, 1, 2}; // up - down
93 const uint8_t rl[4] = {3, 2, 0, 1}; // right - left
94 unsigned int orient = 0; // 0: up, 1: right, 2: down, 3:left
95 bool flip = false;
96 for(int i = NB_BITS_2D-1; i >= 0; i--)
97 {
98 result <<= 2;
99 uint64_t two_bits = (mort >> (2*i)) & 0b11;
100 uint8_t new_two_bits = 0b00;
101 switch(orient)
102 {
103 case 0: // up
104 new_two_bits = ud[two_bits];
105 break;
106 case 1: // right
107 new_two_bits = rl[two_bits];
108 break;
109 case 2: // down
110 new_two_bits = ud[3-two_bits];
111 break;
112 case 3: // left
113 new_two_bits = rl[3-two_bits];
114 break;
115 default:
116 throw;
117 }
118 result |= flip ? (0b11 - new_two_bits) : new_two_bits;
119 // Rotate:
120 if (new_two_bits == 0b00) { orient = (orient+1) % 4; flip = !flip; }
121 if (new_two_bits == 0b11) { orient = (orient+3) % 4; flip = !flip; }
122 }
123 return result;
124}
125
126/**! Computation of the Hilbert code. Idea is similar as Morton, but this time points are organized along a Hilbert curve.
127 *
128 * See wikipedia for example for a nice picture.
129 *
130 * We proceed by first computing the Morton code, and then swaping/flipping the bits of each 'slot' (2 bits in 2D, 3 bits in 3D)
131 * corresponding to each depth level of the Morton code.
132 *
133 * Detailed explanation for 3D:
134 * Going from one level to the next finer level implies rotating the unit Hilbert curve that we will apply.
135 * This rotation corresponds to the rotation of a cube in 3D. In the algorithm below, the notation U, R, F corresponds
136 * to the usual notations given when solving the Rubik's cube:
137 * U is for Up (the top face of the cube),
138 * F if for Front (the face pointing towards the viewer)
139 * R is for Right
140 * A prime like in U' or in F' means the rotation is done counter-clockwise.
141 *
142 * The cube orientation at any time is given by a triplet of numbers between -3 and 3 (0 excluded)
143 * At the begining the cube is oriented like this
144 *
145 * z
146 * |
147 * | y
148 * | /
149 * |/________ x
150 *
151 * which corresponds to the triplet {1,2,3}
152 *
153 * For example a cube orientation of {3, 2, -1} means that what was the orignal X axis is now the Y axis, what was Y is now Z, and what was Z is now
154 * the opposite of X:
155 * y
156 * /
157 * /________ z
158 * |
159 * |
160 * |
161 * x
162 *
163 * Each time we go to the next finer level, we rotate the cube according to the position we are at in the current Hilbert curve.
164 * Sometimes we also need to go through the unit Hilbert curve numbering in reverse.
165 *
166 * The needed rotation were written based on the nice images found there:
167 * https://pypi.org/project/numpy-hilbert-curve/
168 */
169uint64_t hilbertCode_3D(uint32_t x, uint32_t y, uint32_t z)
170{
171 uint64_t result = 0;
172 uint64_t mort = mortonCode(x,y,z);
173
174 // Compute p1 . p2 --- mathematical definition : (p1.p2)(x) = p1(p2(x)) = res(x)
175 auto compose = [](const cube_pos_t& p1, const cube_pos_t& p2) -> cube_pos_t
176 {
177 cube_pos_t res;
178 for (int i = 0; i < 3; i++)
179 {
180 uint8_t idx = (uint8_t)(std::abs(p1[i])-1); // 0 excluded in p1, so this is actually never negative. We can brute-force cast.
181 int8_t sig = p1[i] > 0 ? 1 : -1;
182 res[i] = (int8_t)(p2[idx]*sig);
183 }
184 return res;
185 };
186
187 auto apply_perm = [](const cube_pos_t& perm, const uint64_t& cod) -> uint8_t
188 {
189 std::array<uint8_t, 3> cod2; // x,y,z
190 cod2[0] = (uint8_t)(cod & 0b001);
191 cod2[1] = (uint8_t)((cod & 0b010) >> 1);
192 cod2[2] = (uint8_t)((cod & 0b100) >> 2);
193
194 std::array<uint8_t, 3> res;
195
196 for(int i=0; i < 3; i++)
197 {
198 int8_t v = perm[i];
199 uint8_t idx = (uint8_t)(std::abs(v)-1); // 0 excluded in perm, so this is actually never negative. We can brute-force cast.
200 int8_t mask = (v < 0) ? 0b1 : 0b0;
201 res[idx] = (uint8_t)(cod2[i] ^ mask); // XOR
202 }
203 return (uint8_t)(res[0] | (res[1] << 1) | (res[2] << 2));
204 };
205
206 cube_pos_t curr_perm = {1,2,3}; // 1 represents X axis, 2 the Y axis, 3 the Z axis.
207
208 bool flip = false; // do we need to scan the unit Hilbert curve in reverse?
209 for(int i = NB_BITS_3D-1; i >= 0; i--) // for each level
210 {
211 result <<= 3;
212 uint64_t three_bits = (mort >> (3*i)) & 0b111;
213 // Apply current permutation to pos
214 uint64_t new_three_bits = apply_perm(curr_perm, three_bits);
215
216 // Apply Hilbert ordering:
217 new_three_bits = unit_hilbert[new_three_bits];
218
219 uint64_t orig3b = new_three_bits; // without the flip!!!
220
221 if(flip)
222 new_three_bits = new_three_bits ^ 0b111;
223
224 result |= new_three_bits;
225 if (i==0) break;
226
227 // Prepare cube position for next level at depth i+1.
228 // The permutation to apply depends on where we are on the current Hilbert curve at level i:
229 switch(orig3b)
230 {
231 case 0: // U R -> {2,-1,3} {1,3,-2} -> {2,3,1}
232 curr_perm = compose(curr_perm, {2,3,1});
233 break;
234 case 7: // U' R -> {-2,1,3} {1,3,-2} -> {-2,3,-1}
235 curr_perm = compose(curr_perm, {-2,3,-1});
236 break;
237 case 3: // F' flip
238 curr_perm = compose(curr_perm, {-3,2,1});
239 flip = !flip;
240 break;
241 case 4: // F flip
242 curr_perm = compose(curr_perm, {3,2,-1});
243 flip = !flip;
244 break;
245 case 1: // U flip
246 curr_perm = compose(curr_perm, {2,-1,3});
247 flip = !flip;
248 break;
249 case 6: // U' flip
250 curr_perm = compose(curr_perm, {-2,1,3});
251 flip = !flip;
252 break;
253 case 2: // nothing to do!
254 break;
255 case 5: // nothing to do!
256 break;
257 default:
258 throw;
259 }
260 }
261 return result;
262}
263
264} // end anonymous namespace
265
266
267Sortie& Reorder_Mesh::printOn(Sortie& os) const { return os; }
268
269// Default is Morton, with all geometrical entities handled.
271{
272 int algo;
273
274 Param p(que_suis_je());
275 algo = 0;
276 p.ajouter("algo", &algo); // XD_ADD_P dico
277 // XD_CONT Z-Curve algorithm to use for geometrical entity renumbering.
278 p.dictionnaire("none", 0); // XD_ADD_DICO No reordering performed (the default).
279 p.dictionnaire("morton", 1); // XD_ADD_DICO Morton scheme for reordering.
280 p.dictionnaire("hilbert", 2); // XD_ADD_DICO Hilbert scheme for reordering.
281
282 p.ajouter_flag("dump", &dump_); // XD_ADD_P flag
283 // XD_CONT if set, will dump text files giving the numbering of the various geometrical entities before and after
284 // XD_CONT renumbering. Mainly used for debugging.
285 // Values of those flags will be set to false by default:
286 p.ajouter_flag("no_nodes", &no_nodes_); // XD_ADD_P flag
287 // XD_CONT Whether to avoid node reordering.
288 p.ajouter_flag("no_elems", &no_elems_); // XD_ADD_P flag
289 // XD_CONT Whether to avoid element reordering.
290 p.ajouter_flag("no_faces", &no_faces_); // XD_ADD_P flag
291 // XD_CONT Whether to avoid face reordering.
292
293 p.lire_avec_accolades(is);
294
295 algo_ = static_cast<Reorder_Algo>(algo);
296
297 return is;
298}
299
300/**! Performs the reordering of the nodes and elements of a domain according to the chosen algorithm
301 */
302template<typename _SIZE_>
304{
305 using int_t = _SIZE_;
306 using ArrOfInt_t = ArrOfInt_T<_SIZE_>;
307 using DoubleTab_t = DoubleTab_T<_SIZE_>;
308
309 // No re-ordering requested or nothing to do:
310 if (algo() == Reorder_Algo::None) return;
311 if (skip_nodes() && skip_elems()) return;
312
313 Cerr << "****************************************************************" << finl;
314
315 std::string algon = algo() == Reorder_Algo::Morton ? "Morton" : "Hilbert";
316
317 // Renumbering utilities:
318 auto renum_tab_indices = [] (auto& tab, const auto& renum)
319 {
320 assert(tab.nb_dim() == 2);
321 auto new_tab(tab);
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);
325 tab = new_tab;
326 };
327 auto renum_tab_values = [] (auto& tab, const auto& renum)
328 {
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++) // with virtuals
332 for (int j=0; j<tab.dimension(1); j++)
333 {
334 auto val = tab(i,j);
335 if (val < 0 || val >= sz_renum) continue; // skip uninitialized or virtual values
336 tab(i,j) = renum(tab(i,j));
337 }
338 };
339 auto renum_vect_values = [] (auto& vect, const auto& renum)
340 {
341 for (int_t i=0; i<vect.size_array(); i++)
342 vect(i) = renum(vect(i));
343 };
344 auto compute_how_many = [] (ArrOfInt_t renum) -> int_t
345 {
346 int_t cnt = 0;
347 for(int_t i = 0; i < renum.size_array(); i++)
348 if (renum[i] != i) cnt++;
349 return cnt;
350 };
351
352 // Nodes and Cells renumbering
353 ArrOfInt_t renum_nodes, renum_elems;
354 int_t nnodes=0, nelems=0;
355
356 if (!skip_nodes())
357 {
358 Cerr << "[Reordering] mesh *nodes* using " << algon << " scheme ..." << finl;
359 compute_renumbering(dom.les_sommets(), renum_nodes);
360 nnodes = compute_how_many(renum_nodes);
361
362 dump_to_file(dom.les_sommets(), "reordering_som_before.txt");
363 renum_tab_indices(dom.les_sommets(), renum_nodes);
364 dump_to_file(dom.les_sommets(), "reordering_som_after.txt");
365
366 // renum_vect_values(renum_som_perio_, renum_nodes);
367 renum_tab_values(dom.les_elems(), renum_nodes);
368
369 for (int i=0; i<dom.faces_bord().size(); i++)
370 renum_tab_values(dom.bord(i).les_sommets_des_faces(), renum_nodes);
371 for (int i=0; i<dom.faces_raccord().size(); i++)
372 renum_tab_values(dom.raccord(i)->les_sommets_des_faces(), renum_nodes);
373 for (int i=0; i<dom.bords_int().size(); i++)
374 renum_tab_values(dom.bords_interne(i).les_sommets_des_faces(), renum_nodes);
375 for (int i=0; i<dom.groupes_faces().size(); i++)
376 renum_tab_values(dom.groupe_faces(i).les_sommets_des_faces(), renum_nodes);
377 }
378
379 if (!skip_elems())
380 {
381 Cerr << "[Reordering] mesh *elements* using " << algon << " scheme ..." << finl;
382 DoubleTab_t xp;
383
385 // grrrrr .... xp also contains virtuals, but without a proper // structure, hence dimension(0) == dimension_tot(0).
386 // And we just want to reorder real elements, not virtual ones (they must remain at the end)
387 // We must trim :
388 xp.resize(dom.les_elems().dimension(0), xp.dimension_int(1));
389
390 compute_renumbering(xp, renum_elems);
391 nelems = compute_how_many(renum_elems);
392
393 dump_to_file(xp, "reordering_elem_before.txt");
394
395 renum_tab_indices(dom.les_elems(), renum_elems);
396 renum_tab_indices(xp, renum_elems);
397
398 dump_to_file(xp, "reordering_elem_after.txt");
399 }
400
401 if (dom.nb_ss_domaines() && !skip_elems())
402 for (int i = 0; i < dom.nb_ss_domaines(); i++)
403 renum_vect_values(dom.ss_domaine(i).les_elems(), renum_elems);
404
405 for (int i=0; i<dom.domaines_frontieres().size(); i++)
407
408 if (Process::nproc()>1)
409 {
410 // If this piece of code is reached, we are necessarily after a Scatter, and hence with a Domaine_32 object:
411 if constexpr (std::is_same<_SIZE_, trustIdType>::value)
412 Process::exit("Should never happen!");
413 else
414 {
415 Domaine_32_64<int>& this32 = static_cast<Domaine_32_64<int>&>(dom);
416 Cerr << "[Reordering] Updating joints and parallel structures ..." << finl;
417 // Local bits of the joints needs renumbering so that they will be the items to be sent when we
418 // update the parallel structures:
419 if (!skip_nodes())
420 {
421 for (Joint & j: dom.faces_joint())
422 {
423 ArrOfInt& ic = j.set_joint_item(JOINT_ITEM::SOMMET).set_items_communs();
424 renum_vect_values(ic, renum_nodes);
425 // Sort them by increasing order (requirement of Scatter::construire_correspondance_sommets_par_coordonnees ?)
426 ic.ordonne_array();
427
428 IntTab& soms = j.faces().les_sommets();
429 renum_tab_values(soms, renum_nodes);
430 if (!skip_elems())
431 {
432 IntTab& fv = j.faces().voisins();
433 renum_tab_values(fv, renum_elems);
434 }
435 }
436
437 // real only, not virtual
438 int nb_som = this32.les_sommets().dimension(0);
439 int nb_elem = this32.les_elems().dimension(0);
440
441 // Then update joints by exchanging with neighbor procs to recompute correspondances
442 // Logic here is the same as what is done in Raffiner_isotrope_parallele:
444
445 // Remove virtual parts from sommets and elems, they will be recomputed by construire_structures_paralleles()
446 this32.les_sommets().resize(nb_som, this32.les_sommets().dimension(1)); // cut virtual
447 this32.les_elems().resize(nb_elem, this32.les_elems().dimension(1)); // cut virtual
448
450 Scatter::construire_correspondance_sommets_par_coordonnees(this32, false /* does not allow resize of items_communs */);
452 }
453 }
454 }
455 else
457
458 Cerr << "[Reordering] " << nnodes << " nodes and " << nelems << " cells were permuted." << finl;
459 Cerr << "****************************************************************" << finl;
460}
461
462
463/**! Compute the renumbering of the given array so that the points follow either a Morton curve or a Hilbert curve.
464 *
465 * @param renum an array 'renum' so that renum[i] gives the new index of the point orginally numbered 'i' (old-to-new).
466 */
467template <typename _SIZE_>
468void Reorder_Mesh::compute_renumbering(const DoubleTab_T<_SIZE_>& points, ArrOfInt_T<_SIZE_>& renum) const
469{
470 using int_t = _SIZE_;
471
472 const int dim = Objet_U::dimension;
473 assert(points.dimension_int(1) == dim);
474
475 int_t nb_pts = points.dimension(0); // without virtuals! They must remain unchanged at the end of the arrays.
476 if (nb_pts==0) return; // Nothing to do :-)
477
478 // Find bounding box
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;
481
482 for(int_t i = 0; i < nb_pts; i++)
483 for (int j = 0; j < dim; j++)
484 {
485 if (points(i,j) < minV[j]) minV[j] = points(i,j);
486 if (points(i,j) > maxV[j]) maxV[j] = points(i,j);
487 }
488
489 // Quantization function - this function turns a double value within a range [minVal, maxVal]
490 // into an integer such that the whole range of possible integers will be covered between min and maxVal
491 auto quantize = [&](double value, double minVal, double maxVal) -> uint32_t
492 {
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));
497 };
498
499 // Prepare renumbering vector
500 // new-2-old format: new2old[i] gives the index in the initial mesh of the point now located at index 'i'.
501 ArrOfInt_T<_SIZE_> new2old(nb_pts);
502
503 renum.resize(nb_pts);
504 std::iota(new2old.begin(), new2old.end(), 0);
505
506 // Compute code vector
507 std::vector<uint64_t> codes(nb_pts);
508 if (dim == 2)
509 for (int_t i = 0; i < nb_pts; i++)
510 {
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);
514 }
515 else
516 for (int_t i = 0; i < nb_pts; i++)
517 {
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);
522 }
523
524 // Sort indices based on code comparison
525 std::sort(new2old.begin(), new2old.end(), [&](int a, int b)
526 {
527 return codes[a] < codes[b];
528 });
529
530 // Translate as old-2-new in renum:
531 for (int_t i = 0; i < nb_pts; i++) renum[new2old[i]] = i;
532}
533
534template<typename _SIZE_>
535void Reorder_Mesh::dump_to_file(const DoubleTab_T<_SIZE_>& points, const std::string& filename) const
536{
537 if(!dump_) return;
538
539 std::ofstream outFile(filename);
540 if (!outFile.is_open())
541 throw std::runtime_error("Failed to open file: " + filename);
542
543 for (_SIZE_ i = 0; i < points.dimension(0); i++)
544 {
545 for (int j = 0; j < points.dimension_int(1); j++)
546 outFile << points(i, j) << " ";
547 outFile << "\n";
548 }
549
550 outFile.close();
551}
552
553
554// Instanciate
555template void Reorder_Mesh::reorder_domain(Domaine_32_64<int>& dom) const;
556template void Reorder_Mesh::dump_to_file(const DoubleTab_T<int>& points, const std::string& filename) const;
557template void Reorder_Mesh::compute_renumbering(const DoubleTab_T<int>& points, ArrOfInt_T<int>& renum) const;
558
559#ifdef INT_is_64_
561template void Reorder_Mesh::dump_to_file(const DoubleTab_T<trustIdType>& points, const std::string& filename) const;
562template void Reorder_Mesh::compute_renumbering(const DoubleTab_T<trustIdType>& points, ArrOfInt_T<trustIdType>& renum) const;
563#endif
564
classe Domaine_32_64 un Domaine est un maillage compose d'un ensemble d'elements geometriques de meme...
Definition Domaine.h:62
Domaine_32_64 & domaine_frontiere(int i)
Definition Domaine.h:242
const Sous_Domaine_t & ss_domaine(int i) const
Definition Domaine.h:290
Groupe_Faces_t & groupe_faces(int i)
Definition Domaine.h:221
Bord_Interne_t & bords_interne(int i)
Definition Domaine.h:208
Raccord_t & raccord(int i)
Definition Domaine.h:248
void calculer_centres_gravite(DoubleTab_t &xp) const
Calcule les centres de gravites des elements du domaine.
Definition Domaine.h:503
DoubleTab_t & les_sommets()
Definition Domaine.h:113
Bords_t & faces_bord()
Definition Domaine.h:198
int nb_ss_domaines() const
Definition Domaine.h:289
Raccords_t & faces_raccord()
Definition Domaine.h:253
IntTab_t & les_elems()
Definition Domaine.h:129
Bords_Internes_t & bords_int()
Definition Domaine.h:213
Bord_t & bord(int i)
Definition Domaine.h:193
Joints_t & faces_joint()
Definition Domaine.h:265
Groupes_Faces_t & groupes_faces()
Definition Domaine.h:224
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
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
Definition Objet_U.h:73
static int dimension
Definition Objet_U.h:99
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
Reorder_Mesh allows the user to trigger the renumbering of the mesh entities.
Reorder_Algo algo_
Reordering algorithm.
bool skip_nodes() const
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.
bool skip_elems() const
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...
Definition Scatter.cpp:2742
static void construire_structures_paralleles(Domaine &dom)
Construction des structures paralleles du domaine et du domaine (determination des elements distants ...
Definition Scatter.cpp:672
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(...
Definition Scatter.cpp:2678
static void trier_les_joints(Joints &joints)
Sort joints by increasing neighbor proc number.
Definition Scatter.cpp:712
static void uninit_sequential_domain(Domaine_32_64< _SIZE_ > &dom)
methode utilisee par les interpretes qui modifient le domaine (sequentiel), detruit les descripteurs ...
Definition Scatter.cpp:2757
Classe de base des flux de sortie.
Definition Sortie.h:52
const IntVect_t & les_elems() const
Iterator_ end()
Definition TRUSTArray.h:112
void ordonne_array()
Iterator_ begin()
Definition TRUSTArray.h:111
void resize(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
Definition TRUSTArray.h:156
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(int d) const
Definition TRUSTTab.tpp:133