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