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