Arcane  4.2.3.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CartesianMesh.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* CartesianMesh.cc (C) 2000-2026 */
9/* */
10/* Maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/TraceAccessor.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/AutoDestroyUserData.h"
17#include "arcane/utils/IUserDataList.h"
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/Event.h"
22#include "arcane/utils/Convert.h"
23
24#include "arcane/core/IMesh.h"
25#include "arcane/core/ItemPrinter.h"
26#include "arcane/core/IItemFamily.h"
27#include "arcane/core/IParallelMng.h"
28#include "arcane/core/VariableTypes.h"
29#include "arcane/core/Properties.h"
30#include "arcane/core/IMeshModifier.h"
31#include "arcane/core/MeshStats.h"
32#include "arcane/core/ICartesianMeshGenerationInfo.h"
33#include "arcane/core/MeshEvents.h"
34#include "arcane/core/MeshKind.h"
35#include "arcane/core/internal/IMeshInternal.h"
36
37#include "arcane/cartesianmesh/internal/CartesianPatchGroup.h"
38#include "arcane/cartesianmesh/ICartesianMesh.h"
39#include "arcane/cartesianmesh/AMRZonePosition.h"
40#include "arcane/cartesianmesh/CartesianConnectivity.h"
41#include "arcane/cartesianmesh/CartesianMeshRenumberingInfo.h"
42#include "arcane/cartesianmesh/CartesianMeshCoarsening.h"
43#include "arcane/cartesianmesh/CartesianMeshCoarsening2.h"
44#include "arcane/cartesianmesh/CartesianMeshPatchListView.h"
45#include "arcane/cartesianmesh/internal/CartesianMeshPatch.h"
46#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
47
48#include "arcane/cartesianmesh/internal/CartesianMeshUniqueIdRenumbering.h"
49#include "arcane/cartesianmesh/v2/CartesianMeshUniqueIdRenumberingV2.h"
50#include "arcane/cartesianmesh/CartesianMeshNumberingMng.h"
51
52#include "arcane/cartesianmesh/internal/CartesianMeshAMRPatchMng.h"
53#include "arcane/core/IGhostLayerMng.h"
54#include "arcane/cartesianmesh/internal/CartesianMeshNumberingMngInternal.h"
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58/*!
59 * \defgroup ArcaneCartesianMesh Maillages cartésiens.
60 *
61 * Ensemble de classes assurant la gestion des maillages cartésiens.
62 *
63 * Pour plus d'informations, référez-vous à la page \ref arcanedoc_entities_cartesianmesh.
64 */
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68namespace Arcane
69{
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
74/*!
75 * \brief Informations spécifiques pour un maillage cartésien.
76 */
77class CartesianMeshImpl
78: public TraceAccessor
79, public ICartesianMesh
80{
81 class InternalApi
82 : public ICartesianMeshInternal
83 {
84 public:
85
86 explicit InternalApi(CartesianMeshImpl* cartesian_mesh)
87 : m_cartesian_mesh(cartesian_mesh)
88 {
89 }
90
91 public:
92
93 Ref<CartesianMeshCoarsening2> createCartesianMeshCoarsening2() override
94 {
95 return m_cartesian_mesh->_createCartesianMeshCoarsening2();
96 }
97 void addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id) override
98 {
99 m_cartesian_mesh->_addPatchFromExistingChildren(parent_cells_local_id);
100 }
101 void initCartesianMeshAMRPatchMng() override
102 {
103 if (m_numbering_mng.isNull()) {
104 initCartesianMeshNumberingMngInternal();
105 }
106 if (m_amr_mng.isNull()) {
107 m_amr_mng = makeRef(new CartesianMeshAMRPatchMng(m_cartesian_mesh, m_numbering_mng.get()));
108 }
109 }
110 Ref<ICartesianMeshAMRPatchMng> cartesianMeshAMRPatchMng() override
111 {
112 return m_amr_mng;
113 }
114 void initCartesianMeshNumberingMngInternal() override
115 {
116 if (m_numbering_mng.isNull()) {
117 m_numbering_mng = makeRef(new CartesianMeshNumberingMngInternal(m_cartesian_mesh->mesh()));
118 }
119 }
120 Ref<ICartesianMeshNumberingMngInternal> cartesianMeshNumberingMngInternal() override
121 {
122 return m_numbering_mng;
123 }
124 CartesianPatchGroup& cartesianPatchGroup() override { return m_cartesian_mesh->_cartesianPatchGroup(); }
125 // TODO : Moche.
126 void saveInfosInProperties() override { m_cartesian_mesh->_saveInfosInProperties(); }
127
128 private:
129
130 CartesianMeshImpl* m_cartesian_mesh = nullptr;
133 };
134
135 public:
136
137 explicit CartesianMeshImpl(IMesh* mesh);
138
139 public:
140
141 void build() override;
142
143 //! Maillage associé à ce maillage cartésien
144 IMesh* mesh() const override { return m_mesh; }
145
146 //! Gestionnaire de traces associé.
147 ITraceMng* traceMng() const override { return TraceAccessor::traceMng(); }
148
150 {
151 return m_all_items_direction_info->cellDirection(dir);
152 }
153
155 {
156 return m_all_items_direction_info->cellDirection(idir);
157 }
158
160 {
161 return m_all_items_direction_info->faceDirection(dir);
162 }
163
165 {
166 return m_all_items_direction_info->faceDirection(idir);
167 }
168
170 {
171 return m_all_items_direction_info->nodeDirection(dir);
172 }
173
175 {
176 return m_all_items_direction_info->nodeDirection(idir);
177 }
178
179 void computeDirections() override;
180
181 void recreateFromDump() override;
182
184 {
185 return m_connectivity;
186 }
187
188 Int32 nbPatch() const override { return m_patch_group.nbPatch(); }
189 ICartesianMeshPatch* patch(Int32 index) const override { return m_patch_group.patch(index).get(); }
190 CartesianPatch amrPatch(Int32 index) const override { return CartesianPatch(m_patch_group.patch(index).get()); }
191 CartesianMeshPatchListView patches() const override { return m_patch_group.patchListView(); }
192
193 void refinePatch2D(Real2 position, Real2 length) override;
194 void refinePatch3D(Real3 position, Real3 length) override;
195 void refinePatch(const AMRZonePosition& position) override;
196
197 void coarseZone2D(Real2 position, Real2 length) override;
198 void coarseZone3D(Real3 position, Real3 length) override;
199 void coarseZone(const AMRZonePosition& position) override;
200
201 Integer reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers) override;
202
204
205 void checkValid() const override;
206
208
209 //! API interne à Arcane
210 ICartesianMeshInternal* _internalApi() override { return &m_internal_api; }
211
212 void computeDirectionsPatchV2(Integer index) override;
213
214 private:
215
216 // Implémentation de 'ICartesianMeshInternal'
217 Ref<CartesianMeshCoarsening2> _createCartesianMeshCoarsening2();
218 void _addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id);
219 CartesianPatchGroup& _cartesianPatchGroup() { return m_patch_group; }
220 void _computeDirectionsV2();
221
222 private:
223
224 InternalApi m_internal_api;
225 //! Indice dans la numérotation locale de la maille, de la face dans
226 // la direction X, Y ou Z
227 Int32 m_local_face_direction[3] = { -1, -1, -1 };
228 IMesh* m_mesh = nullptr;
229 Ref<CartesianMeshPatch> m_all_items_direction_info;
230 CartesianConnectivity m_connectivity;
231 UniqueArray<CartesianConnectivity::Index> m_nodes_to_cell_storage;
232 UniqueArray<CartesianConnectivity::Index> m_cells_to_node_storage;
233 UniqueArray<CartesianConnectivity::Permutation> m_permutation_storage;
234 bool m_is_amr = false;
235 //! Groupe de mailles pour chaque patch AMR.
236 CartesianPatchGroup m_patch_group;
237 ScopedPtrT<Properties> m_properties;
238
239 EventObserverPool m_event_pool;
240 bool m_is_mesh_event_added = false;
241 Int64 m_mesh_timestamp = 0;
242 eMeshAMRKind m_amr_type;
243
244 private:
245
246 void _computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir,
247 VariableCellReal3& cells_center,
248 VariableFaceReal3& faces_center, CellGroup all_cells,
249 NodeGroup all_nodes);
250
251 void _computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir,
252 CellGroup all_cells,
253 CellGroup in_patch_cells,
254 CellGroup overlap_cells,
255 NodeGroup all_nodes);
256
257 void _applyRefine(const AMRZonePosition& position);
258 void _applyCoarse(const AMRZonePosition& zone_position);
259 void _addPatch(ConstArrayView<Int32> parent_cells);
260 void _saveInfosInProperties();
261
262 std::tuple<CellGroup, NodeGroup>
263 _buildPatchGroups(const CellGroup& cells, Integer patch_level);
264 void _checkNeedComputeDirections();
265 void _checkAddObservableMeshChanged();
266};
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271extern "C++" ICartesianMesh*
272arcaneCreateCartesianMesh(IMesh* mesh)
273{
274 auto* cm = new CartesianMeshImpl(mesh);
275 cm->build();
276 return cm;
277}
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
281
282CartesianMeshImpl::
283CartesianMeshImpl(IMesh* mesh)
284: TraceAccessor(mesh->traceMng())
285, m_internal_api(this)
286, m_mesh(mesh)
287, m_nodes_to_cell_storage(platform::getDefaultDataAllocator())
288, m_cells_to_node_storage(platform::getDefaultDataAllocator())
289, m_permutation_storage(platform::getDefaultDataAllocator())
290, m_patch_group(this)
291, m_amr_type(mesh->meshKind().meshAMRKind())
292{
293 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
294 m_internal_api.initCartesianMeshNumberingMngInternal();
295 m_internal_api.initCartesianMeshAMRPatchMng();
296 }
297 m_all_items_direction_info = m_patch_group.groundPatch();
298}
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
303void CartesianMeshImpl::
304build()
305{
306 m_properties = new Properties(*(mesh()->properties()), "CartesianMesh");
307 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
308 m_internal_api.cartesianMeshNumberingMngInternal()->build();
309 }
310 m_patch_group.build();
311}
312
313namespace
314{
315 const Int32 SERIALIZE_VERSION = 1;
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
321void CartesianMeshImpl::
322_checkNeedComputeDirections()
323{
324 Int64 new_timestamp = mesh()->timestamp();
325 if (m_mesh_timestamp != new_timestamp) {
326 info() << "Le horodatage du maillage a changé (ancien=" << m_mesh_timestamp << " nouveau=" << new_timestamp << ")";
328 }
329}
330
331/*---------------------------------------------------------------------------*/
332/*---------------------------------------------------------------------------*/
333
334void CartesianMeshImpl::
335_saveInfosInProperties()
336{
337 // Sauve le numéro de version pour être sur que c'est OK en reprise
338 m_properties->set("Version", SERIALIZE_VERSION);
339
340 m_patch_group.saveInfosInProperties();
341
342 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
343 m_internal_api.cartesianMeshNumberingMngInternal()->saveInfosInProperties();
344 //m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
345 }
346}
347
348/*---------------------------------------------------------------------------*/
349/*---------------------------------------------------------------------------*/
350
353{
354 info() << "Création des infos 'CartesianMesh' à partir du dump";
355
356 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
357 m_internal_api.cartesianMeshNumberingMngInternal()->recreateFromDump();
358 m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
359 }
360
361 // Sauve le numéro de version pour être sur que c'est OK en reprise
362 Int32 v = m_properties->getInt32("Version");
363 if (v != SERIALIZE_VERSION)
364 ARCANE_FATAL("Mauvaise version de sérialisation : tentative de lecture à partir d'un point de contrôle incompatible v={0} attendu={1}",
365 v, SERIALIZE_VERSION);
366
367 m_patch_group.recreateFromDump();
368
369 m_all_items_direction_info = m_patch_group.groundPatch();
370
372}
373
374/*---------------------------------------------------------------------------*/
375/*---------------------------------------------------------------------------*/
376
377void CartesianMeshImpl::
378_checkAddObservableMeshChanged()
379{
380 if (m_is_mesh_event_added)
381 return;
382 m_is_mesh_event_added = true;
383 // Pour appeler automatiquement 'computeDirections()' après un appel à
384 // IMesh::prepareForDump().
385 auto f1 = [&](const MeshEventArgs&) { this->_checkNeedComputeDirections(); };
386 mesh()->eventObservable(eMeshEventType::EndPrepareDump).attach(m_event_pool, f1);
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
394{
395 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
396 // TODO : Voir où mettre la renumérotation.
397 m_internal_api.cartesianMeshNumberingMngInternal()->renumberingFacesLevel0FromOriginalArcaneNumbering();
398 _computeDirectionsV2();
399 return;
400 }
401 info() << "CartesianMesh: computeDirections()";
402
403 m_mesh_timestamp = mesh()->timestamp();
404 _checkAddObservableMeshChanged();
405
406 m_is_amr = m_mesh->isAmrActivated();
407
408 VariableCellReal3 cells_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshCellCenter"));
409 VariableFaceReal3 faces_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshFaceCenter"));
410
411 // Calcule les coordonnées du centre des mailles.
412 VariableNodeReal3& nodes_coord = m_mesh->nodesCoordinates();
413 ENUMERATE_CELL (icell, m_mesh->allCells()) {
414 Cell cell = *icell;
415 Real3 center;
416 for (NodeLocalId inode : cell.nodeIds())
417 center += nodes_coord[inode];
418 center /= cell.nbNode();
419 cells_center[icell] = center;
420 }
421 ENUMERATE_FACE (iface, m_mesh->allFaces()) {
422 Face face = *iface;
423 Real3 center;
424 for (NodeLocalId inode : face.nodeIds())
425 center += nodes_coord[inode];
426 center /= face.nbNode();
427 faces_center[iface] = center;
428 }
429
430 IItemFamily* cell_family = m_mesh->cellFamily();
431 IItemFamily* node_family = m_mesh->nodeFamily();
432 Int32 next_face_x = -1;
433 Int32 next_face_y = -1;
434 Int32 next_face_z = -1;
435
436 CellVectorView cell_view = cell_family->allItems().view();
437 Cell cell0 = cell_view[0];
438 Integer nb_face = cell0.nbFace();
439 Integer nb_node = cell0.nbNode();
440 Real3 cell_center = cells_center[cell0];
441
442 info(4) << "sizeof(CellDirectionMng)=" << sizeof(CellDirectionMng)
443 << " sizeof(FaceDirectionMng)=" << sizeof(FaceDirectionMng)
444 << " sizeof(NodelDirectionMng)=" << sizeof(NodeDirectionMng);
445 info(4) << "sizeof(IndexedItemConnectivityViewBase)=" << sizeof(IndexedItemConnectivityViewBase)
446 << " sizeof(CellInfoListView)=" << sizeof(CellInfoListView);
447 info(4) << "Cartesian mesh compute directions is_amr=" << m_is_amr;
448
449 for (Integer i = 0; i < nb_node; ++i) {
450 Node node = cell0.node(i);
451 info(4) << "Nœud I=" << i << " nœud=" << ItemPrinter(node) << " pos=" << nodes_coord[node];
452 }
453
454 bool is_3d = m_mesh->dimension() == 3;
455
456 // On suppose que toutes les mailles ont le même sens de numérotation dans le maillage.
457 // Par exemple, pour toutes les mailles, la face d'indice 0 est celle du haut, celle
458 // d'indice 1 celle de droite.
459 if (is_3d) {
460 Real max_x = -1;
461 Real max_y = -1;
462 Real max_z = -1;
463
464 for (Integer i = 0; i < nb_face; ++i) {
465 Face f = cell0.face(i);
466
467 Real3 next_center = faces_center[f];
468
469 Real diff_x = next_center.x - cell_center.x;
470 Real diff_y = next_center.y - cell_center.y;
471 Real diff_z = next_center.z - cell_center.z;
472
473 info(4) << "FACE_SUIVANTE=" << ItemPrinter(f) << " centre=" << next_center << " diff=" << Real3(diff_x, diff_y, diff_z);
474
475 if (diff_x > max_x) {
476 max_x = diff_x;
477 next_face_x = i;
478 }
479
480 if (diff_y > max_y) {
481 max_y = diff_y;
482 next_face_y = i;
483 }
484
485 if (diff_z > max_z) {
486 max_z = diff_z;
487 next_face_z = i;
488 }
489 }
490 info(4) << "Avancement dans la direction X -> " << next_face_x;
491 info(4) << "Avancement dans la direction Y -> " << next_face_y;
492 info(4) << "Avancement dans la direction Z -> " << next_face_z;
493 }
494 else {
495 Real max_x = -1;
496 Real max_y = -1;
497
498 for (Integer i = 0; i < nb_face; ++i) {
499 Face f = cell0.face(i);
500
501 Real3 next_center = faces_center[f];
502
503 Real diff_x = next_center.x - cell_center.x;
504 Real diff_y = next_center.y - cell_center.y;
505
506 info(4) << "FACE_SUIVANTE=" << ItemPrinter(f) << " centre=" << next_center << " diff=" << Real2(diff_x, diff_y);
507
508 if (diff_x > max_x) {
509 max_x = diff_x;
510 next_face_x = i;
511 }
512
513 if (diff_y > max_y) {
514 max_y = diff_y;
515 next_face_y = i;
516 }
517 }
518 info(4) << "Avancement dans la direction X -> " << next_face_x;
519 info(4) << "Avancement dans la direction Y -> " << next_face_y;
520 }
521 m_all_items_direction_info->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
522
523 info() << "Informations des propriétés IMesh:";
524
525 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
526
527 info() << "GlobalNbCell = " << cmgi->globalNbCells();
528 info() << "OwnNbCell: " << cmgi->ownNbCells();
529 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
530 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
531
532 CellGroup all_cells = cell_family->allItems();
533 NodeGroup all_nodes = node_family->allItems();
534 if (m_is_amr) {
535 auto x = _buildPatchGroups(mesh()->allLevelCells(0), 0);
536 all_cells = std::get<0>(x);
537 all_nodes = std::get<1>(x);
538 }
539
540 if (next_face_x != (-1)) {
541 m_local_face_direction[MD_DirX] = next_face_x;
542 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirX, cells_center, faces_center, all_cells, all_nodes);
543 }
544 if (next_face_y != (-1)) {
545 m_local_face_direction[MD_DirY] = next_face_y;
546 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirY, cells_center, faces_center, all_cells, all_nodes);
547 }
548 if (next_face_z != (-1)) {
549 m_local_face_direction[MD_DirZ] = next_face_z;
550 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirZ, cells_center, faces_center, all_cells, all_nodes);
551 }
552
553 // Positionne les informations par direction
554 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
555 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
556 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
557 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
558 }
559
560 info() << "Calcul de la connectivité cartésienne";
561
562 m_permutation_storage.resize(1);
563 m_permutation_storage[0].compute();
564 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
565 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
566 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
567 m_connectivity._computeInfos(mesh(), nodes_coord, cells_center);
568
569 // Ajoute informations de connectivités pour les patchs AMR
570 // TODO: supporter plusieurs appels à cette méthode ?
571 for (Integer patch_index = 1; patch_index < m_patch_group.nbPatch(); ++patch_index) {
572 CellGroup cells = m_patch_group.allCells(patch_index);
573 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
574 info() << "Nom du patch AMR=" << cells.name() << " taille=" << cells.size() << " index=" << patch_index << " nbPatch=" << m_patch_group.nbPatch();
575 patch->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
576 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index);
577 _computeMeshDirection(*patch.get(), MD_DirX, cells_center, faces_center, patch_cells, patch_nodes);
578 _computeMeshDirection(*patch.get(), MD_DirY, cells_center, faces_center, patch_cells, patch_nodes);
579 if (is_3d)
580 _computeMeshDirection(*patch.get(), MD_DirZ, cells_center, faces_center, patch_cells, patch_nodes);
581 }
582
583 if (arcaneIsCheck())
584 checkValid();
585
586 _saveInfosInProperties();
587}
588
589/*---------------------------------------------------------------------------*/
590/*---------------------------------------------------------------------------*/
591
592std::tuple<CellGroup, NodeGroup> CartesianMeshImpl::
593_buildPatchGroups(const CellGroup& cells, Integer patch_level)
594{
595 // On créé un groupe pour chaque patch en garantissant que l'ordre de parcours
596 // est celui des uniqueId() des entités
597 // TODO: à terme, il faudrait que l'ordre de parcours soit le même que
598 // celui du maillage cartésien. Pour cela, il faut soit que les uniqueId()
599 // des mailles/noeuds créés soient dans le même ordre que le maillage cartésien,
600 // soit que la fonction de tri soit spécifique à ce type de maillage.
601 NodeGroup nodes = cells.nodeGroup();
602 IItemFamily* cell_family = cells.itemFamily();
603 IItemFamily* node_family = nodes.itemFamily();
604
605 String cell_group_name = String("AMRPatchCells") + patch_level;
606 CellGroup patch_cells = cell_family->createGroup(cell_group_name, Int32ConstArrayView(), true);
607 // Définit les mêmes mailles que \a cells mais force le tri
608 patch_cells.setItems(cells.view().localIds(), true);
609
610 String node_group_name = String("AMRPatchNodes") + patch_level;
611 NodeGroup patch_nodes = node_family->createGroup(node_group_name, Int32ConstArrayView(), true);
612 // Définit les mêmes nœuds que \a nodes mais force le tri
613 patch_nodes.setItems(nodes.view().localIds(), true);
614 info(4) << "PATCH_CELLS nom=" << patch_cells.name() << " taille=" << patch_cells.size();
615 info(4) << "PATCH_NODES nom=" << patch_nodes.name() << " taille=" << patch_nodes.size();
616 return { patch_cells, patch_nodes };
617}
618
619/*---------------------------------------------------------------------------*/
620/*---------------------------------------------------------------------------*/
621
622void CartesianMeshImpl::
623_computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir, VariableCellReal3& cells_center,
624 VariableFaceReal3& faces_center, CellGroup all_cells, NodeGroup all_nodes)
625{
626 IItemFamily* cell_family = m_mesh->cellFamily();
627 IItemFamily* face_family = m_mesh->faceFamily();
628 IItemFamily* node_family = m_mesh->nodeFamily();
629
630 Int32 max_cell_id = cell_family->maxLocalId();
631 Int32 max_face_id = face_family->maxLocalId();
632 Int32 max_node_id = node_family->maxLocalId();
633
634 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
635 cell_dm._internalResizeInfos(max_cell_id);
636
637 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
638 face_dm._internalResizeInfos(max_face_id);
639
640 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
641 node_dm._internalResizeInfos(max_node_id);
642
643 //TODO: attention à remettre à jour après changement de maillage.
644 info(4) << "COMPUTE DIRECTION dir=" << dir;
645
646 Int32 prev_local_face = -1;
647 Int32 next_local_face = m_local_face_direction[dir];
648 Integer mesh_dim = m_mesh->dimension();
649 // Calcule le numéro local de la face opposée à la face suivante.
650 if (mesh_dim == 2)
651 prev_local_face = (next_local_face + 2) % 4;
652 else if (mesh_dim == 3)
653 prev_local_face = (next_local_face + 3) % 6;
654
655 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
656
657 // Positionne pour chaque maille les faces avant et après dans la direction.
658 // On s'assure que ces entités sont dans le groupe des entités de la direction correspondante
659 // Un identifiant local est dense et borné par maxLocalId(), donc un seul tableau répond à
660 // la question d'appartenance que le groupe pose ici avec une seule allocation.
661 UniqueArray<bool> is_in_cells(m_mesh->cellFamily()->maxLocalId(), false);
662 ENUMERATE_CELL (icell, all_cells) {
663 is_in_cells[icell.itemLocalId()] = true;
664 }
665
666 // Calcule les mailles devant/derrière. En cas de patch AMR, il faut que ces deux mailles
667 // soient de même niveau
668 ENUMERATE_CELL (icell, all_cells) {
669 Cell cell = *icell;
670 Int32 my_level = cell.level();
671 Face next_face = cell.face(next_local_face);
672 Cell next_cell = next_face.backCell() == cell ? next_face.frontCell() : next_face.backCell();
673 if (next_cell.null() || !is_in_cells[next_cell.localId()])
674 next_cell = Cell();
675 else if (next_cell.level() != my_level)
676 next_cell = Cell();
677
678 Face prev_face = cell.face(prev_local_face);
679 Cell prev_cell = prev_face.backCell() == cell ? prev_face.frontCell() : prev_face.backCell();
680 if (prev_cell.null() || !is_in_cells[prev_cell.localId()])
681 prev_cell = Cell();
682 else if (prev_cell.level() != my_level)
683 prev_cell = Cell();
684 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
685 }
686 cell_dm._internalComputeInnerAndOuterItems(all_cells);
687 face_dm._internalComputeInfos(cell_dm, cells_center, faces_center);
688 node_dm._internalComputeInfos(cell_dm, all_nodes, cells_center);
689}
690
691/*---------------------------------------------------------------------------*/
692/*---------------------------------------------------------------------------*/
693
694void CartesianMeshImpl::
695_computeDirectionsV2()
696{
697 info() << "CartesianMesh: computeDirectionsV2()";
698
699 m_mesh_timestamp = mesh()->timestamp();
700 _checkAddObservableMeshChanged();
701
702 m_is_amr = m_mesh->isAmrActivated();
703
704 if (m_mesh->dimension() == 3) {
705 m_local_face_direction[MD_DirX] = 4;
706 m_local_face_direction[MD_DirY] = 5;
707 m_local_face_direction[MD_DirZ] = 3;
708 }
709 else {
710 m_local_face_direction[MD_DirX] = 1;
711 m_local_face_direction[MD_DirY] = 2;
712 }
713
714 info() << "Compute cartesian connectivity";
715
716 m_permutation_storage.resize(1);
717 m_permutation_storage[0].compute();
718 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
719 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
720 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
721 m_connectivity._computeInfos(this);
722
723 // Ajoute informations de connectivités pour les patchs AMR
724 for (Integer patch_index = 0; patch_index < m_patch_group.nbPatch(); ++patch_index) {
725 computeDirectionsPatchV2(patch_index);
726 }
727
728 if (arcaneIsCheck())
729 checkValid();
730
731 _saveInfosInProperties();
732}
733
734/*---------------------------------------------------------------------------*/
735/*---------------------------------------------------------------------------*/
736
737void CartesianMeshImpl::
738computeDirectionsPatchV2(Integer patch_index)
739{
740 bool is_3d = m_mesh->dimension() == 3;
741
742 CellGroup cells = m_patch_group.allCells(patch_index);
743 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
744
745 if (patch->index() == -1) {
746 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
747 info() << "Informations depuis les propriétés IMesh:";
748 info() << "GlobalNbCell = " << cmgi->globalNbCells();
749 info() << "OwnNbCell: " << cmgi->ownNbCells();
750 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
751 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
752 // Positionne les informations par direction
753 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
754 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
755 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
756 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
757 }
758 }
759
760 info() << "Nom du patch AMR=" << cells.name() << " taille=" << cells.size() << " index=" << patch_index << " trueindex=" << patch->index() << " nbPatch=" << m_patch_group.nbPatch();
761 {
762 const AMRPatchPosition position = patch->position();
763 info() << " position min=" << position.minPoint() << " max=" << position.maxPoint() << " level=" << position.level() << " overlapLayerSize=" << position.overlapLayerSize();
764 }
765 patch->_internalComputeNodeCellInformations();
766 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index); // TODO À supprimer
767 _computeMeshDirectionV2(*patch.get(), MD_DirX, m_patch_group.allCells(patch_index), m_patch_group.inPatchCells(patch_index), m_patch_group.overlapCells(patch_index), patch_nodes);
768 _computeMeshDirectionV2(*patch.get(), MD_DirY, m_patch_group.allCells(patch_index), m_patch_group.inPatchCells(patch_index), m_patch_group.overlapCells(patch_index), patch_nodes);
769 if (is_3d)
770 _computeMeshDirectionV2(*patch.get(), MD_DirZ, m_patch_group.allCells(patch_index), m_patch_group.inPatchCells(patch_index), m_patch_group.overlapCells(patch_index), patch_nodes);
771}
772
773/*---------------------------------------------------------------------------*/
774/*---------------------------------------------------------------------------*/
775
776void CartesianMeshImpl::
777_computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir, CellGroup all_cells, CellGroup in_patch_cells, CellGroup overlap_cells, NodeGroup all_nodes)
778{
779 IItemFamily* cell_family = m_mesh->cellFamily();
780 IItemFamily* face_family = m_mesh->faceFamily();
781 IItemFamily* node_family = m_mesh->nodeFamily();
782
783 Int32 max_cell_id = cell_family->maxLocalId();
784 Int32 max_face_id = face_family->maxLocalId();
785 Int32 max_node_id = node_family->maxLocalId();
786
787 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
788 cell_dm._internalResizeInfos(max_cell_id);
789
790 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
791 face_dm._internalResizeInfos(max_face_id);
792
793 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
794 node_dm._internalResizeInfos(max_node_id);
795
796 //TODO: attention à remettre à jour après changement de maillage.
797 info(4) << "COMPUTE DIRECTION dir=" << dir;
798
799 Int32 prev_local_face = -1;
800 Int32 next_local_face = m_local_face_direction[dir];
801 Integer mesh_dim = m_mesh->dimension();
802 // Calcul le numero local de face oppose à la face suivante.
803 if (mesh_dim == 2)
804 prev_local_face = (next_local_face + 2) % 4;
805 else if (mesh_dim == 3)
806 prev_local_face = (next_local_face + 3) % 6;
807
808 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
809
810 // Positionne pour chaque maille les faces avant et après dans la direction.
811 // On s'assure que ces entités sont dans le groupe des entités de la direction correspondante
812 UniqueArray<bool> is_in_cells(m_mesh->cellFamily()->maxLocalId(), false);
813 ENUMERATE_ (Cell, icell, all_cells) {
814 is_in_cells[icell.itemLocalId()] = true;
815 }
816
817 // Calcule les mailles devant/derrière. En cas de patch AMR, il faut que ces deux mailles
818 // soient de même niveau
819 ENUMERATE_ (Cell, icell, all_cells) {
820 Cell cell = *icell;
821 Int32 my_level = cell.level();
822 Face next_face = cell.face(next_local_face);
823 Cell next_cell = next_face.backCell() == cell ? next_face.frontCell() : next_face.backCell();
824 if (next_cell.null() || !is_in_cells[next_cell.localId()] || next_cell.level() != my_level) {
825 next_cell = Cell();
826 }
827
828 Face prev_face = cell.face(prev_local_face);
829 Cell prev_cell = prev_face.backCell() == cell ? prev_face.frontCell() : prev_face.backCell();
830 if (prev_cell.null() || !is_in_cells[prev_cell.localId()] || prev_cell.level() != my_level) {
831 prev_cell = Cell();
832 }
833
834 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
835 }
836 cell_dm._internalComputeCellGroups(all_cells, in_patch_cells, overlap_cells);
837 face_dm._internalComputeInfos(cell_dm);
838 node_dm._internalComputeInfos(cell_dm, all_nodes);
839}
840
841/*---------------------------------------------------------------------------*/
842/*---------------------------------------------------------------------------*/
843
845refinePatch2D(Real2 position, Real2 length)
846{
847 info() << "REFINEMENT 2D position=" << position << " length=" << length;
848 refinePatch({ position, length });
849}
850
851/*---------------------------------------------------------------------------*/
852/*---------------------------------------------------------------------------*/
853
855refinePatch3D(Real3 position, Real3 length)
856{
857 info() << "REFINEMENT 3D position=" << position << " length=" << length;
858 refinePatch({ position, length });
859}
860
861/*---------------------------------------------------------------------------*/
862/*---------------------------------------------------------------------------*/
863
865refinePatch(const AMRZonePosition& position)
866{
867 _applyRefine(position);
868 _saveInfosInProperties();
869}
870
871/*---------------------------------------------------------------------------*/
872/*---------------------------------------------------------------------------*/
873
875coarseZone2D(Real2 position, Real2 length)
876{
877 info() << "COARSEN 2D position=" << position << " length=" << length;
878 coarseZone({ position, length });
879}
880
881/*---------------------------------------------------------------------------*/
882/*---------------------------------------------------------------------------*/
883
885coarseZone3D(Real3 position, Real3 length)
886{
887 info() << "COARSEN 3D position=" << position << " length=" << length;
888 coarseZone({ position, length });
889}
890
891/*---------------------------------------------------------------------------*/
892/*---------------------------------------------------------------------------*/
893
895coarseZone(const AMRZonePosition& position)
896{
897 _applyCoarse(position);
898 _saveInfosInProperties();
899}
900
901/*---------------------------------------------------------------------------*/
902/*---------------------------------------------------------------------------*/
903
905reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers)
906{
907 if (level < 1) {
908 ARCANE_FATAL("Vous ne pouvez pas réduire le nombre de couches fantômes du niveau 0 avec cette méthode");
909 }
910
911 // Nombre de couche de maille fantôme max. Bof; à modifier.
912 const Int32 max_nb_layer = 128;
913 Int32 level_max = 0;
914
915 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
916 level_max = std::max(level_max, icell->level());
917 }
918
919 level_max = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, level_max);
920 //debug() << "Niveau max : " << level_max;
921
923
924 Integer level_0_nb_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer();
925 //debug() << "NbGhostLayers niveau 0 : " << level_0_nb_ghost_layer;
926
927 if (level_0_nb_ghost_layer == 0) {
928 return 0;
929 }
930
931 Integer nb_ghost_layer = Convert::toInt32(level_0_nb_ghost_layer * pow(2, level));
932
933 //debug() << "NbGhostLayers niveau " << level << " : " << nb_ghost_layer;
934
935 // On considère qu'on a toujours 2*2 mailles filles (2*2*2 en 3D).
936 if (target_nb_ghost_layers % 2 != 0) {
937 target_nb_ghost_layers++;
938 }
939
940 if (target_nb_ghost_layers == nb_ghost_layer) {
941 return nb_ghost_layer;
942 }
943
944 //debug() << "TargetNbGhostLayers niveau " << level << " : " << target_nb_ghost_layers;
945
946 Integer parent_level = level - 1;
947 Integer parent_target_nb_ghost_layer = target_nb_ghost_layers / 2;
948
949 // TODO AH : On est forcé de dé-raffiner niveau par niveau. À changer.
950 UniqueArray<UniqueArray<Int32>> cell_lid2(level_max);
951
952 //UniqueArray<Int32> cell_lid;
953 std::function<void(Cell)> children_list;
954
955 children_list = [&cell_lid2, &children_list](Cell cell) -> void {
956 for (Integer i = 0; i < cell.nbHChildren(); ++i) {
957 //debug() << "child of lid=" << cell.localId() << " : lid=" << cell.hChild(i).localId() << " -- level : " << cell.level();
958 cell_lid2[cell.level()].add(cell.hChild(i).localId());
959 children_list(cell.hChild(i));
960 }
961 };
962
963 // Algorithme de numérotation des couches de mailles fantômes.
964 {
965 VariableNodeInt32 level_node{ VariableBuildInfo{ m_mesh, "LevelNode" } };
966 level_node.fill(-1);
967
968 VariableCellInt32 level_cell{ VariableBuildInfo{ m_mesh, "LevelCell" } };
969 level_cell.fill(-1);
970
971 ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
972 Cell front_cell = iface->frontCell();
973 Cell back_cell = iface->backCell();
974 if (
975 ((front_cell.null() || (!front_cell.isOwn() && front_cell.level() == parent_level)) && ((!back_cell.null()) && (back_cell.isOwn() && back_cell.level() == parent_level))) ||
976 ((back_cell.null() || (!back_cell.isOwn() && back_cell.level() == parent_level)) && ((!front_cell.null()) && (front_cell.isOwn() && front_cell.level() == parent_level)))) {
977 for (Node node : iface->nodes()) {
978 level_node[node] = 0;
979 //debug() << "Node layer 0 : " << node.uniqueId();
980 }
981 }
982 }
983
984 bool is_modif = true;
985 Int32 current_layer = 0;
986 while (is_modif) {
987 is_modif = false;
988
989 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
990 if (icell->isOwn() || icell->level() != parent_level || level_cell[icell] != -1) {
991 continue;
992 }
993
994 Int32 min = max_nb_layer;
995 Int32 max = -1;
996
997 for (Node node : icell->nodes()) {
998 Int32 nlevel = level_node[node];
999 if (nlevel != -1) {
1000 min = std::min(min, nlevel);
1001 max = std::max(max, nlevel);
1002 }
1003 }
1004
1005 // On fait couche par couche (voir pour enlever cette limitation).
1006 if (min != current_layer) {
1007 continue;
1008 }
1009
1010 // Maille n'ayant pas de nodes déjà traités.
1011 if (min == max_nb_layer && max == -1) {
1012 continue;
1013 }
1014
1015 Integer new_level = ((min == max) ? min + 1 : max);
1016
1017 for (Node node : icell->nodes()) {
1018 Int32 nlevel = level_node[node];
1019 if (nlevel == -1) {
1020 level_node[node] = new_level;
1021 //debug() << "Node layer " << new_level << " : " << node.uniqueId();
1022 is_modif = true;
1023 }
1024 }
1025
1026 level_cell[icell] = min;
1027
1028 //debug() << "Cell uid : " << icell->uniqueId()
1029 // << " -- Layer : " << min;
1030
1031 if (min >= parent_target_nb_ghost_layer) {
1032 children_list(*icell);
1033 }
1034 }
1035 current_layer++;
1036 if (current_layer >= max_nb_layer) {
1037 ARCANE_FATAL("Erreur dans l'algorithme du compteur de couches fantômes. Signalez-le s'il vous plaît.");
1038 }
1039 }
1040 }
1041
1042 for (Integer i = level_max - 1; i >= 0; --i) {
1043 // Une communication pour éviter beaucoup d'autres.
1044 if (m_mesh->parallelMng()->reduce(Parallel::ReduceMax, cell_lid2[i].size()) == 0) {
1045 continue;
1046 }
1047 //debug() << "Removing children of ghost cell (parent level=" << i << ") (children localIds) : " << cell_lid2[i];
1048
1049 m_mesh->modifier()->flagCellToCoarsen(cell_lid2[i]);
1050 m_mesh->modifier()->coarsenItemsV2(false);
1051 }
1052
1053 info() << "Nb de couches fantômes pour le niveau " << level << " : " << target_nb_ghost_layers;
1054
1055 return target_nb_ghost_layers;
1056}
1057
1058/*---------------------------------------------------------------------------*/
1059/*---------------------------------------------------------------------------*/
1060
1061void CartesianMeshImpl::
1062_addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id)
1063{
1064 _addPatch(parent_cells_local_id);
1065}
1066
1067/*---------------------------------------------------------------------------*/
1068/*---------------------------------------------------------------------------*/
1069/*!
1070 * \brief Crée un patch avec tous les enfants du groupe \a parent_cells.
1071 */
1072void CartesianMeshImpl::
1073_addPatch(ConstArrayView<Int32> parent_cells)
1074{
1075 // Crée le groupe contenant les mailles AMR
1076 // Ce sont les mailles enfants de \a parent_cells
1077
1078 UniqueArray<Int32> children_local_id;
1079 CellInfoListView cells(m_mesh->cellFamily());
1080 for (Int32 cell_local_id : parent_cells) {
1081 Cell c = cells[cell_local_id];
1082 for (Integer k = 0; k < c.nbHChildren(); ++k) {
1083 Cell child = c.hChild(k);
1084 children_local_id.add(child.localId());
1085 }
1086 }
1087
1088 m_patch_group.addPatch(children_local_id);
1089}
1090
1091/*---------------------------------------------------------------------------*/
1092/*---------------------------------------------------------------------------*/
1093
1094void CartesianMeshImpl::
1095_applyRefine(const AMRZonePosition& position)
1096{
1097 if (m_amr_type == eMeshAMRKind::Cell) {
1098 UniqueArray<Int32> cells_local_id;
1099 position.cellsInPatch(mesh(), cells_local_id);
1100
1101 Integer nb_cell = cells_local_id.size();
1102 info(4) << "Local_NbCellToRefine = " << nb_cell;
1103
1104 IParallelMng* pm = m_mesh->parallelMng();
1105 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1106 info(4) << "Global_NbCellToRefine = " << total_nb_cell;
1107 if (total_nb_cell == 0)
1108 return;
1109
1110 debug() << "Raffine avec modifier() (pour tous les types de maillage)";
1111 m_mesh->modifier()->flagCellToRefine(cells_local_id);
1112 m_mesh->modifier()->adapt();
1113
1114 _addPatch(cells_local_id);
1115 }
1116
1117 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1118 debug() << "Raffine avec un raffineur spécifique (pour maillage cartésien uniquement)";
1119 m_patch_group.addPatch(position);
1120 }
1121
1122 else if (m_amr_type == eMeshAMRKind::Patch) {
1123 ARCANE_FATAL("L'AMR de patch général n'est pas implémenté. Veuillez utiliser PatchCartesianMeshOnly (3)");
1124 }
1125 else {
1126 ARCANE_FATAL("L'AMR n'est pas activé");
1127 }
1128
1129 {
1130 MeshStats ms(traceMng(), m_mesh, m_mesh->parallelMng());
1131 ms.dumpStats();
1132 }
1133}
1134
1135/*---------------------------------------------------------------------------*/
1136/*---------------------------------------------------------------------------*/
1137
1138void CartesianMeshImpl::
1139_applyCoarse(const AMRZonePosition& zone_position)
1140{
1141 if (m_amr_type == eMeshAMRKind::Cell) {
1142 UniqueArray<Int32> cells_local_id;
1143
1144 zone_position.cellsInPatch(mesh(), cells_local_id);
1145
1146 Integer nb_cell = cells_local_id.size();
1147 info(4) << "Local_NbCellToCoarsen = " << nb_cell;
1148
1149 IParallelMng* pm = m_mesh->parallelMng();
1150 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1151 info(4) << "Global_NbCellToCoarsen = " << total_nb_cell;
1152 if (total_nb_cell == 0)
1153 return;
1154
1155 debug() << "Coarsening avec modifier() (pour tous les types de maillage)";
1156 m_patch_group.removeCellsInAllPatches(cells_local_id);
1157
1158 m_mesh->modifier()->flagCellToCoarsen(cells_local_id);
1159 m_mesh->modifier()->coarsenItemsV2(true);
1160 }
1161
1162 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1163 debug() << "Coarsening avec un grossisseur spécifique (pour maillage cartésien uniquement)";
1164 m_patch_group.removeCellsInZone(zone_position);
1165 }
1166
1167 else if (m_amr_type == eMeshAMRKind::Patch) {
1168 ARCANE_FATAL("L'AMR de patch général n'est pas implémenté. Veuillez utiliser PatchCartesianMeshOnly (3)");
1169 }
1170 else {
1171 ARCANE_FATAL("L'AMR n'est pas activé");
1172 }
1173
1174 {
1175 MeshStats ms(traceMng(), m_mesh, m_mesh->parallelMng());
1176 ms.dumpStats();
1177 }
1178}
1179
1180/*---------------------------------------------------------------------------*/
1181/*---------------------------------------------------------------------------*/
1182
1184checkValid() const
1185{
1186 info(4) << "Vérification du maillage cartésien valide";
1187 Integer nb_patch = nbPatch();
1188 for (Integer i = 0; i < nb_patch; ++i) {
1189 ICartesianMeshPatch* p = patch(i);
1190 p->checkValid();
1191 }
1192}
1193
1194/*---------------------------------------------------------------------------*/
1195/*---------------------------------------------------------------------------*/
1196
1199{
1200 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
1201
1202 // Regarde d'abord si on renumérote les faces
1203 Int32 face_method = v.renumberFaceMethod();
1204 if (face_method != 0 && face_method != 1)
1205 ARCANE_FATAL("Valeur '{0}' invalide pour renumberFaceMethod(). Les valeurs valides sont 0 ou 1",
1206 face_method);
1207 if (face_method == 1)
1208 ARCANE_THROW(NotImplementedException, "Méthode 1 pour la renumérotation des faces");
1209
1210 // Regarde ensuite les patchs si demandé.
1211 Int32 patch_method = v.renumberPatchMethod();
1212 if (patch_method < 0 || patch_method > 4) {
1213 ARCANE_FATAL("Valeur '{0}' invalide pour renumberPatchMethod(). Les valeurs valides sont 0, 1, 2, 3 ou 4",
1214 patch_method);
1215 }
1216 if (patch_method != 0 && m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1217 ARCANE_FATAL("La renumérotation des éléments du maillage n'est pas compatible avec ce type d'AMR");
1218 }
1219
1220 if (patch_method == 1 || patch_method == 3 || patch_method == 4) {
1221 CartesianMeshUniqueIdRenumbering renumberer(this, cmgi, v.parentPatch(), patch_method);
1222 renumberer.renumber();
1223 }
1224 else if (patch_method == 2) {
1225 warning() << "La méthode de patch 2 est expérimentale !";
1226 CartesianMeshUniqueIdRenumberingV2 renumberer(this, cmgi);
1227 renumberer.renumber();
1228 }
1229
1230 // Termine par un tri éventuel.
1231 if (v.isSortAfterRenumbering()) {
1232 info() << "Compactage et tri après renumérotation";
1233 m_mesh->nodeFamily()->compactItems(true);
1234 m_mesh->faceFamily()->compactItems(true);
1235 m_mesh->cellFamily()->compactItems(true);
1237 }
1238}
1239
1240/*---------------------------------------------------------------------------*/
1241/*---------------------------------------------------------------------------*/
1242
1248
1249/*---------------------------------------------------------------------------*/
1250/*---------------------------------------------------------------------------*/
1251
1252Ref<CartesianMeshCoarsening2> CartesianMeshImpl::
1253_createCartesianMeshCoarsening2()
1254{
1255 return makeRef(new CartesianMeshCoarsening2(this));
1256}
1257
1258/*---------------------------------------------------------------------------*/
1259/*---------------------------------------------------------------------------*/
1260
1261/*---------------------------------------------------------------------------*/
1262/*---------------------------------------------------------------------------*/
1263
1265getReference(const MeshHandleOrMesh& mesh_handle_or_mesh, bool create)
1266{
1267 MeshHandle h = mesh_handle_or_mesh.handle();
1268 //TODO: faire lock pour multi-thread
1269 const char* name = "CartesianMesh";
1270 IUserDataList* udlist = h.meshUserDataList();
1271
1272 IUserData* ud = udlist->data(name, true);
1273 if (!ud) {
1274 if (!create)
1275 return nullptr;
1276 IMesh* mesh = h.meshOrNull();
1277 if (!mesh)
1278 ARCANE_FATAL("Le maillage {0} n'a pas encore été créé", h.meshName());
1279 ICartesianMesh* cm = arcaneCreateCartesianMesh(mesh);
1280 udlist->setData(name, new AutoDestroyUserData<ICartesianMesh>(cm));
1281
1282 // Indique que le maillage est cartésien
1283 MeshKind mk = mesh->meshKind();
1284 mk.setMeshStructure(eMeshStructure::Cartesian);
1285 mesh->_internalApi()->setMeshKind(mk);
1286
1287 return cm;
1288 }
1290 if (!adud)
1291 ARCANE_FATAL("Impossible de caster en ICartesianMesh*");
1292 return adud->data();
1293}
1294
1295/*---------------------------------------------------------------------------*/
1296/*---------------------------------------------------------------------------*/
1297
1298} // End namespace Arcane
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Fichier contenant les mécanismes de gestion des évènements.
Classe permettant de définir une zone d'un maillage.
Integer size() const
Nombre d'éléments du vecteur.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
UserData s'auto-détruisant une fois détaché.
Informations de connectivité d'un maillage cartésien.
Déraffine un maillage cartésien par 2.
Déraffine un maillage cartésien par 2.
Informations spécifiques pour un maillage cartésien.
void refinePatch3D(Real3 position, Real3 length) override
Raffine en 3D un bloc du maillage cartésien.
Int32 nbPatch() const override
Nombre de patchs du maillage.
Integer reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers) override
Méthode permettant de supprimer une ou plusieurs couches de mailles fantômes sur un niveau de raffine...
void refinePatch(const AMRZonePosition &position) override
Raffine un bloc du maillage cartésien.
ITraceMng * traceMng() const override
Gestionnaire de traces associé.
CellDirectionMng cellDirection(Integer idir) override
Liste des mailles dans la direction dir (0, 1 ou 2).
void recreateFromDump() override
Recalcule les informations de cartésiennes après une reprise.
void computeDirections() override
Calcule les infos pour les accès par direction.
FaceDirectionMng faceDirection(Integer idir) override
Liste des faces dans la direction dir (0, 1 ou 2).
void coarseZone(const AMRZonePosition &position) override
Dé-raffine un bloc du maillage cartésien.
NodeDirectionMng nodeDirection(Integer idir) override
Liste des noeuds dans la direction dir (0, 1 ou 2).
void checkValid() const override
Effectue des vérifications sur la validité de l'instance.
IMesh * mesh() const override
Maillage associé à ce maillage cartésien.
FaceDirectionMng faceDirection(eMeshDirection dir) override
Liste des faces dans la direction dir.
NodeDirectionMng nodeDirection(eMeshDirection dir) override
Liste des noeuds dans la direction dir.
void refinePatch2D(Real2 position, Real2 length) override
Raffine en 2D un bloc du maillage cartésien.
ICartesianMeshPatch * patch(Int32 index) const override
Retourne le index-ième patch du maillage.
void coarseZone2D(Real2 position, Real2 length) override
Dé-raffine en 2D un bloc du maillage cartésien.
void renumberItemsUniqueId(const CartesianMeshRenumberingInfo &v) override
Renumérote les uniqueId() des entités.
ICartesianMeshInternal * _internalApi() override
API interne à Arcane.
void coarseZone3D(Real3 position, Real3 length) override
Dé-raffine en 3D un bloc du maillage cartésien.
Ref< CartesianMeshCoarsening > createCartesianMeshCoarsening() override
Créé une instance pour gérer le déraffinement du maillage.
CartesianPatch amrPatch(Int32 index) const override
Retourne le index-ième patch du maillage.
CellDirectionMng cellDirection(eMeshDirection dir) override
Liste des mailles dans la direction dir.
CartesianMeshPatchListView patches() const override
Vue sur la liste des patchs.
CartesianConnectivity connectivity() override
Informations sur la connectivité
Patch AMR d'un maillage cartésien.
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:1214
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1295
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1292
Int32 level() const
Definition Item.h:1368
Vue constante d'un tableau de type T.
Infos sur les face d'une direction spécifique X,Y ou Z d'un maillage structuré.
Face d'une maille.
Definition Item.h:964
Interface d'un patch AMR d'un maillage cartésien.
virtual void checkValid() const =0
Effectue des vérifications sur la validité de l'instance.
Interface d'un maillage cartésien.
static ICartesianMesh * getReference(const MeshHandleOrMesh &mesh, bool create=true)
Récupère ou créé la référence associée à mesh.
virtual IMesh * mesh() const =0
Maillage associé à ce maillage cartésien.
Interface d'une famille d'entités.
Definition IItemFamily.h:86
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Créé un groupe d'entités de nom name contenant les entités local_ids.
virtual Int32 maxLocalId() const =0
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
virtual Int64 timestamp()=0
Compteur indiquant le temps de dernière modification du maillage.
virtual EventObservable< const MeshEventArgs & > & eventObservable(eMeshEventType type)=0
Observable pour un évènement.
Interface du gestionnaire de traces.
Interface d'une liste qui gère des données utilisateurs.
virtual void setData(const String &name, IUserData *ud)=0
Positionne le user-data associé au nom name.
virtual IUserData * data(const String &name, bool allow_null=false) const =0
Donnée associée à name.
Interface pour une donnée utilisateur attachée à un autre objet.
Definition IUserData.h:31
Classe de base d'une vue sur une connectivité non structurée.
NodeGroup nodeGroup() const
Groupe des noeuds des éléments de ce groupe.
Definition ItemGroup.cc:230
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
ItemVectorView view() const
Vue sur les entités du groupe.
Definition ItemGroup.cc:583
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul).
Definition ItemGroup.h:123
void setItems(Int32ConstArrayView items_local_id)
Positionne les entités du groupe.
Definition ItemGroup.cc:489
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:34
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:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Definition Item.h:797
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
constexpr bool isOwn() const
true si l'entité est appartient au sous-domaine
Definition Item.h:253
Arguments des évènements sur le maillage.
Definition MeshEvents.h:43
Classe de compatibilité pour contenir un MeshHandle ou un IMesh*.
Definition MeshHandle.h:159
const MeshHandle & handle() const
handle associé.
Definition MeshHandle.h:182
Handle sur un maillage.
Definition MeshHandle.h:48
IMesh * meshOrNull() const
Retourne le maillage associé à cette instance.
IUserDataList * meshUserDataList() const
Données utilisateurs associées.
Caractéristiques d'un maillage.
Definition MeshKind.h:111
Infos sur les noeuds d'une direction spécifique X,Y ou Z d'un maillage structuré.
Noeud d'un maillage.
Definition Item.h:582
Classe gérant un vecteur réel 2-dimensionnel.
Classe gérant un vecteur réel de 3 dimensions.
bool isNull() const
Indique si le compteur référence une instance non nulle.
InstanceType * get() const
Instance associée ou nullptr si aucune.
Référence à une instance.
Chaîne de caractères unicode.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage warning() const
Flot pour un message d'avertissement.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemVectorViewT< Cell > CellVectorView
Vue sur un vecteur de mailles.
Definition ItemTypes.h:304
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Cell, Real3 > VariableCellReal3
Grandeur au centre des mailles de type coordonnées.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Node, Int32 > VariableNodeInt32
Grandeur au noeud de type entier 32 bits.
MeshVariableScalarRefT< Face, Real3 > VariableFaceReal3
Grandeur aux faces de type coordonnées.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Grandeur au centre des mailles de type entier 32 bits.
Int32 toInt32(Real r)
Convertit un Real en Int32.
@ ReduceSum
Somme des valeurs.
@ ReduceMax
Maximum des valeurs.
Espace de nom pour les fonctions dépendant de la plateforme.
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool arcaneIsCheck()
Vrai si on est en mode vérification.
Definition Misc.cc:68
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:480
@ Cartesian
Maillage cartésien.
Definition MeshKind.h:35
eMeshDirection
Type de la direction pour un maillage structuré
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
@ EndPrepareDump
Evènement envoyé à la fin de prepareForDump().
Definition MeshEvents.h:34
double Real
Type représentant un réel.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
eMeshAMRKind
Type de maillage AMR.
Definition MeshKind.h:48
@ Patch
Le maillage est AMR par patch.
Definition MeshKind.h:54
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
@ PatchCartesianMeshOnly
Le maillage est AMR par patch cartésien (rectangulaire).
Definition MeshKind.h:56
std::int32_t Int32
Type entier signé sur 32 bits.
Real y
deuxième composante du triplet
Real z
troisième composante du triplet
Real x
première composante du triplet