Arcane  v3.15.3.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CartesianMeshCoarsening.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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-2023 */
9/* */
10/* Déraffinement d'un maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/cartesianmesh/CartesianMeshCoarsening.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ValueConvert.h"
18
19#include "arcane/core/IMesh.h"
20#include "arcane/core/ItemGroup.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/CartesianGridDimension.h"
23#include "arcane/core/IMeshModifier.h"
24#include "arcane/core/SimpleSVGMeshExporter.h"
25#include "arcane/core/ItemPrinter.h"
26#include "arcane/core/MeshStats.h"
27
28#include "arcane/cartesianmesh/ICartesianMesh.h"
29#include "arcane/cartesianmesh/CellDirectionMng.h"
30
31#include <unordered_set>
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42CartesianMeshCoarsening::
43CartesianMeshCoarsening(ICartesianMesh* m)
44: TraceAccessor(m->traceMng())
45, m_cartesian_mesh(m)
46{
47 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CARTESIANMESH_COARSENING_VERBOSITY_LEVEL", true))
48 m_verbosity_level = v.value();
49}
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54//! Retourne le max des uniqueId() des entités de \a group
55Int64 CartesianMeshCoarsening::
56_getMaxUniqueId(const ItemGroup& group)
57{
58 Int64 max_offset = 0;
59 ENUMERATE_ (Item, iitem, group) {
60 Item item = *iitem;
61 if (max_offset < item.uniqueId())
62 max_offset = item.uniqueId();
63 }
64 return max_offset;
65}
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70void CartesianMeshCoarsening::
71createCoarseCells()
72{
73 if (m_is_create_coarse_called)
74 ARCANE_FATAL("This method has already been called");
75 m_is_create_coarse_called = true;
76
77 const bool is_verbose = m_verbosity_level > 0;
78 IMesh* mesh = m_cartesian_mesh->mesh();
79 Integer nb_patch = m_cartesian_mesh->nbPatch();
80 if (nb_patch != 1)
81 ARCANE_FATAL("This method is only valid for 1 patch (nb_patch={0})", nb_patch);
82
83 if (!mesh->isAmrActivated())
84 ARCANE_FATAL("AMR is not activated for this case");
85
86 // TODO: Supprimer les mailles fantômes puis les reconstruire
87 // TODO: Mettre à jour les informations dans CellDirectionMng
88 // de ownNbCell(), globalNbCell(), ...
89
90 Integer nb_dir = mesh->dimension();
91 if (nb_dir != 2)
92 ARCANE_FATAL("This method is only valid for 2D mesh");
93
94 IParallelMng* pm = mesh->parallelMng();
95 const Int32 my_rank = pm->commRank();
96 info() << "CoarseCartesianMesh nb_direction=" << nb_dir;
97
98 for (Integer idir = 0; idir < nb_dir; ++idir) {
99 CellDirectionMng cdm(m_cartesian_mesh->cellDirection(idir));
100 Int32 nb_own_cell = cdm.ownNbCell();
101 info() << "NB_OWN_CELL dir=" << idir << " n=" << nb_own_cell;
102 if ((nb_own_cell % 2) != 0)
103 ARCANE_FATAL("Invalid number of cells ({0}) for direction {1}. Should be a multiple of 2",
105 }
106
107 // Calcule l'offset pour la création des uniqueId().
108 // On prend comme offset le max des uniqueId() des faces et des mailles.
109 // A terme avec la numérotation cartésienne partout, on pourra déterminer
110 // directement cette valeur
111 Int64 max_cell_uid = _getMaxUniqueId(mesh->allCells());
112 Int64 max_face_uid = _getMaxUniqueId(mesh->allFaces());
113 const Int64 coarse_grid_cell_offset = 1 + pm->reduce(Parallel::ReduceMax, math::max(max_cell_uid, max_face_uid));
114 m_first_own_cell_unique_id_offset = coarse_grid_cell_offset;
115
116 CellDirectionMng cdm_x(m_cartesian_mesh->cellDirection(0));
117 CellDirectionMng cdm_y(m_cartesian_mesh->cellDirection(1));
118
119 const Int64 global_nb_cell_x = cdm_x.globalNbCell();
120 const Int64 global_nb_cell_y = cdm_y.globalNbCell();
123 CartesianGridDimension::CellUniqueIdComputer2D refined_cell_uid_computer(refined_grid_dim.getCellComputer2D(0));
124 CartesianGridDimension::NodeUniqueIdComputer2D refined_node_uid_computer(refined_grid_dim.getNodeComputer2D(0));
125 CartesianGridDimension::CellUniqueIdComputer2D coarse_cell_uid_computer(coarse_grid_dim.getCellComputer2D(coarse_grid_cell_offset));
126 CartesianGridDimension::FaceUniqueIdComputer2D coarse_face_uid_computer(coarse_grid_dim.getFaceComputer2D(coarse_grid_cell_offset));
127
128 // Pour les mailles et faces grossières, les noeuds existent déjà
129 // On ne peut donc pas utiliser la connectivité cartésienne de la grille grossière
130 // pour eux (on pourra le faire lorsque l'AMR par patch avec duplication sera active)
131 // En attendant on utilise la numérotation de la grille raffinée.
132
133 // TODO: Calculer le nombre de faces et de mailles et allouer en conséquence.
136 Int32 nb_coarse_face = 0;
137 Int32 nb_coarse_cell = 0;
138 //! Liste de la première fille de chaque maille grossière
140 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
141 Cell cell = *icell;
142 Int64 cell_uid = cell.uniqueId();
144 const Int64 cell_x = cell_xy.x;
145 const Int64 cell_y = cell_xy.y;
146 // Comme on déraffine par 2, ne prend que les mailles dont les coordoonnées
147 // topologiques sont paires
148 if ((cell_x % 2) != 0 || (cell_y % 2) != 0)
149 continue;
150 if (is_verbose)
151 info() << "CELLCoarse uid=" << cell_uid << " x=" << cell_x << " y=" << cell_y;
152 const Int64 coarse_cell_x = cell_x / 2;
153 const Int64 coarse_cell_y = cell_y / 2;
154 std::array<Int64, 4> node_uids_container;
156 node_uids[0] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 0);
157 node_uids[1] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 0);
158 node_uids[2] = refined_node_uid_computer.compute(cell_x + 2, cell_y + 2);
159 node_uids[3] = refined_node_uid_computer.compute(cell_x + 0, cell_y + 2);
160 if (is_verbose)
161 info() << "CELLNodes uid=" << node_uids;
162 std::array<Int64, 4> coarse_face_uids = coarse_face_uid_computer.computeForCell(coarse_cell_x, coarse_cell_y);
163 const ItemTypeInfo* cell_type = cell.typeInfo();
164 // Ajoute les 4 faces
165 for (Int32 z = 0; z < 4; ++z) {
167 faces_infos.add(IT_Line2);
169 faces_infos.add(node_uids[lface.node(0)]);
170 faces_infos.add(node_uids[lface.node(1)]);
172 }
173 // Ajoute la maille
174 {
175 cells_infos.add(IT_Quad4);
177 for (Int32 z = 0; z < 4; ++z)
178 cells_infos.add(node_uids[z]);
181 }
182 }
183
190
191 // Maintenant que les mailles grossières sont créées, il faut indiquer
192 // qu'elles sont parentes.
194
195 // Positionne les propriétaires des nouvelles mailles
196 // et ajoute un flag (ItemFlags::II_UserMark1) pour les marquer.
197 // Cela sera utilisé pour détruire les mailles raffinées par la suite.
198 {
200 Cell cell = *icell;
202 cell.mutableItemBase().addFlags(ItemFlags::II_UserMark1);
203 }
204 cell_family->notifyItemsOwnerChanged();
205 }
206
207 // Il faut donner un propriétaire aux faces.
208 // Comme les nouvelles faces utilisent un noeud déjà existant, on prend comme propriétaire
209 // celui du premier noeud de la face
210 {
213 Face face = *iface;
214 Int32 owner = face.node(0).owner();
215 face.mutableItemBase().setOwner(owner, my_rank);
216 }
217 face_family->notifyItemsOwnerChanged();
218 }
219
220 // Met à jour le maillage
221 mesh->modifier()->endUpdate();
222
223 // Après l'appel à endUpdate() les numéros locaux ne changent plus.
224 // On peut s'en servir pour conserver pour chaque maille grossière la liste des mailles
225 // raffinées
226 m_coarse_cells.resize(nb_coarse_cell);
227 m_refined_cells.resize(nb_coarse_cell, 4);
228
229 {
230 CellInfoListView cells(mesh->cellFamily());
233 Int32 coarse_index = 0;
234 std::array<Int32, 4> sub_cell_lids_container;
236
237 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
239 if (!(coarse_cell.itemBase().flags() & ItemFlags::II_UserMark1))
240 continue;
241 // Supprime le flag
242 coarse_cell.mutableItemBase().removeFlags(ItemFlags::II_UserMark1);
243 m_coarse_cells[coarse_index] = coarse_cell.itemLocalId();
245 // A partir de la première sous-maille, on peut connaître les 3 autres
246 // car elles sont respectivement à droite, en haut à droite et en haut.
247 sub_cell_lids[0] = first_child_cell.localId();
248 sub_cell_lids[1] = cdm_x[first_child_cell].next().localId();
249 sub_cell_lids[2] = cdm_y[CellLocalId(sub_cell_lids[1])].next().localId();
250 sub_cell_lids[3] = cdm_y[first_child_cell].next().localId();
251 if (is_verbose)
252 info() << "AddChildForCoarseCell i=" << coarse_index << " coarse=" << ItemPrinter(coarse_cell)
253 << " children_lid=" << sub_cell_lids;
254 for (Int32 z = 0; z < 4; ++z) {
256 m_refined_cells[coarse_index][z] = sub_local_id;
257 if (is_verbose)
258 info() << " AddParentCellToCell: z=" << z << " child=" << ItemPrinter(cells[sub_local_id]);
259 }
260 ++coarse_index;
261 }
262 }
263
264 if (is_verbose) {
265 ENUMERATE_ (Cell, icell, mesh->allCells()) {
266 Cell cell = *icell;
267 info() << "Final cell=" << ItemPrinter(cell) << " level=" << cell.level();
268 }
269 }
270
271 const bool dump_coarse_mesh = false;
272 if (dump_coarse_mesh) {
273 String filename = String::format("mesh_coarse_{0}.svg", my_rank);
274 std::ofstream ofile(filename.localstr());
276 writer.write(mesh->allCells());
277 }
278}
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
283void CartesianMeshCoarsening::
284removeRefinedCells()
285{
286 if (!m_is_create_coarse_called)
287 ARCANE_FATAL("You need to call createCoarseCells() before");
288 if (m_is_remove_refined_called)
289 ARCANE_FATAL("This method has already been called");
290 m_is_remove_refined_called = true;
291
292 IMesh* mesh = m_cartesian_mesh->mesh();
294
295 // Supprime toutes les mailles raffinées ainsi que toutes les mailles fantômes
296 {
297 std::unordered_set<Int32> coarse_cells_set;
298 for (Int32 cell_lid : m_coarse_cells)
300
302 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
303 Int32 local_id = icell.itemLocalId();
304 Cell cell = *icell;
305 if (!cell.isOwn() || (coarse_cells_set.find(local_id) != coarse_cells_set.end()))
306 cells_to_remove.add(local_id);
307 }
308 mesh_modifier->removeCells(cells_to_remove);
309 mesh_modifier->endUpdate();
310 }
311
312 // Reconstruit les mailles fantômes
313 mesh_modifier->setDynamic(true);
314 mesh_modifier->updateGhostLayers();
315
316 // Affiche les statistiques du nouveau maillage
317 {
318 MeshStats ms(traceMng(), mesh, mesh->parallelMng());
319 ms.dumpStats();
320 }
321
322 _recomputeMeshGenerationInfo();
323
324 // Il faut recalculer les nouvelles directions
325 m_cartesian_mesh->computeDirections();
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330/*!
331 * \brief Recalcule les informations sur le nombre de mailles par direction.
332 */
333void CartesianMeshCoarsening::
334_recomputeMeshGenerationInfo()
335{
336 IMesh* mesh = m_cartesian_mesh->mesh();
337 auto* cmgi = ICartesianMeshGenerationInfo::getReference(mesh, false);
338 if (!cmgi)
339 return;
340
341 // Coefficient de dé-raffinement
342 const Int32 cf = 2;
343
344 {
345 ConstArrayView<Int64> v = cmgi->ownCellOffsets();
346 cmgi->setOwnCellOffsets(v[0] / cf, v[1] / cf, v[2] / cf);
347 }
348 {
349 ConstArrayView<Int64> v = cmgi->globalNbCells();
350 cmgi->setGlobalNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
351 }
352 {
353 ConstArrayView<Int32> v = cmgi->ownNbCells();
354 cmgi->setOwnNbCells(v[0] / cf, v[1] / cf, v[2] / cf);
355 }
356 cmgi->setFirstOwnCellUniqueId(m_first_own_cell_unique_id_offset);
357}
358
359/*---------------------------------------------------------------------------*/
360/*---------------------------------------------------------------------------*/
361
362} // End namespace Arcane
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
#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é.
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1191
Int32 level() const
Definition Item.h:1342
Face d'une maille.
Definition Item.h:944
Interface d'une famille d'entités.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
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 IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
Interface du gestionnaire de parallélisme pour un sous-domaine.
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:779
const ItemTypeInfo * typeInfo() const
Infos sur le type de l'entité.
Definition Item.h:386
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:374
bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Arguments pour IMeshModifier::addCells().
Arguments pour IMeshModifier::addFaces().
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.
Référence à une instance.
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-