Arcane  v3.16.0.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
44 NewUniqueIdList(IMesh* mesh)
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,
111 CartesianPatch parent_patch, Int32 patch_method)
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.
bool isNull() const
Indique si le patch est nul.
Maille d'un maillage.
Definition Item.h:1191
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1272
Face d'une maille.
Definition Item.h:944
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 IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
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.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Noeud d'un maillage.
Definition Item.h:573
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Paramètres nécessaires à la construction d'une variable.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Grandeur au centre des mailles de type entier 64 bits.
ItemVariableScalarRefT< Int64 > VariableItemInt64
Grandeur de type entier 64 bits.
MeshVariableScalarRefT< Node, Int64 > VariableNodeInt64
Grandeur au noeud de type entier 64 bits.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Grandeur aux faces de type entier 64 bits.
@ ReduceMax
Maximum des valeurs.
ARCCORE_BASE_EXPORT String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:567
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
std::int32_t Int32
Type entier signé sur 32 bits.