Arcane  v3.15.3.0
Documentation développeur
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 "CartesianMeshAMRPatchMng.h"
15
16#include "arcane/core/IGhostLayerMng.h"
17#include "arcane/core/IMesh.h"
18#include "arcane/core/ItemPrinter.h"
19#include "arcane/core/IParallelMng.h"
20#include "arcane/core/VariableTypes.h"
21#include "arcane/core/IMeshModifier.h"
22
23#include "arcane/cartesianmesh/CellDirectionMng.h"
24#include "arcane/cartesianmesh/CartesianMeshNumberingMng.h"
25#include "arcane/cartesianmesh/internal/ICartesianMeshInternal.h"
26
27#include "arcane/utils/Array2View.h"
28#include "arcane/utils/Array3View.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39CartesianMeshAMRPatchMng::
40CartesianMeshAMRPatchMng(ICartesianMesh* cmesh)
41: TraceAccessor(cmesh->mesh()->traceMng())
42, m_mesh(cmesh->mesh())
43, m_cmesh(cmesh)
44, m_num_mng(Arccore::makeRef(new CartesianMeshNumberingMng(cmesh->mesh())))
45{
46}
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51void CartesianMeshAMRPatchMng::
52flagCellToRefine(Int32ConstArrayView cells_lids)
53{
54 ItemInfoListView cells(m_mesh->cellFamily());
55 for (int lid : cells_lids) {
56 Item item = cells[lid];
57 item.mutableItemBase().addFlags(ItemFlags::II_Refine);
58 }
59 _syncFlagCell();
60}
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
64
65void CartesianMeshAMRPatchMng::
66_syncFlagCell()
67{
68 if (!m_mesh->parallelMng()->isParallel())
69 return;
70
71 VariableCellInteger flag_cells_consistent(VariableBuildInfo(m_mesh, "FlagCellsConsistent"));
72 ENUMERATE_ (Cell, icell, m_mesh->ownCells()) {
73 Cell cell = *icell;
75 // debug() << "Send " << cell
76 // << " -- flag : " << cell.mutableItemBase().flags()
77 // << " -- II_Refine : " << (cell.itemBase().flags() & ItemFlags::II_Refine)
78 // << " -- II_Inactive : " << (cell.itemBase().flags() & ItemFlags::II_Inactive)
79 // ;
80 }
81
82 flag_cells_consistent.synchronize();
83
84 ENUMERATE_ (Cell, icell, m_mesh->allCells().ghost()) {
85 Cell cell = *icell;
86
87 // On ajoute uniquement les flags qui nous interesse (pour éviter d'ajouter le flag "II_Own" par exemple).
88 // On utilise set au lieu de add puisqu'une maille ne peut être à la fois II_Refine et II_Inactive.
89 if (flag_cells_consistent[cell] & ItemFlags::II_Refine) {
90 cell.mutableItemBase().setFlags(ItemFlags::II_Refine);
91 }
92 if (flag_cells_consistent[cell] & ItemFlags::II_Inactive) {
93 cell.mutableItemBase().setFlags(ItemFlags::II_Inactive);
94 }
95
96 // debug() << "After Compute " << cell
97 // << " -- flag : " << cell.mutableItemBase().flags()
98 // << " -- II_Refine : " << (cell.itemBase().flags() & ItemFlags::II_Refine)
99 // << " -- II_Inactive : " << (cell.itemBase().flags() & ItemFlags::II_Inactive)
100 // ;
101 }
102}
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107/*
108 * Pour les commentaires de cette méthode, on considère le repère suivant :
109 * (top)
110 * y (front)
111 * ^ z
112* | /
113 * | /
114 * (left) ------->x (right)
115 * (rear)(bottom)
116 */
117void CartesianMeshAMRPatchMng::
118refine()
119{
120 IParallelMng* pm = m_mesh->parallelMng();
121 Int32 nb_rank = pm->commSize();
122 Int32 my_rank = pm->commRank();
123 Int32 max_level = 0;
124
126 ENUMERATE_ (Cell, icell, m_mesh->allActiveCells()) {
127 Cell cell = *icell;
128 if (cell.itemBase().flags() & ItemFlags::II_Refine) {
129 cell_to_refine_internals.add(cell);
130 if (cell.level() > max_level)
131 max_level = cell.level();
132 }
133 }
134 m_num_mng->prepareLevel(max_level + 1);
135
136 UniqueArray<Int64> cells_infos;
137 UniqueArray<Int64> faces_infos;
139
140 Integer total_nb_cells = 0;
141 Integer total_nb_nodes = 0;
142 Integer total_nb_faces = 0;
143
144 std::unordered_map<Int64, Int32> node_uid_to_owner;
145 std::unordered_map<Int64, Int32> face_uid_to_owner;
146
149
150 // Deux tableaux permettant de récupérer les uniqueIds des noeuds et des faces
151 // de chaque maille enfant à chaque appel à getNodeUids()/getFaceUids().
152 UniqueArray<Int64> child_nodes_uids(m_num_mng->nbNodeByCell());
153 UniqueArray<Int64> child_faces_uids(m_num_mng->nbFaceByCell());
154
155 // On doit enregistrer les mailles parentes de chaque maille enfant pour mettre à jour les connectivités
156 // lors de la création des mailles.
158
159 // Maps remplaçant les mailles fantômes.
160 std::unordered_map<Int64, Integer> around_parent_cells_uid_to_owner;
161 std::unordered_map<Int64, Int32> around_parent_cells_uid_to_flags;
162
163 // Partie échange d'informations sur les mailles autour du patch
164 // (pour remplacer les mailles fantômes).
165 {
166 // On a uniquement besoin de ses deux flags pour les mailles autour.
167 // (II_Refine pour savoir si les mailles autour sont dans le même patch)
168 // (II_Inactive pour savoir si les mailles autour sont déjà raffinées)
169 Int32 usefull_flags = ItemFlags::II_Refine + ItemFlags::II_Inactive;
170
171 // On remplit le tableau avec nos infos, pour les autres processus.
172 ENUMERATE_ (Cell, icell, m_mesh->ownCells()) {
173 Cell cell = *icell;
175 around_parent_cells_uid_to_flags[cell.uniqueId()] = ((cell.itemBase().flags() & usefull_flags) + ItemFlags::II_UserMark1);
176 }
177
178 ENUMERATE_ (Cell, icell, m_mesh->allCells().ghost()) {
179 Cell cell = *icell;
181 around_parent_cells_uid_to_flags[cell.uniqueId()] = ((cell.itemBase().flags() & usefull_flags) + ItemFlags::II_UserMark1);
182 }
183
184 // Tableau qui contiendra les uids des mailles dont on a besoin des infos.
186 {
187 UniqueArray<Int64> cell_uids_around((m_mesh->dimension() == 2) ? 9 : 27);
189 m_num_mng->cellUniqueIdsAroundCell(cell_uids_around, parent_cell);
190 for (Int64 cell_uid : cell_uids_around) {
191 // Si -1 alors il n'y a pas de mailles à cette position.
192 if (cell_uid == -1)
193 continue;
194
195 // TODO C++20 : Mettre map.contains().
196 // SI on a la maille, on n'a pas besoin de demander d'infos.
198 continue;
199
200 uid_of_cells_needed.add(cell_uid);
201 }
202 }
203 }
204
207
210
211 {
213 m_mesh->cellFamily()->itemsUniqueIdToLocalId(local_ids, uid_of_cells_needed_all_procs, false);
214 Integer compt = 0;
215 ENUMERATE_ (Cell, icell, m_mesh->cellFamily()->view(local_ids)) {
216 // Le isOwn est important vu qu'il peut y avoir les mailles fantômes.
217 if (!icell->null() && icell->isOwn()) {
219 flags_of_cells_needed_all_procs[compt] = (icell->itemBase().flags() & usefull_flags);
220 }
221 else {
224 }
225 compt++;
226 }
227 }
228
229 pm->reduce(Parallel::eReduceType::ReduceMax, owner_of_cells_needed_all_procs);
230 pm->reduce(Parallel::eReduceType::ReduceMax, flags_of_cells_needed_all_procs);
231
232 // A partir de ce moment, si les parent_cells sont au niveau 0, le tableau
233 // "owner_of_cells_needed_all_procs" ne devrait plus contenir de "-1".
234 // Si les parent_cells sont au niveau 1 ou plus, il peut y avoir des "-1"
235 // car les mailles autour ne sont pas forcément toutes raffinées.
236 // (exemple : on est en train de faire le niveau 2, donc on regarde les mailles
237 // parent de niveau 1 tout autour. Il se peut que la maille d'à coté n'ai jamais
238 // été raffinée, donc n'a pas de mailles de niveau 1. Comme la maille n'existe pas,
239 // aucun processus ne peut mettre un propriétaire, donc le tableau des propriétaires
240 // contiendra "-1".
241
242 // On récupère les infos des mailles autour qui nous intéressent.
243 {
245 Integer my_pos_in_all_procs_arrays = 0;
249
250 for (Integer i = 0; i < my_rank; ++i) {
252 }
253
256 for (Integer i = 0; i < size_uid_of_cells_needed; ++i) {
259 }
260 }
261 }
262
263 if (m_mesh->dimension() == 2) {
264
265 // Masques pour les cas "voisins enfants" et "voisins parents du même patch".
266 // Ces masques permettent de savoir si l'on doit créer un noeud ou pas selon
267 // les mailles autour.
268 // Par exemple, si l'on est en train d'étudier une maille enfant et qu'il y a
269 // une maille enfant à gauche, on ne doit pas créer les noeuds 0 et 3 (mask_node_if_cell_left[]) (car
270 // ils ont déjà été créés par la maille à gauche).
271 // Idem pour les mailles parentes voisines : si l'on est sur une maille enfant située
272 // sur la partie gauche de la maille parente (mailles enfants 0 et 2 dans le cas d'un
273 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille parente
274 // est en train ((d'être raffiné et à notre sous-domaine) ou (qu'elle est inactive)), on applique
275 // la règle mask_node_if_cell_left[] car les noeuds ont été créé par celle-ci et on veut éviter
276 // les noeuds en doubles.
277 // Ces masques permettent aussi de déterminer le propriétaire des noeuds dans
278 // le cas de multiples sous-domaines.
279 // Par exemple, si l'on est sur une maille enfant située
280 // sur la partie gauche de la maille parente (mailles enfants 0 et 2 dans le cas d'un
281 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille
282 // parente (appartient à un autre sous-domaine) et (est en train d'être raffiné),
283 // on crée ce noeud mais on lui donne comme propriétaire le processus à qui appartient
284 // la maille parente à gauche.
285 const bool mask_node_if_cell_left[] = { false, true, true, false };
286 const bool mask_node_if_cell_bottom[] = { false, false, true, true };
287
288 const bool mask_node_if_cell_right[] = { true, false, false, true };
289 const bool mask_node_if_cell_top[] = { true, true, false, false };
290
291 const bool mask_face_if_cell_left[] = { true, true, true, false };
292 const bool mask_face_if_cell_bottom[] = { false, true, true, true };
293
294 const bool mask_face_if_cell_right[] = { true, false, true, true };
295 const bool mask_face_if_cell_top[] = { true, true, false, true };
296
297 // Pour la taille :
298 // - on a "cell_to_refine_internals.size() * 4" mailles enfants,
299 // - pour chaque maille, on a 2 infos (type de maille et uniqueId de la maille)
300 // - pour chaque maille, on a "m_num_mng->getNbNode()" uniqueIds (les uniqueId de chaque noeud de la maille).
301 cells_infos.reserve((cell_to_refine_internals.size() * 4) * (2 + m_num_mng->nbNodeByCell()));
302
303 // Pour la taille, au maximum :
304 // - on a "cell_to_refine_internals.size() * 12" faces
305 // - pour chaque face, on a 2 infos (type de face et uniqueId de la face)
306 // - pour chaque face, on a 2 uniqueIds de noeuds.
307 faces_infos.reserve((cell_to_refine_internals.size() * 12) * (2 + 2));
308
309 // Pour la taille, au maximum :
310 // - on a (cell_to_refine_internals.size() * 9) uniqueIds de noeuds.
311 nodes_infos.reserve(cell_to_refine_internals.size() * 9);
312
314 const Int64 parent_cell_uid = parent_cell.uniqueId();
315 const Int32 parent_cell_level = parent_cell.level();
316 const bool parent_cell_is_own = (parent_cell.owner() == my_rank);
317
318 const Int64 parent_coord_x = m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, parent_cell_level);
319 const Int64 parent_coord_y = m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, parent_cell_level);
320
321 const Int64 child_coord_x = m_num_mng->offsetLevelToLevel(parent_coord_x, parent_cell_level, parent_cell_level + 1);
322 const Int64 child_coord_y = m_num_mng->offsetLevelToLevel(parent_coord_y, parent_cell_level, parent_cell_level + 1);
323
324 const Integer pattern = m_num_mng->pattern();
325
329
330 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_parent_cell_1d, parent_cell);
331
332 for (Integer i = 0; i < 9; ++i) {
334 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
335 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
339 }
340 else {
344 }
345 }
346
347 // Pour simplifier, on utilise des vues 2D. (array[Y][X]).
351
352 // Voici les priorités pour la propriété des noeuds et des faces :
353 // ┌─────────┐
354 // │6 7 8│
355 // └───────┐ │
356 // ┌─┐ ┌─┐ │ │
357 // │3│ │4│ │5│
358 // │ │ └─┘ └─┘
359 // │ └───────┐
360 // │0 1 2│
361 // └─────────┘
362 // Chaque chiffre désigne une maille parente et une priorité (0 étant la priorité la plus forte).
363 // 4 = parent_cell ("nous")
364
365 // Exemple 1 :
366 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
367 // En bas, il n'y a pas de mailles.
368 // À gauche (donc priorité 3), il y a une maille qui est déjà raffinée (flag "II_Inactive").
369 // On est priorité 4 donc il est prioritaire. Donc les noeuds et des faces que l'on a en commun
370 // lui appartiennent.
371
372 // Exemple 2 :
373 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
374 // En haut, il y a des mailles déjà raffinées (flag "II_Inactive").
375 // On est prioritaire sur elles, on récupère donc la propriété des noeuds et des faces que l'on a
376 // en commun. Ce changement de propriété doit leur être signalé.
377
378 // On simplifie avec un tableau de booléens.
379 // Si true, alors on doit appliquer la priorité de propriété.
380 // Si false, alors on considère qu'il n'y a pas de maille à la position définie.
381 bool is_cell_around_parent_cell_present_and_useful[3][3] = { { false } };
382
383 // Pour les mailles prioritaires sur nous, on doit regarder les deux flags.
384 // Si une maille a le flag "II_Refine", on n'existe pas pour elle donc elle prend la propriété
385 // des faces et des noeuds qu'on a en commun.
386 // Si une maille a le flag "II_Inactive", elle a déjà les bons propriétaires.
387 // Quoi qu'il en soit, si true alors les faces et noeuds qu'on a en commun leurs appartiennent.
388 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)));
389 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)));
390 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)));
391
392 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)));
393 // is_cell_around_parent_cell_present_and_useful[1][1] = parent_cell;
394
395 // Pour les mailles non prioritaires, on doit regarder qu'un seul flag.
396 // Si une maille a le flag "II_Inactive", alors elle doit être avertie qu'on récupère la propriété
397 // des noeuds et des faces qu'on a en commun.
398 // On ne regarde pas le flag "II_Refine" car, si ces mailles sont aussi en train d'être raffinée,
399 // elles savent qu'on existe et qu'on obtient la propriété des noeuds et des faces qu'on a en commun.
400 // En résumé, si true alors les faces et noeuds qu'on a en commun nous appartiennent.
402
406
407 // 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...
408 // ... on regarde si chaque maille parent est présente sur notre sous-domaine, que ce soit une maille fantôme ou non.
409 auto is_cell_around_parent_cell_in_subdomain = [&](Integer y, Integer x) {
410 return is_cell_around_parent_cell_present_and_useful[y][x] && (flags_cells_around_parent_cell(y, x) & ItemFlags::II_UserMark1);
411 };
412
413 // ... on regarde si chaque maille parent est possédé par le même propriétaire que notre maille parent.
414 auto is_cell_around_parent_cell_same_owner = [&](Integer y, Integer x) {
416 };
417
418 // ... on regarde si chaque maille parent a un propriétaire différent par rapport à notre maille parent.
419 auto is_cell_around_parent_cell_different_owner = [&](Integer y, Integer x) {
421 };
422
423 // On itère sur toutes les mailles enfants.
424 for (Int64 j = child_coord_y; j < child_coord_y + pattern; ++j) {
425 for (Int64 i = child_coord_x; i < child_coord_x + pattern; ++i) {
428
429 const Int64 child_cell_uid = m_num_mng->cellUniqueId(parent_cell_level + 1, Int64x2(i, j));
430 debug() << "Child -- x : " << i << " -- y : " << j << " -- level : " << parent_cell_level + 1 << " -- uid : " << child_cell_uid;
431
432 m_num_mng->cellNodeUniqueIds(child_nodes_uids, parent_cell_level + 1, Int64x2(i, j));
433 m_num_mng->cellFaceUniqueIds(child_faces_uids, parent_cell_level + 1, Int64x2(i, j));
434
435 const Integer type_cell = IT_Quad4;
436 const Integer type_face = IT_Line2;
437
438 // Partie Cell.
439 cells_infos.add(type_cell);
440 cells_infos.add(child_cell_uid);
441 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
442 cells_infos.add(child_nodes_uids[nc]);
443 }
444
445 // Partie Face.
446 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
447 Integer child_face_owner = -1;
448 bool is_new_face = false;
449
450 // Deux parties :
451 // 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
452 // maille à côté.
453 // Pour gauche/bas, c'est le même principe. Si la maille enfant est tout à gauche/bas de la maille parente, on regarde
454 // 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
455 // doit créer la face.
456 // Pour droite/haut, le principe est différent de gauche/bas. On ne suit le masque que si on est tout à droite/haut
457 // de la maille parente. Sinon on crée toujours les faces droites/hautes.
458 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
459 // notre sous-domaine, alors il se peut que les faces en communes avec notre maille parente existent déjà, dans ce cas,
460 // pas de doublon.
461 if (
463 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2)) || mask_face_if_cell_right[l]) &&
465 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1)) || mask_face_if_cell_top[l])) {
466 is_new_face = true;
467 faces_infos.add(type_face);
468 faces_infos.add(child_faces_uids[l]);
469
470 // Les noeuds de la face sont toujours les noeuds l et l+1
471 // car on utilise la même exploration pour les deux cas.
472 for (Integer nc = l; nc < l + 2; nc++) {
473 faces_infos.add(child_nodes_uids[nc % m_num_mng->nbNodeByCell()]);
474 }
476
477 // Par défaut, parent_cell est propriétaire de la nouvelle face.
479 }
480
481 // Deuxième partie.
482 // On doit maintenant trouver le bon propriétaire pour la face. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
483 // la condition est identique à celle au-dessus.
484 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr qu'il y a la face qui nous intéresse.
485 // 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
486 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
487 // si la maille est présente sur le sous-domaine.
488 if (
490 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2)) || mask_face_if_cell_right[l]) &&
492 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1)) || mask_face_if_cell_top[l])) {
493 // Ici, la construction des conditions est la même à chaque fois.
494 // Le premier booléen (i == child_coord_x) regarde si l'enfant se trouve
495 // du bon côté de la maille parent.
496 // Le second booléen (!mask_face_if_cell_left[l]) nous dit si la face l est bien
497 // la face en commun avec la maille parent d'à côté.
498 // Le troisième booléen (is_cell_around_parent_cell_different_owner(1, 0)) regarde s'il y a une
499 // maille à côté qui prend la propriété de la face ou à qui on prend la propriété.
500
501 // En outre, il y a deux cas différents selon les priorités définies au-dessus :
502 // - soit nous ne sommes pas prioritaire, alors on attribue le propriétaire prioritaire à notre face,
503 // - soit nous sommes prioritaire, alors on se positionne comme propriétaire de la face et on doit prévenir
504 // tous les autres processus (le processus ancien propriétaire mais aussi les processus qui peuvent
505 // avoir la face en fantôme).
506
507 // Enfin, dans le cas du changement de propriétaire, seul le processus (re)prenant la propriété doit
508 // faire une communication à ce propos. Les processus ne possédant que la face en fantôme ne doit pas
509 // faire de communication (mais ils peuvent définir localement le bon propriétaire, TODO Optimisation possible ?).
510
511 // À gauche, priorité 3 < 4 donc il prend la propriété de la face.
514 }
515
516 // En bas, priorité 1 < 4 donc il prend la propriété de la face.
519 }
520
521 // Sinon, parent_cell est propriétaire de la face.
522 else {
523
524 // Sinon, c'est une face interne donc au parent_cell.
526 }
527 }
528
529 // S'il y a une création de face et/ou un changement de propriétaire.
530 if (child_face_owner != -1) {
532
533 // Lorsqu'il y a un changement de propriétaire sans création de face,
534 // on doit mettre de côté les uniqueIds de ces faces pour pouvoir
535 // itérer dessus par la suite.
536 if (!is_new_face) {
538 debug() << "Child face (change owner) -- x : " << i
539 << " -- y : " << j
540 << " -- level : " << parent_cell_level + 1
541 << " -- face : " << l
542 << " -- uid_face : " << child_faces_uids[l]
543 << " -- owner : " << child_face_owner;
544 }
545 else {
546 debug() << "Child face (create face) -- x : " << i
547 << " -- y : " << j
548 << " -- level : " << parent_cell_level + 1
549 << " -- face : " << l
550 << " -- uid_face : " << child_faces_uids[l]
551 << " -- owner : " << child_face_owner;
552 }
553 }
554 }
555
556 // Partie Node.
557 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
558 // plus de propriétaires possibles.
559 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
560 Integer child_node_owner = -1;
561 bool is_new_node = false;
562
563 // Deux parties :
564 // 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
565 // maille à côté.
566 // Pour gauche/bas, c'est le même principe. Si la maille enfant est tout à gauche/bas de la maille parente, on regarde
567 // 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
568 // doit créer le noeud.
569 // 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
570 // de la maille parente. Sinon on crée toujours les noeuds droites/hautes.
571 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
572 // notre sous-domaine, alors il se peut que les noeuds en communs avec notre maille parente existent déjà, dans ce cas,
573 // pas de doublon.
574 if (
576 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2)) || mask_node_if_cell_right[l]) &&
578 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1)) || mask_node_if_cell_top[l])) {
579 is_new_node = true;
582
583 // Par défaut, parent_cell est propriétaire du nouveau noeud.
585 }
586
587 // Deuxième partie.
588 // On doit maintenant trouver le bon propriétaire pour le noeud. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
589 // la condition est identique à celle au-dessus.
590 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr que le noeud qui nous intéresse existe.
591 // 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
592 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
593 // si la maille est présente sur le sous-domaine.
594 if (
596 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2)) || mask_node_if_cell_right[l]) &&
598 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1)) || mask_node_if_cell_top[l])) {
599 // Par rapport aux faces qui n'ont que deux propriétaires possibles, un noeud peut
600 // en avoir jusqu'à quatre.
601 // (Et oui, en 3D, c'est encore plus amusant !)
602
603 // Si le noeud est sur le côté gauche de la maille parente ("sur la face gauche").
604 if (i == child_coord_x && (!mask_node_if_cell_left[l])) {
605
606 // Si le noeud est sur le bas de la maille parente ("sur la face basse").
607 // Donc noeud en bas à gauche (même position que le noeud de la maille parente).
608 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
609
610 // Priorité 0 < 4.
613 }
614
615 // Priorité 1 < 4.
618 }
619
620 // Priorité 3 < 4.
623 }
624
625 else {
627 }
628 }
629
630 // Si le noeud est en haut de la maille parente ("sur la face haute").
631 // Donc noeud en haut à gauche (même position que le noeud de la maille parente).
632 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
633
634 // Priorité 3 < 4.
637 }
638
639 // Sinon, parent_cell est propriétaire du noeud.
640 else {
642 }
643 }
644
645 // Si le noeud est quelque part sur la face parente gauche...
646 else {
647 // S'il y a une maille à gauche, elle est propriétaire du noeud.
650 }
651
652 // Sinon parent_cell est propriétaire du noeud.
653 else {
655 }
656 }
657 }
658
659 // Si le noeud est sur le côté droit de la maille parente ("sur la face droite").
660 else if (i == (child_coord_x + pattern - 1) && (!mask_node_if_cell_right[l])) {
661
662 // Si le noeud est sur le bas de la maille parente ("sur la face basse").
663 // Donc noeud en bas à droite (même position que le noeud de la maille parente).
664 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
665
666 // Priorité 1 < 4.
669 }
670
671 // Priorité 2 < 4.
674 }
675
676 // Sinon, parent_cell est propriétaire du noeud.
677 else {
679 }
680 }
681
682 // Si le noeud est en haut de la maille parente ("sur la face haute").
683 // Donc noeud en haut à droite (même position que le noeud de la maille parente).
684 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
686 }
687
688 // Si le noeud est quelque part sur la face parente droite...
689 else {
691 }
692 }
693
694 // Si le noeud est ni sur la face parente gauche, ni sur la face parente droite...
695 else {
696
697 // Si le noeud est sur le bas de la maille parente ("sur la face basse") et
698 // qu'il y a une maille en bas de priorité 1 < 4, elle est propriétaire du noeud.
701 }
702
703 // Si le noeud est sur le haut de la maille parente ("sur la face haute") et
704 // qu'il y a une maille en haut de priorité 7 > 4, parent_cell est propriétaire du noeud.
707 }
708
709 // Noeuds qui ne sont sur aucune face de la maille parente.
710 else {
712 }
713 }
714 }
715
716 // S'il y a une création de noeud et/ou un changement de propriétaire.
717 if (child_node_owner != -1) {
719
720 // Lorsqu'il y a un changement de propriétaire sans création de noeud,
721 // on doit mettre de côté les uniqueIds de ces noeuds pour pouvoir
722 // itérer dessus par la suite.
723 if (!is_new_node) {
725 debug() << "Child node (change owner) -- x : " << i
726 << " -- y : " << j
727 << " -- level : " << parent_cell_level + 1
728 << " -- node : " << l
729 << " -- uid_node : " << child_nodes_uids[l]
730 << " -- owner : " << child_node_owner;
731 }
732 else {
733 debug() << "Child node (create node) -- x : " << i
734 << " -- y : " << j
735 << " -- level : " << parent_cell_level + 1
736 << " -- node : " << l
737 << " -- uid_node : " << child_nodes_uids[l]
738 << " -- owner : " << child_node_owner;
739 }
740 }
741 }
742 }
743 }
744 }
745 }
746
747 // Pour le 3D, c'est très ressemblant, juste un peu plus long. Je recopie les commentaires, mais avec quelques adaptations.
748 else if (m_mesh->dimension() == 3) {
749
750 // Masques pour les cas "voisins enfants" et "voisins parents du même patch".
751 // Ces masques permettent de savoir si l'on doit créer un noeud ou pas selon
752 // les mailles autour.
753 // Par exemple, si l'on est en train d'étudier une maille enfant et qu'il y a
754 // une maille enfant à gauche, on ne doit pas créer les noeuds 0, 3, 4, 7 (mask_node_if_cell_left[]) (car
755 // ils ont déjà été créés par la maille à gauche).
756 // Idem pour les mailles parentes voisines : si l'on est sur une maille enfant située
757 // sur la partie gauche de la maille parente (mailles enfants 0, 2, 4, 6 dans le cas d'un
758 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille parente
759 // est en train ((d'être raffiné et à notre sous-domaine) ou (qu'elle est inactive)), on applique
760 // la règle mask_node_if_cell_left[] car les noeuds ont été créé par celle-ci et on veut éviter
761 // les noeuds en doubles.
762 // Ces masques permettent aussi de déterminer le propriétaire des noeuds dans
763 // le cas de multiples sous-domaines.
764 // Par exemple, si l'on est sur une maille enfant située
765 // sur la partie gauche de la maille parente (mailles enfants 0, 2, 4, 6 dans le cas d'un
766 // pattern de raffinement = 2), qu'il y a une maille parente à gauche et que cette maille
767 // parente (appartient à un autre sous-domaine) et (est en train d'être raffiné),
768 // on crée ce noeud mais on lui donne comme propriétaire le processus à qui appartient
769 // la maille parente à gauche.
770 const bool mask_node_if_cell_left[] = { false, true, true, false, false, true, true, false };
771 const bool mask_node_if_cell_bottom[] = { false, false, true, true, false, false, true, true };
772 const bool mask_node_if_cell_rear[] = { false, false, false, false, true, true, true, true };
773
774 const bool mask_node_if_cell_right[] = { true, false, false, true, true, false, false, true };
775 const bool mask_node_if_cell_top[] = { true, true, false, false, true, true, false, false };
776 const bool mask_node_if_cell_front[] = { true, true, true, true, false, false, false, false };
777
778 const bool mask_face_if_cell_left[] = { true, false, true, true, true, true };
779 const bool mask_face_if_cell_bottom[] = { true, true, false, true, true, true };
780 const bool mask_face_if_cell_rear[] = { false, true, true, true, true, true };
781
782 const bool mask_face_if_cell_right[] = { true, true, true, true, false, true };
783 const bool mask_face_if_cell_top[] = { true, true, true, true, true, false };
784 const bool mask_face_if_cell_front[] = { true, true, true, false, true, true };
785
786 // Petite différence par rapport au 2D. Pour le 2D, la position des noeuds des faces
787 // dans le tableau "child_nodes_uids" est toujours pareil (l et l+1, voir le 2D).
788 // Pour le 3D, ce n'est pas le cas donc on a des tableaux pour avoir une correspondance
789 // entre les noeuds de chaque face et la position des noeuds dans le tableau "child_nodes_uids".
790 // (Exemple : pour la face 1 (même ordre d'énumération qu'Arcane), on doit prendre le
791 // tableau "nodes_in_face_1" et donc les noeuds "child_nodes_uids[0]", "child_nodes_uids[3]",
792 // "child_nodes_uids[7]" et "child_nodes_uids[4]").
793 const Integer nodes_in_face_0[] = { 0, 1, 2, 3 };
794 const Integer nodes_in_face_1[] = { 0, 3, 7, 4 };
795 const Integer nodes_in_face_2[] = { 0, 1, 5, 4 };
796 const Integer nodes_in_face_3[] = { 4, 5, 6, 7 };
797 const Integer nodes_in_face_4[] = { 1, 2, 6, 5 };
798 const Integer nodes_in_face_5[] = { 3, 2, 6, 7 };
799
800 const Integer nb_nodes_in_face = 4;
801
802 // Pour la taille :
803 // - on a "cell_to_refine_internals.size() * 8" mailles enfants,
804 // - pour chaque maille, on a 2 infos (type de maille et uniqueId de la maille)
805 // - pour chaque maille, on a "m_num_mng->getNbNode()" uniqueIds (les uniqueId de chaque noeud de la maille).
806 cells_infos.reserve((cell_to_refine_internals.size() * 8) * (2 + m_num_mng->nbNodeByCell()));
807
808 // Pour la taille, au maximum :
809 // - on a "cell_to_refine_internals.size() * 36" faces enfants,
810 // - pour chaque face, on a 2 infos (type de face et uniqueId de la face)
811 // - pour chaque face, on a 4 uniqueIds de noeuds.
812 faces_infos.reserve((cell_to_refine_internals.size() * 36) * (2 + 4));
813
814 // Pour la taille, au maximum :
815 // - on a (cell_to_refine_internals.size() * 27) uniqueIds de noeuds.
816 nodes_infos.reserve(cell_to_refine_internals.size() * 27);
817
819 const Int64 parent_cell_uid = parent_cell.uniqueId();
820 const Int32 parent_cell_level = parent_cell.level();
821
822 const Int64 parent_coord_x = m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, parent_cell_level);
823 const Int64 parent_coord_y = m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, parent_cell_level);
824 const Int64 parent_coord_z = m_num_mng->cellUniqueIdToCoordZ(parent_cell_uid, parent_cell_level);
825
826 const Int64 child_coord_x = m_num_mng->offsetLevelToLevel(parent_coord_x, parent_cell_level, parent_cell_level + 1);
827 const Int64 child_coord_y = m_num_mng->offsetLevelToLevel(parent_coord_y, parent_cell_level, parent_cell_level + 1);
828 const Int64 child_coord_z = m_num_mng->offsetLevelToLevel(parent_coord_z, parent_cell_level, parent_cell_level + 1);
829
830 const Integer pattern = m_num_mng->pattern();
831
835
836 m_num_mng->cellUniqueIdsAroundCell(uid_cells_around_parent_cell_1d, parent_cell);
837
838 for (Integer i = 0; i < 27; ++i) {
840 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
841 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
845 }
846 else {
850 }
851 }
852
853 // Pour simplifier, on utilise des vues 3D. (array[Z][Y][X]).
857
858 // Voici les priorités pour la propriété des noeuds et des faces :
859 // ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐
860 // │ 6 7 8│ │ │15 16 17│ │ │24 25 26│
861 // │ │ │ └───────┐ │ │ │ │
862 // │ │ │ ┌──┐┌──┐│ │ │ │ │
863 // │ 3 4 5│ │ │12││13││14│ │ │21 22 23│
864 // │ │ │ │ │└──┘└──┘ │ │ │
865 // │ │ │ │ └───────┐ │ │ │
866 // │ 0 1 2│ │ │ 9 10 11│ │ │18 19 20│
867 // └──────────┘ │ └──────────┘ │ └──────────┘
868 // Z=0 │ Z=1 │ Z=2
869 // ("arrière") │ │ ("avant")
870
871 // Chaque chiffre désigne une maille parente et une priorité (0 étant la priorité la plus forte).
872 // 13 = parent_cell ("nous")
873
874 // Exemple 1 :
875 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
876 // En bas, il n'y a pas de mailles.
877 // À gauche (donc priorité 12), il y a une maille qui est déjà raffinée (flag "II_Inactive").
878 // On est priorité 13 donc il est prioritaire. Donc les noeuds et des faces que l'on a en commun
879 // lui appartiennent.
880
881 // Exemple 2 :
882 // On cherche à raffiner des mailles de niveau 0 (donc créer des mailles de niveau 1).
883 // En haut, il y a des mailles déjà raffinées (flag "II_Inactive").
884 // On est prioritaire sur elles, on récupère donc la propriété des noeuds et des faces que l'on a
885 // en commun. Ce changement de propriété doit leur être signalé.
886
887 // On simplifie avec un tableau de booléens.
888 // Si true, alors on doit appliquer la priorité de propriété.
889 // Si false, alors on considère qu'il n'y a pas de maille à la position définie.
890 bool is_cell_around_parent_cell_present_and_useful[3][3][3] = { { { false } } };
891
892 // Pour les mailles prioritaires sur nous, on doit regarder les deux flags.
893 // Si une maille a le flag "II_Refine", on n'existe pas pour elle donc elle prend la propriété
894 // des faces et des noeuds qu'on a en commun.
895 // Si une maille a le flag "II_Inactive", elle a déjà les bons propriétaires.
896 // Quoi qu'il en soit, si true alors les faces et noeuds qu'on a en commun leurs appartiennent.
897 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)));
898 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)));
899 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)));
900 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)));
901 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)));
902 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)));
903 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)));
904 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)));
905 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)));
906
907 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)));
908 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)));
909 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)));
910
911 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)));
912 // is_cell_around_parent_cell_present_and_useful[1][1][1] = parent_cell;
913
914 // Pour les mailles non prioritaires, on doit regarder qu'un seul flag.
915 // Si une maille a le flag "II_Inactive", alors elle doit être avertie qu'on récupère la propriété
916 // des noeuds et des faces qu'on a en commun.
917 // On ne regarde pas le flag "II_Refine" car, si ces mailles sont aussi en train d'être raffinée,
918 // elles savent qu'on existe et qu'on obtient la propriété des noeuds et des faces qu'on a en commun.
919 // En résumé, si true alors les faces et noeuds qu'on a en commun nous appartiennent.
920 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));
921
922 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));
923 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));
924 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));
925
926 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));
927 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));
928 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));
929 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));
930 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));
931 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));
932 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));
933 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));
934 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));
935
936 // 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...
937 // ... on regarde si chaque maille parent est présente sur notre sous-domaine, que ce soit une maille fantôme ou non.
938 auto is_cell_around_parent_cell_in_subdomain = [&](Integer z, Integer y, Integer x) {
939 return is_cell_around_parent_cell_present_and_useful[z][y][x] && (flags_cells_around_parent_cell(z, y, x) & ItemFlags::II_UserMark1);
940 };
941
942 // ... on regarde si chaque maille parent est possédé par le même propriétaire que notre maille parent.
943 auto is_cell_around_parent_cell_same_owner = [&](Integer z, Integer y, Integer x) {
945 };
946
947 // ... on regarde si chaque maille parent a un propriétaire différent par rapport à notre maille parent.
948 auto is_cell_around_parent_cell_different_owner = [&](Integer z, Integer y, Integer x) {
950 };
951
952 // On itère sur toutes les mailles enfants.
953 for (Int64 k = child_coord_z; k < child_coord_z + pattern; ++k) {
954 for (Int64 j = child_coord_y; j < child_coord_y + pattern; ++j) {
955 for (Int64 i = child_coord_x; i < child_coord_x + pattern; ++i) {
958
959 const Int64 child_cell_uid = m_num_mng->cellUniqueId(parent_cell_level + 1, Int64x3(i, j, k));
960 debug() << "Child -- x : " << i << " -- y : " << j << " -- z : " << k << " -- level : " << parent_cell_level + 1 << " -- uid : " << child_cell_uid;
961
962 m_num_mng->cellNodeUniqueIds(child_nodes_uids, parent_cell_level + 1, Int64x3(i, j, k));
963 m_num_mng->cellFaceUniqueIds(child_faces_uids, parent_cell_level + 1, Int64x3(i, j, k));
964
965 const Integer type_cell = IT_Hexaedron8;
966 const Integer type_face = IT_Quad4;
967
968 // Partie Cell.
969 cells_infos.add(type_cell);
970 cells_infos.add(child_cell_uid);
971 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
972 cells_infos.add(child_nodes_uids[nc]);
973 }
974
975 // Partie Face.
976 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
977 Integer child_face_owner = -1;
978 bool is_new_face = false;
979
980 // Deux parties :
981 // 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
982 // maille à côté.
983 // 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
984 // 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
985 // doit créer la face.
986 // 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
987 // de la maille parente. Sinon on crée toujours les faces droites/hautes/avant.
988 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
989 // notre sous-domaine, alors il se peut que les faces en communes avec notre maille parente existent déjà, dans ce cas,
990 // pas de doublon.
991 if (
993 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 1, 2)) || mask_face_if_cell_right[l]) &&
995 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2, 1)) || mask_face_if_cell_top[l]) &&
997 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1, 1)) || mask_face_if_cell_front[l])) {
998 is_new_face = true;
999 faces_infos.add(type_face);
1000 faces_infos.add(child_faces_uids[l]);
1001
1002 // On récupère la position des noeuds de la face dans le tableau "ua_node_uid".
1004 switch (l) {
1005 case 0:
1007 break;
1008 case 1:
1010 break;
1011 case 2:
1013 break;
1014 case 3:
1016 break;
1017 case 4:
1019 break;
1020 case 5:
1022 break;
1023 default:
1024 ARCANE_FATAL("Bizarre...");
1025 }
1026 for (Integer nc : nodes_in_face_l) {
1027 faces_infos.add(child_nodes_uids[nc]);
1028 }
1030
1031 // Par défaut, parent_cell est propriétaire de la nouvelle face.
1033 }
1034
1035 // Deuxième partie.
1036 // On doit maintenant trouver le bon propriétaire pour la face. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
1037 // la condition est identique à celle au-dessus.
1038 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr qu'il y a la face qui nous intéresse.
1039 // 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
1040 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
1041 // si la maille est présente sur le sous-domaine.
1042 if (
1044 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 1, 2)) || mask_face_if_cell_right[l]) &&
1046 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2, 1)) || mask_face_if_cell_top[l]) &&
1048 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1, 1)) || mask_face_if_cell_front[l])) {
1049 // Ici, la construction des conditions est la même à chaque fois.
1050 // Le premier booléen (i == child_coord_x) regarde si l'enfant se trouve
1051 // du bon côté de la maille parent.
1052 // Le second booléen (!mask_face_if_cell_left[l]) nous dit si la face l est bien
1053 // la face en commun avec la maille parent d'à côté.
1054 // Le troisième booléen (is_cell_around_parent_cell_different_owner(1, 0)) regarde s'il y a une
1055 // maille à côté qui prend la propriété de la face ou à qui on prend la propriété.
1056
1057 // En outre, il y a deux cas différents selon les priorités définies au-dessus :
1058 // - soit nous ne sommes pas prioritaire, alors on attribue le propriétaire prioritaire à notre face,
1059 // - soit nous sommes prioritaire, alors on se positionne comme propriétaire de la face et on doit prévenir
1060 // tous les autres processus (le processus ancien propriétaire mais aussi les processus qui peuvent
1061 // avoir la face en fantôme).
1062
1063 // Enfin, dans le cas du changement de propriétaire, seul le processus (re)prenant la propriété doit
1064 // faire une communication à ce propos. Les processus ne possédant que la face en fantôme ne doit pas
1065 // faire de communication (mais ils peuvent définir localement le bon propriétaire, TODO Optimisation possible ?).
1066
1067 // À gauche, priorité 12 < 13 donc il prend la propriété de la face.
1070 }
1071
1072 // En bas, priorité 10 < 13 donc il prend la propriété de la face.
1075 }
1076
1077 // À l'arrière, priorité 4 < 13 donc il prend la propriété de la face.
1080 }
1081
1082 // Sinon, parent_cell est propriétaire de la face.
1083 else {
1084
1085 // Sinon, c'est une face interne donc au parent_cell.
1087 }
1088 }
1089
1090 // S'il y a une création de face et/ou un changement de propriétaire.
1091 if (child_face_owner != -1) {
1093
1094 // Lorsqu'il y a un changement de propriétaire sans création de face,
1095 // on doit mettre de côté les uniqueIds de ces faces pour pouvoir
1096 // itérer dessus par la suite.
1097 if (!is_new_face) {
1099 debug() << "Child face (change owner) -- x : " << i
1100 << " -- y : " << j
1101 << " -- z : " << k
1102 << " -- level : " << parent_cell_level + 1
1103 << " -- face : " << l
1104 << " -- uid_face : " << child_faces_uids[l]
1105 << " -- owner : " << child_face_owner;
1106 }
1107 else {
1108 debug() << "Child face (create face) -- x : " << i
1109 << " -- y : " << j
1110 << " -- z : " << k
1111 << " -- level : " << parent_cell_level + 1
1112 << " -- face : " << l
1113 << " -- uid_face : " << child_faces_uids[l]
1114 << " -- owner : " << child_face_owner;
1115 }
1116 }
1117 }
1118
1119 // Partie Node.
1120 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
1121 // plus de propriétaires possibles.
1122 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
1123 Integer child_node_owner = -1;
1124 bool is_new_node = false;
1125
1126 // Deux parties :
1127 // 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
1128 // maille à côté.
1129 // 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
1130 // 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
1131 // doit créer le noeud.
1132 // Pour droite/haut/avant, le principe est différent de gauche/bas/arrière. On ne suit le masque que si la maille
1133 // enfant est toute à droite/haut/avant
1134 // de la maille parente. Sinon on crée toujours les noeuds droites/hautes/avant.
1135 // Enfin, on utilise le tableau "is_cell_around_parent_cell_in_subdomain". Si la maille parente d'à côté est sur
1136 // notre sous-domaine, alors il se peut que les noeuds en communs avec notre maille parente existent déjà, dans ce cas,
1137 // pas de doublon.
1138 if (
1140 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 1, 2)) || mask_node_if_cell_right[l]) &&
1142 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(1, 2, 1)) || mask_node_if_cell_top[l]) &&
1144 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_in_subdomain(2, 1, 1)) || mask_node_if_cell_front[l])) {
1145 is_new_node = true;
1148
1149 // Par défaut, parent_cell est propriétaire du nouveau noeud.
1151 }
1152
1153 // Deuxième partie.
1154 // On doit maintenant trouver le bon propriétaire pour le noeud. Mis à part le tableau "is_cell_around_parent_cell_same_owner",
1155 // la condition est identique à celle au-dessus.
1156 // Le changement de tableau est important puisqu'à partir d'ici, on est sûr que le noeud qui nous intéresse existe.
1157 // 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
1158 // un changement de propriétaire est possible, selon les priorités définies au-dessus. On n'a pas besoin de savoir
1159 // si la maille est présente sur le sous-domaine.
1160 if (
1162 ((i != (child_coord_x + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 1, 2)) || mask_node_if_cell_right[l]) &&
1164 ((j != (child_coord_y + pattern - 1) || !is_cell_around_parent_cell_same_owner(1, 2, 1)) || mask_node_if_cell_top[l]) &&
1166 ((k != (child_coord_z + pattern - 1) || !is_cell_around_parent_cell_same_owner(2, 1, 1)) || mask_node_if_cell_front[l])) {
1167
1168 // Par rapport aux faces qui n'ont que deux propriétaires possibles, un noeud peut
1169 // en avoir jusqu'à huit.
1170
1171 // Si le noeud est sur la face gauche de la maille parente.
1172 if (i == child_coord_x && (!mask_node_if_cell_left[l])) {
1173
1174 // Si le noeud est sur la face basse de la maille parente.
1175 // Donc noeud sur l'arête à gauche en bas.
1176 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1177
1178 // Si le noeud est sur la face arrière de la maille parente.
1179 // Donc noeud à gauche, en bas, en arrière (même position que le noeud de la maille parente).
1180 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1181
1182 // Priorité 0 < 13.
1185 }
1186
1187 // Priorité 1 < 13.
1190 }
1191
1192 // Priorité 3 < 13.
1195 }
1196
1197 // Priorité 4 < 13.
1200 }
1201
1202 // Priorité 9 < 13.
1205 }
1206
1207 // Priorité 10 < 13.
1210 }
1211
1212 // Priorité 12 < 13.
1215 }
1216
1217 // Pas de mailles autour.
1218 else {
1220 }
1221 }
1222
1223 // Si le noeud est sur la face avant de la maille parente.
1224 // Donc noeud à gauche, en bas, en avant (même position que le noeud de la maille parente).
1225 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1226
1227 // Priorité 9 < 13.
1230 }
1231
1232 // Priorité 10 < 13.
1235 }
1236
1237 // Priorité 12 < 13.
1240 }
1241
1242 // Sinon, parent_cell est propriétaire du noeud.
1243 else {
1245 }
1246 }
1247
1248 // Sinon le noeud est quelque part sur l'arête à gauche en bas...
1249 else {
1250
1251 // Priorité 9 < 13.
1254 }
1255
1256 // Priorité 10 < 13.
1259 }
1260
1261 // Priorité 12 < 13.
1264 }
1265
1266 // Pas de mailles autour.
1267 else {
1269 }
1270 }
1271 }
1272
1273 // Si le noeud est sur la face haute de la maille parente.
1274 // Donc noeud sur l'arête à gauche en haut.
1275 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1276
1277 // Si le noeud est sur la face arrière de la maille parente.
1278 // Donc noeud à gauche, en haut, en arrière (même position que le noeud de la maille parente).
1279 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1280
1281 // Priorité 3 < 13.
1284 }
1285
1286 // Priorité 4 < 13.
1289 }
1290
1291 // Priorité 6 < 13.
1294 }
1295
1296 // Priorité 7 < 13.
1299 }
1300
1301 // Priorité 12 < 13.
1304 }
1305
1306 // Sinon, parent_cell est propriétaire du noeud.
1307 else {
1309 }
1310 }
1311
1312 // Si le noeud est sur la face avant de la maille parente.
1313 // Donc noeud à gauche, en haut, en avant (même position que le noeud de la maille parente).
1314 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1315
1316 // Priorité 4 < 13.
1319 }
1320
1321 // Sinon, parent_cell est propriétaire du noeud.
1322 else {
1324 }
1325 }
1326
1327 // Sinon le noeud est quelque part sur l'arête à gauche en haut...
1328 else {
1329
1330 // Priorité 12 < 13.
1333 }
1334
1335 // Sinon, parent_cell est propriétaire du noeud.
1336 else {
1338 }
1339 }
1340 }
1341
1342 // Sinon le noeud est ni sur l'arête à gauche en bas, ni sur l'arête à gauche en haut.
1343 else {
1344
1345 // Si le noeud est quelque part sur l'arête à gauche en arrière.
1346 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1347
1348 // Priorité 3 < 13.
1351 }
1352
1353 // Priorité 4 < 13.
1356 }
1357
1358 // Priorité 12 < 13.
1361 }
1362
1363 // Pas de mailles autour.
1364 else {
1366 }
1367 }
1368
1369 // Si le noeud est quelque part sur l'arête à gauche en avant.
1370 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1371
1372 // Priorité 12 < 13.
1375 }
1376
1377 // Sinon, parent_cell est propriétaire du noeud.
1378 else {
1380 }
1381 }
1382
1383 // Sinon le noeud est quelque part sur la face gauche...
1384 else {
1385
1386 // Priorité 12 < 13.
1389 }
1390
1391 // Parent_cell est le proprio.
1392 else {
1394 }
1395 }
1396 }
1397 }
1398
1399 // À partir de là, on a exploré tous les noeuds et toutes les arêtes de la face parente gauche.
1400
1401 // Si le noeud est sur la face droite de la maille parente.
1402 else if (i == (child_coord_x + pattern - 1) && (!mask_node_if_cell_right[l])) {
1403
1404 // Si le noeud est sur la face basse de la maille parente.
1405 // Donc noeud sur l'arête à droite en bas.
1406 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1407
1408 // Si le noeud est sur la face arrière de la maille parente.
1409 // Donc noeud à droite, en bas, en arrière (même position que le noeud de la maille parente).
1410 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1411
1412 // Priorité 1 < 13.
1415 }
1416
1417 // Priorité 2 < 13.
1420 }
1421
1422 // Priorité 4 < 13.
1425 }
1426
1427 // Priorité 5 < 13.
1430 }
1431
1432 // Priorité 10 < 13.
1435 }
1436
1437 // Priorité 11 < 13.
1440 }
1441
1442 // Sinon, parent_cell est propriétaire du noeud.
1443 else {
1445 }
1446 }
1447
1448 // Si le noeud est sur la face avant de la maille parente.
1449 // Donc noeud à droite, en bas, en avant (même position que le noeud de la maille parente).
1450 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1451
1452 // Priorité 10 < 13.
1455 }
1456
1457 // Priorité 11 < 13.
1460 }
1461
1462 // Sinon, parent_cell est propriétaire du noeud.
1463 else {
1465 }
1466 }
1467
1468 // Sinon le noeud est quelque part sur l'arête à droite en bas...
1469 else {
1470
1471 // Priorité 10 < 13.
1474 }
1475
1476 // Priorité 11 < 13.
1479 }
1480
1481 // Sinon, parent_cell est propriétaire du noeud.
1482 else {
1484 }
1485 }
1486 }
1487
1488 // Si le noeud est sur la face haute de la maille parente.
1489 // Donc noeud sur l'arête à droite en haut.
1490 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1491
1492 // Si le noeud est sur la face arrière de la maille parente.
1493 // Donc noeud à droite, en haut, en arrière (même position que le noeud de la maille parente).
1494 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1495
1496 // Priorité 4 < 13.
1499 }
1500
1501 // Priorité 5 < 13.
1504 }
1505
1506 // Priorité 7 < 13.
1509 }
1510
1511 // Priorité 8 < 13.
1514 }
1515
1516 // Sinon, parent_cell est propriétaire du noeud.
1517 else {
1519 }
1520 }
1521
1522 // Si le noeud est sur la face avant de la maille parente.
1523 // Donc noeud à droite, en haut, en avant (même position que le noeud de la maille parente).
1524 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1526 }
1527
1528 // Sinon le noeud est quelque part sur l'arête à droite en haut...
1529 else {
1531 }
1532 }
1533
1534 // Sinon le noeud est ni sur l'arête à droite en bas, ni sur l'arête à droite en haut.
1535 else {
1536 // Si le noeud est quelque part sur l'arête à droite en arrière.
1537 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1538
1539 // Priorité 4 < 13.
1542 }
1543
1544 // Priorité 5 < 13.
1547 }
1548
1549 // Sinon, parent_cell est propriétaire du noeud.
1550 else {
1552 }
1553 }
1554
1555 // Si le noeud est quelque part sur l'arête à droite en avant.
1556 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1558 }
1559
1560 // Sinon le noeud est quelque part sur la face droite...
1561 else {
1563 }
1564 }
1565 }
1566
1567 // À partir de là, on a exploré tous les noeuds de la maille parente et toutes les arêtes
1568 // de la face parente droite (et gauche).
1569 // Donc il ne reste que quatre arêtes et quatre faces à explorer.
1570
1571 // Sinon le noeud est ni sur la face gauche, ni sur la face droite.
1572 else {
1573
1574 // Si le noeud est sur la face basse de la maille parente.
1575 if (j == child_coord_y && (!mask_node_if_cell_bottom[l])) {
1576
1577 // Si le noeud est sur la face arrière de la maille parente.
1578 // Donc noeud sur l'arête en arrière en bas.
1579 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1580
1581 // Priorité 1 < 13.
1584 }
1585
1586 // Priorité 4 < 13.
1589 }
1590
1591 // Priorité 10 < 13.
1594 }
1595
1596 // Pas de mailles autour.
1597 else {
1599 }
1600 }
1601
1602 // Si le noeud est sur la face avant de la maille parente.
1603 // Donc noeud sur l'arête en avant en bas.
1604 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1605
1606 // Priorité 10 < 13.
1609 }
1610
1611 // Sinon, parent_cell est propriétaire du noeud.
1612 else {
1614 }
1615 }
1616
1617 // Sinon le noeud est quelque part sur la face en bas...
1618 else {
1619
1620 // Priorité 10 < 13.
1623 }
1624
1625 // Parent_cell est le proprio.
1626 else {
1628 }
1629 }
1630 }
1631
1632 // Si le noeud est sur la face haute de la maille parente.
1633 else if (j == (child_coord_y + pattern - 1) && (!mask_node_if_cell_top[l])) {
1634
1635 // Si le noeud est sur la face arrière de la maille parente.
1636 // Donc noeud sur l'arête en arrière en haut.
1637 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1638
1639 // Priorité 4 < 13.
1642 }
1643
1644 // Priorité 7 < 13.
1647 }
1648
1649 // Sinon, parent_cell est propriétaire du noeud.
1650 else {
1652 }
1653 }
1654
1655 // Si le noeud est sur la face avant de la maille parente.
1656 // Donc noeud sur l'arête en avant en haut.
1657 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1659 }
1660
1661 // Sinon le noeud est quelque part sur la face en haut...
1662 else {
1664 }
1665 }
1666
1667 // Il ne reste plus que deux faces, la face arrière et la face avant...
1668 else {
1669
1670 // Si le noeud est quelque part sur la face arrière...
1671 if (k == child_coord_z && (!mask_node_if_cell_rear[l])) {
1672
1673 // Priorité 4 < 13.
1676 }
1677
1678 // Parent_cell est le proprio.
1679 else {
1681 }
1682 }
1683
1684 // Si le noeud est quelque part sur la face avant...
1685 else if (k == (child_coord_z + pattern - 1) && (!mask_node_if_cell_front[l])) {
1687 }
1688
1689 // Sinon, le noeud est à l'intérieur de la maille parente.
1690 else {
1692 }
1693 }
1694 }
1695 }
1696
1697 // S'il y a une création de noeud et/ou un changement de propriétaire.
1698 if (child_node_owner != -1) {
1700
1701 // Lorsqu'il y a un changement de propriétaire sans création de noeud,
1702 // on doit mettre de côté les uniqueIds de ces noeuds pour pouvoir
1703 // itérer dessus par la suite.
1704 if (!is_new_node) {
1706 debug() << "Child node (change owner) -- x : " << i
1707 << " -- y : " << j
1708 << " -- z : " << k
1709 << " -- level : " << parent_cell_level + 1
1710 << " -- node : " << l
1711 << " -- uid_node : " << child_nodes_uids[l]
1712 << " -- owner : " << child_node_owner;
1713 }
1714 else {
1715 debug() << "Child node (create node) -- x : " << i
1716 << " -- y : " << j
1717 << " -- z : " << k
1718 << " -- level : " << parent_cell_level + 1
1719 << " -- node : " << l
1720 << " -- uid_node : " << child_nodes_uids[l]
1721 << " -- owner : " << child_node_owner;
1722 }
1723 }
1724 }
1725 }
1726 }
1727 }
1728 }
1729 }
1730 else {
1731 ARCANE_FATAL("Bad dimension");
1732 }
1733
1734 // Nodes
1735 {
1736 debug() << "Nb new nodes in patch : " << total_nb_nodes;
1737 {
1738 const Integer nb_node_owner_change = node_uid_change_owner_only.size();
1739
1740 // Ce tableau contiendra les localIds des nouveaux noeuds mais aussi les localIds
1741 // des noeuds qui changent juste de propriétaire.
1743
1744 // On crée les noeuds. On met les localIds des nouveaux noeuds au début du tableau.
1745 m_mesh->modifier()->addNodes(nodes_infos, nodes_lid.subView(0, total_nb_nodes));
1746
1747 // On cherche les localIds des noeuds qui changent de proprio et on les met à la fin du tableau.
1748 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(nodes_lid.subView(total_nb_nodes, nb_node_owner_change), node_uid_change_owner_only, true);
1749
1752 Integer index = 0;
1753
1754 // On attribue les bons propriétaires aux noeuds.
1755 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
1756 Node node = *inode;
1758
1759 if (node_uid_to_owner[node.uniqueId()] == my_rank) {
1760 node.mutableItemBase().addFlags(ItemFlags::II_Own);
1761 }
1762 // TODO : Corriger ça dans la partie concerné directement.
1763 else {
1764 node.mutableItemBase().removeFlags(ItemFlags::II_Shared);
1765 }
1766 // Attention, node.level() == -1 ici.
1767 uid_child_nodes[index++] = m_num_mng->parentNodeUniqueIdOfNode(node.uniqueId(), max_level + 1, false);
1768 }
1769
1770 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(lid_child_nodes, uid_child_nodes, false);
1771 NodeInfoListView nodes(m_mesh->nodeFamily());
1772
1773 index = 0;
1774 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
1775 const Int32 child_lid = lid_child_nodes[index++];
1776 if (child_lid == NULL_ITEM_ID) {
1777 continue;
1778 }
1779
1780 Node parent = nodes[child_lid];
1781 Node child = *inode;
1782
1783 m_mesh->modifier()->addParentNodeToNode(child, parent);
1784 m_mesh->modifier()->addChildNodeToNode(parent, child);
1785 }
1786 }
1787 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
1788 }
1789
1790 // Faces
1791 {
1792 debug() << "Nb new faces in patch : " << total_nb_faces;
1793 {
1794 const Integer nb_face_owner_change = face_uid_change_owner_only.size();
1795
1796 // Ce tableau contiendra les localIds des nouvelles faces mais aussi les localIds
1797 // des faces qui changent juste de propriétaire.
1799
1800 // On crée les faces. On met les localIds des nouvelles faces au début du tableau.
1801 m_mesh->modifier()->addFaces(total_nb_faces, faces_infos, faces_lid.subView(0, total_nb_faces));
1802
1803 // On cherche les localIds des faces qui changent de proprio et on les met à la fin du tableau.
1804 m_mesh->faceFamily()->itemsUniqueIdToLocalId(faces_lid.subView(total_nb_faces, nb_face_owner_change), face_uid_change_owner_only, true);
1805
1808 Integer index = 0;
1809
1810 // On attribue les bons propriétaires aux faces.
1811 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
1812 Face face = *iface;
1814
1815 if (face_uid_to_owner[face.uniqueId()] == my_rank) {
1816 face.mutableItemBase().addFlags(ItemFlags::II_Own);
1817 }
1818 // TODO : Corriger ça dans la partie concerné directement.
1819 else {
1820 face.mutableItemBase().removeFlags(ItemFlags::II_Shared);
1821 }
1822 // Attention, face.level() == -1 ici.
1823 uid_parent_faces[index++] = m_num_mng->parentFaceUniqueIdOfFace(face.uniqueId(), max_level + 1, false);
1824 //debug() << "Parent of : " << face.uniqueId() << " is : " << uid_child_faces[index - 1];
1825 }
1826
1827 m_mesh->faceFamily()->itemsUniqueIdToLocalId(lid_parent_faces, uid_parent_faces, false);
1828 FaceInfoListView faces(m_mesh->faceFamily());
1829
1830 index = 0;
1831 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
1832 const Int32 child_lid = lid_parent_faces[index++];
1833 if (child_lid == NULL_ITEM_ID) {
1834 continue;
1835 }
1836
1837 Face parent = faces[child_lid];
1838 Face child = *iface;
1839
1840 m_mesh->modifier()->addParentFaceToFace(child, parent);
1841 m_mesh->modifier()->addChildFaceToFace(parent, child);
1842 }
1843 }
1844 m_mesh->faceFamily()->notifyItemsOwnerChanged();
1845 }
1846
1847 // Cells
1848 {
1849 debug() << "Nb new cells in patch : " << total_nb_cells;
1850
1852 m_mesh->modifier()->addCells(total_nb_cells, cells_infos, cells_lid);
1853
1854 // Itération sur les nouvelles mailles.
1855 CellInfoListView cells(m_mesh->cellFamily());
1856 for (Integer i = 0; i < total_nb_cells; ++i) {
1857 Cell child = cells[cells_lid[i]];
1858
1859 child.mutableItemBase().setOwner(parent_cells[i].owner(), my_rank);
1860
1861 child.mutableItemBase().addFlags(ItemFlags::II_JustAdded);
1862
1863 if (parent_cells[i].owner() == my_rank) {
1864 child.mutableItemBase().addFlags(ItemFlags::II_Own);
1865 }
1866
1867 if (parent_cells[i].itemBase().flags() & ItemFlags::II_Shared) {
1868 child.mutableItemBase().addFlags(ItemFlags::II_Shared);
1869 }
1870
1871 m_mesh->modifier()->addParentCellToCell(child, parent_cells[i]);
1872 m_mesh->modifier()->addChildCellToCell(parent_cells[i], child);
1873 }
1874
1875 // Itération sur les mailles parentes.
1876 for (Cell cell : cell_to_refine_internals) {
1877 cell.mutableItemBase().removeFlags(ItemFlags::II_Refine);
1878 cell.mutableItemBase().addFlags(ItemFlags::II_JustRefined | ItemFlags::II_Inactive);
1879 }
1880 m_mesh->cellFamily()->notifyItemsOwnerChanged();
1881 }
1882
1883 m_mesh->modifier()->endUpdate();
1884
1885 // On positionne les noeuds dans l'espace.
1887 m_num_mng->setChildNodeCoordinates(parent_cell);
1888 // On ajoute le flag "II_Shared" aux noeuds et aux faces des mailles partagées.
1889 if (parent_cell.mutableItemBase().flags() & ItemFlags::II_Shared) {
1890 for (Integer i = 0; i < parent_cell.nbHChildren(); ++i) {
1891 Cell child_cell = parent_cell.hChild(i);
1892 for (Node node : child_cell.nodes()) {
1893 if (node.mutableItemBase().flags() & ItemFlags::II_Own) {
1894 node.mutableItemBase().addFlags(ItemFlags::II_Shared);
1895 }
1896 }
1897
1898 for (Face face : child_cell.faces()) {
1899 if (face.mutableItemBase().flags() & ItemFlags::II_Own) {
1900 face.mutableItemBase().addFlags(ItemFlags::II_Shared);
1901 }
1902 }
1903 }
1904 }
1905 }
1906
1907 // Recalcule les informations de synchronisation.
1908 m_mesh->computeSynchronizeInfos();
1909
1910 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
1911 // debug() << "\t" << *icell;
1912 // for(Node node : icell->nodes()){
1913 // debug() << "\t\t" << node;
1914 // }
1915 // for(Face face : icell->faces()){
1916 // debug() << "\t\t\t" << face;
1917 // }
1918 // }
1919 // info() << "Résumé :";
1920 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
1921 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
1922 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
1923 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
1924 // }
1925 // }
1926 // info() << "Résumé node:";
1927 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
1928 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
1929 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
1930 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
1931 // }
1932 // }
1933 //
1934 // info() << "Résumé :";
1935 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
1936 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
1937 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
1938 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
1939 // }
1940 // }
1941}
1942
1943/*---------------------------------------------------------------------------*/
1944/*---------------------------------------------------------------------------*/
1945
1946void CartesianMeshAMRPatchMng::
1947coarse()
1948{
1949 IParallelMng* pm = m_mesh->parallelMng();
1950 Int32 nb_rank = pm->commSize();
1951 Int32 my_rank = pm->commRank();
1952
1954
1955 // TODO : Remplacer around_parent_cells_uid_to_owner par parent_to_child_cells ?
1956 std::unordered_map<Int64, Int32> around_parent_cells_uid_to_owner;
1957 std::unordered_map<Int64, bool> around_parent_cells_uid_is_in_subdomain;
1958 std::unordered_map<Int64, UniqueArray<Cell>> parent_to_child_cells;
1959
1960 std::unordered_map<Int64, Int32> node_uid_to_owner;
1961 std::unordered_map<Int64, Int32> face_uid_to_owner;
1962
1963 // On va créer le niveau -1.
1964 // À noter qu'à la fin de la méthode, on replacera ce niveau
1965 // à 0.
1966 m_num_mng->prepareLevel(-1);
1967
1968 // On crée une ou plusieurs couches de mailles fantômes
1969 // pour éviter qu'une maille parente n'ai pas le même
1970 // nombre de mailles enfant.
1971 // ----------
1972 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1973 IMeshModifier* mesh_modifier = m_mesh->modifier();
1974 IGhostLayerMng* gm = m_mesh->ghostLayerMng();
1975 // Il faut au moins utiliser la version 3 pour pouvoir supporter
1976 // plusieurs couches de mailles fantômes
1977 Int32 version = gm->builderVersion();
1978 if (version < 3)
1979 gm->setBuilderVersion(3);
1980 Int32 nb_ghost_layer = gm->nbGhostLayer();
1981 // TODO AH : Cette ligne permettrait d'avoir moins de mailles fantômes et
1982 // d'éviter leurs suppressions en cas d'inutilité. Mais le comportement
1983 // serait différent de l'AMR historique.
1984 //gm->setNbGhostLayer(nb_ghost_layer + (nb_ghost_layer % m_num_mng->pattern()));
1985 // Comportement de l'AMR historique.
1986 gm->setNbGhostLayer(nb_ghost_layer * 2);
1987 mesh_modifier->setDynamic(true);
1988 mesh_modifier->updateGhostLayers();
1989 // Remet le nombre initial de couches de mailles fantômes
1990 gm->setNbGhostLayer(nb_ghost_layer);
1991 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1992 // ----------
1993
1994 // On récupère les uniqueIds des parents à créer.
1995 ENUMERATE_ (Cell, icell, m_mesh->allLevelCells(0)) {
1996 Cell cell = *icell;
1997
1998 Int64 parent_uid = m_num_mng->parentCellUniqueIdOfCell(cell);
1999
2000 // On évite les doublons.
2001 if (!cell_uid_to_create.contains(parent_uid)) {
2003 // On en profite pour sauvegarder les owners des futures mailles
2004 // qui seront les mêmes owners que les mailles enfants.
2007 }
2008 else {
2009 // Ça peut arriver si le partitionnement n'est pas adapté.
2011 ARCANE_FATAL("Pb owner");
2012 }
2013 }
2014
2015 // On doit sauvegarder les enfants des parents pour créer les connectivités
2016 // à la fin.
2018 }
2019
2020 // info() << cell_uid_to_create;
2021 // for (const auto& [key, value] : parent_to_child_cells) {
2022 // info() << "Parent : " << key << " -- Children : " << value;
2023 // }
2024
2025 UniqueArray<Int64> cells_infos;
2026 UniqueArray<Int64> faces_infos;
2028
2029 Integer total_nb_cells = 0;
2030 Integer total_nb_nodes = 0;
2031 Integer total_nb_faces = 0;
2032
2033 // Deux tableaux permettant de récupérer les uniqueIds des noeuds et des faces
2034 // de chaque maille parent à chaque appel à getNodeUids()/getFaceUids().
2035 UniqueArray<Int64> parent_nodes_uids(m_num_mng->nbNodeByCell());
2036 UniqueArray<Int64> parent_faces_uids(m_num_mng->nbFaceByCell());
2037
2038 // Partie échange d'informations sur les mailles autour du patch
2039 // (pour remplacer les mailles fantômes).
2040 {
2041 // Tableau qui contiendra les uids des mailles dont on a besoin des infos.
2043 {
2044 UniqueArray<Int64> cell_uids_around((m_mesh->dimension() == 2) ? 9 : 27);
2045 for (Int64 parent_cell : cell_uid_to_create) {
2046 m_num_mng->cellUniqueIdsAroundCell(cell_uids_around, parent_cell, -1);
2047 for (Int64 cell_uid : cell_uids_around) {
2048 // Si -1 alors il n'y a pas de mailles à cette position.
2049 if (cell_uid == -1)
2050 continue;
2051
2052 // TODO C++20 : Mettre map.contains().
2053 // SI on a la maille, on n'a pas besoin de demander d'infos.
2055 continue;
2056
2057 // TODO : Bof
2058 if (!uid_of_cells_needed.contains(cell_uid)) {
2059 uid_of_cells_needed.add(cell_uid);
2060
2061 // Si on a besoin des infos, c'est que l'on ne les possèdent pas :-)
2062 // On en profite pour enregistrer cette information pour distinguer les
2063 // mailles fantômes dont on possède les items (faces/noeuds) de celle dont
2064 // on ne possède rien.
2066 }
2067 }
2068 }
2069 }
2070
2071 // On partage les cell uid nécessaires de tout le monde.
2074
2076
2077 {
2078 // On enregistre le propriétaire des mailles que l'on possède.
2079 for (Integer i = 0; i < uid_of_cells_needed_all_procs.size(); ++i) {
2082 }
2083 else {
2084 // Le ReduceMax fera disparaitre ce -1.
2086 }
2087 }
2088 }
2089
2090 // On récupère les owners de toutes les mailles nécessaires.
2091 pm->reduce(Parallel::eReduceType::ReduceMax, owner_of_cells_needed_all_procs);
2092
2093 // On ne traite que les owners des mailles nécessaires pour nous.
2094 {
2096 Integer my_pos_in_all_procs_arrays = 0;
2100
2101 // On zap les mailles de tous les procs avant nous.
2102 for (Integer i = 0; i < my_rank; ++i) {
2104 }
2105
2106 // On enregistre les owners nécessaires.
2108 for (Integer i = 0; i < size_uid_of_cells_needed; ++i) {
2110
2111 // En rafinnement, il peut y avoir plusieurs niveaux d'écarts entre les patchs.
2112 // En déraffinement, c'est impossible vu que le niveau 0 n'a pas de "trous".
2113 if (owner_of_cells_needed[i] == -1) {
2114 ARCANE_FATAL("En déraffinement, c'est normalement impossible");
2115 }
2116 }
2117 }
2118 }
2119
2120 if (m_mesh->dimension() == 2) {
2121
2122 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2123 // ou si on doit regarder la maille d'à côté avant (false).
2124 // Rappel que le parcours des faces par Arcane est dans l'ordre NumPad{2, 6, 8, 4}.
2125 const bool mask_face_if_cell_left[] = { true, true, true, false };
2126 const bool mask_face_if_cell_bottom[] = { false, true, true, true };
2127
2128 // Rappel que le parcours des nodes par Arcane est dans l'ordre NumPad{1, 3, 9, 7}.
2129 const bool mask_node_if_cell_left[] = { false, true, true, false };
2130 const bool mask_node_if_cell_bottom[] = { false, false, true, true };
2131
2132 // Pour le raffinement, on parcourait les mailles parents existantes.
2133 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2134 for (Int64 parent_cell_uid : cell_uid_to_create) {
2135
2137 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around, parent_cell_uid, -1);
2138
2141
2143 // Attention au "not" dans le nom de la variable.
2145
2146 for (Integer i = 0; i < 9; ++i) {
2147 Int64 uid_cell = cells_uid_around[i];
2148 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2149 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2153 }
2154 else {
2155 cells_uid_around[i] = -1;
2158 }
2159 }
2160
2161 // Ces deux lambdas sont différentes.
2162 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2163 // la première lambda répondra donc forcément true alors que la seconde false.
2164 auto is_cell_around_parent_cell_different_owner = [&](Integer y, Integer x) {
2166 };
2167
2168 auto is_cell_around_parent_cell_exist_and_different_owner = [&](Integer y, Integer x) {
2170 };
2171
2173 debug() << "Parent"
2174 << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2175 << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2176 << " -- level : " << -1
2177 << " -- uid : " << parent_cell_uid;
2178
2179 // On récupère les uniqueIds des nodes et faces à créer.
2180 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2181 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2182
2183 const Integer type_cell = IT_Quad4;
2184 const Integer type_face = IT_Line2;
2185
2186 // Partie Cell.
2187 cells_infos.add(type_cell);
2188 cells_infos.add(parent_cell_uid);
2189 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2190 cells_infos.add(parent_nodes_uids[nc]);
2191 }
2192
2193 // Partie Face.
2194 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2195 Integer parent_face_owner = -1;
2196
2197 // On regarde si l'on doit traiter la face.
2198 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2199 // ou si la maille à gauche est dans notre sous-domaine ou non.
2200 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2201 // on doit créer la face en tant que face fantôme.
2202 if (
2205 faces_infos.add(type_face);
2206 faces_infos.add(parent_faces_uids[l]);
2207
2208 // Les noeuds de la face sont toujours les noeuds l et l+1
2209 // car on utilise la même exploration pour les deux cas.
2210 for (Integer nc = l; nc < l + 2; nc++) {
2211 faces_infos.add(parent_nodes_uids[nc % m_num_mng->nbNodeByCell()]);
2212 }
2214
2217 }
2220 }
2221 else {
2223 }
2225 debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2226 << " -- level : " << -1
2227 << " -- face : " << l
2228 << " -- uid_face : " << parent_faces_uids[l]
2229 << " -- owner : " << parent_face_owner;
2230 }
2231 }
2232
2233 // Partie Node.
2234 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2235 // plus de propriétaires possibles.
2236 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2237 Integer parent_node_owner = -1;
2238 if (
2243
2244 if ((!mask_node_if_cell_left[l])) {
2245 if ((!mask_node_if_cell_bottom[l])) {
2248 }
2251 }
2254 }
2255 else {
2257 }
2258 }
2259 else {
2262 }
2263 else {
2265 }
2266 }
2267 }
2268 else {
2269 if ((!mask_node_if_cell_bottom[l])) {
2272 }
2275 }
2276 else {
2278 }
2279 }
2280 else {
2282 }
2283 }
2284
2286 debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2287 << " -- level : " << -1
2288 << " -- node : " << l
2289 << " -- uid_node : " << parent_nodes_uids[l]
2290 << " -- owner : " << parent_node_owner;
2291 }
2292 }
2293 }
2294 }
2295 else if (m_mesh->dimension() == 3) {
2296
2297 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2298 // ou si on doit regarder la maille d'à côté avant (false).
2299 const bool mask_node_if_cell_left[] = { false, true, true, false, false, true, true, false };
2300 const bool mask_node_if_cell_bottom[] = { false, false, true, true, false, false, true, true };
2301 const bool mask_node_if_cell_rear[] = { false, false, false, false, true, true, true, true };
2302
2303 const bool mask_face_if_cell_left[] = { true, false, true, true, true, true };
2304 const bool mask_face_if_cell_bottom[] = { true, true, false, true, true, true };
2305 const bool mask_face_if_cell_rear[] = { false, true, true, true, true, true };
2306
2307 // Petite différence par rapport au 2D. Pour le 2D, la position des noeuds des faces
2308 // dans le tableau "parent_nodes_uids" est toujours pareil (l et l+1, voir le 2D).
2309 // Pour le 3D, ce n'est pas le cas donc on a des tableaux pour avoir une correspondance
2310 // entre les noeuds de chaque face et la position des noeuds dans le tableau "parent_nodes_uids".
2311 // (Exemple : pour la face 1 (même ordre d'énumération qu'Arcane), on doit prendre le
2312 // tableau "nodes_in_face_1" et donc les noeuds "parent_nodes_uids[0]", "parent_nodes_uids[3]",
2313 // "parent_nodes_uids[7]" et "parent_nodes_uids[4]").
2314 const Integer nodes_in_face_0[] = { 0, 1, 2, 3 };
2315 const Integer nodes_in_face_1[] = { 0, 3, 7, 4 };
2316 const Integer nodes_in_face_2[] = { 0, 1, 5, 4 };
2317 const Integer nodes_in_face_3[] = { 4, 5, 6, 7 };
2318 const Integer nodes_in_face_4[] = { 1, 2, 6, 5 };
2319 const Integer nodes_in_face_5[] = { 3, 2, 6, 7 };
2320
2321 const Integer nb_nodes_in_face = 4;
2322
2323 // Pour le raffinement, on parcourait les mailles parents existantes.
2324 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2325 for (Int64 parent_cell_uid : cell_uid_to_create) {
2326
2328 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around, parent_cell_uid, -1);
2329
2332
2334 // Attention au "not" dans le nom de la variable.
2336
2337 for (Integer i = 0; i < 27; ++i) {
2338 Int64 uid_cell = cells_uid_around[i];
2339 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2340 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2344 }
2345 else {
2346 cells_uid_around[i] = -1;
2349 }
2350 }
2351
2352 // Ces deux lambdas sont différentes.
2353 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2354 // la première lambda répondra donc forcément true alors que la seconde false.
2355 auto is_cell_around_parent_cell_different_owner = [&](Integer z, Integer y, Integer x) {
2357 };
2358
2359 auto is_cell_around_parent_cell_exist_and_different_owner = [&](Integer z, Integer y, Integer x) {
2361 };
2362
2364 debug() << "Parent"
2365 << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2366 << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2367 << " -- z : " << m_num_mng->cellUniqueIdToCoordZ(parent_cell_uid, -1)
2368 << " -- level : " << -1
2369 << " -- uid : " << parent_cell_uid;
2370
2371 // On récupère les uniqueIds des nodes et faces à créer.
2372 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2373 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2374
2375 const Integer type_cell = IT_Hexaedron8;
2376 const Integer type_face = IT_Quad4;
2377
2378 // Partie Cell.
2379 cells_infos.add(type_cell);
2380 cells_infos.add(parent_cell_uid);
2381 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2382 cells_infos.add(parent_nodes_uids[nc]);
2383 }
2384
2385 // Partie Face.
2386 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2387 Integer parent_face_owner = -1;
2388
2389 // On regarde si l'on doit traiter la face.
2390 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2391 // ou si la maille à gauche est dans notre sous-domaine ou non.
2392 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2393 // on doit créer la face en tant que face fantôme.
2394 if (
2398 faces_infos.add(type_face);
2399 faces_infos.add(parent_faces_uids[l]);
2400
2401 // On récupère la position des noeuds de la face dans le tableau "ua_node_uid".
2403 switch (l) {
2404 case 0:
2406 break;
2407 case 1:
2409 break;
2410 case 2:
2412 break;
2413 case 3:
2415 break;
2416 case 4:
2418 break;
2419 case 5:
2421 break;
2422 default:
2423 ARCANE_FATAL("Bizarre...");
2424 }
2425 for (Integer nc : nodes_in_face_l) {
2426 faces_infos.add(parent_nodes_uids[nc]);
2427 }
2429
2432 }
2435 }
2438 }
2439 else {
2441 }
2443 debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2444 << " -- level : " << -1
2445 << " -- face : " << l
2446 << " -- uid_face : " << parent_faces_uids[l]
2447 << " -- owner : " << parent_face_owner;
2448 }
2449 }
2450
2451 // Partie Node.
2452 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2453 // plus de propriétaires possibles.
2454 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2455 Integer parent_node_owner = -1;
2456 if (
2462
2463 if ((!mask_node_if_cell_left[l])) {
2464 if ((!mask_node_if_cell_bottom[l])) {
2465 if ((!mask_node_if_cell_rear[l])) {
2466
2469 }
2472 }
2475 }
2478 }
2481 }
2484 }
2487 }
2488 else {
2490 }
2491 }
2492 else {
2495 }
2498 }
2501 }
2502 else {
2504 }
2505 }
2506 }
2507 else {
2508 if ((!mask_node_if_cell_rear[l])) {
2511 }
2514 }
2517 }
2520 }
2523 }
2524 else {
2526 }
2527 }
2528 else {
2531 }
2532 else {
2534 }
2535 }
2536 }
2537 }
2538 else {
2539 if ((!mask_node_if_cell_bottom[l])) {
2540 if ((!mask_node_if_cell_rear[l])) {
2543 }
2546 }
2549 }
2552 }
2555 }
2558 }
2559 else {
2561 }
2562 }
2563 else {
2566 }
2569 }
2570 else {
2572 }
2573 }
2574 }
2575 else {
2576 if ((!mask_node_if_cell_rear[l])) {
2579 }
2582 }
2585 }
2588 }
2589 else {
2591 }
2592 }
2593 else {
2595 }
2596 }
2597 }
2598
2600 debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2601 << " -- level : " << -1
2602 << " -- node : " << l
2603 << " -- uid_node : " << parent_nodes_uids[l]
2604 << " -- owner : " << parent_node_owner;
2605 }
2606 }
2607 }
2608 }
2609 else {
2610 ARCANE_FATAL("Bad dimension");
2611 }
2612
2613 // Nodes
2614 {
2615 debug() << "Nb new nodes in patch : " << total_nb_nodes;
2616 {
2617 // Ce tableau contiendra les localIds des nouveaux noeuds.
2619
2620 // On crée les noeuds. On met les localIds des nouveaux noeuds au début du tableau.
2621 m_mesh->modifier()->addNodes(nodes_infos, nodes_lid);
2622
2625 Integer index = 0;
2626
2627 // On attribue les bons propriétaires aux noeuds.
2628 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2629 Node node = *inode;
2630
2631 ARCANE_ASSERT((node_uid_to_owner.find(node.uniqueId()) != node_uid_to_owner.end()), ("No owner found for node"));
2632 ARCANE_ASSERT((node_uid_to_owner[node.uniqueId()] < nb_rank && node_uid_to_owner[node.uniqueId()] >= 0), ("Bad owner found for node"));
2633
2635
2636 if (node_uid_to_owner[node.uniqueId()] == my_rank) {
2637 node.mutableItemBase().addFlags(ItemFlags::II_Own);
2638 }
2639
2640 uid_child_nodes[index++] = m_num_mng->childNodeUniqueIdOfNode(node.uniqueId(), -1);
2641 }
2642 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(lid_child_nodes, uid_child_nodes, false);
2643 NodeInfoListView nodes(m_mesh->nodeFamily());
2644
2645 index = 0;
2646 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2647 const Int32 child_lid = lid_child_nodes[index++];
2648 if (child_lid == NULL_ITEM_ID) {
2649 continue;
2650 }
2651
2652 Node child = nodes[child_lid];
2653 Node parent = *inode;
2654
2655 m_mesh->modifier()->addParentNodeToNode(child, parent);
2656 m_mesh->modifier()->addChildNodeToNode(parent, child);
2657 }
2658 }
2659
2660 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2661 }
2662
2663 // Faces
2664 {
2665 debug() << "Nb new faces in patch : " << total_nb_faces;
2666 {
2667 Integer nb_child = (m_mesh->dimension() == 2 ? 2 : 4);
2669
2670 m_mesh->modifier()->addFaces(total_nb_faces, faces_infos, faces_lid);
2671
2672 UniqueArray<Int64> uid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2673 UniqueArray<Int32> lid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2674 Integer index = 0;
2675
2676 // On attribue les bons propriétaires aux faces.
2677 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2678 Face face = *iface;
2679
2680 ARCANE_ASSERT((face_uid_to_owner.find(face.uniqueId()) != face_uid_to_owner.end()), ("No owner found for face"));
2681 ARCANE_ASSERT((face_uid_to_owner[face.uniqueId()] < nb_rank && face_uid_to_owner[face.uniqueId()] >= 0), ("Bad owner found for face"));
2682
2684
2685 if (face_uid_to_owner[face.uniqueId()] == my_rank) {
2686 face.mutableItemBase().addFlags(ItemFlags::II_Own);
2687 }
2688
2689 for (Integer i = 0; i < nb_child; ++i) {
2690 uid_child_faces[index++] = m_num_mng->childFaceUniqueIdOfFace(face.uniqueId(), -1, i);
2691 }
2692 }
2693
2694 m_mesh->faceFamily()->itemsUniqueIdToLocalId(lid_child_faces, uid_child_faces, false);
2695 FaceInfoListView faces(m_mesh->faceFamily());
2696
2697 index = 0;
2698 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2699 for (Integer i = 0; i < nb_child; ++i) {
2700 const Int32 child_lid = lid_child_faces[index++];
2701 if (child_lid == NULL_ITEM_ID) {
2702 continue;
2703 }
2704
2705 Face child = faces[child_lid];
2706 Face parent = *iface;
2707
2708 m_mesh->modifier()->addParentFaceToFace(child, parent);
2709 m_mesh->modifier()->addChildFaceToFace(parent, child);
2710 }
2711 }
2712 }
2713
2714 m_mesh->faceFamily()->notifyItemsOwnerChanged();
2715 }
2716
2717 // Cells
2719 {
2720 debug() << "Nb new cells in patch : " << total_nb_cells;
2721
2722 m_mesh->modifier()->addCells(total_nb_cells, cells_infos, cells_lid);
2723
2724 // Itération sur les nouvelles mailles.
2725 CellInfoListView cells(m_mesh->cellFamily());
2726 for (Integer i = 0; i < total_nb_cells; ++i) {
2727 Cell parent = cells[cells_lid[i]];
2728
2730
2731 parent.mutableItemBase().addFlags(ItemFlags::II_JustAdded);
2732 parent.mutableItemBase().addFlags(ItemFlags::II_JustCoarsened);
2733 parent.mutableItemBase().addFlags(ItemFlags::II_Inactive);
2734
2736 parent.mutableItemBase().addFlags(ItemFlags::II_Own);
2737 }
2738 if (parent_to_child_cells[parent.uniqueId()][0].itemBase().flags() & ItemFlags::II_Shared) {
2739 parent.mutableItemBase().addFlags(ItemFlags::II_Shared);
2740 }
2741 for (Cell child : parent_to_child_cells[parent.uniqueId()]) {
2742 m_mesh->modifier()->addParentCellToCell(child, parent);
2743 m_mesh->modifier()->addChildCellToCell(parent, child);
2744 }
2745 }
2746 m_mesh->cellFamily()->notifyItemsOwnerChanged();
2747 }
2748
2749 m_mesh->modifier()->endUpdate();
2750 m_num_mng->updateFirstLevel();
2751
2752 // On positionne les noeuds dans l'espace.
2753 CellInfoListView cells(m_mesh->cellFamily());
2754 for (Integer i = 0; i < total_nb_cells; ++i) {
2755 Cell parent_cell = cells[cells_lid[i]];
2756 m_num_mng->setParentNodeCoordinates(parent_cell);
2757
2758 // On ajoute le flag "II_Shared" aux noeuds et aux faces des mailles partagées.
2759 if (parent_cell.mutableItemBase().flags() & ItemFlags::II_Shared) {
2760 for (Node node : parent_cell.nodes()) {
2761 if (node.mutableItemBase().flags() & ItemFlags::II_Own) {
2762 node.mutableItemBase().addFlags(ItemFlags::II_Shared);
2763 }
2764 }
2765 for (Face face : parent_cell.faces()) {
2766 if (face.mutableItemBase().flags() & ItemFlags::II_Own) {
2767 face.mutableItemBase().addFlags(ItemFlags::II_Shared);
2768 }
2769 }
2770 }
2771 }
2772
2774 {
2775 CellGroup parent_cells = m_mesh->allLevelCells(0);
2776 m_cmesh->_internalApi()->addPatchFromExistingChildren(parent_cells.view().localIds());
2777 }
2778
2779 // Recalcule les informations de synchronisation
2780 // Cela n'est pas nécessaire pour l'AMR car ces informations seront recalculées
2781 // lors du raffinement mais comme on ne sais pas si on va faire du raffinement
2782 // après il est préférable de calculer ces informations dans tous les cas.
2783 m_mesh->computeSynchronizeInfos();
2784
2785 // Il faut recalculer les nouvelles directions après les modifications
2786 // et l'ajout de patch.
2787 m_cmesh->computeDirections();
2788
2789 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
2790 // debug() << "\t" << *icell;
2791 // for(Node node : icell->nodes()){
2792 // debug() << "\t\t" << node;
2793 // }
2794 // for(Face face : icell->faces()){
2795 // debug() << "\t\t\t" << face;
2796 // }
2797 // }
2798 // info() << "Résumé :";
2799 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
2800 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
2801 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
2802 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
2803 // }
2804 // }
2805 // info() << "Résumé node:";
2806 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
2807 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
2808 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
2809 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
2810 // }
2811 // }
2812 //
2813 // info() << "Résumé face:";
2814 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
2815 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
2816 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
2817 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
2818 // }
2819 // }
2820}
2821
2822/*---------------------------------------------------------------------------*/
2823/*---------------------------------------------------------------------------*/
2824
2825} // End namespace Arcane
2826
2827/*---------------------------------------------------------------------------*/
2828/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1191
Int32 level() const
Definition Item.h:1342
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:944
Interface de modification du maillage.
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é
Vue sur une liste pour obtenir des informations sur les entités.
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
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
void setFlags(Int32 f)
Positionne les flags de l'entité
void addFlags(Int32 added_flags)
Ajoute les flags \added_flags à ceux de l'entité
void removeFlags(Int32 removed_flags)
Supprime les flags \added_flags de ceux de l'entité
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:573
Paramètres nécessaires à la construction d'une variable.
Classe gérant un vecteur de dimension 2 de type T.
Definition Vector2.h:36
Vue constante d'un tableau de type T.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Espace de nom de Arccore.
Definition ArcaneTypes.h:29
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.