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