Arcane  v4.1.2.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
CartesianPatchGroup.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* CartesianPatchGroup.cc (C) 2000-2025 */
9/* */
10/* Gestion du groupe de patchs du maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/cartesianmesh/internal/CartesianPatchGroup.h"
14
15#include "arcane/utils/FixedArray.h"
16#include "arcane/utils/Vector3.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/ITraceMng.h"
19
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IParallelMng.h"
22#include "arcane/core/MeshKind.h"
23#include "arcane/core/Properties.h"
24
25#include "arcane/cartesianmesh/ICartesianMesh.h"
26#include "arcane/cartesianmesh/AMRZonePosition.h"
27
28#include "arcane/cartesianmesh/internal/CartesianMeshPatch.h"
29#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
30#include "arcane/cartesianmesh/internal/AMRPatchPositionLevelGroup.h"
31#include "arcane/cartesianmesh/internal/AMRPatchPositionSignature.h"
32#include "arcane/cartesianmesh/internal/AMRPatchPositionSignatureCut.h"
33#include "arcane/cartesianmesh/internal/ICartesianMeshNumberingMngInternal.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44// Le patch 0 est un patch spécial "ground". Il ne possède pas de cell_group
45// dans le tableau "m_amr_patch_cell_groups".
46// Pour les index, on utilise toujours celui des tableaux m_amr_patches_pointer
47// et m_amr_patches.
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52CartesianPatchGroup::
53CartesianPatchGroup(ICartesianMesh* cmesh)
54: m_cmesh(cmesh)
55, m_index_new_patches(1)
56, m_size_of_overlap_layer_sub_top_level(0)
57, m_higher_level(0)
58{}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63void CartesianPatchGroup::
64build()
65{
66 m_properties = makeRef(new Properties(*(m_cmesh->mesh()->properties()), "CartesianPatchGroup"));
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72void CartesianPatchGroup::
73saveInfosInProperties()
74{
75 m_properties->set("Version", 1);
76
77 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
78 UniqueArray<String> patch_group_names;
79 for (Integer i = 1; i < m_amr_patches_pointer.size(); ++i) {
80 patch_group_names.add(allCells(i).name());
81 }
82 m_properties->set("PatchGroupNames", patch_group_names);
83 }
84
85 else {
86 UniqueArray<String> patch_group_names(m_amr_patches_pointer.size() - 1);
87 UniqueArray<Int32> level(m_amr_patches_pointer.size());
88 UniqueArray<Int32> overlap(m_amr_patches_pointer.size());
89 UniqueArray<Int32> index(m_amr_patches_pointer.size());
90 UniqueArray<CartCoordType> min_point(m_amr_patches_pointer.size() * 3);
91 UniqueArray<CartCoordType> max_point(m_amr_patches_pointer.size() * 3);
92
93 for (Integer i = 0; i < m_amr_patches_pointer.size(); ++i) {
94 const AMRPatchPosition& position = m_amr_patches_pointer[i]->_internalApi()->positionRef();
95 level[i] = position.level();
96 overlap[i] = position.overlapLayerSize();
97 index[i] = m_amr_patches_pointer[i]->index();
98
99 const Integer pos = i * 3;
100 min_point[pos + 0] = position.minPoint().x;
101 min_point[pos + 1] = position.minPoint().y;
102 min_point[pos + 2] = position.minPoint().z;
103 max_point[pos + 0] = position.maxPoint().x;
104 max_point[pos + 1] = position.maxPoint().y;
105 max_point[pos + 2] = position.maxPoint().z;
106
107 if (i != 0) {
108 patch_group_names[i - 1] = allCells(i).name();
109 }
110 }
111 m_properties->set("LevelPatches", level);
112 m_properties->set("OverlapSizePatches", overlap);
113 m_properties->set("IndexPatches", index);
114 m_properties->set("MinPointPatches", min_point);
115 m_properties->set("MaxPointPatches", max_point);
116
117 // TODO : Trouver une autre façon de gérer ça.
118 // Dans le cas d'une protection reprise, le tableau m_available_index
119 // ne peut pas être correctement recalculé à cause des éléments après
120 // le "index max" des "index actif". Ces éléments "en trop" ne
121 // peuvent pas être retrouvés sans plus d'infos.
122 m_properties->set("PatchGroupNamesAvailable", m_available_group_index);
123 m_properties->set("PatchGroupNames", patch_group_names);
124 }
125}
126
127/*---------------------------------------------------------------------------*/
128/*---------------------------------------------------------------------------*/
129
130void CartesianPatchGroup::
131recreateFromDump()
132{
133 // Sauve le numéro de version pour être sur que c'est OK en reprise
134 Int32 v = m_properties->getInt32("Version");
135 if (v != 1) {
136 ARCANE_FATAL("Bad serializer version: trying to read from incompatible checkpoint v={0} expected={1}", v, 1);
137 }
138
139 clear();
140
141 // Récupère les noms des groupes des patchs
142 UniqueArray<String> patch_group_names;
143 m_properties->get("PatchGroupNames", patch_group_names);
144
145 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
146 m_cmesh->traceMng()->info(4) << "Found n=" << patch_group_names.size() << " patchs";
147
148 IItemFamily* cell_family = m_cmesh->mesh()->cellFamily();
149 for (const String& x : patch_group_names) {
150 CellGroup group = cell_family->findGroup(x);
151 if (group.null())
152 ARCANE_FATAL("Can not find cell group '{0}'", x);
153 addPatchAfterRestore(group);
154 }
155 }
156 else {
157 UniqueArray<Int32> level;
158 UniqueArray<Int32> overlap;
159 UniqueArray<Int32> index;
160 UniqueArray<CartCoordType> min_point;
161 UniqueArray<CartCoordType> max_point;
162
163 m_properties->get("LevelPatches", level);
164 m_properties->get("OverlapSizePatches", overlap);
165 m_properties->get("IndexPatches", index);
166 m_properties->get("MinPointPatches", min_point);
167 m_properties->get("MaxPointPatches", max_point);
168
169 if (index.size() < 1) {
170 ARCANE_FATAL("Le ground est forcement save");
171 }
172
173 {
174 ConstArrayView min(min_point.subConstView(0, 3));
175 ConstArrayView max(max_point.subConstView(0, 3));
176
177 AMRPatchPosition position(
178 level[0],
179 { min[MD_DirX], min[MD_DirY], min[MD_DirZ] },
180 { max[MD_DirX], max[MD_DirY], max[MD_DirZ] },
181 overlap[0]);
182
183 m_amr_patches_pointer[0]->_internalApi()->setPosition(position);
184 }
185
186 IItemFamily* cell_family = m_cmesh->mesh()->cellFamily();
187
188 for (Integer i = 1; i < index.size(); ++i) {
189 ConstArrayView min(min_point.subConstView(i * 3, 3));
190 ConstArrayView max(max_point.subConstView(i * 3, 3));
191
192 AMRPatchPosition position(
193 level[i],
194 { min[MD_DirX], min[MD_DirY], min[MD_DirZ] },
195 { max[MD_DirX], max[MD_DirY], max[MD_DirZ] },
196 overlap[i]);
197
198 const String& x = patch_group_names[i - 1];
199 CellGroup cell_group = cell_family->findGroup(x);
200 if (cell_group.null())
201 ARCANE_FATAL("Can not find cell group '{0}'", x);
202
203 auto* cdi = new CartesianMeshPatch(m_cmesh, index[i], position);
204 _addPatchInstance(makeRef(cdi));
205 _addCellGroup(cell_group, cdi);
206 }
207
208 UniqueArray<Int32> available_index;
209 m_properties->get("PatchGroupNamesAvailable", available_index);
210 rebuildAvailableGroupIndex(available_index);
211 }
212}
213
214/*---------------------------------------------------------------------------*/
215/*---------------------------------------------------------------------------*/
216
217Ref<CartesianMeshPatch> CartesianPatchGroup::
218groundPatch()
219{
220 _createGroundPatch();
221 return patch(0);
222}
223
224/*---------------------------------------------------------------------------*/
225/*---------------------------------------------------------------------------*/
226
227void CartesianPatchGroup::
228addPatch(ConstArrayView<Int32> cells_local_id)
229{
230 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
231 ARCANE_FATAL("Do not use this method with AMR type 3");
232 }
233
234 Integer index = _nextIndexForNewPatch();
235 String children_group_name = String("CartesianMeshPatchCells") + index;
236 IItemFamily* cell_family = m_cmesh->mesh()->cellFamily();
237 CellGroup children_cells = cell_family->createGroup(children_group_name, cells_local_id, true);
238 addPatch(children_cells, index);
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
244// Il faut appeler rebuildAvailableIndex() après les appels à cette méthode.
245Integer CartesianPatchGroup::
246addPatchAfterRestore(CellGroup cell_group)
247{
248 const String& name = cell_group.name();
249 Integer group_index = -1;
250 if (name.startsWith("CartesianMeshPatchCells")) {
251 String index_str = name.substring(23);
252 group_index = std::stoi(index_str.localstr());
253 }
254 else {
255 ARCANE_FATAL("Invalid group");
256 }
257
258 addPatch(cell_group, group_index);
259 return group_index;
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265void CartesianPatchGroup::
266addPatch(CellGroup cell_group, Integer group_index)
267{
268 _createGroundPatch();
269 if (cell_group.null())
270 ARCANE_FATAL("Null cell group");
271
272 AMRPatchPosition position;
273
274 auto* cdi = new CartesianMeshPatch(m_cmesh, group_index, position);
275 _addPatchInstance(makeRef(cdi));
276 _addCellGroup(cell_group, cdi);
277}
278
279/*---------------------------------------------------------------------------*/
280/*---------------------------------------------------------------------------*/
281
282void CartesianPatchGroup::
283addPatch(const AMRZonePosition& zone_position)
284{
285 clearRefineRelatedFlags();
286
287 auto amr = m_cmesh->_internalApi()->cartesianMeshAMRPatchMng();
288 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
289
290 auto position = zone_position.toAMRPatchPosition(m_cmesh);
291 Int32 level = position.level();
292
293 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
294 if (!icell->hasHChildren()) {
295 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
296 if (position.isInWithOverlap(pos)) {
297 icell->mutableItemBase().addFlags(ItemFlags::II_Refine);
298 }
299 }
300 }
301
302 amr->refine();
303
304 _addPatch(position.patchUp(m_cmesh->mesh()->dimension()));
305}
306
307/*---------------------------------------------------------------------------*/
308/*---------------------------------------------------------------------------*/
309
310// Attention : avant _createGroundPatch() = 0, après _createGroundPatch(); = 1
311Integer CartesianPatchGroup::
312nbPatch() const
313{
314 return m_amr_patches.size();
315}
316
317/*---------------------------------------------------------------------------*/
318/*---------------------------------------------------------------------------*/
319
320Ref<CartesianMeshPatch> CartesianPatchGroup::
321patch(const Integer index) const
322{
323 return m_amr_patches[index];
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
328
329CartesianMeshPatchListView CartesianPatchGroup::
330patchListView() const
331{
332 return CartesianMeshPatchListView{ m_amr_patches_pointer };
333}
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
337
338CellGroup CartesianPatchGroup::
339allCells(const Integer index)
340{
341 if (index == 0) {
342 ARCANE_FATAL("You cannot get cells of ground patch with this method");
343 }
344 return m_amr_patch_cell_groups_all[index - 1];
345}
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
349
350CellGroup CartesianPatchGroup::
351inPatchCells(Integer index)
352{
353 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
354 ARCANE_FATAL("Method available only with AMR PatchCartesianMeshOnly");
355 }
356 if (index == 0) {
357 ARCANE_FATAL("You cannot get cells of ground patch with this method");
358 }
359 return m_amr_patch_cell_groups_inpatch[index - 1];
360}
361
362/*---------------------------------------------------------------------------*/
363/*---------------------------------------------------------------------------*/
364
365CellGroup CartesianPatchGroup::
366overallCells(Integer index)
367{
368 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
369 ARCANE_FATAL("Method available only with AMR PatchCartesianMeshOnly");
370 }
371 if (index == 0) {
372 ARCANE_FATAL("You cannot get cells of ground patch with this method");
373 }
374 return m_amr_patch_cell_groups_overall[index - 1];
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380// Attention : efface aussi le ground patch. Nécessaire de le récupérer après coup.
381void CartesianPatchGroup::
382clear()
383{
384 _removeAllPatches();
385 _createGroundPatch();
386}
387
388/*---------------------------------------------------------------------------*/
389/*---------------------------------------------------------------------------*/
390
391void CartesianPatchGroup::
392removePatch(const Integer index)
393{
394 if (m_patches_to_delete.contains(index)) {
395 return;
396 }
397 if (index == 0) {
398 ARCANE_FATAL("You cannot remove ground patch");
399 }
400 if (index < 1 || index >= m_amr_patches.size()) {
401 ARCANE_FATAL("Invalid index");
402 }
403
404 m_patches_to_delete.add(index);
405}
406
407/*---------------------------------------------------------------------------*/
408/*---------------------------------------------------------------------------*/
409
410void CartesianPatchGroup::
411removeCellsInAllPatches(ConstArrayView<Int32> cells_local_id)
412{
413 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
414 ARCANE_FATAL("Method available only with AMR Cell");
415 }
416 for (CellGroup cells : m_amr_patch_cell_groups_all) {
417 cells.removeItems(cells_local_id);
418 }
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424void CartesianPatchGroup::
425_removeCellsInAllPatches(const AMRPatchPosition& zone_to_delete)
426{
427 // Attention si suppression de la suppression en deux étapes : _splitPatch() supprime aussi des patchs.
428 // i = 1 car on ne peut pas déraffjner le patch ground.
429 const Integer nb_patchs = m_amr_patches_pointer.size();
430 for (Integer i = 1; i < nb_patchs; ++i) {
431 ICartesianMeshPatch* patch = m_amr_patches_pointer[i];
432 // m_cmesh->traceMng()->info() << "I : " << i
433 // << " -- Compare Patch (min : " << patch->position().minPoint()
434 // << ", max : " << patch->position().maxPoint()
435 // << ", level : " << patch->position().level()
436 // << ") and Zone (min : " << zone_to_delete.minPoint()
437 // << ", max : " << zone_to_delete.maxPoint()
438 // << ", level : " << zone_to_delete.level() << ")";
439
440 if (zone_to_delete.haveIntersection(patch->position())) {
441 _splitPatch(i, zone_to_delete);
442 }
443 }
444}
445
446/*---------------------------------------------------------------------------*/
447/*---------------------------------------------------------------------------*/
448
449void CartesianPatchGroup::
450removeCellsInZone(const AMRZonePosition& zone_to_delete)
451{
452 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
453 ARCANE_FATAL("Method available only with AMR PatchCartesianMeshOnly");
454 }
455 clearRefineRelatedFlags();
456
457 UniqueArray<Int32> cells_local_id;
458
459 AMRPatchPosition patch_position;
460 zone_to_delete.cellsInPatch(m_cmesh, cells_local_id, patch_position);
461
462 _removeCellsInAllPatches(patch_position);
463 applyPatchEdit(false);
464 auto amr = m_cmesh->_internalApi()->cartesianMeshAMRPatchMng();
465 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
466
467 Int32 level = patch_position.level();
468
469 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
470 if (!icell->hasHChildren()) {
471 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
472 if (patch_position.isIn(pos)) {
473 icell->mutableItemBase().addFlags(ItemFlags::II_Coarsen);
474 }
475 }
476 }
477
478 amr->coarsen(true);
479}
480
481/*---------------------------------------------------------------------------*/
482/*---------------------------------------------------------------------------*/
483
484void CartesianPatchGroup::
485applyPatchEdit(bool remove_empty_patches)
486{
487 // m_cmesh->mesh()->traceMng()->info() << "applyPatchEdit() -- Remove nb patch : " << m_patches_to_delete.size();
488
489 std::stable_sort(m_patches_to_delete.begin(), m_patches_to_delete.end(),
490 [](const Integer a, const Integer b) {
491 return a < b;
492 });
493
494 _removeMultiplePatches(m_patches_to_delete);
495 m_patches_to_delete.clear();
496
497 if (remove_empty_patches) {
498 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
499 ARCANE_FATAL("remove_empty_patches=true available only with AMR Cell");
500 }
501 UniqueArray<Integer> size_of_patches(m_amr_patch_cell_groups_all.size());
502 for (Integer i = 0; i < m_amr_patch_cell_groups_all.size(); ++i) {
503 size_of_patches[i] = m_amr_patch_cell_groups_all[i].size();
504 }
505 m_cmesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, size_of_patches);
506 for (Integer i = 0; i < size_of_patches.size(); ++i) {
507 if (size_of_patches[i] == 0) {
508 m_patches_to_delete.add(i + 1);
509 }
510 }
511 _removeMultiplePatches(m_patches_to_delete);
512 m_patches_to_delete.clear();
513 }
514
515 m_higher_level = 0;
516 for (const auto patch : m_amr_patches_pointer) {
517 const Int32 level = patch->_internalApi()->positionRef().level();
518 if (level > m_higher_level) {
519 m_higher_level = level;
520 }
521 }
522}
523
524/*---------------------------------------------------------------------------*/
525/*---------------------------------------------------------------------------*/
526
527void CartesianPatchGroup::
528updateLevelsAndAddGroundPatch()
529{
530 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
531 return;
532 }
533 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
534
535 // Attention : on suppose que numbering->updateFirstLevel(); a déjà été appelé !
536
537 // TODO : Mettre à jour la taille des couches de recouvrement !
538
539 for (ICartesianMeshPatch* patch : m_amr_patches_pointer) {
540 const Int32 level = patch->position().level();
541 // Si le niveau est 0, c'est le patch spécial 0 donc on ne modifie que le max, le niveau reste à 0.
542 if (level == 0) {
543 const CartCoord3Type max_point = patch->position().maxPoint();
544 if (m_cmesh->mesh()->dimension() == 2) {
545 patch->_internalApi()->positionRef().setMaxPoint({
546 numbering->offsetLevelToLevel(max_point.x, level, level - 1),
547 numbering->offsetLevelToLevel(max_point.y, level, level - 1),
548 1,
549 });
550 }
551 else {
552 patch->_internalApi()->positionRef().setMaxPoint({
553 numbering->offsetLevelToLevel(max_point.x, level, level - 1),
554 numbering->offsetLevelToLevel(max_point.y, level, level - 1),
555 numbering->offsetLevelToLevel(max_point.z, level, level - 1),
556 });
557 }
558 }
559 // Sinon, on "surélève" le niveau des patchs vu qu'il va y avoir le patch "-1"
560 else {
561 patch->_internalApi()->positionRef().setLevel(level + 1);
562 if (level + 1 > m_higher_level) {
563 m_higher_level = level + 1;
564 }
565 }
566 }
567
568 AMRPatchPosition old_ground;
569 old_ground.setLevel(1);
570 old_ground.setMinPoint({ 0, 0, 0 });
571 old_ground.setMaxPoint({ numbering->globalNbCellsX(1), numbering->globalNbCellsY(1), numbering->globalNbCellsZ(1) });
572 old_ground.setOverlapLayerSize(0);
573
574 _addPatch(old_ground);
575}
576
577/*---------------------------------------------------------------------------*/
578/*---------------------------------------------------------------------------*/
579
580Integer CartesianPatchGroup::
581_nextIndexForNewPatch()
582{
583 if (!m_available_group_index.empty()) {
584 const Integer elem = m_available_group_index.back();
585 m_available_group_index.popBack();
586 return elem;
587 }
588 return m_index_new_patches++;
589}
590
591/*---------------------------------------------------------------------------*/
592/*---------------------------------------------------------------------------*/
593
594void CartesianPatchGroup::
595mergePatches()
596{
597 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
598 return;
599 }
600 // m_cmesh->traceMng()->info() << "Global fusion";
601 UniqueArray<std::pair<Integer, Int64>> index_n_nb_cells;
602 {
603 Integer index = 0;
604 for (auto patch : m_amr_patches_pointer) {
605 index_n_nb_cells.add({ index++, patch->position().nbCells() });
606 }
607 }
608
609 // Algo de fusion.
610 // D'abord, on trie les patchs du plus petit nb de mailles au plus grand nb de mailles (optionnel).
611 // Ensuite, pour chaque patch, on regarde si l'on peut le fusionner avec un autre.
612 // Si on arrive à faire une fusion, on recommence l'algo jusqu'à ne plus pouvoir fusionner.
613 bool fusion = true;
614 while (fusion) {
615 fusion = false;
616
617 std::stable_sort(index_n_nb_cells.begin(), index_n_nb_cells.end(),
618 [](const std::pair<Integer, Int64>& a, const std::pair<Integer, Int64>& b) {
619 return a.second < b.second;
620 });
621
622 for (Integer p0 = 0; p0 < index_n_nb_cells.size(); ++p0) {
623 auto [index_p0, nb_cells_p0] = index_n_nb_cells[p0];
624
625 AMRPatchPosition& patch_fusion_0 = m_amr_patches_pointer[index_p0]->_internalApi()->positionRef();
626 if (patch_fusion_0.isNull())
627 continue;
628
629 // Si une fusion a déjà eu lieu, on doit alors regarder les patchs avant "p0"
630 // (vu qu'il y en a au moins un qui a été modifié).
631 // (une "optimisation" pourrait être de récupérer la position du premier
632 // patch fusionné mais bon, moins lisible + pas beaucoup de patchs).
633 for (Integer p1 = p0 + 1; p1 < m_amr_patches_pointer.size(); ++p1) {
634 auto [index_p1, nb_cells_p1] = index_n_nb_cells[p1];
635
636 AMRPatchPosition& patch_fusion_1 = m_amr_patches_pointer[index_p1]->_internalApi()->positionRef();
637 if (patch_fusion_1.isNull())
638 continue;
639
640 // m_cmesh->traceMng()->info() << "\tCheck fusion"
641 // << " -- 0 Min point : " << patch_fusion_0.minPoint()
642 // << " -- 0 Max point : " << patch_fusion_0.maxPoint()
643 // << " -- 0 Level : " << patch_fusion_0.level()
644 // << " -- 1 Min point : " << patch_fusion_1.minPoint()
645 // << " -- 1 Max point : " << patch_fusion_1.maxPoint()
646 // << " -- 1 Level : " << patch_fusion_1.level();
647
648 if (patch_fusion_0.fusion(patch_fusion_1)) {
649 // m_cmesh->traceMng()->info() << "Fusion OK";
650 patch_fusion_1.setLevel(-2); // Devient null.
651 index_n_nb_cells[p0].second = patch_fusion_0.nbCells();
652
653 UniqueArray<Int32> local_ids;
654 allCells(index_p1).view().fillLocalIds(local_ids);
655 allCells(index_p0).addItems(local_ids, false);
656
657 // m_cmesh->traceMng()->info() << "Remove patch : " << index_p1;
658 removePatch(index_p1);
659
660 fusion = true;
661 break;
662 }
663 }
664 if (fusion) {
665 break;
666 }
667 }
668 }
669}
670
671/*---------------------------------------------------------------------------*/
672/*---------------------------------------------------------------------------*/
673
674void CartesianPatchGroup::
675refine(bool clear_refine_flag)
676{
677 // TODO : Le paramètre clear_refine_flag doit être à true pour l'instant.
678 // À cause des mailles de recouvrements, on doit regénérer les patchs
679 // de tous les niveaux à chaque fois. Pour que ça fonctionne, il
680 // faudrait demander le nombre de niveaux qui sera généré en tout,
681 // pour cette itération, pour calculer en avance la taille de la
682 // couche de recouvrement de chaque niveau.
683 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
684 ARCANE_FATAL("Method available only with AMR PatchCartesianMeshOnly");
685 }
686 Integer dimension = m_cmesh->mesh()->dimension();
687 Int32 nb_overlap_cells = m_size_of_overlap_layer_sub_top_level;
688 Int32 min_level = 0;
689 Int32 future_max_level = -1; // Désigne le niveau max qui aura des enfants, donc le futur level max +1.
690 Int32 old_max_level = -1; // Mais s'il reste des mailles à des niveaux plus haut, il faut les retirer.
691 auto amr = m_cmesh->_internalApi()->cartesianMeshAMRPatchMng();
692
693 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allCells()) {
694 Integer level = icell->level();
695 if (icell->hasFlags(ItemFlags::II_Refine)) {
696 if (level > future_max_level)
697 future_max_level = level;
698 }
699 if (level > old_max_level)
700 old_max_level = level;
701 }
702 future_max_level = m_cmesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, future_max_level);
703 old_max_level = m_cmesh->mesh()->parallelMng()->reduce(MessagePassing::ReduceMax, old_max_level);
704
705 // m_cmesh->traceMng()->info() << "Min level : " << min_level << " -- Max level : " << future_max_level;
706 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
707
708 AMRPatchPositionLevelGroup all_patches(future_max_level);
709
710 for (Int32 level = future_max_level; level >= min_level; --level) {
711 // m_cmesh->traceMng()->info() << "Refine Level " << level << " with " << nb_overlap_cells << " layers of overlap cells";
712 if (level != future_max_level) {
713 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allCells()) {
714 if (icell->level() == level && icell->hasFlags(ItemFlags::II_Refine)) {
715 const CartCoord3Type pos = numbering->offsetLevelToLevel(numbering->cellUniqueIdToCoord(*icell), level, level + 1);
716 for (const auto& patch : all_patches.patches(level)) {
717 if (patch.isInWithOverlap(pos, patch.overlapLayerSize() + 1)) {
718 icell->mutableItemBase().removeFlags(ItemFlags::II_Refine);
719 }
720 }
721 }
722 }
723 // m_cmesh->traceMng()->info() << "All patch level+1 with margin (can be overlap) : ";
724 // for (auto& elem : all_patches.patches(level + 1)) {
725 // m_cmesh->traceMng()->info() << "\tPatch -- min = " << elem.minPointWithOverlap() << " -- max = " << elem.maxPointWithOverlap();
726 // }
727 }
728
729 AMRPatchPosition all_level;
730 all_level.setLevel(level);
731 all_level.setMinPoint({ 0, 0, 0 });
732 all_level.setMaxPoint({ numbering->globalNbCellsX(level), numbering->globalNbCellsY(level), numbering->globalNbCellsZ(level) });
733 all_level.setOverlapLayerSize(nb_overlap_cells);
734
735 AMRPatchPositionSignature sig(all_level, m_cmesh, &all_patches);
736 UniqueArray<AMRPatchPositionSignature> sig_array;
737 sig_array.add(sig);
738
739 AMRPatchPositionSignatureCut::cut(sig_array);
740
741 for (const auto& elem : sig_array) {
742 all_patches.addPatch(elem.patch());
743 }
744 nb_overlap_cells /= 2;
745 nb_overlap_cells += 1;
746
748 /*
749 {
750 Real global_efficacity = 0;
751 m_cmesh->traceMng()->info() << "All patch : ";
752 for (auto& elem : sig_array) {
753 m_cmesh->traceMng()->info() << "\tPatch -- min = " << elem.patch().minPoint() << " -- max = " << elem.patch().maxPoint() << " -- Efficacité : " << elem.efficacity();
754 global_efficacity += elem.efficacity();
755 }
756 global_efficacity /= sig_array.size();
757 m_cmesh->traceMng()->info() << "Global efficacity : " << global_efficacity;
758 UniqueArray<Integer> out(numbering->globalNbCellsY(level) * numbering->globalNbCellsX(level), -1);
759 Array2View<Integer> av_out(out.data(), numbering->globalNbCellsY(level), numbering->globalNbCellsX(level));
760 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allCells()) {
761 if (icell->level() != level)
762 continue;
763 Integer pos_x = numbering->cellUniqueIdToCoordX(*icell);
764 Integer pos_y = numbering->cellUniqueIdToCoordY(*icell);
765 Integer pos_z = numbering->cellUniqueIdToCoordZ(*icell);
766 Integer patch = -1;
767 for (Integer i = 0; i < sig_array.size(); ++i) {
768 const AMRPatchPositionSignature& elem = sig_array[i];
769 if (elem.patch().isInWithOverlap(pos_x, pos_y, pos_z)) {
770 patch = -2;
771 }
772 if (elem.isIn(pos_x, pos_y, pos_z)) {
773 if (patch >= 0) {
774 ARCANE_FATAL("ABCDEFG -- old : {0} -- new : {1}", patch, i);
775 }
776 patch = i;
777 }
778 }
779 if (patch == -1 && icell->hasFlags(ItemFlags::II_Refine)) {
780 ARCANE_FATAL("Bad Patch");
781 }
782 av_out(pos_y, pos_x) = patch;
783 }
784
785 StringBuilder str = "";
786 for (Integer i = 0; i < numbering->globalNbCellsX(level); ++i) {
787 str += "\n";
788 for (Integer j = 0; j < numbering->globalNbCellsY(level); ++j) {
789 Integer c = av_out(i, j);
790 if (c >= 0) {
791 str += "[";
792 if (c < 10)
793 str += " ";
794 str += c;
795 str += "]";
796 }
797 else if (c == -2) {
798 str += "[RE]";
799 }
800 else
801 str += "[ ]";
802 }
803 }
804 m_cmesh->traceMng()->info() << str;
805 }
806 */
808 }
809
810
811 {
812 clearRefineRelatedFlags();
813 }
814
815 _removeAllPatches();
816 applyPatchEdit(false);
817
818 for (Int32 level = min_level; level <= future_max_level; ++level) {
819 all_patches.fusionPatches(level);
820
821 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
822 if (!icell->hasHChildren()) {
823 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
824 for (const AMRPatchPosition& patch : all_patches.patches(level)) {
825 if (patch.isInWithOverlap(pos)) {
826 icell->mutableItemBase().addFlags(ItemFlags::II_Refine);
827 }
828 }
829 }
830 }
831
832 /*
833 {
834 UniqueArray<Integer> out(numbering->globalNbCellsY(level) * numbering->globalNbCellsX(level), -1);
835 Array2View<Integer> av_out(out.data(), numbering->globalNbCellsY(level), numbering->globalNbCellsX(level));
836 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
837 Integer pos_x = numbering->cellUniqueIdToCoordX(*icell);
838 Integer pos_y = numbering->cellUniqueIdToCoordY(*icell);
839 Integer pos_z = numbering->cellUniqueIdToCoordZ(*icell);
840 if (icell->hasHChildren()) {
841 av_out(pos_y, pos_x) = 0;
842 }
843 if (icell->hasFlags(ItemFlags::II_Refine)) {
844 av_out(pos_y, pos_x) = 1;
845 }
846 if (icell->hasHChildren() && icell->hasFlags(ItemFlags::II_Refine)) {
847 ARCANE_FATAL("Bad refine cell");
848 }
849 }
850
851 StringBuilder str = "";
852 for (Integer i = 0; i < numbering->globalNbCellsX(level); ++i) {
853 str += "\n";
854 for (Integer j = 0; j < numbering->globalNbCellsY(level); ++j) {
855 Integer c = av_out(i, j);
856 if (c == 1)
857 str += "[++]";
858 else if (c == 0)
859 str += "[XX]";
860 else
861 str += "[ ]";
862 }
863 }
864 m_cmesh->traceMng()->info() << str;
865 }
866 */
867
868 amr->refine();
869
870 // // Pour debug, forcer le else de la methode addPatch(AV<Int32>).
871 // UniqueArray<Int32> d_cell_ids;
872 // ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level + 1)) {
873 // d_cell_ids.add(icell.localId());
874 // }
875 // addPatch(d_cell_ids);
876
877 for (const AMRPatchPosition& patch : all_patches.patches(level)) {
878 _addPatch(patch.patchUp(dimension));
879 }
880 }
881
882 // m_cmesh->traceMng()->info() << "max_level : " << future_max_level << " -- min_level : " << min_level;
883
884 // On retire les mailles qui n'auront plus de parent.
885 // Exemple :
886 // À l'itération précédente, on a mis des flags II_Refine sur des mailles de niveau 0 et 1,
887 // le niveau max était 2.
888 // Alors, dans cette itération, old_max_level = 2.
889 // À cette itération, on a mis des flags II_Refine uniquement sur des mailles de niveau 0.
890 // Alors, future_max_level = 0.
891 //
892 // On doit retirer toutes les mailles de niveau 2 pour éviter les mailles orphelines.
893 {
894 for (Int32 level = old_max_level; level > future_max_level + 1; --level) {
895 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
896 icell->mutableItemBase().addFlags(ItemFlags::II_Coarsen);
897 }
898 amr->coarsen(true);
899 }
900 }
901
902 for (Int32 level = future_max_level + 1; level > min_level; --level) {
903 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level)) {
904 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
905
906 bool is_in = false;
907 for (const AMRPatchPosition& patch : all_patches.patches(level - 1)) {
908 if (patch.patchUp(dimension).isInWithOverlap(pos)) {
909 is_in = true;
910 break;
911 }
912 }
913 if (!is_in) {
914 icell->mutableItemBase().addFlags(ItemFlags::II_Coarsen);
915 }
916 }
917 /*
918 {
919 UniqueArray<Integer> out(numbering->globalNbCellsY(level - 1) * numbering->globalNbCellsX(level - 1), -1);
920 Array2View<Integer> av_out(out.data(), numbering->globalNbCellsY(level - 1), numbering->globalNbCellsX(level - 1));
921 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(level - 1)) {
922 Integer pos_x = numbering->cellUniqueIdToCoordX(*icell);
923 Integer pos_y = numbering->cellUniqueIdToCoordY(*icell);
924 Integer pos_z = numbering->cellUniqueIdToCoordZ(*icell);
925 if (icell->hasHChildren()) {
926 if (icell->hChild(0).hasFlags(ItemFlags::II_Coarsen)) {
927 av_out(pos_y, pos_x) = 1;
928 }
929 else {
930 av_out(pos_y, pos_x) = 0;
931 }
932 }
933 }
934
935 StringBuilder str = "";
936 for (Integer i = 0; i < numbering->globalNbCellsX(level - 1); ++i) {
937 str += "\n";
938 for (Integer j = 0; j < numbering->globalNbCellsY(level - 1); ++j) {
939 Integer c = av_out(i, j);
940 if (c == 1)
941 str += "[--]";
942 else if (c == 0)
943 str += "[XX]";
944 else
945 str += "[ ]";
946 }
947 }
948 m_cmesh->traceMng()->info() << str;
949 }
950 */
951
952 amr->coarsen(true);
953 }
954 m_cmesh->computeDirections();
955
956 if (clear_refine_flag) {
957 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allCells()) {
958 if (icell->hasFlags(ItemFlags::II_Coarsen)) {
959 ARCANE_FATAL("Pas normal");
960 }
961 icell->mutableItemBase().removeFlags(ItemFlags::II_Refine);
962 }
963 }
964
965 // m_cmesh->traceMng()->info() << "NbPatch : " << m_cmesh->patches().size();
966 //
967 // for (Integer i = 0; i < m_cmesh->patches().size(); ++i) {
968 // auto patch = m_cmesh->amrPatch(i);
969 // m_cmesh->traceMng()->info() << "Patch #" << i;
970 // m_cmesh->traceMng()->info() << "\tMin Point : " << patch.patchInterface()->position().minPoint();
971 // m_cmesh->traceMng()->info() << "\tMax Point : " << patch.patchInterface()->position().maxPoint();
972 // m_cmesh->traceMng()->info() << "\tLevel : " << patch.patchInterface()->position().level();
973 // m_cmesh->traceMng()->info() << "\tNbCells : " << patch.patchInterface()->cells().size();
974 // m_cmesh->traceMng()->info() << "\tIndex : " << patch.patchInterface()->index();
975 // }
976}
977
978/*---------------------------------------------------------------------------*/
979/*---------------------------------------------------------------------------*/
980
981void CartesianPatchGroup::
982clearRefineRelatedFlags() const
983{
984 constexpr ItemFlags::FlagType flags_to_remove = (ItemFlags::II_Coarsen | ItemFlags::II_Refine |
985 ItemFlags::II_JustCoarsened | ItemFlags::II_JustRefined |
986 ItemFlags::II_JustAdded | ItemFlags::II_CoarsenInactive);
987 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allCells()) {
988 icell->mutableItemBase().removeFlags(flags_to_remove);
989 }
990}
991
992/*---------------------------------------------------------------------------*/
993/*---------------------------------------------------------------------------*/
994
995void CartesianPatchGroup::
996rebuildAvailableGroupIndex(ConstArrayView<Integer> available_group_index)
997{
998 m_available_group_index = available_group_index;
999}
1000
1001/*---------------------------------------------------------------------------*/
1002/*---------------------------------------------------------------------------*/
1003
1004ConstArrayView<Int32> CartesianPatchGroup::
1005availableGroupIndex()
1006{
1007 return m_available_group_index;
1008}
1009
1010/*---------------------------------------------------------------------------*/
1011/*---------------------------------------------------------------------------*/
1012
1013void CartesianPatchGroup::
1014setOverlapLayerSizeTopLevel(Int32 size_of_overlap_layer_top_level)
1015{
1016 m_size_of_overlap_layer_sub_top_level = (size_of_overlap_layer_top_level + 1) / 2;
1017}
1018
1019/*---------------------------------------------------------------------------*/
1020/*---------------------------------------------------------------------------*/
1021
1022Int32 CartesianPatchGroup::
1023overlapLayerSize(Int32 level)
1024{
1025 if (level < 0 || level > m_higher_level) {
1026 ARCANE_FATAL("Level doesn't exist");
1027 }
1028 if (level == m_higher_level) {
1029 return m_size_of_overlap_layer_sub_top_level * 2;
1030 }
1031 Integer nb_overlap_cells = m_size_of_overlap_layer_sub_top_level;
1032 for (Integer i = m_higher_level - 1; i > level; --i) {
1033 nb_overlap_cells /= 2;
1034 nb_overlap_cells += 1;
1035 }
1036 return nb_overlap_cells;
1037}
1038
1039/*---------------------------------------------------------------------------*/
1040/*---------------------------------------------------------------------------*/
1041
1042void CartesianPatchGroup::
1043_addPatchInstance(Ref<CartesianMeshPatch> v)
1044{
1045 m_amr_patches.add(v);
1046 m_amr_patches_pointer.add(v.get());
1047}
1048
1049/*---------------------------------------------------------------------------*/
1050/*---------------------------------------------------------------------------*/
1051
1052void CartesianPatchGroup::
1053_removeOnePatch(Integer index)
1054{
1055 m_available_group_index.add(m_amr_patches[index]->index());
1056 // m_cmesh->traceMng()->info() << "_removeOnePatch() -- Save group_index : " << m_available_group_index.back();
1057
1058 m_amr_patch_cell_groups_all[index - 1].clear();
1059 m_amr_patch_cell_groups_all.remove(index - 1);
1060
1061 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
1062 m_amr_patch_cell_groups_inpatch[index - 1].clear();
1063 m_amr_patch_cell_groups_inpatch.remove(index - 1);
1064 m_amr_patch_cell_groups_overall[index - 1].clear();
1065 m_amr_patch_cell_groups_overall.remove(index - 1);
1066 }
1067
1068 m_amr_patches_pointer.remove(index);
1069 m_amr_patches.remove(index);
1070}
1071
1072/*---------------------------------------------------------------------------*/
1073/*---------------------------------------------------------------------------*/
1074
1075// Le tableau doit être trié.
1076void CartesianPatchGroup::
1077_removeMultiplePatches(ConstArrayView<Integer> indexes)
1078{
1079 Integer count = 0;
1080 for (const Integer index : indexes) {
1081 _removeOnePatch(index - count);
1082 count++;
1083 }
1084}
1085
1086/*---------------------------------------------------------------------------*/
1087/*---------------------------------------------------------------------------*/
1088
1089void CartesianPatchGroup::
1090_removeAllPatches()
1091{
1092 Ref<CartesianMeshPatch> ground_patch = m_amr_patches.front();
1093
1094 for (CellGroup cell_group : m_amr_patch_cell_groups_all) {
1095 cell_group.clear();
1096 }
1097 m_amr_patch_cell_groups_all.clear();
1098
1099 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
1100 for (CellGroup cell_group : m_amr_patch_cell_groups_inpatch) {
1101 cell_group.clear();
1102 }
1103 for (CellGroup cell_group : m_amr_patch_cell_groups_overall) {
1104 cell_group.clear();
1105 }
1106 m_amr_patch_cell_groups_inpatch.clear();
1107 m_amr_patch_cell_groups_overall.clear();
1108 }
1109
1110 m_amr_patches_pointer.clear();
1111 m_amr_patches.clear();
1112 m_available_group_index.clear();
1113 m_patches_to_delete.clear();
1114 m_index_new_patches = 1;
1115
1116 m_amr_patches.add(ground_patch);
1117 m_amr_patches_pointer.add(ground_patch.get());
1118}
1119
1120/*---------------------------------------------------------------------------*/
1121/*---------------------------------------------------------------------------*/
1122
1123void CartesianPatchGroup::
1124_createGroundPatch()
1125{
1126 if (!m_amr_patches.empty())
1127 return;
1128 auto patch = makeRef(new CartesianMeshPatch(m_cmesh, -1));
1129 _addPatchInstance(patch);
1130
1131 if (m_cmesh->mesh()->meshKind().meshAMRKind() == eMeshAMRKind::PatchCartesianMeshOnly) {
1132 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
1133 patch->_internalApi()->positionRef().setMinPoint({ 0, 0, 0 });
1134 patch->_internalApi()->positionRef().setMaxPoint({ numbering->globalNbCellsX(0), numbering->globalNbCellsY(0), numbering->globalNbCellsZ(0) });
1135 patch->_internalApi()->positionRef().setLevel(0);
1136 }
1137}
1138
1139/*---------------------------------------------------------------------------*/
1140/*---------------------------------------------------------------------------*/
1141
1142void CartesianPatchGroup::
1143_addCellGroup(CellGroup cell_group, CartesianMeshPatch* patch)
1144{
1145 m_amr_patch_cell_groups_all.add(cell_group);
1146
1147 if (m_cmesh->mesh()->meshKind().meshAMRKind() != eMeshAMRKind::PatchCartesianMeshOnly) {
1148 // Patch non-régulier.
1149 // m_amr_patch_cell_groups_inpatch.add(cell_group);
1150 // m_amr_patch_cell_groups_overall.add(CellGroup());
1151 return;
1152 }
1153
1154 AMRPatchPosition patch_position = patch->position();
1155 Ref<ICartesianMeshNumberingMngInternal> numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
1156
1157 UniqueArray<Int32> inpatch_items_lid;
1158 UniqueArray<Int32> overall_items_lid;
1159
1160 ENUMERATE_ (Cell, icell, cell_group) {
1161 Cell cell = *icell;
1162 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(cell);
1163
1164 if (cell.isOwn() && patch_position.isIn(pos)) {
1165 inpatch_items_lid.add(cell.localId());
1166 }
1167 else {
1168 overall_items_lid.add(cell.localId());
1169 }
1170 }
1171
1172 CellGroup own = m_cmesh->mesh()->cellFamily()->createGroup(cell_group.name().clone() + "_InPatch", inpatch_items_lid, true);
1173 m_amr_patch_cell_groups_inpatch.add(own);
1174
1175 CellGroup overall = m_cmesh->mesh()->cellFamily()->createGroup(cell_group.name().clone() + "_Overall", overall_items_lid, true);
1176 m_amr_patch_cell_groups_overall.add(overall);
1177}
1178
1179/*---------------------------------------------------------------------------*/
1180/*---------------------------------------------------------------------------*/
1181
1182/*---------------------------------------------------------------------------*/
1183/*---------------------------------------------------------------------------*/
1184
1185// Il est nécessaire que le patch source et le patch part_to_remove soient
1186// en contact pour que cette méthode fonctionne.
1187void CartesianPatchGroup::
1188_splitPatch(Integer index_patch, const AMRPatchPosition& part_to_remove)
1189{
1190 // m_cmesh->traceMng()->info() << "Coarse Zone"
1191 // << " -- Min point : " << part_to_remove.minPoint()
1192 // << " -- Max point : " << part_to_remove.maxPoint()
1193 // << " -- Level : " << part_to_remove.level();
1194
1195 // p1 est le bout de patch qu'il faut retirer de p0.
1196 // On a donc uniquement quatre cas à traiter (sachant que p0 et p1 sont
1197 // forcément en contact en x et/ou y et/ou z).
1198 //
1199 // Cas 1 :
1200 // p0 |-----|
1201 // p1 |---------|
1202 // r = {-1, -1}
1203 //
1204 // Cas 2 :
1205 // p0 |-----|
1206 // p1 |-----|
1207 // r = {p1_min, -1}
1208 //
1209 // Cas 3 :
1210 // p0 |-----|
1211 // p1 |-----|
1212 // r = {-1, p1_max}
1213 //
1214 // Cas 4 :
1215 // p0 |-----|
1216 // p1 |---|
1217 // r = {p1_min, p1_max}
1218 auto cut_points_p0 = [](CartCoordType p0_min, CartCoordType p0_max, CartCoordType p1_min, CartCoordType p1_max) -> std::pair<CartCoordType, CartCoordType> {
1219 std::pair to_return{ -1, -1 };
1220 if (p1_min > p0_min && p1_min < p0_max) {
1221 to_return.first = p1_min;
1222 }
1223 if (p1_max > p0_min && p1_max < p0_max) {
1224 to_return.second = p1_max;
1225 }
1226 return to_return;
1227 };
1228
1229 ICartesianMeshPatch* patch = m_amr_patches_pointer[index_patch];
1230 AMRPatchPosition patch_position = patch->position();
1231
1232 UniqueArray<AMRPatchPosition> new_patch_out;
1233
1234 CartCoord3Type min_point_of_patch_to_exclude(-1, -1, -1);
1235
1236 // Partie découpe du patch autour de la zone à exclure.
1237 {
1238 UniqueArray<AMRPatchPosition> new_patch_in;
1239
1240 // On coupe le patch en x.
1241 {
1242 auto cut_point_x = cut_points_p0(patch_position.minPoint().x, patch_position.maxPoint().x, part_to_remove.minPoint().x, part_to_remove.maxPoint().x);
1243
1244 // p0 |-----|
1245 // p1 |---------|
1246 if (cut_point_x.first == -1 && cut_point_x.second == -1) {
1247 min_point_of_patch_to_exclude.x = patch_position.minPoint().x;
1248 new_patch_out.add(patch_position);
1249 }
1250 // p0 |-----|
1251 // p1 |-----|
1252 else if (cut_point_x.second == -1) {
1253 min_point_of_patch_to_exclude.x = cut_point_x.first;
1254 auto [fst, snd] = patch_position.cut(cut_point_x.first, MD_DirX);
1255 new_patch_out.add(fst);
1256 new_patch_out.add(snd);
1257 }
1258 // p0 |-----|
1259 // p1 |-----|
1260 else if (cut_point_x.first == -1) {
1261 min_point_of_patch_to_exclude.x = patch_position.minPoint().x;
1262 auto [fst, snd] = patch_position.cut(cut_point_x.second, MD_DirX);
1263 new_patch_out.add(fst);
1264 new_patch_out.add(snd);
1265 }
1266 // p0 |-----|
1267 // p1 |---|
1268 else {
1269 min_point_of_patch_to_exclude.x = cut_point_x.first;
1270 auto [fst, snd_thr] = patch_position.cut(cut_point_x.first, MD_DirX);
1271 new_patch_out.add(fst);
1272 auto [snd, thr] = snd_thr.cut(cut_point_x.second, MD_DirX);
1273 new_patch_out.add(snd);
1274 new_patch_out.add(thr);
1275 }
1276 }
1277
1278 // On coupe le patch en y.
1279 {
1280 std::swap(new_patch_out, new_patch_in);
1281
1282 auto cut_point_y = cut_points_p0(patch_position.minPoint().y, patch_position.maxPoint().y, part_to_remove.minPoint().y, part_to_remove.maxPoint().y);
1283
1284 // p0 |-----|
1285 // p1 |---------|
1286 if (cut_point_y.first == -1 && cut_point_y.second == -1) {
1287 for (const AMRPatchPosition& patch_x : new_patch_in) {
1288 min_point_of_patch_to_exclude.y = patch_x.minPoint().y;
1289 new_patch_out.add(patch_x);
1290 }
1291 }
1292 // p0 |-----|
1293 // p1 |-----|
1294 else if (cut_point_y.second == -1) {
1295 min_point_of_patch_to_exclude.y = cut_point_y.first;
1296 for (const AMRPatchPosition& patch_x : new_patch_in) {
1297 auto [fst, snd] = patch_x.cut(cut_point_y.first, MD_DirY);
1298 new_patch_out.add(fst);
1299 new_patch_out.add(snd);
1300 }
1301 }
1302 // p0 |-----|
1303 // p1 |-----|
1304 else if (cut_point_y.first == -1) {
1305 for (const AMRPatchPosition& patch_x : new_patch_in) {
1306 min_point_of_patch_to_exclude.y = patch_x.minPoint().y;
1307 auto [fst, snd] = patch_x.cut(cut_point_y.second, MD_DirY);
1308 new_patch_out.add(fst);
1309 new_patch_out.add(snd);
1310 }
1311 }
1312 // p0 |-----|
1313 // p1 |---|
1314 else {
1315 min_point_of_patch_to_exclude.y = cut_point_y.first;
1316 for (const AMRPatchPosition& patch_x : new_patch_in) {
1317 auto [fst, snd_thr] = patch_x.cut(cut_point_y.first, MD_DirY);
1318 new_patch_out.add(fst);
1319 auto [snd, thr] = snd_thr.cut(cut_point_y.second, MD_DirY);
1320 new_patch_out.add(snd);
1321 new_patch_out.add(thr);
1322 }
1323 }
1324 }
1325
1326 // On coupe le patch en z.
1327 if (m_cmesh->mesh()->dimension() == 3) {
1328 std::swap(new_patch_out, new_patch_in);
1329 new_patch_out.clear();
1330
1331 auto cut_point_z = cut_points_p0(patch_position.minPoint().z, patch_position.maxPoint().z, part_to_remove.minPoint().z, part_to_remove.maxPoint().z);
1332
1333 // p0 |-----|
1334 // p1 |---------|
1335 if (cut_point_z.first == -1 && cut_point_z.second == -1) {
1336 for (const AMRPatchPosition& patch_y : new_patch_in) {
1337 min_point_of_patch_to_exclude.z = patch_y.minPoint().z;
1338 new_patch_out.add(patch_y);
1339 }
1340 }
1341 // p0 |-----|
1342 // p1 |-----|
1343 else if (cut_point_z.second == -1) {
1344 for (const AMRPatchPosition& patch_y : new_patch_in) {
1345 min_point_of_patch_to_exclude.z = cut_point_z.first;
1346 auto [fst, snd] = patch_y.cut(cut_point_z.first, MD_DirZ);
1347 new_patch_out.add(fst);
1348 new_patch_out.add(snd);
1349 }
1350 }
1351 // p0 |-----|
1352 // p1 |-----|
1353 else if (cut_point_z.first == -1) {
1354 for (const AMRPatchPosition& patch_y : new_patch_in) {
1355 min_point_of_patch_to_exclude.z = patch_y.minPoint().z;
1356 auto [fst, snd] = patch_y.cut(cut_point_z.second, MD_DirZ);
1357 new_patch_out.add(fst);
1358 new_patch_out.add(snd);
1359 }
1360 }
1361 // p0 |-----|
1362 // p1 |---|
1363 else {
1364 for (const AMRPatchPosition& patch_y : new_patch_in) {
1365 min_point_of_patch_to_exclude.z = cut_point_z.first;
1366 auto [fst, snd_thr] = patch_y.cut(cut_point_z.first, MD_DirZ);
1367 new_patch_out.add(fst);
1368 auto [snd, thr] = snd_thr.cut(cut_point_z.second, MD_DirZ);
1369 new_patch_out.add(snd);
1370 new_patch_out.add(thr);
1371 }
1372 }
1373 }
1374 }
1375
1376 // Partie fusion et ajout.
1377 {
1378 if (m_cmesh->mesh()->dimension() == 2) {
1379 min_point_of_patch_to_exclude.z = 0;
1380 }
1381 // m_cmesh->traceMng()->info() << "Nb of new patch before fusion : " << new_patch_out.size();
1382 // m_cmesh->traceMng()->info() << "min_point_of_patch_to_exclude : " << min_point_of_patch_to_exclude;
1383
1384 // On met à null le patch représentant le bout de patch à retirer.
1385 for (AMRPatchPosition& new_patch : new_patch_out) {
1386 if (new_patch.minPoint() == min_point_of_patch_to_exclude) {
1387 new_patch.setLevel(-2); // Devient null.
1388 }
1389 // else {
1390 // m_cmesh->traceMng()->info() << "\tPatch before fusion"
1391 // << " -- Min point : " << new_patch.minPoint()
1392 // << " -- Max point : " << new_patch.maxPoint()
1393 // << " -- Level : " << new_patch.level();
1394 // }
1395 }
1396
1397 AMRPatchPositionLevelGroup::fusionPatches(new_patch_out, false);
1398
1399 // On ajoute les nouveaux patchs dans la liste des patchs.
1400 Integer d_nb_patch_final = 0;
1401 for (const auto& new_patch : new_patch_out) {
1402 if (!new_patch.isNull()) {
1403 // m_cmesh->traceMng()->info() << "\tNew cut patch"
1404 // << " -- Min point : " << new_patch.minPoint()
1405 // << " -- Max point : " << new_patch.maxPoint()
1406 // << " -- Level : " << new_patch.level();
1407 _addCutPatch(new_patch, m_amr_patch_cell_groups_all[index_patch - 1]);
1408 d_nb_patch_final++;
1409 }
1410 }
1411 // m_cmesh->traceMng()->info() << "Nb of new patch after fusion : " << d_nb_patch_final;
1412 }
1413
1414 removePatch(index_patch);
1415}
1416
1417/*---------------------------------------------------------------------------*/
1418/*---------------------------------------------------------------------------*/
1419
1420void CartesianPatchGroup::
1421_addCutPatch(const AMRPatchPosition& new_patch_position, CellGroup parent_patch_cell_group)
1422{
1423 // Si cette méthode est utilisé par une autre méthode que _splitPatch(),
1424 // voir si la mise à jour de m_higher_level est nécessaire.
1425 // (jusque-là, ce n'est pas utile vu qu'il y aura appel à applyPatchEdit()).
1426 if (parent_patch_cell_group.null())
1427 ARCANE_FATAL("Null cell group");
1428
1429 IItemFamily* cell_family = m_cmesh->mesh()->cellFamily();
1430 Integer group_index = _nextIndexForNewPatch();
1431 String patch_group_name = String("CartesianMeshPatchCells") + group_index;
1432
1433 auto* cdi = new CartesianMeshPatch(m_cmesh, group_index, new_patch_position);
1434 _addPatchInstance(makeRef(cdi));
1435
1436 UniqueArray<Int32> cells_local_id;
1437
1438 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
1439 ENUMERATE_ (Cell, icell, parent_patch_cell_group) {
1440 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
1441 if (new_patch_position.isIn(pos)) {
1442 cells_local_id.add(icell.localId());
1443 }
1444 }
1445
1446 CellGroup parent_cells = cell_family->createGroup(patch_group_name, cells_local_id, true);
1447 _addCellGroup(parent_cells, cdi);
1448
1449 // m_cmesh->traceMng()->info() << "_addCutPatch()"
1450 // << " -- m_amr_patch_cell_groups : " << m_amr_patch_cell_groups_all.size()
1451 // << " -- m_amr_patches : " << m_amr_patches.size()
1452 // << " -- group_index : " << group_index
1453 // << " -- cell_group name : " << m_amr_patch_cell_groups_all.back().name();
1454}
1455
1456/*---------------------------------------------------------------------------*/
1457/*---------------------------------------------------------------------------*/
1458
1459void CartesianPatchGroup::
1460_addPatch(const AMRPatchPosition& new_patch_position)
1461{
1462 UniqueArray<Int32> cells_local_id;
1463
1464 auto numbering = m_cmesh->_internalApi()->cartesianMeshNumberingMngInternal();
1465 ENUMERATE_ (Cell, icell, m_cmesh->mesh()->allLevelCells(new_patch_position.level())) {
1466 const CartCoord3Type pos = numbering->cellUniqueIdToCoord(*icell);
1467 if (new_patch_position.isInWithOverlap(pos)) {
1468 cells_local_id.add(icell.localId());
1469 }
1470 }
1471
1472 IItemFamily* cell_family = m_cmesh->mesh()->cellFamily();
1473 Integer group_index = _nextIndexForNewPatch();
1474 String patch_group_name = String("CartesianMeshPatchCells") + group_index;
1475
1476 auto* cdi = new CartesianMeshPatch(m_cmesh, group_index, new_patch_position);
1477
1478 _addPatchInstance(makeRef(cdi));
1479 CellGroup parent_cells = cell_family->createGroup(patch_group_name, cells_local_id, true);
1480 _addCellGroup(parent_cells, cdi);
1481
1482 if (new_patch_position.level() > m_higher_level) {
1483 m_higher_level = new_patch_position.level();
1484 }
1485
1486 // m_cmesh->traceMng()->info() << "_addPatch()"
1487 // << " -- m_amr_patch_cell_groups : " << m_amr_patch_cell_groups_all.size()
1488 // << " -- m_amr_patches : " << m_amr_patches.size()
1489 // << " -- group_index : " << group_index
1490 // << " -- cell_group name : " << m_amr_patch_cell_groups_all.back().name();
1491}
1492
1493/*---------------------------------------------------------------------------*/
1494/*---------------------------------------------------------------------------*/
1495
1496} // End namespace Arcane
1497
1498/*---------------------------------------------------------------------------*/
1499/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Interface d'un maillage cartésien.
virtual ItemGroup createGroup(const String &name, Int32ConstArrayView local_ids, bool do_override=false)=0
Créé un groupe d'entités de nom name contenant les entités local_ids.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
IMesh * mesh() const
Maillage auquel appartient ce groupe (0 pour le group nul)
Definition ItemGroup.h:126
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
@ MD_DirZ
Direction Z.
@ MD_DirY
Direction Y.
@ MD_DirX
Direction X.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52