Arcane  v3.14.10.0
Documentation développeur
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
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());
89 writer.write(mesh->allCells());
90}
91
92/*---------------------------------------------------------------------------*/
93/*---------------------------------------------------------------------------*/
100void CartesianMeshCoarsening2::
101_doDoubleGhostLayers()
102{
103 IMesh* mesh = m_cartesian_mesh->mesh();
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",
158 }
159
160 _writeMeshSVG("orig");
161
162 // Double la couche de mailles fantômes
163 _doDoubleGhostLayers();
164
165 if (is_verbose) {
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
219 {
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();
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.
268 Int32 nb_coarse_face = 0;
269 Int32 nb_coarse_cell = 0;
272
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;
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) {
308 faces_infos.add(IT_Line2);
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;
320 }
321 // Ajoute la maille
322 {
323 cells_infos.add(IT_Quad4);
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]);
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;
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)
366 }
367 }
368
369 // Construit les faces
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();
378 add_cells_args.setAllowBuildFaces(false);
379 mesh->modifier()->addCells(add_cells_args);
380
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;
390 for (Int32 i = 0; i < nb_coarse_cell; ++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 {
415 Int32 index = 0;
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) {
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();
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.
464 Int32 nb_coarse_face = 0;
465 Int32 nb_coarse_cell = 0;
468
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
480 // Liste ordonnée des noeuds des faces créées
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;
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) {
520 faces_infos.add(IT_Quad4);
522 for (Int32 knode = 0; knode < const_face_nb_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;
529 }
530
531 // Ajoute la maille
532 {
533 cells_infos.add(IT_Hexaedron8);
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]);
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;
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)
601 }
602 }
603
604 // Construit les faces
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();
613 add_cells_args.setAllowBuildFaces(false);
614 mesh->modifier()->addCells(add_cells_args);
615
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;
625 for (Int32 i = 0; i < nb_coarse_cell; ++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
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 {
657 Int32 index = 0;
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) {
665 }
666 ++index;
667 }
668 cell_family->notifyItemsOwnerChanged();
669 face_family->notifyItemsOwnerChanged();
670 }
671}
672
673/*---------------------------------------------------------------------------*/
674/*---------------------------------------------------------------------------*/
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();
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);
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é
Classe pour calculer en 2D le uniqueId() d'une maille en fonction de sa position dans la grille.
Classe pour calculer en 3D le uniqueId() d'une maille en fonction de sa position dans la grille.
Classe pour calculer en 2D le uniqueId() d'une face en fonction de sa position dans la grille.
Classe pour calculer en 2D le uniqueId() d'une face en fonction de sa position dans la grille.
Classe pour calculer en 2D le uniqueId() d'un noeud en fonction de sa position dans la grille.
Classe pour calculer en 3D le uniqueId() d'un noeud en fonction de sa position dans la grille.
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é.
Vue sur les informations des mailles.
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
Interface d'une famille d'entités.
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.
Interface de modification du maillage.
virtual void updateGhostLayers()=0
Mise à jour de la couche fantôme.
virtual void setDynamic(bool v)=0
Positionne la propriété indiquant si le maillage peut évoluer.
virtual void removeCells(Int32ConstArrayView cells_local_id)=0
Supprime 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.
virtual IGhostLayerMng * ghostLayerMng() const =0
Gestionnare de couche fantômes associé
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.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:35
Informations locales sur une face d'une maille.
Infos sur un type d'entité du maillage.
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
Classe de base d'un élément de maillage.
Definition Item.h:83
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
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Arguments pour IMeshModifier::addCells().
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
void addFlags(Int32 added_flags)
Ajoute les flags \added_flags à ceux de l'entité
Exportation d'un maillage au format SVG.
Famille de mailles.
Definition CellFamily.h:46
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-