Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
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/* Cartesian mesh. */
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
23#include "arcane/core/IMesh.h"
24#include "arcane/core/ItemPrinter.h"
25#include "arcane/core/IItemFamily.h"
26#include "arcane/core/IParallelMng.h"
27#include "arcane/core/VariableTypes.h"
28#include "arcane/core/Properties.h"
29#include "arcane/core/IMeshModifier.h"
30#include "arcane/core/MeshStats.h"
31#include "arcane/core/ICartesianMeshGenerationInfo.h"
32#include "arcane/core/MeshEvents.h"
33#include "arcane/core/MeshKind.h"
34#include "arcane/core/internal/IMeshInternal.h"
35
36#include "arcane/cartesianmesh/internal/CartesianPatchGroup.h"
37#include "arcane/cartesianmesh/ICartesianMesh.h"
38#include "arcane/cartesianmesh/AMRZonePosition.h"
39#include "arcane/cartesianmesh/CartesianConnectivity.h"
40#include "arcane/cartesianmesh/CartesianMeshRenumberingInfo.h"
41#include "arcane/cartesianmesh/CartesianMeshCoarsening.h"
42#include "arcane/cartesianmesh/CartesianMeshCoarsening2.h"
43#include "arcane/cartesianmesh/CartesianMeshPatchListView.h"
44#include "arcane/cartesianmesh/internal/CartesianMeshPatch.h"
45#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
46
47#include "arcane/cartesianmesh/internal/CartesianMeshUniqueIdRenumbering.h"
48#include "arcane/cartesianmesh/v2/CartesianMeshUniqueIdRenumberingV2.h"
49#include "arcane/cartesianmesh/CartesianMeshNumberingMng.h"
50
51#include "arcane/cartesianmesh/internal/CartesianMeshAMRPatchMng.h"
52#include "arcane/core/IGhostLayerMng.h"
53#include "arcane/cartesianmesh/internal/CartesianMeshNumberingMngInternal.h"
54
55#include <set>
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59/*!
60 * \defgroup ArcaneCartesianMesh Cartesian meshes.
61 *
62 * Set of classes ensuring the management of Cartesian meshes.
63 *
64 * For more information, refer to the page \ref arcanedoc_entities_cartesianmesh.
65 */
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
68
69namespace Arcane
70{
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75/*!
76 * \brief Specific information for a Cartesian mesh.
77 */
78class CartesianMeshImpl
79: public TraceAccessor
80, public ICartesianMesh
81{
82 class InternalApi
83 : public ICartesianMeshInternal
84 {
85 public:
86
87 explicit InternalApi(CartesianMeshImpl* cartesian_mesh)
88 : m_cartesian_mesh(cartesian_mesh)
89 {
90 }
91
92 public:
93
94 Ref<CartesianMeshCoarsening2> createCartesianMeshCoarsening2() override
95 {
96 return m_cartesian_mesh->_createCartesianMeshCoarsening2();
97 }
98 void addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id) override
99 {
100 m_cartesian_mesh->_addPatchFromExistingChildren(parent_cells_local_id);
101 }
102 void initCartesianMeshAMRPatchMng() override
103 {
104 if (m_numbering_mng.isNull()) {
105 initCartesianMeshNumberingMngInternal();
106 }
107 if (m_amr_mng.isNull()) {
108 m_amr_mng = makeRef(new CartesianMeshAMRPatchMng(m_cartesian_mesh, m_numbering_mng.get()));
109 }
110 }
111 Ref<ICartesianMeshAMRPatchMng> cartesianMeshAMRPatchMng() override
112 {
113 return m_amr_mng;
114 }
115 void initCartesianMeshNumberingMngInternal() override
116 {
117 if (m_numbering_mng.isNull()) {
118 m_numbering_mng = makeRef(new CartesianMeshNumberingMngInternal(m_cartesian_mesh->mesh()));
119 }
120 }
121 Ref<ICartesianMeshNumberingMngInternal> cartesianMeshNumberingMngInternal() override
122 {
123 return m_numbering_mng;
124 }
125 CartesianPatchGroup& cartesianPatchGroup() override { return m_cartesian_mesh->_cartesianPatchGroup(); }
126 // TODO : Ugly.
127 void saveInfosInProperties() override { m_cartesian_mesh->_saveInfosInProperties(); }
128
129 private:
130
131 CartesianMeshImpl* m_cartesian_mesh = nullptr;
134 };
135
136 public:
137
138 explicit CartesianMeshImpl(IMesh* mesh);
139
140 public:
141
142 void build() override;
143
144 //! Mesh associated with this Cartesian mesh
145 IMesh* mesh() const override { return m_mesh; }
146
147 //! Associated trace manager.
148 ITraceMng* traceMng() const override { return TraceAccessor::traceMng(); }
149
151 {
152 return m_all_items_direction_info->cellDirection(dir);
153 }
154
156 {
157 return m_all_items_direction_info->cellDirection(idir);
158 }
159
161 {
162 return m_all_items_direction_info->faceDirection(dir);
163 }
164
166 {
167 return m_all_items_direction_info->faceDirection(idir);
168 }
169
171 {
172 return m_all_items_direction_info->nodeDirection(dir);
173 }
174
176 {
177 return m_all_items_direction_info->nodeDirection(idir);
178 }
179
180 void computeDirections() override;
181
182 void recreateFromDump() override;
183
185 {
186 return m_connectivity;
187 }
188
189 Int32 nbPatch() const override { return m_patch_group.nbPatch(); }
190 ICartesianMeshPatch* patch(Int32 index) const override { return m_patch_group.patch(index).get(); }
191 CartesianPatch amrPatch(Int32 index) const override { return CartesianPatch(m_patch_group.patch(index).get()); }
192 CartesianMeshPatchListView patches() const override { return m_patch_group.patchListView(); }
193
194 void refinePatch2D(Real2 position, Real2 length) override;
195 void refinePatch3D(Real3 position, Real3 length) override;
196 void refinePatch(const AMRZonePosition& position) override;
197
198 void coarseZone2D(Real2 position, Real2 length) override;
199 void coarseZone3D(Real3 position, Real3 length) override;
200 void coarseZone(const AMRZonePosition& position) override;
201
202 Integer reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers) override;
203
205
206 void checkValid() const override;
207
209
210 //! Internal API for Arcane
211 ICartesianMeshInternal* _internalApi() override { return &m_internal_api; }
212
213 void computeDirectionsPatchV2(Integer index) override;
214
215 private:
216
217 // Implementation of 'ICartesianMeshInternal'
218 Ref<CartesianMeshCoarsening2> _createCartesianMeshCoarsening2();
219 void _addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id);
220 CartesianPatchGroup& _cartesianPatchGroup() { return m_patch_group; }
221 void _computeDirectionsV2();
222
223 private:
224
225 InternalApi m_internal_api;
226 //! Index in the local numbering of the cell, of the face in
227 // the X, Y or Z direction
228 Int32 m_local_face_direction[3] = { -1, -1, -1 };
229 IMesh* m_mesh = nullptr;
230 Ref<CartesianMeshPatch> m_all_items_direction_info;
231 CartesianConnectivity m_connectivity;
232 UniqueArray<CartesianConnectivity::Index> m_nodes_to_cell_storage;
233 UniqueArray<CartesianConnectivity::Index> m_cells_to_node_storage;
234 UniqueArray<CartesianConnectivity::Permutation> m_permutation_storage;
235 bool m_is_amr = false;
236 //! Group of cells for each AMR patch.
237 CartesianPatchGroup m_patch_group;
238 ScopedPtrT<Properties> m_properties;
239
240 EventObserverPool m_event_pool;
241 bool m_is_mesh_event_added = false;
242 Int64 m_mesh_timestamp = 0;
243 eMeshAMRKind m_amr_type;
244
245 private:
246
247 void _computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir,
248 VariableCellReal3& cells_center,
249 VariableFaceReal3& faces_center, CellGroup all_cells,
250 NodeGroup all_nodes);
251
252 void _computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir,
253 CellGroup all_cells,
254 CellGroup in_patch_cells,
255 CellGroup overlap_cells,
256 NodeGroup all_nodes);
257
258 void _applyRefine(const AMRZonePosition& position);
259 void _applyCoarse(const AMRZonePosition& zone_position);
260 void _addPatch(ConstArrayView<Int32> parent_cells);
261 void _saveInfosInProperties();
262
263 std::tuple<CellGroup, NodeGroup>
264 _buildPatchGroups(const CellGroup& cells, Integer patch_level);
265 void _checkNeedComputeDirections();
266 void _checkAddObservableMeshChanged();
267};
268
269/*---------------------------------------------------------------------------*/
270/*---------------------------------------------------------------------------*/
271
272extern "C++" ICartesianMesh*
273arcaneCreateCartesianMesh(IMesh* mesh)
274{
275 auto* cm = new CartesianMeshImpl(mesh);
276 cm->build();
277 return cm;
278}
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
283CartesianMeshImpl::
284CartesianMeshImpl(IMesh* mesh)
285: TraceAccessor(mesh->traceMng())
286, m_internal_api(this)
287, m_mesh(mesh)
288, m_nodes_to_cell_storage(platform::getDefaultDataAllocator())
289, m_cells_to_node_storage(platform::getDefaultDataAllocator())
290, m_permutation_storage(platform::getDefaultDataAllocator())
291, m_patch_group(this)
292, m_amr_type(mesh->meshKind().meshAMRKind())
293{
294 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
295 m_internal_api.initCartesianMeshNumberingMngInternal();
296 m_internal_api.initCartesianMeshAMRPatchMng();
297 }
298 m_all_items_direction_info = m_patch_group.groundPatch();
299}
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
304void CartesianMeshImpl::
305build()
306{
307 m_properties = new Properties(*(mesh()->properties()), "CartesianMesh");
308 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
309 m_internal_api.cartesianMeshNumberingMngInternal()->build();
310 }
311 m_patch_group.build();
312}
313
314namespace
315{
316 const Int32 SERIALIZE_VERSION = 1;
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322void CartesianMeshImpl::
323_checkNeedComputeDirections()
324{
325 Int64 new_timestamp = mesh()->timestamp();
326 if (m_mesh_timestamp != new_timestamp) {
327 info() << "Mesh timestamp has changed (old=" << m_mesh_timestamp << " new=" << new_timestamp << ")";
329 }
330}
331
332/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
334
335void CartesianMeshImpl::
336_saveInfosInProperties()
337{
338 // Saves the version number to ensure it is OK upon restart/recovery
339 m_properties->set("Version", SERIALIZE_VERSION);
340
341 m_patch_group.saveInfosInProperties();
342
343 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
344 m_internal_api.cartesianMeshNumberingMngInternal()->saveInfosInProperties();
345 //m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
346 }
347}
348
349/*---------------------------------------------------------------------------*/
350/*---------------------------------------------------------------------------*/
351
354{
355 info() << "Creating 'CartesianMesh' infos from dump";
356
357 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
358 m_internal_api.cartesianMeshNumberingMngInternal()->recreateFromDump();
359 m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
360 }
361
362 // Saves the version number to ensure it is OK upon restart/recovery
363 Int32 v = m_properties->getInt32("Version");
364 if (v != SERIALIZE_VERSION)
365 ARCANE_FATAL("Bad serializer version: trying to read from incompatible checkpoint v={0} expected={1}",
366 v, SERIALIZE_VERSION);
367
368 m_patch_group.recreateFromDump();
369
370 m_all_items_direction_info = m_patch_group.groundPatch();
371
373}
374
375/*---------------------------------------------------------------------------*/
376/*---------------------------------------------------------------------------*/
377
378void CartesianMeshImpl::
379_checkAddObservableMeshChanged()
380{
381 if (m_is_mesh_event_added)
382 return;
383 m_is_mesh_event_added = true;
384 // To automatically call 'computeDirections()' after a call to
385 // IMesh::prepareForDump().
386 auto f1 = [&](const MeshEventArgs&) { this->_checkNeedComputeDirections(); };
387 mesh()->eventObservable(eMeshEventType::EndPrepareDump).attach(m_event_pool, f1);
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
395{
396 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
397 // TODO: See where to put the renumbering.
398 m_internal_api.cartesianMeshNumberingMngInternal()->renumberingFacesLevel0FromOriginalArcaneNumbering();
399 _computeDirectionsV2();
400 return;
401 }
402 info() << "CartesianMesh: computeDirections()";
403
404 m_mesh_timestamp = mesh()->timestamp();
405 _checkAddObservableMeshChanged();
406
407 m_is_amr = m_mesh->isAmrActivated();
408
409 VariableCellReal3 cells_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshCellCenter"));
410 VariableFaceReal3 faces_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshFaceCenter"));
411
412 // Calculates the coordinates of the cell centers.
413 VariableNodeReal3& nodes_coord = m_mesh->nodesCoordinates();
414 ENUMERATE_CELL (icell, m_mesh->allCells()) {
415 Cell cell = *icell;
416 Real3 center;
417 for (NodeLocalId inode : cell.nodeIds())
418 center += nodes_coord[inode];
419 center /= cell.nbNode();
420 cells_center[icell] = center;
421 }
422 ENUMERATE_FACE (iface, m_mesh->allFaces()) {
423 Face face = *iface;
424 Real3 center;
425 for (NodeLocalId inode : face.nodeIds())
426 center += nodes_coord[inode];
427 center /= face.nbNode();
428 faces_center[iface] = center;
429 }
430
431 IItemFamily* cell_family = m_mesh->cellFamily();
432 IItemFamily* node_family = m_mesh->nodeFamily();
433 Int32 next_face_x = -1;
434 Int32 next_face_y = -1;
435 Int32 next_face_z = -1;
436
437 CellVectorView cell_view = cell_family->allItems().view();
438 Cell cell0 = cell_view[0];
439 Integer nb_face = cell0.nbFace();
440 Integer nb_node = cell0.nbNode();
441 Real3 cell_center = cells_center[cell0];
442
443 info(4) << "sizeof(CellDirectionMng)=" << sizeof(CellDirectionMng)
444 << " sizeof(FaceDirectionMng)=" << sizeof(FaceDirectionMng)
445 << " sizeof(NodelDirectionMng)=" << sizeof(NodeDirectionMng);
446 info(4) << "sizeof(IndexedItemConnectivityViewBase)=" << sizeof(IndexedItemConnectivityViewBase)
447 << " sizeof(CellInfoListView)=" << sizeof(CellInfoListView);
448 info(4) << "Cartesian mesh compute directions is_amr=" << m_is_amr;
449
450 for (Integer i = 0; i < nb_node; ++i) {
451 Node node = cell0.node(i);
452 info(4) << "Node I=" << i << " node=" << ItemPrinter(node) << " pos=" << nodes_coord[node];
453 }
454
455 bool is_3d = m_mesh->dimension() == 3;
456
457 // We assume that all cells have the same numbering direction in the mesh.
458 // For example, for all cells, face index 0 is the top one, face
459 // index 1 is the right one.
460 if (is_3d) {
461 Real max_x = -1;
462 Real max_y = -1;
463 Real max_z = -1;
464
465 for (Integer i = 0; i < nb_face; ++i) {
466 Face f = cell0.face(i);
467
468 Real3 next_center = faces_center[f];
469
470 Real diff_x = next_center.x - cell_center.x;
471 Real diff_y = next_center.y - cell_center.y;
472 Real diff_z = next_center.z - cell_center.z;
473
474 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real3(diff_x, diff_y, diff_z);
475
476 if (diff_x > max_x) {
477 max_x = diff_x;
478 next_face_x = i;
479 }
480
481 if (diff_y > max_y) {
482 max_y = diff_y;
483 next_face_y = i;
484 }
485
486 if (diff_z > max_z) {
487 max_z = diff_z;
488 next_face_z = i;
489 }
490 }
491 info(4) << "Advance in direction X -> " << next_face_x;
492 info(4) << "Advance in direction Y -> " << next_face_y;
493 info(4) << "Advance in direction Z -> " << next_face_z;
494 }
495 else {
496 Real max_x = -1;
497 Real max_y = -1;
498
499 for (Integer i = 0; i < nb_face; ++i) {
500 Face f = cell0.face(i);
501
502 Real3 next_center = faces_center[f];
503
504 Real diff_x = next_center.x - cell_center.x;
505 Real diff_y = next_center.y - cell_center.y;
506
507 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real2(diff_x, diff_y);
508
509 if (diff_x > max_x) {
510 max_x = diff_x;
511 next_face_x = i;
512 }
513
514 if (diff_y > max_y) {
515 max_y = diff_y;
516 next_face_y = i;
517 }
518 }
519 info(4) << "Advance in direction X -> " << next_face_x;
520 info(4) << "Advance in direction Y -> " << next_face_y;
521 }
522 m_all_items_direction_info->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
523
524 info() << "Informations from IMesh properties:";
525
526 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
527
528 info() << "GlobalNbCell = " << cmgi->globalNbCells();
529 info() << "OwnNbCell: " << cmgi->ownNbCells();
530 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
531 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
532
533 CellGroup all_cells = cell_family->allItems();
534 NodeGroup all_nodes = node_family->allItems();
535 if (m_is_amr) {
536 auto x = _buildPatchGroups(mesh()->allLevelCells(0), 0);
537 all_cells = std::get<0>(x);
538 all_nodes = std::get<1>(x);
539 }
540
541 if (next_face_x != (-1)) {
542 m_local_face_direction[MD_DirX] = next_face_x;
543 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirX, cells_center, faces_center, all_cells, all_nodes);
544 }
545 if (next_face_y != (-1)) {
546 m_local_face_direction[MD_DirY] = next_face_y;
547 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirY, cells_center, faces_center, all_cells, all_nodes);
548 }
549 if (next_face_z != (-1)) {
550 m_local_face_direction[MD_DirZ] = next_face_z;
551 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirZ, cells_center, faces_center, all_cells, all_nodes);
552 }
553
554 // Position the information by direction
555 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
556 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
557 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
558 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
559 }
560
561 info() << "Compute cartesian connectivity";
562
563 m_permutation_storage.resize(1);
564 m_permutation_storage[0].compute();
565 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
566 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
567 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
568 m_connectivity._computeInfos(mesh(), nodes_coord, cells_center);
569
570 // Adds connectivity information for AMR patches
571 // TODO: support multiple calls to this method?
572 for (Integer patch_index = 1; patch_index < m_patch_group.nbPatch(); ++patch_index) {
573 CellGroup cells = m_patch_group.allCells(patch_index);
574 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
575 info() << "AMR Patch name=" << cells.name() << " size=" << cells.size() << " index=" << patch_index << " nbPatch=" << m_patch_group.nbPatch();
576 patch->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
577 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index);
578 _computeMeshDirection(*patch.get(), MD_DirX, cells_center, faces_center, patch_cells, patch_nodes);
579 _computeMeshDirection(*patch.get(), MD_DirY, cells_center, faces_center, patch_cells, patch_nodes);
580 if (is_3d)
581 _computeMeshDirection(*patch.get(), MD_DirZ, cells_center, faces_center, patch_cells, patch_nodes);
582 }
583
584 if (arcaneIsCheck())
585 checkValid();
586
587 _saveInfosInProperties();
588}
589
590/*---------------------------------------------------------------------------*/
591/*---------------------------------------------------------------------------*/
592
593std::tuple<CellGroup, NodeGroup> CartesianMeshImpl::
594_buildPatchGroups(const CellGroup& cells, Integer patch_level)
595{
596 // We create a group for each patch ensuring that the traversal order
597 // is that of the entities' uniqueId()
598 // TODO: eventually, the traversal order should be the same as
599 // that of the Cartesian mesh. To do this, either the uniqueId()
600 // of the created cells/nodes are in the same order as the Cartesian mesh,
601 // or that the sorting function is specific to this type of mesh.
602 NodeGroup nodes = cells.nodeGroup();
603 IItemFamily* cell_family = cells.itemFamily();
604 IItemFamily* node_family = nodes.itemFamily();
605
606 String cell_group_name = String("AMRPatchCells") + patch_level;
607 CellGroup patch_cells = cell_family->createGroup(cell_group_name, Int32ConstArrayView(), true);
608 // Sets the same cells as \a cells but forces the sort
609 patch_cells.setItems(cells.view().localIds(), true);
610
611 String node_group_name = String("AMRPatchNodes") + patch_level;
612 NodeGroup patch_nodes = node_family->createGroup(node_group_name, Int32ConstArrayView(), true);
613 // Sets the same nodes as \a nodes but forces the sort
614 patch_nodes.setItems(nodes.view().localIds(), true);
615 info(4) << "PATCH_CELLS name=" << patch_cells.name() << " size=" << patch_cells.size();
616 info(4) << "PATCH_NODES name=" << patch_nodes.name() << " size=" << patch_nodes.size();
617 return { patch_cells, patch_nodes };
618}
619
620/*---------------------------------------------------------------------------*/
621/*---------------------------------------------------------------------------*/
622
623void CartesianMeshImpl::
624_computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir, VariableCellReal3& cells_center,
625 VariableFaceReal3& faces_center, CellGroup all_cells, NodeGroup all_nodes)
626{
627 IItemFamily* cell_family = m_mesh->cellFamily();
628 IItemFamily* face_family = m_mesh->faceFamily();
629 IItemFamily* node_family = m_mesh->nodeFamily();
630
631 Int32 max_cell_id = cell_family->maxLocalId();
632 Int32 max_face_id = face_family->maxLocalId();
633 Int32 max_node_id = node_family->maxLocalId();
634
635 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
636 cell_dm._internalResizeInfos(max_cell_id);
637
638 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
639 face_dm._internalResizeInfos(max_face_id);
640
641 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
642 node_dm._internalResizeInfos(max_node_id);
643
644 //TODO: remember to update after mesh change.
645 info(4) << "COMPUTE DIRECTION dir=" << dir;
646
647 Int32 prev_local_face = -1;
648 Int32 next_local_face = m_local_face_direction[dir];
649 Integer mesh_dim = m_mesh->dimension();
650 // Calculate the local number of the face opposite the next face.
651 if (mesh_dim == 2)
652 prev_local_face = (next_local_face + 2) % 4;
653 else if (mesh_dim == 3)
654 prev_local_face = (next_local_face + 3) % 6;
655
656 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
657
658 // Position the faces before and after for each cell in the direction.
659 // We ensure that these entities are in the group of entities for the corresponding direction
660 std::set<Int32> cells_set;
661 ENUMERATE_CELL (icell, all_cells) {
662 cells_set.insert(icell.itemLocalId());
663 }
664
665 // Calculate the front/back cells. In the case of an AMR patch, these two cells
666 // must be of the same level
667 ENUMERATE_CELL (icell, all_cells) {
668 Cell cell = *icell;
669 Int32 my_level = cell.level();
670 Face next_face = cell.face(next_local_face);
671 Cell next_cell = next_face.backCell() == cell ? next_face.frontCell() : next_face.backCell();
672 if (cells_set.find(next_cell.localId()) == cells_set.end())
673 next_cell = Cell();
674 else if (next_cell.level() != my_level)
675 next_cell = Cell();
676
677 Face prev_face = cell.face(prev_local_face);
678 Cell prev_cell = prev_face.backCell() == cell ? prev_face.frontCell() : prev_face.backCell();
679 if (cells_set.find(prev_cell.localId()) == cells_set.end())
680 prev_cell = Cell();
681 else if (prev_cell.level() != my_level)
682 prev_cell = Cell();
683 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
684 }
685 cell_dm._internalComputeInnerAndOuterItems(all_cells);
686 face_dm._internalComputeInfos(cell_dm, cells_center, faces_center);
687 node_dm._internalComputeInfos(cell_dm, all_nodes, cells_center);
688}
689
690/*---------------------------------------------------------------------------*/
691/*---------------------------------------------------------------------------*/
692
693void CartesianMeshImpl::
694_computeDirectionsV2()
695{
696 info() << "CartesianMesh: computeDirectionsV2()";
697
698 m_mesh_timestamp = mesh()->timestamp();
699 _checkAddObservableMeshChanged();
700
701 m_is_amr = m_mesh->isAmrActivated();
702
703 if (m_mesh->dimension() == 3) {
704 m_local_face_direction[MD_DirX] = 4;
705 m_local_face_direction[MD_DirY] = 5;
706 m_local_face_direction[MD_DirZ] = 3;
707 }
708 else {
709 m_local_face_direction[MD_DirX] = 1;
710 m_local_face_direction[MD_DirY] = 2;
711 }
712
713 info() << "Compute cartesian connectivity";
714
715 m_permutation_storage.resize(1);
716 m_permutation_storage[0].compute();
717 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
718 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
719 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
720 m_connectivity._computeInfos(this);
721
722 // Adds connectivity information for AMR patches
723 for (Integer patch_index = 0; patch_index < m_patch_group.nbPatch(); ++patch_index) {
724 computeDirectionsPatchV2(patch_index);
725 }
726
727 if (arcaneIsCheck())
728 checkValid();
729
730 _saveInfosInProperties();
731}
732
733/*---------------------------------------------------------------------------*/
734/*---------------------------------------------------------------------------*/
735
736void CartesianMeshImpl::
737computeDirectionsPatchV2(Integer patch_index)
738{
739 bool is_3d = m_mesh->dimension() == 3;
740
741 CellGroup cells = m_patch_group.allCells(patch_index);
742 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
743
744 if (patch->index() == -1) {
745 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
746 info() << "Informations from IMesh properties:";
747 info() << "GlobalNbCell = " << cmgi->globalNbCells();
748 info() << "OwnNbCell: " << cmgi->ownNbCells();
749 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
750 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
751 // Position the information by direction
752 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
753 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
754 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
755 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
756 }
757 }
758
759 info() << "AMR Patch name=" << cells.name() << " size=" << cells.size() << " index=" << patch_index << " trueindex=" << patch->index() << " nbPatch=" << m_patch_group.nbPatch();
760 {
761 const AMRPatchPosition position = patch->position();
762 info() << " position min=" << position.minPoint() << " max=" << position.maxPoint() << " level=" << position.level() << " overlapLayerSize=" << position.overlapLayerSize();
763 }
764 patch->_internalComputeNodeCellInformations();
765 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index); // TODO To delete
766 _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);
767 _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);
768 if (is_3d)
769 _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);
770}
771
772/*---------------------------------------------------------------------------*/
773/*---------------------------------------------------------------------------*/
774
775void CartesianMeshImpl::
776_computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir, CellGroup all_cells, CellGroup in_patch_cells, CellGroup overlap_cells, NodeGroup all_nodes)
777{
778 IItemFamily* cell_family = m_mesh->cellFamily();
779 IItemFamily* face_family = m_mesh->faceFamily();
780 IItemFamily* node_family = m_mesh->nodeFamily();
781
782 Int32 max_cell_id = cell_family->maxLocalId();
783 Int32 max_face_id = face_family->maxLocalId();
784 Int32 max_node_id = node_family->maxLocalId();
785
786 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
787 cell_dm._internalResizeInfos(max_cell_id);
788
789 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
790 face_dm._internalResizeInfos(max_face_id);
791
792 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
793 node_dm._internalResizeInfos(max_node_id);
794
795 //TODO: remember to update after mesh change.
796 info(4) << "COMPUTE DIRECTION dir=" << dir;
797
798 Int32 prev_local_face = -1;
799 Int32 next_local_face = m_local_face_direction[dir];
800 Integer mesh_dim = m_mesh->dimension();
801 // Calculate the local number of the face opposite the next face.
802 if (mesh_dim == 2)
803 prev_local_face = (next_local_face + 2) % 4;
804 else if (mesh_dim == 3)
805 prev_local_face = (next_local_face + 3) % 6;
806
807 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
808
809 // Position the faces before and after for each cell in the direction.
810 // We ensure that these entities are in the group of entities for the corresponding direction
811 std::set<Int32> cells_set;
812 ENUMERATE_ (Cell, icell, all_cells) {
813 cells_set.insert(icell.itemLocalId());
814 }
815
816 // Calculate the front/back cells. In the case of an AMR patch, these two cells
817 // must be of the same level
818 ENUMERATE_ (Cell, icell, all_cells) {
819 Cell cell = *icell;
820 Int32 my_level = cell.level();
821 Face next_face = cell.face(next_local_face);
822 Cell next_cell = next_face.backCell() == cell ? next_face.frontCell() : next_face.backCell();
823 if (!cells_set.contains(next_cell.localId()) || next_cell.level() != my_level) {
824 next_cell = Cell();
825 }
826
827 Face prev_face = cell.face(prev_local_face);
828 Cell prev_cell = prev_face.backCell() == cell ? prev_face.frontCell() : prev_face.backCell();
829 if (!cells_set.contains(prev_cell.localId()) || prev_cell.level() != my_level) {
830 prev_cell = Cell();
831 }
832
833 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
834 }
835 cell_dm._internalComputeCellGroups(all_cells, in_patch_cells, overlap_cells);
836 face_dm._internalComputeInfos(cell_dm);
837 node_dm._internalComputeInfos(cell_dm, all_nodes);
838}
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
842
844refinePatch2D(Real2 position, Real2 length)
845{
846 info() << "REFINEMENT 2D position=" << position << " length=" << length;
847 refinePatch({ position, length });
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
854refinePatch3D(Real3 position, Real3 length)
855{
856 info() << "REFINEMENT 3D position=" << position << " length=" << length;
857 refinePatch({ position, length });
858}
859
860/*---------------------------------------------------------------------------*/
861/*---------------------------------------------------------------------------*/
862
864refinePatch(const AMRZonePosition& position)
865{
866 _applyRefine(position);
867 _saveInfosInProperties();
868}
869
870/*---------------------------------------------------------------------------*/
871/*---------------------------------------------------------------------------*/
872
874coarseZone2D(Real2 position, Real2 length)
875{
876 info() << "COARSEN 2D position=" << position << " length=" << length;
877 coarseZone({ position, length });
878}
879
880/*---------------------------------------------------------------------------*/
881/*---------------------------------------------------------------------------*/
882
884coarseZone3D(Real3 position, Real3 length)
885{
886 info() << "COARSEN 3D position=" << position << " length=" << length;
887 coarseZone({ position, length });
888}
889
890/*---------------------------------------------------------------------------*/
891/*---------------------------------------------------------------------------*/
892
894coarseZone(const AMRZonePosition& position)
895{
896 _applyCoarse(position);
897 _saveInfosInProperties();
898}
899
900/*---------------------------------------------------------------------------*/
901/*---------------------------------------------------------------------------*/
902
904reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers)
905{
906 if (level < 1) {
907 ARCANE_FATAL("You cannot reduce number of ghost layer of level 0 with this method");
908 }
909
910 // Maximum number of ghost cell layers. Meh; needs modification.
911 const Int32 max_nb_layer = 128;
912 Int32 level_max = 0;
913
914 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
915 level_max = std::max(level_max, icell->level());
916 }
917
918 level_max = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, level_max);
919 //debug() << "Level max : " << level_max;
920
922
923 Integer level_0_nb_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer();
924 //debug() << "NbGhostLayers level 0 : " << level_0_nb_ghost_layer;
925
926 if (level_0_nb_ghost_layer == 0) {
927 return 0;
928 }
929
930 Integer nb_ghost_layer = Convert::toInt32(level_0_nb_ghost_layer * pow(2, level));
931
932 //debug() << "NbGhostLayers level " << level << " : " << nb_ghost_layer;
933
934 // We assume there are always 2*2 child cells (2*2*2 in 3D).
935 if (target_nb_ghost_layers % 2 != 0) {
936 target_nb_ghost_layers++;
937 }
938
939 if (target_nb_ghost_layers == nb_ghost_layer) {
940 return nb_ghost_layer;
941 }
942
943 //debug() << "TargetNbGhostLayers level " << level << " : " << target_nb_ghost_layers;
944
945 Integer parent_level = level - 1;
946 Integer parent_target_nb_ghost_layer = target_nb_ghost_layers / 2;
947
948 // TODO AH: We are forced to derefine level by level. Needs changing.
949 UniqueArray<UniqueArray<Int32>> cell_lid2(level_max);
950
951 //UniqueArray<Int32> cell_lid;
952 std::function<void(Cell)> children_list;
953
954 children_list = [&cell_lid2, &children_list](Cell cell) -> void {
955 for (Integer i = 0; i < cell.nbHChildren(); ++i) {
956 //debug() << "child of lid=" << cell.localId() << " : lid=" << cell.hChild(i).localId() << " -- level : " << cell.level();
957 cell_lid2[cell.level()].add(cell.hChild(i).localId());
958 children_list(cell.hChild(i));
959 }
960 };
961
962 // Algorithm for numbering ghost cell layers.
963 {
964 VariableNodeInt32 level_node{ VariableBuildInfo{ m_mesh, "LevelNode" } };
965 level_node.fill(-1);
966
967 VariableCellInt32 level_cell{ VariableBuildInfo{ m_mesh, "LevelCell" } };
968 level_cell.fill(-1);
969
970 ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
971 Cell front_cell = iface->frontCell();
972 Cell back_cell = iface->backCell();
973 if (
974 ((front_cell.null() || (!front_cell.isOwn() && front_cell.level() == parent_level)) && ((!back_cell.null()) && (back_cell.isOwn() && back_cell.level() == parent_level))) ||
975 ((back_cell.null() || (!back_cell.isOwn() && back_cell.level() == parent_level)) && ((!front_cell.null()) && (front_cell.isOwn() && front_cell.level() == parent_level)))) {
976 for (Node node : iface->nodes()) {
977 level_node[node] = 0;
978 //debug() << "Node layer 0 : " << node.uniqueId();
979 }
980 }
981 }
982
983 bool is_modif = true;
984 Int32 current_layer = 0;
985 while (is_modif) {
986 is_modif = false;
987
988 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
989 if (icell->isOwn() || icell->level() != parent_level || level_cell[icell] != -1) {
990 continue;
991 }
992
993 Int32 min = max_nb_layer;
994 Int32 max = -1;
995
996 for (Node node : icell->nodes()) {
997 Int32 nlevel = level_node[node];
998 if (nlevel != -1) {
999 min = std::min(min, nlevel);
1000 max = std::max(max, nlevel);
1001 }
1002 }
1003
1004 // We do layer by layer (see how to remove this limitation).
1005 if (min != current_layer) {
1006 continue;
1007 }
1008
1009 // Cell without nodes already processed.
1010 if (min == max_nb_layer && max == -1) {
1011 continue;
1012 }
1013
1014 Integer new_level = ((min == max) ? min + 1 : max);
1015
1016 for (Node node : icell->nodes()) {
1017 Int32 nlevel = level_node[node];
1018 if (nlevel == -1) {
1019 level_node[node] = new_level;
1020 //debug() << "Node layer " << new_level << " : " << node.uniqueId();
1021 is_modif = true;
1022 }
1023 }
1024
1025 level_cell[icell] = min;
1026
1027 //debug() << "Cell uid : " << icell->uniqueId()
1028 // << " -- Layer : " << min;
1029
1030 if (min >= parent_target_nb_ghost_layer) {
1031 children_list(*icell);
1032 }
1033 }
1034 current_layer++;
1035 if (current_layer >= max_nb_layer) {
1036 ARCANE_FATAL("Error in ghost layer counter algo. Report it plz.");
1037 }
1038 }
1039 }
1040
1041 for (Integer i = level_max - 1; i >= 0; --i) {
1042 // A communication to avoid many others.
1043 if (m_mesh->parallelMng()->reduce(Parallel::ReduceMax, cell_lid2[i].size()) == 0) {
1044 continue;
1045 }
1046 //debug() << "Removing children of ghost cell (parent level=" << i << ") (children localIds) : " << cell_lid2[i];
1047
1048 m_mesh->modifier()->flagCellToCoarsen(cell_lid2[i]);
1049 m_mesh->modifier()->coarsenItemsV2(false);
1050 }
1051
1052 info() << "Nb ghost layer for level " << level << " : " << target_nb_ghost_layers;
1053
1054 return target_nb_ghost_layers;
1055}
1056
1057/*---------------------------------------------------------------------------*/
1058/*---------------------------------------------------------------------------*/
1059
1060void CartesianMeshImpl::
1061_addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id)
1062{
1063 _addPatch(parent_cells_local_id);
1064}
1065
1066/*---------------------------------------------------------------------------*/
1067/*---------------------------------------------------------------------------*/
1068/*!
1069 * \brief Creates a patch with all children of the group \a parent_cells.
1070 */
1071void CartesianMeshImpl::
1072_addPatch(ConstArrayView<Int32> parent_cells)
1073{
1074 // Create the group containing the AMR cells
1075 // These are the child cells of \a parent_cells
1076
1077 UniqueArray<Int32> children_local_id;
1078 CellInfoListView cells(m_mesh->cellFamily());
1079 for (Int32 cell_local_id : parent_cells) {
1080 Cell c = cells[cell_local_id];
1081 for (Integer k = 0; k < c.nbHChildren(); ++k) {
1082 Cell child = c.hChild(k);
1083 children_local_id.add(child.localId());
1084 }
1085 }
1086
1087 m_patch_group.addPatch(children_local_id);
1088}
1089
1090/*---------------------------------------------------------------------------*/
1091/*---------------------------------------------------------------------------*/
1092
1093void CartesianMeshImpl::
1094_applyRefine(const AMRZonePosition& position)
1095{
1096 if (m_amr_type == eMeshAMRKind::Cell) {
1097 UniqueArray<Int32> cells_local_id;
1098 position.cellsInPatch(mesh(), cells_local_id);
1099
1100 Integer nb_cell = cells_local_id.size();
1101 info(4) << "Local_NbCellToRefine = " << nb_cell;
1102
1103 IParallelMng* pm = m_mesh->parallelMng();
1104 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1105 info(4) << "Global_NbCellToRefine = " << total_nb_cell;
1106 if (total_nb_cell == 0)
1107 return;
1108
1109 debug() << "Refine with modifier() (for all mesh types)";
1110 m_mesh->modifier()->flagCellToRefine(cells_local_id);
1111 m_mesh->modifier()->adapt();
1112
1113 _addPatch(cells_local_id);
1114 }
1115
1116 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1117 debug() << "Refine with specific refiner (for cartesian mesh only)";
1118 m_patch_group.addPatch(position);
1119 }
1120
1121 else if (m_amr_type == eMeshAMRKind::Patch) {
1122 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1123 }
1124 else {
1125 ARCANE_FATAL("AMR is not enabled");
1126 }
1127
1128 {
1129 MeshStats ms(traceMng(), m_mesh, m_mesh->parallelMng());
1130 ms.dumpStats();
1131 }
1132}
1133
1134/*---------------------------------------------------------------------------*/
1135/*---------------------------------------------------------------------------*/
1136
1137void CartesianMeshImpl::
1138_applyCoarse(const AMRZonePosition& zone_position)
1139{
1140 if (m_amr_type == eMeshAMRKind::Cell) {
1141 UniqueArray<Int32> cells_local_id;
1142
1143 zone_position.cellsInPatch(mesh(), cells_local_id);
1144
1145 Integer nb_cell = cells_local_id.size();
1146 info(4) << "Local_NbCellToCoarsen = " << nb_cell;
1147
1148 IParallelMng* pm = m_mesh->parallelMng();
1149 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1150 info(4) << "Global_NbCellToCoarsen = " << total_nb_cell;
1151 if (total_nb_cell == 0)
1152 return;
1153
1154 debug() << "Coarse with modifier() (for all mesh types)";
1155 m_patch_group.removeCellsInAllPatches(cells_local_id);
1156
1157 m_mesh->modifier()->flagCellToCoarsen(cells_local_id);
1158 m_mesh->modifier()->coarsenItemsV2(true);
1159 }
1160
1161 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1162 debug() << "Coarsen with specific coarser (for cartesian mesh only)";
1163 m_patch_group.removeCellsInZone(zone_position);
1164 }
1165
1166 else if (m_amr_type == eMeshAMRKind::Patch) {
1167 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1168 }
1169 else {
1170 ARCANE_FATAL("AMR is not enabled");
1171 }
1172
1173 {
1174 MeshStats ms(traceMng(), m_mesh, m_mesh->parallelMng());
1175 ms.dumpStats();
1176 }
1177}
1178
1179/*---------------------------------------------------------------------------*/
1180/*---------------------------------------------------------------------------*/
1181
1183checkValid() const
1184{
1185 info(4) << "Check valid CartesianMesh";
1186 Integer nb_patch = nbPatch();
1187 for (Integer i = 0; i < nb_patch; ++i) {
1188 ICartesianMeshPatch* p = patch(i);
1189 p->checkValid();
1190 }
1191}
1192
1193/*---------------------------------------------------------------------------*/
1194/*---------------------------------------------------------------------------*/
1195
1198{
1199 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
1200
1201 // First check if faces are renumbered
1202 Int32 face_method = v.renumberFaceMethod();
1203 if (face_method != 0 && face_method != 1)
1204 ARCANE_FATAL("Invalid value '{0}' for renumberFaceMethod(). Valid values are 0 or 1",
1205 face_method);
1206 if (face_method == 1)
1207 ARCANE_THROW(NotImplementedException, "Method 1 for face renumbering");
1208
1209 // Then check the patches if requested.
1210 Int32 patch_method = v.renumberPatchMethod();
1211 if (patch_method < 0 || patch_method > 4) {
1212 ARCANE_FATAL("Invalid value '{0}' for renumberPatchMethod(). Valid values are 0, 1, 2, 3 or 4",
1213 patch_method);
1214 }
1215 if (patch_method != 0 && m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1216 ARCANE_FATAL("Mesh items renumbering is not compatible with this type of AMR");
1217 }
1218
1219 if (patch_method == 1 || patch_method == 3 || patch_method == 4) {
1220 CartesianMeshUniqueIdRenumbering renumberer(this, cmgi, v.parentPatch(), patch_method);
1221 renumberer.renumber();
1222 }
1223 else if (patch_method == 2) {
1224 warning() << "The patch method 2 is experimental!";
1225 CartesianMeshUniqueIdRenumberingV2 renumberer(this, cmgi);
1226 renumberer.renumber();
1227 }
1228
1229 // Finally, an optional sort.
1230 if (v.isSortAfterRenumbering()) {
1231 info() << "Compacting and Sorting after renumbering";
1232 m_mesh->nodeFamily()->compactItems(true);
1233 m_mesh->faceFamily()->compactItems(true);
1234 m_mesh->cellFamily()->compactItems(true);
1236 }
1237}
1238
1239/*---------------------------------------------------------------------------*/
1240/*---------------------------------------------------------------------------*/
1241
1247
1248/*---------------------------------------------------------------------------*/
1249/*---------------------------------------------------------------------------*/
1250
1251Ref<CartesianMeshCoarsening2> CartesianMeshImpl::
1252_createCartesianMeshCoarsening2()
1253{
1254 return makeRef(new CartesianMeshCoarsening2(this));
1255}
1256
1257/*---------------------------------------------------------------------------*/
1258/*---------------------------------------------------------------------------*/
1259
1260/*---------------------------------------------------------------------------*/
1261/*---------------------------------------------------------------------------*/
1262
1264getReference(const MeshHandleOrMesh& mesh_handle_or_mesh, bool create)
1265{
1266 MeshHandle h = mesh_handle_or_mesh.handle();
1267 //TODO: implement lock for multi-thread
1268 const char* name = "CartesianMesh";
1269 IUserDataList* udlist = h.meshUserDataList();
1270
1271 IUserData* ud = udlist->data(name, true);
1272 if (!ud) {
1273 if (!create)
1274 return nullptr;
1275 IMesh* mesh = h.meshOrNull();
1276 if (!mesh)
1277 ARCANE_FATAL("The mesh {0} is not yet created", h.meshName());
1278 ICartesianMesh* cm = arcaneCreateCartesianMesh(mesh);
1279 udlist->setData(name, new AutoDestroyUserData<ICartesianMesh>(cm));
1280
1281 // Indicates that the mesh is Cartesian
1282 MeshKind mk = mesh->meshKind();
1283 mk.setMeshStructure(eMeshStructure::Cartesian);
1284 mesh->_internalApi()->setMeshKind(mk);
1285
1286 return cm;
1287 }
1289 if (!adud)
1290 ARCANE_FATAL("Can not cast to ICartesianMesh*");
1291 return adud->data();
1292}
1293
1294/*---------------------------------------------------------------------------*/
1295/*---------------------------------------------------------------------------*/
1296
1297} // End namespace Arcane
1298
1299/*---------------------------------------------------------------------------*/
1300/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
File containing event management mechanisms.
Class allowing the definition of a mesh zone.
Integer size() const
Number of elements in the vector.
void add(ConstReferenceType val)
Adds element val to the end of the array.
UserData that self-destructs once detached.
Connectivity information of a Cartesian mesh.
Coarsens a Cartesian mesh by 2.
Coarsens a Cartesian mesh by 2.
Specific information for a Cartesian mesh.
void refinePatch3D(Real3 position, Real3 length) override
Refines a block of the Cartesian mesh in 3D.
Int32 nbPatch() const override
Number of patches in the mesh.
Integer reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers) override
Method for deleting one or more layers of ghost cells at a defined refinement level.
void refinePatch(const AMRZonePosition &position) override
Refines a block of the Cartesian mesh.
ITraceMng * traceMng() const override
Associated trace manager.
CellDirectionMng cellDirection(Integer idir) override
List of cells in direction dir (0, 1 or 2).
void recreateFromDump() override
Recalculates Cartesian information after a restart.
void computeDirections() override
Calculates information for directional access.
FaceDirectionMng faceDirection(Integer idir) override
List of faces in direction dir (0, 1 or 2).
void coarseZone(const AMRZonePosition &position) override
Coarsens a block of the Cartesian mesh.
NodeDirectionMng nodeDirection(Integer idir) override
List of nodes in direction dir (0, 1 or 2).
void checkValid() const override
Performs checks on the validity of the instance.
IMesh * mesh() const override
Mesh associated with this Cartesian mesh.
FaceDirectionMng faceDirection(eMeshDirection dir) override
List of faces in direction dir.
NodeDirectionMng nodeDirection(eMeshDirection dir) override
List of nodes in direction dir.
void refinePatch2D(Real2 position, Real2 length) override
Refines a block of the Cartesian mesh in 2D.
ICartesianMeshPatch * patch(Int32 index) const override
Returns the index-th patch of the mesh.
void coarseZone2D(Real2 position, Real2 length) override
Coarsens a block of the Cartesian mesh in 2D.
void renumberItemsUniqueId(const CartesianMeshRenumberingInfo &v) override
Renumbers the uniqueId() of entities.
ICartesianMeshInternal * _internalApi() override
Internal API for Arcane.
void coarseZone3D(Real3 position, Real3 length) override
Coarsens a block of the Cartesian mesh in 3D.
Ref< CartesianMeshCoarsening > createCartesianMeshCoarsening() override
Creates an instance to manage mesh coarsening.
CartesianPatch amrPatch(Int32 index) const override
Returns the index-th patch of the mesh.
CellDirectionMng cellDirection(eMeshDirection dir) override
List of cells in direction dir.
CartesianMeshPatchListView patches() const override
View of the list of patches.
CartesianConnectivity connectivity() override
Connectivity information.
AMR Patch of a Cartesian mesh.
Info about the cells in a specific X, Y, or Z direction of a structured mesh.
View of cell information.
Cell of a mesh.
Definition Item.h:1300
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Int32 nbFace() const
Number of faces of the cell.
Definition Item.h:1397
Int32 level() const
Definition Item.h:1473
Constant view of an array of type T.
Info on the faces of a specific direction X, Y, or Z of a structured mesh.
Face of a cell.
Definition Item.h:1032
Interface of an AMR patch of a Cartesian mesh.
virtual void checkValid() const =0
Performs checks on the validity of the instance.
static ICartesianMesh * getReference(const MeshHandleOrMesh &mesh, bool create=true)
Retrieves or creates the reference associated with mesh.
virtual IMesh * mesh() const =0
Mesh associated with this Cartesian mesh.
Interface of an entity family.
Definition IItemFamily.h:83
virtual ItemGroup allItems() const =0
Group of all entities.
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Creates an entity group named name containing the entities local_ids.
virtual Int32 maxLocalId() const =0
virtual IItemFamily * cellFamily()=0
Returns the cell family.
virtual Int64 timestamp()=0
Counter indicating the time of the last mesh modification.
virtual EventObservable< const MeshEventArgs & > & eventObservable(eMeshEventType type)=0
Observable for an event.
Interface of a list that manages user data.
virtual void setData(const String &name, IUserData *ud)=0
Sets the user data associated with the name name.
virtual IUserData * data(const String &name, bool allow_null=false) const =0
Data associated with name.
Interface for user data attached to another object.
Definition IUserData.h:33
Base class for a view on unstructured connectivity.
NodeGroup nodeGroup() const
Group of nodes of the elements of this group.
Definition ItemGroup.cc:222
const String & name() const
Group name.
Definition ItemGroup.h:81
ItemVectorView view() const
View of the group entities.
Definition ItemGroup.cc:580
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
IItemFamily * itemFamily() const
Entity family to which this group belongs (0 for the null group).
Definition ItemGroup.h:128
void setItems(Int32ConstArrayView items_local_id)
Sets the entities of the group.
Definition ItemGroup.cc:484
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
Int32ConstArrayView localIds() const
Array of local IDs of entities.
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
NodeLocalIdView nodeIds() const
List of nodes of the entity.
Definition Item.h:846
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
Definition Item.h:230
constexpr bool isOwn() const
true if the entity belongs to the subdomain
Definition Item.h:267
Arguments for mesh events.
Definition MeshEvents.h:44
Compatibility class to hold a MeshHandle or an IMesh*.
Definition MeshHandle.h:196
const MeshHandle & handle() const
Associated handle.
Definition MeshHandle.h:219
Handle on a mesh.
Definition MeshHandle.h:48
IMesh * meshOrNull() const
Returns the mesh associated with this instance.
IUserDataList * meshUserDataList() const
Associated user data.
Definition MeshHandle.h:158
Characteristics of a mesh.
Definition MeshKind.h:113
Info about nodes in a specific direction X, Y, or Z of a structured mesh.
Node of a mesh.
Definition Item.h:598
Class managing a 2-dimensional real vector.
Definition Real2.h:122
Class managing a 3-dimensional real vector.
Definition Real3.h:132
bool isNull() const
Indicates if the counter references a non-null instance.
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
TraceMessage warning() const
Flow for a warning message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemVectorViewT< Cell > CellVectorView
View over a vector of cells.
Definition ItemTypes.h:305
ItemGroupT< Node > NodeGroup
Group of nodes.
Definition ItemTypes.h:168
MeshVariableScalarRefT< Cell, Real3 > VariableCellReal3
Coordinate type quantity at cell center.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
MeshVariableScalarRefT< Node, Int32 > VariableNodeInt32
Quantity at the node of 32-bit integer type.
MeshVariableScalarRefT< Face, Real3 > VariableFaceReal3
Coordinate type quantity at face.
MeshVariableScalarRefT< Cell, Int32 > VariableCellInt32
Quantity at the cell center of 32-bit integer type.
Int32 toInt32(Real r)
Converts a Real to Int32.
@ ReduceMax
Maximum of values.
Namespace for platform-dependent functions.
IMemoryAllocator * getDefaultDataAllocator()
Default allocator for data.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
bool arcaneIsCheck()
True if running in check mode.
Definition Misc.cc:66
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:482
@ Cartesian
Cartesian mesh.
Definition MeshKind.h:36
eMeshDirection
Direction type for a structured mesh.
@ MD_DirZ
Z Direction.
@ MD_DirY
Y Direction.
@ MD_DirX
X Direction.
@ EndPrepareDump
Event sent at the end of prepareForDump().
Definition MeshEvents.h:34
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
eMeshAMRKind
AMR mesh type.
Definition MeshKind.h:49
@ Patch
The mesh is AMR by patch.
Definition MeshKind.h:55
@ Cell
The mesh is AMR by cell.
Definition MeshKind.h:53
@ PatchCartesianMeshOnly
The mesh is AMR by Cartesian patch (rectangular).
Definition MeshKind.h:57
std::int32_t Int32
Signed integer type of 32 bits.
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35