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