Arcane  v4.1.4.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CartesianMesh.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CartesianMesh.cc (C) 2000-2026 */
9/* */
10/* Maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/TraceAccessor.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/AutoDestroyUserData.h"
17#include "arcane/utils/IUserDataList.h"
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/PlatformUtils.h"
21#include "arcane/utils/Event.h"
22
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 void computeDirectionsPatchV2(Integer index) override;
211
212 private:
213
214 // Implémentation de 'ICartesianMeshInternal'
215 Ref<CartesianMeshCoarsening2> _createCartesianMeshCoarsening2();
216 void _addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id);
217 CartesianPatchGroup& _cartesianPatchGroup() { return m_patch_group; }
218 void _computeDirectionsV2();
219
220 private:
221
222 InternalApi m_internal_api;
223 //! Indice dans la numérotation locale de la maille, de la face dans
224 // la direction X, Y ou Z
225 Int32 m_local_face_direction[3] = { -1, -1, -1 };
226 IMesh* m_mesh = nullptr;
227 Ref<CartesianMeshPatch> m_all_items_direction_info;
228 CartesianConnectivity m_connectivity;
229 UniqueArray<CartesianConnectivity::Index> m_nodes_to_cell_storage;
230 UniqueArray<CartesianConnectivity::Index> m_cells_to_node_storage;
231 UniqueArray<CartesianConnectivity::Permutation> m_permutation_storage;
232 bool m_is_amr = false;
233 //! Groupe de mailles pour chaque patch AMR.
234 CartesianPatchGroup m_patch_group;
235 ScopedPtrT<Properties> m_properties;
236
237 EventObserverPool m_event_pool;
238 bool m_is_mesh_event_added = false;
239 Int64 m_mesh_timestamp = 0;
240 eMeshAMRKind m_amr_type;
241
242 private:
243
244 void _computeMeshDirection(CartesianMeshPatch& cdi,eMeshDirection dir,
245 VariableCellReal3& cells_center,
246 VariableFaceReal3& faces_center,CellGroup all_cells,
247 NodeGroup all_nodes);
248
249 void _computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir,
250 CellGroup all_cells,
251 CellGroup in_patch_cells,
252 CellGroup overlap_cells,
253 NodeGroup all_nodes);
254
255 void _applyRefine(const AMRZonePosition &position);
256 void _applyCoarse(const AMRZonePosition& zone_position);
257 void _addPatch(ConstArrayView<Int32> parent_cells);
258 void _saveInfosInProperties();
259
260 std::tuple<CellGroup, NodeGroup>
261 _buildPatchGroups(const CellGroup& cells, Integer patch_level);
262 void _checkNeedComputeDirections();
263 void _checkAddObservableMeshChanged();
264};
265
266/*---------------------------------------------------------------------------*/
267/*---------------------------------------------------------------------------*/
268
269extern "C++" ICartesianMesh*
270arcaneCreateCartesianMesh(IMesh* mesh)
271{
272 auto* cm = new CartesianMeshImpl(mesh);
273 cm->build();
274 return cm;
275}
276
277/*---------------------------------------------------------------------------*/
278/*---------------------------------------------------------------------------*/
279
280CartesianMeshImpl::
281CartesianMeshImpl(IMesh* mesh)
282: TraceAccessor(mesh->traceMng())
283, m_internal_api(this)
284, m_mesh(mesh)
285, m_nodes_to_cell_storage(platform::getDefaultDataAllocator())
286, m_cells_to_node_storage(platform::getDefaultDataAllocator())
287, m_permutation_storage(platform::getDefaultDataAllocator())
288, m_patch_group(this)
289, m_amr_type(mesh->meshKind().meshAMRKind())
290{
291 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
292 m_internal_api.initCartesianMeshNumberingMngInternal();
293 m_internal_api.initCartesianMeshAMRPatchMng();
294 }
295 m_all_items_direction_info = m_patch_group.groundPatch();
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301void CartesianMeshImpl::
302build()
303{
304 m_properties = new Properties(*(mesh()->properties()),"CartesianMesh");
305 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
306 m_internal_api.cartesianMeshNumberingMngInternal()->build();
307 }
308 m_patch_group.build();
309}
310
311namespace
312{
313const Int32 SERIALIZE_VERSION = 1;
314}
315
316/*---------------------------------------------------------------------------*/
317/*---------------------------------------------------------------------------*/
318
319void CartesianMeshImpl::
320_checkNeedComputeDirections()
321{
322 Int64 new_timestamp = mesh()->timestamp();
323 if (m_mesh_timestamp!=new_timestamp){
324 info() << "Mesh timestamp has changed (old=" << m_mesh_timestamp << " new=" << new_timestamp << ")";
326 }
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
332void CartesianMeshImpl::
333_saveInfosInProperties()
334{
335 // Sauve le numéro de version pour être sur que c'est OK en reprise
336 m_properties->set("Version",SERIALIZE_VERSION);
337
338 m_patch_group.saveInfosInProperties();
339
340 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
341 m_internal_api.cartesianMeshNumberingMngInternal()->saveInfosInProperties();
342 //m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
343 }
344}
345
346/*---------------------------------------------------------------------------*/
347/*---------------------------------------------------------------------------*/
348
351{
352 info() << "Creating 'CartesianMesh' infos from dump";
353
354 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
355 m_internal_api.cartesianMeshNumberingMngInternal()->recreateFromDump();
356 m_internal_api.cartesianMeshNumberingMngInternal()->printStatus();
357 }
358
359 // Sauve le numéro de version pour être sur que c'est OK en reprise
360 Int32 v = m_properties->getInt32("Version");
361 if (v!=SERIALIZE_VERSION)
362 ARCANE_FATAL("Bad serializer version: trying to read from incompatible checkpoint v={0} expected={1}",
363 v,SERIALIZE_VERSION);
364
365 m_patch_group.recreateFromDump();
366
367 m_all_items_direction_info = m_patch_group.groundPatch();
368
370}
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
374
375void CartesianMeshImpl::
376_checkAddObservableMeshChanged()
377{
378 if (m_is_mesh_event_added)
379 return;
380 m_is_mesh_event_added = true;
381 // Pour appeler automatiquement 'computeDirections()' après un appel à
382 // IMesh::prepareForDump().
383 auto f1 = [&](const MeshEventArgs&){ this->_checkNeedComputeDirections(); };
384 mesh()->eventObservable(eMeshEventType::EndPrepareDump).attach(m_event_pool,f1);
385}
386
387/*---------------------------------------------------------------------------*/
388/*---------------------------------------------------------------------------*/
389
392{
393 if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
394 // TODO : Voir où mettre la renumérotation.
395 m_internal_api.cartesianMeshNumberingMngInternal()->renumberingFacesLevel0FromOriginalArcaneNumbering();
396 _computeDirectionsV2();
397 return;
398 }
399 info() << "CartesianMesh: computeDirections()";
400
401 m_mesh_timestamp = mesh()->timestamp();
402 _checkAddObservableMeshChanged();
403
404 m_is_amr = m_mesh->isAmrActivated();
405
406 VariableCellReal3 cells_center(VariableBuildInfo(m_mesh,"TemporaryCartesianMeshCellCenter"));
407 VariableFaceReal3 faces_center(VariableBuildInfo(m_mesh,"TemporaryCartesianMeshFaceCenter"));
408
409 // Calcule les coordonnées du centre des mailles.
410 VariableNodeReal3& nodes_coord = m_mesh->nodesCoordinates();
411 ENUMERATE_CELL(icell,m_mesh->allCells()){
412 Cell cell = *icell;
413 Real3 center;
414 for( NodeLocalId inode : cell.nodeIds() )
415 center += nodes_coord[inode];
416 center /= cell.nbNode();
417 cells_center[icell] = center;
418 }
419 ENUMERATE_FACE(iface,m_mesh->allFaces()){
420 Face face = *iface;
421 Real3 center;
422 for( NodeLocalId inode : face.nodeIds() )
423 center += nodes_coord[inode];
424 center /= face.nbNode();
425 faces_center[iface] = center;
426 }
427
428 IItemFamily* cell_family = m_mesh->cellFamily();
429 IItemFamily* node_family = m_mesh->nodeFamily();
430 Int32 next_face_x = -1;
431 Int32 next_face_y = -1;
432 Int32 next_face_z = -1;
433
434 CellVectorView cell_view = cell_family->allItems().view();
435 Cell cell0 = cell_view[0];
436 Integer nb_face = cell0.nbFace();
437 Integer nb_node = cell0.nbNode();
438 Real3 cell_center = cells_center[cell0];
439
440 info(4) << "sizeof(CellDirectionMng)=" << sizeof(CellDirectionMng)
441 << " sizeof(FaceDirectionMng)=" << sizeof(FaceDirectionMng)
442 << " sizeof(NodelDirectionMng)=" << sizeof(NodeDirectionMng);
443 info(4) << "sizeof(IndexedItemConnectivityViewBase)=" << sizeof(IndexedItemConnectivityViewBase)
444 << " sizeof(CellInfoListView)=" << sizeof(CellInfoListView);
445 info(4) << "Cartesian mesh compute directions is_amr=" << m_is_amr;
446
447 for( Integer i=0; i<nb_node; ++i ){
448 Node node = cell0.node(i);
449 info(4) << "Node I=" << i << " node=" << ItemPrinter(node) << " pos=" << nodes_coord[node];
450 }
451
452 bool is_3d = m_mesh->dimension() == 3;
453
454 // On suppose que toutes les mailles ont le même sens de numérotation dans le maillage.
455 // Par exemple, pour toutes les mailles, la face d'indice 0 est celle du haut, celle
456 // d'indice 1 celle de droite.
457 if (is_3d) {
458 Real max_x = -1;
459 Real max_y = -1;
460 Real max_z = -1;
461
462 for (Integer i = 0; i < nb_face; ++i) {
463 Face f = cell0.face(i);
464
465 Real3 next_center = faces_center[f];
466
467 Real diff_x = next_center.x - cell_center.x;
468 Real diff_y = next_center.y - cell_center.y;
469 Real diff_z = next_center.z - cell_center.z;
470
471 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real3(diff_x, diff_y, diff_z);
472
473 if (diff_x > max_x) {
474 max_x = diff_x;
475 next_face_x = i;
476 }
477
478 if (diff_y > max_y) {
479 max_y = diff_y;
480 next_face_y = i;
481 }
482
483 if (diff_z > max_z) {
484 max_z = diff_z;
485 next_face_z = i;
486 }
487 }
488 info(4) << "Advance in direction X -> " << next_face_x;
489 info(4) << "Advance in direction Y -> " << next_face_y;
490 info(4) << "Advance in direction Z -> " << next_face_z;
491 }
492 else {
493 Real max_x = -1;
494 Real max_y = -1;
495
496 for (Integer i = 0; i < nb_face; ++i) {
497 Face f = cell0.face(i);
498
499 Real3 next_center = faces_center[f];
500
501 Real diff_x = next_center.x - cell_center.x;
502 Real diff_y = next_center.y - cell_center.y;
503
504 info(4) << "NEXT_FACE=" << ItemPrinter(f) << " center=" << next_center << " diff=" << Real2(diff_x, diff_y);
505
506 if (diff_x > max_x) {
507 max_x = diff_x;
508 next_face_x = i;
509 }
510
511 if (diff_y > max_y) {
512 max_y = diff_y;
513 next_face_y = i;
514 }
515 }
516 info(4) << "Advance in direction X -> " << next_face_x;
517 info(4) << "Advance in direction Y -> " << next_face_y;
518 }
519 m_all_items_direction_info->_internalComputeNodeCellInformations(cell0,cells_center[cell0],nodes_coord);
520
521 info() << "Informations from IMesh properties:";
522
523 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh,true);
524
525 info() << "GlobalNbCell = " << cmgi->globalNbCells();
526 info() << "OwnNbCell: " << cmgi->ownNbCells();
527 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
528 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
529
530 CellGroup all_cells = cell_family->allItems();
531 NodeGroup all_nodes = node_family->allItems();
532 if (m_is_amr){
533 auto x = _buildPatchGroups(mesh()->allLevelCells(0),0);
534 all_cells = std::get<0>(x);
535 all_nodes = std::get<1>(x);
536 }
537
538 if (next_face_x!=(-1)){
539 m_local_face_direction[MD_DirX] = next_face_x;
540 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirX, cells_center, faces_center, all_cells, all_nodes);
541 }
542 if (next_face_y!=(-1)){
543 m_local_face_direction[MD_DirY] = next_face_y;
544 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirY, cells_center, faces_center, all_cells, all_nodes);
545 }
546 if (next_face_z != (-1)) {
547 m_local_face_direction[MD_DirZ] = next_face_z;
548 _computeMeshDirection(*m_all_items_direction_info.get(), MD_DirZ, cells_center, faces_center, all_cells, all_nodes);
549 }
550
551 // Positionne les informations par direction
552 for( Integer idir=0, nb_dir=mesh()->dimension(); idir<nb_dir; ++idir ){
553 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
554 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
555 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
556 }
557
558 info() << "Compute cartesian connectivity";
559
560 m_permutation_storage.resize(1);
561 m_permutation_storage[0].compute();
562 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
563 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
564 m_connectivity._setStorage(m_nodes_to_cell_storage,m_cells_to_node_storage,&m_permutation_storage[0]);
565 m_connectivity._computeInfos(mesh(),nodes_coord,cells_center);
566
567 // Ajoute informations de connectivités pour les patchs AMR
568 // TODO: supporter plusieurs appels à cette méthode ?
569 for (Integer patch_index = 1; patch_index < m_patch_group.nbPatch(); ++patch_index) {
570 CellGroup cells = m_patch_group.allCells(patch_index);
571 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
572 info() << "AMR Patch name=" << cells.name() << " size=" << cells.size() << " index=" << patch_index << " nbPatch=" << m_patch_group.nbPatch();
573 patch->_internalComputeNodeCellInformations(cell0, cells_center[cell0], nodes_coord);
574 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index);
575 _computeMeshDirection(*patch.get(), MD_DirX, cells_center, faces_center, patch_cells, patch_nodes);
576 _computeMeshDirection(*patch.get(), MD_DirY, cells_center, faces_center, patch_cells, patch_nodes);
577 if (is_3d)
578 _computeMeshDirection(*patch.get(), MD_DirZ, cells_center, faces_center, patch_cells, patch_nodes);
579 }
580
581 if (arcaneIsCheck())
582 checkValid();
583
584 _saveInfosInProperties();
585}
586
587/*---------------------------------------------------------------------------*/
588/*---------------------------------------------------------------------------*/
589
590std::tuple<CellGroup,NodeGroup> CartesianMeshImpl::
591_buildPatchGroups(const CellGroup& cells,Integer patch_level)
592{
593 // On créé un groupe pour chaque patch en garantissant que l'ordre de parcours
594 // est celui des uniqueId() des entités
595 // TODO: à terme, il faudrait que l'ordre de parcours soit le même que
596 // celui du maillage cartésien. Pour cela, il faut soit que les uniqueId()
597 // des mailles/noeuds créés soient dans le même ordre que le maillage cartésien,
598 // soit que la fonction de tri soit spécifique à ce type de maillage.
599 NodeGroup nodes = cells.nodeGroup();
600 IItemFamily* cell_family = cells.itemFamily();
601 IItemFamily* node_family = nodes.itemFamily();
602
603 String cell_group_name = String("AMRPatchCells") + patch_level;
604 CellGroup patch_cells = cell_family->createGroup(cell_group_name,Int32ConstArrayView(),true);
605 // Met les mêmes mailles que \a cells mais force le tri
606 patch_cells.setItems(cells.view().localIds(),true);
607
608 String node_group_name = String("AMRPatchNodes") + patch_level;
609 NodeGroup patch_nodes = node_family->createGroup(node_group_name,Int32ConstArrayView(),true);
610 // Met les mêmes noeuds que \a nodes mais force le tri
611 patch_nodes.setItems(nodes.view().localIds(),true);
612 info(4) << "PATCH_CELLS name=" << patch_cells.name() << " size=" << patch_cells.size();
613 info(4) << "PATCH_NODES name=" << patch_nodes.name() << " size=" << patch_nodes.size();
614 return { patch_cells, patch_nodes };
615}
616
617/*---------------------------------------------------------------------------*/
618/*---------------------------------------------------------------------------*/
619
620void CartesianMeshImpl::
621_computeMeshDirection(CartesianMeshPatch& cdi, eMeshDirection dir, VariableCellReal3& cells_center,
622 VariableFaceReal3& faces_center, CellGroup all_cells, NodeGroup all_nodes)
623{
624 IItemFamily* cell_family = m_mesh->cellFamily();
625 IItemFamily* face_family = m_mesh->faceFamily();
626 IItemFamily* node_family = m_mesh->nodeFamily();
627
628 Int32 max_cell_id = cell_family->maxLocalId();
629 Int32 max_face_id = face_family->maxLocalId();
630 Int32 max_node_id = node_family->maxLocalId();
631
632 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
633 cell_dm._internalResizeInfos(max_cell_id);
634
635 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
636 face_dm._internalResizeInfos(max_face_id);
637
638 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
639 node_dm._internalResizeInfos(max_node_id);
640
641 //TODO: attention à remettre à jour après changement de maillage.
642 info(4) << "COMPUTE DIRECTION dir=" << dir;
643
644 Int32 prev_local_face = -1;
645 Int32 next_local_face = m_local_face_direction[dir];
646 Integer mesh_dim = m_mesh->dimension();
647 // Calcul le numero local de face oppose à la face suivante.
648 if (mesh_dim==2)
649 prev_local_face = (next_local_face + 2) % 4;
650 else if (mesh_dim==3)
651 prev_local_face = (next_local_face + 3) % 6;
652
653 cell_dm._internalSetLocalFaceIndex(next_local_face,prev_local_face);
654
655 // Positionne pour chaque maille les faces avant et après dans la direction.
656 // On s'assure que ces entités sont dans le groupe des entités de la direction correspondante
657 std::set<Int32> cells_set;
658 ENUMERATE_CELL(icell,all_cells){
659 cells_set.insert(icell.itemLocalId());
660 }
661
662 // Calcule les mailles devant/derrière. En cas de patch AMR, il faut que ces deux mailles
663 // soient de même niveau
664 ENUMERATE_CELL (icell, all_cells) {
665 Cell cell = *icell;
666 Int32 my_level = cell.level();
667 Face next_face = cell.face(next_local_face);
668 Cell next_cell = next_face.backCell()==cell ? next_face.frontCell() : next_face.backCell();
669 if (cells_set.find(next_cell.localId()) == cells_set.end())
670 next_cell = Cell();
671 else if (next_cell.level() != my_level)
672 next_cell = Cell();
673
674 Face prev_face = cell.face(prev_local_face);
675 Cell prev_cell = prev_face.backCell()==cell ? prev_face.frontCell() : prev_face.backCell();
676 if (cells_set.find(prev_cell.localId()) == cells_set.end())
677 prev_cell = Cell();
678 else if (prev_cell.level() != my_level)
679 prev_cell = Cell();
680 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
681 }
682 cell_dm._internalComputeInnerAndOuterItems(all_cells);
683 face_dm._internalComputeInfos(cell_dm,cells_center,faces_center);
684 node_dm._internalComputeInfos(cell_dm,all_nodes,cells_center);
685}
686
687/*---------------------------------------------------------------------------*/
688/*---------------------------------------------------------------------------*/
689
690void CartesianMeshImpl::
691_computeDirectionsV2()
692{
693 info() << "CartesianMesh: computeDirectionsV2()";
694
695 m_mesh_timestamp = mesh()->timestamp();
696 _checkAddObservableMeshChanged();
697
698 m_is_amr = m_mesh->isAmrActivated();
699
700 if (m_mesh->dimension() == 3) {
701 m_local_face_direction[MD_DirX] = 4;
702 m_local_face_direction[MD_DirY] = 5;
703 m_local_face_direction[MD_DirZ] = 3;
704 }
705 else {
706 m_local_face_direction[MD_DirX] = 1;
707 m_local_face_direction[MD_DirY] = 2;
708 }
709
710 info() << "Compute cartesian connectivity";
711
712 m_permutation_storage.resize(1);
713 m_permutation_storage[0].compute();
714 m_nodes_to_cell_storage.resize(mesh()->nodeFamily()->maxLocalId());
715 m_cells_to_node_storage.resize(mesh()->cellFamily()->maxLocalId());
716 m_connectivity._setStorage(m_nodes_to_cell_storage, m_cells_to_node_storage, &m_permutation_storage[0]);
717 m_connectivity._computeInfos(this);
718
719 // Ajoute informations de connectivités pour les patchs AMR
720 for (Integer patch_index = 0; patch_index < m_patch_group.nbPatch(); ++patch_index) {
721 computeDirectionsPatchV2(patch_index);
722 }
723
724 if (arcaneIsCheck())
725 checkValid();
726
727 _saveInfosInProperties();
728}
729
730/*---------------------------------------------------------------------------*/
731/*---------------------------------------------------------------------------*/
732
733void CartesianMeshImpl::
734computeDirectionsPatchV2(Integer patch_index)
735{
736 bool is_3d = m_mesh->dimension() == 3;
737
738 CellGroup cells = m_patch_group.allCells(patch_index);
739 Ref<CartesianMeshPatch> patch = m_patch_group.patch(patch_index);
740
741 if (patch->index() == -1) {
742 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh, true);
743 info() << "Informations from IMesh properties:";
744 info() << "GlobalNbCell = " << cmgi->globalNbCells();
745 info() << "OwnNbCell: " << cmgi->ownNbCells();
746 info() << "SubDomainOffset: " << cmgi->subDomainOffsets();
747 info() << "OwnCellOffset: " << cmgi->ownCellOffsets();
748 // Positionne les informations par direction
749 for (Integer idir = 0, nb_dir = mesh()->dimension(); idir < nb_dir; ++idir) {
750 CellDirectionMng& cdm = m_all_items_direction_info->cellDirection(idir);
751 cdm._internalSetOffsetAndNbCellInfos(cmgi->globalNbCells()[idir], cmgi->ownNbCells()[idir],
752 cmgi->subDomainOffsets()[idir], cmgi->ownCellOffsets()[idir]);
753 }
754 }
755
756 info() << "AMR Patch name=" << cells.name() << " size=" << cells.size() << " index=" << patch_index << " trueindex=" << patch->index() << " nbPatch=" << m_patch_group.nbPatch();
757 {
758 const AMRPatchPosition position = patch->position();
759 info() << " position min=" << position.minPoint() << " max=" << position.maxPoint() << " level=" << position.level() << " overlapLayerSize=" << position.overlapLayerSize();
760 }
761 patch->_internalComputeNodeCellInformations();
762 auto [patch_cells, patch_nodes] = _buildPatchGroups(cells, patch_index); // TODO A suppr
763 _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);
764 _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);
765 if (is_3d)
766 _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);
767}
768
769/*---------------------------------------------------------------------------*/
770/*---------------------------------------------------------------------------*/
771
772void CartesianMeshImpl::
773_computeMeshDirectionV2(CartesianMeshPatch& cdi, eMeshDirection dir, CellGroup all_cells, CellGroup in_patch_cells, CellGroup overlap_cells, NodeGroup all_nodes)
774{
775 IItemFamily* cell_family = m_mesh->cellFamily();
776 IItemFamily* face_family = m_mesh->faceFamily();
777 IItemFamily* node_family = m_mesh->nodeFamily();
778
779 Int32 max_cell_id = cell_family->maxLocalId();
780 Int32 max_face_id = face_family->maxLocalId();
781 Int32 max_node_id = node_family->maxLocalId();
782
783 CellDirectionMng& cell_dm = cdi.cellDirection(dir);
784 cell_dm._internalResizeInfos(max_cell_id);
785
786 FaceDirectionMng& face_dm = cdi.faceDirection(dir);
787 face_dm._internalResizeInfos(max_face_id);
788
789 NodeDirectionMng& node_dm = cdi.nodeDirection(dir);
790 node_dm._internalResizeInfos(max_node_id);
791
792 //TODO: attention à remettre à jour après changement de maillage.
793 info(4) << "COMPUTE DIRECTION dir=" << dir;
794
795 Int32 prev_local_face = -1;
796 Int32 next_local_face = m_local_face_direction[dir];
797 Integer mesh_dim = m_mesh->dimension();
798 // Calcul le numero local de face oppose à la face suivante.
799 if (mesh_dim == 2)
800 prev_local_face = (next_local_face + 2) % 4;
801 else if (mesh_dim == 3)
802 prev_local_face = (next_local_face + 3) % 6;
803
804 cell_dm._internalSetLocalFaceIndex(next_local_face, prev_local_face);
805
806 // Positionne pour chaque maille les faces avant et après dans la direction.
807 // On s'assure que ces entités sont dans le groupe des entités de la direction correspondante
808 std::set<Int32> cells_set;
809 ENUMERATE_ (Cell, icell, all_cells) {
810 cells_set.insert(icell.itemLocalId());
811 }
812
813 // Calcule les mailles devant/derrière. En cas de patch AMR, il faut que ces deux mailles
814 // soient de même niveau
815 ENUMERATE_ (Cell, icell, all_cells) {
816 Cell cell = *icell;
817 Int32 my_level = cell.level();
818 Face next_face = cell.face(next_local_face);
819 Cell next_cell = next_face.backCell() == cell ? next_face.frontCell() : next_face.backCell();
820 if (!cells_set.contains(next_cell.localId()) || next_cell.level() != my_level) {
821 next_cell = Cell();
822 }
823
824 Face prev_face = cell.face(prev_local_face);
825 Cell prev_cell = prev_face.backCell() == cell ? prev_face.frontCell() : prev_face.backCell();
826 if (!cells_set.contains(prev_cell.localId()) || prev_cell.level() != my_level) {
827 prev_cell = Cell();
828 }
829
830 cell_dm.m_infos_view[icell.itemLocalId()] = CellDirectionMng::ItemDirectionInfo(next_cell, prev_cell);
831 }
832 cell_dm._internalComputeCellGroups(all_cells, in_patch_cells, overlap_cells);
833 face_dm._internalComputeInfos(cell_dm);
834 node_dm._internalComputeInfos(cell_dm, all_nodes);
835}
836
837/*---------------------------------------------------------------------------*/
838/*---------------------------------------------------------------------------*/
839
841refinePatch2D(Real2 position,Real2 length)
842{
843 info() << "REFINEMENT 2D position=" << position << " length=" << length;
844 refinePatch({ position, length });
845}
846
847/*---------------------------------------------------------------------------*/
848/*---------------------------------------------------------------------------*/
849
851refinePatch3D(Real3 position, Real3 length)
852{
853 info() << "REFINEMENT 3D position=" << position << " length=" << length;
854 refinePatch({ position, length });
855}
856
857/*---------------------------------------------------------------------------*/
858/*---------------------------------------------------------------------------*/
859
861refinePatch(const AMRZonePosition& position)
862{
863 _applyRefine(position);
864 _saveInfosInProperties();
865}
866
867/*---------------------------------------------------------------------------*/
868/*---------------------------------------------------------------------------*/
869
871coarseZone2D(Real2 position, Real2 length)
872{
873 info() << "COARSEN 2D position=" << position << " length=" << length;
874 coarseZone({ position, length });
875}
876
877/*---------------------------------------------------------------------------*/
878/*---------------------------------------------------------------------------*/
879
881coarseZone3D(Real3 position, Real3 length)
882{
883 info() << "COARSEN 3D position=" << position << " length=" << length;
884 coarseZone({ position, length });
885}
886
887/*---------------------------------------------------------------------------*/
888/*---------------------------------------------------------------------------*/
889
891coarseZone(const AMRZonePosition& position)
892{
893 _applyCoarse(position);
894 _saveInfosInProperties();
895}
896
897/*---------------------------------------------------------------------------*/
898/*---------------------------------------------------------------------------*/
899
901reduceNbGhostLayers(Integer level, Integer target_nb_ghost_layers)
902{
903 if (level < 1) {
904 ARCANE_FATAL("You cannot reduce number of ghost layer of level 0 with this method");
905 }
906
907 // Nombre de couche de maille fantôme max. Bof; à modifier.
908 const Int32 max_nb_layer = 128;
909 Int32 level_max = 0;
910
911 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
912 level_max = std::max(level_max, icell->level());
913 }
914
915 level_max = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, level_max);
916 //debug() << "Level max : " << level_max;
917
919
920 Integer level_0_nb_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer();
921 //debug() << "NbGhostLayers level 0 : " << level_0_nb_ghost_layer;
922
923 if (level_0_nb_ghost_layer == 0) {
924 return 0;
925 }
926
927 Integer nb_ghost_layer = Convert::toInt32(level_0_nb_ghost_layer * pow(2, level));
928
929 //debug() << "NbGhostLayers level " << level << " : " << nb_ghost_layer;
930
931 // On considère qu'on a toujours 2*2 mailles filles (2*2*2 en 3D).
932 if (target_nb_ghost_layers % 2 != 0) {
933 target_nb_ghost_layers++;
934 }
935
936 if (target_nb_ghost_layers == nb_ghost_layer) {
937 return nb_ghost_layer;
938 }
939
940 //debug() << "TargetNbGhostLayers level " << level << " : " << target_nb_ghost_layers;
941
942 Integer parent_level = level - 1;
943 Integer parent_target_nb_ghost_layer = target_nb_ghost_layers / 2;
944
945 // TODO AH : On est forcé de dé-raffiner niveau par niveau. À changer.
946 UniqueArray<UniqueArray<Int32>> cell_lid2(level_max);
947
948 //UniqueArray<Int32> cell_lid;
949 std::function<void(Cell)> children_list;
950
951 children_list = [&cell_lid2, &children_list](Cell cell) -> void {
952 for (Integer i = 0; i < cell.nbHChildren(); ++i) {
953 //debug() << "child of lid=" << cell.localId() << " : lid=" << cell.hChild(i).localId() << " -- level : " << cell.level();
954 cell_lid2[cell.level()].add(cell.hChild(i).localId());
955 children_list(cell.hChild(i));
956 }
957 };
958
959 // Algorithme de numérotation des couches de mailles fantômes.
960 {
961 VariableNodeInt32 level_node{ VariableBuildInfo{ m_mesh, "LevelNode" } };
962 level_node.fill(-1);
963
964 VariableCellInt32 level_cell{ VariableBuildInfo{ m_mesh, "LevelCell" } };
965 level_cell.fill(-1);
966
967 ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
968 Cell front_cell = iface->frontCell();
969 Cell back_cell = iface->backCell();
970 if (
971 ((front_cell.null() || (!front_cell.isOwn() && front_cell.level() == parent_level)) && ((!back_cell.null()) && (back_cell.isOwn() && back_cell.level() == parent_level))) ||
972 ((back_cell.null() || (!back_cell.isOwn() && back_cell.level() == parent_level)) && ((!front_cell.null()) && (front_cell.isOwn() && front_cell.level() == parent_level)))) {
973 for (Node node : iface->nodes()) {
974 level_node[node] = 0;
975 //debug() << "Node layer 0 : " << node.uniqueId();
976 }
977 }
978 }
979
980 bool is_modif = true;
981 Int32 current_layer = 0;
982 while (is_modif) {
983 is_modif = false;
984
985 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
986 if (icell->isOwn() || icell->level() != parent_level || level_cell[icell] != -1) {
987 continue;
988 }
989
990 Int32 min = max_nb_layer;
991 Int32 max = -1;
992
993 for (Node node : icell->nodes()) {
994 Int32 nlevel = level_node[node];
995 if (nlevel != -1) {
996 min = std::min(min, nlevel);
997 max = std::max(max, nlevel);
998 }
999 }
1000
1001 // On fait couche par couche (voir pour enlever cette limitation).
1002 if (min != current_layer) {
1003 continue;
1004 }
1005
1006 // Maille n'ayant pas de nodes déjà traités.
1007 if (min == max_nb_layer && max == -1) {
1008 continue;
1009 }
1010
1011 Integer new_level = ((min == max) ? min + 1 : max);
1012
1013 for (Node node : icell->nodes()) {
1014 Int32 nlevel = level_node[node];
1015 if (nlevel == -1) {
1016 level_node[node] = new_level;
1017 //debug() << "Node layer " << new_level << " : " << node.uniqueId();
1018 is_modif = true;
1019 }
1020 }
1021
1022 level_cell[icell] = min;
1023
1024 //debug() << "Cell uid : " << icell->uniqueId()
1025 // << " -- Layer : " << min;
1026
1027 if (min >= parent_target_nb_ghost_layer) {
1028 children_list(*icell);
1029 }
1030 }
1031 current_layer++;
1032 if (current_layer >= max_nb_layer) {
1033 ARCANE_FATAL("Error in ghost layer counter algo. Report it plz.");
1034 }
1035 }
1036 }
1037
1038 for (Integer i = level_max - 1; i >= 0; --i) {
1039 // Une comm pour en éviter plein d'autres.
1040 if (m_mesh->parallelMng()->reduce(Parallel::ReduceMax, cell_lid2[i].size()) == 0) {
1041 continue;
1042 }
1043 //debug() << "Removing children of ghost cell (parent level=" << i << ") (children localIds) : " << cell_lid2[i];
1044
1045 m_mesh->modifier()->flagCellToCoarsen(cell_lid2[i]);
1046 m_mesh->modifier()->coarsenItemsV2(false);
1047 }
1048
1049 info() << "Nb ghost layer for level " << level << " : " << target_nb_ghost_layers;
1050
1051 return target_nb_ghost_layers;
1052}
1053
1054/*---------------------------------------------------------------------------*/
1055/*---------------------------------------------------------------------------*/
1056
1057void CartesianMeshImpl::
1058_addPatchFromExistingChildren(ConstArrayView<Int32> parent_cells_local_id)
1059{
1060 _addPatch(parent_cells_local_id);
1061}
1062
1063/*---------------------------------------------------------------------------*/
1064/*---------------------------------------------------------------------------*/
1065/*!
1066 * \brief Créé un patch avec tous les enfants du groupe \a parent_cells.
1067 */
1068void CartesianMeshImpl::
1069_addPatch(ConstArrayView<Int32> parent_cells)
1070{
1071 // Créé le groupe contenant les mailles AMR
1072 // Il s'agit des mailles filles de \a parent_cells
1073
1074 UniqueArray<Int32> children_local_id;
1075 CellInfoListView cells(m_mesh->cellFamily());
1076 for (Int32 cell_local_id : parent_cells) {
1077 Cell c = cells[cell_local_id];
1078 for (Integer k = 0; k < c.nbHChildren(); ++k) {
1079 Cell child = c.hChild(k);
1080 children_local_id.add(child.localId());
1081 }
1082 }
1083
1084 m_patch_group.addPatch(children_local_id);
1085}
1086
1087/*---------------------------------------------------------------------------*/
1088/*---------------------------------------------------------------------------*/
1089
1090void CartesianMeshImpl::
1091_applyRefine(const AMRZonePosition& position)
1092{
1093 if (m_amr_type == eMeshAMRKind::Cell) {
1094 UniqueArray<Int32> cells_local_id;
1095 position.cellsInPatch(mesh(), cells_local_id);
1096
1097 Integer nb_cell = cells_local_id.size();
1098 info(4) << "Local_NbCellToRefine = " << nb_cell;
1099
1100 IParallelMng* pm = m_mesh->parallelMng();
1101 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1102 info(4) << "Global_NbCellToRefine = " << total_nb_cell;
1103 if (total_nb_cell == 0)
1104 return;
1105
1106 debug() << "Refine with modifier() (for all mesh types)";
1107 m_mesh->modifier()->flagCellToRefine(cells_local_id);
1108 m_mesh->modifier()->adapt();
1109
1110 _addPatch(cells_local_id);
1111 }
1112
1113 else if(m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1114 debug() << "Refine with specific refiner (for cartesian mesh only)";
1115 m_patch_group.addPatch(position);
1116 }
1117
1118 else if (m_amr_type == eMeshAMRKind::Patch) {
1119 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1120 }
1121 else{
1122 ARCANE_FATAL("AMR is not enabled");
1123 }
1124
1125 {
1126 MeshStats ms(traceMng(),m_mesh,m_mesh->parallelMng());
1127 ms.dumpStats();
1128 }
1129}
1130
1131/*---------------------------------------------------------------------------*/
1132/*---------------------------------------------------------------------------*/
1133
1134void CartesianMeshImpl::
1135_applyCoarse(const AMRZonePosition& zone_position)
1136{
1137 if (m_amr_type == eMeshAMRKind::Cell) {
1138 UniqueArray<Int32> cells_local_id;
1139
1140 zone_position.cellsInPatch(mesh(), cells_local_id);
1141
1142 Integer nb_cell = cells_local_id.size();
1143 info(4) << "Local_NbCellToCoarsen = " << nb_cell;
1144
1145 IParallelMng* pm = m_mesh->parallelMng();
1146 Int64 total_nb_cell = pm->reduce(Parallel::ReduceSum, nb_cell);
1147 info(4) << "Global_NbCellToCoarsen = " << total_nb_cell;
1148 if (total_nb_cell == 0)
1149 return;
1150
1151 debug() << "Coarse with modifier() (for all mesh types)";
1152 m_patch_group.removeCellsInAllPatches(cells_local_id);
1153 m_patch_group.applyPatchEdit(true, false);
1154
1155 m_mesh->modifier()->flagCellToCoarsen(cells_local_id);
1156 m_mesh->modifier()->coarsenItemsV2(true);
1157 }
1158
1159 else if (m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1160 debug() << "Coarsen with specific coarser (for cartesian mesh only)";
1161 m_patch_group.removeCellsInZone(zone_position);
1162 }
1163
1164 else if (m_amr_type == eMeshAMRKind::Patch) {
1165 ARCANE_FATAL("General patch AMR is not implemented. Please use PatchCartesianMeshOnly (3)");
1166 }
1167 else {
1168 ARCANE_FATAL("AMR is not enabled");
1169 }
1170
1171 {
1172 MeshStats ms(traceMng(), m_mesh, m_mesh->parallelMng());
1173 ms.dumpStats();
1174 }
1175}
1176
1177/*---------------------------------------------------------------------------*/
1178/*---------------------------------------------------------------------------*/
1179
1181checkValid() const
1182{
1183 info(4) << "Check valid CartesianMesh";
1184 Integer nb_patch = nbPatch();
1185 for( Integer i=0; i<nb_patch; ++i ){
1186 ICartesianMeshPatch* p = patch(i);
1187 p->checkValid();
1188 }
1189}
1190
1191/*---------------------------------------------------------------------------*/
1192/*---------------------------------------------------------------------------*/
1193
1196{
1197 auto* cmgi = ICartesianMeshGenerationInfo::getReference(m_mesh,true);
1198
1199 // Regarde d'abord si on renumérote les faces
1200 Int32 face_method = v.renumberFaceMethod();
1201 if (face_method!=0 && face_method!=1)
1202 ARCANE_FATAL("Invalid value '{0}' for renumberFaceMethod(). Valid values are 0 or 1",
1203 face_method);
1204 if (face_method==1)
1205 ARCANE_THROW(NotImplementedException,"Method 1 for face renumbering");
1206
1207 // Regarde ensuite les patchs si demandé.
1208 Int32 patch_method = v.renumberPatchMethod();
1209 if (patch_method < 0 || patch_method > 4) {
1210 ARCANE_FATAL("Invalid value '{0}' for renumberPatchMethod(). Valid values are 0, 1, 2, 3 or 4",
1211 patch_method);
1212 }
1213 if (patch_method != 0 && m_amr_type == eMeshAMRKind::PatchCartesianMeshOnly) {
1214 ARCANE_FATAL("Mesh items renumbering is not compatible with this type of AMR");
1215 }
1216
1217 if (patch_method == 1 || patch_method == 3 || patch_method == 4) {
1218 CartesianMeshUniqueIdRenumbering renumberer(this, cmgi, v.parentPatch(), patch_method);
1219 renumberer.renumber();
1220 }
1221 else if (patch_method == 2) {
1222 warning() << "The patch method 2 is experimental!";
1223 CartesianMeshUniqueIdRenumberingV2 renumberer(this, cmgi);
1224 renumberer.renumber();
1225 }
1226
1227 // Termine par un tri éventuel.
1228 if (v.isSortAfterRenumbering()){
1229 info() << "Compacting and Sorting after renumbering";
1230 m_mesh->nodeFamily()->compactItems(true);
1231 m_mesh->faceFamily()->compactItems(true);
1232 m_mesh->cellFamily()->compactItems(true);
1234 }
1235}
1236
1237/*---------------------------------------------------------------------------*/
1238/*---------------------------------------------------------------------------*/
1239
1245
1246/*---------------------------------------------------------------------------*/
1247/*---------------------------------------------------------------------------*/
1248
1249Ref<CartesianMeshCoarsening2> CartesianMeshImpl::
1250_createCartesianMeshCoarsening2()
1251{
1252 return makeRef(new CartesianMeshCoarsening2(this));
1253}
1254
1255/*---------------------------------------------------------------------------*/
1256/*---------------------------------------------------------------------------*/
1257
1258/*---------------------------------------------------------------------------*/
1259/*---------------------------------------------------------------------------*/
1260
1262getReference(const MeshHandleOrMesh& mesh_handle_or_mesh,bool create)
1263{
1264 MeshHandle h = mesh_handle_or_mesh.handle();
1265 //TODO: faire lock pour multi-thread
1266 const char* name = "CartesianMesh";
1267 IUserDataList* udlist = h.meshUserDataList();
1268
1269 IUserData* ud = udlist->data(name,true);
1270 if (!ud){
1271 if (!create)
1272 return nullptr;
1273 IMesh* mesh = h.meshOrNull();
1274 if (!mesh)
1275 ARCANE_FATAL("The mesh {0} is not yet created",h.meshName());
1276 ICartesianMesh* cm = arcaneCreateCartesianMesh(mesh);
1277 udlist->setData(name,new AutoDestroyUserData<ICartesianMesh>(cm));
1278
1279 // Indique que le maillage est cartésien
1280 MeshKind mk = mesh->meshKind();
1281 mk.setMeshStructure(eMeshStructure::Cartesian);
1282 mesh->_internalApi()->setMeshKind(mk);
1283
1284 return cm;
1285 }
1287 if (!adud)
1288 ARCANE_FATAL("Can not cast to ICartesianMesh*");
1289 return adud->data();
1290}
1291
1292/*---------------------------------------------------------------------------*/
1293/*---------------------------------------------------------------------------*/
1294
1295} // End namespace Arcane
1296
1297/*---------------------------------------------------------------------------*/
1298/*---------------------------------------------------------------------------*/
#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:482
@ 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