Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CartesianMeshCoarsening2.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/* CartesianMeshCoarsening.cc (C) 2000-2024 */
9/* */
10/* Déraffinement d'un maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/CartesianMeshCoarsening2.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ValueConvert.h"
18#include "arcane/utils/SmallArray.h"
19
20#include "arcane/core/IMesh.h"
21#include "arcane/core/ItemGroup.h"
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/CartesianGridDimension.h"
24#include "arcane/core/IMeshModifier.h"
25#include "arcane/core/SimpleSVGMeshExporter.h"
26#include "arcane/core/ItemPrinter.h"
27#include "arcane/core/MeshStats.h"
28#include "arcane/core/IGhostLayerMng.h"
29
30#include "arcane/mesh/CellFamily.h"
31
32#include "arcane/cartesianmesh/ICartesianMesh.h"
33#include "arcane/cartesianmesh/CellDirectionMng.h"
34#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
35
36#include <unordered_set>
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47CartesianMeshCoarsening2::
48CartesianMeshCoarsening2(ICartesianMesh* m)
49: TraceAccessor(m->traceMng())
50, m_cartesian_mesh(m)
51{
52 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CARTESIANMESH_COARSENING_VERBOSITY_LEVEL", true))
53 m_verbosity_level = v.value();
54}
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58
59//! Retourne le max des uniqueId() des entités de \a group
60Int64 CartesianMeshCoarsening2::
61_getMaxUniqueId(const ItemGroup& group)
62{
63 Int64 max_offset = 0;
64 ENUMERATE_ (Item, iitem, group) {
65 Item item = *iitem;
66 if (max_offset < item.uniqueId())
67 max_offset = item.uniqueId();
68 }
69 return max_offset;
70}
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75void CartesianMeshCoarsening2::
76_writeMeshSVG(const String& name)
77{
78 if (m_verbosity_level <= 0)
79 return;
80 IMesh* mesh = m_cartesian_mesh->mesh();
81 if (mesh->dimension() != 2)
82 return;
83 IParallelMng* pm = mesh->parallelMng();
84 const Int32 mesh_rank = pm->commRank();
85 String filename = String::format("mesh_{0}_{1}.svg", name, mesh_rank);
86 info() << "WriteMesh name=" << filename;
87 std::ofstream ofile(filename.localstr());
88 SimpleSVGMeshExporter writer(ofile);
89 writer.write(mesh->allCells());
90}
91
92/*---------------------------------------------------------------------------*/
93/*---------------------------------------------------------------------------*/
94/*!
95 * \brief Double la couche de mailles fantômes du maillage initial.
96 *
97 * Cela permettra ensuite d'avoir la bonne valeur de couches de mailles
98 * fantômes pour le maillage final grossier.
99 */
100void CartesianMeshCoarsening2::
101_doDoubleGhostLayers()
102{
103 IMesh* mesh = m_cartesian_mesh->mesh();
104 IMeshModifier* mesh_modifier = mesh->modifier();
105 IGhostLayerMng* gm = mesh->ghostLayerMng();
106 // Il faut au moins utiliser la version 3 pour pouvoir supporter
107 // plusieurs couches de mailles fantômes
108 Int32 version = gm->builderVersion();
109 if (version < 3)
110 gm->setBuilderVersion(3);
111 Int32 nb_ghost_layer = gm->nbGhostLayer();
112 gm->setNbGhostLayer(nb_ghost_layer * 2);
113 mesh_modifier->setDynamic(true);
114 mesh_modifier->updateGhostLayers();
115 // Remet le nombre initial de couches de mailles fantômes
116 gm->setNbGhostLayer(nb_ghost_layer);
117
118 // Comme le nombre d'entités a été modifié, il faut recalculer les directions
119 m_cartesian_mesh->computeDirections();
120
121 // Écrit le nouveau maillage
122 _writeMeshSVG("double_ghost");
123}
124
125/*---------------------------------------------------------------------------*/
126/*---------------------------------------------------------------------------*/
127
128void CartesianMeshCoarsening2::
129createCoarseCells()
130{
131 if (m_is_create_coarse_called)
132 ARCANE_FATAL("This method has already been called");
133 m_is_create_coarse_called = true;
134
135 const bool is_verbose = m_verbosity_level > 0;
136 IMesh* mesh = m_cartesian_mesh->mesh();
137 IParallelMng* pm = mesh->parallelMng();
138 Integer nb_patch = m_cartesian_mesh->nbPatch();
139 if (nb_patch != 1)
140 ARCANE_FATAL("This method is only valid for 1 patch (nb_patch={0})", nb_patch);
141
142 if (!mesh->isAmrActivated())
143 ARCANE_FATAL("AMR is not activated for this case");
144
145 Integer nb_dir = mesh->dimension();
146 if (nb_dir != 2 && nb_dir != 3)
147 ARCANE_FATAL("This method is only valid for 2D or 3D mesh (dim={0})", nb_dir);
148
149 info() << "CoarseCartesianMesh nb_direction=" << nb_dir;
150
151 for (Integer idir = 0; idir < nb_dir; ++idir) {
152 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
153 Int32 nb_own_cell = cdm.ownNbCell();
154 info() << "NB_OWN_CELL dir=" << idir << " n=" << nb_own_cell;
155 if ((nb_own_cell % 2) != 0)
156 ARCANE_FATAL("Invalid number of cells ({0}) for direction {1}. Should be a multiple of 2",
157 nb_own_cell, idir);
158 }
159
160 _writeMeshSVG("orig");
161
162 // Double la couche de mailles fantômes
163 _doDoubleGhostLayers();
164
165 if (is_verbose) {
166 SmallArray<Int64, 8> uids;
167 ENUMERATE_ (Cell, icell, mesh->allCells()) {
168 Cell cell = *icell;
169 info() << "Orig cell=" << ItemPrinter(cell) << " Face0=" << cell.face(0).uniqueId()
170 << " Face1=" << cell.face(1).uniqueId() << " level=" << cell.level();
171 Int32 nb_node = cell.nbNode();
172 uids.resize(nb_node);
173 for (Int32 i = 0; i < nb_node; ++i)
174 uids[i] = cell.node(i).uniqueId();
175 info() << "Orig cell_uid=" << cell.uniqueId() << " Nodes=" << uids;
176 Int32 nb_face = cell.nbFace();
177 uids.resize(nb_face);
178 for (Int32 i = 0; i < nb_face; ++i)
179 uids[i] = cell.face(i).uniqueId();
180 info() << "Orig cell_uid=" << cell.uniqueId() << " Faces=" << uids;
181 }
182 }
183
184 // Calcul l'offset pour la création des uniqueId().
185 // On prend comme offset le max des uniqueId() des faces et des mailles.
186 // A terme avec la numérotation cartésienne partout, on pourra déterminer
187 // directement cette valeur
188 Int64 max_cell_uid = _getMaxUniqueId(mesh->allCells());
189 Int64 max_face_uid = _getMaxUniqueId(mesh->allFaces());
190 const Int64 coarse_grid_cell_offset = 1 + pm->reduce(Parallel::ReduceMax, math::max(max_cell_uid, max_face_uid));
191 m_first_own_cell_unique_id_offset = coarse_grid_cell_offset;
192 info() << "FirstCellUniqueIdOffset=" << m_first_own_cell_unique_id_offset;
193 if (nb_dir == 3)
194 _createCoarseCells3D();
195 else if (nb_dir == 2)
196 _createCoarseCells2D();
197 else
198 ARCANE_FATAL("Invalid dimension '{0}'", nb_dir);
199
200 mesh->modifier()->endUpdate();
201
202 if (is_verbose) {
203 ENUMERATE_ (Cell, icell, mesh->allCells()) {
204 Cell cell = *icell;
205 info() << "Final cell=" << ItemPrinter(cell) << " Face0=" << cell.face(0).uniqueId()
206 << " Face1=" << cell.face(1).uniqueId() << " level=" << cell.level();
207 }
208 }
209
210 _recomputeMeshGenerationInfo();
211
212 // Affiche les statistiques du nouveau maillage
213 {
214 MeshStats ms(traceMng(), mesh, mesh->parallelMng());
215 ms.dumpStats();
216 }
217
218 //! Créé le patch avec les mailles filles
219 {
220 CellGroup parent_cells = mesh->allLevelCells(0);
221 m_cartesian_mesh->_internalApi()->addPatchFromExistingChildren(parent_cells.view().localIds());
222 }
223
224 // Recalcule les informations de synchronisation
225 // Cela n'est pas nécessaire pour l'AMR car ces informations seront recalculées
226 // lors du raffinement mais comme on ne sais pas si on va faire du raffinement
227 // après il est préférable de calculer ces informations dans tous les cas.
229
230 // Il faut recalculer les nouvelles directions après les modifications
231 // et l'ajout de patch.
232 m_cartesian_mesh->computeDirections();
233
234 _writeMeshSVG("coarse");
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240void CartesianMeshCoarsening2::
241_createCoarseCells2D()
242{
243 const bool is_verbose = m_verbosity_level > 0;
244 IMesh* mesh = m_cartesian_mesh->mesh();
245 IParallelMng* pm = mesh->parallelMng();
246 const Int32 my_rank = pm->commRank();
247
248 CellDirectionMng cdm_x(m_cartesian_mesh->cellDirection(0));
249 CellDirectionMng cdm_y(m_cartesian_mesh->cellDirection(1));
250
251 const Int64 global_nb_cell_x = cdm_x.globalNbCell();
252 const Int64 global_nb_cell_y = cdm_y.globalNbCell();
253 CartesianGridDimension refined_grid_dim(global_nb_cell_x, global_nb_cell_y);
254 CartesianGridDimension coarse_grid_dim(global_nb_cell_x / 2, global_nb_cell_y / 2);
255 CartesianGridDimension::CellUniqueIdComputer2D refined_cell_uid_computer(refined_grid_dim.getCellComputer2D(0));
256 CartesianGridDimension::NodeUniqueIdComputer2D refined_node_uid_computer(refined_grid_dim.getNodeComputer2D(0));
257 CartesianGridDimension::CellUniqueIdComputer2D coarse_cell_uid_computer(coarse_grid_dim.getCellComputer2D(m_first_own_cell_unique_id_offset));
258 CartesianGridDimension::FaceUniqueIdComputer2D coarse_face_uid_computer(coarse_grid_dim.getFaceComputer2D(m_first_own_cell_unique_id_offset));
259
260 // Pour les mailles et faces grossières, les noeuds existent déjà
261 // On ne peut donc pas utiliser la connectivité cartésienne de la grille grossière
262 // pour eux (on pourra le faire lorsque l'AMR par patch avec duplication sera active)
263 // En attendant on utilise la numérotation de la grille raffinée.
264
265 // TODO: Calculer en avance le nombre de faces et de mailles et allouer en conséquence.
266 UniqueArray<Int64> faces_infos;
267 UniqueArray<Int64> cells_infos;
268 Int32 nb_coarse_face = 0;
269 Int32 nb_coarse_cell = 0;
270 //! Liste de la première fille de chaque maille grossière
271 UniqueArray<Cell> first_child_cells;
272
273 UniqueArray<Int64> refined_cells_lids;
274 UniqueArray<Int32> coarse_cells_owner;
275 UniqueArray<Int32> coarse_faces_owner;
276
277 ENUMERATE_ (Cell, icell, mesh->allCells()) {
278 Cell cell = *icell;
279 Int64 cell_uid = cell.uniqueId();
280 Int64x3 cell_xy = refined_cell_uid_computer.compute(cell_uid);
281 const Int64 cell_x = cell_xy.x;
282 const Int64 cell_y = cell_xy.y;
283 // Nécessaire pour le recalcul des mailles fantômes. On considère ces
284 // mailles comme si elles venaient juste d'être raffinées.
285 cell.mutableItemBase().addFlags(ItemFlags::II_JustRefined);
286 // Comme on déraffine par 2, ne prend que les mailles dont les coordoonnées
287 // topologiques sont paires
288 if ((cell_x % 2) != 0 || (cell_y % 2) != 0)
289 continue;
290 if (is_verbose)
291 info() << "CellToCoarse refined_uid=" << cell_uid << " x=" << cell_x << " y=" << cell_y;
292 coarse_cells_owner.add(cell.owner());
293 const Int64 coarse_cell_x = cell_x / 2;
294 const Int64 coarse_cell_y = cell_y / 2;
295 std::array<Int64, 4> node_uids_container;
296 ArrayView<Int64> node_uids(node_uids_container);
297 node_uids[0] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 0);
298 node_uids[1] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 0);
299 node_uids[2] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 2);
300 node_uids[3] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 2);
301 if (is_verbose)
302 info() << "CELLNodes uid=" << node_uids;
303 std::array<Int64, 4> coarse_face_uids = coarse_face_uid_computer.computeForCell(coarse_cell_x, coarse_cell_y);
304 const ItemTypeInfo* cell_type = cell.typeInfo();
305 // Ajoute les 4 faces
306 for (Int32 z = 0; z < 4; ++z) {
307 ItemTypeInfo::LocalFace lface = cell_type->localFace(z);
308 faces_infos.add(IT_Line2);
309 faces_infos.add(coarse_face_uids[z]);
310 Int64 node_uid0 = node_uids[lface.node(0)];
311 Int64 node_uid1 = node_uids[lface.node(1)];
312
313 if (node_uid0 > node_uid1)
314 std::swap(node_uid0, node_uid1);
315 if (is_verbose)
316 info() << "ADD_FACE coarse_uid=" << coarse_face_uids[z] << " n0=" << node_uid0 << " n1=" << node_uid1;
317 faces_infos.add(node_uid0);
318 faces_infos.add(node_uid1);
319 ++nb_coarse_face;
320 }
321 // Ajoute la maille
322 {
323 cells_infos.add(IT_Quad4);
324 Int64 coarse_cell_uid = coarse_cell_uid_computer.compute(coarse_cell_x, coarse_cell_y);
325 cells_infos.add(coarse_cell_uid);
326 if (is_verbose)
327 info() << "CoarseCellUid=" << coarse_cell_uid;
328 m_coarse_cells_uid.add(coarse_cell_uid);
329 for (Int32 z = 0; z < 4; ++z)
330 cells_infos.add(node_uids[z]);
331 ++nb_coarse_cell;
332 first_child_cells.add(cell);
333 }
334 // A partir de la première sous-maille, on peut connaitre les 3 autres
335 // car elles sont respectivement à droite, en haut à droite et en haut.
336 {
337 std::array<Int32, 4> sub_cell_lids_container;
338 ArrayView<Int32> sub_lids(sub_cell_lids_container);
339 Cell cell1 = cdm_x[cell].next();
340 // Vérifie la validité des sous-mailles.
341 // Normalement il ne devrait pas y avoir de problèmes sauf si le
342 // nombre de mailles dans chaque direction du sous-domaine
343 // n'est pas un nombre pair.
344 if (cell1.null())
345 ARCANE_FATAL("Bad right cell for cell {0}", ItemPrinter(cell));
346 Cell cell2 = cdm_y[cell1].next();
347 if (cell2.null())
348 ARCANE_FATAL("Bad upper right cell for cell {0}", ItemPrinter(cell));
349 Cell cell3 = cdm_y[cell].next();
350 if (cell3.null())
351 ARCANE_FATAL("Bad upper cell for cell {0}", ItemPrinter(cell));
352 sub_lids[0] = cell.localId();
353 sub_lids[1] = cell1.localId();
354 sub_lids[2] = cell2.localId();
355 sub_lids[3] = cell3.localId();
356 // Il faudra donner un propriétaire aux faces.
357 // Ces nouvelles faces auront le même propriétaire que les faces raffinées
358 // auquelles elles correspondent
359 //info() << "CELL_NB_FACE=" << cell.nbFace() << " " << cell1.nbFace() << " " << cell2.nbFace() << " " << cell3.nbFace();
360 coarse_faces_owner.add(cell.face(0).owner());
361 coarse_faces_owner.add(cell1.face(1).owner());
362 coarse_faces_owner.add(cell2.face(2).owner());
363 coarse_faces_owner.add(cell3.face(3).owner());
364 for (Int32 i = 0; i < 4; ++i)
365 refined_cells_lids.add(sub_lids[i]);
366 }
367 }
368
369 // Construit les faces
370 UniqueArray<Int32> faces_local_ids(nb_coarse_face);
371 mesh->modifier()->addFaces(nb_coarse_face, faces_infos, faces_local_ids);
372
373 // Construit les mailles
374 // Indique qu'on n'a pas le droit de construire à la volée les faces.
375 // Normalement elles ont toutes été ajoutées via addFaces();
376 UniqueArray<Int32> cells_local_ids(nb_coarse_cell);
377 MeshModifierAddCellsArgs add_cells_args(nb_coarse_cell, cells_infos, cells_local_ids);
378 add_cells_args.setAllowBuildFaces(false);
379 mesh->modifier()->addCells(add_cells_args);
380
381 IItemFamily* cell_family = mesh->cellFamily();
382
383 // Maintenant que les mailles grossières sont créées, il faut indiquer
384 // qu'elles sont parentes.
385 using mesh::CellFamily;
386 CellInfoListView cells(mesh->cellFamily());
387 CellFamily* true_cell_family = ARCANE_CHECK_POINTER(dynamic_cast<CellFamily*>(cell_family));
388 std::array<Int32, 4> sub_cell_lids_container;
389 ArrayView<Int32> sub_cell_lids(sub_cell_lids_container);
390 for (Int32 i = 0; i < nb_coarse_cell; ++i) {
391 Int32 coarse_cell_lid = cells_local_ids[i];
392 Cell coarse_cell = cells[coarse_cell_lid];
393 Cell first_child_cell = first_child_cells[i];
394 // A partir de la première sous-maille, on peut connaitre les 3 autres
395 // car elles sont respectivement à droite, en haut à droite et en haut.
396 sub_cell_lids[0] = first_child_cell.localId();
397 sub_cell_lids[1] = cdm_x[first_child_cell].next().localId();
398 sub_cell_lids[2] = cdm_y[CellLocalId(sub_cell_lids[1])].next().localId();
399 sub_cell_lids[3] = cdm_y[first_child_cell].next().localId();
400 if (is_verbose)
401 info() << "AddChildForCoarseCell i=" << i << " coarse=" << ItemPrinter(coarse_cell)
402 << " children_lid=" << sub_cell_lids;
403 for (Int32 z = 0; z < 4; ++z) {
404 Cell child_cell = cells[sub_cell_lids[z]];
405 if (is_verbose)
406 info() << " AddParentCellToCell: z=" << z << " child=" << ItemPrinter(child_cell);
407 true_cell_family->_addParentCellToCell(child_cell, coarse_cell);
408 }
409 true_cell_family->_addChildrenCellsToCell(coarse_cell, sub_cell_lids);
410 }
411
412 // Positionne les propriétaires des nouvelles mailles et faces
413 {
414 IItemFamily* face_family = mesh->faceFamily();
415 Int32 index = 0;
416 ENUMERATE_ (Cell, icell, cell_family->view(cells_local_ids)) {
417 Cell cell = *icell;
418 Int32 owner = coarse_cells_owner[index];
419 cell.mutableItemBase().setOwner(owner, my_rank);
420 const Int64 sub_cell_index = index * 4;
421 for (Int32 z = 0; z < 4; ++z) {
422 cell.face(z).mutableItemBase().setOwner(coarse_faces_owner[sub_cell_index + z], my_rank);
423 }
424 ++index;
425 }
426 cell_family->notifyItemsOwnerChanged();
427 face_family->notifyItemsOwnerChanged();
428 }
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
434void CartesianMeshCoarsening2::
435_createCoarseCells3D()
436{
437 const bool is_verbose = m_verbosity_level > 0;
438 IMesh* mesh = m_cartesian_mesh->mesh();
439 IParallelMng* pm = mesh->parallelMng();
440 const Int32 my_rank = pm->commRank();
441
442 CellDirectionMng cdm_x(m_cartesian_mesh->cellDirection(0));
443 CellDirectionMng cdm_y(m_cartesian_mesh->cellDirection(1));
444 CellDirectionMng cdm_z(m_cartesian_mesh->cellDirection(2));
445
446 const Int64 global_nb_cell_x = cdm_x.globalNbCell();
447 const Int64 global_nb_cell_y = cdm_y.globalNbCell();
448 const Int64 global_nb_cell_z = cdm_z.globalNbCell();
449 CartesianGridDimension refined_grid_dim(global_nb_cell_x, global_nb_cell_y, global_nb_cell_z);
450 CartesianGridDimension coarse_grid_dim(global_nb_cell_x / 2, global_nb_cell_y / 2, global_nb_cell_z / 2);
451 CartesianGridDimension::CellUniqueIdComputer3D refined_cell_uid_computer(refined_grid_dim.getCellComputer3D(0));
452 CartesianGridDimension::NodeUniqueIdComputer3D refined_node_uid_computer(refined_grid_dim.getNodeComputer3D(0));
453 CartesianGridDimension::CellUniqueIdComputer3D coarse_cell_uid_computer(coarse_grid_dim.getCellComputer3D(m_first_own_cell_unique_id_offset));
454 CartesianGridDimension::FaceUniqueIdComputer3D coarse_face_uid_computer(coarse_grid_dim.getFaceComputer3D(m_first_own_cell_unique_id_offset));
455
456 // Pour les mailles et faces grossières, les noeuds existent déjà
457 // On ne peut donc pas utiliser la connectivité cartésienne de la grille grossière
458 // pour eux (on pourra le faire lorsque l'AMR par patch avec duplication sera active)
459 // En attendant on utilise la numérotation de la grille raffinée.
460
461 // TODO: Calculer en avance le nombre de faces et de mailles et allouer en conséquence.
462 UniqueArray<Int64> faces_infos;
463 UniqueArray<Int64> cells_infos;
464 Int32 nb_coarse_face = 0;
465 Int32 nb_coarse_cell = 0;
466 //! Liste de la première fille de chaque maille grossière
467 UniqueArray<Cell> first_child_cells;
468
469 UniqueArray<Int64> refined_cells_lids;
470 UniqueArray<Int32> coarse_cells_owner;
471 UniqueArray<Int32> coarse_faces_owner;
472
473 static constexpr Int32 const_cell_nb_node = 8;
474 static constexpr Int32 const_cell_nb_face = 6;
475 static constexpr Int32 const_cell_nb_sub_cell = 8;
476 static constexpr Int32 const_face_nb_node = 4;
477
478 // Liste des uniqueId() des noeuds des faces créées
479 SmallArray<Int64, const_face_nb_node> face_node_uids(const_face_nb_node);
480 // Liste ordonnée des noeuds des faces créées
481 SmallArray<Int64, const_face_nb_node> face_sorted_node_uids(const_face_nb_node);
482 ENUMERATE_ (Cell, icell, mesh->allCells()) {
483 Cell cell = *icell;
484 Int64 cell_uid = cell.uniqueId();
485 Int64x3 cell_xyz = refined_cell_uid_computer.compute(cell_uid);
486 const Int64 cell_x = cell_xyz.x;
487 const Int64 cell_y = cell_xyz.y;
488 const Int64 cell_z = cell_xyz.z;
489 // Nécessaire pour le recalcul des mailles fantômes. On considère ces
490 // mailles comme si elles venaient juste d'être raffinées.
491 cell.mutableItemBase().addFlags(ItemFlags::II_JustRefined);
492 // Comme on déraffine par 2, ne prend que les mailles dont les coordoonnées
493 // topologiques sont paires
494 if ((cell_x % 2) != 0 || (cell_y % 2) != 0 || (cell_z % 2) != 0)
495 continue;
496 if (is_verbose)
497 info() << "CellToCoarse refined_uid=" << cell_uid << " x=" << cell_x << " y=" << cell_y << " z=" << cell_z;
498 coarse_cells_owner.add(cell.owner());
499 const Int64 coarse_cell_x = cell_x / 2;
500 const Int64 coarse_cell_y = cell_y / 2;
501 const Int64 coarse_cell_z = cell_z / 2;
502 std::array<Int64, const_cell_nb_node> node_uids_container;
503 ArrayView<Int64> node_uids(node_uids_container);
504 node_uids[0] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 0, cell_z + 0);
505 node_uids[1] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 0, cell_z + 0);
506 node_uids[2] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 2, cell_z + 0);
507 node_uids[3] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 2, cell_z + 0);
508 node_uids[4] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 0, cell_z + 2);
509 node_uids[5] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 0, cell_z + 2);
510 node_uids[6] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 2, cell_z + 2);
511 node_uids[7] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 2, cell_z + 2);
512 if (is_verbose)
513 info() << "CELLNodes uid=" << node_uids;
514 std::array<Int64, const_cell_nb_face> coarse_face_uids = coarse_face_uid_computer.computeForCell(coarse_cell_x, coarse_cell_y, coarse_cell_z);
515 const ItemTypeInfo* cell_type = cell.typeInfo();
516
517 // Ajoute les 6 faces
518 for (Int32 z = 0; z < const_cell_nb_face; ++z) {
519 ItemTypeInfo::LocalFace lface = cell_type->localFace(z);
520 faces_infos.add(IT_Quad4);
521 faces_infos.add(coarse_face_uids[z]);
522 for (Int32 knode = 0; knode < const_face_nb_node; ++knode)
523 face_node_uids[knode] = node_uids[lface.node(knode)];
524 MeshUtils::reorderNodesOfFace(face_node_uids, face_sorted_node_uids);
525 if (is_verbose)
526 info() << "ADD_FACE coarse_uid=" << coarse_face_uids[z] << " n=" << face_sorted_node_uids;
527 faces_infos.addRange(face_sorted_node_uids);
528 ++nb_coarse_face;
529 }
530
531 // Ajoute la maille
532 {
533 cells_infos.add(IT_Hexaedron8);
534 Int64 coarse_cell_uid = coarse_cell_uid_computer.compute(coarse_cell_x, coarse_cell_y, coarse_cell_z);
535 cells_infos.add(coarse_cell_uid);
536 if (is_verbose)
537 info() << "CoarseCellUid=" << coarse_cell_uid;
538 m_coarse_cells_uid.add(coarse_cell_uid);
539 for (Int32 z = 0; z < const_cell_nb_node; ++z)
540 cells_infos.add(node_uids[z]);
541 ++nb_coarse_cell;
542 first_child_cells.add(cell);
543 }
544
545 // A partir de la première sous-maille, on peut connaitre les 7 autres
546 // car elles sont respectivement à droite, en haut à droite et en haut,
547 // au dessus, au dessus à droit, au dessus en haut à droit et .
548 {
549 std::array<Int32, const_cell_nb_sub_cell> sub_cell_lids_container;
550 ArrayView<Int32> sub_lids(sub_cell_lids_container);
551 Cell cell1 = cdm_x[cell].next();
552 // Vérifie la validité des sous-mailles.
553 // Normalement il ne devrait pas y avoir de problèmes sauf si le
554 // nombre de mailles dans chaque direction du sous-domaine
555 // n'est pas un nombre pair.
556 if (cell1.null())
557 ARCANE_FATAL("Bad right cell for cell {0}", ItemPrinter(cell));
558 Cell cell2 = cdm_y[cell1].next();
559 if (cell2.null())
560 ARCANE_FATAL("Bad upper right cell for cell {0}", ItemPrinter(cell));
561 Cell cell3 = cdm_y[cell].next();
562 if (cell3.null())
563 ARCANE_FATAL("Bad upper cell for cell {0}", ItemPrinter(cell));
564
565 Cell cell4 = cdm_z[cell].next();
566 if (cell4.null())
567 ARCANE_FATAL("Bad top cell for cell {0}", ItemPrinter(cell));
568
569 Cell cell5 = cdm_x[cell4].next();
570 if (cell5.null())
571 ARCANE_FATAL("Bad top right cell for cell {0}", ItemPrinter(cell));
572 Cell cell6 = cdm_y[cell5].next();
573 if (cell6.null())
574 ARCANE_FATAL("Bad top upper right cell for cell {0}", ItemPrinter(cell));
575 Cell cell7 = cdm_y[cell4].next();
576 if (cell7.null())
577 ARCANE_FATAL("Bad top upper cell for cell {0}", ItemPrinter(cell));
578
579 sub_lids[0] = cell.localId();
580 sub_lids[1] = cell1.localId();
581 sub_lids[2] = cell2.localId();
582 sub_lids[3] = cell3.localId();
583 sub_lids[4] = cell4.localId();
584 sub_lids[5] = cell5.localId();
585 sub_lids[6] = cell6.localId();
586 sub_lids[7] = cell7.localId();
587 // Il faudra donner un propriétaire aux faces.
588 // Ces nouvelles faces auront le même propriétaire que les faces raffinées
589 // auquelles elles correspondent
590 //info() << "CELL_NB_FACE=" << cell.nbFace() << " " << cell1.nbFace() << " " << cell2.nbFace() << " " << cell3.nbFace();
591 coarse_faces_owner.add(cell.face(0).owner());
592 coarse_faces_owner.add(cell1.face(1).owner());
593 coarse_faces_owner.add(cell2.face(2).owner());
594 coarse_faces_owner.add(cell3.face(3).owner());
595
596 coarse_faces_owner.add(cell4.face(4).owner());
597 coarse_faces_owner.add(cell5.face(5).owner());
598
599 for (Int32 i = 0; i < const_cell_nb_sub_cell; ++i)
600 refined_cells_lids.add(sub_lids[i]);
601 }
602 }
603
604 // Construit les faces
605 UniqueArray<Int32> faces_local_ids(nb_coarse_face);
606 mesh->modifier()->addFaces(nb_coarse_face, faces_infos, faces_local_ids);
607
608 // Construit les mailles
609 // Indique qu'on n'a pas le droit de construire à la volée les faces.
610 // Normalement elles ont toutes été ajoutées via addFaces();
611 UniqueArray<Int32> cells_local_ids(nb_coarse_cell);
612 MeshModifierAddCellsArgs add_cells_args(nb_coarse_cell, cells_infos, cells_local_ids);
613 add_cells_args.setAllowBuildFaces(false);
614 mesh->modifier()->addCells(add_cells_args);
615
616 IItemFamily* cell_family = mesh->cellFamily();
617
618 // Maintenant que les mailles grossières sont créées, il faut indiquer
619 // qu'elles sont parentes.
620 using mesh::CellFamily;
621 CellInfoListView cells(mesh->cellFamily());
622 CellFamily* true_cell_family = ARCANE_CHECK_POINTER(dynamic_cast<CellFamily*>(cell_family));
623 std::array<Int32, const_cell_nb_sub_cell> sub_cell_lids_container;
624 ArrayView<Int32> sub_cell_lids(sub_cell_lids_container);
625 for (Int32 i = 0; i < nb_coarse_cell; ++i) {
626 Int32 coarse_cell_lid = cells_local_ids[i];
627 Cell coarse_cell = cells[coarse_cell_lid];
628 Cell first_child_cell = first_child_cells[i];
629 // A partir de la première sous-maille, on peut connaitre les 3 autres
630 // car elles sont respectivement à droite, en haut à droite et en haut.
631 sub_cell_lids[0] = first_child_cell.localId();
632 sub_cell_lids[1] = cdm_x[first_child_cell].next().localId();
633 sub_cell_lids[2] = cdm_y[CellLocalId(sub_cell_lids[1])].next().localId();
634 sub_cell_lids[3] = cdm_y[first_child_cell].next().localId();
635
636 Cell top_first_child_cell = cdm_z[first_child_cell].next();
637 sub_cell_lids[4] = top_first_child_cell.localId();
638 sub_cell_lids[5] = cdm_x[top_first_child_cell].next().localId();
639 sub_cell_lids[6] = cdm_y[CellLocalId(sub_cell_lids[5])].next().localId();
640 sub_cell_lids[7] = cdm_y[top_first_child_cell].next().localId();
641
642 if (is_verbose)
643 info() << "AddChildForCoarseCell i=" << i << " coarse=" << ItemPrinter(coarse_cell)
644 << " children_lid=" << sub_cell_lids;
645 for (Int32 z = 0; z < const_cell_nb_sub_cell; ++z) {
646 Cell child_cell = cells[sub_cell_lids[z]];
647 if (is_verbose)
648 info() << " AddParentCellToCell: z=" << z << " child=" << ItemPrinter(child_cell);
649 true_cell_family->_addParentCellToCell(child_cell, coarse_cell);
650 }
651 true_cell_family->_addChildrenCellsToCell(coarse_cell, sub_cell_lids);
652 }
653
654 // Positionne les propriétaires des nouvelles mailles et faces
655 {
656 IItemFamily* face_family = mesh->faceFamily();
657 Int32 index = 0;
658 ENUMERATE_ (Cell, icell, cell_family->view(cells_local_ids)) {
659 Cell cell = *icell;
660 Int32 owner = coarse_cells_owner[index];
661 cell.mutableItemBase().setOwner(owner, my_rank);
662 const Int64 sub_cell_index = index * const_cell_nb_face;
663 for (Int32 z = 0; z < const_cell_nb_face; ++z) {
664 cell.face(z).mutableItemBase().setOwner(coarse_faces_owner[sub_cell_index + z], my_rank);
665 }
666 ++index;
667 }
668 cell_family->notifyItemsOwnerChanged();
669 face_family->notifyItemsOwnerChanged();
670 }
671}
672
673/*---------------------------------------------------------------------------*/
674/*---------------------------------------------------------------------------*/
675/*!
676 * \brief Recalcule les informations sur le nombre de mailles par direction.
677 */
678void CartesianMeshCoarsening2::
679_recomputeMeshGenerationInfo()
680{
681 IMesh* mesh = m_cartesian_mesh->mesh();
682 auto* cmgi = ICartesianMeshGenerationInfo::getReference(mesh, false);
683 if (!cmgi)
684 return;
685
686 // Coefficient de dé-raffinement
687 const Int32 cf = 2;
688
689 {
690 ConstArrayView<Int64> v = cmgi->ownCellOffsets();
691 cmgi->setOwnCellOffsets(v[0] / cf, v[1] / cf, v[2] / cf);
692 }
693 {
694 ConstArrayView<Int64> v = cmgi->globalNbCells();
695 cmgi->setGlobalNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
696 }
697 {
698 ConstArrayView<Int32> v = cmgi->ownNbCells();
699 cmgi->setOwnNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
700 }
701 cmgi->setFirstOwnCellUniqueId(m_first_own_cell_unique_id_offset);
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706
707void CartesianMeshCoarsening2::
708removeRefinedCells()
709{
710 if (!m_is_create_coarse_called)
711 ARCANE_FATAL("You need to call createCoarseCells() before");
712 if (m_is_remove_refined_called)
713 ARCANE_FATAL("This method has already been called");
714 m_is_remove_refined_called = true;
715
716 const bool is_verbose = m_verbosity_level > 0;
717
718 IMesh* mesh = m_cartesian_mesh->mesh();
719 IMeshModifier* mesh_modifier = mesh->modifier();
720
721 info() << "RemoveRefinedCells nb_coarse_cell=" << m_coarse_cells_uid.size();
722 if (is_verbose)
723 info() << "CoarseCells=" << m_coarse_cells_uid;
724
725 // Supprime toutes les mailles raffinées ainsi que toutes les mailles fantômes
726 {
727 std::unordered_set<Int64> coarse_cells_set;
728 for (Int64 cell_uid : m_coarse_cells_uid)
729 coarse_cells_set.insert(cell_uid);
730 UniqueArray<Int32> cells_to_remove;
731 ENUMERATE_ (Cell, icell, mesh->allCells()) {
732 Int32 local_id = icell.itemLocalId();
733 Cell cell = *icell;
734 if (coarse_cells_set.find(cell.uniqueId()) == coarse_cells_set.end())
735 cells_to_remove.add(local_id);
736 }
737 if (is_verbose)
738 info() << "CellsToRemove n=" << cells_to_remove.size() << " list=" << cells_to_remove;
739 mesh_modifier->removeCells(cells_to_remove);
740 mesh_modifier->endUpdate();
741 }
742
743 // Reconstruit les mailles fantômes
744 mesh_modifier->setDynamic(true);
745 mesh_modifier->updateGhostLayers();
746
747 // Affiche les statistiques du nouveau maillage
748 {
749 MeshStats ms(traceMng(), mesh, mesh->parallelMng());
750 ms.dumpStats();
751 }
752
753 // Il faut recalculer les nouvelles directions
754 m_cartesian_mesh->computeDirections();
755}
756
757/*---------------------------------------------------------------------------*/
758/*---------------------------------------------------------------------------*/
759
760} // End namespace Arcane
761
762/*---------------------------------------------------------------------------*/
763/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Informations sur les dimensions d'une grille cartésienne.
Infos sur les mailles d'une direction spécifique X,Y ou Z d'un maillage structuré.
Int32 ownNbCell() const
Nombre de mailles propres dans cette direction.
Maille d'un maillage.
Definition Item.h:1178
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1255
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1252
Int32 level() const
Definition Item.h:1328
virtual FaceGroup allFaces()=0
Groupe de toutes les faces.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual void addFaces(Integer nb_face, Int64ConstArrayView face_infos, Int32ArrayView face_lids=Int32ArrayView())=0
Ajoute des faces.
virtual void addCells(Integer nb_cell, Int64ConstArrayView cell_infos, Int32ArrayView cells_lid=Int32ArrayView())=0
Ajoute des mailles.
virtual void endUpdate()=0
Notifie l'instance de la fin de la modification du maillage.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
virtual CellGroup allLevelCells(const Integer &level)=0
Groupe de toutes les mailles de niveau level.
virtual void computeSynchronizeInfos()=0
Recalcule les informations de synchronisation.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
ItemVectorView view() const
Vue sur les entités du groupe.
Definition ItemGroup.cc:582
ItemGroupImplInternal * _internalApi() const
API interne à Arcane.
Definition ItemGroup.cc:645
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:35
Informations locales sur une face d'une maille.
Integer node(Integer i) const
Indice locale dans la maille du i-ème noeud de la face.
Infos sur un type d'entité du maillage.
LocalFace localFace(Integer id) const
Connectivité locale de la i-ème face de la maille.
Int32ConstArrayView localIds() const
Tableau des numéros locaux des entités.
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:768
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:765
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
Definition Item.h:377
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:365
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:210
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:229
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
void dumpStats() override
Imprime des infos sur le maillage.
Definition MeshStats.cc:62
void addFlags(Int32 added_flags)
Ajoute les flags \added_flags à ceux de l'entité
Vue modifiable d'un tableau d'un type T.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vecteur 1D de données avec sémantique par valeur (style STL).
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-