Arcane  4.1.11.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MeshRefinement.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/* MeshRefinement.cc (C) 2000-2025 */
9/* */
10/* Manipulation of an AMR mesh. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#ifndef AMRMAXCONSISTENCYITER
15#define AMRMAXCONSISTENCYITER 10
16#endif
17
18// \brief class of methods for refining unstructured meshes
20
22#include "arcane/utils/Real3.h"
23#include "arcane/utils/ArgumentException.h"
24
25#include "arcane/core/IParallelMng.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IItemFamily.h"
28#include "arcane/core/Item.h"
29
30#include "arcane/core/VariableTypes.h"
31#include "arcane/core/ItemPrinter.h"
32#include "arcane/core/SharedVariable.h"
33#include "arcane/core/ItemRefinementPattern.h"
34#include "arcane/core/Properties.h"
35#include "arcane/core/IGhostLayerMng.h"
36#include "arcane/core/ItemVector.h"
37
38#include "arcane/mesh/DynamicMesh.h"
39#include "arcane/mesh/ItemRefinement.h"
40#include "arcane/mesh/MeshRefinement.h"
41#include "arcane/mesh/ParallelAMRConsistency.h"
42#include "arcane/mesh/FaceReorienter.h"
43#include "arcane/mesh/NodeFamily.h"
44#include "arcane/mesh/EdgeFamily.h"
45
46#include "arcane/core/materials/IMeshMaterialMng.h"
47
48#include <vector>
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53namespace Arcane::mesh
54{
55
56namespace
57{
58 void _setRefineFlags(Item v)
59 {
60 Integer f = v.itemBase().flags();
61 f &= ~ItemFlags::II_Coarsen;
63 v.mutableItemBase().setFlags(f);
64 }
65 void _setCoarseFlags(Item v)
66 {
67 Integer f = v.itemBase().flags();
68 f &= ~ItemFlags::II_Refine;
70 v.mutableItemBase().setFlags(f);
71 }
72
73} // namespace
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78#ifdef ACTIVATE_PERF_COUNTER
79const std::string MeshRefinement::PerfCounter::m_names[MeshRefinement::PerfCounter::NbCounters] = {
80 "INIT",
81 "CLEAR",
82 "ENDUPDATE",
83 "UPDATEMAP",
84 "UPDATEMAP2",
85 "CONSIST",
86 "PCONSIST",
87 "PCONSIST2",
88 "PGCONSIST",
89 "CONTRACT",
90 "COARSEN",
91 "REFINE",
92 "INTERP",
93 "PGHOST",
94 "COMPACT"
95};
96#endif
97
98// Mesh refinement methods
102, m_mesh(mesh)
103, m_face_family(&(mesh->trueFaceFamily()))
104, m_node_finder(mesh)
105, m_face_finder(mesh)
107, m_max_level(-1)
108, m_nb_cell_target(0)
109, m_face_level_mismatch_limit(1)
110, m_max_node_uid(NULL_ITEM_UNIQUE_ID)
111, m_next_node_uid(NULL_ITEM_UNIQUE_ID)
112, m_max_cell_uid(NULL_ITEM_UNIQUE_ID)
113, m_next_cell_uid(NULL_ITEM_UNIQUE_ID)
114, m_max_face_uid(NULL_ITEM_UNIQUE_ID)
115, m_next_face_uid(NULL_ITEM_UNIQUE_ID)
116, m_max_nb_hChildren(0)
117, m_node_owner_memory(VariableBuildInfo(mesh, "NodeOwnerMemoryVar"))
118{
119 // \todo create a builder
123 m_need_update = true;
124
125 ENUMERATE_NODE (inode, m_mesh->allNodes())
126 m_node_owner_memory[inode] = inode->owner();
127
128#ifdef ACTIVATE_PERF_COUNTER
129 m_perf_counter.init();
130#endif
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
138{
139 this->clear();
140 delete m_item_refinement;
142 delete m_call_back_mng;
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
149clear()
150{
151 CHECKPERF(m_perf_counter.start(PerfCounter::CLEAR))
152 m_node_finder._clear();
153 m_face_finder._clear();
154 CHECKPERF(m_perf_counter.stop(PerfCounter::CLEAR))
155}
156/*---------------------------------------------------------------------------*/
157/*---------------------------------------------------------------------------*/
158
160init()
161{
162 // Recalculate the max uniqueId() of nodes/cells/faces.
163 CHECKPERF(m_perf_counter.start(PerfCounter::INIT))
164 IParallelMng* pm = m_mesh->parallelMng();
165 {
166 Int64 max_node_uid = 0;
167 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
168 const Node& node = *inode;
169 const Int64 uid = node.uniqueId();
170 if (uid > max_node_uid)
171 max_node_uid = uid;
172 }
173
174 if (pm->commSize() > 1)
175 m_max_node_uid = pm->reduce(Parallel::ReduceMax, max_node_uid);
176 else
177 m_max_node_uid = max_node_uid;
178 info() << "NODE_UID_INFO: MY_MAX_UID=" << max_node_uid << " GLOBAL=" << m_max_node_uid;
179 m_next_node_uid = m_max_node_uid + 1 + m_mesh->parallelMng()->commRank();
180 }
181 ItemTypeMng* itm = m_mesh->itemTypeMng();
182
183 {
184 Int64 max_cell_uid = 0;
185 Integer max_nb_hChildren = 0;
186 ENUMERATE_CELL (icell, m_mesh->allCells()) {
187 const Cell& cell = *icell;
188 const Int64 uid = cell.uniqueId();
189 const Int32 nb_hChildren = itm->nbHChildrenByItemType(cell.type());
190 if (uid > max_cell_uid)
191 max_cell_uid = uid;
192 if (nb_hChildren > max_nb_hChildren)
193 max_nb_hChildren = nb_hChildren;
194 }
195 if (pm->commSize() > 1) {
196 m_max_cell_uid = pm->reduce(Parallel::ReduceMax, max_cell_uid);
197 m_max_nb_hChildren = pm->reduce(Parallel::ReduceMax, max_nb_hChildren);
198 }
199 else {
200 m_max_cell_uid = max_cell_uid;
201 m_max_nb_hChildren = max_nb_hChildren;
202 }
203 info() << "CELL_UID_INFO: MY_MAX_UID=" << max_cell_uid << " GLOBAL=" << m_max_cell_uid;
204 m_next_cell_uid = m_max_cell_uid + 1 + pm->commRank() * m_max_nb_hChildren;
205 }
206
207 {
208 Int64 max_face_uid = 0;
209 ENUMERATE_FACE (iface, m_mesh->allFaces()) {
210 const Face& face = *iface;
211 const Int64 uid = face.uniqueId();
212 if (uid > max_face_uid)
213 max_face_uid = uid;
214 }
215
216 if (pm->commSize() > 1)
217 m_max_face_uid = pm->reduce(Parallel::ReduceMax, max_face_uid);
218 else
219 m_max_face_uid = max_face_uid;
220 info() << "FACE_UID_INFO: MY_MAX_UID=" << max_face_uid << " GLOBAL=" << m_max_face_uid;
221 m_next_face_uid = m_max_face_uid + 1 + pm->commRank();
222 }
223
225
226 CHECKPERF(m_perf_counter.stop(PerfCounter::INIT))
227}
228
229void MeshRefinement::
230_updateMaxUid(ArrayView<ItemInternal*> cells)
231{
232 // Recalculate the max uniqueId() of nodes/cells/faces.
233 CHECKPERF(m_perf_counter.start(PerfCounter::INIT))
236 {
237
238 Int64 max_node_uid = m_max_node_uid;
239 Int64 max_cell_uid = m_max_cell_uid;
240 Integer max_nb_hChildren = m_max_nb_hChildren;
241 Int64 max_face_uid = m_max_face_uid;
242
243 typedef std::set<Int64> set_type;
244 typedef std::pair<set_type::iterator, bool> insert_return_type;
245 set_type node_list;
246 set_type face_list;
247 for (Integer icell = 0; icell < cells.size(); ++icell) {
248 Cell cell = cells[icell];
249 for (UInt32 i = 0, nc = cell.nbHChildren(); i < nc; i++) {
250 Cell child = cell.hChild(i);
251
252 //UPDATE MAX CELL UID
253 const Int64 cell_uid = child.uniqueId();
254 const Int32 nb_hChildren = itm->nbHChildrenByItemType(child.type());
255 if (cell_uid > max_cell_uid)
256 max_cell_uid = cell_uid;
257 if (nb_hChildren > max_nb_hChildren)
258 max_nb_hChildren = nb_hChildren;
259
260 //UPDATE MAX NODE UID
261 for (Node inode : child.nodes()) {
262 const Int64 uid = inode.uniqueId();
263 insert_return_type value = node_list.insert(uid);
264 if (value.second) {
265 if (uid > max_node_uid)
266 max_node_uid = uid;
267 }
268 }
269
270 //UPDATE MAX FACE UID
271 for (Face iface : child.faces()) {
272 const Int64 uid = iface.uniqueId();
273 insert_return_type value = face_list.insert(uid);
274 if (value.second) {
275 if (uid > max_face_uid)
276 max_face_uid = uid;
277 }
278 }
279 }
280 }
281
282 if (pm->commSize() > 1) {
283 m_max_node_uid = pm->reduce(Parallel::ReduceMax, max_node_uid);
284 m_max_cell_uid = pm->reduce(Parallel::ReduceMax, max_cell_uid);
285 m_max_nb_hChildren = pm->reduce(Parallel::ReduceMax, max_nb_hChildren);
286 m_max_face_uid = pm->reduce(Parallel::ReduceMax, max_face_uid);
287 }
288 else {
289 m_max_node_uid = max_node_uid;
290 m_max_cell_uid = max_cell_uid;
291 m_max_nb_hChildren = max_nb_hChildren;
292 m_max_face_uid = max_face_uid;
293 }
294 m_next_node_uid = m_max_node_uid + 1 + m_mesh->parallelMng()->commRank();
295 m_next_cell_uid = m_max_cell_uid + 1 + pm->commRank() * m_max_nb_hChildren;
296 m_next_face_uid = m_max_face_uid + 1 + pm->commRank();
297 }
298
299 CHECKPERF(m_perf_counter.stop(PerfCounter::INIT))
300}
301
302void MeshRefinement::initMeshContainingBox()
303{
305 m_node_finder.setBox(&m_mesh_containing_box);
306 m_face_finder.setBox(&m_mesh_containing_box);
307}
308
309void MeshRefinement::update()
310{
311 init();
312 initMeshContainingBox();
313 m_item_refinement->initHMin();
314 m_node_finder.init();
315 //m_node_finder.check() ;
316 m_face_finder.initFaceCenter();
317 m_face_finder.init();
318 //m_face_finder.check() ;
320 m_need_update = false;
321}
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
327{
328 CellLocalIdToCellConverter cells(m_mesh->cellFamily());
329 for (Integer i = 0, is = lids.size(); i < is; i++) {
330 Item item = cells[lids[i]];
331 //ARCANE_ASSERT((item->type() ==IT_Hexaedron8),(""));
333 }
334}
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339void MeshRefinement::
340flagCellToCoarsen(Int32ConstArrayView lids)
341{
343 for (Integer i = 0, is = lids.size(); i < is; i++) {
344 Item item = cells[lids[i]];
345 //ARCANE_ASSERT((item->type() ==IT_Hexaedron8),(""));
347 }
348}
349/*---------------------------------------------------------------------------*/
350/*---------------------------------------------------------------------------*/
351
353refineAndCoarsenItems(const bool maintain_level_one)
354{
355 CHECKPERF(m_perf_counter.start(PerfCounter::INIT))
356
357 bool _maintain_level_one = maintain_level_one;
358
359 // the level-one rule is the only implemented condition
360 if (!maintain_level_one) {
361 warning() << "Warning, level one rule is the only condition accepted for AMR!";
362 }
363 else
364 _maintain_level_one = m_face_level_mismatch_limit;
365
366 // We cannot yet transform a non-level-one mesh into a level-one mesh
367 if (_maintain_level_one) {
368 ARCANE_ASSERT((_checkLevelOne(true)), ("checkLevelOne failed"));
369 }
370
371 // Clear refinement flags from a previous step
372 this->_cleanRefinementFlags();
373 CHECKPERF(m_perf_counter.stop(PerfCounter::INIT))
374
375 // Parallel consistency must come first, otherwise
376 // coarsening along interfaces between processors could occasionally be
377 // falsely prevented
378 if (m_mesh->parallelMng()->isParallel())
380
381 CHECKPERF(m_perf_counter.start(PerfCounter::CONSIST))
382 // Repeat until flag matching is achieved on each processor
383 Integer iter = 0;
384 do {
385 // Repeat until coarsening/refinement flags are locally satisfied
386 bool satisfied = false;
387 do {
388 const bool coarsening_satisfied = this->_makeCoarseningCompatible(maintain_level_one);
389 const bool refinement_satisfied = this->_makeRefinementCompatible(maintain_level_one);
390 satisfied = (coarsening_satisfied && refinement_satisfied);
391#ifdef ARCANE_DEBUG
392 bool max_satisfied = satisfied, min_satisfied = satisfied;
393 max_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, max_satisfied);
394 min_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, min_satisfied);
395 ARCANE_ASSERT((satisfied == max_satisfied), ("parallel max_satisfied failed"));
396 ARCANE_ASSERT((satisfied == min_satisfied), ("parallel min_satisfied failed"));
397#endif
398 } while (!satisfied);
399 ++iter;
400 } while (m_mesh->parallelMng()->isParallel() && !this->_makeFlagParallelConsistent() && iter < 10);
401 if (iter == AMRMAXCONSISTENCYITER)
402 fatal() << " MAX CONSISTENCY ITER REACHED";
403 CHECKPERF(m_perf_counter.stop(PerfCounter::CONSIST))
404
405 // First, coarsen the flagged items.
406 CHECKPERF(m_perf_counter.start(PerfCounter::COARSEN))
407 const bool coarsening_changed_mesh = this->_coarsenItems();
408 CHECKPERF(m_perf_counter.stop(PerfCounter::COARSEN))
409
410 // Now, refine the flagged items. This will take
411 // more memory, and possibly more than is available.
412 Int64UniqueArray cells_to_refine;
413 const bool refining_changed_mesh = this->_refineItems(cells_to_refine);
414
415 // Finally, preparing the new mesh for use
416 if (refining_changed_mesh || coarsening_changed_mesh) {
417 bool do_compact = m_mesh->properties()->getBool("compact");
418 m_mesh->properties()->setBool("compact", true); // Forcing compaction prevents from bugs when using AMR
419
420 // Refinement
421 CHECKPERF(m_perf_counter.start(PerfCounter::ENDUPDATE))
422 m_mesh->modifier()->endUpdate();
423 m_mesh->properties()->setBool("compact", do_compact);
424 CHECKPERF(m_perf_counter.stop(PerfCounter::ENDUPDATE))
425
426 // Coarsening
427 //bool remove_ghost_children = false;
428 if (coarsening_changed_mesh) {
429 //remove_ghost_children=true;
430
431 CHECKPERF(m_perf_counter.start(PerfCounter::CONTRACT))
432 this->_contract();
433 CHECKPERF(m_perf_counter.stop(PerfCounter::CONTRACT))
434
435 CHECKPERF(m_perf_counter.start(PerfCounter::ENDUPDATE))
436 m_mesh->properties()->setBool("compact", true); // Forcing compaction prevents from bugs when using AMR (leads to problems whith dof)
437 m_mesh->modifier()->endUpdate();
438 m_mesh->properties()->setBool("compact", do_compact);
439 CHECKPERF(m_perf_counter.stop(PerfCounter::ENDUPDATE))
440 }
441
442 // callback to transport variables onto the new mesh
443 CHECKPERF(m_perf_counter.start(PerfCounter::INTERP))
444 this->_interpolateData(cells_to_refine);
445 CHECKPERF(m_perf_counter.stop(PerfCounter::INTERP))
446 //
447
448 if (!coarsening_changed_mesh && m_mesh->parallelMng()->isParallel())
449 this->_makeFlagParallelConsistent2();
450
451 if (m_mesh->parallelMng()->isParallel()) {
452 CHECKPERF(m_perf_counter.start(PerfCounter::PGHOST))
453 m_mesh->modifier()->setDynamic(true);
454 UniqueArray<Int64> ghost_cell_to_refine;
455 UniqueArray<Int64> ghost_cell_to_coarsen;
456 m_mesh->modifier()->updateGhostLayerFromParent(ghost_cell_to_refine,
457 ghost_cell_to_coarsen,
458 false);
459 _update(ghost_cell_to_refine);
460 CHECKPERF(m_perf_counter.stop(PerfCounter::PGHOST))
461 _checkOwner("refineAndCoarsenItems after ghost update");
462 }
463
464 /*
465 if(do_compact)
466 {
467 CHECKPERF( m_perf_counter.start(PerfCounter::COMPACT) )
468 m_mesh->properties()->setBool("compact",true) ;
469 DynamicMesh* mesh = dynamic_cast<DynamicMesh*> (m_mesh);
470 if(mesh)
471 mesh->compact() ;
472 CHECKPERF( m_perf_counter.stop(PerfCounter::COMPACT) )
473 }*/
474
475#ifdef ACTIVATE_PERF_COUNTER
476 info() << "MESH REFINEMENT PERF INFO";
477 m_perf_counter.printInfo(info().file());
478 info() << "NODE FINDER PERF INFO";
479 m_node_finder.getPerfCounter().printInfo(info().file());
480 info() << "FACE FINDER PERF INFO";
481 m_face_finder.getPerfCounter().printInfo(info().file());
482 info() << "PARALLEL AMR CONSISTENCY PERF INFO";
483 m_parallel_amr_consistency->getPerfCounter().printInfo(info().file());
484#endif
485 return true;
486 }
487 // If there were no changes in the mesh
488 return false;
489}
490
491/*---------------------------------------------------------------------------*/
492/*---------------------------------------------------------------------------*/
493
495coarsenItems(const bool maintain_level_one)
496{
497
498 bool _maintain_level_one = maintain_level_one;
499
500 // the level-one rule is the only implemented condition
501 if (!maintain_level_one) {
502 warning() << "Warning, level one rule is the only condition accepted for AMR!";
503 }
504 else
505 _maintain_level_one = m_face_level_mismatch_limit;
506
507 // We cannot yet transform a non-level-one mesh into a level-one mesh
508 if (_maintain_level_one) {
509 ARCANE_ASSERT((_checkLevelOne(true)), ("check_level_one failed"));
510 }
511
512 // Cleaning up refinement flags from the previous step
513 this->_cleanRefinementFlags();
514
515 // Parallel consistency must come first, otherwise the coarsening
516 // along interfaces between processors could occasionally be
517 // falsely prevented
518 if (m_mesh->parallelMng()->isParallel())
520
521 // Repeat until the flag change matches on every processor
522 do {
523 // Repeat until the flags match locally.
524 bool satisfied = false;
525 do {
526 const bool coarsening_satisfied = this->_makeCoarseningCompatible(maintain_level_one);
527 satisfied = coarsening_satisfied;
528#ifdef ARCANE_DEBUG
529 bool max_satisfied = satisfied, min_satisfied = satisfied;
530 max_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, max_satisfied);
531 min_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, min_satisfied);
532 ARCANE_ASSERT((satisfied == max_satisfied), ("parallel max_satisfied failed"));
533 ARCANE_ASSERT((satisfied == min_satisfied), ("parallel min_satisfied failed"));
534#endif
535 } while (!satisfied);
536 } while (m_mesh->parallelMng()->isParallel() && !this->_makeFlagParallelConsistent());
537
538 // Coarsen the flagged items.
539 const bool mesh_changed = this->_coarsenItems();
540
541 //if (_maintain_level_one)
542 //ARCANE_ASSERT( (checkLevelOne(true)),("checkLevelOne failed"));
543 //ARCANE_ASSERT( (this->makeCoarseningCompatible(maintain_level_one)), ("make_coarsening_comptaible failed"));
544
545 // Finally, preparing the new mesh for use
546 if (mesh_changed) {
547 this->_contract();
548 _checkOwner("coarsenItems");
549 //
550 //m_mesh->modifier()->setDynamic(true);
551 //m_mesh->modifier()->updateGhostLayerFromParent(false);
552 }
553
554 return mesh_changed;
555}
556
557/*---------------------------------------------------------------------------*/
558/*---------------------------------------------------------------------------*/
559
561coarsenItemsV2(bool update_parent_flag)
562{
563 // Cleaning up refinement flags from the previous step
564 this->_cleanRefinementFlags();
565
566 UniqueArray<Int32> to_coarse;
567 //UniqueArray<Int64> d_to_coarse_uid;
568
569 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
570 Cell cell = *icell;
572 // We cannot coarsen level-0 cells.
573 if (cell.level() == 0) {
574 ARCANE_FATAL("Cannot coarse level-0 cell");
575 }
576 Cell parent = cell.hParent();
577
578 // TODO AH: To perform multi-level coarsening at once,
579 // the II_Inactive flag must be removed (for the FaceFamily::removeCellFromFace() method).
580 if (update_parent_flag) {
584 }
585
586 // For a level n-1 cell, if one of its child cells must be coarsened,
587 // then all its child cells must be coarsened.
588 for (Integer i = 0; i < parent.nbHChildren(); ++i) {
589 Cell child = parent.hChild(i);
590 if (!(child.mutableItemBase().flags() & ItemFlags::II_Coarsen)) {
591 ARCANE_FATAL("Parent cannot have children with coarse flag and children without coarse flag -- Parent uid: {0} -- Child uid: {1}", parent.uniqueId(), child.uniqueId());
592 }
593 }
594
595 // For now, it is impossible to coarsen multiple levels at once.
596 // TODO AH: The FaceReorienter::checkAndChangeOrientationAMR() method will check a
597 // face that should be deleted, see why.
599 ARCANE_FATAL("Cannot coarse parent and child in same time");
600 }
601 if (cell.nbHChildren() != 0) {
602 ARCANE_FATAL("For now, cannot coarse cell with children");
603 // for (Integer i = 0; i < cell.nbHChildren(); ++i) {
604 // Cell child = cell.hChild(i);
605 // if (!(child.mutableItemBase().flags() & ItemFlags::II_Coarsen)) {
606 // ARCANE_FATAL("Cannot coarse cell with non-coarsen children -- Parent uid: {0} -- Child uid: {1}", cell.uniqueId(), child.uniqueId());
607 // }
608 // }
609 }
610 to_coarse.add(cell.localId());
611 //d_to_coarse_uid.add(cell.uniqueId());
612 }
613 }
614
615 if (m_mesh->parallelMng()->isParallel()) {
616 bool has_ghost_layer = m_mesh->ghostLayerMng()->nbGhostLayer() != 0;
617
618 ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
619 Cell cell = *icell;
621 for (Face face : cell.faces()) {
622 Cell other_cell = face.oppositeCell(cell);
623 // debug() << "Check face uid : " << face.uniqueId();
624 // If the face is on the boundary, it will be deleted.
625 if (other_cell.null()) { // && !has_ghost_layer) {
626 continue;
627 //needed_cell.add(face.uniqueId());
628 }
629 if (other_cell.level() != cell.level()) {
630 //warning() << "Bad connectivity";
631 continue;
632 }
633 // If both cells are going to be deleted, the face will be deleted.
634 if (other_cell.mutableItemBase().flags() & ItemFlags::II_Coarsen) {
635 continue;
636 }
637 // If the adjacent cell is refined, we will have more than one level difference.
638 if (other_cell.nbHChildren() != 0) { // && !(other_cell.mutableItemBase().flags() & ItemFlags::II_Coarsen)) { // Impossible to coarsen multiple levels.
639 ARCANE_FATAL("Max one level diff between two cells is allowed -- Uid of Cell to be coarseing: {0} -- Uid of Opposite cell with children: {1}", cell.uniqueId(), other_cell.uniqueId());
640 }
641 // If the adjacent cell is not ours, it takes the ownership of the adjacent cell.
642 if (other_cell.owner() != cell.owner()) {
643 // debug() << "Face uid : " << face.uniqueId()
644 // << " -- old owner: " << face.owner()
645 // << " -- new owner: " << other_cell.owner();
646 face.mutableItemBase().setOwner(other_cell.owner(), cell.owner());
647 // debug() << "Set owner face uid: " << face.uniqueId() << " -- New owner: " << other_cell.owner();
648 }
649 }
650 for (Node node : cell.nodes()) {
651 // debug() << "Check node uid : " << node.uniqueId();
652
653 // Will the node be deleted?
654 {
655 bool will_deleted = true;
656 for (Cell cell2 : node.cells()) {
657 if (!(cell2.mutableItemBase().flags() & ItemFlags::II_Coarsen)) {
658 will_deleted = false;
659 break;
660 }
661 }
662 if (will_deleted) {
663 continue;
664 }
665 }
666
667 // Will the node need to change owner?
668 {
669 Integer node_owner = node.owner();
670 Integer new_owner = -1;
671 bool need_new_owner = true;
672 for (Cell cell2 : node.cells()) {
673 if (!(cell2.mutableItemBase().flags() & ItemFlags::II_Coarsen)) {
674 if (cell2.owner() == node_owner) {
675 need_new_owner = false;
676 break;
677 }
678 new_owner = cell2.owner();
679 }
680 }
681 if (!need_new_owner) {
682 continue;
683 }
684 // debug() << "Node uid : " << node.uniqueId()
685 // << " -- old owner: " << node.owner()
686 // << " -- new owner: " << new_owner;
687 node.mutableItemBase().setOwner(new_owner, cell.owner());
688 // debug() << "Set owner node uid: " << node.uniqueId() << " -- New owner: " << new_owner;
689 }
690 }
691 }
692 }
693
694 if (!has_ghost_layer) {
695 // TODO
696 ARCANE_NOT_YET_IMPLEMENTED("Support des maillages sans mailles fantômes à faire");
697 }
698 }
699
700 //debug() << "Removed cells: " << d_to_coarse_uid;
701
702 m_mesh->modifier()->removeCells(to_coarse);
703 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
704 m_mesh->faceFamily()->notifyItemsOwnerChanged();
705 m_mesh->modifier()->endUpdate();
706 m_mesh->cellFamily()->computeSynchronizeInfos();
707 m_mesh->nodeFamily()->computeSynchronizeInfos();
708 m_mesh->faceFamily()->computeSynchronizeInfos();
709 m_mesh->modifier()->setDynamic(true);
710
711 UniqueArray<Int64> ghost_cell_to_refine;
712 UniqueArray<Int64> ghost_cell_to_coarsen;
713
714 if (!update_parent_flag) {
715 // If materials are active, material recalculation must be forced because the cell groups
716 // have been modified and thus the list of constituents as well
718 if (mm)
719 mm->forceRecompute();
720 }
721
722 m_mesh->modifier()->updateGhostLayerFromParent(ghost_cell_to_refine, ghost_cell_to_coarsen, true);
723
724 return m_mesh->parallelMng()->reduce(Parallel::ReduceMax, (!to_coarse.empty()));
725}
726
727/*---------------------------------------------------------------------------*/
728/*---------------------------------------------------------------------------*/
729
731refineItems(const bool maintain_level_one)
732{
733
734 bool _maintain_level_one = maintain_level_one;
735
736 // the level-one rule is the only implemented condition
737 if (!maintain_level_one) {
738 warning() << "Warning, level one rule is the only condition accepted for AMR!";
739 }
740 else
741 _maintain_level_one = m_face_level_mismatch_limit;
742
743 if (_maintain_level_one) {
744 ARCANE_ASSERT((_checkLevelOne(true)), ("check_level_one failed"));
745 }
746 // Cleaning up refinement flags from the previous step
747 this->_cleanRefinementFlags();
748
749 // Parallel consistency must come first, otherwise the coarsening
750 // along interfaces between processors could occasionally be
751 // falsely prevented
752 if (m_mesh->parallelMng()->isParallel())
754
755 // Repeat until the flag change matches on every processor
756 do {
757 // Repeat until the flags match locally.
758 bool satisfied = false;
759 do {
760 const bool refinement_satisfied = this->_makeRefinementCompatible(maintain_level_one);
761 satisfied = refinement_satisfied;
762#ifdef ARCANE_DEBUG
763 bool max_satisfied = satisfied, min_satisfied = satisfied;
764 max_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, max_satisfied);
765 min_satisfied = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, min_satisfied);
766 ARCANE_ASSERT((satisfied == max_satisfied), ("parallel max_satisfied failed"));
767 ARCANE_ASSERT((satisfied == min_satisfied), ("parallel min_satisfied failed"));
768#endif
769 } while (!satisfied);
770 } while (m_mesh->parallelMng()->isParallel() && !this->_makeFlagParallelConsistent());
771
772 // Now, refine the flagged items. This will take
773 // more memory, and possibly more than is available.
774 Int64UniqueArray cells_to_refine;
775 const bool mesh_changed = this->_refineItems(cells_to_refine);
776
777 // Finally, preparing the new mesh for use
778 if (mesh_changed) {
779 // update
780 bool do_compact = m_mesh->properties()->getBool("compact");
781 m_mesh->properties()->setBool("compact", true); // Forcing compaction prevents from bugs when using AMR
782 m_mesh->modifier()->endUpdate();
783 m_mesh->properties()->setBool("compact", do_compact);
784
785 // callback to transport variables onto the new mesh
786 this->_interpolateData(cells_to_refine);
787
788 // ghost update
789 m_mesh->modifier()->setDynamic(true);
790 UniqueArray<Int64> ghost_cell_to_refine;
791 UniqueArray<Int64> ghost_cell_to_coarsen;
792 m_mesh->modifier()->updateGhostLayerFromParent(ghost_cell_to_refine, ghost_cell_to_coarsen, false);
793 _update(ghost_cell_to_refine);
794 }
795
796 //if (_maintain_level_one)
797 //ARCANE_ASSERT( (checkLevelOne(true)), ("check_level_one failed"));
798 //ARCANE_ASSERT( (this->makeRefinementCompatible(maintain_level_one)), ("make_refinment_compatible failed"));
799
800 return mesh_changed;
801}
802
803/*---------------------------------------------------------------------------*/
804/*---------------------------------------------------------------------------*/
805
808{
809 // Refine n times
810 // FIXME - this should not work if n>1 and the mesh
811 // is already attached to the system of equations to be solved
812 for (Integer rstep = 0; rstep < n; rstep++) {
813 // Cleaning up refinement flags
814 this->_cleanRefinementFlags();
815
816 // iterate only over active cells
817 // Flag all active items for refinement
818 ENUMERATE_CELL (icell, m_mesh->ownActiveCells()) {
819 Cell cell = *icell;
820 _setRefineFlags(cell);
821 }
822 // Refine all the items we have flagged.
823 Int64UniqueArray cells_to_refine;
824 this->_refineItems(cells_to_refine);
825 warning() << "ATTENTION: No Data Projection with this method!";
826 }
827
828 bool do_compact = m_mesh->properties()->getBool("compact");
829 m_mesh->properties()->setBool("compact", true); // Forcing compaction prevents from bugs when using AMR
830 m_mesh->modifier()->endUpdate();
831 m_mesh->properties()->setBool("compact", do_compact);
832}
833
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
839{
840 // Coarsen n times
841 for (Integer rstep = 0; rstep < n; rstep++) {
842 // Cleaning refinement flags
843 this->_cleanRefinementFlags();
844
845 // Iterate only over active cells
846 // Flag all active items for coarsening
847 ENUMERATE_CELL (icell, m_mesh->ownActiveCells()) {
848 Cell cell = *icell;
849 _setCoarseFlags(cell);
850 if (cell.nbHParent() != 0) {
852 }
853 }
854 // Coarsen all items we just flagged.
855 this->_coarsenItems();
856 warning() << "ATTENTION: No Data Restriction with this method!";
857 }
858
859 // Finally, preparation of the new mesh for use
860 bool do_compact = m_mesh->properties()->getBool("compact");
861 m_mesh->properties()->setBool("compact", true);
862 m_mesh->modifier()->endUpdate();
863 m_mesh->properties()->setBool("compact", do_compact);
864}
865
866/*---------------------------------------------------------------------------*/
867/*---------------------------------------------------------------------------*/
868
870findOrAddNodeUid(const Real3& p, const Real& tol)
871{
872 //debug() << "addNode()";
873
874 // Return the node if it already exists
875 Int64 uid = m_node_finder.find(p, tol);
876 if (uid != NULL_ITEM_ID) {
877 // debug() << "addNode() done";
878 return uid;
879 }
880 // Add the node to the map.
881 Int64 new_uid = m_next_node_uid;
882 m_node_finder.insert(p, new_uid, tol);
883 m_next_node_uid += m_mesh->parallelMng()->commSize() + 1;
884 // Return the uid of the new node
885 // debug() << "addNode() done";
886 return new_uid;
887}
888/*---------------------------------------------------------------------------*/
889/*---------------------------------------------------------------------------*/
891findOrAddFaceUid(const Real3& p, const Real& tol, bool& is_added)
892{
893 //debug() << "findOrAddFaceUid()";
894
895 // Return the face if it already exists
896 Int64 uid = m_face_finder.find(p, tol);
897 if (uid != NULL_ITEM_ID) {
898 // debug() << "findOrAddFaceUid() done";
899 is_added = false;
900 return uid;
901 }
902 // Add the face to the map.
903 is_added = true;
904 Int64 new_uid = m_next_face_uid;
905 m_face_finder.insert(p, new_uid, tol);
906 m_next_face_uid += m_mesh->parallelMng()->commSize() + 1;
907 // Return the uid of the new face
908 // debug() << "findOrAddFaceUid() done";
909 return new_uid;
910}
911
912/*---------------------------------------------------------------------------*/
913/*---------------------------------------------------------------------------*/
914
917{
918 Int64 new_uid = m_next_cell_uid;
919 Int64 comm_size = m_mesh->parallelMng()->commSize();
920 m_next_cell_uid += comm_size * m_max_nb_hChildren;
921 return new_uid;
922}
923
924/*---------------------------------------------------------------------------*/
925/*---------------------------------------------------------------------------*/
926/* PRIVATE METHODS */
927/*---------------------------------------------------------------------------*/
928/*---------------------------------------------------------------------------*/
929
932{
933 //jmg this->init(); // \todo not necessary to call on every update
934 //m_node_finder.init();
935 m_node_finder.check();
936 //m_face_finder.init();
937 m_face_finder.check();
938 debug() << "[MeshRefinement::updateLocalityMap] done";
939}
940/*---------------------------------------------------------------------------*/
941/*---------------------------------------------------------------------------*/
942
943void MeshRefinement::
944_updateLocalityMap2()
945{
946 //this->init(); // \todo not necessary to call on every update
947 //this->m_node_finder.init2();
948 //m_node_finder.check2() ;
949 //m_face_finder.init2();
950 //m_face_finder.check2();
951 //debug() << "[MeshRefinement::updateLocalityMap2] done";
952}
953/*---------------------------------------------------------------------------*/
954/*---------------------------------------------------------------------------*/
955
957_checkLevelOne(bool arcane_assert_pass)
958{
959 bool failure = false;
960
961 Integer sid = m_mesh->parallelMng()->commRank();
962 // Iterate only over active cells
963 ENUMERATE_CELL (icell, m_mesh->allActiveCells()) {
964 Cell cell = *icell;
965 for (Face face : cell.faces()) {
966 if (face.nbCell() != 2)
967 continue;
968 Cell back_cell = face.backCell();
969 Cell front_cell = face.frontCell();
970
971 // We choose the other cell on the face side
972 Cell neighbor = (back_cell == cell) ? front_cell : back_cell;
973 if (neighbor.null() || !neighbor.isActive() || !(neighbor.owner() == sid))
974 continue;
975 //debug() << "#### " << ineighbor->uniqueId() << " " << ineighbor->level() << " " << cell.level();
976 if ((neighbor.level() + 1 < cell.level())) {
977 failure = true;
978 break;
979 }
980 }
981 }
982
983 // If one processor fails, we fail globally
984 failure = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, failure);
985
986 if (failure) {
987 // We did not pass the level-one test, so arcane_assert
988 // based on the input boolean.
989 if (arcane_assert_pass)
990 throw FatalErrorException(A_FUNCINFO, "checkLevelOne failed");
991 return false;
992 }
993 return true;
994}
995
996/*---------------------------------------------------------------------------*/
997/*---------------------------------------------------------------------------*/
998
1000_checkUnflagged(bool arcane_assert_pass)
1001{
1002 bool found_flag = false;
1003
1004 // Search for local flags
1005 // Iterate only over active cells
1006 ENUMERATE_CELL (icell, m_mesh->ownActiveCells()) {
1007 const Cell cell = *icell;
1008 const Integer f = cell.itemBase().flags();
1009 if ((f & ItemFlags::II_Refine) | (f & ItemFlags::II_Coarsen)) {
1010 found_flag = true;
1011 break;
1012 }
1013 }
1014 // If we find a flag on any processor, it counts
1015 found_flag = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, found_flag);
1016 if (found_flag) {
1017 // We did not pass the "items are unflagged" test,
1018 // thus arcane_assert the non-value of arcane_assert_pass
1019 if (arcane_assert_pass)
1020 throw FatalErrorException(A_FUNCINFO, "checkUnflagged failed");
1021 return false;
1022 }
1023 return true;
1024}
1025
1026/*---------------------------------------------------------------------------*/
1027/*---------------------------------------------------------------------------*/
1028
1031{
1032 if (!m_mesh->parallelMng()->isParallel())
1033 return true;
1034
1035 CHECKPERF(m_perf_counter.start(PerfCounter::PCONSIST))
1036 debug() << "makeFlagsParallelConsistent() begin";
1037 bool parallel_consistent = true;
1038 VariableCellInteger flag_cells_consistent(VariableBuildInfo(m_mesh, "FlagCellsConsistent"));
1039 UniqueArray<Item> ghost_cells;
1040 ghost_cells.reserve(m_mesh->allCells().size() - m_mesh->ownCells().size());
1041 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1042 Cell cell = *icell;
1043 if (cell.isOwn()) {
1044 Integer f = cell.itemBase().flags(); // TODO getAMRFlags()
1045 flag_cells_consistent[icell] = f;
1046 }
1047 else
1048 ghost_cells.add(cell);
1049 }
1050 flag_cells_consistent.synchronize();
1051 //ENUMERATE_CELL(icell,m_mesh->allCells())
1052 for (Integer icell = 0, nb_cell = ghost_cells.size(); icell < nb_cell; ++icell) {
1053 Item iitem = ghost_cells[icell];
1054 Integer f = iitem.itemBase().flags();
1055
1056 //if(iitem->owner() != sid)
1057 {
1058 // it is possible that the ghost flags are (temporarily) more
1059 // conservative than our own flags, such as when a refinement of one of our
1060 // cells on the remote processor is dictated by a refinement of one of our cells
1061 const Integer g = flag_cells_consistent[Cell(iitem)];
1062 if ((g & ItemFlags::II_Refine) && !(f & ItemFlags::II_Refine)) {
1064 iitem.mutableItemBase().setFlags(f);
1065 parallel_consistent = false;
1066 }
1067 else if ((g & ItemFlags::II_Coarsen) && !(f & ItemFlags::II_Coarsen)) {
1069 iitem.mutableItemBase().setFlags(f);
1070 parallel_consistent = false;
1071 }
1074 iitem.mutableItemBase().setFlags(f);
1075 parallel_consistent = false;
1076 }
1077 else if ((g & ItemFlags::II_JustRefined) && !(f & ItemFlags::II_JustRefined)) {
1079 iitem.mutableItemBase().setFlags(f);
1080 parallel_consistent = false;
1081 }
1082 /*
1083 else if ((g & ItemFlags::II_CoarsenInactive) && !(f & ItemFlags::II_CoarsenInactive)){
1084 f |= ItemFlags::II_CoarsenInactive;
1085 //f |= ItemFlags::II_Inactive;
1086 iitem->setFlags(f);
1087 parallel_consistent = false;
1088 }
1089 else if ((g & ItemFlags::II_DoNothing) && !(f & ItemFlags::II_DoNothing)){
1090 f |= ItemFlags::II_DoNothing;
1091 //f |= ItemFlags::II_Inactive;
1092 iitem->setFlags(f);
1093 parallel_consistent = false;
1094 }
1095
1096 else if ((g & ItemFlags::II_Inactive) && !(f & ItemFlags::II_Inactive)){
1097 f |= ItemFlags::II_Inactive;
1098 //f |= ItemFlags::II_Inactive;
1099 iitem->setFlags(f);
1100 parallel_consistent = false;
1101 }*/
1102 }
1103 }
1104 // If we are not consistent on every processor then
1105 // we are not globally consistent
1106 parallel_consistent = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, parallel_consistent);
1107 debug() << "makeFlagsParallelConsistent() end -- parallel_consistent : " << parallel_consistent;
1108
1109 CHECKPERF(m_perf_counter.stop(PerfCounter::PCONSIST))
1110 return parallel_consistent;
1111}
1112/*---------------------------------------------------------------------------*/
1113/*---------------------------------------------------------------------------*/
1114bool MeshRefinement::
1115_makeFlagParallelConsistent2()
1116{
1117 if (!m_mesh->parallelMng()->isParallel())
1118 return true;
1119
1120 CHECKPERF(m_perf_counter.start(PerfCounter::PCONSIST2))
1121 debug() << "makeFlagsParallelConsistent2() begin";
1122 bool parallel_consistent = true;
1123 VariableCellInteger flag_cells_consistent(VariableBuildInfo(m_mesh, "FlagCellsConsistent"));
1124 UniqueArray<Item> ghost_cells;
1125 ghost_cells.reserve(m_mesh->allCells().size() - m_mesh->ownCells().size());
1126 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1127 Cell cell = *icell;
1128 if (cell.isOwn()) {
1129 Integer f = cell.itemBase().flags(); // TODO getAMRFlags()
1130 flag_cells_consistent[icell] = f;
1131 }
1132 else
1133 ghost_cells.add(cell);
1134 }
1135 flag_cells_consistent.synchronize();
1136 //ENUMERATE_CELL(icell,m_mesh->allCells())
1137 for (Integer icell = 0, nb_cell = ghost_cells.size(); icell < nb_cell; ++icell) {
1138 //const Cell& cell = *icell;
1139 //ItemInternal * iitem = cell.internal();
1140 //Integer f = iitem->flags();
1141 Item iitem = ghost_cells[icell];
1142 Integer f = iitem.itemBase().flags();
1143
1144 //if(iitem->owner() != sid)
1145 {
1146 Integer g = flag_cells_consistent[Cell(iitem)];
1149 iitem.mutableItemBase().setFlags(f);
1150 parallel_consistent = false;
1151 }
1152 else if ((g & ItemFlags::II_JustRefined) && !(f & ItemFlags::II_JustRefined)) {
1154 iitem.mutableItemBase().setFlags(f);
1155 parallel_consistent = false;
1156 }
1157 else if ((g & ItemFlags::II_Inactive) && !(f & ItemFlags::II_Inactive)) {
1159 iitem.mutableItemBase().setFlags(f);
1160 parallel_consistent = false;
1161 }
1162 /*else if ((f & ItemFlags::II_JustRefined) && !(g & ItemFlags::II_JustRefined)){
1163 f &= ~ItemFlags::II_JustRefined;
1164 iitem->setFlags(f);
1165 parallel_consistent = false;
1166 }*/
1167 }
1168 }
1169 // If we are not consistent on every processor then
1170 // we are not globally consistent
1171 parallel_consistent = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, parallel_consistent);
1172 debug() << "makeFlagsParallelConsistent2() end";
1173
1174 CHECKPERF(m_perf_counter.stop(PerfCounter::PCONSIST2))
1175 return parallel_consistent;
1176}
1177/*---------------------------------------------------------------------------*/
1178/*---------------------------------------------------------------------------*/
1179
1181_makeCoarseningCompatible(const bool maintain_level_one)
1182{
1183
1184 debug() << "makeCoarseningCompatible() begin";
1185
1186 bool _maintain_level_one = maintain_level_one;
1187
1188 // the level-one rule is the only implemented condition
1189 if (!maintain_level_one) {
1190 warning() << "Warning, level one rule is the only condition accepted for AMR!";
1191 }
1192 else
1193 _maintain_level_one = m_face_level_mismatch_limit;
1194
1195 // unless we encounter a specific situation, the level-one rule
1196 // will be satisfied after executing this loop just once
1197 bool level_one_satisfied = true;
1198
1199 // unless we encounter a specific situation, we will be compatible
1200 // with all chosen refinement flags
1201 bool compatible_with_refinement = true;
1202
1203 // Find the maximum level in the mesh
1204 Integer max_level = 0;
1205
1206 // first we look at all active level 0 items. Since it makes no sense to
1207 // coarsen them, we must therefore remove their coarsening flags if
1208 // they are already positioned.
1209 // Iterate only over active cells
1210 ENUMERATE_CELL (icell, m_mesh->allActiveCells()) {
1211 const Cell cell = *icell;
1212 max_level = std::max(max_level, cell.level());
1213
1214 Integer f = cell.itemBase().flags();
1215 if ((cell.level() == 0) && (f & ItemFlags::II_Coarsen)) {
1216 f &= ~ItemFlags::II_Coarsen;
1218 cell.mutableItemBase().setFlags(f);
1219 }
1220 }
1221 // If there are no items to refine on this processor then
1222 // there is no work for us
1223 if (max_level == 0) {
1224 debug() << "makeCoarseningCompatible() done";
1225
1226 // however, it remains to check with the other processors
1227 compatible_with_refinement = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, compatible_with_refinement);
1228
1229 return compatible_with_refinement;
1230 }
1231 // Loop over all active items. If an item is marked
1232 // for coarsening, we check its neighbors. If one of its neighbors
1233 // is marked for refinement and is at the same level, then there is a
1234 // conflict. By convention, refinement wins, so we unmark the item for
1235 // coarsening. Level-one would be violated in this case, so we must re-execute
1236 // the loop.
1237 const Integer sid = m_mesh->parallelMng()->commRank();
1238 if (_maintain_level_one) {
1239
1240 repeat:
1241 level_one_satisfied = true;
1242
1243 do {
1244 level_one_satisfied = true;
1245 // iterate only over active cells
1246 ENUMERATE_CELL (icell, m_mesh->ownActiveCells()) {
1247 Cell cell = *icell;
1248 //ItemInternal* iitem = cell.internal();
1249 bool my_flag_changed = false;
1250 Integer f = cell.itemBase().flags();
1251 if (f & ItemFlags::II_Coarsen) { // If the item is active and the coarsening flag is set
1252 const Int32 my_level = cell.level();
1253 for (Face face : cell.faces()) {
1254 if (face.nbCell() != 2)
1255 continue;
1256 Cell back_cell = face.backCell();
1257 Cell front_cell = face.frontCell();
1258
1259 // We choose the other cell on the side of the face
1260 Cell neighbor = (back_cell == cell) ? front_cell : back_cell;
1261 //const ItemInternal* ineighbor = neighbor.internal();
1262 //if (ineighbor->owner() == sub_domain_id) // I have a neighbor here
1263
1264 {
1265 if (neighbor.isActive()) // and is active
1266 {
1267 if ((neighbor.level() == my_level) &&
1268 (neighbor.itemBase().flags() & ItemFlags::II_Refine)) { // the neighbor is at my level and wants to be refined
1269 f &= ~ItemFlags::II_Coarsen;
1271 cell.mutableItemBase().setFlags(f);
1272 my_flag_changed = true;
1273 break;
1274 }
1275 }
1276 else {
1277 // I have a neighbor and it is not active. This means it has children.
1278 // while it may be possible to coarsen me if all children
1279 // of this item want to be coarsened, it is impossible to know at this stage.
1280 // We forget it for now. This can be achieved in two steps.
1281 f &= ~ItemFlags::II_Coarsen;
1283 cell.mutableItemBase().setFlags(f);
1284 my_flag_changed = true;
1285 break;
1286 }
1287 }
1288 }
1289 }
1290
1291 // if the flag of the current cell has changed, we have not
1292 // satisfied the level one rule.
1293 if (my_flag_changed)
1294 level_one_satisfied = false;
1295
1296 // Furthermore, if it has non-local neighbors, and
1297 // we are not in sequential mode, then we must subsequently
1298 // return compatible_with_refinement= false, because
1299 // our change must be propagated to neighboring processors
1300 if (my_flag_changed && m_mesh->parallelMng()->isParallel())
1301 for (Face face : cell.faces()) {
1302 if (face.nbCell() != 2)
1303 continue;
1304 Cell back_cell = face.backCell();
1305 Cell front_cell = face.frontCell();
1306
1307 // We choose the other cell on the side of the face
1308 Cell neighbor = (back_cell == cell) ? front_cell : back_cell;
1309 //ItemInternal* ineighbor = neighbor.internal();
1310 if (neighbor.owner() != sid) { // I have a neighbor here
1311 compatible_with_refinement = false;
1312 break;
1313 }
1314 // TODO FIXME - for non level-1 meshes we must
1315 // test all descendants
1316 if (neighbor.hasHChildren())
1317 for (Integer c = 0; c != neighbor.nbHChildren(); ++c)
1318 if (neighbor.hChild(c).owner() != sid) {
1319 compatible_with_refinement = false;
1320 break;
1321 }
1322 }
1323 }
1324 } while (!level_one_satisfied);
1325
1326 } // end if (_maintain_level_one)
1327
1328 // afterwards, we look at all ancestor items.
1329 // if there is a parent item with all its children
1330 // wanting to be coarsened, then the item is a candidate
1331 // for coarsening. If all children do not
1332 // want to be coarsened, then all need to have their
1333 // coarsening flag cleared.
1334 for (int level = (max_level); level >= 0; level--) {
1335 // iterate over cells level by level
1336 ENUMERATE_CELL (icell, m_mesh->ownLevelCells(level)) {
1337 const Cell cell = *icell;
1338 //ItemInternal* iitem = cell.internal();
1339 if (cell.isAncestor()) {
1340 // at this point the item has not been eliminated
1341 // as a candidate for coarsening
1342 bool is_a_candidate = true;
1343 bool found_remote_child = false;
1344
1345 for (Integer c = 0; c < cell.nbHChildren(); c++) {
1346 Cell child = cell.hChild(c);
1347 if (child.owner() != sid)
1348 found_remote_child = true;
1349 else if (!(child.itemBase().flags() & ItemFlags::II_Coarsen) || !child.isActive())
1350 is_a_candidate = false;
1351 }
1352
1353 if (!is_a_candidate && !found_remote_child) {
1355 for (Integer c = 0; c < cell.nbHChildren(); c++) {
1356 Cell child = cell.hChild(c);
1357 if (child.owner() != sid)
1358 continue;
1359 if (child.itemBase().flags() & ItemFlags::II_Coarsen) {
1360 level_one_satisfied = false;
1361 Int32 f = child.itemBase().flags();
1362 f &= ~ItemFlags::II_Coarsen;
1364 child.mutableItemBase().setFlags(f);
1365 }
1366 }
1367 }
1368 }
1369 }
1370 }
1371 if (!level_one_satisfied && _maintain_level_one)
1372 goto repeat;
1373
1374 // If all children of a parent are marked for coarsening
1375 // Then mark the parent so it can kill its children.
1376 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
1377 const Cell cell = *icell;
1378 //ItemInternal* iitem = cell.internal();
1379 if (cell.isAncestor()) {
1380 // Assume that all children are local and marked for
1381 // coarsening and thus look for a contradiction
1382 bool all_children_flagged_for_coarsening = true;
1383 bool found_remote_child = false;
1384
1385 for (Integer c = 0; c < cell.nbHChildren(); c++) {
1386 Cell child = cell.hChild(c);
1387 if (child.owner() != sid)
1388 found_remote_child = true;
1389 else if (!(child.itemBase().flags() & ItemFlags::II_Coarsen))
1390 all_children_flagged_for_coarsening = false;
1391 }
1392 Integer f = cell.itemBase().flags();
1393 f &= ~ItemFlags::II_CoarsenInactive;
1394 if (!found_remote_child && all_children_flagged_for_coarsening) {
1396 cell.mutableItemBase().setFlags(f);
1397 }
1398 else if (!found_remote_child) {
1400 cell.mutableItemBase().setFlags(f);
1401 }
1402 }
1403 }
1404
1405 debug() << "makeCoarseningCompatible() done";
1406
1407 // If we are not compatible on one processor, we are not compatible globally
1408 compatible_with_refinement = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, compatible_with_refinement);
1409
1410 return compatible_with_refinement;
1411}
1412
1413/*---------------------------------------------------------------------------*/
1414/*---------------------------------------------------------------------------*/
1415
1417_makeRefinementCompatible(const bool maintain_level_one)
1418{
1419
1420 debug() << "makeRefinementCompatible() begin";
1421
1422 bool _maintain_level_one = maintain_level_one;
1423
1424 // the level-one rule is the only condition implemented
1425 if (!maintain_level_one) {
1426 warning() << "Warning, level one rule is the only condition accepted now for AMR!";
1427 }
1428 else
1429 _maintain_level_one = m_face_level_mismatch_limit;
1430
1431 // unless we encounter a specific situation, the level-one rule
1432 // will be satisfied after running this loop just once
1433 bool level_one_satisfied = true;
1434
1435 // unless we encounter a specific situation, we will be compatible
1436 // with all chosen coarsening flags
1437 bool compatible_with_coarsening = true;
1438
1439 // this loop enforces the level-1 rule. We should only
1440 // execute it if the user actually wants level-1 to be satisfied!
1441 Integer sid = m_mesh->parallelMng()->commRank();
1442 if (_maintain_level_one) {
1443 do {
1444 level_one_satisfied = true;
1445 // iterate only over active cells
1446 ENUMERATE_CELL (icell, m_mesh->allActiveCells()) {
1447 const Cell cell = *icell;
1448 //ItemInternal* iitem = cell.internal();
1449 if (cell.itemBase().flags() & ItemFlags::II_Refine) { // If the item is active and the refinement flag is set
1450 const Int32 my_level = cell.level();
1451 bool refinable = true;
1452 //check if refinable
1453 for (Face face : cell.faces()) {
1454 if (face.nbCell() != 2)
1455 continue;
1456 Cell back_cell = face.backCell();
1457 Cell front_cell = face.frontCell();
1458
1459 // We choose the other cell on the side of the face
1460 Cell neighbor = (back_cell == cell) ? front_cell : back_cell;
1461 //ItemInternal* ineighbor = neighbor.internal();
1462 //if (ineighbor->isActive() && ineighbor->owner() == sid)// I have a neighbor here and it is active
1463 if (neighbor.isActive()) { // I have a neighbor here and it is active
1464 // Case 2: The neighbor is one level below mine.
1465 // The neighbor must be refined to satisfy
1466 // the level-1 rule, regardless of whether it
1467 // was originally marked for refinement. If it
1468 // was not already flagged, we must repeat
1469 // this process.
1470 Integer f = neighbor.itemBase().flags();
1471 if (((neighbor.level() + 1) == my_level) &&
1473 refinable = false;
1474 Integer my_f = cell.itemBase().flags();
1475 my_f &= ~ItemFlags::II_Refine;
1476 cell.mutableItemBase().setFlags(my_f);
1477 break;
1478 }
1479 }
1480 }
1481 if (refinable)
1482 for (Face face : cell.faces()) {
1483 if (face.nbCell() != 2)
1484 continue;
1485 Cell back_cell = face.backCell();
1486 Cell front_cell = face.frontCell();
1487
1488 // We choose the other cell on the side of the face
1489 Cell neighbor = (back_cell == cell) ? front_cell : back_cell;
1490 //ItemInternal* ineighbor = neighbor.internal();
1491 if (neighbor.isActive() && neighbor.owner() == sid) { // I have a neighbor here and it is active
1492
1493 // Case 1: The neighbor is at the same level as me.
1494 // 1a: The neighbor will be refined -> NO PROBLEM
1495 // 1b: The neighbor will not be refined -> NO PROBLEM
1496 // 1c: The neighbor already wants to be refined -> PROBLEM
1497 if (neighbor.level() == my_level) {
1498 Integer f = neighbor.itemBase().flags();
1499 if (f & ItemFlags::II_Coarsen) {
1500 f &= ~ItemFlags::II_Coarsen;
1502 neighbor.mutableItemBase().setFlags(f);
1503 if (neighbor.nbHParent() != 0) {
1505 }
1506 compatible_with_coarsening = false;
1507 level_one_satisfied = false;
1508 }
1509 }
1510
1511 // Case 2: The neighbor is one level below mine.
1512 // The neighbor must be refined to satisfy
1513 // the level-1 rule, regardless of whether it
1514 // was originally marked for refinement. If it
1515 // was not already flagged, we must repeat
1516 // this process.
1517
1518 else if ((neighbor.level() + 1) == my_level) {
1519 Integer f = neighbor.itemBase().flags();
1520 if (!(f & ItemFlags::II_Refine)) {
1521 f &= ~ItemFlags::II_Coarsen;
1523 neighbor.mutableItemBase().setFlags(f);
1524 if (neighbor.nbHParent() != 0) {
1526 }
1527 compatible_with_coarsening = false;
1528 level_one_satisfied = false;
1529 }
1530 }
1531#ifdef ARCANE_DEBUG
1532 // Check. We should never enter a
1533 // case where our neighbor is more than one level away.
1534
1535 else if ((neighbor.level() + 1) < my_level) {
1536 fatal() << "a neighbor is more than one level away";
1537 }
1538
1539 // Note that the only other possibility is that
1540 // the neighbor has already been refined, in this case it is not
1541 // active and we should never fall here.
1542
1543 else {
1544 fatal() << "serious problem: we should never get here";
1545 }
1546#endif
1547 }
1548 }
1549 }
1550 }
1551 } while (!level_one_satisfied);
1552 } // end if (_maintain_level_one)
1553
1554 // If we are not compatible on one processor, we are not compatible globally
1555 compatible_with_coarsening = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, compatible_with_coarsening);
1556
1557 debug() << "makeRefinementCompatible() done";
1558
1559 return compatible_with_coarsening;
1560}
1561
1562/*---------------------------------------------------------------------------*/
1563/*---------------------------------------------------------------------------*/
1564
1567{
1568 debug() << "[MeshRefinement::_coarsenItems] begin" << m_mesh->allNodes().size();
1569 // Flag indicating if this call actually changes the mesh
1570 bool mesh_changed = false;
1571
1572 // iterate over all cells
1573 // Int32UniqueArray cell_to_detach;
1574 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
1575 Cell cell = *icell;
1576 Cell iitem = cell;
1577 // active items flagged for coarsening will not be
1578 // removed until contraction via MeshRefinement::contract()
1579
1580 if (cell.itemBase().flags() & ItemFlags::II_Coarsen) {
1581 // Whoops? no level-0 item should be both active
1582 // and flagged for coarsening.
1583 ARCANE_ASSERT((cell.level() != 0), ("no level-0 element should be active and flagged for coarsening"));
1584
1585 // TODO Remove this item from any neighborhood list
1586 // pointing to it.
1587 // FIXME at IFP, we use the REMOVE_UID_ON_DETACH macro by default which deletes the CELL UID
1588 // in the cell_uid map, so we cannot use detachCell by default. For now
1589 // we use the MeshRefinement::contract() method after updating the variables
1590 // cell_to_detach.add(iitem->localId());
1591
1592 //cells_to_remove.add(cell);
1593 // TODO optimization of unused uids.
1594 // m_unused_items.push_back (uid);
1595
1596 // Do not destroy the item until MeshRefinement::contract()
1597 // m_mesh->modifier()->removeCells(iitem->localId());
1598
1599 // The mesh has certainly changed
1600 mesh_changed = true;
1601 }
1602 else if (cell.itemBase().flags() & ItemFlags::II_CoarsenInactive) {
1603 switch (cell.type()) {
1604 case IT_Quad4:
1605 m_item_refinement->coarsenOneCell<IT_Quad4>(iitem, getRefinementPattern<IT_Quad4>());
1606 break;
1607 case IT_Tetraedron4:
1608 m_item_refinement->coarsenOneCell<IT_Tetraedron4>(iitem, getRefinementPattern<IT_Tetraedron4>());
1609 break;
1610 case IT_Pyramid5:
1611 m_item_refinement->coarsenOneCell<IT_Pyramid5>(iitem, getRefinementPattern<IT_Pyramid5>());
1612 break;
1613 case IT_Pentaedron6:
1614 m_item_refinement->coarsenOneCell<IT_Pentaedron6>(iitem, getRefinementPattern<IT_Pentaedron6>());
1615 break;
1616 case IT_Hexaedron8:
1617 m_item_refinement->coarsenOneCell<IT_Hexaedron8>(iitem, getRefinementPattern<IT_Hexaedron8>());
1618 break;
1619 case IT_HemiHexa7:
1620 m_item_refinement->coarsenOneCell<IT_HemiHexa7>(iitem, getRefinementPattern<IT_HemiHexa7>());
1621 break;
1622 case IT_HemiHexa6:
1623 m_item_refinement->coarsenOneCell<IT_HemiHexa6>(iitem, getRefinementPattern<IT_HemiHexa6>());
1624 break;
1625 case IT_HemiHexa5:
1626 m_item_refinement->coarsenOneCell<IT_HemiHexa5>(iitem, getRefinementPattern<IT_HemiHexa5>());
1627 break;
1628 case IT_AntiWedgeLeft6:
1629 m_item_refinement->coarsenOneCell<IT_AntiWedgeLeft6>(iitem, getRefinementPattern<IT_AntiWedgeLeft6>());
1630 break;
1631 case IT_AntiWedgeRight6:
1632 m_item_refinement->coarsenOneCell<IT_AntiWedgeRight6>(iitem, getRefinementPattern<IT_AntiWedgeRight6>());
1633 break;
1634 case IT_DiTetra5:
1635 m_item_refinement->coarsenOneCell<IT_DiTetra5>(iitem, getRefinementPattern<IT_DiTetra5>());
1636 break;
1637 default:
1638 ARCANE_FATAL("Not supported refinement Item Type type={0}", iitem.type());
1639 }
1640 ARCANE_ASSERT(cell.isActive(), ("cell_active failed"));
1641
1642 // The mesh has certainly changed
1643 mesh_changed = true;
1644 }
1645 }
1646 // TODO
1647 // m_mesh->modifier->detachCells(cell_to_detach);
1648
1649 // If the mesh changed on one processor, then it changed globally
1650 mesh_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, mesh_changed);
1651 // And maybe we need to update the entities reflecting the change
1652 //if (mesh_changed)
1653 // \todo compact and update max_uids in parallel
1654
1655 // if a cell is derefined elsewhere, the nodes attached to this cell
1656 // must be updated. This is handled in endUpdate()
1657
1658 debug() << "[MeshRefinement::_coarsenItems()] done " << m_mesh->allNodes().size();
1659
1660 return mesh_changed;
1661}
1662
1663/*---------------------------------------------------------------------------*/
1664/*---------------------------------------------------------------------------*/
1665
1667_refineItems(Int64Array& cell_to_refine_uids)
1668{
1669 // Updating m_node_finder, m_face_finder will allow the mesh
1670 // to be globally consistent (uids consistency).
1671 debug() << "[MeshRefinement::_refineItems]" << m_mesh->allNodes().size();
1672#ifdef ARCANE_DEBUG
1673 m_node_finder.check();
1674 m_face_finder.check();
1675#endif
1676 CHECKPERF(m_perf_counter.start(PerfCounter::REFINE))
1677 m_face_finder.clearNewUids();
1678 // Iterate over the items, count the items
1679 // flagged for refinement.
1680 //Integer nb_cell_flagged = 0;
1681 UniqueArray<Cell> cell_to_refine_internals;
1682 ENUMERATE_CELL (icell, m_mesh->ownCells()) {
1683 Cell cell = *icell;
1684 if (cell.itemBase().flags() & ItemFlags::II_Refine) {
1685 cell_to_refine_uids.add(cell.uniqueId());
1686 cell_to_refine_internals.add(cell);
1687 }
1688 }
1689 debug() << "[MeshRefinement::_refineItems] " << cell_to_refine_uids.size() << " flagged cells for refinement";
1690
1691 // Build a local vector of the marked items
1692 // for refinement.
1693 /*
1694 local_copy_of_cells.reserve(nb_cell_flagged);
1695
1696 ENUMERATE_CELL(icell,m_mesh->ownCells()){
1697 Cell cell = *icell;
1698 ItemInternal* iitem = cell.internal();
1699 if(iitem->flags() & ItemFlags::II_Refine)
1700 local_copy_of_cells.add(iitem);
1701 }
1702 */
1703 // Now, iterate over the local copies and refine each item.
1704 const Int32 i_size = cell_to_refine_internals.size();
1705 for (Integer e = 0; e != i_size; ++e) {
1706 Cell iitem = cell_to_refine_internals[e];
1707 //debug()<<"\t[MeshRefinement::_refineItems] focus on cell "<<iitem->uniqueId();
1708 switch (iitem.type()) {
1709 case IT_Quad4:
1710 m_item_refinement->refineOneCell<IT_Quad4>(iitem, *this);
1711 break;
1712 case IT_Tetraedron4:
1713 m_item_refinement->refineOneCell<IT_Tetraedron4>(iitem, *this);
1714 break;
1715 case IT_Pyramid5:
1716 m_item_refinement->refineOneCell<IT_Pyramid5>(iitem, *this);
1717 break;
1718 case IT_Pentaedron6:
1719 m_item_refinement->refineOneCell<IT_Pentaedron6>(iitem, *this);
1720 break;
1721 case IT_Hexaedron8:
1722 m_item_refinement->refineOneCell<IT_Hexaedron8>(iitem, *this);
1723 break;
1724 case IT_HemiHexa7:
1725 m_item_refinement->refineOneCell<IT_HemiHexa7>(iitem, *this);
1726 break;
1727 case IT_HemiHexa6:
1728 m_item_refinement->refineOneCell<IT_HemiHexa6>(iitem, *this);
1729 break;
1730 case IT_HemiHexa5:
1731 m_item_refinement->refineOneCell<IT_HemiHexa5>(iitem, *this);
1732 break;
1733 case IT_AntiWedgeLeft6:
1734 m_item_refinement->refineOneCell<IT_AntiWedgeLeft6>(iitem, *this);
1735 break;
1736 case IT_AntiWedgeRight6:
1737 m_item_refinement->refineOneCell<IT_AntiWedgeRight6>(iitem, *this);
1738 break;
1739 case IT_DiTetra5:
1740 m_item_refinement->refineOneCell<IT_DiTetra5>(iitem, *this);
1741 break;
1742 default:
1743 ARCANE_FATAL("Not supported refinement Item Type type={0}", iitem.type());
1744 }
1745 }
1746
1747 // The mesh changes if items are refined
1748 bool mesh_changed = !(i_size == 0);
1749
1750 // If the mesh changes on one processor, it changes globally
1751 mesh_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, mesh_changed);
1752
1753 // And we need to update the number of ids
1754 if (mesh_changed) {
1755 for (Integer e = 0; e != i_size; ++e) {
1756 Cell i_hParent_cell = cell_to_refine_internals[e];
1757 populateBackFrontCellsFromParentFaces(i_hParent_cell);
1758 }
1759 }
1760 CHECKPERF(m_perf_counter.stop(PerfCounter::REFINE))
1761 if (mesh_changed && m_mesh->parallelMng()->isParallel()) {
1762 CHECKPERF(m_perf_counter.start(PerfCounter::PGCONSIST))
1763#ifdef ARCANE_DEBUG
1764 m_node_finder.check2();
1765 m_face_finder.check2();
1766#endif
1767
1768 // Nodes and faces parallel consistency
1769 m_parallel_amr_consistency->makeNewItemsConsistent(m_node_finder, m_face_finder);
1770 CHECKPERF(m_perf_counter.stop(PerfCounter::PGCONSIST))
1771 }
1772
1773 debug() << "[MeshRefinement::_refineItems] done" << m_mesh->allNodes().size();
1774
1775 return mesh_changed;
1776}
1777
1778/*---------------------------------------------------------------------------*/
1779/*---------------------------------------------------------------------------*/
1780
1783{
1784 // Cleanup of refinement flags from a previous step
1785 ENUMERATE_CELL (icell, m_mesh->allCells()) {
1786 Cell cell = *icell;
1787 auto mutable_cell = cell.mutableItemBase();
1788 Integer f = mutable_cell.flags();
1789 if (cell.isActive()) {
1791 mutable_cell.setFlags(f);
1792 }
1793 else {
1795 mutable_cell.setFlags(f);
1796 }
1797 // This could be left from the last step
1798 if (f & ItemFlags::II_JustRefined) {
1799 f &= ~ItemFlags::II_JustRefined;
1801 mutable_cell.setFlags(f);
1802 }
1804 f &= ~ItemFlags::II_JustCoarsened;
1806 mutable_cell.setFlags(f);
1807 }
1808 if (f & ItemFlags::II_JustAdded) {
1809 f &= ~ItemFlags::II_JustAdded;
1811 mutable_cell.setFlags(f);
1812 }
1814 f &= ~ItemFlags::II_CoarsenInactive;
1816 mutable_cell.setFlags(f);
1817 }
1818 }
1819}
1820
1821/*---------------------------------------------------------------------------*/
1822/*---------------------------------------------------------------------------*/
1823
1825_contract()
1826{
1828 ItemInternalMap& cells_map = mesh->cellsMap();
1829
1830 // Flag indicating if this call actually changes the mesh
1831 bool mesh_changed = false;
1832
1833 if (arcaneIsDebug()) {
1834 cells_map.eachItem([&](impl::ItemBase item) {
1835 if (item.isOwn())
1836 // a cell is either active, subactive, or ancestor
1837 ARCANE_ASSERT((item.isActive() || item.isSubactive() || item.isAncestor()), (" "));
1838 });
1839 }
1840
1841 //
1842 std::set<Int32> cells_to_remove_set;
1843 UniqueArray<ItemInternal*> parent_cells;
1844
1845 cells_map.eachItem([&](impl::ItemBase iitem) {
1846 if (!iitem.isOwn())
1847 return;
1848
1849 // suppression of subactive cells
1850 if (iitem.isSubactive()) {
1851 // no level 0 cell should be subactive.
1852 ARCANE_ASSERT((iitem.nbHParent() != 0), (""));
1853 cells_to_remove_set.insert(iitem.localId());
1854 // inform the client of the mesh change
1855 mesh_changed = true;
1856 }
1857 else {
1858 // Compression of active cells
1859 if (iitem.isActive()) {
1860 bool active_parent = false;
1861 for (Integer c = 0; c < iitem.nbHChildren(); c++) {
1862 impl::ItemBase ichild = iitem.hChildBase(c);
1863 if (!ichild.isSuppressed()) {
1864 //debug() << "[\tMeshRefinement::contract]PARENT UID=" << iitem->uniqueId() << " " << iitem->owner() << " "
1865 // << iitem->level();
1866 cells_to_remove_set.insert(ichild.localId());
1867 //debug() << "[\tMeshRefinement::contract]CHILD UID=" << ichild->uniqueId() << " " << ichild->owner();
1868 active_parent = true;
1869 }
1870 }
1871 if (active_parent) {
1872 parent_cells.add(iitem._itemInternal());
1873 ARCANE_ASSERT((iitem.flags() & ItemFlags::II_JustCoarsened), ("Incoherent JustCoarsened flag"));
1874 }
1875 // inform the client of the mesh change
1876 mesh_changed = true;
1877 }
1878 else {
1879 ARCANE_ASSERT((iitem.isAncestor()), (""));
1880 }
1881 }
1882 });
1883 //
1884 UniqueArray<Int32> cell_lids(arcaneCheckArraySize(cells_to_remove_set.size()));
1885 std::copy(std::begin(cells_to_remove_set), std::end(cells_to_remove_set), std::begin(cell_lids));
1886
1887 if (m_mesh->parallelMng()->isParallel()) {
1888 this->_makeFlagParallelConsistent2();
1889 this->_removeGhostChildren();
1890 this->_updateItemOwner(cell_lids);
1891 m_mesh->parallelMng()->barrier();
1892 }
1893 if (cell_lids.size() > 0) {
1894 this->_upscaleData(parent_cells);
1895 _invalidate(parent_cells);
1896 //_updateItemOwner(cells_local_id);
1897 m_mesh->modifier()->removeCells(cell_lids, false);
1898 const Integer ps = parent_cells.size();
1899 for (Integer i = 0; i < ps; i++)
1901 }
1902 else
1903 mesh_changed = false;
1904
1905 return mesh_changed;
1906}
1907
1908/*---------------------------------------------------------------------------*/
1909/*---------------------------------------------------------------------------*/
1910
1911void MeshRefinement::
1912registerCallBack(IAMRTransportFunctor* f)
1913{
1914 m_call_back_mng->registerCallBack(f);
1915}
1916
1917/*---------------------------------------------------------------------------*/
1918/*---------------------------------------------------------------------------*/
1919
1920void MeshRefinement::
1921unRegisterCallBack(IAMRTransportFunctor* f)
1922{
1923 m_call_back_mng->unregisterCallBack(f);
1924}
1925
1926/*---------------------------------------------------------------------------*/
1927/*---------------------------------------------------------------------------*/
1928
1930_interpolateData(const Int64Array& cells_to_refine)
1931{
1932 const Int32 nb_cells = cells_to_refine.size();
1933 Int32UniqueArray lids(nb_cells);
1934 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids.view(), cells_to_refine.constView());
1935 CellInfoListView internals(m_mesh->cellFamily());
1936
1937 UniqueArray<ItemInternal*> cells_to_refine_internals(nb_cells);
1938 for (Integer i = 0; i < nb_cells; i++) {
1939 cells_to_refine_internals[i] = ItemCompatibility::_itemInternal(internals[lids[i]]);
1940 }
1941 m_call_back_mng->callCallBacks(cells_to_refine_internals, Prolongation);
1942 _update(cells_to_refine_internals);
1943}
1944
1945void MeshRefinement::
1946_update(ArrayView<Int64> cells_to_refine_uids)
1947{
1948 CHECKPERF(m_perf_counter.start(PerfCounter::UPDATEMAP))
1949 const Int32 nb_cells = cells_to_refine_uids.size();
1950 Int32UniqueArray lids(nb_cells);
1951 m_mesh->cellFamily()->itemsUniqueIdToLocalId(lids, cells_to_refine_uids);
1952 CellInfoListView internals(m_mesh->cellFamily());
1953 UniqueArray<ItemInternal*> cells_to_refine(nb_cells);
1954 for (Integer i = 0; i < nb_cells; i++) {
1955 cells_to_refine[i] = ItemCompatibility::_itemInternal(internals[lids[i]]);
1956 }
1957 m_node_finder.updateData(cells_to_refine);
1958 m_face_finder.updateData(cells_to_refine);
1959 _updateMaxUid(cells_to_refine);
1960 m_item_refinement->updateChildHMin(cells_to_refine);
1961 //m_face_finder.updateFaceCenter(cells_to_refine);
1962 CHECKPERF(m_perf_counter.stop(PerfCounter::UPDATEMAP))
1963}
1964
1965void MeshRefinement::
1966_update(ArrayView<ItemInternal*> cells_to_refine)
1967{
1968 CHECKPERF(m_perf_counter.start(PerfCounter::UPDATEMAP))
1969 m_node_finder.updateData(cells_to_refine);
1970 m_face_finder.updateData(cells_to_refine);
1971 _updateMaxUid(cells_to_refine);
1972 m_item_refinement->updateChildHMin(cells_to_refine);
1973 //m_face_finder.updateFaceCenter(cells_to_refine);
1974 CHECKPERF(m_perf_counter.stop(PerfCounter::UPDATEMAP))
1975}
1976
1977void MeshRefinement::
1978_invalidate(ArrayView<ItemInternal*> coarsen_cells)
1979{
1980 CHECKPERF(m_perf_counter.start(PerfCounter::CLEAR))
1981 m_node_finder.clearData(coarsen_cells);
1982 m_face_finder.clearData(coarsen_cells);
1983 CHECKPERF(m_perf_counter.stop(PerfCounter::CLEAR))
1984}
1985
1986/*---------------------------------------------------------------------------*/
1987/*---------------------------------------------------------------------------*/
1988
1991{
1992 m_call_back_mng->callCallBacks(parent_cells, Restriction);
1993}
1994
1995/*---------------------------------------------------------------------------*/
1996/*---------------------------------------------------------------------------*/
1997
1998void MeshRefinement::
1999_updateItemOwner(Int32ArrayView cell_to_remove_lids)
2000{
2001 IItemFamily* cell_family = m_mesh->cellFamily();
2002 CellInfoListView cells_list(cell_family);
2003
2006
2007 const Integer sid = m_mesh->parallelMng()->commRank();
2008
2009 bool node_owner_changed = false;
2010 bool face_owner_changed = false;
2011
2012 std::map<Int32, bool> marker;
2013
2014 for (Integer i = 0, is = cell_to_remove_lids.size(); i < is; i++) {
2015 Cell item = cells_list[cell_to_remove_lids[i]];
2016 for (Node node : item.nodes()) {
2017
2018 if (marker.find(node.localId()) != marker.end())
2019 continue;
2020 else
2021 marker[node.localId()] = true;
2022
2023 //debug() << "NODE " << FullItemPrinter(node);
2024 //const Int32 owner = node->owner();
2025 bool is_ok = false;
2026 Integer count = 0;
2027 const Integer node_cs = node.cells().size();
2028 for (Cell cell : node.cells()) {
2029 if (cell_to_remove_lids.contains(cell.localId())) {
2030 count++;
2031 if (count == node_cs)
2032 is_ok = true;
2033 continue;
2034 }
2035 // SDC : this condition contributes to desynchronize node owners...
2036 // if (cell->owner() == owner)
2037 // {
2038 // is_ok = true;
2039 // break;
2040 // }
2041 }
2042 if (!is_ok) {
2043 Cell cell;
2044 for (Cell cell2 : node.cells()) {
2045 if (cell_to_remove_lids.contains(cell2.localId()))
2046 continue;
2047 if (cell.null() || cell2.uniqueId() < cell.uniqueId())
2048 cell = cell2;
2049 }
2050 if (cell.null())
2051 ARCANE_FATAL("Inconsistent null cell owner reference");
2052 const Int32 new_owner = cell.owner();
2053 nodes_owner[node] = new_owner;
2054 node.mutableItemBase().setOwner(new_owner, sid);
2055 //debug() << " NODE CHANGED OWNER " << node->uniqueId();
2056 node_owner_changed = true;
2057 }
2058 }
2059 for (Face face : item.faces()) {
2060 if (face.nbCell() != 2)
2061 continue;
2062 const Int32 owner = face.owner();
2063 bool is_ok = false;
2064 for (Cell cell : face.cells()) {
2065 if ((item.uniqueId() == cell.uniqueId()) || !(item.level() == cell.level()))
2066 continue;
2067 if (cell.owner() == owner) {
2068 is_ok = true;
2069 break;
2070 }
2071 }
2072 if (!is_ok) {
2073 for (Cell cell2 : face.cells()) {
2074 if (item.uniqueId() == cell2.uniqueId())
2075 continue;
2076 faces_owner[face] = cell2.owner();
2077 face.mutableItemBase().setOwner(cell2.owner(), sid);
2078 //debug() << " FACE CHANGED OWNER " << FullItemPrinter(face);
2079 face_owner_changed = true;
2080 }
2081 }
2082 }
2083 }
2084
2085 node_owner_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, node_owner_changed);
2086 if (node_owner_changed) {
2087 // nodes_owner.synchronize(); // SDC Especially not the sync is KO at this moment (unrefined/de-refined ghosts)
2088 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2089 m_mesh->nodeFamily()->endUpdate();
2090 }
2091 face_owner_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, face_owner_changed);
2092 if (face_owner_changed) {
2093 faces_owner.synchronize();
2094 m_mesh->faceFamily()->notifyItemsOwnerChanged();
2095 m_mesh->faceFamily()->endUpdate();
2096 }
2097}
2098
2099/*---------------------------------------------------------------------------*/
2100/*---------------------------------------------------------------------------*/
2101
2102void MeshRefinement::
2103_updateItemOwner2()
2104{
2105 // It is necessary that every sub-item is a neighboring cell with the same owner
2106 VariableItemInt32& nodes_owner(m_mesh->nodeFamily()->itemsNewOwner());
2107
2108 NodeGroup own_nodes = m_mesh->ownNodes();
2109 bool owner_changed = false;
2110 ENUMERATE_NODE (inode, own_nodes) {
2111 Node node = (*inode);
2112 Int32 owner = node.owner();
2113 bool is_ok = false;
2114 for (Cell cell : node.cells()) {
2115 if (cell.owner() == owner) {
2116 is_ok = true;
2117 break;
2118 }
2119 }
2120 if (!is_ok) {
2121 Cell cell;
2122 for (Cell cell2 : node.cells()) {
2123 if (cell.null() || cell2.uniqueId() < cell.uniqueId())
2124 cell = cell2;
2125 }
2126 ARCANE_ASSERT((!cell.null()), ("Inconsistent null cell owner reference"));
2127 nodes_owner[node] = cell.owner();
2128 owner_changed = true;
2129 }
2130 }
2131 owner_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, owner_changed);
2132 if (owner_changed) {
2133 nodes_owner.synchronize();
2134 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2135 m_mesh->nodeFamily()->endUpdate();
2136 }
2137
2138 // It is necessary that every sub-item is a neighboring cell with the same owner
2139 VariableItemInt32& faces_owner(m_mesh->faceFamily()->itemsNewOwner());
2140
2141 FaceGroup own_faces = m_mesh->ownFaces();
2142 owner_changed = false;
2143 ENUMERATE_FACE (iface, own_faces) {
2144 Face face = (*iface);
2145 Int32 owner = face.owner();
2146 bool is_ok = false;
2147 for (Cell cell : face.cells()) {
2148 if (cell.owner() == owner) {
2149 is_ok = true;
2150 break;
2151 }
2152 }
2153 if (!is_ok) {
2154 if (face.nbCell() == 2)
2155 fatal() << "Face" << ItemPrinter(face) << " has a different owner with respect to Back/Front Cells";
2156
2157 faces_owner[face] = face.boundaryCell().owner();
2158 owner_changed = true;
2159 }
2160 }
2161 owner_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMin, owner_changed);
2162 if (owner_changed) {
2163 faces_owner.synchronize();
2164 m_mesh->faceFamily()->notifyItemsOwnerChanged();
2165 m_mesh->faceFamily()->endUpdate();
2166 }
2167}
2168/*---------------------------------------------------------------------------*/
2169/*---------------------------------------------------------------------------*/
2170
2171bool MeshRefinement::
2172_removeGhostChildren()
2173{
2174 const Integer sid = m_mesh->parallelMng()->commRank();
2175 DynamicMesh* mesh = m_mesh;
2176 ItemInternalMap& cells_map = mesh->cellsMap();
2177
2178 // Removal of meshes
2179 Int32UniqueArray cells_to_remove;
2180 cells_to_remove.reserve(1000);
2181 UniqueArray<ItemInternal*> parent_cells;
2182 parent_cells.reserve(1000);
2183
2184 cells_map.eachItem([&](impl::ItemBase cell) {
2185 if (cell.owner() == sid)
2186 return;
2187
2188 if (cell.flags() & ItemFlags::II_JustCoarsened) {
2189 for (Integer c = 0, cs = cell.nbHChildren(); c < cs; c++) {
2190 cells_to_remove.add(cell.hChildBase(c).localId());
2191 }
2192 parent_cells.add(cell._itemInternal());
2193 }
2194 });
2195
2196 _invalidate(parent_cells);
2197
2198 // Before removal, update the owners of isolated Nodes/Faces
2199 _updateItemOwner(cells_to_remove);
2200 //info() << "Number of cells to remove: " << cells_to_remove.size();
2201 m_mesh->modifier()->removeCells(cells_to_remove, false);
2202 for (Integer i = 0, ps = parent_cells.size(); i < ps; i++)
2204
2205 return cells_to_remove.size() > 0;
2206}
2207
2208/*---------------------------------------------------------------------------*/
2209/*---------------------------------------------------------------------------*/
2210
2211void MeshRefinement::
2212populateBackFrontCellsFromParentFaces(Cell parent_cell)
2213{
2214 switch (parent_cell.type()) {
2215 case IT_Quad4:
2217 break;
2218 case IT_Tetraedron4:
2220 break;
2221 case IT_Pyramid5:
2223 break;
2224 case IT_Pentaedron6:
2226 break;
2227 case IT_Hexaedron8:
2229 break;
2230 case IT_HemiHexa7:
2232 break;
2233 case IT_HemiHexa6:
2235 break;
2236 case IT_HemiHexa5:
2238 break;
2239 case IT_AntiWedgeLeft6:
2241 break;
2242 case IT_AntiWedgeRight6:
2244 break;
2245 case IT_DiTetra5:
2247 break;
2248 default:
2249 ARCANE_FATAL("Not supported refinement Item Type type={0}", parent_cell.type());
2250 }
2251}
2252/*---------------------------------------------------------------------------*/
2253/*---------------------------------------------------------------------------*/
2254
2255template <int typeID> void MeshRefinement::
2257{
2258 Integer nb_children = parent_cell.nbHChildren();
2260 for (Integer c = 0; c < nb_children; c++) {
2261 Cell child = parent_cell.hChild(c);
2262 Integer nb_child_faces = child.nbFace();
2263 for (Integer fc = 0; fc < nb_child_faces; fc++) {
2264 if (rp.face_mapping_topo(c, fc) == 0)
2265 continue;
2266 const Integer f = rp.face_mapping(c, fc);
2267 Face face = parent_cell.face(f);
2268 Integer nb_cell_face = face.nbCell();
2269 if (nb_cell_face == 1)
2270 continue;
2271 Face subface = child.face(fc);
2272 Integer nb_cell_subface = subface.nbCell();
2273 if (nb_cell_subface == 1) {
2274 m_face_family->addBackFrontCellsFromParentFace(subface, face);
2275 }
2276 else {
2277 if (face.backCell().isOwn() != face.frontCell().isOwn()) {
2278 m_face_family->replaceBackFrontCellsFromParentFace(child, subface, parent_cell, face);
2279 }
2280 else {
2281 if (!face.backCell().isOwn() && !face.frontCell().isOwn()) {
2282 m_face_family->replaceBackFrontCellsFromParentFace(child, subface, parent_cell, face);
2283 }
2284 }
2285 }
2286 ARCANE_ASSERT((subface.backCell() != parent_cell && subface.frontCell() != parent_cell),
2287 ("back front cells error"));
2288 }
2289 }
2290}
2291
2292/*---------------------------------------------------------------------------*/
2293/*---------------------------------------------------------------------------*/
2294
2297{
2298 ARCANE_ASSERT((parent_cell.isActive()), (""));
2299 Integer nb_faces = parent_cell.nbFace();
2300 for (Integer f = 0; f < nb_faces; f++) {
2301 Face face = parent_cell.face(f);
2302 Integer nb_cell_face = face.nbCell();
2303 if (nb_cell_face == 1)
2304 continue;
2305 Cell neighbor_cell = (face.cell(0) == parent_cell) ? face.cell(1) : face.cell(0);
2306 if (neighbor_cell.isActive())
2307 continue;
2308 switch (neighbor_cell.type()) {
2309 case IT_Quad4:
2310 _populateBackFrontCellsFromChildrenFaces<IT_Quad4>(face, parent_cell, neighbor_cell);
2311 break;
2312 case IT_Tetraedron4:
2313 _populateBackFrontCellsFromChildrenFaces<IT_Tetraedron4>(face, parent_cell, neighbor_cell);
2314 break;
2315 case IT_Pyramid5:
2316 _populateBackFrontCellsFromChildrenFaces<IT_Pyramid5>(face, parent_cell, neighbor_cell);
2317 break;
2318 case IT_Pentaedron6:
2319 _populateBackFrontCellsFromChildrenFaces<IT_Pentaedron6>(face, parent_cell, neighbor_cell);
2320 break;
2321 case IT_Hexaedron8:
2322 _populateBackFrontCellsFromChildrenFaces<IT_Hexaedron8>(face, parent_cell, neighbor_cell);
2323 break;
2324 case IT_HemiHexa7:
2325 _populateBackFrontCellsFromChildrenFaces<IT_HemiHexa7>(face, parent_cell, neighbor_cell);
2326 break;
2327 case IT_HemiHexa6:
2328 _populateBackFrontCellsFromChildrenFaces<IT_HemiHexa6>(face, parent_cell, neighbor_cell);
2329 break;
2330 case IT_HemiHexa5:
2331 _populateBackFrontCellsFromChildrenFaces<IT_HemiHexa5>(face, parent_cell, neighbor_cell);
2332 break;
2333 case IT_AntiWedgeLeft6:
2334 _populateBackFrontCellsFromChildrenFaces<IT_AntiWedgeLeft6>(face, parent_cell, neighbor_cell);
2335 break;
2336 case IT_AntiWedgeRight6:
2337 _populateBackFrontCellsFromChildrenFaces<IT_AntiWedgeRight6>(face, parent_cell, neighbor_cell);
2338 break;
2339 case IT_DiTetra5:
2340 _populateBackFrontCellsFromChildrenFaces<IT_DiTetra5>(face, parent_cell, neighbor_cell);
2341 break;
2342 default:
2343 ARCANE_FATAL("Not supported refinement Item Type type={0}", neighbor_cell.type());
2344 }
2345 }
2346}
2347
2348/*---------------------------------------------------------------------------*/
2349/*---------------------------------------------------------------------------*/
2350
2351template <int typeID> void MeshRefinement::
2352_populateBackFrontCellsFromChildrenFaces(Face face, Cell parent_cell,
2353 Cell neighbor_cell)
2354{
2356 for (Integer f = 0; f < neighbor_cell.nbFace(); f++) {
2357 if (neighbor_cell.face(f) == face) {
2358 Integer nb_children = neighbor_cell.nbHChildren();
2359 for (Integer c = 0; c < nb_children; c++) {
2360 Cell child = neighbor_cell.hChild(c);
2361 Integer nb_child_faces = child.nbFace();
2362 for (Integer fc = 0; fc < nb_child_faces; fc++) {
2363 if (f == rp.face_mapping(c, fc) && (rp.face_mapping_topo(c, fc))) {
2364 Face subface = child.face(fc);
2365 if (subface.itemBase().flags() & ItemFlags::II_HasBackCell) {
2366 m_face_family->addFrontCellToFace(subface, parent_cell);
2367 }
2368 else if (subface.itemBase().flags() & ItemFlags::II_HasFrontCell) {
2369 m_face_family->addBackCellToFace(subface, parent_cell);
2370 }
2371 ARCANE_ASSERT((subface.backCell() != subface.frontCell()), ("back front cells error"));
2372 }
2373 }
2374 }
2375 break;
2376 }
2377 }
2378}
2379
2380/*---------------------------------------------------------------------------*/
2381/*---------------------------------------------------------------------------*/
2382
2383void MeshRefinement::
2384_checkOwner(const String& msg)
2385{
2386 // This method has been introduced to patch node owner desynchronization occuring in IFPEN applications
2387 info() << "----CheckOwner in " << msg;
2388 VariableNodeInt32 syncvariable(VariableBuildInfo(m_mesh, "SyncVarNodeOwnerContract"));
2389 syncvariable.fill(-1);
2390 bool has_owner_changed = false;
2391 ENUMERATE_NODE (inode, m_mesh->ownNodes())
2392 syncvariable[inode] = inode->owner();
2393 VariableNodeInt32 syncvariable_copy(VariableBuildInfo(m_mesh, "SyncVarNodeOwnerContractCopy"));
2394 syncvariable_copy.copy(syncvariable);
2395 syncvariable.synchronize();
2396 ItemVector desync_nodes(m_mesh->nodeFamily());
2397 ENUMERATE_NODE (inode, m_mesh->allNodes()) {
2398 if (syncvariable[inode] == -1) {
2399 debug(Trace::Highest) << "----- Inconsistent owner (ghost everywhere) for node with uid : "
2400 << inode->uniqueId().asInt64();
2401 desync_nodes.addItem(*inode);
2402 has_owner_changed = true;
2403 }
2404 if (inode->isOwn() && (syncvariable_copy[inode] != syncvariable[inode])) {
2405 debug(Trace::Highest) << "----- Inconsistent owner (own everywhere) for node with uid : "
2406 << inode->uniqueId().asInt64();
2407 desync_nodes.addItem(*inode);
2408 has_owner_changed = true;
2409 }
2410 }
2411 // Find a new owner different from the historical one stored in node_owner_memory
2412 // Indeed the desync occured while changing from this historical owner to avoid an isolated item
2413 // Going back to this owner would make this problem of isolated owner appear again
2414 // 1-Get the owners of all desync nodes on every process
2415 // 1.1 Synchronize desync_nodes : if a node is desynchronized in a domain, all the domains must do the correction
2416 Int64UniqueArray desync_node_uids(desync_nodes.size());
2417 ENUMERATE_NODE (inode, desync_nodes) {
2418 desync_node_uids[inode.index()] = inode->uniqueId().asInt64();
2419 }
2420 Int64UniqueArray desync_node_uids_gather;
2421 m_mesh->parallelMng()->allGatherVariable(desync_node_uids.view(), desync_node_uids_gather);
2422 Int32UniqueArray desync_node_lids_gather(desync_node_uids_gather.size());
2423 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(desync_node_lids_gather, desync_node_uids_gather, false);
2424 for (auto lid : desync_node_lids_gather) {
2425 if (lid == NULL_ITEM_LOCAL_ID)
2426 continue;
2427 if (std::find(desync_nodes.viewAsArray().begin(), desync_nodes.viewAsArray().end(), lid) == desync_nodes.viewAsArray().end()) {
2428 desync_nodes.add(lid);
2429 }
2430 }
2431 // 1.2 Exchange the owners of the desynchronized nodes
2432 // each process fill an array [node1_uid, node1_owner,...nodei_uid, nodei_owner,...]
2433 Int64UniqueArray desync_node_owners(2 * desync_nodes.size());
2434 ENUMERATE_NODE (inode, desync_nodes) {
2435 desync_node_owners[2 * inode.index()] = inode->uniqueId().asInt64();
2436 desync_node_owners[2 * inode.index() + 1] = inode->owner();
2437 }
2438 // 1.2 gather this array on every process
2439 Int64UniqueArray desync_node_owners_gather;
2440 m_mesh->parallelMng()->allGatherVariable(desync_node_owners.view(), desync_node_owners_gather);
2441 // 1.3 store the information in a map <uid, Array[owner] >
2442 std::map<Int64, Int32SharedArray> uid_owners_map;
2443 for (Integer node_index = 0; node_index + 1 < desync_node_owners_gather.size();) {
2444 uid_owners_map[desync_node_owners_gather[node_index]].add((Int32)desync_node_owners_gather[node_index + 1]);
2445 desync_node_uids_gather.add(desync_node_owners_gather[node_index]);
2446 node_index += 2;
2447 }
2448 // 2 choose the unique owner of the desynchronized nodes :
2449 // Choose the minimum owner (same choice on each proc) different from the historical owner
2450 Integer new_owner = m_mesh->parallelMng()->commSize() + 1;
2451 ENUMERATE_NODE (inode, desync_nodes) {
2452 for (auto owner : uid_owners_map[inode->uniqueId().asInt64()]) {
2453 if (owner < new_owner && owner != m_node_owner_memory[inode])
2454 new_owner = owner;
2455 }
2456 debug(Trace::Highest) << "------ Change owner for node " << inode->uniqueId() << " from " << inode->owner() << " to " << new_owner;
2457 inode->mutableItemBase().setOwner(new_owner, m_mesh->parallelMng()->commRank());
2458 new_owner = m_mesh->parallelMng()->commSize() + 1;
2459 }
2460 // Update family if owners have changed
2461 bool p_has_owner_changed = m_mesh->parallelMng()->reduce(Parallel::ReduceMax, has_owner_changed);
2462 if (p_has_owner_changed) {
2463 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2464 m_mesh->nodeFamily()->endUpdate();
2465 m_mesh->nodeFamily()->computeSynchronizeInfos();
2466 }
2467 // update node memory owner
2468 ENUMERATE_NODE (inode, m_mesh->allNodes())
2469 m_node_owner_memory[inode] = inode->owner();
2470}
2471
2472/*---------------------------------------------------------------------------*/
2473/*---------------------------------------------------------------------------*/
2474
2476getMesh() const
2477{
2478 return m_mesh;
2479}
2480
2481/*---------------------------------------------------------------------------*/
2482/*---------------------------------------------------------------------------*/
2483
2485getMesh()
2486{
2487 return m_mesh;
2488}
2489
2490/*---------------------------------------------------------------------------*/
2491/*---------------------------------------------------------------------------*/
2492
2493} // End namespace Arcane::mesh
2494
2495/*---------------------------------------------------------------------------*/
2496/*---------------------------------------------------------------------------*/
#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.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Déclarations des types utilisés dans Arcane.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
Tableau d'items de types quelconques.
ConstArrayView< T > constView() const
Vue constante sur ce tableau.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
ArrayView< T > view() const
Vue mutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue sur les informations des mailles.
Classe pour convertir un CellLocalId vers une maille.
Maille d'un maillage.
Definition Item.h:1214
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1298
Int32 nbHChildren() const
Nombre d'enfants pour l'AMR.
Definition Item.h:1333
bool isAncestor() const
Definition Item.h:1355
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
bool hasHChildren() const
Definition Item.h:1361
bool isActive() const
Definition Item.h:1346
Int32 level() const
Definition Item.h:1368
Cell hParent() const
Definition Item.h:1327
Int32 nbHParent() const
Nombre de parent pour l'AMR.
Definition Item.h:1330
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Face d'une maille.
Definition Item.h:964
Cell frontCell() const
Maille devant la face (maille nulle si aucune).
Definition Item.h:1652
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1665
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2).
Definition Item.h:1042
Cell backCell() const
Maille derrière la face (maille nulle si aucune).
Definition Item.h:1646
Exception lorsqu'une erreur fatale est survenue.
Interface d'un fonctor avec argument.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
virtual VariableItemInt32 & itemsNewOwner()=0
Variable contenant le numéro du nouveau sous-domaine propriétaire de l'entité.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
bool isSuppressed() const
Vrai si l'entité est supprimée.
bool isActive() const
Int32 flags() const
Flags de l'entité
bool isSubactive() const
Int32 nbHParent() const
Nombre de parents pour l'AMR.
bool isOwn() const
Vrai si l'entité appartient au sous-domaine.
bool isAncestor() const
Int32 nbHChildren() const
Nombre d'enfants pour l'AMR.
Int32 localId() const
Numéro local (au sous-domaine) de l'entité
Flags pour les caractéristiques des entités.
Definition ItemFlags.h:38
@ II_Inactive
L'entité est inactive //COARSEN_INACTIVE,.
Definition ItemFlags.h:80
@ II_Refine
L'entité est marquée pour raffinement.
Definition ItemFlags.h:77
@ II_JustAdded
L'entité vient d'être ajoutée.
Definition ItemFlags.h:61
@ II_HasBackCell
L'entité a une maille derrière.
Definition ItemFlags.h:52
@ II_JustRefined
L'entité vient d'être raffinée.
Definition ItemFlags.h:78
@ II_CoarsenInactive
L'entité est inactive et a des enfants tagués pour dé-raffinement.
Definition ItemFlags.h:81
@ II_HasFrontCell
L'entité a une maille devant.
Definition ItemFlags.h:51
@ II_DoNothing
L'entité est bloquée.
Definition ItemFlags.h:76
@ II_Coarsen
L'entité est marquée pour dé-raffinement.
Definition ItemFlags.h:75
@ II_JustCoarsened
L'entité vient d'être dé-raffiné
Definition ItemFlags.h:79
@ II_UserMark1
Marque utilisateur.
Definition ItemFlags.h:94
Integer size() const
Nombre d'éléments du groupe.
Definition ItemGroup.h:88
Vue sur une liste pour obtenir des informations sur les entités.
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:65
static Int32 nbHChildrenByItemType(Integer type)
AMR.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:794
Classe de base d'un élément de maillage.
Definition Item.h:83
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:380
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
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
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:369
Int16 type() const
Type de l'entité
Definition Item.h:241
Interface du gestionnaire des matériaux et des milieux d'un maillage.
virtual void forceRecompute()=0
Force le recalcul des informations des matériaux.
static IMeshMaterialMng * getReference(const MeshHandleOrMesh &mesh_handle, bool create=true)
Récupère ou créé la référence associée à mesh.
void setFlags(Int32 f)
Positionne les flags de l'entité
void addFlags(Int32 added_flags)
Ajoute les flags added_flags à ceux de l'entité
void removeFlags(Int32 removed_flags)
Supprime les flags removed_flags de ceux de l'entité
Noeud d'un maillage.
Definition Item.h:582
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
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 fatal() const
Flot pour un message d'erreur fatale.
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.
Implementation of a mesh.
Definition DynamicMesh.h:98
IItemFamily * nodeFamily() override
Retourne la famille des noeuds.
IItemFamily * cellFamily() override
Retourne la famille des mailles.
IParallelMng * parallelMng() override
Gestionnaire de parallèlisme.
ItemTypeMng * itemTypeMng() const override
Gestionnaire de types d'entités associé
CellGroup allCells() override
Groupe de toutes les mailles.
IItemFamily * faceFamily() override
Retourne la famille des faces.
CellGroup ownCells() override
Groupe de toutes les mailles propres au domaine.
void addFrontCellToFace(Face face, Cell new_cell)
Adds a front edge to the face.
void addBackCellToFace(Face face, Cell new_cell)
Adds a back cell to the face.
Associative array of ItemInternal.
void eachItem(const Lambda &lambda)
Template function to iterate over the instance's entities.
bool _checkUnflagged(bool arcane_assert_yes=false)
MeshRefinement(DynamicMesh *mesh)
void populateBackFrontCellsFromChildrenFaces(Cell parent_cell)
bool coarsenItemsV2(bool update_parent_flag)
Method allowing the removal of meshes marked with the flag "II_Coarsen".
bool refineAndCoarsenItems(const bool maintain_level_one=true)
bool refineItems(const bool maintain_level_one=true)
const IMesh * getMesh() const
Constant reference to the mesh.
void uniformlyCoarsen(Integer n=1)
Int64 findOrAddFaceUid(const Real3 &face_center, const Real &tol, bool &is_added)
MapCoordToUid::Box m_mesh_containing_box
ParallelAMRConsistency * m_parallel_amr_consistency
bool _makeCoarseningCompatible(const bool)
const ItemRefinementPatternT< typeID > & getRefinementPattern() const
bool _makeRefinementCompatible(const bool)
void _upscaleData(Array< ItemInternal * > &parent_cells)
Upscaling of data on the parent meshes.
ItemRefinement * m_item_refinement
Int64 findOrAddNodeUid(const Real3 &p, const Real &tol)
bool _checkLevelOne(bool arcane_assert_yes=false)
void uniformlyRefine(Integer n=1)
bool coarsenItems(const bool maintain_level_one=true)
void _populateBackFrontCellsFromParentFaces(Cell parent_cell)
void _interpolateData(const Int64Array &cells_to_refine)
Interpolation of data on the child meshes.
virtual void flagCellToRefine(Int32ConstArrayView cells_lids)
Passing the error committed by the mesh to the refinement flag.
bool _refineItems(Int64Array &cells_to_refine)
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Cell, Integer > VariableCellInteger
Grandeur au centre des mailles de type entier.
MeshVariableScalarRefT< Node, Int32 > VariableNodeInt32
Grandeur au noeud de type entier 32 bits.
ItemVariableScalarRefT< Int32 > VariableItemInt32
Grandeur de type entier 32 bits.
@ ReduceMin
Minimum des valeurs.
@ ReduceMax
Maximum des valeurs.
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:125
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:339
std::uint32_t UInt32
Type entier non signé sur 32 bits.
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
bool arcaneIsDebug()
Vrai si la macro ARCANE_DEBUG est définie.
Definition Misc.cc:80
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
ArrayView< Int32 > Int32ArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:453
double Real
Type représentant un réel.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
std::int32_t Int32
Type entier signé sur 32 bits.