Arcane  v3.16.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
CartesianMeshAMRPatchMng.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/* CartesianMeshAMRPatchMng.cc (C) 2000-2025 */
9/* */
10/* Gestionnaire de l'AMR par patch d'un maillage cartésien. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include <arcane/cartesianmesh/CartesianMeshAMRPatchMng.h>
15
16#include "arcane/cartesianmesh/CellDirectionMng.h"
17#include "arcane/cartesianmesh/CartesianMeshNumberingMng.h"
18#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
19
20#include "arcane/utils/Array2View.h"
21#include "arcane/utils/Array3View.h"
22#include "arcane/utils/FixedArray.h"
23#include "arcane/utils/Vector2.h"
24
25#include "arcane/core/IGhostLayerMng.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/ItemPrinter.h"
28#include "arcane/core/IParallelMng.h"
29#include "arcane/core/VariableTypes.h"
30#include "arcane/core/IMeshModifier.h"
31#include "arcane/core/materials/IMeshMaterialMng.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42CartesianMeshAMRPatchMng::
43CartesianMeshAMRPatchMng(ICartesianMesh* cmesh, ICartesianMeshNumberingMng* numbering_mng)
44: TraceAccessor(cmesh->mesh()->traceMng())
45, m_mesh(cmesh->mesh())
46, m_cmesh(cmesh)
47, m_num_mng(numbering_mng)
48{
49}
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
54void CartesianMeshAMRPatchMng::
55flagCellToRefine(const Int32ConstArrayView cells_lids, const bool clear_old_flags)
56{
57 if (clear_old_flags) {
58 constexpr ItemFlags::FlagType flags_to_remove = (
62 );
63 ENUMERATE_(Cell, icell, m_mesh->allCells()){
64 icell->mutableItemBase().removeFlags(flags_to_remove);
65 }
66 }
67
68 const ItemInfoListView cells(m_mesh->cellFamily());
69 for (const int lid : cells_lids) {
70 Item item = cells[lid];
72 }
73 _syncFlagCell();
74}
75
76/*---------------------------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78
79void CartesianMeshAMRPatchMng::
80flagCellToCoarsen(const Int32ConstArrayView cells_lids, const bool clear_old_flags)
81{
82 if (clear_old_flags) {
83 constexpr ItemFlags::FlagType flags_to_remove = (
87 );
88 ENUMERATE_(Cell, icell, m_mesh->allCells()){
89 icell->mutableItemBase().removeFlags(flags_to_remove);
90 }
91 }
92
93 const ItemInfoListView cells(m_mesh->cellFamily());
94 for (const Integer lid : cells_lids) {
95 Item item = cells[lid];
97 }
98 _syncFlagCell();
99}
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
104void CartesianMeshAMRPatchMng::
105_syncFlagCell() const
106{
107 if (!m_mesh->parallelMng()->isParallel())
108 return;
109
110 VariableCellInteger flag_cells_consistent(VariableBuildInfo(m_mesh, "FlagCellsConsistent"));
111 ENUMERATE_ (Cell, icell, m_mesh->ownCells()) {
112 Cell cell = *icell;
113 flag_cells_consistent[cell] = cell.mutableItemBase().flags();
114 // debug() << "Send " << cell
115 // << " -- flag : " << cell.mutableItemBase().flags()
116 // << " -- II_Refine : " << (cell.itemBase().flags() & ItemFlags::II_Refine)
117 // << " -- II_Inactive : " << (cell.itemBase().flags() & ItemFlags::II_Inactive)
118 // ;
119 }
120
121 flag_cells_consistent.synchronize();
122
123 ENUMERATE_ (Cell, icell, m_mesh->allCells().ghost()) {
124 Cell cell = *icell;
125
126 // On ajoute uniquement les flags qui nous interesse (pour éviter d'ajouter le flag "II_Own" par exemple).
127 // On utilise set au lieu de add puisqu'une maille ne peut être à la fois II_Refine et II_Inactive.
128 if (flag_cells_consistent[cell] & ItemFlags::II_Refine) {
129 cell.mutableItemBase().setFlags(ItemFlags::II_Refine);
130 }
131 if (flag_cells_consistent[cell] & ItemFlags::II_Inactive) {
132 cell.mutableItemBase().setFlags(ItemFlags::II_Inactive);
133 }
134 if (flag_cells_consistent[cell] & ItemFlags::II_Coarsen) {
135 cell.mutableItemBase().setFlags(ItemFlags::II_Coarsen);
136 }
137
138 // debug() << "After Compute " << cell
139 // << " -- flag : " << cell.mutableItemBase().flags()
140 // << " -- II_Refine : " << (cell.itemBase().flags() & ItemFlags::II_Refine)
141 // << " -- II_Inactive : " << (cell.itemBase().flags() & ItemFlags::II_Inactive)
142 // ;
143 }
144}
145
146/*---------------------------------------------------------------------------*/
147/*---------------------------------------------------------------------------*/
148
149/*
150 * Pour les commentaires de cette méthode, on considère le repère suivant :
151 * (top)
152 * y (front)
153 * ^ z
154 * | /
155 * | /
156 * (left) ------->x (right)
157 * (rear)(bottom)
158 */
159void CartesianMeshAMRPatchMng::
160refine()
161{
162 IParallelMng* pm = m_mesh->parallelMng();
163 Int32 my_rank = pm->commRank();
164 Int32 max_level = 0;
165
166 UniqueArray<Cell> cell_to_refine_internals;
167 ENUMERATE_ (Cell, icell, m_mesh->allActiveCells()) {
168 Cell cell = *icell;
169 if (cell.itemBase().flags() & ItemFlags::II_Refine) {
170 cell_to_refine_internals.add(cell);
171 if (cell.level() > max_level)
172 max_level = cell.level();
173 }
174 }
175 m_num_mng->prepareLevel(max_level + 1);
176
177 UniqueArray<Int64> cells_infos;
178 UniqueArray<Int64> faces_infos;
179 UniqueArray<Int64> nodes_infos;
180
181 Integer total_nb_cells = 0;
182 Integer total_nb_nodes = 0;
183 Integer total_nb_faces = 0;
184
185 std::unordered_map<Int64, Int32> node_uid_to_owner;
186 std::unordered_map<Int64, Int32> face_uid_to_owner;
187
188 UniqueArray<Int64> node_uid_change_owner_only;
189 UniqueArray<Int64> face_uid_change_owner_only;
190
191 // Deux tableaux permettant de récupérer les uniqueIds des noeuds et des faces
192 // de chaque maille enfant à chaque appel à getNodeUids()/getFaceUids().
193 UniqueArray<Int64> child_nodes_uids(m_num_mng->nbNodeByCell());
194 UniqueArray<Int64> child_faces_uids(m_num_mng->nbFaceByCell());
195
196 // On doit enregistrer les mailles parentes de chaque maille enfant pour mettre à jour les connectivités
197 // lors de la création des mailles.
198 UniqueArray<Cell> parent_cells;
199
200 // Maps remplaçant les mailles fantômes.
201 std::unordered_map<Int64, Integer> around_parent_cells_uid_to_owner;
202 std::unordered_map<Int64, Int32> around_parent_cells_uid_to_flags;
203
204 {
205 // On a uniquement besoin de ses deux flags pour les mailles autour.
206 // (II_Refine pour savoir si les mailles autour sont dans le même patch)
207 // (II_Inactive pour savoir si les mailles autour sont déjà raffinées)
209 _shareInfosOfCellsAroundPatch(cell_to_refine_internals, around_parent_cells_uid_to_owner, around_parent_cells_uid_to_flags, useful_flags);
210 }
211
212 if (m_mesh->dimension() == 2) {
213
214 // Masques pour les cas "voisins enfants" et "voisins parents du même patch".
215 // Ces masques permettent de savoir si l'on doit créer un noeud ou pas selon
216 // les mailles autour.
217 // Par exemple, si l'on est en train d'étudier une maille enfant et qu'il y a
218 // une maille enfant à gauche, on ne doit pas créer les noeuds 0 et 3 (mask_node_if_cell_left[]) (car
219 // ils ont déjà été créés par la maille à gauche).
220 // Idem pour les mailles parentes voisines : si l'on est sur une maille enfant située
221 // sur la partie gauche de la maille parente (mailles enfants 0 et 2 dans le cas d'un
222 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille parente
223 // est en train ((d'être raffiné et à notre sous-domaine) ou (qu'elle est inactive)), on applique
224 // la règle mask_node_if_cell_left[] car les noeuds ont été créé par celle-ci et on veut éviter
225 // les noeuds en doubles.
226 // Ces masques permettent aussi de déterminer le propriétaire des noeuds dans
227 // le cas de multiples sous-domaines.
228 // Par exemple, si l'on est sur une maille enfant située
229 // sur la partie gauche de la maille parente (mailles enfants 0 et 2 dans le cas d'un
230 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille
231 // parente (appartient à un autre sous-domaine) et (est en train d'être raffiné),
232 // on crée ce noeud mais on lui donne comme propriétaire le processus à qui appartient
233 // la maille parente à gauche.
234 constexpr bool mask_node_if_cell_left[] = { false, true, true, false };
235 constexpr bool mask_node_if_cell_bottom[] = { false, false, true, true };
236
237 constexpr bool mask_node_if_cell_right[] = { true, false, false, true };
238 constexpr bool mask_node_if_cell_top[] = { true, true, false, false };
239
240 constexpr bool mask_face_if_cell_left[] = { true, true, true, false };
241 constexpr bool mask_face_if_cell_bottom[] = { false, true, true, true };
242
243 constexpr bool mask_face_if_cell_right[] = { true, false, true, true };
244 constexpr bool mask_face_if_cell_top[] = { true, true, false, true };
245
246 // Pour la taille :
247 // - on a "cell_to_refine_internals.size() * 4" mailles enfants,
248 // - pour chaque maille, on a 2 infos (type de maille et uniqueId de la maille)
249 // - pour chaque maille, on a "m_num_mng->getNbNode()" uniqueIds (les uniqueId de chaque noeud de la maille).
250 cells_infos.reserve((cell_to_refine_internals.size() * 4) * (2 + m_num_mng->nbNodeByCell()));
251
252 // Pour la taille, au maximum :
253 // - on a "cell_to_refine_internals.size() * 12" faces
254 // - pour chaque face, on a 2 infos (type de face et uniqueId de la face)
255 // - pour chaque face, on a 2 uniqueIds de noeuds.
256 faces_infos.reserve((cell_to_refine_internals.size() * 12) * (2 + 2));
257
258 // Pour la taille, au maximum :
259 // - on a (cell_to_refine_internals.size() * 9) uniqueIds de noeuds.
260 nodes_infos.reserve(cell_to_refine_internals.size() * 9);
261
262 FixedArray<Int64, 9> uid_cells_around_parent_cell_1d;
263 FixedArray<Int32, 9> owner_cells_around_parent_cell_1d;
264 FixedArray<Int32, 9> flags_cells_around_parent_cell_1d;
265
266 for (Cell parent_cell : cell_to_refine_internals) {
267 const Int64 parent_cell_uid = parent_cell.uniqueId();
268 const Int32 parent_cell_level = parent_cell.level();
269 const bool parent_cell_is_own = (parent_cell.owner() == my_rank);
270
271 const Int64 parent_coord_x = m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, parent_cell_level);
272 const Int64 parent_coord_y = m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, parent_cell_level);
273
274 const Int64 child_coord_x = m_num_mng->offsetLevelToLevel(parent_coord_x, parent_cell_level, parent_cell_level + 1);
275 const Int64 child_coord_y = m_num_mng->offsetLevelToLevel(parent_coord_y, parent_cell_level, parent_cell_level + 1);
276
277 const Integer pattern = m_num_mng->pattern();
278
279 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_parent_cell_1d.view(), parent_cell);
280
281 for (Integer i = 0; i < 9; ++i) {
282 Int64 uid_cell = uid_cells_around_parent_cell_1d[i];
283 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
284 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
285 if (uid_cell != -1 && around_parent_cells_uid_to_owner[uid_cell] != -1) {
286 owner_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_owner[uid_cell];
287 flags_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_flags[uid_cell];
288 }
289 else {
290 uid_cells_around_parent_cell_1d[i] = -1;
291 owner_cells_around_parent_cell_1d[i] = -1;
292 flags_cells_around_parent_cell_1d[i] = 0;
293 }
294 }
295
296 // Pour simplifier, on utilise des vues 2D. (array[Y][X]).
297 ConstArray2View uid_cells_around_parent_cell(uid_cells_around_parent_cell_1d.data(), 3, 3);
298 ConstArray2View owner_cells_around_parent_cell(owner_cells_around_parent_cell_1d.data(), 3, 3);
299 ConstArray2View flags_cells_around_parent_cell(flags_cells_around_parent_cell_1d.data(), 3, 3);
300
301 // #priority_owner_2d
302 // Voici les priorités pour la propriété des noeuds et des faces :
303 // ┌─────────┐
304 // │6 7 8│
305 // └───────┐ │
306 // ┌─┐ ┌─┐ │ │
307 // │3│ │4│ │5│
308 // │ │ └─┘ └─┘
309 // │ └───────┐
310 // │0 1 2│
311 // └─────────┘
312 //
313 // ^y
314 // |
315 // ->x
316
317 // #arcane_order_to_around_2d
318 // Note pour les maillages cartésiens 2D :
319 // Les itérateurs sur les faces itèrent dans l'ordre (pour la maille 4 ici) :
320 // 1. Face entre [4, 1],
321 // 2. Face entre [4, 5],
322 // 3. Face entre [4, 7],
323 // 4. Face entre [4, 3],
324 //
325 // Les itérateurs sur les noeuds itèrent dans l'ordre (pour la maille 4 ici) :
326 // 1. Noeud entre [4, 0]
327 // 2. Noeud entre [4, 2]
328 // 3. Noeud entre [4, 8]
329 // 4. Noeud entre [4, 6]
330
331 // Chaque chiffre désigne une maille parente et une priorité (0 étant la priorité la plus forte).
332 // 4 = parent_cell ("nous")
333
334 // Exemple 1 :
335 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
336 // En bas, il n'y a pas de mailles.
337 // À gauche (donc priorité 3), il y a une maille qui est déjà raffinée (flag "II_Inactive").
338 // On est priorité 4 donc il est prioritaire. Donc les noeuds et des faces que l'on a en commun
339 // lui appartiennent.
340
341 // Exemple 2 :
342 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
343 // En haut, il y a des mailles déjà raffinées (flag "II_Inactive").
344 // On est prioritaire sur elles, on récupère donc la propriété des noeuds et des faces que l'on a
345 // en commun. Ce changement de propriété doit leur être signalé.
346
347 // On simplifie avec un tableau de booléens.
348 // Si true, alors on doit appliquer la priorité de propriété.
349 // Si false, alors on considère qu'il n'y a pas de maille à la position définie.
350 FixedArray<FixedArray<bool, 3>, 3> is_cell_around_parent_cell_present_and_useful;
351
352 // Pour les mailles prioritaires sur nous, on doit regarder les deux flags.
353 // Si une maille a le flag "II_Refine", on n'existe pas pour elle donc elle prend la propriété
354 // des faces et des noeuds qu'on a en commun.
355 // Si une maille a le flag "II_Inactive", elle a déjà les bons propriétaires.
356 // Quoi qu'il en soit, si true alors les faces et noeuds qu'on a en commun leurs appartiennent.
357 is_cell_around_parent_cell_present_and_useful[0][0] = ((uid_cells_around_parent_cell(0, 0) != -1) && (flags_cells_around_parent_cell(0, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
358 is_cell_around_parent_cell_present_and_useful[0][1] = ((uid_cells_around_parent_cell(0, 1) != -1) && (flags_cells_around_parent_cell(0, 1) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
359 is_cell_around_parent_cell_present_and_useful[0][2] = ((uid_cells_around_parent_cell(0, 2) != -1) && (flags_cells_around_parent_cell(0, 2) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
360
361 is_cell_around_parent_cell_present_and_useful[1][0] = ((uid_cells_around_parent_cell(1, 0) != -1) && (flags_cells_around_parent_cell(1, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
362 // is_cell_around_parent_cell_present_and_useful[1][1] = parent_cell;
363
364 // Pour les mailles non prioritaires, on doit regarder qu'un seul flag.
365 // Si une maille a le flag "II_Inactive", alors elle doit être avertie qu'on récupère la propriété
366 // des noeuds et des faces qu'on a en commun.
367 // On ne regarde pas le flag "II_Refine" car, si ces mailles sont aussi en train d'être raffinée,
368 // elles savent qu'on existe et qu'on obtient la propriété des noeuds et des faces qu'on a en commun.
369 // En résumé, si true alors les faces et noeuds qu'on a en commun nous appartiennent.
370 is_cell_around_parent_cell_present_and_useful[1][2] = ((uid_cells_around_parent_cell(1, 2) != -1) && (flags_cells_around_parent_cell(1, 2) & ItemFlags::II_Inactive));
371
372 is_cell_around_parent_cell_present_and_useful[2][0] = ((uid_cells_around_parent_cell(2, 0) != -1) && (flags_cells_around_parent_cell(2, 0) & ItemFlags::II_Inactive));
373 is_cell_around_parent_cell_present_and_useful[2][1] = ((uid_cells_around_parent_cell(2, 1) != -1) && (flags_cells_around_parent_cell(2, 1) & ItemFlags::II_Inactive));
374 is_cell_around_parent_cell_present_and_useful[2][2] = ((uid_cells_around_parent_cell(2, 2) != -1) && (flags_cells_around_parent_cell(2, 2) & ItemFlags::II_Inactive));
375
376 // En plus de regarder si chaque maille parent autour de notre maille parent existe et possède (II_Inactive) ou possédera (II_Refine) des enfants...
377 // ... on regarde si chaque maille parent est présente sur notre sous-domaine, que ce soit une maille fantôme ou non.
378 auto is_cell_around_parent_cell_in_subdomain = [&](const Integer y, const Integer x) {
379 return is_cell_around_parent_cell_present_and_useful[y][x] && (flags_cells_around_parent_cell(y, x) & ItemFlags::II_UserMark1);
380 };
381
382 // ... on regarde si chaque maille parent est possédé par le même propriétaire que notre maille parent.
383 auto is_cell_around_parent_cell_same_owner = [&](const Integer y, const Integer x) {
384 return is_cell_around_parent_cell_present_and_useful[y][x] && (owner_cells_around_parent_cell(y, x) == owner_cells_around_parent_cell(1, 1));
385 };
386
387 // ... on regarde si chaque maille parent a un propriétaire différent par rapport à notre maille parent.
388 auto is_cell_around_parent_cell_different_owner = [&](const Integer y, const Integer x) {
389 return is_cell_around_parent_cell_present_and_useful[y][x] && (owner_cells_around_parent_cell(y, x) != owner_cells_around_parent_cell(1, 1));
390 };
391
392 // On itère sur toutes les mailles enfants.
393 for (Int64 j = child_coord_y; j < child_coord_y + pattern; ++j) {
394 for (Int64 i = child_coord_x; i < child_coord_x + pattern; ++i) {
395 parent_cells.add(parent_cell);
396 total_nb_cells++;
397
398 const Int64 child_cell_uid = m_num_mng->cellUniqueId(parent_cell_level + 1, Int64x2(i, j));
399 // debug() << "Child -- x : " << i << " -- y : " << j << " -- level : " << parent_cell_level + 1 << " -- uid : " << child_cell_uid;
400
401 m_num_mng->cellNodeUniqueIds(child_nodes_uids, parent_cell_level + 1, Int64x2(i, j));
402 m_num_mng->cellFaceUniqueIds(child_faces_uids, parent_cell_level + 1, Int64x2(i, j));
403
404 constexpr Integer type_cell = IT_Quad4;
405 constexpr Integer type_face = IT_Line2;
406
407 // Partie Cell.
408 cells_infos.add(type_cell);
409 cells_infos.add(child_cell_uid);
410 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
411 cells_infos.add(child_nodes_uids[nc]);
412 }
413
414 // Partie Face.
415 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
416 Integer child_face_owner = -1;
417 bool is_new_face = false;
418
419 // Deux parties :
420 // D'abord, on regarde si l'on doit créer la face l. Pour cela, on doit regarder si elle est présente sur la
421 // maille à côté.
422 // Pour gauche/bas, c'est le même principe. Si la maille enfant est tout à gauche/bas de la maille parente, on regarde
423 // s'il y a une maille parente à gauche/bas. Sinon, on crée la face. Si oui, on regarde le masque pour savoir si l'on
424 // doit créer la face.
425 // Pour droite/haut, le principe est différent de gauche/bas. On ne suit le masque que si on est tout à droite/haut
426 // de la maille parente. Sinon on crée toujours les faces droites/hautes.
427 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
428 // notre sous-domaine, alors il se peut que les faces en communes avec notre maille parente existent déjà, dans ce cas,
429 // pas de doublon.
430 if (
431 ((i == child_coord_x && !is_cell_around_parent_cell_in_subdomain(1, 0)) || (mask_face_if_cell_left[l])) &&
432 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2)) || mask_face_if_cell_right[l]) &&
433 ((j == child_coord_y && !is_cell_around_parent_cell_in_subdomain(0, 1)) || (mask_face_if_cell_bottom[l])) &&
434 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1)) || mask_face_if_cell_top[l])) {
435 is_new_face = true;
436 faces_infos.add(type_face);
437 faces_infos.add(child_faces_uids[l]);
438
439 // Les noeuds de la face sont toujours les noeuds l et l+1
440 // car on utilise la même exploration pour les deux cas.
441 for (Integer nc = l; nc < l + 2; nc++) {
442 faces_infos.add(child_nodes_uids[nc % m_num_mng->nbNodeByCell()]);
443 }
444 total_nb_faces++;
445
446 // Par défaut, parent_cell est propriétaire de la nouvelle face.
447 child_face_owner = owner_cells_around_parent_cell(1, 1);
448 }
449
450 // Deuxième partie.
451 // On doit maintenant trouver le bon propriétaire pour la face. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
452 // la condition est identique à celle au-dessus.
453 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr qu'il y a la face qui nous intéresse.
454 // Le nouveau tableau permet de savoir si la maille d'à côté est aussi à nous ou pas. Si ce n'est pas le cas, alors
455 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
456 // si la maille est présente sur le sous-domaine.
457 if (
458 ((i == child_coord_x && !is_cell_around_parent_cell_same_owner(1, 0)) || (mask_face_if_cell_left[l])) &&
459 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2)) || mask_face_if_cell_right[l]) &&
460 ((j == child_coord_y && !is_cell_around_parent_cell_same_owner(0, 1)) || (mask_face_if_cell_bottom[l])) &&
461 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1)) || mask_face_if_cell_top[l])) {
462 // Ici, la construction des conditions est la même à chaque fois.
463 // Le premier booléen (i == child_coord_x) regarde si l'enfant se trouve
464 // du bon côté de la maille parent.
465 // Le second booléen (!mask_face_if_cell_left[l]) nous dit si la face l est bien
466 // la face en commun avec la maille parent d'à côté.
467 // Le troisième booléen (is_cell_around_parent_cell_different_owner(1, 0)) regarde s'il y a une
468 // maille à côté qui prend la propriété de la face ou à qui on prend la propriété.
469
470 // En outre, il y a deux cas différents selon les priorités définies au-dessus :
471 // - soit nous ne sommes pas prioritaire, alors on attribue le propriétaire prioritaire à notre face,
472 // - soit nous sommes prioritaire, alors on se positionne comme propriétaire de la face et on doit prévenir
473 // tous les autres processus (le processus ancien propriétaire mais aussi les processus qui peuvent
474 // avoir la face en fantôme).
475
476 // Enfin, dans le cas du changement de propriétaire, seul le processus (re)prenant la propriété doit
477 // faire une communication à ce propos. Les processus ne possédant que la face en fantôme ne doit pas
478 // faire de communication (mais ils peuvent définir localement le bon propriétaire, TODO Optimisation possible ?).
479
480 // À gauche, priorité 3 < 4 donc il prend la propriété de la face.
481 if (i == child_coord_x && (!mask_face_if_cell_left[l]) && is_cell_around_parent_cell_different_owner(1, 0)) {
482 child_face_owner = owner_cells_around_parent_cell(1, 0);
483 }
484
485 // En bas, priorité 1 < 4 donc il prend la propriété de la face.
486 else if (j == child_coord_y && (!mask_face_if_cell_bottom[l]) && is_cell_around_parent_cell_different_owner(0, 1)) {
487 child_face_owner = owner_cells_around_parent_cell(0, 1);
488 }
489
490 // Sinon, parent_cell est propriétaire de la face.
491 else {
492
493 // Sinon, c'est une face interne donc au parent_cell.
494 child_face_owner = owner_cells_around_parent_cell(1, 1);
495 }
496 }
497
498 // S'il y a une création de face et/ou un changement de propriétaire.
499 if (child_face_owner != -1) {
500 face_uid_to_owner[child_faces_uids[l]] = child_face_owner;
501
502 // Lorsqu'il y a un changement de propriétaire sans création de face,
503 // on doit mettre de côté les uniqueIds de ces faces pour pouvoir
504 // itérer dessus par la suite.
505 if (!is_new_face) {
506 face_uid_change_owner_only.add(child_faces_uids[l]);
507 // debug() << "Child face (change owner) -- x : " << i
508 // << " -- y : " << j
509 // << " -- level : " << parent_cell_level + 1
510 // << " -- face : " << l
511 // << " -- uid_face : " << child_faces_uids[l]
512 // << " -- owner : " << child_face_owner;
513 }
514 else {
515 // debug() << "Child face (create face) -- x : " << i
516 // << " -- y : " << j
517 // << " -- level : " << parent_cell_level + 1
518 // << " -- face : " << l
519 // << " -- uid_face : " << child_faces_uids[l]
520 // << " -- owner : " << child_face_owner;
521 }
522 }
523 }
524
525 // Partie Node.
526 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
527 // plus de propriétaires possibles.
528 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
529 Integer child_node_owner = -1;
530 bool is_new_node = false;
531
532 // Deux parties :
533 // D'abord, on regarde si l'on doit créer le noeud l. Pour cela, on doit regarder s'il est présente sur la
534 // maille à côté.
535 // Pour gauche/bas, c'est le même principe. Si la maille enfant est tout à gauche/bas de la maille parente, on regarde
536 // s'il y a une maille parente à gauche/bas. Sinon, on crée le noeud. Si oui, on regarde le masque pour savoir si l'on
537 // doit créer le noeud.
538 // Pour droite/haut, le principe est différent de gauche/bas. On ne suit le masque que si la maille enfant est toute à droite/haut
539 // de la maille parente. Sinon on crée toujours les noeuds droites/hautes.
540 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
541 // notre sous-domaine, alors il se peut que les noeuds en communs avec notre maille parente existent déjà, dans ce cas,
542 // pas de doublon.
543 if (
544 ((i == child_coord_x && !is_cell_around_parent_cell_in_subdomain(1, 0)) || (mask_node_if_cell_left[l])) &&
545 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2)) || mask_node_if_cell_right[l]) &&
546 ((j == child_coord_y && !is_cell_around_parent_cell_in_subdomain(0, 1)) || (mask_node_if_cell_bottom[l])) &&
547 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1)) || mask_node_if_cell_top[l])) {
548 is_new_node = true;
549 nodes_infos.add(child_nodes_uids[l]);
550 total_nb_nodes++;
551
552 // Par défaut, parent_cell est propriétaire du nouveau noeud.
553 child_node_owner = owner_cells_around_parent_cell(1, 1);
554 }
555
556 // Deuxième partie.
557 // On doit maintenant trouver le bon propriétaire pour le noeud. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
558 // la condition est identique à celle au-dessus.
559 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr que le noeud qui nous intéresse existe.
560 // Le nouveau tableau permet de savoir si la maille d'à côté est aussi à nous ou pas. Si ce n'est pas le cas, alors
561 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
562 // si la maille est présente sur le sous-domaine.
563 if (
564 ((i == child_coord_x && !is_cell_around_parent_cell_same_owner(1, 0)) || (mask_node_if_cell_left[l])) &&
565 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2)) || mask_node_if_cell_right[l]) &&
566 ((j == child_coord_y && !is_cell_around_parent_cell_same_owner(0, 1)) || (mask_node_if_cell_bottom[l])) &&
567 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1)) || mask_node_if_cell_top[l])) {
568 // Par rapport aux faces qui n'ont que deux propriétaires possibles, un noeud peut
569 // en avoir jusqu'à quatre.
570 // (Et oui, en 3D, c'est encore plus amusant !)
571
572 // Si le noeud est sur le côté gauche de la maille parente ("sur la face gauche").
573 if (i == child_coord_x && (!mask_node_if_cell_left[l])) {
574
575 // Si le noeud est sur le bas de la maille parente ("sur la face basse").
576 // Donc noeud en bas à gauche (même position que le noeud de la maille parente).
577 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
578
579 // Priorité 0 < 4.
580 if (is_cell_around_parent_cell_different_owner(0, 0)) {
581 child_node_owner = owner_cells_around_parent_cell(0, 0);
582 }
583
584 // Priorité 1 < 4.
585 else if (is_cell_around_parent_cell_different_owner(0, 1)) {
586 child_node_owner = owner_cells_around_parent_cell(0, 1);
587 }
588
589 // Priorité 3 < 4.
590 else if (is_cell_around_parent_cell_different_owner(1, 0)) {
591 child_node_owner = owner_cells_around_parent_cell(1, 0);
592 }
593
594 else {
595 child_node_owner = owner_cells_around_parent_cell(1, 1);
596 }
597 }
598
599 // Si le noeud est en haut de la maille parente ("sur la face haute").
600 // Donc noeud en haut à gauche (même position que le noeud de la maille parente).
601 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
602
603 // Priorité 3 < 4.
604 if (is_cell_around_parent_cell_different_owner(1, 0)) {
605 child_node_owner = owner_cells_around_parent_cell(1, 0);
606 }
607
608 // Sinon, parent_cell est propriétaire du noeud.
609 else {
610 child_node_owner = owner_cells_around_parent_cell(1, 1);
611 }
612 }
613
614 // Si le noeud est quelque part sur la face parente gauche...
615 else {
616 // S'il y a une maille à gauche, elle est propriétaire du noeud.
617 if (is_cell_around_parent_cell_different_owner(1, 0)) {
618 child_node_owner = owner_cells_around_parent_cell(1, 0);
619 }
620
621 // Sinon parent_cell est propriétaire du noeud.
622 else {
623 child_node_owner = owner_cells_around_parent_cell(1, 1);
624 }
625 }
626 }
627
628 // Si le noeud est sur le côté droit de la maille parente ("sur la face droite").
629 else if (i == (child_coord_x + pattern - 1) && (!mask_node_if_cell_right[l])) {
630
631 // Si le noeud est sur le bas de la maille parente ("sur la face basse").
632 // Donc noeud en bas à droite (même position que le noeud de la maille parente).
633 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
634
635 // Priorité 1 < 4.
636 if (is_cell_around_parent_cell_different_owner(0, 1)) {
637 child_node_owner = owner_cells_around_parent_cell(0, 1);
638 }
639
640 // Priorité 2 < 4.
641 else if (is_cell_around_parent_cell_different_owner(0, 2)) {
642 child_node_owner = owner_cells_around_parent_cell(0, 2);
643 }
644
645 // Sinon, parent_cell est propriétaire du noeud.
646 else {
647 child_node_owner = owner_cells_around_parent_cell(1, 1);
648 }
649 }
650
651 // Si le noeud est en haut de la maille parente ("sur la face haute").
652 // Donc noeud en haut à droite (même position que le noeud de la maille parente).
653 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
654 child_node_owner = owner_cells_around_parent_cell(1, 1);
655 }
656
657 // Si le noeud est quelque part sur la face parente droite...
658 else {
659 child_node_owner = owner_cells_around_parent_cell(1, 1);
660 }
661 }
662
663 // Si le noeud est ni sur la face parente gauche, ni sur la face parente droite...
664 else {
665
666 // Si le noeud est sur le bas de la maille parente ("sur la face basse") et
667 // qu'il y a une maille en bas de priorité 1 < 4, elle est propriétaire du noeud.
668 if (j == child_coord_y && (!mask_node_if_cell_bottom[l]) && is_cell_around_parent_cell_different_owner(0, 1)) {
669 child_node_owner = owner_cells_around_parent_cell(0, 1);
670 }
671
672 // Si le noeud est sur le haut de la maille parente ("sur la face haute") et
673 // qu'il y a une maille en haut de priorité 7 > 4, parent_cell est propriétaire du noeud.
674 else if (parent_cell_is_own && j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l]) && is_cell_around_parent_cell_different_owner(2, 1)) {
675 child_node_owner = owner_cells_around_parent_cell(1, 1);
676 }
677
678 // Noeuds qui ne sont sur aucune face de la maille parente.
679 else {
680 child_node_owner = owner_cells_around_parent_cell(1, 1);
681 }
682 }
683 }
684
685 // S'il y a une création de noeud et/ou un changement de propriétaire.
686 if (child_node_owner != -1) {
687 node_uid_to_owner[child_nodes_uids[l]] = child_node_owner;
688
689 // Lorsqu'il y a un changement de propriétaire sans création de noeud,
690 // on doit mettre de côté les uniqueIds de ces noeuds pour pouvoir
691 // itérer dessus par la suite.
692 if (!is_new_node) {
693 node_uid_change_owner_only.add(child_nodes_uids[l]);
694 // debug() << "Child node (change owner) -- x : " << i
695 // << " -- y : " << j
696 // << " -- level : " << parent_cell_level + 1
697 // << " -- node : " << l
698 // << " -- uid_node : " << child_nodes_uids[l]
699 // << " -- owner : " << child_node_owner;
700 }
701 else {
702 // debug() << "Child node (create node) -- x : " << i
703 // << " -- y : " << j
704 // << " -- level : " << parent_cell_level + 1
705 // << " -- node : " << l
706 // << " -- uid_node : " << child_nodes_uids[l]
707 // << " -- owner : " << child_node_owner;
708 }
709 }
710 }
711 }
712 }
713 }
714 }
715
716 // Pour le 3D, c'est très ressemblant, juste un peu plus long. Je recopie les commentaires, mais avec quelques adaptations.
717 else if (m_mesh->dimension() == 3) {
718
719 // Masques pour les cas "voisins enfants" et "voisins parents du même patch".
720 // Ces masques permettent de savoir si l'on doit créer un noeud ou pas selon
721 // les mailles autour.
722 // Par exemple, si l'on est en train d'étudier une maille enfant et qu'il y a
723 // une maille enfant à gauche, on ne doit pas créer les noeuds 0, 3, 4, 7 (mask_node_if_cell_left[]) (car
724 // ils ont déjà été créés par la maille à gauche).
725 // Idem pour les mailles parentes voisines : si l'on est sur une maille enfant située
726 // sur la partie gauche de la maille parente (mailles enfants 0, 2, 4, 6 dans le cas d'un
727 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille parente
728 // est en train ((d'être raffiné et à notre sous-domaine) ou (qu'elle est inactive)), on applique
729 // la règle mask_node_if_cell_left[] car les noeuds ont été créé par celle-ci et on veut éviter
730 // les noeuds en doubles.
731 // Ces masques permettent aussi de déterminer le propriétaire des noeuds dans
732 // le cas de multiples sous-domaines.
733 // Par exemple, si l'on est sur une maille enfant située
734 // sur la partie gauche de la maille parente (mailles enfants 0, 2, 4, 6 dans le cas d'un
735 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille
736 // parente (appartient à un autre sous-domaine) et (est en train d'être raffiné),
737 // on crée ce noeud mais on lui donne comme propriétaire le processus à qui appartient
738 // la maille parente à gauche.
739 constexpr bool mask_node_if_cell_left[] = { false, true, true, false, false, true, true, false };
740 constexpr bool mask_node_if_cell_bottom[] = { false, false, true, true, false, false, true, true };
741 constexpr bool mask_node_if_cell_rear[] = { false, false, false, false, true, true, true, true };
742
743 constexpr bool mask_node_if_cell_right[] = { true, false, false, true, true, false, false, true };
744 constexpr bool mask_node_if_cell_top[] = { true, true, false, false, true, true, false, false };
745 constexpr bool mask_node_if_cell_front[] = { true, true, true, true, false, false, false, false };
746
747 constexpr bool mask_face_if_cell_left[] = { true, false, true, true, true, true };
748 constexpr bool mask_face_if_cell_bottom[] = { true, true, false, true, true, true };
749 constexpr bool mask_face_if_cell_rear[] = { false, true, true, true, true, true };
750
751 constexpr bool mask_face_if_cell_right[] = { true, true, true, true, false, true };
752 constexpr bool mask_face_if_cell_top[] = { true, true, true, true, true, false };
753 constexpr bool mask_face_if_cell_front[] = { true, true, true, false, true, true };
754
755 // Petite différence par rapport au 2D. Pour le 2D, la position des noeuds des faces
756 // dans le tableau "child_nodes_uids" est toujours pareil (l et l+1, voir le 2D).
757 // Pour le 3D, ce n'est pas le cas donc on a des tableaux pour avoir une correspondance
758 // entre les noeuds de chaque face et la position des noeuds dans le tableau "child_nodes_uids".
759 // (Exemple : pour la face 1 (même ordre d'énumération qu'Arcane), on doit prendre le
760 // tableau "nodes_in_face_1" et donc les noeuds "child_nodes_uids[0]", "child_nodes_uids[3]",
761 // "child_nodes_uids[7]" et "child_nodes_uids[4]").
762 constexpr Integer nodes_in_face_0[] = { 0, 1, 2, 3 };
763 constexpr Integer nodes_in_face_1[] = { 0, 3, 7, 4 };
764 constexpr Integer nodes_in_face_2[] = { 0, 1, 5, 4 };
765 constexpr Integer nodes_in_face_3[] = { 4, 5, 6, 7 };
766 constexpr Integer nodes_in_face_4[] = { 1, 2, 6, 5 };
767 constexpr Integer nodes_in_face_5[] = { 3, 2, 6, 7 };
768
769 constexpr Integer nb_nodes_in_face = 4;
770
771 // Pour la taille :
772 // - on a "cell_to_refine_internals.size() * 8" mailles enfants,
773 // - pour chaque maille, on a 2 infos (type de maille et uniqueId de la maille)
774 // - pour chaque maille, on a "m_num_mng->getNbNode()" uniqueIds (les uniqueId de chaque noeud de la maille).
775 cells_infos.reserve((cell_to_refine_internals.size() * 8) * (2 + m_num_mng->nbNodeByCell()));
776
777 // Pour la taille, au maximum :
778 // - on a "cell_to_refine_internals.size() * 36" faces enfants,
779 // - pour chaque face, on a 2 infos (type de face et uniqueId de la face)
780 // - pour chaque face, on a 4 uniqueIds de noeuds.
781 faces_infos.reserve((cell_to_refine_internals.size() * 36) * (2 + 4));
782
783 // Pour la taille, au maximum :
784 // - on a (cell_to_refine_internals.size() * 27) uniqueIds de noeuds.
785 nodes_infos.reserve(cell_to_refine_internals.size() * 27);
786
787 FixedArray<Int64, 27> uid_cells_around_parent_cell_1d;
788 FixedArray<Int32, 27> owner_cells_around_parent_cell_1d;
789 FixedArray<Int32, 27> flags_cells_around_parent_cell_1d;
790
791 for (Cell parent_cell : cell_to_refine_internals) {
792 const Int64 parent_cell_uid = parent_cell.uniqueId();
793 const Int32 parent_cell_level = parent_cell.level();
794
795 const Int64 parent_coord_x = m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, parent_cell_level);
796 const Int64 parent_coord_y = m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, parent_cell_level);
797 const Int64 parent_coord_z = m_num_mng->cellUniqueIdToCoordZ(parent_cell_uid, parent_cell_level);
798
799 const Int64 child_coord_x = m_num_mng->offsetLevelToLevel(parent_coord_x, parent_cell_level, parent_cell_level + 1);
800 const Int64 child_coord_y = m_num_mng->offsetLevelToLevel(parent_coord_y, parent_cell_level, parent_cell_level + 1);
801 const Int64 child_coord_z = m_num_mng->offsetLevelToLevel(parent_coord_z, parent_cell_level, parent_cell_level + 1);
802
803 const Integer pattern = m_num_mng->pattern();
804
805 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_parent_cell_1d.view(), parent_cell);
806
807 for (Integer i = 0; i < 27; ++i) {
808 Int64 uid_cell = uid_cells_around_parent_cell_1d[i];
809 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
810 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
811 if (uid_cell != -1 && around_parent_cells_uid_to_owner[uid_cell] != -1) {
812 owner_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_owner[uid_cell];
813 flags_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_flags[uid_cell];
814 }
815 else {
816 uid_cells_around_parent_cell_1d[i] = -1;
817 owner_cells_around_parent_cell_1d[i] = -1;
818 flags_cells_around_parent_cell_1d[i] = 0;
819 }
820 }
821
822 // Pour simplifier, on utilise des vues 3D. (array[Z][Y][X]).
823 ConstArray3View uid_cells_around_parent_cell(uid_cells_around_parent_cell_1d.data(), 3, 3, 3);
824 ConstArray3View owner_cells_around_parent_cell(owner_cells_around_parent_cell_1d.data(), 3, 3, 3);
825 ConstArray3View flags_cells_around_parent_cell(flags_cells_around_parent_cell_1d.data(), 3, 3, 3);
826
827 // #priority_owner_3d
828 // Voici les priorités pour la propriété des noeuds et des faces :
829 // ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐
830 // │ 6 7 8│ │ │15 16 17│ │ │24 25 26│
831 // │ │ │ └───────┐ │ │ │ │
832 // │ │ │ ┌──┐┌──┐│ │ │ │ │
833 // │ 3 4 5│ │ │12││13││14│ │ │21 22 23│
834 // │ │ │ │ │└──┘└──┘ │ │ │
835 // │ │ │ │ └───────┐ │ │ │
836 // │ 0 1 2│ │ │ 9 10 11│ │ │18 19 20│
837 // └──────────┘ │ └──────────┘ │ └──────────┘
838 // Z=0 │ Z=1 │ Z=2
839 // ("arrière") │ │ ("avant")
840 //
841 // ^y
842 // |
843 // ->x
844
845 // #arcane_order_to_around_3d
846 // Note pour les maillages cartésiens 3D :
847 // Les itérateurs sur les faces itèrent dans l'ordre (pour la maille 13 ici) :
848 // 1. Face entre [13, 4],
849 // 2. Face entre [13, 12],
850 // 3. Face entre [13, 10],
851 // 4. Face entre [13, 22],
852 // 5. Face entre [13, 14],
853 // 6. Face entre [13, 16],
854 //
855 // Les itérateurs sur les noeuds itèrent dans l'ordre (pour la maille 13 ici) :
856 // 1. Noeud entre [13, 0]
857 // 2. Noeud entre [13, 2]
858 // 3. Noeud entre [13, 8]
859 // 4. Noeud entre [13, 6]
860 // 5. Noeud entre [13, 18]
861 // 6. Noeud entre [13, 20]
862 // 7. Noeud entre [13, 26]
863 // 8. Noeud entre [13, 24]
864
865 // Chaque chiffre désigne une maille parente et une priorité (0 étant la priorité la plus forte).
866 // 13 = parent_cell ("nous")
867
868 // Exemple 1 :
869 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
870 // En bas, il n'y a pas de mailles.
871 // À gauche (donc priorité 12), il y a une maille qui est déjà raffinée (flag "II_Inactive").
872 // On est priorité 13 donc il est prioritaire. Donc les noeuds et des faces que l'on a en commun
873 // lui appartiennent.
874
875 // Exemple 2 :
876 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
877 // En haut, il y a des mailles déjà raffinées (flag "II_Inactive").
878 // On est prioritaire sur elles, on récupère donc la propriété des noeuds et des faces que l'on a
879 // en commun. Ce changement de propriété doit leur être signalé.
880
881 // On simplifie avec un tableau de booléens.
882 // Si true, alors on doit appliquer la priorité de propriété.
883 // Si false, alors on considère qu'il n'y a pas de maille à la position définie.
884 FixedArray<FixedArray<FixedArray<bool, 3>, 3>, 3> is_cell_around_parent_cell_present_and_useful;
885
886 // Pour les mailles prioritaires sur nous, on doit regarder les deux flags.
887 // Si une maille a le flag "II_Refine", on n'existe pas pour elle donc elle prend la propriété
888 // des faces et des noeuds qu'on a en commun.
889 // Si une maille a le flag "II_Inactive", elle a déjà les bons propriétaires.
890 // Quoi qu'il en soit, si true alors les faces et noeuds qu'on a en commun leurs appartiennent.
891 is_cell_around_parent_cell_present_and_useful[0][0][0] = ((uid_cells_around_parent_cell(0, 0, 0) != -1) && (flags_cells_around_parent_cell(0, 0, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
892 is_cell_around_parent_cell_present_and_useful[0][0][1] = ((uid_cells_around_parent_cell(0, 0, 1) != -1) && (flags_cells_around_parent_cell(0, 0, 1) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
893 is_cell_around_parent_cell_present_and_useful[0][0][2] = ((uid_cells_around_parent_cell(0, 0, 2) != -1) && (flags_cells_around_parent_cell(0, 0, 2) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
894 is_cell_around_parent_cell_present_and_useful[0][1][0] = ((uid_cells_around_parent_cell(0, 1, 0) != -1) && (flags_cells_around_parent_cell(0, 1, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
895 is_cell_around_parent_cell_present_and_useful[0][1][1] = ((uid_cells_around_parent_cell(0, 1, 1) != -1) && (flags_cells_around_parent_cell(0, 1, 1) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
896 is_cell_around_parent_cell_present_and_useful[0][1][2] = ((uid_cells_around_parent_cell(0, 1, 2) != -1) && (flags_cells_around_parent_cell(0, 1, 2) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
897 is_cell_around_parent_cell_present_and_useful[0][2][0] = ((uid_cells_around_parent_cell(0, 2, 0) != -1) && (flags_cells_around_parent_cell(0, 2, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
898 is_cell_around_parent_cell_present_and_useful[0][2][1] = ((uid_cells_around_parent_cell(0, 2, 1) != -1) && (flags_cells_around_parent_cell(0, 2, 1) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
899 is_cell_around_parent_cell_present_and_useful[0][2][2] = ((uid_cells_around_parent_cell(0, 2, 2) != -1) && (flags_cells_around_parent_cell(0, 2, 2) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
900
901 is_cell_around_parent_cell_present_and_useful[1][0][0] = ((uid_cells_around_parent_cell(1, 0, 0) != -1) && (flags_cells_around_parent_cell(1, 0, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
902 is_cell_around_parent_cell_present_and_useful[1][0][1] = ((uid_cells_around_parent_cell(1, 0, 1) != -1) && (flags_cells_around_parent_cell(1, 0, 1) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
903 is_cell_around_parent_cell_present_and_useful[1][0][2] = ((uid_cells_around_parent_cell(1, 0, 2) != -1) && (flags_cells_around_parent_cell(1, 0, 2) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
904
905 is_cell_around_parent_cell_present_and_useful[1][1][0] = ((uid_cells_around_parent_cell(1, 1, 0) != -1) && (flags_cells_around_parent_cell(1, 1, 0) & (ItemFlags::II_Refine | ItemFlags::II_Inactive)));
906 // is_cell_around_parent_cell_present_and_useful[1][1][1] = parent_cell;
907
908 // Pour les mailles non prioritaires, on doit regarder qu'un seul flag.
909 // Si une maille a le flag "II_Inactive", alors elle doit être avertie qu'on récupère la propriété
910 // des noeuds et des faces qu'on a en commun.
911 // On ne regarde pas le flag "II_Refine" car, si ces mailles sont aussi en train d'être raffinée,
912 // elles savent qu'on existe et qu'on obtient la propriété des noeuds et des faces qu'on a en commun.
913 // En résumé, si true alors les faces et noeuds qu'on a en commun nous appartiennent.
914 is_cell_around_parent_cell_present_and_useful[1][1][2] = ((uid_cells_around_parent_cell(1, 1, 2) != -1) && (flags_cells_around_parent_cell(1, 1, 2) & ItemFlags::II_Inactive));
915
916 is_cell_around_parent_cell_present_and_useful[1][2][0] = ((uid_cells_around_parent_cell(1, 2, 0) != -1) && (flags_cells_around_parent_cell(1, 2, 0) & ItemFlags::II_Inactive));
917 is_cell_around_parent_cell_present_and_useful[1][2][1] = ((uid_cells_around_parent_cell(1, 2, 1) != -1) && (flags_cells_around_parent_cell(1, 2, 1) & ItemFlags::II_Inactive));
918 is_cell_around_parent_cell_present_and_useful[1][2][2] = ((uid_cells_around_parent_cell(1, 2, 2) != -1) && (flags_cells_around_parent_cell(1, 2, 2) & ItemFlags::II_Inactive));
919
920 is_cell_around_parent_cell_present_and_useful[2][0][0] = ((uid_cells_around_parent_cell(2, 0, 0) != -1) && (flags_cells_around_parent_cell(2, 0, 0) & ItemFlags::II_Inactive));
921 is_cell_around_parent_cell_present_and_useful[2][0][1] = ((uid_cells_around_parent_cell(2, 0, 1) != -1) && (flags_cells_around_parent_cell(2, 0, 1) & ItemFlags::II_Inactive));
922 is_cell_around_parent_cell_present_and_useful[2][0][2] = ((uid_cells_around_parent_cell(2, 0, 2) != -1) && (flags_cells_around_parent_cell(2, 0, 2) & ItemFlags::II_Inactive));
923 is_cell_around_parent_cell_present_and_useful[2][1][0] = ((uid_cells_around_parent_cell(2, 1, 0) != -1) && (flags_cells_around_parent_cell(2, 1, 0) & ItemFlags::II_Inactive));
924 is_cell_around_parent_cell_present_and_useful[2][1][1] = ((uid_cells_around_parent_cell(2, 1, 1) != -1) && (flags_cells_around_parent_cell(2, 1, 1) & ItemFlags::II_Inactive));
925 is_cell_around_parent_cell_present_and_useful[2][1][2] = ((uid_cells_around_parent_cell(2, 1, 2) != -1) && (flags_cells_around_parent_cell(2, 1, 2) & ItemFlags::II_Inactive));
926 is_cell_around_parent_cell_present_and_useful[2][2][0] = ((uid_cells_around_parent_cell(2, 2, 0) != -1) && (flags_cells_around_parent_cell(2, 2, 0) & ItemFlags::II_Inactive));
927 is_cell_around_parent_cell_present_and_useful[2][2][1] = ((uid_cells_around_parent_cell(2, 2, 1) != -1) && (flags_cells_around_parent_cell(2, 2, 1) & ItemFlags::II_Inactive));
928 is_cell_around_parent_cell_present_and_useful[2][2][2] = ((uid_cells_around_parent_cell(2, 2, 2) != -1) && (flags_cells_around_parent_cell(2, 2, 2) & ItemFlags::II_Inactive));
929
930 // En plus de regarder si chaque maille parent autour de notre maille parent existe et possède (II_Inactive) ou possédera (II_Refine) des enfants...
931 // ... on regarde si chaque maille parent est présente sur notre sous-domaine, que ce soit une maille fantôme ou non.
932 auto is_cell_around_parent_cell_in_subdomain = [&](const Integer z, const Integer y, const Integer x) {
933 return is_cell_around_parent_cell_present_and_useful[z][y][x] && (flags_cells_around_parent_cell(z, y, x) & ItemFlags::II_UserMark1);
934 };
935
936 // ... on regarde si chaque maille parent est possédé par le même propriétaire que notre maille parent.
937 auto is_cell_around_parent_cell_same_owner = [&](const Integer z, const Integer y, const Integer x) {
938 return is_cell_around_parent_cell_present_and_useful[z][y][x] && (owner_cells_around_parent_cell(z, y, x) == owner_cells_around_parent_cell(1, 1, 1));
939 };
940
941 // ... on regarde si chaque maille parent a un propriétaire différent par rapport à notre maille parent.
942 auto is_cell_around_parent_cell_different_owner = [&](const Integer z, const Integer y, const Integer x) {
943 return is_cell_around_parent_cell_present_and_useful[z][y][x] && (owner_cells_around_parent_cell(z, y, x) != owner_cells_around_parent_cell(1, 1, 1));
944 };
945
946 // On itère sur toutes les mailles enfants.
947 for (Int64 k = child_coord_z; k < child_coord_z + pattern; ++k) {
948 for (Int64 j = child_coord_y; j < child_coord_y + pattern; ++j) {
949 for (Int64 i = child_coord_x; i < child_coord_x + pattern; ++i) {
950 parent_cells.add(parent_cell);
951 total_nb_cells++;
952
953 const Int64 child_cell_uid = m_num_mng->cellUniqueId(parent_cell_level + 1, Int64x3(i, j, k));
954 // debug() << "Child -- x : " << i << " -- y : " << j << " -- z : " << k << " -- level : " << parent_cell_level + 1 << " -- uid : " << child_cell_uid;
955
956 m_num_mng->cellNodeUniqueIds(child_nodes_uids, parent_cell_level + 1, Int64x3(i, j, k));
957 m_num_mng->cellFaceUniqueIds(child_faces_uids, parent_cell_level + 1, Int64x3(i, j, k));
958
959 constexpr Integer type_cell = IT_Hexaedron8;
960 constexpr Integer type_face = IT_Quad4;
961
962 // Partie Cell.
963 cells_infos.add(type_cell);
964 cells_infos.add(child_cell_uid);
965 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
966 cells_infos.add(child_nodes_uids[nc]);
967 }
968
969 // Partie Face.
970 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
971 Integer child_face_owner = -1;
972 bool is_new_face = false;
973
974 // Deux parties :
975 // D'abord, on regarde si l'on doit créer la face l. Pour cela, on doit regarder si elle est présente sur la
976 // maille à côté.
977 // Pour gauche/bas/arrière, c'est le même principe. Si la maille enfant est tout à gauche/bas/arrière de la maille parente, on regarde
978 // s'il y a une maille parente à gauche/bas/arrière. Sinon, on crée la face. Si oui, on regarde le masque pour savoir si l'on
979 // doit créer la face.
980 // Pour droite/haut/avant, le principe est différent de gauche/bas/arrière. On ne suit le masque que si on est tout à droite/haut/avant
981 // de la maille parente. Sinon on crée toujours les faces droites/hautes/avant.
982 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
983 // notre sous-domaine, alors il se peut que les faces en communes avec notre maille parente existent déjà, dans ce cas,
984 // pas de doublon.
985 if (
986 ((i == child_coord_x && !is_cell_around_parent_cell_in_subdomain(1, 1, 0)) || mask_face_if_cell_left[l]) &&
987 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 1, 2)) || mask_face_if_cell_right[l]) &&
988 ((j == child_coord_y && !is_cell_around_parent_cell_in_subdomain(1, 0, 1)) || mask_face_if_cell_bottom[l]) &&
989 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2, 1)) || mask_face_if_cell_top[l]) &&
990 ((k == child_coord_z && !is_cell_around_parent_cell_in_subdomain(0, 1, 1)) || mask_face_if_cell_rear[l]) &&
991 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1, 1)) || mask_face_if_cell_front[l])) {
992 is_new_face = true;
993 faces_infos.add(type_face);
994 faces_infos.add(child_faces_uids[l]);
995
996 // On récupère la position des noeuds de la face dans le tableau "ua_node_uid".
997 ConstArrayView<Integer> nodes_in_face_l;
998 switch (l) {
999 case 0:
1000 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_0, nb_nodes_in_face);
1001 break;
1002 case 1:
1003 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_1, nb_nodes_in_face);
1004 break;
1005 case 2:
1006 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_2, nb_nodes_in_face);
1007 break;
1008 case 3:
1009 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_3, nb_nodes_in_face);
1010 break;
1011 case 4:
1012 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_4, nb_nodes_in_face);
1013 break;
1014 case 5:
1015 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_5, nb_nodes_in_face);
1016 break;
1017 default:
1018 ARCANE_FATAL("Bizarre...");
1019 }
1020 for (Integer nc : nodes_in_face_l) {
1021 faces_infos.add(child_nodes_uids[nc]);
1022 }
1023 total_nb_faces++;
1024
1025 // Par défaut, parent_cell est propriétaire de la nouvelle face.
1026 child_face_owner = owner_cells_around_parent_cell(1, 1, 1);
1027 }
1028
1029 // Deuxième partie.
1030 // On doit maintenant trouver le bon propriétaire pour la face. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
1031 // la condition est identique à celle au-dessus.
1032 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr qu'il y a la face qui nous intéresse.
1033 // Le nouveau tableau permet de savoir si la maille d'à côté est aussi à nous ou pas. Si ce n'est pas le cas, alors
1034 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
1035 // si la maille est présente sur le sous-domaine.
1036 if (
1037 ((i == child_coord_x && !is_cell_around_parent_cell_same_owner(1, 1, 0)) || mask_face_if_cell_left[l]) &&
1038 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 1, 2)) || mask_face_if_cell_right[l]) &&
1039 ((j == child_coord_y && !is_cell_around_parent_cell_same_owner(1, 0, 1)) || mask_face_if_cell_bottom[l]) &&
1040 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2, 1)) || mask_face_if_cell_top[l]) &&
1041 ((k == child_coord_z && !is_cell_around_parent_cell_same_owner(0, 1, 1)) || mask_face_if_cell_rear[l]) &&
1042 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1, 1)) || mask_face_if_cell_front[l])) {
1043 // Ici, la construction des conditions est la même à chaque fois.
1044 // Le premier booléen (i == child_coord_x) regarde si l'enfant se trouve
1045 // du bon côté de la maille parent.
1046 // Le second booléen (!mask_face_if_cell_left[l]) nous dit si la face l est bien
1047 // la face en commun avec la maille parent d'à côté.
1048 // Le troisième booléen (is_cell_around_parent_cell_different_owner(1, 0)) regarde s'il y a une
1049 // maille à côté qui prend la propriété de la face ou à qui on prend la propriété.
1050
1051 // En outre, il y a deux cas différents selon les priorités définies au-dessus :
1052 // - soit nous ne sommes pas prioritaire, alors on attribue le propriétaire prioritaire à notre face,
1053 // - soit nous sommes prioritaire, alors on se positionne comme propriétaire de la face et on doit prévenir
1054 // tous les autres processus (le processus ancien propriétaire mais aussi les processus qui peuvent
1055 // avoir la face en fantôme).
1056
1057 // Enfin, dans le cas du changement de propriétaire, seul le processus (re)prenant la propriété doit
1058 // faire une communication à ce propos. Les processus ne possédant que la face en fantôme ne doit pas
1059 // faire de communication (mais ils peuvent définir localement le bon propriétaire, TODO Optimisation possible ?).
1060
1061 // À gauche, priorité 12 < 13 donc il prend la propriété de la face.
1062 if (i == child_coord_x && (!mask_face_if_cell_left[l]) && is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1063 child_face_owner = owner_cells_around_parent_cell(1, 1, 0);
1064 }
1065
1066 // En bas, priorité 10 < 13 donc il prend la propriété de la face.
1067 else if (j == child_coord_y && (!mask_face_if_cell_bottom[l]) && is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1068 child_face_owner = owner_cells_around_parent_cell(1, 0, 1);
1069 }
1070
1071 // À l'arrière, priorité 4 < 13 donc il prend la propriété de la face.
1072 else if (k == child_coord_z && (!mask_face_if_cell_rear[l]) && is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1073 child_face_owner = owner_cells_around_parent_cell(0, 1, 1);
1074 }
1075
1076 // Sinon, parent_cell est propriétaire de la face.
1077 else {
1078
1079 // Sinon, c'est une face interne donc au parent_cell.
1080 child_face_owner = owner_cells_around_parent_cell(1, 1, 1);
1081 }
1082 }
1083
1084 // S'il y a une création de face et/ou un changement de propriétaire.
1085 if (child_face_owner != -1) {
1086 face_uid_to_owner[child_faces_uids[l]] = child_face_owner;
1087
1088 // Lorsqu'il y a un changement de propriétaire sans création de face,
1089 // on doit mettre de côté les uniqueIds de ces faces pour pouvoir
1090 // itérer dessus par la suite.
1091 if (!is_new_face) {
1092 face_uid_change_owner_only.add(child_faces_uids[l]);
1093 // debug() << "Child face (change owner) -- x : " << i
1094 // << " -- y : " << j
1095 // << " -- z : " << k
1096 // << " -- level : " << parent_cell_level + 1
1097 // << " -- face : " << l
1098 // << " -- uid_face : " << child_faces_uids[l]
1099 // << " -- owner : " << child_face_owner;
1100 }
1101 else {
1102 // debug() << "Child face (create face) -- x : " << i
1103 // << " -- y : " << j
1104 // << " -- z : " << k
1105 // << " -- level : " << parent_cell_level + 1
1106 // << " -- face : " << l
1107 // << " -- uid_face : " << child_faces_uids[l]
1108 // << " -- owner : " << child_face_owner;
1109 }
1110 }
1111 }
1112
1113 // Partie Node.
1114 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
1115 // plus de propriétaires possibles.
1116 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
1117 Integer child_node_owner = -1;
1118 bool is_new_node = false;
1119
1120 // Deux parties :
1121 // D'abord, on regarde si l'on doit créer le noeud l. Pour cela, on doit regarder s'il est présente sur la
1122 // maille à côté.
1123 // Pour gauche/bas/arrière, c'est le même principe. Si la maille enfant est tout à gauche/bas/arrière de la maille parente, on regarde
1124 // s'il y a une maille parente à gauche/bas/arrière. Sinon, on crée le noeud. Si oui, on regarde le masque pour savoir si l'on
1125 // doit créer le noeud.
1126 // Pour droite/haut/avant, le principe est différent de gauche/bas/arrière. On ne suit le masque que si la maille
1127 // enfant est toute à droite/haut/avant
1128 // de la maille parente. Sinon on crée toujours les noeuds droites/hautes/avant.
1129 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
1130 // notre sous-domaine, alors il se peut que les noeuds en communs avec notre maille parente existent déjà, dans ce cas,
1131 // pas de doublon.
1132 if (
1133 ((i == child_coord_x && !is_cell_around_parent_cell_in_subdomain(1, 1, 0)) || mask_node_if_cell_left[l]) &&
1134 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 1, 2)) || mask_node_if_cell_right[l]) &&
1135 ((j == child_coord_y && !is_cell_around_parent_cell_in_subdomain(1, 0, 1)) || mask_node_if_cell_bottom[l]) &&
1136 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2, 1)) || mask_node_if_cell_top[l]) &&
1137 ((k == child_coord_z && !is_cell_around_parent_cell_in_subdomain(0, 1, 1)) || mask_node_if_cell_rear[l]) &&
1138 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1, 1)) || mask_node_if_cell_front[l])) {
1139 is_new_node = true;
1140 nodes_infos.add(child_nodes_uids[l]);
1141 total_nb_nodes++;
1142
1143 // Par défaut, parent_cell est propriétaire du nouveau noeud.
1144 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1145 }
1146
1147 // Deuxième partie.
1148 // On doit maintenant trouver le bon propriétaire pour le noeud. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
1149 // la condition est identique à celle au-dessus.
1150 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr que le noeud qui nous intéresse existe.
1151 // Le nouveau tableau permet de savoir si la maille d'à côté est aussi à nous ou pas. Si ce n'est pas le cas, alors
1152 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
1153 // si la maille est présente sur le sous-domaine.
1154 if (
1155 ((i == child_coord_x && !is_cell_around_parent_cell_same_owner(1, 1, 0)) || mask_node_if_cell_left[l]) &&
1156 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 1, 2)) || mask_node_if_cell_right[l]) &&
1157 ((j == child_coord_y && !is_cell_around_parent_cell_same_owner(1, 0, 1)) || mask_node_if_cell_bottom[l]) &&
1158 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2, 1)) || mask_node_if_cell_top[l]) &&
1159 ((k == child_coord_z && !is_cell_around_parent_cell_same_owner(0, 1, 1)) || mask_node_if_cell_rear[l]) &&
1160 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1, 1)) || mask_node_if_cell_front[l])) {
1161
1162 // Par rapport aux faces qui n'ont que deux propriétaires possibles, un noeud peut
1163 // en avoir jusqu'à huit.
1164
1165 // Si le noeud est sur la face gauche de la maille parente.
1166 if (i == child_coord_x && (!mask_node_if_cell_left[l])) {
1167
1168 // Si le noeud est sur la face basse de la maille parente.
1169 // Donc noeud sur l'arête à gauche en bas.
1170 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1171
1172 // Si le noeud est sur la face arrière de la maille parente.
1173 // Donc noeud à gauche, en bas, en arrière (même position que le noeud de la maille parente).
1174 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1175
1176 // Priorité 0 < 13.
1177 if (is_cell_around_parent_cell_different_owner(0, 0, 0)) {
1178 child_node_owner = owner_cells_around_parent_cell(0, 0, 0);
1179 }
1180
1181 // Priorité 1 < 13.
1182 else if (is_cell_around_parent_cell_different_owner(0, 0, 1)) {
1183 child_node_owner = owner_cells_around_parent_cell(0, 0, 1);
1184 }
1185
1186 // Priorité 3 < 13.
1187 else if (is_cell_around_parent_cell_different_owner(0, 1, 0)) {
1188 child_node_owner = owner_cells_around_parent_cell(0, 1, 0);
1189 }
1190
1191 // Priorité 4 < 13.
1192 else if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1193 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1194 }
1195
1196 // Priorité 9 < 13.
1197 else if (is_cell_around_parent_cell_different_owner(1, 0, 0)) {
1198 child_node_owner = owner_cells_around_parent_cell(1, 0, 0);
1199 }
1200
1201 // Priorité 10 < 13.
1202 else if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1203 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1204 }
1205
1206 // Priorité 12 < 13.
1207 else if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1208 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1209 }
1210
1211 // Pas de mailles autour.
1212 else {
1213 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1214 }
1215 }
1216
1217 // Si le noeud est sur la face avant de la maille parente.
1218 // Donc noeud à gauche, en bas, en avant (même position que le noeud de la maille parente).
1219 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1220
1221 // Priorité 9 < 13.
1222 if (is_cell_around_parent_cell_different_owner(1, 0, 0)) {
1223 child_node_owner = owner_cells_around_parent_cell(1, 0, 0);
1224 }
1225
1226 // Priorité 10 < 13.
1227 else if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1228 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1229 }
1230
1231 // Priorité 12 < 13.
1232 else if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1233 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1234 }
1235
1236 // Sinon, parent_cell est propriétaire du noeud.
1237 else {
1238 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1239 }
1240 }
1241
1242 // Sinon le noeud est quelque part sur l'arête à gauche en bas...
1243 else {
1244
1245 // Priorité 9 < 13.
1246 if (is_cell_around_parent_cell_different_owner(1, 0, 0)) {
1247 child_node_owner = owner_cells_around_parent_cell(1, 0, 0);
1248 }
1249
1250 // Priorité 10 < 13.
1251 else if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1252 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1253 }
1254
1255 // Priorité 12 < 13.
1256 else if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1257 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1258 }
1259
1260 // Pas de mailles autour.
1261 else {
1262 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1263 }
1264 }
1265 }
1266
1267 // Si le noeud est sur la face haute de la maille parente.
1268 // Donc noeud sur l'arête à gauche en haut.
1269 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1270
1271 // Si le noeud est sur la face arrière de la maille parente.
1272 // Donc noeud à gauche, en haut, en arrière (même position que le noeud de la maille parente).
1273 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1274
1275 // Priorité 3 < 13.
1276 if (is_cell_around_parent_cell_different_owner(0, 1, 0)) {
1277 child_node_owner = owner_cells_around_parent_cell(0, 1, 0);
1278 }
1279
1280 // Priorité 4 < 13.
1281 else if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1282 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1283 }
1284
1285 // Priorité 6 < 13.
1286 else if (is_cell_around_parent_cell_different_owner(0, 2, 0)) {
1287 child_node_owner = owner_cells_around_parent_cell(0, 2, 0);
1288 }
1289
1290 // Priorité 7 < 13.
1291 else if (is_cell_around_parent_cell_different_owner(0, 2, 1)) {
1292 child_node_owner = owner_cells_around_parent_cell(0, 2, 1);
1293 }
1294
1295 // Priorité 12 < 13.
1296 else if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1297 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1298 }
1299
1300 // Sinon, parent_cell est propriétaire du noeud.
1301 else {
1302 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1303 }
1304 }
1305
1306 // Si le noeud est sur la face avant de la maille parente.
1307 // Donc noeud à gauche, en haut, en avant (même position que le noeud de la maille parente).
1308 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1309
1310 // Priorité 4 < 13.
1311 if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1312 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1313 }
1314
1315 // Sinon, parent_cell est propriétaire du noeud.
1316 else {
1317 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1318 }
1319 }
1320
1321 // Sinon le noeud est quelque part sur l'arête à gauche en haut...
1322 else {
1323
1324 // Priorité 12 < 13.
1325 if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1326 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1327 }
1328
1329 // Sinon, parent_cell est propriétaire du noeud.
1330 else {
1331 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1332 }
1333 }
1334 }
1335
1336 // Sinon le noeud est ni sur l'arête à gauche en bas, ni sur l'arête à gauche en haut.
1337 else {
1338
1339 // Si le noeud est quelque part sur l'arête à gauche en arrière.
1340 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1341
1342 // Priorité 3 < 13.
1343 if (is_cell_around_parent_cell_different_owner(0, 1, 0)) {
1344 child_node_owner = owner_cells_around_parent_cell(0, 1, 0);
1345 }
1346
1347 // Priorité 4 < 13.
1348 else if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1349 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1350 }
1351
1352 // Priorité 12 < 13.
1353 else if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1354 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1355 }
1356
1357 // Pas de mailles autour.
1358 else {
1359 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1360 }
1361 }
1362
1363 // Si le noeud est quelque part sur l'arête à gauche en avant.
1364 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1365
1366 // Priorité 12 < 13.
1367 if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1368 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1369 }
1370
1371 // Sinon, parent_cell est propriétaire du noeud.
1372 else {
1373 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1374 }
1375 }
1376
1377 // Sinon le noeud est quelque part sur la face gauche...
1378 else {
1379
1380 // Priorité 12 < 13.
1381 if (is_cell_around_parent_cell_different_owner(1, 1, 0)) {
1382 child_node_owner = owner_cells_around_parent_cell(1, 1, 0);
1383 }
1384
1385 // Parent_cell est le proprio.
1386 else {
1387 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1388 }
1389 }
1390 }
1391 }
1392
1393 // À partir de là, on a exploré tous les noeuds et toutes les arêtes de la face parente gauche.
1394
1395 // Si le noeud est sur la face droite de la maille parente.
1396 else if (i == (child_coord_x + pattern - 1) && (!mask_node_if_cell_right[l])) {
1397
1398 // Si le noeud est sur la face basse de la maille parente.
1399 // Donc noeud sur l'arête à droite en bas.
1400 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1401
1402 // Si le noeud est sur la face arrière de la maille parente.
1403 // Donc noeud à droite, en bas, en arrière (même position que le noeud de la maille parente).
1404 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1405
1406 // Priorité 1 < 13.
1407 if (is_cell_around_parent_cell_different_owner(0, 0, 1)) {
1408 child_node_owner = owner_cells_around_parent_cell(0, 0, 1);
1409 }
1410
1411 // Priorité 2 < 13.
1412 else if (is_cell_around_parent_cell_different_owner(0, 0, 2)) {
1413 child_node_owner = owner_cells_around_parent_cell(0, 0, 2);
1414 }
1415
1416 // Priorité 4 < 13.
1417 else if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1418 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1419 }
1420
1421 // Priorité 5 < 13.
1422 else if (is_cell_around_parent_cell_different_owner(0, 1, 2)) {
1423 child_node_owner = owner_cells_around_parent_cell(0, 1, 2);
1424 }
1425
1426 // Priorité 10 < 13.
1427 else if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1428 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1429 }
1430
1431 // Priorité 11 < 13.
1432 else if (is_cell_around_parent_cell_different_owner(1, 0, 2)) {
1433 child_node_owner = owner_cells_around_parent_cell(1, 0, 2);
1434 }
1435
1436 // Sinon, parent_cell est propriétaire du noeud.
1437 else {
1438 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1439 }
1440 }
1441
1442 // Si le noeud est sur la face avant de la maille parente.
1443 // Donc noeud à droite, en bas, en avant (même position que le noeud de la maille parente).
1444 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1445
1446 // Priorité 10 < 13.
1447 if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1448 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1449 }
1450
1451 // Priorité 11 < 13.
1452 else if (is_cell_around_parent_cell_different_owner(1, 0, 2)) {
1453 child_node_owner = owner_cells_around_parent_cell(1, 0, 2);
1454 }
1455
1456 // Sinon, parent_cell est propriétaire du noeud.
1457 else {
1458 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1459 }
1460 }
1461
1462 // Sinon le noeud est quelque part sur l'arête à droite en bas...
1463 else {
1464
1465 // Priorité 10 < 13.
1466 if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1467 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1468 }
1469
1470 // Priorité 11 < 13.
1471 else if (is_cell_around_parent_cell_different_owner(1, 0, 2)) {
1472 child_node_owner = owner_cells_around_parent_cell(1, 0, 2);
1473 }
1474
1475 // Sinon, parent_cell est propriétaire du noeud.
1476 else {
1477 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1478 }
1479 }
1480 }
1481
1482 // Si le noeud est sur la face haute de la maille parente.
1483 // Donc noeud sur l'arête à droite en haut.
1484 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1485
1486 // Si le noeud est sur la face arrière de la maille parente.
1487 // Donc noeud à droite, en haut, en arrière (même position que le noeud de la maille parente).
1488 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1489
1490 // Priorité 4 < 13.
1491 if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1492 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1493 }
1494
1495 // Priorité 5 < 13.
1496 else if (is_cell_around_parent_cell_different_owner(0, 1, 2)) {
1497 child_node_owner = owner_cells_around_parent_cell(0, 1, 2);
1498 }
1499
1500 // Priorité 7 < 13.
1501 else if (is_cell_around_parent_cell_different_owner(0, 2, 1)) {
1502 child_node_owner = owner_cells_around_parent_cell(0, 2, 1);
1503 }
1504
1505 // Priorité 8 < 13.
1506 else if (is_cell_around_parent_cell_different_owner(0, 2, 2)) {
1507 child_node_owner = owner_cells_around_parent_cell(0, 2, 2);
1508 }
1509
1510 // Sinon, parent_cell est propriétaire du noeud.
1511 else {
1512 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1513 }
1514 }
1515
1516 // Si le noeud est sur la face avant de la maille parente.
1517 // Donc noeud à droite, en haut, en avant (même position que le noeud de la maille parente).
1518 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1519 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1520 }
1521
1522 // Sinon le noeud est quelque part sur l'arête à droite en haut...
1523 else {
1524 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1525 }
1526 }
1527
1528 // Sinon le noeud est ni sur l'arête à droite en bas, ni sur l'arête à droite en haut.
1529 else {
1530 // Si le noeud est quelque part sur l'arête à droite en arrière.
1531 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1532
1533 // Priorité 4 < 13.
1534 if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1535 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1536 }
1537
1538 // Priorité 5 < 13.
1539 else if (is_cell_around_parent_cell_different_owner(0, 1, 2)) {
1540 child_node_owner = owner_cells_around_parent_cell(0, 1, 2);
1541 }
1542
1543 // Sinon, parent_cell est propriétaire du noeud.
1544 else {
1545 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1546 }
1547 }
1548
1549 // Si le noeud est quelque part sur l'arête à droite en avant.
1550 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1551 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1552 }
1553
1554 // Sinon le noeud est quelque part sur la face droite...
1555 else {
1556 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1557 }
1558 }
1559 }
1560
1561 // À partir de là, on a exploré tous les noeuds de la maille parente et toutes les arêtes
1562 // de la face parente droite (et gauche).
1563 // Donc il ne reste que quatre arêtes et quatre faces à explorer.
1564
1565 // Sinon le noeud est ni sur la face gauche, ni sur la face droite.
1566 else {
1567
1568 // Si le noeud est sur la face basse de la maille parente.
1569 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1570
1571 // Si le noeud est sur la face arrière de la maille parente.
1572 // Donc noeud sur l'arête en arrière en bas.
1573 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1574
1575 // Priorité 1 < 13.
1576 if (is_cell_around_parent_cell_different_owner(0, 0, 1)) {
1577 child_node_owner = owner_cells_around_parent_cell(0, 0, 1);
1578 }
1579
1580 // Priorité 4 < 13.
1581 else if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1582 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1583 }
1584
1585 // Priorité 10 < 13.
1586 else if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1587 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1588 }
1589
1590 // Pas de mailles autour.
1591 else {
1592 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1593 }
1594 }
1595
1596 // Si le noeud est sur la face avant de la maille parente.
1597 // Donc noeud sur l'arête en avant en bas.
1598 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1599
1600 // Priorité 10 < 13.
1601 if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1602 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1603 }
1604
1605 // Sinon, parent_cell est propriétaire du noeud.
1606 else {
1607 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1608 }
1609 }
1610
1611 // Sinon le noeud est quelque part sur la face en bas...
1612 else {
1613
1614 // Priorité 10 < 13.
1615 if (is_cell_around_parent_cell_different_owner(1, 0, 1)) {
1616 child_node_owner = owner_cells_around_parent_cell(1, 0, 1);
1617 }
1618
1619 // Parent_cell est le proprio.
1620 else {
1621 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1622 }
1623 }
1624 }
1625
1626 // Si le noeud est sur la face haute de la maille parente.
1627 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1628
1629 // Si le noeud est sur la face arrière de la maille parente.
1630 // Donc noeud sur l'arête en arrière en haut.
1631 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1632
1633 // Priorité 4 < 13.
1634 if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1635 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1636 }
1637
1638 // Priorité 7 < 13.
1639 else if (is_cell_around_parent_cell_different_owner(0, 2, 1)) {
1640 child_node_owner = owner_cells_around_parent_cell(0, 2, 1);
1641 }
1642
1643 // Sinon, parent_cell est propriétaire du noeud.
1644 else {
1645 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1646 }
1647 }
1648
1649 // Si le noeud est sur la face avant de la maille parente.
1650 // Donc noeud sur l'arête en avant en haut.
1651 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1652 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1653 }
1654
1655 // Sinon le noeud est quelque part sur la face en haut...
1656 else {
1657 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1658 }
1659 }
1660
1661 // Il ne reste plus que deux faces, la face arrière et la face avant...
1662 else {
1663
1664 // Si le noeud est quelque part sur la face arrière...
1665 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1666
1667 // Priorité 4 < 13.
1668 if (is_cell_around_parent_cell_different_owner(0, 1, 1)) {
1669 child_node_owner = owner_cells_around_parent_cell(0, 1, 1);
1670 }
1671
1672 // Parent_cell est le proprio.
1673 else {
1674 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1675 }
1676 }
1677
1678 // Si le noeud est quelque part sur la face avant...
1679 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1680 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1681 }
1682
1683 // Sinon, le noeud est à l'intérieur de la maille parente.
1684 else {
1685 child_node_owner = owner_cells_around_parent_cell(1, 1, 1);
1686 }
1687 }
1688 }
1689 }
1690
1691 // S'il y a une création de noeud et/ou un changement de propriétaire.
1692 if (child_node_owner != -1) {
1693 node_uid_to_owner[child_nodes_uids[l]] = child_node_owner;
1694
1695 // Lorsqu'il y a un changement de propriétaire sans création de noeud,
1696 // on doit mettre de côté les uniqueIds de ces noeuds pour pouvoir
1697 // itérer dessus par la suite.
1698 if (!is_new_node) {
1699 node_uid_change_owner_only.add(child_nodes_uids[l]);
1700 // debug() << "Child node (change owner) -- x : " << i
1701 // << " -- y : " << j
1702 // << " -- z : " << k
1703 // << " -- level : " << parent_cell_level + 1
1704 // << " -- node : " << l
1705 // << " -- uid_node : " << child_nodes_uids[l]
1706 // << " -- owner : " << child_node_owner;
1707 }
1708 else {
1709 // debug() << "Child node (create node) -- x : " << i
1710 // << " -- y : " << j
1711 // << " -- z : " << k
1712 // << " -- level : " << parent_cell_level + 1
1713 // << " -- node : " << l
1714 // << " -- uid_node : " << child_nodes_uids[l]
1715 // << " -- owner : " << child_node_owner;
1716 }
1717 }
1718 }
1719 }
1720 }
1721 }
1722 }
1723 }
1724 else {
1725 ARCANE_FATAL("Bad dimension");
1726 }
1727
1728 // Nodes
1729 {
1730 debug() << "Nb new nodes in patch : " << total_nb_nodes;
1731 {
1732 const Integer nb_node_owner_change = node_uid_change_owner_only.size();
1733
1734 // Ce tableau contiendra les localIds des nouveaux noeuds mais aussi les localIds
1735 // des noeuds qui changent juste de propriétaire.
1736 UniqueArray<Int32> nodes_lid(total_nb_nodes + nb_node_owner_change);
1737
1738 // On crée les noeuds. On met les localIds des nouveaux noeuds au début du tableau.
1739 m_mesh->modifier()->addNodes(nodes_infos, nodes_lid.subView(0, total_nb_nodes));
1740
1741 // On cherche les localIds des noeuds qui changent de proprio et on les met à la fin du tableau.
1742 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(nodes_lid.subView(total_nb_nodes, nb_node_owner_change), node_uid_change_owner_only, true);
1743
1744 UniqueArray<Int64> uid_child_nodes(total_nb_nodes + nb_node_owner_change);
1745 UniqueArray<Int32> lid_child_nodes(total_nb_nodes + nb_node_owner_change);
1746 Integer index = 0;
1747
1748 // On attribue les bons propriétaires aux noeuds.
1749 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
1750 Node node = *inode;
1751 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId()], my_rank);
1752
1753 if (node_uid_to_owner[node.uniqueId()] == my_rank) {
1755 }
1756 // TODO : Corriger ça dans la partie concerné directement.
1757 else {
1759 }
1760 // Attention, node.level() == -1 ici.
1761 uid_child_nodes[index++] = m_num_mng->parentNodeUniqueIdOfNode(node.uniqueId(), max_level + 1, false);
1762 }
1763
1764 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(lid_child_nodes, uid_child_nodes, false);
1765 NodeInfoListView nodes(m_mesh->nodeFamily());
1766
1767 index = 0;
1768 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
1769 const Int32 child_lid = lid_child_nodes[index++];
1770 if (child_lid == NULL_ITEM_ID) {
1771 continue;
1772 }
1773
1774 Node parent = nodes[child_lid];
1775 Node child = *inode;
1776
1777 m_mesh->modifier()->addParentNodeToNode(child, parent);
1778 m_mesh->modifier()->addChildNodeToNode(parent, child);
1779 }
1780 }
1781 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
1782 }
1783
1784 // Faces
1785 {
1786 debug() << "Nb new faces in patch : " << total_nb_faces;
1787 {
1788 const Integer nb_face_owner_change = face_uid_change_owner_only.size();
1789
1790 // Ce tableau contiendra les localIds des nouvelles faces mais aussi les localIds
1791 // des faces qui changent juste de propriétaire.
1792 UniqueArray<Int32> faces_lid(total_nb_faces + nb_face_owner_change);
1793
1794 // On crée les faces. On met les localIds des nouvelles faces au début du tableau.
1795 m_mesh->modifier()->addFaces(total_nb_faces, faces_infos, faces_lid.subView(0, total_nb_faces));
1796
1797 // On cherche les localIds des faces qui changent de proprio et on les met à la fin du tableau.
1798 m_mesh->faceFamily()->itemsUniqueIdToLocalId(faces_lid.subView(total_nb_faces, nb_face_owner_change), face_uid_change_owner_only, true);
1799
1800 UniqueArray<Int64> uid_parent_faces(total_nb_faces + nb_face_owner_change);
1801 UniqueArray<Int32> lid_parent_faces(total_nb_faces + nb_face_owner_change);
1802 Integer index = 0;
1803
1804 // On attribue les bons propriétaires aux faces.
1805 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
1806 Face face = *iface;
1807 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId()], my_rank);
1808
1809 if (face_uid_to_owner[face.uniqueId()] == my_rank) {
1811 }
1812 // TODO : Corriger ça dans la partie concerné directement.
1813 else {
1815 }
1816 // Attention, face.level() == -1 ici.
1817 uid_parent_faces[index++] = m_num_mng->parentFaceUniqueIdOfFace(face.uniqueId(), max_level + 1, false);
1818 // debug() << "Parent of : " << face.uniqueId() << " is : " << uid_child_faces[index - 1];
1819 }
1820
1821 m_mesh->faceFamily()->itemsUniqueIdToLocalId(lid_parent_faces, uid_parent_faces, false);
1822 FaceInfoListView faces(m_mesh->faceFamily());
1823
1824 index = 0;
1825 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
1826 const Int32 child_lid = lid_parent_faces[index++];
1827 if (child_lid == NULL_ITEM_ID) {
1828 continue;
1829 }
1830
1831 Face parent = faces[child_lid];
1832 Face child = *iface;
1833
1834 m_mesh->modifier()->addParentFaceToFace(child, parent);
1835 m_mesh->modifier()->addChildFaceToFace(parent, child);
1836 }
1837 }
1838 m_mesh->faceFamily()->notifyItemsOwnerChanged();
1839 }
1840
1841 // Cells
1842 {
1843 debug() << "Nb new cells in patch : " << total_nb_cells;
1844
1845 UniqueArray<Int32> cells_lid(total_nb_cells);
1846 m_mesh->modifier()->addCells(total_nb_cells, cells_infos, cells_lid);
1847
1848 // Itération sur les nouvelles mailles.
1849 CellInfoListView cells(m_mesh->cellFamily());
1850 for (Integer i = 0; i < total_nb_cells; ++i) {
1851 Cell child = cells[cells_lid[i]];
1852
1853 child.mutableItemBase().setOwner(parent_cells[i].owner(), my_rank);
1854
1856
1857 if (parent_cells[i].owner() == my_rank) {
1859 }
1860
1861 if (parent_cells[i].itemBase().flags() & ItemFlags::II_Shared) {
1863 }
1864
1865 m_mesh->modifier()->addParentCellToCell(child, parent_cells[i]);
1866 m_mesh->modifier()->addChildCellToCell(parent_cells[i], child);
1867 }
1868
1869 // Itération sur les mailles parentes.
1870 for (Cell cell : cell_to_refine_internals) {
1871 cell.mutableItemBase().removeFlags(ItemFlags::II_Refine);
1872 cell.mutableItemBase().addFlags(ItemFlags::II_JustRefined | ItemFlags::II_Inactive);
1873 }
1874 m_mesh->cellFamily()->notifyItemsOwnerChanged();
1875 }
1876
1877 m_mesh->modifier()->endUpdate();
1878
1879 // On positionne les noeuds dans l'espace.
1880 for (Cell parent_cell : cell_to_refine_internals) {
1881 m_num_mng->setChildNodeCoordinates(parent_cell);
1882 // On ajoute le flag "II_Shared" aux noeuds et aux faces des mailles partagées.
1883 if (parent_cell.mutableItemBase().flags() & ItemFlags::II_Shared) {
1884 for (Integer i = 0; i < parent_cell.nbHChildren(); ++i) {
1885 Cell child_cell = parent_cell.hChild(i);
1886 for (Node node : child_cell.nodes()) {
1887 if (node.mutableItemBase().flags() & ItemFlags::II_Own) {
1888 node.mutableItemBase().addFlags(ItemFlags::II_Shared);
1889 }
1890 }
1891
1892 for (Face face : child_cell.faces()) {
1893 if (face.mutableItemBase().flags() & ItemFlags::II_Own) {
1894 face.mutableItemBase().addFlags(ItemFlags::II_Shared);
1895 }
1896 }
1897 }
1898 }
1899 }
1900
1901 // Recalcule les informations de synchronisation.
1902 m_mesh->computeSynchronizeInfos();
1903
1904 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
1905 // debug() << "\t" << *icell;
1906 // for(Node node : icell->nodes()){
1907 // debug() << "\t\t" << node;
1908 // }
1909 // for(Face face : icell->faces()){
1910 // debug() << "\t\t\t" << face;
1911 // }
1912 // }
1913 // info() << "Résumé :";
1914 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
1915 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
1916 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
1917 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
1918 // }
1919 // }
1920 // info() << "Résumé node:";
1921 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
1922 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
1923 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
1924 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
1925 // }
1926 // }
1927 //
1928 // info() << "Résumé :";
1929 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
1930 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
1931 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
1932 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
1933 // }
1934 // }
1935}
1936
1937/*---------------------------------------------------------------------------*/
1938/*---------------------------------------------------------------------------*/
1939
1940void CartesianMeshAMRPatchMng::
1941createSubLevel()
1942{
1943 IParallelMng* pm = m_mesh->parallelMng();
1944 Int32 nb_rank = pm->commSize();
1945 Int32 my_rank = pm->commRank();
1946
1947 UniqueArray<Int64> cell_uid_to_create;
1948
1949 // TODO : Remplacer around_parent_cells_uid_to_owner par parent_to_child_cells ?
1950 std::unordered_map<Int64, Int32> around_parent_cells_uid_to_owner;
1951 std::unordered_map<Int64, bool> around_parent_cells_uid_is_in_subdomain;
1952 std::unordered_map<Int64, UniqueArray<Cell>> parent_to_child_cells;
1953
1954 std::unordered_map<Int64, Int32> node_uid_to_owner;
1955 std::unordered_map<Int64, Int32> face_uid_to_owner;
1956
1957 // On va créer le niveau -1.
1958 // À noter qu'à la fin de la méthode, on replacera ce niveau
1959 // à 0.
1960 m_num_mng->prepareLevel(-1);
1961
1962 // On crée une ou plusieurs couches de mailles fantômes
1963 // pour éviter qu'une maille parente n'ai pas le même
1964 // nombre de mailles enfant.
1965 // ----------
1966 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1967 IMeshModifier* mesh_modifier = m_mesh->modifier();
1968 IGhostLayerMng* gm = m_mesh->ghostLayerMng();
1969 // Il faut au moins utiliser la version 3 pour pouvoir supporter
1970 // plusieurs couches de mailles fantômes
1971 Int32 version = gm->builderVersion();
1972 if (version < 3)
1973 gm->setBuilderVersion(3);
1974 Int32 nb_ghost_layer = gm->nbGhostLayer();
1975 // TODO AH : Cette ligne permettrait d'avoir moins de mailles fantômes et
1976 // d'éviter leurs suppressions en cas d'inutilité. Mais le comportement
1977 // serait différent de l'AMR historique.
1978 //gm->setNbGhostLayer(nb_ghost_layer + (nb_ghost_layer % m_num_mng->pattern()));
1979 // Comportement de l'AMR historique.
1980 gm->setNbGhostLayer(nb_ghost_layer * 2);
1981 mesh_modifier->setDynamic(true);
1982 mesh_modifier->updateGhostLayers();
1983 // Remet le nombre initial de couches de mailles fantômes
1984 gm->setNbGhostLayer(nb_ghost_layer);
1985 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1986 // ----------
1987
1988 // On récupère les uniqueIds des parents à créer.
1989 ENUMERATE_ (Cell, icell, m_mesh->allLevelCells(0)) {
1990 Cell cell = *icell;
1991
1992 Int64 parent_uid = m_num_mng->parentCellUniqueIdOfCell(cell);
1993
1994 // On évite les doublons.
1995 if (!cell_uid_to_create.contains(parent_uid)) {
1996 cell_uid_to_create.add(parent_uid);
1997 // On en profite pour sauvegarder les owners des futures mailles
1998 // qui seront les mêmes owners que les mailles enfants.
1999 around_parent_cells_uid_to_owner[parent_uid] = cell.owner();
2000 around_parent_cells_uid_is_in_subdomain[parent_uid] = true;
2001 }
2002 else {
2003 // Ça peut arriver si le partitionnement n'est pas adapté.
2004 if (around_parent_cells_uid_to_owner[parent_uid] != cell.owner()) {
2005 ARCANE_FATAL("Pb owner");
2006 }
2007 }
2008
2009 // On doit sauvegarder les enfants des parents pour créer les connectivités
2010 // à la fin.
2011 parent_to_child_cells[parent_uid].add(cell);
2012 }
2013
2014 // info() << cell_uid_to_create;
2015 // for (const auto& [key, value] : parent_to_child_cells) {
2016 // info() << "Parent : " << key << " -- Children : " << value;
2017 // }
2018
2019 UniqueArray<Int64> cells_infos;
2020 UniqueArray<Int64> faces_infos;
2021 UniqueArray<Int64> nodes_infos;
2022
2023 Integer total_nb_cells = 0;
2024 Integer total_nb_nodes = 0;
2025 Integer total_nb_faces = 0;
2026
2027 // Deux tableaux permettant de récupérer les uniqueIds des noeuds et des faces
2028 // de chaque maille parent à chaque appel à getNodeUids()/getFaceUids().
2029 UniqueArray<Int64> parent_nodes_uids(m_num_mng->nbNodeByCell());
2030 UniqueArray<Int64> parent_faces_uids(m_num_mng->nbFaceByCell());
2031
2032 // Partie échange d'informations sur les mailles autour du patch
2033 // (pour remplacer les mailles fantômes).
2034 {
2035 // Tableau qui contiendra les uids des mailles dont on a besoin des infos.
2036 UniqueArray<Int64> uid_of_cells_needed;
2037 {
2038 UniqueArray<Int64> cell_uids_around((m_mesh->dimension() == 2) ? 9 : 27);
2039 for (Int64 parent_cell : cell_uid_to_create) {
2040 m_num_mng->cellUniqueIdsAroundCell(cell_uids_around, parent_cell, -1);
2041 for (Int64 cell_uid : cell_uids_around) {
2042 // Si -1 alors il n'y a pas de mailles à cette position.
2043 if (cell_uid == -1)
2044 continue;
2045
2046 // TODO C++20 : Mettre map.contains().
2047 // SI on a la maille, on n'a pas besoin de demander d'infos.
2048 if (around_parent_cells_uid_to_owner.find(cell_uid) != around_parent_cells_uid_to_owner.end())
2049 continue;
2050
2051 // TODO : Bof
2052 if (!uid_of_cells_needed.contains(cell_uid)) {
2053 uid_of_cells_needed.add(cell_uid);
2054
2055 // Si on a besoin des infos, c'est que l'on ne les possèdent pas :-)
2056 // On en profite pour enregistrer cette information pour distinguer les
2057 // mailles fantômes dont on possède les items (faces/noeuds) de celle dont
2058 // on ne possède rien.
2059 around_parent_cells_uid_is_in_subdomain[cell_uid] = false;
2060 }
2061 }
2062 }
2063 }
2064
2065 // On partage les cell uid nécessaires de tout le monde.
2066 UniqueArray<Int64> uid_of_cells_needed_all_procs;
2067 pm->allGatherVariable(uid_of_cells_needed, uid_of_cells_needed_all_procs);
2068
2069 UniqueArray<Int32> owner_of_cells_needed_all_procs(uid_of_cells_needed_all_procs.size());
2070
2071 {
2072 // On enregistre le propriétaire des mailles que l'on possède.
2073 for (Integer i = 0; i < uid_of_cells_needed_all_procs.size(); ++i) {
2074 if (around_parent_cells_uid_to_owner.find(uid_of_cells_needed_all_procs[i]) != around_parent_cells_uid_to_owner.end()) {
2075 owner_of_cells_needed_all_procs[i] = around_parent_cells_uid_to_owner[uid_of_cells_needed_all_procs[i]];
2076 }
2077 else {
2078 // Le ReduceMax fera disparaitre ce -1.
2079 owner_of_cells_needed_all_procs[i] = -1;
2080 }
2081 }
2082 }
2083
2084 // On récupère les owners de toutes les mailles nécessaires.
2085 pm->reduce(Parallel::eReduceType::ReduceMax, owner_of_cells_needed_all_procs);
2086
2087 // On ne traite que les owners des mailles nécessaires pour nous.
2088 {
2089 Integer size_uid_of_cells_needed = uid_of_cells_needed.size();
2090 Integer my_pos_in_all_procs_arrays = 0;
2091 UniqueArray<Integer> size_uid_of_cells_needed_per_proc(nb_rank);
2092 ArrayView<Integer> av(1, &size_uid_of_cells_needed);
2093 pm->allGather(av, size_uid_of_cells_needed_per_proc);
2094
2095 // On zap les mailles de tous les procs avant nous.
2096 for (Integer i = 0; i < my_rank; ++i) {
2097 my_pos_in_all_procs_arrays += size_uid_of_cells_needed_per_proc[i];
2098 }
2099
2100 // On enregistre les owners nécessaires.
2101 ArrayView<Int32> owner_of_cells_needed = owner_of_cells_needed_all_procs.subView(my_pos_in_all_procs_arrays, size_uid_of_cells_needed);
2102 for (Integer i = 0; i < size_uid_of_cells_needed; ++i) {
2103 around_parent_cells_uid_to_owner[uid_of_cells_needed[i]] = owner_of_cells_needed[i];
2104
2105 // En rafinnement, il peut y avoir plusieurs niveaux d'écarts entre les patchs.
2106 // En déraffinement, c'est impossible vu que le niveau 0 n'a pas de "trous".
2107 if (owner_of_cells_needed[i] == -1) {
2108 ARCANE_FATAL("En déraffinement, c'est normalement impossible");
2109 }
2110 }
2111 }
2112 }
2113
2114 if (m_mesh->dimension() == 2) {
2115
2116 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2117 // ou si on doit regarder la maille d'à côté avant (false).
2118 // Rappel que le parcours des faces par Arcane est dans l'ordre NumPad{2, 6, 8, 4}.
2119 constexpr bool mask_face_if_cell_left[] = { true, true, true, false };
2120 constexpr bool mask_face_if_cell_bottom[] = { false, true, true, true };
2121
2122 // Rappel que le parcours des nodes par Arcane est dans l'ordre NumPad{1, 3, 9, 7}.
2123 constexpr bool mask_node_if_cell_left[] = { false, true, true, false };
2124 constexpr bool mask_node_if_cell_bottom[] = { false, false, true, true };
2125
2126 FixedArray<Int64, 9> cells_uid_around;
2127 FixedArray<Int32, 9> owner_cells_around_parent_cell_1d;
2128 FixedArray<bool, 9> is_not_in_subdomain_cells_around_parent_cell_1d;
2129
2130 // Pour le raffinement, on parcourait les mailles parents existantes.
2131 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2132 for (Int64 parent_cell_uid : cell_uid_to_create) {
2133
2134 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around.view(), parent_cell_uid, -1);
2135
2136 ConstArray2View owner_cells_around_parent_cell(owner_cells_around_parent_cell_1d.data(), 3, 3);
2137 // Attention au "not" dans le nom de la variable.
2138 ConstArray2View is_not_in_subdomain_cells_around_parent_cell(is_not_in_subdomain_cells_around_parent_cell_1d.data(), 3, 3);
2139
2140 for (Integer i = 0; i < 9; ++i) {
2141 Int64 uid_cell = cells_uid_around[i];
2142 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2143 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2144 if (uid_cell != -1 && around_parent_cells_uid_to_owner[uid_cell] != -1) {
2145 owner_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_owner[uid_cell];
2146 is_not_in_subdomain_cells_around_parent_cell_1d[i] = !around_parent_cells_uid_is_in_subdomain[uid_cell];
2147 }
2148 else {
2149 cells_uid_around[i] = -1;
2150 owner_cells_around_parent_cell_1d[i] = -1;
2151 is_not_in_subdomain_cells_around_parent_cell_1d[i] = true;
2152 }
2153 }
2154
2155 // Ces deux lambdas sont différentes.
2156 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2157 // la première lambda répondra donc forcément true alors que la seconde false.
2158 auto is_cell_around_parent_cell_different_owner = [&](const Integer y, const Integer x) {
2159 return (owner_cells_around_parent_cell(y, x) != owner_cells_around_parent_cell(1, 1));
2160 };
2161
2162 auto is_cell_around_parent_cell_exist_and_different_owner = [&](const Integer y, const Integer x) {
2163 return (owner_cells_around_parent_cell(y, x) != -1 && (owner_cells_around_parent_cell(y, x) != owner_cells_around_parent_cell(1, 1)));
2164 };
2165
2166 total_nb_cells++;
2167 // debug() << "Parent"
2168 // << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2169 // << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2170 // << " -- level : " << -1
2171 // << " -- uid : " << parent_cell_uid;
2172
2173 // On récupère les uniqueIds des nodes et faces à créer.
2174 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2175 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2176
2177 constexpr Integer type_cell = IT_Quad4;
2178 constexpr Integer type_face = IT_Line2;
2179
2180 // Partie Cell.
2181 cells_infos.add(type_cell);
2182 cells_infos.add(parent_cell_uid);
2183 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2184 cells_infos.add(parent_nodes_uids[nc]);
2185 }
2186
2187 // Partie Face.
2188 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2189 // On regarde si l'on doit traiter la face.
2190 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2191 // ou si la maille à gauche est dans notre sous-domaine ou non.
2192 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2193 // on doit créer la face en tant que face fantôme.
2194 if (
2195 (mask_face_if_cell_left[l] || is_cell_around_parent_cell_different_owner(1, 0) || is_not_in_subdomain_cells_around_parent_cell(1, 0)) &&
2196 (mask_face_if_cell_bottom[l] || is_cell_around_parent_cell_different_owner(0, 1) || is_not_in_subdomain_cells_around_parent_cell(0, 1))) {
2197 Integer parent_face_owner = -1;
2198 faces_infos.add(type_face);
2199 faces_infos.add(parent_faces_uids[l]);
2200
2201 // Les noeuds de la face sont toujours les noeuds l et l+1
2202 // car on utilise la même exploration pour les deux cas.
2203 for (Integer nc = l; nc < l + 2; nc++) {
2204 faces_infos.add(parent_nodes_uids[nc % m_num_mng->nbNodeByCell()]);
2205 }
2206 total_nb_faces++;
2207
2208 if ((!mask_face_if_cell_left[l]) && is_cell_around_parent_cell_exist_and_different_owner(1, 0)) {
2209 parent_face_owner = owner_cells_around_parent_cell(1, 0);
2210 }
2211 else if ((!mask_face_if_cell_bottom[l]) && is_cell_around_parent_cell_exist_and_different_owner(0, 1)) {
2212 parent_face_owner = owner_cells_around_parent_cell(0, 1);
2213 }
2214 else {
2215 parent_face_owner = owner_cells_around_parent_cell(1, 1);
2216 }
2217 face_uid_to_owner[parent_faces_uids[l]] = parent_face_owner;
2218 // debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2219 // << " -- level : " << -1
2220 // << " -- face : " << l
2221 // << " -- uid_face : " << parent_faces_uids[l]
2222 // << " -- owner : " << parent_face_owner;
2223 }
2224 }
2225
2226 // Partie Node.
2227 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2228 // plus de propriétaires possibles.
2229 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2230 if (
2231 (mask_node_if_cell_left[l] || is_cell_around_parent_cell_different_owner(1, 0) || is_not_in_subdomain_cells_around_parent_cell(1, 0)) &&
2232 (mask_node_if_cell_bottom[l] || is_cell_around_parent_cell_different_owner(0, 1) || is_not_in_subdomain_cells_around_parent_cell(0, 1))) {
2233 Integer parent_node_owner = -1;
2234 nodes_infos.add(parent_nodes_uids[l]);
2235 total_nb_nodes++;
2236
2237 if ((!mask_node_if_cell_left[l])) {
2238 if ((!mask_node_if_cell_bottom[l])) {
2239 if (is_cell_around_parent_cell_exist_and_different_owner(0, 0)) {
2240 parent_node_owner = owner_cells_around_parent_cell(0, 0);
2241 }
2242 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1)) {
2243 parent_node_owner = owner_cells_around_parent_cell(0, 1);
2244 }
2245 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0)) {
2246 parent_node_owner = owner_cells_around_parent_cell(1, 0);
2247 }
2248 else {
2249 parent_node_owner = owner_cells_around_parent_cell(1, 1);
2250 }
2251 }
2252 else {
2253 if (is_cell_around_parent_cell_exist_and_different_owner(1, 0)) {
2254 parent_node_owner = owner_cells_around_parent_cell(1, 0);
2255 }
2256 else {
2257 parent_node_owner = owner_cells_around_parent_cell(1, 1);
2258 }
2259 }
2260 }
2261 else {
2262 if ((!mask_node_if_cell_bottom[l])) {
2263 if (is_cell_around_parent_cell_exist_and_different_owner(0, 1)) {
2264 parent_node_owner = owner_cells_around_parent_cell(0, 1);
2265 }
2266 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 2)) {
2267 parent_node_owner = owner_cells_around_parent_cell(0, 2);
2268 }
2269 else {
2270 parent_node_owner = owner_cells_around_parent_cell(1, 1);
2271 }
2272 }
2273 else {
2274 parent_node_owner = owner_cells_around_parent_cell(1, 1);
2275 }
2276 }
2277
2278 node_uid_to_owner[parent_nodes_uids[l]] = parent_node_owner;
2279 // debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2280 // << " -- level : " << -1
2281 // << " -- node : " << l
2282 // << " -- uid_node : " << parent_nodes_uids[l]
2283 // << " -- owner : " << parent_node_owner;
2284 }
2285 }
2286 }
2287 }
2288 else if (m_mesh->dimension() == 3) {
2289
2290 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2291 // ou si on doit regarder la maille d'à côté avant (false).
2292 constexpr bool mask_node_if_cell_left[] = { false, true, true, false, false, true, true, false };
2293 constexpr bool mask_node_if_cell_bottom[] = { false, false, true, true, false, false, true, true };
2294 constexpr bool mask_node_if_cell_rear[] = { false, false, false, false, true, true, true, true };
2295
2296 constexpr bool mask_face_if_cell_left[] = { true, false, true, true, true, true };
2297 constexpr bool mask_face_if_cell_bottom[] = { true, true, false, true, true, true };
2298 constexpr bool mask_face_if_cell_rear[] = { false, true, true, true, true, true };
2299
2300 // Petite différence par rapport au 2D. Pour le 2D, la position des noeuds des faces
2301 // dans le tableau "parent_nodes_uids" est toujours pareil (l et l+1, voir le 2D).
2302 // Pour le 3D, ce n'est pas le cas donc on a des tableaux pour avoir une correspondance
2303 // entre les noeuds de chaque face et la position des noeuds dans le tableau "parent_nodes_uids".
2304 // (Exemple : pour la face 1 (même ordre d'énumération qu'Arcane), on doit prendre le
2305 // tableau "nodes_in_face_1" et donc les noeuds "parent_nodes_uids[0]", "parent_nodes_uids[3]",
2306 // "parent_nodes_uids[7]" et "parent_nodes_uids[4]").
2307 constexpr Integer nodes_in_face_0[] = { 0, 1, 2, 3 };
2308 constexpr Integer nodes_in_face_1[] = { 0, 3, 7, 4 };
2309 constexpr Integer nodes_in_face_2[] = { 0, 1, 5, 4 };
2310 constexpr Integer nodes_in_face_3[] = { 4, 5, 6, 7 };
2311 constexpr Integer nodes_in_face_4[] = { 1, 2, 6, 5 };
2312 constexpr Integer nodes_in_face_5[] = { 3, 2, 6, 7 };
2313
2314 constexpr Integer nb_nodes_in_face = 4;
2315 FixedArray<Int64, 27> cells_uid_around;
2316 FixedArray<Int32, 27> owner_cells_around_parent_cell_1d;
2317 FixedArray<bool, 27> is_not_in_subdomain_cells_around_parent_cell_1d;
2318
2319 // Pour le raffinement, on parcourait les mailles parents existantes.
2320 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2321 for (Int64 parent_cell_uid : cell_uid_to_create) {
2322
2323 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around.view(), parent_cell_uid, -1);
2324
2325 ConstArray3View owner_cells_around_parent_cell(owner_cells_around_parent_cell_1d.data(), 3, 3, 3);
2326 // Attention au "not" dans le nom de la variable.
2327 ConstArray3View is_not_in_subdomain_cells_around_parent_cell(is_not_in_subdomain_cells_around_parent_cell_1d.data(), 3, 3, 3);
2328
2329 for (Integer i = 0; i < 27; ++i) {
2330 Int64 uid_cell = cells_uid_around[i];
2331 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2332 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2333 if (uid_cell != -1 && around_parent_cells_uid_to_owner[uid_cell] != -1) {
2334 owner_cells_around_parent_cell_1d[i] = around_parent_cells_uid_to_owner[uid_cell];
2335 is_not_in_subdomain_cells_around_parent_cell_1d[i] = !around_parent_cells_uid_is_in_subdomain[uid_cell];
2336 }
2337 else {
2338 cells_uid_around[i] = -1;
2339 owner_cells_around_parent_cell_1d[i] = -1;
2340 is_not_in_subdomain_cells_around_parent_cell_1d[i] = true;
2341 }
2342 }
2343
2344 // Ces deux lambdas sont différentes.
2345 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2346 // la première lambda répondra donc forcément true alors que la seconde false.
2347 auto is_cell_around_parent_cell_different_owner = [&](const Integer z, const Integer y, const Integer x) {
2348 return (owner_cells_around_parent_cell(z, y, x) != owner_cells_around_parent_cell(1, 1, 1));
2349 };
2350
2351 auto is_cell_around_parent_cell_exist_and_different_owner = [&](const Integer z, const Integer y, const Integer x) {
2352 return (owner_cells_around_parent_cell(z, y, x) != -1 && (owner_cells_around_parent_cell(z, y, x) != owner_cells_around_parent_cell(1, 1, 1)));
2353 };
2354
2355 total_nb_cells++;
2356 // debug() << "Parent"
2357 // << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2358 // << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2359 // << " -- z : " << m_num_mng->cellUniqueIdToCoordZ(parent_cell_uid, -1)
2360 // << " -- level : " << -1
2361 // << " -- uid : " << parent_cell_uid;
2362
2363 // On récupère les uniqueIds des nodes et faces à créer.
2364 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2365 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2366
2367 constexpr Integer type_cell = IT_Hexaedron8;
2368 constexpr Integer type_face = IT_Quad4;
2369
2370 // Partie Cell.
2371 cells_infos.add(type_cell);
2372 cells_infos.add(parent_cell_uid);
2373 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2374 cells_infos.add(parent_nodes_uids[nc]);
2375 }
2376
2377 // Partie Face.
2378 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2379 // On regarde si l'on doit traiter la face.
2380 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2381 // ou si la maille à gauche est dans notre sous-domaine ou non.
2382 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2383 // on doit créer la face en tant que face fantôme.
2384 if (
2385 (mask_face_if_cell_left[l] || is_cell_around_parent_cell_different_owner(1, 1, 0) || is_not_in_subdomain_cells_around_parent_cell(1, 1, 0)) &&
2386 (mask_face_if_cell_bottom[l] || is_cell_around_parent_cell_different_owner(1, 0, 1) || is_not_in_subdomain_cells_around_parent_cell(1, 0, 1)) &&
2387 (mask_face_if_cell_rear[l] || is_cell_around_parent_cell_different_owner(0, 1, 1) || is_not_in_subdomain_cells_around_parent_cell(0, 1, 1))) {
2388 Integer parent_face_owner = -1;
2389 faces_infos.add(type_face);
2390 faces_infos.add(parent_faces_uids[l]);
2391
2392 // On récupère la position des noeuds de la face dans le tableau "ua_node_uid".
2393 ConstArrayView<Integer> nodes_in_face_l;
2394 switch (l) {
2395 case 0:
2396 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_0, nb_nodes_in_face);
2397 break;
2398 case 1:
2399 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_1, nb_nodes_in_face);
2400 break;
2401 case 2:
2402 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_2, nb_nodes_in_face);
2403 break;
2404 case 3:
2405 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_3, nb_nodes_in_face);
2406 break;
2407 case 4:
2408 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_4, nb_nodes_in_face);
2409 break;
2410 case 5:
2411 nodes_in_face_l = ConstArrayView<Integer>::create(nodes_in_face_5, nb_nodes_in_face);
2412 break;
2413 default:
2414 ARCANE_FATAL("Bizarre...");
2415 }
2416 for (Integer nc : nodes_in_face_l) {
2417 faces_infos.add(parent_nodes_uids[nc]);
2418 }
2419 total_nb_faces++;
2420
2421 if ((!mask_face_if_cell_left[l]) && is_cell_around_parent_cell_exist_and_different_owner(1, 1, 0)) {
2422 parent_face_owner = owner_cells_around_parent_cell(1, 1, 0);
2423 }
2424 else if ((!mask_face_if_cell_bottom[l]) && is_cell_around_parent_cell_exist_and_different_owner(1, 0, 1)) {
2425 parent_face_owner = owner_cells_around_parent_cell(1, 0, 1);
2426 }
2427 else if ((!mask_face_if_cell_rear[l]) && is_cell_around_parent_cell_exist_and_different_owner(0, 1, 1)) {
2428 parent_face_owner = owner_cells_around_parent_cell(0, 1, 1);
2429 }
2430 else {
2431 parent_face_owner = owner_cells_around_parent_cell(1, 1, 1);
2432 }
2433 face_uid_to_owner[parent_faces_uids[l]] = parent_face_owner;
2434 // debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2435 // << " -- level : " << -1
2436 // << " -- face : " << l
2437 // << " -- uid_face : " << parent_faces_uids[l]
2438 // << " -- owner : " << parent_face_owner;
2439 }
2440 }
2441
2442 // Partie Node.
2443 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2444 // plus de propriétaires possibles.
2445 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2446 if (
2447 (mask_node_if_cell_left[l] || is_cell_around_parent_cell_different_owner(1, 1, 0) || is_not_in_subdomain_cells_around_parent_cell(1, 1, 0)) &&
2448 (mask_node_if_cell_bottom[l] || is_cell_around_parent_cell_different_owner(1, 0, 1) || is_not_in_subdomain_cells_around_parent_cell(1, 0, 1)) &&
2449 (mask_node_if_cell_rear[l] || is_cell_around_parent_cell_different_owner(0, 1, 1) || is_not_in_subdomain_cells_around_parent_cell(0, 1, 1))) {
2450 Integer parent_node_owner = -1;
2451 nodes_infos.add(parent_nodes_uids[l]);
2452 total_nb_nodes++;
2453
2454 if ((!mask_node_if_cell_left[l])) {
2455 if ((!mask_node_if_cell_bottom[l])) {
2456 if ((!mask_node_if_cell_rear[l])) {
2457
2458 if (is_cell_around_parent_cell_exist_and_different_owner(0, 0, 0)) {
2459 parent_node_owner = owner_cells_around_parent_cell(0, 0, 0);
2460 }
2461 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 0, 1)) {
2462 parent_node_owner = owner_cells_around_parent_cell(0, 0, 1);
2463 }
2464 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 0)) {
2465 parent_node_owner = owner_cells_around_parent_cell(0, 1, 0);
2466 }
2467 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 1)) {
2468 parent_node_owner = owner_cells_around_parent_cell(0, 1, 1);
2469 }
2470 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 0)) {
2471 parent_node_owner = owner_cells_around_parent_cell(1, 0, 0);
2472 }
2473 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 1)) {
2474 parent_node_owner = owner_cells_around_parent_cell(1, 0, 1);
2475 }
2476 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 1, 0)) {
2477 parent_node_owner = owner_cells_around_parent_cell(1, 1, 0);
2478 }
2479 else {
2480 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2481 }
2482 }
2483 else {
2484 if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 0)) {
2485 parent_node_owner = owner_cells_around_parent_cell(1, 0, 0);
2486 }
2487 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 1)) {
2488 parent_node_owner = owner_cells_around_parent_cell(1, 0, 1);
2489 }
2490 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 1, 0)) {
2491 parent_node_owner = owner_cells_around_parent_cell(1, 1, 0);
2492 }
2493 else {
2494 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2495 }
2496 }
2497 }
2498 else {
2499 if ((!mask_node_if_cell_rear[l])) {
2500 if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 0)) {
2501 parent_node_owner = owner_cells_around_parent_cell(0, 1, 0);
2502 }
2503 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 1)) {
2504 parent_node_owner = owner_cells_around_parent_cell(0, 1, 1);
2505 }
2506 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 2, 0)) {
2507 parent_node_owner = owner_cells_around_parent_cell(0, 2, 0);
2508 }
2509 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 2, 1)) {
2510 parent_node_owner = owner_cells_around_parent_cell(0, 2, 1);
2511 }
2512 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 1, 0)) {
2513 parent_node_owner = owner_cells_around_parent_cell(1, 1, 0);
2514 }
2515 else {
2516 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2517 }
2518 }
2519 else {
2520 if (is_cell_around_parent_cell_exist_and_different_owner(1, 1, 0)) {
2521 parent_node_owner = owner_cells_around_parent_cell(1, 1, 0);
2522 }
2523 else {
2524 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2525 }
2526 }
2527 }
2528 }
2529 else {
2530 if ((!mask_node_if_cell_bottom[l])) {
2531 if ((!mask_node_if_cell_rear[l])) {
2532 if (is_cell_around_parent_cell_exist_and_different_owner(0, 0, 1)) {
2533 parent_node_owner = owner_cells_around_parent_cell(0, 0, 1);
2534 }
2535 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 0, 2)) {
2536 parent_node_owner = owner_cells_around_parent_cell(0, 0, 2);
2537 }
2538 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 1)) {
2539 parent_node_owner = owner_cells_around_parent_cell(0, 1, 1);
2540 }
2541 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 2)) {
2542 parent_node_owner = owner_cells_around_parent_cell(0, 1, 2);
2543 }
2544 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 1)) {
2545 parent_node_owner = owner_cells_around_parent_cell(1, 0, 1);
2546 }
2547 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 2)) {
2548 parent_node_owner = owner_cells_around_parent_cell(1, 0, 2);
2549 }
2550 else {
2551 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2552 }
2553 }
2554 else {
2555 if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 1)) {
2556 parent_node_owner = owner_cells_around_parent_cell(1, 0, 1);
2557 }
2558 else if (is_cell_around_parent_cell_exist_and_different_owner(1, 0, 2)) {
2559 parent_node_owner = owner_cells_around_parent_cell(1, 0, 2);
2560 }
2561 else {
2562 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2563 }
2564 }
2565 }
2566 else {
2567 if ((!mask_node_if_cell_rear[l])) {
2568 if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 1)) {
2569 parent_node_owner = owner_cells_around_parent_cell(0, 1, 1);
2570 }
2571 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 1, 2)) {
2572 parent_node_owner = owner_cells_around_parent_cell(0, 1, 2);
2573 }
2574 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 2, 1)) {
2575 parent_node_owner = owner_cells_around_parent_cell(0, 2, 1);
2576 }
2577 else if (is_cell_around_parent_cell_exist_and_different_owner(0, 2, 2)) {
2578 parent_node_owner = owner_cells_around_parent_cell(0, 2, 2);
2579 }
2580 else {
2581 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2582 }
2583 }
2584 else {
2585 parent_node_owner = owner_cells_around_parent_cell(1, 1, 1);
2586 }
2587 }
2588 }
2589
2590 node_uid_to_owner[parent_nodes_uids[l]] = parent_node_owner;
2591 // debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2592 // << " -- level : " << -1
2593 // << " -- node : " << l
2594 // << " -- uid_node : " << parent_nodes_uids[l]
2595 // << " -- owner : " << parent_node_owner;
2596 }
2597 }
2598 }
2599 }
2600 else {
2601 ARCANE_FATAL("Bad dimension");
2602 }
2603
2604 // Nodes
2605 {
2606 debug() << "Nb new nodes in patch : " << total_nb_nodes;
2607 {
2608 // Ce tableau contiendra les localIds des nouveaux noeuds.
2609 UniqueArray<Int32> nodes_lid(total_nb_nodes);
2610
2611 // On crée les noeuds. On met les localIds des nouveaux noeuds au début du tableau.
2612 m_mesh->modifier()->addNodes(nodes_infos, nodes_lid);
2613
2614 UniqueArray<Int64> uid_child_nodes(total_nb_nodes);
2615 UniqueArray<Int32> lid_child_nodes(total_nb_nodes);
2616 Integer index = 0;
2617
2618 // On attribue les bons propriétaires aux noeuds.
2619 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2620 Node node = *inode;
2621
2622 ARCANE_ASSERT((node_uid_to_owner.find(node.uniqueId()) != node_uid_to_owner.end()), ("No owner found for node"));
2623 ARCANE_ASSERT((node_uid_to_owner[node.uniqueId()] < nb_rank && node_uid_to_owner[node.uniqueId()] >= 0), ("Bad owner found for node"));
2624
2625 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId()], my_rank);
2626
2627 if (node_uid_to_owner[node.uniqueId()] == my_rank) {
2629 }
2630
2631 uid_child_nodes[index++] = m_num_mng->childNodeUniqueIdOfNode(node.uniqueId(), -1);
2632 }
2633 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(lid_child_nodes, uid_child_nodes, false);
2634 NodeInfoListView nodes(m_mesh->nodeFamily());
2635
2636 index = 0;
2637 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2638 const Int32 child_lid = lid_child_nodes[index++];
2639 if (child_lid == NULL_ITEM_ID) {
2640 continue;
2641 }
2642
2643 Node child = nodes[child_lid];
2644 Node parent = *inode;
2645
2646 m_mesh->modifier()->addParentNodeToNode(child, parent);
2647 m_mesh->modifier()->addChildNodeToNode(parent, child);
2648 }
2649 }
2650
2651 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2652 }
2653
2654 // Faces
2655 {
2656 debug() << "Nb new faces in patch : " << total_nb_faces;
2657 {
2658 Integer nb_child = (m_mesh->dimension() == 2 ? 2 : 4);
2659 UniqueArray<Int32> faces_lid(total_nb_faces);
2660
2661 m_mesh->modifier()->addFaces(total_nb_faces, faces_infos, faces_lid);
2662
2663 UniqueArray<Int64> uid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2664 UniqueArray<Int32> lid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2665 Integer index = 0;
2666
2667 // On attribue les bons propriétaires aux faces.
2668 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2669 Face face = *iface;
2670
2671 ARCANE_ASSERT((face_uid_to_owner.find(face.uniqueId()) != face_uid_to_owner.end()), ("No owner found for face"));
2672 ARCANE_ASSERT((face_uid_to_owner[face.uniqueId()] < nb_rank && face_uid_to_owner[face.uniqueId()] >= 0), ("Bad owner found for face"));
2673
2674 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId()], my_rank);
2675
2676 if (face_uid_to_owner[face.uniqueId()] == my_rank) {
2678 }
2679
2680 for (Integer i = 0; i < nb_child; ++i) {
2681 uid_child_faces[index++] = m_num_mng->childFaceUniqueIdOfFace(face.uniqueId(), -1, i);
2682 }
2683 }
2684
2685 m_mesh->faceFamily()->itemsUniqueIdToLocalId(lid_child_faces, uid_child_faces, false);
2686 FaceInfoListView faces(m_mesh->faceFamily());
2687
2688 index = 0;
2689 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2690 for (Integer i = 0; i < nb_child; ++i) {
2691 const Int32 child_lid = lid_child_faces[index++];
2692 if (child_lid == NULL_ITEM_ID) {
2693 continue;
2694 }
2695
2696 Face child = faces[child_lid];
2697 Face parent = *iface;
2698
2699 m_mesh->modifier()->addParentFaceToFace(child, parent);
2700 m_mesh->modifier()->addChildFaceToFace(parent, child);
2701 }
2702 }
2703 }
2704
2705 m_mesh->faceFamily()->notifyItemsOwnerChanged();
2706 }
2707
2708 // Cells
2709 UniqueArray<Int32> cells_lid(total_nb_cells);
2710 {
2711 debug() << "Nb new cells in patch : " << total_nb_cells;
2712
2713 m_mesh->modifier()->addCells(total_nb_cells, cells_infos, cells_lid);
2714
2715 // Itération sur les nouvelles mailles.
2716 CellInfoListView cells(m_mesh->cellFamily());
2717 for (Integer i = 0; i < total_nb_cells; ++i) {
2718 Cell parent = cells[cells_lid[i]];
2719
2720 parent.mutableItemBase().setOwner(around_parent_cells_uid_to_owner[parent.uniqueId()], my_rank);
2721
2725
2726 if (around_parent_cells_uid_to_owner[parent.uniqueId()] == my_rank) {
2728 }
2729 if (parent_to_child_cells[parent.uniqueId()][0].itemBase().flags() & ItemFlags::II_Shared) {
2731 }
2732 for (Cell child : parent_to_child_cells[parent.uniqueId()]) {
2733 m_mesh->modifier()->addParentCellToCell(child, parent);
2734 m_mesh->modifier()->addChildCellToCell(parent, child);
2735 }
2736 }
2737 m_mesh->cellFamily()->notifyItemsOwnerChanged();
2738 }
2739
2740 m_mesh->modifier()->endUpdate();
2741 m_num_mng->updateFirstLevel();
2742
2743 // On positionne les noeuds dans l'espace.
2744 CellInfoListView cells(m_mesh->cellFamily());
2745 for (Integer i = 0; i < total_nb_cells; ++i) {
2746 Cell parent_cell = cells[cells_lid[i]];
2747 m_num_mng->setParentNodeCoordinates(parent_cell);
2748
2749 // On ajoute le flag "II_Shared" aux noeuds et aux faces des mailles partagées.
2750 if (parent_cell.mutableItemBase().flags() & ItemFlags::II_Shared) {
2751 for (Node node : parent_cell.nodes()) {
2752 if (node.mutableItemBase().flags() & ItemFlags::II_Own) {
2753 node.mutableItemBase().addFlags(ItemFlags::II_Shared);
2754 }
2755 }
2756 for (Face face : parent_cell.faces()) {
2757 if (face.mutableItemBase().flags() & ItemFlags::II_Own) {
2758 face.mutableItemBase().addFlags(ItemFlags::II_Shared);
2759 }
2760 }
2761 }
2762 }
2763
2764 //! Créé le patch avec les mailles filles
2765 {
2766 CellGroup parent_cells = m_mesh->allLevelCells(0);
2767 m_cmesh->_internalApi()->addPatchFromExistingChildren(parent_cells.view().localIds());
2768 }
2769
2770 // Recalcule les informations de synchronisation
2771 // Cela n'est pas nécessaire pour l'AMR car ces informations seront recalculées
2772 // lors du raffinement mais comme on ne sais pas si on va faire du raffinement
2773 // après il est préférable de calculer ces informations dans tous les cas.
2774 m_mesh->computeSynchronizeInfos();
2775
2776 // Il faut recalculer les nouvelles directions après les modifications
2777 // et l'ajout de patch.
2778 m_cmesh->computeDirections();
2779
2780 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
2781 // debug() << "\t" << *icell;
2782 // for(Node node : icell->nodes()){
2783 // debug() << "\t\t" << node;
2784 // }
2785 // for(Face face : icell->faces()){
2786 // debug() << "\t\t\t" << face;
2787 // }
2788 // }
2789 // info() << "Résumé :";
2790 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
2791 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
2792 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
2793 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
2794 // }
2795 // }
2796 // info() << "Résumé node:";
2797 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
2798 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
2799 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
2800 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
2801 // }
2802 // }
2803 //
2804 // info() << "Résumé face:";
2805 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
2806 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
2807 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
2808 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
2809 // }
2810 // }
2811}
2812
2813/*---------------------------------------------------------------------------*/
2814/*---------------------------------------------------------------------------*/
2815
2816void CartesianMeshAMRPatchMng::
2817coarsen(bool update_parent_flag)
2818{
2819 // On commence par lister les mailles à ré-raffiner.
2820 UniqueArray<Cell> cells_to_coarsen_internal;
2821 ENUMERATE_ (Cell, icell, m_mesh->allActiveCells()) {
2822 Cell cell = *icell;
2823 if (cell.itemBase().flags() & ItemFlags::II_Coarsen) {
2824 if (cell.level() == 0) {
2825 ARCANE_FATAL("Cannot coarse level-0 cell");
2826 }
2827
2828 Cell parent = cell.hParent();
2829
2830 if (update_parent_flag) {
2834 }
2835
2836 // Pour une maille de niveau n-1, si une de ses mailles filles doit être dé-raffinée,
2837 // alors toutes ses mailles filles doivent être dé-raffinées.
2838 for (Integer i = 0; i < parent.nbHChildren(); ++i) {
2839 Cell child = parent.hChild(i);
2840 if (!(child.mutableItemBase().flags() & ItemFlags::II_Coarsen)) {
2841 ARCANE_FATAL("Parent cannot have children with coarse flag and children without coarse flag -- Parent uid: {0} -- Child uid: {1}", parent.uniqueId(), child.uniqueId());
2842 }
2843 }
2844 if (parent.mutableItemBase().flags() & ItemFlags::II_Coarsen) {
2845 ARCANE_FATAL("Cannot coarse parent and child in same time");
2846 }
2847 if (cell.nbHChildren() != 0) {
2848 ARCANE_FATAL("For now, cannot coarse cell with children");
2849 }
2850 cells_to_coarsen_internal.add(cell);
2851 }
2852 }
2853
2854 // Maps remplaçant les mailles fantômes.
2855 std::unordered_map<Int64, Integer> around_cells_uid_to_owner;
2856 std::unordered_map<Int64, Int32> around_cells_uid_to_flags;
2857
2858 {
2859 // On a uniquement besoin de ses deux flags pour les mailles autour.
2860 // (II_Coarsen pour savoir si les mailles autour sont aussi à dé-raffinées)
2861 // (II_Inactive pour savoir si les mailles autour sont déjà raffinées(pour vérifier qu'il n'y a pas plus d'un niveau d'écart))
2863 _shareInfosOfCellsAroundPatch(cells_to_coarsen_internal, around_cells_uid_to_owner, around_cells_uid_to_flags, useful_flags);
2864 }
2865
2866 // Avant de supprimer les mailles, on doit changer les propriétaires des faces/noeuds entre les mailles
2867 // à supprimer et les mailles restantes.
2868 if (m_mesh->dimension() == 2) {
2869 FixedArray<Int64, 9> uid_cells_around_cell_1d;
2870 FixedArray<Int32, 9> owner_cells_around_cell_1d;
2871 FixedArray<Int32, 9> flags_cells_around_cell_1d;
2872
2873 for (Cell cell_to_coarsen : cells_to_coarsen_internal) {
2874 const Int64 cell_to_coarsen_uid = cell_to_coarsen.uniqueId();
2875 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_cell_1d.view(), cell_to_coarsen);
2876
2877 {
2878 Integer nb_cells_to_coarsen_or_empty_around = 0;
2879
2880 for (Integer i = 0; i < 9; ++i) {
2881 Int64 uid_cell = uid_cells_around_cell_1d[i];
2882 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2883 // Si around_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2884 if (uid_cell != -1 && around_cells_uid_to_owner[uid_cell] != -1) {
2885 owner_cells_around_cell_1d[i] = around_cells_uid_to_owner[uid_cell];
2886 flags_cells_around_cell_1d[i] = around_cells_uid_to_flags[uid_cell];
2887
2888 if (flags_cells_around_cell_1d[i] & ItemFlags::II_Coarsen) {
2889 nb_cells_to_coarsen_or_empty_around++;
2890 }
2891 }
2892 else {
2893 uid_cells_around_cell_1d[i] = -1;
2894 owner_cells_around_cell_1d[i] = -1;
2895 flags_cells_around_cell_1d[i] = 0;
2896
2897 nb_cells_to_coarsen_or_empty_around++;
2898 }
2899 }
2900
2901 // Si toutes les mailles autours de nous sont soit inexistantes, soit
2902 // à supprimer, inutile de chercher de nouveaux propriétaires pour nos items.
2903 // Notre maille est à dé-raffiner, donc nb_cells_to_coarsen_or_empty_around >= 1.
2904 if (nb_cells_to_coarsen_or_empty_around == 9) {
2905 continue;
2906 }
2907 }
2908
2909 // Le propriétaire de notre maille.
2910 Int32 cell_to_coarsen_owner = owner_cells_around_cell_1d[4];
2911
2912 {
2913 // On donne la position de la face dans le tableau des mailles autours
2914 // selon l'index de la face attribué par Arcane.
2915 // (Voir commentaire tagué "arcane_order_to_around_2d").
2916 // cell_to_coarsen.face(0) = uid_cells_around_cell_1d[1]
2917 // cell_to_coarsen.face(1) = uid_cells_around_cell_1d[5]
2918 // ...
2919 constexpr Integer arcane_order_to_pos_around[] = { 1, 5, 7, 3 };
2920
2921 Integer count = -1;
2922
2923 for (Face face : cell_to_coarsen.faces()) {
2924 count++;
2925 Int64 other_cell_uid = uid_cells_around_cell_1d[arcane_order_to_pos_around[count]];
2926 if (other_cell_uid == -1) {
2927 // On est au bord du maillage ou il n'y a pas de maille du même niveau à côté,
2928 // pas besoin de changer le owner de la face (elle sera supprimée).
2929 continue;
2930 }
2931 Int32 other_cell_flag = flags_cells_around_cell_1d[arcane_order_to_pos_around[count]];
2932
2933 if (other_cell_flag & ItemFlags::II_Coarsen) {
2934 // La maille d'à côté sera aussi supprimée, pas besoin de changer le owner de la face.
2935 continue;
2936 }
2937 if (other_cell_flag & ItemFlags::II_Inactive) {
2938 // La maille d'à côté a des enfants. Il y aura donc au moins deux niveaux de
2939 // raffinements de différences.
2940 ARCANE_FATAL("Max one level diff between two cells is allowed -- Uid of Cell to be coarseing: {0} -- Uid of Opposite cell with children: {1}", cell_to_coarsen_uid, other_cell_uid);
2941 }
2942 Int32 other_cell_owner = owner_cells_around_cell_1d[arcane_order_to_pos_around[count]];
2943 if (other_cell_owner != cell_to_coarsen_owner) {
2944 // La maille d'à côté existe et appartient à quelqu'un d'autre. On lui donne la face.
2945 face.mutableItemBase().setOwner(other_cell_owner, cell_to_coarsen_owner);
2946 }
2947 }
2948 }
2949
2950 {
2951 Integer count = -1;
2952
2953 // Ici, plus compliqué.
2954 // Chaque élement du tableau de niveau 0 désigne un noeud.
2955 // Comme pour les faces, l'ordre est décrit au commentaire tagué "arcane_order_to_around_2d".
2956 //
2957 // Ensuite, par rapport aux faces, on a l'aspect priorité (comme notre maille
2958 // sera supprimé, pour chaque face, soit elle prendra la propriété de la maille d'à côté
2959 // si elle est "survivante", soit elle sera supprimée).
2960 // Un noeud est présent dans quatre mailles. Trois mailles seront potentiellement "survivantes".
2961 // On doit déterminer à qui appartiendra ce noeud parmi ces trois mailles.
2962 // Pour le savoir, on utilise les priorités décrites dans le commentaire
2963 // tagué "priority_owner_2d".
2964 //
2965 // Exemple : Le noeud n°0 est présent sur quatre mailles autour avec les priorités : P0, P1, P3, P4.
2966 // La maille P4 (la "notre") sera supprimé.
2967 // Dans le tableau n°0, on met les trois priorités (de la plus faible à la plus forte).
2968 // Ensuite, on itére sur ces trois mailles (toujours de la plus faible à la plus forte).
2969 // Si la maille i est "survivante", elle prend la propriété.
2970 // Au final, la maille ayant la priorité la plus forte aura le noeud.
2971 // Si aucune maille n'a pris la propriété, alors le noeud sera supprimée.
2972 //
2973 constexpr Integer priority_and_pos_of_cells_around_node[4][3] = { { 3, 1, 0 }, { 5, 2, 1 }, { 8, 7, 5 }, { 7, 6, 3 } };
2974
2975 for (Node node : cell_to_coarsen.nodes()) {
2976 count++;
2977 Integer final_owner = -1;
2978 for (Integer other_cell = 0; other_cell < 3; ++other_cell) {
2979 Int64 other_cell_uid = uid_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
2980 if (other_cell_uid == -1) {
2981 // On est au bord du maillage ou il n'y a pas de maille du même niveau à côté,
2982 // le noeud ne prendra pas son propriétaire.
2983 continue;
2984 }
2985 Int32 other_cell_flag = flags_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
2986
2987 if (other_cell_flag & ItemFlags::II_Coarsen) {
2988 // La maille d'à côté sera aussi supprimée, elle ne pourra pas prendre
2989 // la propriété de notre noeud.
2990 continue;
2991 }
2992 if (other_cell_flag & ItemFlags::II_Inactive) {
2993 // La maille d'à côté a des enfants. Il y aura donc au moins deux niveaux de
2994 // raffinements de différences.
2995 ARCANE_FATAL("Max one level diff between two cells is allowed -- Uid of Cell to be coarseing: {0} -- Uid of Opposite cell with children: {1}", cell_to_coarsen_uid, other_cell_uid);
2996 }
2997 Int32 other_cell_owner = owner_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
2998 if (other_cell_owner != cell_to_coarsen_owner) {
2999 // La maille d'à côté existe et appartient à quelqu'un d'autre. On lui donne le noeud.
3000 final_owner = other_cell_owner;
3001 }
3002 }
3003 if (final_owner != -1) {
3004 node.mutableItemBase().setOwner(final_owner, cell_to_coarsen_owner);
3005 }
3006 }
3007 }
3008 }
3009 }
3010 else if (m_mesh->dimension() == 3) {
3011 FixedArray<Int64, 27> uid_cells_around_cell_1d;
3012 FixedArray<Int32, 27> owner_cells_around_cell_1d;
3013 FixedArray<Int32, 27> flags_cells_around_cell_1d;
3014
3015 for (Cell cell_to_coarsen : cells_to_coarsen_internal) {
3016 const Int64 cell_to_coarsen_uid = cell_to_coarsen.uniqueId();
3017 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_cell_1d.view(), cell_to_coarsen);
3018
3019 {
3020 Integer nb_cells_to_coarsen_or_empty_around = 0;
3021
3022 for (Integer i = 0; i < 27; ++i) {
3023 Int64 uid_cell = uid_cells_around_cell_1d[i];
3024 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
3025 // Si around_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
3026 if (uid_cell != -1 && around_cells_uid_to_owner[uid_cell] != -1) {
3027 owner_cells_around_cell_1d[i] = around_cells_uid_to_owner[uid_cell];
3028 flags_cells_around_cell_1d[i] = around_cells_uid_to_flags[uid_cell];
3029
3030 if (flags_cells_around_cell_1d[i] & ItemFlags::II_Coarsen) {
3031 nb_cells_to_coarsen_or_empty_around++;
3032 }
3033 }
3034 else {
3035 uid_cells_around_cell_1d[i] = -1;
3036 owner_cells_around_cell_1d[i] = -1;
3037 flags_cells_around_cell_1d[i] = 0;
3038
3039 nb_cells_to_coarsen_or_empty_around++;
3040 }
3041 }
3042
3043 // Si toutes les mailles autours de nous sont soit inexistantes, soit
3044 // à supprimer, inutile de chercher de nouveaux propriétaires pour nos items.
3045 // Notre maille est à dé-raffiner, donc nb_cells_to_coarsen_or_empty_around >= 1.
3046 if (nb_cells_to_coarsen_or_empty_around == 27) {
3047 continue;
3048 }
3049 }
3050
3051 // Le propriétaire de notre maille.
3052 Int32 cell_to_coarsen_owner = owner_cells_around_cell_1d[13];
3053
3054 {
3055 // On donne la position de la face dans le tableau des mailles autours
3056 // selon l'index de la face attribué par Arcane.
3057 // (Voir commentaire tagué "arcane_order_to_around_3d").
3058 // cell_to_coarsen.face(0) = uid_cells_around_cell_1d[4]
3059 // cell_to_coarsen.face(1) = uid_cells_around_cell_1d[12]
3060 // ...
3061 constexpr Integer arcane_order_to_pos_around[] = { 4, 12, 10, 22, 14, 16 };
3062
3063 Integer count = -1;
3064
3065 for (Face face : cell_to_coarsen.faces()) {
3066 count++;
3067 Int64 other_cell_uid = uid_cells_around_cell_1d[arcane_order_to_pos_around[count]];
3068 if (other_cell_uid == -1) {
3069 // On est au bord du maillage ou il n'y a pas de maille du même niveau à côté,
3070 // pas besoin de changer le owner de la face (elle sera supprimée).
3071 continue;
3072 }
3073 Int32 other_cell_flag = flags_cells_around_cell_1d[arcane_order_to_pos_around[count]];
3074
3075 if (other_cell_flag & ItemFlags::II_Coarsen) {
3076 // La maille d'à côté sera aussi supprimée, pas besoin de changer le owner de la face.
3077 continue;
3078 }
3079 if (other_cell_flag & ItemFlags::II_Inactive) {
3080 // La maille d'à côté a des enfants. Il y aura donc au moins deux niveaux de
3081 // raffinements de différences.
3082 ARCANE_FATAL("Max one level diff between two cells is allowed -- Uid of Cell to be coarseing: {0} -- Uid of Opposite cell with children: {1}", cell_to_coarsen_uid, other_cell_uid);
3083 }
3084 Int32 other_cell_owner = owner_cells_around_cell_1d[arcane_order_to_pos_around[count]];
3085 if (other_cell_owner != cell_to_coarsen_owner) {
3086 // La maille d'à côté existe et appartient à quelqu'un d'autre. On lui donne la face.
3087 face.mutableItemBase().setOwner(other_cell_owner, cell_to_coarsen_owner);
3088 }
3089 }
3090 }
3091
3092 {
3093 Integer count = -1;
3094
3095 // Chaque élement du tableau de niveau 0 désigne un noeud.
3096 // Comme pour les faces, l'ordre est décrit au commentaire tagué "arcane_order_to_around_3d".
3097 //
3098 // Ensuite, on a l'aspect priorité.
3099 // Un noeud est présent dans huit mailles. Sept mailles seront potentiellement "survivantes".
3100 // On doit déterminer à qui appartiendra ce noeud parmi ces sept mailles.
3101 // Pour le savoir, on utilise les priorités décrites dans le commentaire
3102 // tagué "priority_owner_3d".
3103 //
3104 // Exemple : Le noeud n°0 est présent sur huit mailles autour avec les priorités : P12, P10, P9, ...
3105 // La maille P13 (la "notre") sera supprimé.
3106 // Dans le tableau n°0, on met les sept priorités (de la plus faible à la plus forte).
3107 // Ensuite, on itére sur ces sept mailles (toujours de la plus faible à la plus forte).
3108 // Si la maille i est "survivante", elle prend la propriété.
3109 // Au final, la maille ayant la priorité la plus forte aura le noeud.
3110 // Si aucune maille n'a pris la propriété, alors le noeud sera supprimée.
3111 //
3112 constexpr Integer priority_and_pos_of_cells_around_node[8][7] = {
3113 {12, 10, 9, 4, 3, 1, 0},
3114 {14, 11, 10, 5, 4, 2, 1},
3115 {17, 16, 14, 8, 7, 5, 4},
3116 {16, 15, 12, 7, 6, 4, 3},
3117 {22, 21, 19, 18, 12, 10, 9},
3118 {23, 22, 20, 19, 14, 11, 10},
3119 {26, 25, 23, 22, 17, 16, 14},
3120 {25, 24, 22, 21, 16, 15, 12}
3121 };
3122
3123 for (Node node : cell_to_coarsen.nodes()) {
3124 count++;
3125 Integer final_owner = -1;
3126 for (Integer other_cell = 0; other_cell < 7; ++other_cell) {
3127 Int64 other_cell_uid = uid_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
3128 if (other_cell_uid == -1) {
3129 // On est au bord du maillage ou il n'y a pas de maille du même niveau à côté,
3130 // le noeud ne prendra pas son propriétaire.
3131 continue;
3132 }
3133 Int32 other_cell_flag = flags_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
3134
3135 if (other_cell_flag & ItemFlags::II_Coarsen) {
3136 // La maille d'à côté sera aussi supprimée, elle ne pourra pas prendre
3137 // la propriété de notre noeud.
3138 continue;
3139 }
3140 if (other_cell_flag & ItemFlags::II_Inactive) {
3141 // La maille d'à côté a des enfants. Il y aura donc au moins deux niveaux de
3142 // raffinements de différences.
3143 ARCANE_FATAL("Max one level diff between two cells is allowed -- Uid of Cell to be coarseing: {0} -- Uid of Opposite cell with children: {1}", cell_to_coarsen_uid, other_cell_uid);
3144 }
3145 Int32 other_cell_owner = owner_cells_around_cell_1d[priority_and_pos_of_cells_around_node[count][other_cell]];
3146 if (other_cell_owner != cell_to_coarsen_owner) {
3147 // La maille d'à côté existe et appartient à quelqu'un d'autre. On lui donne le noeud.
3148 node.mutableItemBase().setOwner(other_cell_owner, cell_to_coarsen_owner);
3149 }
3150 }
3151 if (final_owner != -1) {
3152 node.mutableItemBase().setOwner(final_owner, cell_to_coarsen_owner);
3153 }
3154 }
3155 }
3156 }
3157 }
3158
3159 else {
3160 ARCANE_FATAL("Bad dimension");
3161 }
3162
3163 UniqueArray<Int32> local_ids;
3164 for (Cell cell : cells_to_coarsen_internal) {
3165 local_ids.add(cell.localId());
3166 }
3167 m_mesh->modifier()->removeCells(local_ids);
3168 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
3169 m_mesh->faceFamily()->notifyItemsOwnerChanged();
3170 m_mesh->modifier()->endUpdate();
3171 m_mesh->cellFamily()->computeSynchronizeInfos();
3172 m_mesh->nodeFamily()->computeSynchronizeInfos();
3173 m_mesh->faceFamily()->computeSynchronizeInfos();
3174 m_mesh->modifier()->setDynamic(true);
3175
3176 UniqueArray<Int64> ghost_cell_to_refine;
3177 UniqueArray<Int64> ghost_cell_to_coarsen;
3178
3179 if (!update_parent_flag) {
3180 // Si les matériaux sont actifs, il faut forcer un recalcul des matériaux car les groupes
3181 // de mailles ont été modifiés et donc la liste des constituants aussi
3183 if (mm)
3184 mm->forceRecompute();
3185 }
3186
3187 m_mesh->modifier()->updateGhostLayerFromParent(ghost_cell_to_refine, ghost_cell_to_coarsen, true);
3188}
3189
3190/*---------------------------------------------------------------------------*/
3191/*---------------------------------------------------------------------------*/
3192
3193/*!
3194 * \brief Méthode permettant d'obtenir les propriétaires et les flags des
3195 * mailles autour des mailles de patch_cells.
3196 *
3197 * \param patch_cells Les mailles autour desquelles on a besoin des infos des mailles autour.
3198 * \param around_cells_uid_to_owner Les propriétaires des mailles de patch_cells et des mailles autours des mailles de patch_cells.
3199 * \param around_cells_uid_to_flags Les flags des mailles de patch_cells et des mailles autours des mailles de patch_cells.
3200 * \param useful_flags Les flags qu'il est nécessaire de récupérer.
3201 */
3202void CartesianMeshAMRPatchMng::
3203_shareInfosOfCellsAroundPatch(ConstArrayView<Cell> patch_cells, std::unordered_map<Int64, Integer>& around_cells_uid_to_owner, std::unordered_map<Int64, Int32>& around_cells_uid_to_flags, Int32 useful_flags) const
3204{
3205 IParallelMng* pm = m_mesh->parallelMng();
3206 Int32 my_rank = pm->commRank();
3207 Int32 nb_rank = pm->commSize();
3208
3209 // Partie échange d'informations sur les mailles autour du patch
3210 // (pour remplacer les mailles fantômes).
3211
3212 // On remplit le tableau avec nos infos, pour les autres processus.
3213 ENUMERATE_ (Cell, icell, m_mesh->ownCells()) {
3214 Cell cell = *icell;
3215 around_cells_uid_to_owner[cell.uniqueId()] = my_rank;
3216 around_cells_uid_to_flags[cell.uniqueId()] = ((cell.itemBase().flags() & useful_flags) + ItemFlags::II_UserMark1);
3217 }
3218
3219 ENUMERATE_ (Cell, icell, m_mesh->allCells().ghost()) {
3220 Cell cell = *icell;
3221 around_cells_uid_to_owner[cell.uniqueId()] = cell.owner();
3222 around_cells_uid_to_flags[cell.uniqueId()] = ((cell.itemBase().flags() & useful_flags) + ItemFlags::II_UserMark1);
3223 }
3224
3225 // Tableau qui contiendra les uids des mailles dont on a besoin des infos.
3226 UniqueArray<Int64> uid_of_cells_needed;
3227 {
3228 UniqueArray<Int64> cell_uids_around((m_mesh->dimension() == 2) ? 9 : 27);
3229 for (Cell cell : patch_cells) {
3230 m_num_mng->cellUniqueIdsAroundCell(cell_uids_around, cell);
3231 for (Int64 cell_uid : cell_uids_around) {
3232 // Si -1 alors il n'y a pas de mailles à cette position.
3233 if (cell_uid == -1)
3234 continue;
3235
3236 // TODO C++20 : Mettre map.contains().
3237 // SI on a la maille, on n'a pas besoin de demander d'infos.
3238 if (around_cells_uid_to_owner.find(cell_uid) != around_cells_uid_to_owner.end())
3239 continue;
3240
3241 uid_of_cells_needed.add(cell_uid);
3242 }
3243 }
3244 }
3245
3246 UniqueArray<Int64> uid_of_cells_needed_all_procs;
3247 pm->allGatherVariable(uid_of_cells_needed, uid_of_cells_needed_all_procs);
3248
3249 UniqueArray<Int32> flags_of_cells_needed_all_procs(uid_of_cells_needed_all_procs.size());
3250 UniqueArray<Int32> owner_of_cells_needed_all_procs(uid_of_cells_needed_all_procs.size());
3251
3252 {
3253 UniqueArray<Int32> local_ids(uid_of_cells_needed_all_procs.size());
3254 m_mesh->cellFamily()->itemsUniqueIdToLocalId(local_ids, uid_of_cells_needed_all_procs, false);
3255 Integer compt = 0;
3256 ENUMERATE_ (Cell, icell, m_mesh->cellFamily()->view(local_ids)) {
3257 // Le isOwn est important vu qu'il peut y avoir les mailles fantômes.
3258 if (!icell->null() && icell->isOwn()) {
3259 owner_of_cells_needed_all_procs[compt] = my_rank;
3260 flags_of_cells_needed_all_procs[compt] = (icell->itemBase().flags() & useful_flags);
3261 }
3262 else {
3263 owner_of_cells_needed_all_procs[compt] = -1;
3264 flags_of_cells_needed_all_procs[compt] = 0;
3265 }
3266 compt++;
3267 }
3268 }
3269
3270 pm->reduce(Parallel::eReduceType::ReduceMax, owner_of_cells_needed_all_procs);
3271 pm->reduce(Parallel::eReduceType::ReduceMax, flags_of_cells_needed_all_procs);
3272
3273 // A partir de ce moment, si les parent_cells sont au niveau 0, le tableau
3274 // "owner_of_cells_needed_all_procs" ne devrait plus contenir de "-1".
3275 // Si les parent_cells sont au niveau 1 ou plus, il peut y avoir des "-1"
3276 // car les mailles autour ne sont pas forcément toutes raffinées.
3277 // (exemple : on est en train de faire le niveau 2, donc on regarde les mailles
3278 // parent de niveau 1 tout autour. Il se peut que la maille d'à coté n'ai jamais
3279 // été raffinée, donc n'a pas de mailles de niveau 1. Comme la maille n'existe pas,
3280 // aucun processus ne peut mettre un propriétaire, donc le tableau des propriétaires
3281 // contiendra "-1".
3282
3283 // On récupère les infos des mailles autour qui nous intéressent.
3284 {
3285 Integer size_uid_of_cells_needed = uid_of_cells_needed.size();
3286 Integer my_pos_in_all_procs_arrays = 0;
3287 UniqueArray<Integer> size_uid_of_cells_needed_per_proc(nb_rank);
3288 ArrayView<Integer> av(1, &size_uid_of_cells_needed);
3289 pm->allGather(av, size_uid_of_cells_needed_per_proc);
3290
3291 for (Integer i = 0; i < my_rank; ++i) {
3292 my_pos_in_all_procs_arrays += size_uid_of_cells_needed_per_proc[i];
3293 }
3294
3295 ArrayView<Int32> owner_of_cells_needed = owner_of_cells_needed_all_procs.subView(my_pos_in_all_procs_arrays, size_uid_of_cells_needed);
3296 ArrayView<Int32> flags_of_cells_needed = flags_of_cells_needed_all_procs.subView(my_pos_in_all_procs_arrays, size_uid_of_cells_needed);
3297 for (Integer i = 0; i < size_uid_of_cells_needed; ++i) {
3298 around_cells_uid_to_owner[uid_of_cells_needed[i]] = owner_of_cells_needed[i];
3299 around_cells_uid_to_flags[uid_of_cells_needed[i]] = flags_of_cells_needed[i];
3300 }
3301 }
3302}
3303
3304/*---------------------------------------------------------------------------*/
3305/*---------------------------------------------------------------------------*/
3306
3307} // End namespace Arcane
3308
3309/*---------------------------------------------------------------------------*/
3310/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Integer size() const
Nombre d'éléments du vecteur.
bool contains(ConstReferenceType v) const
Vrai si le tableau contient l'élément de valeur v.
Vue modifiable d'un tableau d'un type T.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sous-vue à partir de l'élément abegin et contenant asize éléments.
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1191
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1272
Int32 nbHChildren() const
Nombre d'enfants pour l'AMR.
Definition Item.h:1307
Cell hChild(Int32 i) const
i-ème enfant AMR
Definition Item.h:1310
Int32 level() const
Definition Item.h:1342
Cell hParent() const
Definition Item.h:1301
Vue constante d'un tableau de type T.
static constexpr ThatClass create(const_pointer ptr, Integer asize) noexcept
Construit une vue sur une zone mémoire commencant par ptr et.
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:944
Tableau 1D de taille fixe.
Definition FixedArray.h:45
constexpr __host__ __device__ ArrayView< T > view()
Vue modifiable sur le tableau.
Definition FixedArray.h:97
Interface d'un maillage cartésien.
virtual void setBuilderVersion(Integer n)=0
Positionne la version du constructeur de mailles fantômes. Pour l'instant (version 3....
virtual Integer nbGhostLayer() const =0
Nombre de couches fantômes.
virtual Integer builderVersion() const =0
Version du constructeur de mailles fantômes.
virtual void setNbGhostLayer(Integer n)=0
Positionne le nombre de couches fantômes.
Interface de modification du maillage.
virtual void updateGhostLayers()=0
Mise à jour de la couche fantôme.
virtual void setDynamic(bool v)=0
Positionne la propriété indiquant si le maillage peut évoluer.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Int32 flags() const
Flags de l'entité
@ II_Inactive
L'entité est inactive //COARSEN_INACTIVE,.
Definition ItemFlags.h:66
@ II_Refine
L'entité est marquée pour raffinement.
Definition ItemFlags.h:63
@ II_JustAdded
L'entité vient d'être ajoutée.
Definition ItemFlags.h:54
@ II_Shared
L'entité est partagée par un autre sous-domaine.
Definition ItemFlags.h:51
@ II_JustRefined
L'entité vient d'être raffinée.
Definition ItemFlags.h:64
@ II_Own
L'entité est une entité propre au sous-domaine.
Definition ItemFlags.h:48
@ II_CoarsenInactive
L'entité est inactive et a des enfants tagués pour déraffinement.
Definition ItemFlags.h:67
@ II_Coarsen
L'entité est marquée pour déraffinement.
Definition ItemFlags.h:61
@ II_JustCoarsened
L'entité vient d'être déraffiné
Definition ItemFlags.h:65
@ II_UserMark1
Marque utilisateur old_value 1<<24.
Definition ItemFlags.h:69
ItemVectorView view() const
Vue sur les entités du groupe.
Definition ItemGroup.cc:582
Vue sur une liste pour obtenir des informations sur les entités.
Int32ConstArrayView localIds() const
Tableau des numéros locaux des entités.
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
Classe de base d'un élément de maillage.
Definition Item.h:83
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:374
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:363
Interface du gestionnaire des matériaux et des milieux d'un maillage.
virtual void forceRecompute()=0
Force le recalcul des informations des matériaux.
static IMeshMaterialMng * getReference(const MeshHandleOrMesh &mesh_handle, bool create=true)
Récupère ou créé la référence associée à mesh.
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
void addFlags(Int32 added_flags)
Ajoute les flags \added_flags à ceux de l'entité
void removeFlags(Int32 removed_flags)
Supprime les flags \added_flags de ceux de l'entité
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:573
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
MeshVariableScalarRefT< Cell, Integer > VariableCellInteger
Grandeur au centre des mailles de type entier.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:569
std::int32_t Int32
Type entier signé sur 32 bits.