Arcane  4.2.1.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#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#include <set>
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60/*!
61 * \defgroup ArcaneCartesianMesh Cartesian meshes.
62 *
63 * Set of classes ensuring the management of Cartesian meshes.
64 *
65 * For more information, refer to the page \ref arcanedoc_entities_cartesianmesh.
66 */
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70namespace Arcane
71{
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76/*!
77 * \brief Specific information for a Cartesian mesh.
78 */
79class CartesianMeshImpl
80: public TraceAccessor
81, public ICartesianMesh
82{
83 class InternalApi
84 : public ICartesianMeshInternal
85 {
86 public:
87
88 explicit InternalApi(CartesianMeshImpl* cartesian_mesh)
89 : m_cartesian_mesh(cartesian_mesh)
90 {
91 }
92
93 public:
94
95 Ref<CartesianMeshCoarsening2> createCartesianMeshCoarsening2() override
96 {
97 return m_cartesian_mesh->_createCartesianMeshCoarsening2();
98 }
99 void addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id) override
100 {
101 m_cartesian_mesh->_addPatchFromExistingChildren(parent_cells_local_id);
102 }
103 void initCartesianMeshAMRPatchMng() override
104 {
105 if (m_numbering_mng.isNull()) {
106 initCartesianMeshNumberingMngInternal();
107 }
108 if (m_amr_mng.isNull()) {
109 m_amr_mng = makeRef(new CartesianMeshAMRPatchMng(m_cartesian_mesh, m_numbering_mng.get()));
110 }
111 }
112 Ref<ICartesianMeshAMRPatchMng> cartesianMeshAMRPatchMng() override
113 {
114 return m_amr_mng;
115 }
116 void initCartesianMeshNumberingMngInternal() override
117 {
118 if (m_numbering_mng.isNull()) {
119 m_numbering_mng = makeRef(new CartesianMeshNumberingMngInternal(m_cartesian_mesh->mesh()));
120 }
121 }
122 Ref<ICartesianMeshNumberingMngInternal> cartesianMeshNumberingMngInternal() override
123 {
124 return m_numbering_mng;
125 }
126 CartesianPatchGroup& cartesianPatchGroup() override { return m_cartesian_mesh->_cartesianPatchGroup(); }
127 // TODO : Ugly.
128 void saveInfosInProperties() override { m_cartesian_mesh->_saveInfosInProperties(); }
129
130 private:
131
132 CartesianMeshImpl* m_cartesian_mesh = nullptr;
135 };
136
137 public:
138
139 explicit CartesianMeshImpl(IMesh* mesh);
140
141 public:
142
143 void build() override;
144
145 //! Mesh associated with this Cartesian mesh
146 IMesh* mesh() const override { return m_mesh; }
147
148 //! Associated trace manager.
149 ITraceMng* traceMng() const override { return TraceAccessor::traceMng(); }
150
152 {
153 return m_all_items_direction_info->cellDirection(dir);
154 }
155
157 {
158 return m_all_items_direction_info->cellDirection(idir);
159 }
160
162 {
163 return m_all_items_direction_info->faceDirection(dir);
164 }
165
167 {
168 return m_all_items_direction_info->faceDirection(idir);
169 }
170
172 {
173 return m_all_items_direction_info->nodeDirection(dir);
174 }
175
177 {
178 return m_all_items_direction_info->nodeDirection(idir);
179 }
180
181 void computeDirections() override;
182
183 void recreateFromDump() override;
184
186 {
187 return m_connectivity;
188 }
189
190 Int32 nbPatch() const override { return m_patch_group.nbPatch(); }
191 ICartesianMeshPatch* patch(Int32 index) const override { return m_patch_group.patch(index).get(); }
192 CartesianPatch amrPatch(Int32 index) const override { return CartesianPatch(m_patch_group.patch(index).get()); }
193 CartesianMeshPatchListView patches() const override { return m_patch_group.patchListView(); }
194
195 void refinePatch2D(Real2 position, Real2 length) override;
196 void refinePatch3D(Real3 position, Real3 length) override;
197 void refinePatch(const AMRZonePosition& position) override;
198
199 void coarseZone2D(Real2 position, Real2 length) override;
200 void coarseZone3D(Real3 position, Real3 length) override;
201 void coarseZone(const AMRZonePosition& position) override;
202
203 Integer reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers) override;
204
206
207 void checkValid() const override;
208
210
211 //! Internal API for Arcane
212 ICartesianMeshInternal* _internalApi() override { return &m_internal_api; }
213
214 void computeDirectionsPatchV2(Integer index) override;
215
216 private:
217
218 // Implementation of 'ICartesianMeshInternal'
219 Ref<CartesianMeshCoarsening2> _createCartesianMeshCoarsening2();
220 void _addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id);
221 CartesianPatchGroup& _cartesianPatchGroup() { return m_patch_group; }
222 void _computeDirectionsV2();
223
224 private:
225
226 InternalApi m_internal_api;
227 //! Index in the local numbering of the cell, of the face in
228 // the X, Y or Z direction
229 Int32 m_local_face_direction[3] = { -1, -1, -1 };
230 IMesh* m_mesh = nullptr;
231 Ref<CartesianMeshPatch> m_all_items_direction_info;
232 CartesianConnectivity m_connectivity;
233 UniqueArray<CartesianConnectivity::Index> m_nodes_to_cell_storage;
234 UniqueArray<CartesianConnectivity::Index> m_cells_to_node_storage;
235 UniqueArray<CartesianConnectivity::Permutation> m_permutation_storage;
236 bool m_is_amr = false;
237 //! Group of cells for each AMR patch.
238 CartesianPatchGroup m_patch_group;
239 ScopedPtrT<Properties> m_properties;
240
241 EventObserverPool m_event_pool;
242 bool m_is_mesh_event_added = false;
243 Int64 m_mesh_timestamp = 0;
244 eMeshAMRKind m_amr_type;
245
246 private:
247
248 void _computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir,
249 VariableCellReal3& cells_center,
250 VariableFaceReal3& faces_center, CellGroup all_cells,
251 NodeGroup all_nodes);
252
253 void _computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir,
254 CellGroup all_cells,
255 CellGroup in_patch_cells,
256 CellGroup overlap_cells,
257 NodeGroup all_nodes);
258
259 void _applyRefine(const AMRZonePosition& position);
260 void _applyCoarse(const AMRZonePosition& zone_position);
261 void _addPatch(ConstArrayView<Int32> parent_cells);
262 void _saveInfosInProperties();
263
264 std::tuple<CellGroup, NodeGroup>
265 _buildPatchGroups(const CellGroup& cells, Integer patch_level);
266 void _checkNeedComputeDirections();
267 void _checkAddObservableMeshChanged();
268};
269
270/*---------------------------------------------------------------------------*/
271/*---------------------------------------------------------------------------*/
272
273extern "C++" ICartesianMesh*
274arcaneCreateCartesianMesh(IMesh* mesh)
275{
276 auto* cm = new CartesianMeshImpl(mesh);
277 cm->build();
278 return cm;
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284CartesianMeshImpl::
285CartesianMeshImpl(IMesh* mesh)
286: TraceAccessor(mesh->traceMng())
287, m_internal_api(this)
288, m_mesh(mesh)
289, m_nodes_to_cell_storage(platform::getDefaultDataAllocator())
290, m_cells_to_node_storage(platform::getDefaultDataAllocator())
291, m_permutation_storage(platform::getDefaultDataAllocator())
292, m_patch_group(this)
293, m_amr_type(mesh->meshKind().meshAMRKind())
294{
295 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
296 m_internal_api.initCartesianMeshNumberingMngInternal();
297 m_internal_api.initCartesianMeshAMRPatchMng();
298 }
299 m_all_items_direction_info = m_patch_group.groundPatch();
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
305void CartesianMeshImpl::
306build()
307{
308 m_properties = new Properties(*(mesh()->properties()), "CartesianMesh");
309 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
310 m_internal_api.cartesianMeshNumberingMngInternal()->build();
311 }
312 m_patch_group.build();
313}
314
315namespace
316{
317 const Int32 SERIALIZE_VERSION = 1;
318}
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
323void CartesianMeshImpl::
324_checkNeedComputeDirections()
325{
326 Int64 new_timestamp = mesh()->timestamp();
327 if (m_mesh_timestamp != new_timestamp) {
328 info() << "Mesh timestamp has changed (old=" << m_mesh_timestamp << " new=" << new_timestamp << ")";
330 }
331}
332
333/*---------------------------------------------------------------------------*/
334/*---------------------------------------------------------------------------*/
335
336void CartesianMeshImpl::
337_saveInfosInProperties()
338{
339 // Saves the version number to ensure it is OK upon restart/recovery
340 m_properties->set("Version", SERIALIZE_VERSION);
341
342 m_patch_group.saveInfosInProperties();
343
344 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
345 m_internal_api.cartesianMeshNumberingMngInternal()->saveInfosInProperties();
346 //m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
347 }
348}
349
350/*---------------------------------------------------------------------------*/
351/*---------------------------------------------------------------------------*/
352
355{
356 info() << "Creating 'CartesianMesh' infos from dump";
357
358 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
359 m_internal_api.cartesianMeshNumberingMngInternal()->recreateFromDump();
360 m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
361 }
362
363 // Saves the version number to ensure it is OK upon restart/recovery
364 Int32 v = m_properties->getInt32("Version");
365 if (v != SERIALIZE_VERSION)
366 ARCANE_FATAL("Bad serializer version: trying to read from incompatible checkpoint v={0} expected={1}",
367 v, SERIALIZE_VERSION);
368
369 m_patch_group.recreateFromDump();
370
371 m_all_items_direction_info = m_patch_group.groundPatch();
372
374}
375
376/*---------------------------------------------------------------------------*/
377/*---------------------------------------------------------------------------*/
378
379void CartesianMeshImpl::
380_checkAddObservableMeshChanged()
381{
382 if (m_is_mesh_event_added)
383 return;
384 m_is_mesh_event_added = true;
385 // To automatically call 'computeDirections()' after a call to
386 // IMesh::prepareForDump().
387 auto f1 = [&](const MeshEventArgs&) { this->_checkNeedComputeDirections(); };
388 mesh()->eventObservable(eMeshEventType::EndPrepareDump).attach(m_event_pool, f1);
389}
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393
396{
397 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
398 // TODO: See where to put the renumbering.
399 m_internal_api.cartesianMeshNumberingMngInternal()->renumberingFacesLevel0FromOriginalArcaneNumbering();
400 _computeDirectionsV2();
401 return;
402 }
403 info() << "CartesianMesh: computeDirections()";
404
405 m_mesh_timestamp = mesh()->timestamp();
406 _checkAddObservableMeshChanged();
407
408 m_is_amr = m_mesh->isAmrActivated();
409
410 VariableCellReal3 cells_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshCellCenter"));
411 VariableFaceReal3 faces_center(VariableBuildInfo(m_mesh, "TemporaryCartesianMeshFaceCenter"));
412
413 // Calculates the coordinates of the cell centers.
414 VariableNodeReal3& nodes_coord = m_mesh->nodesCoordinates();
415 ENUMERATE_CELL (icell, m_mesh->allCells()) {
416 Cell cell = *icell;
417 Real3 center;
418 for (NodeLocalId inode : cell.nodeIds())
419 center += nodes_coord[inode];
420 center /= cell.nbNode();
421 cells_center[icell] = center;
422 }
423 ENUMERATE_FACE (iface, m_mesh->allFaces()) {
424 Face face = *iface;
425 Real3 center;
426 for (NodeLocalId inode : face.nodeIds())
427 center += nodes_coord[inode];
428 center /= face.nbNode();
429 faces_center[iface] = center;
430 }
431
432 IItemFamily* cell_family = m_mesh->cellFamily();
433 IItemFamily* node_family = m_mesh->nodeFamily();
434 Int32 next_face_x = -1;
435 Int32 next_face_y = -1;
436 Int32 next_face_z = -1;
437
438 CellVectorView cell_view = cell_family->allItems().view();
439 Cell cell0 = cell_view[0];
440 Integer nb_face = cell0.nbFace();
441 Integer nb_node = cell0.nbNode();
442 Real3 cell_center = cells_center[cell0];
443
444 info(4) << "sizeof(CellDirectionMng)=" << sizeof(CellDirectionMng)
445 << " sizeof(FaceDirectionMng)=" << sizeof(FaceDirectionMng)
446 << " sizeof(NodelDirectionMng)=" << sizeof(NodeDirectionMng);
447 info(4) << "sizeof(IndexedItemConnectivityViewBase)=" << sizeof(IndexedItemConnectivityViewBase)
448 << " sizeof(CellInfoListView)=" << sizeof(CellInfoListView);
449 info(4) << "Cartesian mesh compute directions is_amr=" << m_is_amr;
450
451 for (Integer i = 0; i < nb_node; ++i) {
452 Node node = cell0.node(i);
453 info(4) << "Node I=" << i << " node=" << ItemPrinter(node) << " pos=" << nodes_coord[node];
454 }
455
456 bool is_3d = m_mesh->dimension() == 3;
457
458 // We assume that all cells have the same numbering direction in the mesh.
459 // For example, for all cells, face index 0 is the top one, face
460 // index 1 is the right one.
461 if (is_3d) {
462 Real max_x = -1;
463 Real max_y = -1;
464 Real max_z = -1;
465
466 for (Integer i = 0; i < nb_face; ++i) {
467 Face f = cell0.face(i);
468
469 Real3 next_center = faces_center[f];
470
471 Real diff_x = next_center.x - cell_center.x;
472 Real diff_y = next_center.y - cell_center.y;
473 Real diff_z = next_center.z - cell_center.z;
474
475 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real3(diff_x, diff_y, diff_z);
476
477 if (diff_x > max_x) {
478 max_x = diff_x;
479 next_face_x = i;
480 }
481
482 if (diff_y > max_y) {
483 max_y = diff_y;
484 next_face_y = i;
485 }
486
487 if (diff_z > max_z) {
488 max_z = diff_z;
489 next_face_z = i;
490 }
491 }
492 info(4) << "Advance in direction X -> " << next_face_x;
493 info(4) << "Advance in direction Y -> " << next_face_y;
494 info(4) << "Advance in direction Z -> " << next_face_z;
495 }
496 else {
497 Real max_x = -1;
498 Real max_y = -1;
499
500 for (Integer i = 0; i < nb_face; ++i) {
501 Face f = cell0.face(i);
502
503 Real3 next_center = faces_center[f];
504
505 Real diff_x = next_center.x - cell_center.x;
506 Real diff_y = next_center.y - cell_center.y;
507
508 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real2(diff_x, diff_y);
509
510 if (diff_x > max_x) {
511 max_x = diff_x;
512 next_face_x = i;
513 }
514
515 if (diff_y > max_y) {
516 max_y = diff_y;
517 next_face_y = i;
518 }
519 }
520 info(4) << "Advance in direction X -> " << next_face_x;
521 info(4) << "Advance in direction Y -> " << next_face_y;
522 }
523 m_all_items_direction_info->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
524
525 info() << "Informations from IMesh properties:";
526
527 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
528
529 info() << "GlobalNbCell = " << cmgi->globalNbCells();
530 info() << "OwnNbCell: " << cmgi->ownNbCells();
531 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
532 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
533
534 CellGroup all_cells = cell_family->allItems();
535 NodeGroup all_nodes = node_family->allItems();
536 if (m_is_amr) {
537 auto x = _buildPatchGroups(mesh()->allLevelCells(0), 0);
538 all_cells = std::get<0>(x);
539 all_nodes = std::get<1>(x);
540 }
541
542 if (next_face_x != (-1)) {
543 m_local_face_direction[MD_DirX] = next_face_x;
544 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirX, cells_center, faces_center, all_cells, all_nodes);
545 }
546 if (next_face_y != (-1)) {
547 m_local_face_direction[MD_DirY] = next_face_y;
548 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirY, cells_center, faces_center, all_cells, all_nodes);
549 }
550 if (next_face_z != (-1)) {
551 m_local_face_direction[MD_DirZ] = next_face_z;
552 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirZ, cells_center, faces_center, all_cells, all_nodes);
553 }
554
555 // Position the information by direction
556 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
557 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
558 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
559 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
560 }
561
562 info() << "Compute cartesian connectivity";
563
564 m_permutation_storage.resize(1);
565 m_permutation_storage[0].compute();
566 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
567 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
568 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
569 m_connectivity._computeInfos(mesh(), nodes_coord, cells_center);
570
571 // Adds connectivity information for AMR patches
572 // TODO: support multiple calls to this method?
573 for (Integer patch_index = 1; patch_index < m_patch_group.nbPatch(); ++patch_index) {
574 CellGroup cells = m_patch_group.allCells(patch_index);
575 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
576 info() << "AMR Patch name=" << cells.name() << " size=" << cells.size() << " index=" << patch_index << " nbPatch=" << m_patch_group.nbPatch();
577 patch->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
578 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index);
579 _computeMeshDirection(*patch.get(), MD_DirX, cells_center, faces_center, patch_cells, patch_nodes);
580 _computeMeshDirection(*patch.get(), MD_DirY, cells_center, faces_center, patch_cells, patch_nodes);
581 if (is_3d)
582 _computeMeshDirection(*patch.get(), MD_DirZ, cells_center, faces_center, patch_cells, patch_nodes);
583 }
584
585 if (arcaneIsCheck())
586 checkValid();
587
588 _saveInfosInProperties();
589}
590
591/*---------------------------------------------------------------------------*/
592/*---------------------------------------------------------------------------*/
593
594std::tuple<CellGroup, NodeGroup> CartesianMeshImpl::
595_buildPatchGroups(const CellGroup& cells, Integer patch_level)
596{
597 // We create a group for each patch ensuring that the traversal order
598 // is that of the entities' uniqueId()
599 // TODO: eventually, the traversal order should be the same as
600 // that of the Cartesian mesh. To do this, either the uniqueId()
601 // of the created cells/nodes are in the same order as the Cartesian mesh,
602 // or that the sorting function is specific to this type of mesh.
603 NodeGroup nodes = cells.nodeGroup();
604 IItemFamily* cell_family = cells.itemFamily();
605 IItemFamily* node_family = nodes.itemFamily();
606
607 String cell_group_name = String("AMRPatchCells") + patch_level;
608 CellGroup patch_cells = cell_family->createGroup(cell_group_name, Int32ConstArrayView(), true);
609 // Sets the same cells as \a cells but forces the sort
610 patch_cells.setItems(cells.view().localIds(), true);
611
612 String node_group_name = String("AMRPatchNodes") + patch_level;
613 NodeGroup patch_nodes = node_family->createGroup(node_group_name, Int32ConstArrayView(), true);
614 // Sets the same nodes as \a nodes but forces the sort
615 patch_nodes.setItems(nodes.view().localIds(), true);
616 info(4) << "PATCH_CELLS name=" << patch_cells.name() << " size=" << patch_cells.size();
617 info(4) << "PATCH_NODES name=" << patch_nodes.name() << " size=" << patch_nodes.size();
618 return { patch_cells, patch_nodes };
619}
620
621/*---------------------------------------------------------------------------*/
622/*---------------------------------------------------------------------------*/
623
624void CartesianMeshImpl::
625_computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir, VariableCellReal3& cells_center,
626 VariableFaceReal3& faces_center, CellGroup all_cells, NodeGroup all_nodes)
627{
628 IItemFamily* cell_family = m_mesh->cellFamily();
629 IItemFamily* face_family = m_mesh->faceFamily();
630 IItemFamily* node_family = m_mesh->nodeFamily();
631
632 Int32 max_cell_id = cell_family->maxLocalId();
633 Int32 max_face_id = face_family->maxLocalId();
634 Int32 max_node_id = node_family->maxLocalId();
635
636 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
637 cell_dm._internalResizeInfos(max_cell_id);
638
639 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
640 face_dm._internalResizeInfos(max_face_id);
641
642 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
643 node_dm._internalResizeInfos(max_node_id);
644
645 //TODO: remember to update after mesh change.
646 info(4) << "COMPUTE DIRECTION dir=" << dir;
647
648 Int32 prev_local_face = -1;
649 Int32 next_local_face = m_local_face_direction[dir];
650 Integer mesh_dim = m_mesh->dimension();
651 // Calculate the local number of the face opposite the next face.
652 if (mesh_dim == 2)
653 prev_local_face = (next_local_face + 2) % 4;
654 else if (mesh_dim == 3)
655 prev_local_face = (next_local_face + 3) % 6;
656
657 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
658
659 // Position the faces before and after for each cell in the direction.
660 // We ensure that these entities are in the group of entities for the corresponding direction
661 std::set<Int32> cells_set;
662 ENUMERATE_CELL (icell, all_cells) {
663 cells_set.insert(icell.itemLocalId());
664 }
665
666 // Calculate the front/back cells. In the case of an AMR patch, these two cells
667 // must be of the same level
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 (cells_set.find(next_cell.localId()) == cells_set.end())
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 (cells_set.find(prev_cell.localId()) == cells_set.end())
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 // Adds connectivity information for AMR patches
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 from IMesh properties:";
748 info() << "GlobalNbCell = " << cmgi->globalNbCells();
749 info() << "OwnNbCell: " << cmgi->ownNbCells();
750 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
751 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
752 // Position the information by 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() << "AMR Patch name=" << cells.name() << " size=" << 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 To delete
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: remember to update after mesh change.
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 // Calculate the local number of the face opposite the next face.
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 // Position the faces before and after for each cell in the direction.
811 // We ensure that these entities are in the group of entities for the corresponding direction
812 std::set<Int32> cells_set;
813 ENUMERATE_ (Cell, icell, all_cells) {
814 cells_set.insert(icell.itemLocalId());
815 }
816
817 // Calculate the front/back cells. In the case of an AMR patch, these two cells
818 // must be of the same level
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 (!cells_set.contains(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 (!cells_set.contains(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("You cannot reduce number of ghost layer of level 0 with this method");
909 }
910
911 // Maximum number of ghost cell layers. Meh; needs modification.
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() << "Level max : " << level_max;
921
923
924 Integer level_0_nb_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer();
925 //debug() << "NbGhostLayers level 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 level " << level << " : " << nb_ghost_layer;
934
935 // We assume there are always 2*2 child cells (2*2*2 in 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 level " << 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: We are forced to derefine level by level. Needs changing.
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 // Algorithm for numbering ghost cell layers.
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 // We do layer by layer (see how to remove this limitation).
1006 if (min != current_layer) {
1007 continue;
1008 }
1009
1010 // Cell without nodes already processed.
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("Error in ghost layer counter algo. Report it plz.");
1038 }
1039 }
1040 }
1041
1042 for (Integer i = level_max - 1; i >= 0; --i) {
1043 // A communication to avoid many others.
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 ghost layer for level " << 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 Creates a patch with all children of the group \a parent_cells.
1071 */
1072void CartesianMeshImpl::
1073_addPatch(ConstArrayView<Int32> parent_cells)
1074{
1075 // Create the group containing the AMR cells
1076 // These are the child cells of \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() << "Refine with modifier() (for all mesh types)";
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() << "Refine with specific refiner (for cartesian mesh only)";
1119 m_patch_group.addPatch(position);
1120 }
1121
1122 else if (m_amr_type == eMeshAMRKind::Patch) {
1123 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1124 }
1125 else {
1126 ARCANE_FATAL("AMR is not enabled");
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() << "Coarse with modifier() (for all mesh types)";
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() << "Coarsen with specific coarser (for cartesian mesh only)";
1164 m_patch_group.removeCellsInZone(zone_position);
1165 }
1166
1167 else if (m_amr_type == eMeshAMRKind::Patch) {
1168 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1169 }
1170 else {
1171 ARCANE_FATAL("AMR is not enabled");
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) << "Check valid CartesianMesh";
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 // First check if faces are renumbered
1203 Int32 face_method = v.renumberFaceMethod();
1204 if (face_method != 0 && face_method != 1)
1205 ARCANE_FATAL("Invalid value '{0}' for renumberFaceMethod(). Valid values are 0 or 1",
1206 face_method);
1207 if (face_method == 1)
1208 ARCANE_THROW(NotImplementedException, "Method 1 for face renumbering");
1209
1210 // Then check the patches if requested.
1211 Int32 patch_method = v.renumberPatchMethod();
1212 if (patch_method < 0 || patch_method > 4) {
1213 ARCANE_FATAL("Invalid value '{0}' for renumberPatchMethod(). Valid values are 0, 1, 2, 3 or 4",
1214 patch_method);
1215 }
1216 if (patch_method != 0 && m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1217 ARCANE_FATAL("Mesh items renumbering is not compatible with this type of 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() << "The patch method 2 is experimental!";
1226 CartesianMeshUniqueIdRenumberingV2 renumberer(this, cmgi);
1227 renumberer.renumber();
1228 }
1229
1230 // Finally, an optional sort.
1231 if (v.isSortAfterRenumbering()) {
1232 info() << "Compacting and Sorting after renumbering";
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: implement lock for 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("The mesh {0} is not yet created", h.meshName());
1279 ICartesianMesh* cm = arcaneCreateCartesianMesh(mesh);
1280 udlist->setData(name, new AutoDestroyUserData<ICartesianMesh>(cm));
1281
1282 // Indicates that the mesh is Cartesian
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("Can not cast to ICartesianMesh*");
1292 return adud->data();
1293}
1294
1295/*---------------------------------------------------------------------------*/
1296/*---------------------------------------------------------------------------*/
1297
1298} // End namespace Arcane
1299
1300/*---------------------------------------------------------------------------*/
1301/*---------------------------------------------------------------------------*/
#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.
Class managing a 3-dimensional real vector.
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:476
@ 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
Real z
third component of the triplet
Real x
first component of the triplet