Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CartesianMeshUniqueIdRenumbering.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CartesianMeshUniqueIdRenumbering.cc (C) 2000-2024 */
9/* */
10/* Renumérotation des uniqueId() pour les maillages cartésiens. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/internal/CartesianMeshUniqueIdRenumbering.h"
15
16#include "arcane/utils/PlatformUtils.h"
17
18#include "arcane/cartesianmesh/ICartesianMesh.h"
19#include "arcane/cartesianmesh/ICartesianMeshPatch.h"
20
21#include "arcane/core/CartesianGridDimension.h"
22#include "arcane/core/VariableTypes.h"
23#include "arcane/core/IMesh.h"
24#include "arcane/core/IItemFamily.h"
25#include "arcane/core/IParallelMng.h"
26#include "arcane/core/ICartesianMeshGenerationInfo.h"
28
29#include <array>
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
41{
42 public:
43
45 : cells(VariableBuildInfo(mesh, "ArcaneRenumberCellsNewUid"))
46 , nodes(VariableBuildInfo(mesh, "ArcaneRenumberNodesNewUid"))
47 , faces(VariableBuildInfo(mesh, "ArcaneRenumberFacesNewUid"))
48 {
49 cells.fill(NULL_ITEM_UNIQUE_ID);
50 nodes.fill(NULL_ITEM_UNIQUE_ID);
51 faces.fill(NULL_ITEM_UNIQUE_ID);
52 }
53
54 public:
55
56 void markCellNoRenumber(Cell c)
57 {
58 _setCell(c);
59 for (Node n : c.nodes())
60 _setNode(n);
61 for (Face f : c.faces())
62 _setFace(f);
63 }
64 Int64 maxUniqueId() const
65 {
66 return math::max(max_cell_uid, max_node_uid, max_face_uid);
67 }
68
69 public:
70
74
75 private:
76
77 Int64 max_cell_uid = NULL_ITEM_UNIQUE_ID;
78 Int64 max_node_uid = NULL_ITEM_UNIQUE_ID;
79 Int64 max_face_uid = NULL_ITEM_UNIQUE_ID;
80
81 private:
82
83 void _setNode(Node node)
84 {
85 Int64 uid = node.uniqueId();
86 nodes[node] = uid;
87 if (uid > max_node_uid)
88 max_node_uid = uid;
89 }
90 void _setFace(Face face)
91 {
92 Int64 uid = face.uniqueId();
93 faces[face] = uid;
94 if (uid > max_face_uid)
95 max_face_uid = uid;
96 }
97 void _setCell(Cell cell)
98 {
99 Int64 uid = cell.uniqueId();
100 cells[cell] = uid;
101 if (uid > max_cell_uid)
102 max_cell_uid = uid;
103 }
104};
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109CartesianMeshUniqueIdRenumbering::
110CartesianMeshUniqueIdRenumbering(ICartesianMesh* cmesh, ICartesianMeshGenerationInfo* gen_info,
112: TraceAccessor(cmesh->traceMng())
113, m_cartesian_mesh(cmesh)
114, m_generation_info(gen_info)
115, m_parent_patch(parent_patch)
116, m_patch_method(patch_method)
117{
118 if (platform::getEnvironmentVariable("ARCANE_DEBUG_AMR_RENUMBERING") == "1")
119 m_is_verbose = true;
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124
125void CartesianMeshUniqueIdRenumbering::
126renumber()
127{
128 IMesh* mesh = m_cartesian_mesh->mesh();
129 IParallelMng* pm = mesh->parallelMng();
130 const Int32 dimension = mesh->dimension();
131 Int64 cartesian_global_nb_cell = m_generation_info->globalNbCell();
132
133 const bool use_v2 = (m_patch_method == 3);
134 info() << "Apply UniqueId renumbering to mesh '" << mesh->name() << "'"
135 << " global_nb_cell=" << cartesian_global_nb_cell
136 << " global_nb_cell_by_dim=" << m_generation_info->globalNbCells()
137 << " mesh_dimension=" << dimension
138 << " patch_method=" << m_patch_method
139 << " use_v2=" << use_v2;
140
141 NewUniqueIdList new_uids(mesh);
142
143 // Indique si on utilise le patch par défaut.
144 bool use_default_patch = false;
145 CartesianPatch patch0 = m_parent_patch;
146 if (patch0.isNull()) {
147 patch0 = m_cartesian_mesh->patch(0);
148 if (m_patch_method != 4)
149 use_default_patch = true;
150 }
151
152 // TODO: Afficher le numéro du patch.
153
154 // Marque les entités issues de 'm_parent_patch' comme n'étant pas renumérotées.
155 // Si 'm_parent_patch' n'est pas spécifié, on prend les mailles du patch initial.
156 // Marque aussi les mailles parentes du patch comme étant non renumérotées.
157 // NOTE: Cela ne fonctionne bien que si 'm_parent_patch' est le patch initial
158 // ou un patch juste en dessous. Dans l'utilisation actuelle c'est toujours le cas
159 // car on appelle cette méthode avec soit le patch de base, soit le patch issu
160 // du raffinement du patch initial.
161 Int32 patch_level = 0;
162 ENUMERATE_ (Cell, icell, patch0.cells()) {
163 Cell c{ *icell };
164 patch_level = c.level();
165 new_uids.markCellNoRenumber(c);
166 Cell parent = c.hParent();
167 if (!parent.null())
168 new_uids.markCellNoRenumber(parent);
169 }
170
171 Int64ConstArrayView global_nb_cells_by_direction = m_generation_info->globalNbCells();
172 Int64 nb_cell_x = global_nb_cells_by_direction[MD_DirX];
173 Int64 nb_cell_y = global_nb_cells_by_direction[MD_DirY];
174 Int64 nb_cell_z = global_nb_cells_by_direction[MD_DirZ];
175
176 if (nb_cell_x <= 0)
177 ARCANE_FATAL("Bad value '{0}' for globalNbCells()[MD_DirX] (should be >0)", nb_cell_x);
178 if (dimension >= 2 && nb_cell_y <= 0)
179 ARCANE_FATAL("Bad value '{0}' for globalNbCells()[MD_DirY] (should be >0)", nb_cell_y);
180 if (dimension >= 3 && nb_cell_z <= 0)
181 ARCANE_FATAL("Bad value '{0}' for globalNbCells()[MD_DirZ] (should be >0)", nb_cell_z);
182
183 // Calcule le nombre de mailles du patch servant de référence.
184 // Suppose qu'on raffine d'un facteur 2 à chaque fois
185 info() << "PatchLevel=" << patch_level << " use_default_path=" << use_default_patch;
186 Int32 multiplier = 1;
187 for (Int32 z = 0; z < patch_level; ++z)
188 multiplier *= 2;
189 nb_cell_x *= multiplier;
190 nb_cell_y *= multiplier;
191 nb_cell_z *= multiplier;
192
193 CartesianGridDimension grid(nb_cell_x, nb_cell_y, nb_cell_z);
194
195 Int64 max_item_uid = pm->reduce(Parallel::ReduceMax, new_uids.maxUniqueId());
196 info() << "MaxItem uniqueId=" << max_item_uid;
197 Int64 base_adder = 1 + max_item_uid;
198 if (use_default_patch)
199 base_adder = 0;
200
201 // On suppose que la patch servant de référence a une numérotation cartésienne d'origine
202 // ce qui veut dire qu'on peut déterminer les coordonnées topologiques de la maille
203 // grâce à son uniqueId()
204 if (dimension == 2) {
205 CartesianGridDimension::CellUniqueIdComputer2D cell_uid_computer(0, nb_cell_x);
206 ENUMERATE_ (Cell, icell, patch0.cells()) {
207 Cell cell{ *icell };
208 Int64 uid = cell.uniqueId();
209 Int32 level = cell.level();
210 auto [coord_i, coord_j, coord_k] = cell_uid_computer.compute(uid);
211 if (m_is_verbose)
212 info() << "Renumbering: PARENT: cell_uid=" << uid << " I=" << coord_i
213 << " J=" << coord_j << " nb_cell_x=" << nb_cell_x;
214 if (use_default_patch)
215 // Indique qu'on est de niveau 1 pour avoir la même numérotation qu'avec la version 3.9
216 level = 1;
217 _applyChildrenCell2D(cell, new_uids, coord_i, coord_j, nb_cell_x, nb_cell_y, level, base_adder);
218 }
219 }
220 else if (dimension == 3) {
221 CartesianGridDimension::CellUniqueIdComputer3D cell_uid_computer(grid.getCellComputer3D(0));
222 ENUMERATE_ (Cell, icell, patch0.cells()) {
223 Cell cell{ *icell };
224 Int64 uid = cell.uniqueId();
225 auto [coord_i, coord_j, coord_k] = cell_uid_computer.compute(uid);
226 Int32 level = cell.level();
227 if (m_is_verbose)
228 info() << "Renumbering: PARENT: cell_uid=" << uid << " level=" << level
229 << " I=" << coord_i << " J=" << coord_j << " K=" << coord_k
230 << " nb_cell_x=" << nb_cell_x << " nb_cell_y=" << nb_cell_y << " nb_cell_z=" << nb_cell_z;
231 if (use_v2)
232 _applyChildrenCell3DV2(cell, new_uids, coord_i, coord_j, coord_k,
233 nb_cell_x, nb_cell_y, nb_cell_z, level,
234 base_adder, base_adder, base_adder);
235 else
236 _applyChildrenCell3D(cell, new_uids, coord_i, coord_j, coord_k,
237 nb_cell_x, nb_cell_y, nb_cell_z, level,
238 base_adder, base_adder, base_adder);
239 }
240 }
241
242 // TODO: faire une classe pour cela.
243 //info() << "Change CellFamily";
244 //mesh->cellFamily()->notifyItemsUniqueIdChanged();
245
246 _applyFamilyRenumbering(mesh->cellFamily(), new_uids.cells);
247 _applyFamilyRenumbering(mesh->nodeFamily(), new_uids.nodes);
248 _applyFamilyRenumbering(mesh->faceFamily(), new_uids.faces);
249 mesh->checkValidMesh();
250}
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255void CartesianMeshUniqueIdRenumbering::
256_applyFamilyRenumbering(IItemFamily* family, VariableItemInt64& items_new_uid)
257{
258 info() << "Change uniqueId() for family=" << family->name();
259 items_new_uid.synchronize();
260 ENUMERATE_ (Item, iitem, family->allItems()) {
261 Item item{ *iitem };
262 Int64 current_uid = item.uniqueId();
263 Int64 new_uid = items_new_uid[iitem];
264 if (new_uid >= 0 && new_uid != current_uid) {
265 if (m_is_verbose)
266 info() << "Change ItemUID old=" << current_uid << " new=" << new_uid;
267 item.mutableItemBase().setUniqueId(new_uid);
268 }
269 }
270 family->notifyItemsUniqueIdChanged();
271}
272
273/*---------------------------------------------------------------------------*/
274/*---------------------------------------------------------------------------*/
275
276void CartesianMeshUniqueIdRenumbering::
277_applyChildrenCell2D(Cell cell, NewUniqueIdList& new_uids,
278 Int64 coord_i, Int64 coord_j,
279 Int64 nb_cell_x, Int64 nb_cell_y, Int32 level, Int64 base_adder)
280{
281 // TODO: pour pouvoir s'adapter à tous les raffinements, au lieu de 4,
282 // il faudrait prendre le max des nbHChildren()
283
284 if (coord_i >= nb_cell_x)
285 ARCANE_FATAL("Bad coordinate X={0} max={1}", coord_i, nb_cell_x);
286 if (coord_j >= nb_cell_y)
287 ARCANE_FATAL("Bad coordinate Y={0} max={1}", coord_j, nb_cell_y);
288
289 // Suppose qu'on a un pattern 2x2
290 coord_i *= 2;
291 coord_j *= 2;
292 nb_cell_x *= 2;
293 nb_cell_y *= 2;
294 const Int64 nb_node_x = nb_cell_x + 1;
295 const Int64 nb_node_y = nb_cell_y + 1;
296 const Int64 cell_adder = base_adder + (nb_cell_x * nb_cell_y * level);
297 const Int64 nb_face_x = nb_cell_x + 1;
298 const Int64 node_adder = base_adder + (nb_node_x * nb_node_y * level);
299 const Int64 face_adder = base_adder + (node_adder * 2);
300
301 // Renumérote les noeuds de la maille courante.
302 // Suppose qu'on a 4 noeuds
303 // ATTENTION a priori on ne peut pas conserver facilement l'ordre
304 // des uniqueId() entre l'ancienne et la nouvelle numérotation.
305 // Cela invalide l'orientation des faces qu'il faudra refaire.
306 {
307 if (cell.nbNode() != 4)
308 ARCANE_FATAL("Invalid number of nodes N={0}, expected=4", cell.nbNode());
309 std::array<Int64, 4> node_uids;
310 node_uids[0] = (coord_i + 0) + ((coord_j + 0) * nb_node_x);
311 node_uids[1] = (coord_i + 1) + ((coord_j + 0) * nb_node_x);
312 node_uids[2] = (coord_i + 1) + ((coord_j + 1) * nb_node_x);
313 node_uids[3] = (coord_i + 0) + ((coord_j + 1) * nb_node_x);
314 for (Integer z = 0; z < 4; ++z) {
315 Node node = cell.node(z);
316 if (new_uids.nodes[node] < 0) {
317 node_uids[z] += node_adder;
318 if (m_is_verbose)
319 info() << "APPLY_NODE_CHILD: uid=" << node.uniqueId() << " parent_cell=" << cell.uniqueId()
320 << " I=" << z << " new_uid=" << node_uids[z];
321 new_uids.nodes[node] = node_uids[z];
322 }
323 }
324 }
325 // Renumérote les faces
326 // TODO: Vérifier la validité de cette méthode.
327 {
328 if (cell.nbFace() != 4)
329 ARCANE_FATAL("Invalid number of faces N={0}, expected=4", cell.nbFace());
330 std::array<Int64, 4> face_uids;
331 face_uids[0] = (coord_i + 0) + ((coord_j + 0) * nb_face_x);
332 face_uids[1] = (coord_i + 1) + ((coord_j + 0) * nb_face_x);
333 face_uids[2] = (coord_i + 1) + ((coord_j + 1) * nb_face_x);
334 face_uids[3] = (coord_i + 0) + ((coord_j + 1) * nb_face_x);
335 for (Integer z = 0; z < 4; ++z) {
336 Face face = cell.face(z);
337 if (new_uids.faces[face] < 0) {
338 face_uids[z] += face_adder;
339 if (m_is_verbose)
340 info() << "APPLY_FACE_CHILD: uid=" << face.uniqueId() << " parent_cell=" << cell.uniqueId()
341 << " I=" << z << " new_uid=" << face_uids[z];
342 new_uids.faces[face] = face_uids[z];
343 }
344 }
345 }
346 // Renumérote les sous-mailles
347 // Suppose qu'on a 4 mailles enfants comme suit par mailles
348 // -------
349 // | 2| 3|
350 // -------
351 // | 0| 1|
352 // -------
353 Int32 nb_child = cell.nbHChildren();
354 for (Int32 icell = 0; icell < nb_child; ++icell) {
355 Cell sub_cell = cell.hChild(icell);
356 Int64 my_coord_i = coord_i + icell % 2;
357 Int64 my_coord_j = coord_j + icell / 2;
358 Int64 new_uid = (my_coord_i + my_coord_j * nb_cell_x) + cell_adder;
359 if (m_is_verbose)
360 info() << "APPLY_CELL_CHILD: uid=" << sub_cell.uniqueId() << " I=" << my_coord_i << " J=" << my_coord_j
361 << " level=" << level << " new_uid=" << new_uid << " CellAdder=" << cell_adder;
362
363 _applyChildrenCell2D(sub_cell, new_uids, my_coord_i, my_coord_j,
364 nb_cell_x, nb_cell_y, level + 1, base_adder);
365 if (new_uids.cells[sub_cell] < 0)
366 new_uids.cells[sub_cell] = new_uid;
367 }
368}
369
370/*---------------------------------------------------------------------------*/
371/*---------------------------------------------------------------------------*/
372
373void CartesianMeshUniqueIdRenumbering::
374_applyChildrenCell3D(Cell cell, NewUniqueIdList& new_uids,
375 Int64 coord_i, Int64 coord_j, Int64 coord_k,
376 Int64 current_level_nb_cell_x, Int64 current_level_nb_cell_y, Int64 current_level_nb_cell_z,
377 Int32 current_level, Int64 cell_adder, Int64 node_adder, Int64 face_adder)
378{
379 if (coord_i >= current_level_nb_cell_x)
380 ARCANE_FATAL("Bad coordinate X={0} max={1}", coord_i, current_level_nb_cell_x);
381 if (coord_j >= current_level_nb_cell_y)
382 ARCANE_FATAL("Bad coordinate Y={0} max={1}", coord_j, current_level_nb_cell_y);
383 if (coord_k >= current_level_nb_cell_z)
384 ARCANE_FATAL("Bad coordinate Z={0} max={1}", coord_k, current_level_nb_cell_z);
385
386 // TODO: pour pouvoir s'adapter à tous les raffinements, au lieu de 8,
387 // il faudrait prendre le max des nbHChildren()
388
389 const Int64 current_level_nb_node_x = current_level_nb_cell_x + 1;
390 const Int64 current_level_nb_node_y = current_level_nb_cell_y + 1;
391 const Int64 current_level_nb_node_z = current_level_nb_cell_z + 1;
392
393 const Int64 current_level_nb_face_x = current_level_nb_cell_x + 1;
394 const Int64 current_level_nb_face_y = current_level_nb_cell_y + 1;
395 const Int64 current_level_nb_face_z = current_level_nb_cell_z + 1;
396
397 // // Version non récursive pour cell_adder, node_adder et face_adder.
398 // cell_adder = 0;
399 // node_adder = 0;
400 // face_adder = 0;
401 // const Int64 parent_level_nb_cell_x = current_level_nb_cell_x / 2;
402 // const Int64 parent_level_nb_cell_y = current_level_nb_cell_y / 2;
403 // const Int64 parent_level_nb_cell_z = current_level_nb_cell_z / 2;
404 // Int64 level_i_nb_cell_x = parent_level_nb_cell_x;
405 // Int64 level_i_nb_cell_y = parent_level_nb_cell_y;
406 // Int64 level_i_nb_cell_z = parent_level_nb_cell_z;
407 // for(Int32 i = current_level-1; i >= 0; i--){
408 // face_adder += (level_i_nb_cell_z + 1) * level_i_nb_cell_x * level_i_nb_cell_y
409 // + (level_i_nb_cell_x + 1) * level_i_nb_cell_y * level_i_nb_cell_z
410 // + (level_i_nb_cell_y + 1) * level_i_nb_cell_z * level_i_nb_cell_x;
411
412 // cell_adder += level_i_nb_cell_x * level_i_nb_cell_y * level_i_nb_cell_z;
413 // node_adder += (level_i_nb_cell_x + 1) * (level_i_nb_cell_y + 1) * (level_i_nb_cell_z + 1);
414
415 // level_i_nb_cell_x /= 2;
416 // level_i_nb_cell_y /= 2;
417 // level_i_nb_cell_z /= 2;
418 // }
419
420 // Renumérote la maille.
421 {
422 Int64 new_uid = (coord_i + coord_j * current_level_nb_cell_x + coord_k * current_level_nb_cell_x * current_level_nb_cell_y) + cell_adder;
423 if (new_uids.cells[cell] < 0) {
424 new_uids.cells[cell] = new_uid;
425 if (m_is_verbose)
426 info() << "APPLY_CELL_CHILD: uid=" << cell.uniqueId() << " I=" << coord_i << " J=" << coord_j << " K=" << coord_k
427 << " current_level=" << current_level << " new_uid=" << new_uid << " CellAdder=" << cell_adder;
428 }
429 }
430
431 // Renumérote les noeuds de la maille courante.
432 // Suppose qu'on a 8 noeuds
433 // ATTENTION a priori on ne peut pas conserver facilement l'ordre
434 // des uniqueId() entre l'ancienne et la nouvelle numérotation.
435 // Cela invalide l'orientation des faces qu'il faudra refaire.
436 {
437 if (cell.nbNode() != 8)
438 ARCANE_FATAL("Invalid number of nodes N={0}, expected=8", cell.nbNode());
439 std::array<Int64, 8> node_uids;
440 node_uids[0] = (coord_i + 0) + ((coord_j + 0) * current_level_nb_node_x) + ((coord_k + 0) * current_level_nb_node_x * current_level_nb_node_y);
441 node_uids[1] = (coord_i + 1) + ((coord_j + 0) * current_level_nb_node_x) + ((coord_k + 0) * current_level_nb_node_x * current_level_nb_node_y);
442 node_uids[2] = (coord_i + 1) + ((coord_j + 1) * current_level_nb_node_x) + ((coord_k + 0) * current_level_nb_node_x * current_level_nb_node_y);
443 node_uids[3] = (coord_i + 0) + ((coord_j + 1) * current_level_nb_node_x) + ((coord_k + 0) * current_level_nb_node_x * current_level_nb_node_y);
444
445 node_uids[4] = (coord_i + 0) + ((coord_j + 0) * current_level_nb_node_x) + ((coord_k + 1) * current_level_nb_node_x * current_level_nb_node_y);
446 node_uids[5] = (coord_i + 1) + ((coord_j + 0) * current_level_nb_node_x) + ((coord_k + 1) * current_level_nb_node_x * current_level_nb_node_y);
447 node_uids[6] = (coord_i + 1) + ((coord_j + 1) * current_level_nb_node_x) + ((coord_k + 1) * current_level_nb_node_x * current_level_nb_node_y);
448 node_uids[7] = (coord_i + 0) + ((coord_j + 1) * current_level_nb_node_x) + ((coord_k + 1) * current_level_nb_node_x * current_level_nb_node_y);
449
450 for (Integer z = 0; z < 8; ++z) {
451 Node node = cell.node(z);
452 if (new_uids.nodes[node] < 0) {
453 node_uids[z] += node_adder;
454 if (m_is_verbose)
455 info() << "APPLY_NODE_CHILD: uid=" << node.uniqueId() << " parent_cell=" << cell.uniqueId()
456 << " I=" << z << " new_uid=" << node_uids[z];
457 new_uids.nodes[node] = node_uids[z];
458 }
459 }
460 }
461
462 // Renumérote les faces
463 // Cet algo n'est pas basé sur l'algo 2D.
464 // Les UniqueIDs générés sont contigües.
465 // Il est aussi possible de retrouver les UniqueIDs des faces
466 // à l'aide de la position de la cellule et la taille du maillage.
467 // De plus, l'ordre des UniqueIDs des faces d'une cellule est toujours le
468 // même (en notation localId Arcane (cell.face(i)) : 0, 3, 1, 4, 2, 5).
469 // Les UniqueIDs générés sont donc les mêmes quelque soit le découpage.
470 /*
471 x z
472 ┌──► │ ┌──►
473 │ │ │
474 y▼12 13 14 │y▼ ┌────┬────┐
475 │ 26 │ 27 │ │ │ 24 │ 25 │
476 └────┴────┘ │ 0 4 8
477 15 16 17 │
478 │ 28 │ 29 │ │ │ │ │
479 └────┴────┘ │ 2 5 9
480 z=0 │ x=0
481 - - - - - - - - - - - - - - - - - -
482 z=1 │ x=1
483 18 19 20 │ ┌────┬────┐
484 │ 32 │ 33 │ │ │ 30 │ 31 │
485 └────┴────┘ │ 1 6 10
486 21 22 23 │
487 │ 34 │ 35 │ │ │ │ │
488 └────┴────┘ │ 3 7 11
489
490 */
491 // On a un cube décomposé en huit cellules (2x2x2).
492 // Le schéma au-dessus représente les faces des cellules de ce cube avec
493 // les uniqueIDs que l'algorithme génèrera (sans face_adder).
494 // Pour cet algo, on commence par les faces "xy".
495 // On énumère d'abord en x, puis en y, puis en z.
496 // Une fois les faces "xy" numérotées, on fait les faces "yz".
497 // Toujours le même ordre de numérotation.
498 // On termine avec les faces "zx", encore dans le même ordre.
499 //
500 // Dans l'implémentation ci-dessous, on fait la numérotation
501 // maille par maille.
502 const Int64 total_face_xy = current_level_nb_face_z * current_level_nb_cell_x * current_level_nb_cell_y;
503 const Int64 total_face_xy_yz = total_face_xy + current_level_nb_face_x * current_level_nb_cell_y * current_level_nb_cell_z;
504 const Int64 total_face_xy_yz_zx = total_face_xy_yz + current_level_nb_face_y * current_level_nb_cell_z * current_level_nb_cell_x;
505 {
506 if (cell.nbFace() != 6)
507 ARCANE_FATAL("Invalid number of faces N={0}, expected=6", cell.nbFace());
508 std::array<Int64, 6> face_uids;
509
511 // face_uids[0] = (coord_k * current_level_nb_cell_x * current_level_nb_cell_y)
512 // + (coord_j * current_level_nb_cell_x)
513 // + (coord_i);
514
515 // face_uids[3] = ((coord_k+1) * current_level_nb_cell_x * current_level_nb_cell_y)
516 // + (coord_j * current_level_nb_cell_x)
517 // + (coord_i);
518
519 // face_uids[1] = (coord_k * current_level_nb_face_x * current_level_nb_cell_y)
520 // + (coord_j * current_level_nb_face_x)
521 // + (coord_i) + total_face_xy;
522
523 // face_uids[4] = (coord_k * current_level_nb_face_x * current_level_nb_cell_y)
524 // + (coord_j * current_level_nb_face_x)
525 // + (coord_i+1) + total_face_xy;
526
527 // face_uids[2] = (coord_k * current_level_nb_cell_x * current_level_nb_face_y)
528 // + (coord_j * current_level_nb_cell_x)
529 // + (coord_i) + total_face_xy_yz;
530
531 // face_uids[5] = (coord_k * current_level_nb_cell_x * current_level_nb_face_y)
532 // + ((coord_j+1) * current_level_nb_cell_x)
533 // + (coord_i) + total_face_xy_yz;
535
536 const Int64 nb_cell_before_j = coord_j * current_level_nb_cell_x;
537
538 face_uids[0] = (coord_k * current_level_nb_cell_x * current_level_nb_cell_y) + nb_cell_before_j + (coord_i);
539
540 face_uids[3] = face_uids[0] + current_level_nb_cell_x * current_level_nb_cell_y;
541
542 face_uids[1] = (coord_k * current_level_nb_face_x * current_level_nb_cell_y) + (coord_j * current_level_nb_face_x) + (coord_i) + total_face_xy;
543
544 face_uids[4] = face_uids[1] + 1;
545
546 face_uids[2] = (coord_k * current_level_nb_cell_x * current_level_nb_face_y) + nb_cell_before_j + (coord_i) + total_face_xy_yz;
547
548 face_uids[5] = face_uids[2] + current_level_nb_cell_x;
549
550 for (Integer z = 0; z < 6; ++z) {
551 Face face = cell.face(z);
552 if (new_uids.faces[face] < 0) {
553 face_uids[z] += face_adder;
554 if (m_is_verbose)
555 info() << "APPLY_FACE_CHILD: uid=" << face.uniqueId() << " parent_cell=" << cell.uniqueId()
556 << " I=" << z << " new_uid=" << face_uids[z];
557 new_uids.faces[face] = face_uids[z];
558 }
559 }
560 }
561
562 // Renumérote les sous-mailles
563 // Suppose qu'on a 8 mailles enfants (2x2x2) comme suit par mailles
564 // -------
565 // | 2| 3|
566 // -------
567 // | 0| 1|
568 // -------
569 cell_adder += current_level_nb_cell_x * current_level_nb_cell_y * current_level_nb_cell_z;
570 node_adder += current_level_nb_node_x * current_level_nb_node_y * current_level_nb_node_z;
571 face_adder += total_face_xy_yz_zx;
572
573 coord_i *= 2;
574 coord_j *= 2;
575 coord_k *= 2;
576
577 current_level_nb_cell_x *= 2;
578 current_level_nb_cell_y *= 2;
579 current_level_nb_cell_z *= 2;
580
581 current_level += 1;
582
583 Int32 nb_child = cell.nbHChildren();
584 for (Int32 icell = 0; icell < nb_child; ++icell) {
585 Cell sub_cell = cell.hChild(icell);
586 Int64 my_coord_i = coord_i + icell % 2;
587 Int64 my_coord_j = coord_j + (icell % 4) / 2;
588 Int64 my_coord_k = coord_k + icell / 4;
589
590 _applyChildrenCell3D(sub_cell, new_uids, my_coord_i, my_coord_j, my_coord_k,
591 current_level_nb_cell_x, current_level_nb_cell_y, current_level_nb_cell_z,
592 current_level, cell_adder, node_adder, face_adder);
593 }
594}
595
596/*---------------------------------------------------------------------------*/
597/*---------------------------------------------------------------------------*/
598
599void CartesianMeshUniqueIdRenumbering::
600_applyChildrenCell3DV2(Cell cell, NewUniqueIdList& new_uids,
601 Int64 coord_i, Int64 coord_j, Int64 coord_k,
602 Int64 current_level_nb_cell_x, Int64 current_level_nb_cell_y, Int64 current_level_nb_cell_z,
603 Int32 current_level, Int64 cell_adder, Int64 node_adder, Int64 face_adder)
604{
605 if (coord_i >= current_level_nb_cell_x)
606 ARCANE_FATAL("Bad coordinate X={0} max={1}", coord_i, current_level_nb_cell_x);
607 if (coord_j >= current_level_nb_cell_y)
608 ARCANE_FATAL("Bad coordinate Y={0} max={1}", coord_j, current_level_nb_cell_y);
609 if (coord_k >= current_level_nb_cell_z)
610 ARCANE_FATAL("Bad coordinate Z={0} max={1}", coord_k, current_level_nb_cell_z);
611
612 coord_i *= 2;
613 coord_j *= 2;
614 coord_k *= 2;
615
616 current_level_nb_cell_x *= 2;
617 current_level_nb_cell_y *= 2;
618 current_level_nb_cell_z *= 2;
619
620 CartesianGridDimension grid(current_level_nb_cell_x, current_level_nb_cell_y, current_level_nb_cell_z);
621 CartesianGridDimension::CellUniqueIdComputer3D cell_uid_computer(grid.getCellComputer3D(cell_adder));
622 CartesianGridDimension::FaceUniqueIdComputer3D face_uid_computer(grid.getFaceComputer3D(face_adder));
623 CartesianGridDimension::NodeUniqueIdComputer3D node_uid_computer(grid.getNodeComputer3D(node_adder));
624
625 // TODO: pour pouvoir s'adapter à tous les raffinements, au lieu de 8,
626 // il faudrait prendre le max des nbHChildren()
627
628 Int64x3 grid_nb_node = grid.nbNode();
629 Int64x3 grid_nb_face = grid.nbFace();
630
631 // Renumérote la maille.
632 {
633 Int64 new_uid = cell_uid_computer.compute(coord_i, coord_j, coord_k);
634 if (new_uids.cells[cell] < 0) {
635 new_uids.cells[cell] = new_uid;
636 if (m_is_verbose)
637 info() << "APPLY_CELL_CHILD: uid=" << cell.uniqueId() << " I=" << coord_i << " J=" << coord_j << " K=" << coord_k
638 << " current_level=" << current_level << " new_uid=" << new_uid << " CellAdder=" << cell_adder;
639 }
640 }
641
642 static constexpr Int32 const_cell_nb_node = 8;
643 // Renumérote les noeuds de la maille courante.
644 {
645 std::array<Int64, const_cell_nb_node> node_uids = node_uid_computer.computeForCell(coord_i, coord_j, coord_k);
646
647 for (Integer z = 0; z < const_cell_nb_node; ++z) {
648 Node node = cell.node(z);
649 if (new_uids.nodes[node] < 0) {
650 if (m_is_verbose)
651 info() << "APPLY_NODE_CHILD: uid=" << node.uniqueId() << " parent_cell=" << cell.uniqueId()
652 << " I=" << z << " new_uid=" << node_uids[z];
653 new_uids.nodes[node] = node_uids[z];
654 }
655 }
656 }
657
658 // Renumérote les faces
659 // Cet algo n'est pas basé sur l'algo 2D.
660 // Les UniqueIDs générés sont contigües.
661 // Il est aussi possible de retrouver les UniqueIDs des faces
662 // à l'aide de la position de la cellule et la taille du maillage.
663 // De plus, l'ordre des UniqueIDs des faces d'une cellule est toujours le
664 // même (en notation localId Arcane (cell.face(i)) : 0, 3, 1, 4, 2, 5).
665 // Les UniqueIDs générés sont donc les mêmes quelque soit le découpage.
666 /*
667 x z
668 ┌──► │ ┌──►
669 │ │ │
670 y▼12 13 14 │y▼ ┌────┬────┐
671 │ 26 │ 27 │ │ │ 24 │ 25 │
672 └────┴────┘ │ 0 4 8
673 15 16 17 │
674 │ 28 │ 29 │ │ │ │ │
675 └────┴────┘ │ 2 5 9
676 z=0 │ x=0
677 - - - - - - - - - - - - - - - - - -
678 z=1 │ x=1
679 18 19 20 │ ┌────┬────┐
680 │ 32 │ 33 │ │ │ 30 │ 31 │
681 └────┴────┘ │ 1 6 10
682 21 22 23 │
683 │ 34 │ 35 │ │ │ │ │
684 └────┴────┘ │ 3 7 11
685
686 */
687 // On a un cube décomposé en huit cellules (2x2x2).
688 // Le schéma au-dessus représente les faces des cellules de ce cube avec
689 // les uniqueIDs que l'algorithme génèrera (sans face_adder).
690 // Pour cet algo, on commence par les faces "xy".
691 // On énumère d'abord en x, puis en y, puis en z.
692 // Une fois les faces "xy" numérotées, on fait les faces "yz".
693 // Toujours le même ordre de numérotation.
694 // On termine avec les faces "zx", encore dans le même ordre.
695 //
696 // Dans l'implémentation ci-dessous, on fait la numérotation
697 // maille par maille.
698 //const Int64 total_face_xy = grid_nb_face.z * current_level_nb_cell_x * current_level_nb_cell_y;
699 //const Int64 total_face_xy_yz = total_face_xy + grid_nb_face.x * current_level_nb_cell_y * current_level_nb_cell_z;
700 //const Int64 total_face_xy_yz_zx = total_face_xy_yz + grid_nb_face.y * current_level_nb_cell_z * current_level_nb_cell_x;
701 {
702 std::array<Int64, 6> face_uids = face_uid_computer.computeForCell(coord_i, coord_j, coord_k);
703
704 for (Integer z = 0; z < 6; ++z) {
705 Face face = cell.face(z);
706 if (new_uids.faces[face] < 0) {
707 const bool do_print = false;
708 if (do_print) {
709 info() << "Parent_cell=" << cell.uniqueId() << " level=" << cell.level()
710 << " face_adder=" << face_adder << " z=" << z
711 << " x=" << coord_i << " y=" << coord_j << " z=" << coord_k
712 << " cx=" << current_level_nb_cell_x << " cy=" << current_level_nb_cell_y << " cz=" << current_level_nb_cell_z;
713 }
714 if (m_is_verbose || do_print)
715 info() << "APPLY_FACE_CHILD: uid=" << face.uniqueId() << " parent_cell=" << cell.uniqueId()
716 << " I=" << z << " new_uid=" << face_uids[z];
717 new_uids.faces[face] = face_uids[z];
718 }
719 }
720 }
721
722 // Renumérote les sous-mailles
723 // Suppose qu'on a 8 mailles enfants (2x2x2) comme suit par mailles
724 // -------
725 // | 2| 3|
726 // -------
727 // | 0| 1|
728 // -------
729 cell_adder += grid.totalNbCell();
730 node_adder += grid_nb_node.x * grid_nb_node.y * grid_nb_node.z;
731 face_adder += grid_nb_face.x * grid_nb_face.y * grid_nb_face.z;
732
733 current_level += 1;
734
735 Int32 nb_child = cell.nbHChildren();
736 for (Int32 icell = 0; icell < nb_child; ++icell) {
737 Cell sub_cell = cell.hChild(icell);
738 Int64 my_coord_i = coord_i + icell % 2;
739 Int64 my_coord_j = coord_j + (icell % 4) / 2;
740 Int64 my_coord_k = coord_k + icell / 4;
741
742 _applyChildrenCell3DV2(sub_cell, new_uids, my_coord_i, my_coord_j, my_coord_k,
743 current_level_nb_cell_x, current_level_nb_cell_y, current_level_nb_cell_z,
744 current_level, cell_adder, node_adder, face_adder);
745 }
746}
747
748/*---------------------------------------------------------------------------*/
749/*---------------------------------------------------------------------------*/
750
751} // End namespace Arcane
752
753/*---------------------------------------------------------------------------*/
754/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Fonctions utilitaires sur le maillage.
Patch AMR d'un maillage cartésien.
CellGroup cells()
Groupe de mailles du patch.
Maille d'un maillage.
Definition Item.h:1178
Face d'une maille.
Definition Item.h:932
Informations sur la génération des maillages cartésiens.
Interface d'un maillage cartésien.
virtual IMesh * mesh() const =0
Maillage associé à ce maillage cartésien.
virtual ICartesianMeshPatch * patch(Int32 index) const =0
Retourne le index-ième patch du maillage.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual String name() const =0
Nom du maillage.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual void checkValidMesh()=0
Vérification de la validité des structues internes de maillage (interne)
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Noeud d'un maillage.
Definition Dom.h:204
Paramètres nécessaires à la construction d'une variable.
TraceMessage info() const
Flot pour un message d'information.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
ItemVariableScalarRefT< Int64 > VariableItemInt64
Grandeur de type entier 64 bits.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:638