Arcane  v3.14.10.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-2024 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-2024 */
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
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.
441 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); 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;
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.
971 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); 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;
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) {
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 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
1908 // debug() << "\t" << *icell;
1909 // for(Node node : icell->nodes()){
1910 // debug() << "\t\t" << node;
1911 // }
1912 // for(Face face : icell->faces()){
1913 // debug() << "\t\t\t" << face;
1914 // }
1915 // }
1916 // info() << "Résumé :";
1917 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
1918 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
1919 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
1920 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
1921 // }
1922 // }
1923 // info() << "Résumé node:";
1924 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
1925 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
1926 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
1927 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
1928 // }
1929 // }
1930 //
1931 // info() << "Résumé :";
1932 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
1933 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
1934 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
1935 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
1936 // }
1937 // }
1938}
1939
1940/*---------------------------------------------------------------------------*/
1941/*---------------------------------------------------------------------------*/
1942
1943void CartesianMeshAMRPatchMng::
1944coarse()
1945{
1946 IParallelMng* pm = m_mesh->parallelMng();
1947 Int32 nb_rank = pm->commSize();
1948 Int32 my_rank = pm->commRank();
1949
1951
1952 // TODO : Remplacer around_parent_cells_uid_to_owner par parent_to_child_cells ?
1953 std::unordered_map<Int64, Int32> around_parent_cells_uid_to_owner;
1954 std::unordered_map<Int64, bool> around_parent_cells_uid_is_in_subdomain;
1955 std::unordered_map<Int64, UniqueArray<Cell>> parent_to_child_cells;
1956
1957 std::unordered_map<Int64, Int32> node_uid_to_owner;
1958 std::unordered_map<Int64, Int32> face_uid_to_owner;
1959
1960 // On va créer le niveau -1.
1961 // À noter qu'à la fin de la méthode, on replacera ce niveau
1962 // à 0.
1963 m_num_mng->prepareLevel(-1);
1964
1965 // On crée une ou plusieurs couches de mailles fantômes
1966 // pour éviter qu'une maille parente n'ai pas le même
1967 // nombre de mailles enfant.
1968 // ----------
1969 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1970 IMeshModifier* mesh_modifier = m_mesh->modifier();
1971 IGhostLayerMng* gm = m_mesh->ghostLayerMng();
1972 // Il faut au moins utiliser la version 3 pour pouvoir supporter
1973 // plusieurs couches de mailles fantômes
1974 Int32 version = gm->builderVersion();
1975 if (version < 3)
1976 gm->setBuilderVersion(3);
1977 Int32 nb_ghost_layer = gm->nbGhostLayer();
1978 gm->setNbGhostLayer(nb_ghost_layer + (nb_ghost_layer % m_num_mng->pattern()));
1979 mesh_modifier->setDynamic(true);
1980 mesh_modifier->updateGhostLayers();
1981 // Remet le nombre initial de couches de mailles fantômes
1982 gm->setNbGhostLayer(nb_ghost_layer);
1983 // CartesianMeshCoarsening2::_doDoubleGhostLayers()
1984 // ----------
1985
1986 // On récupère les uniqueIds des parents à créer.
1987 ENUMERATE_ (Cell, icell, m_mesh->allLevelCells(0)) {
1988 Cell cell = *icell;
1989
1990 Int64 parent_uid = m_num_mng->parentCellUniqueIdOfCell(cell);
1991
1992 // On évite les doublons.
1993 if (!cell_uid_to_create.contains(parent_uid)) {
1995 // On en profite pour sauvegarder les owners des futures mailles
1996 // qui seront les mêmes owners que les mailles enfants.
1999 }
2000 else {
2001 // Ça peut arriver si le partitionnement n'est pas adapté.
2003 ARCANE_FATAL("Pb owner");
2004 }
2005 }
2006
2007 // On doit sauvegarder les enfants des parents pour créer les connectivités
2008 // à la fin.
2010 }
2011
2012 // info() << cell_uid_to_create;
2013 // for (const auto& [key, value] : parent_to_child_cells) {
2014 // info() << "Parent : " << key << " -- Children : " << value;
2015 // }
2016
2020
2021 Integer total_nb_cells = 0;
2022 Integer total_nb_nodes = 0;
2023 Integer total_nb_faces = 0;
2024
2025 // Deux tableaux permettant de récupérer les uniqueIds des noeuds et des faces
2026 // de chaque maille parent à chaque appel à getNodeUids()/getFaceUids().
2027 UniqueArray<Int64> parent_nodes_uids(m_num_mng->nbNodeByCell());
2028 UniqueArray<Int64> parent_faces_uids(m_num_mng->nbFaceByCell());
2029
2030 // Partie échange d'informations sur les mailles autour du patch
2031 // (pour remplacer les mailles fantômes).
2032 {
2033 // Tableau qui contiendra les uids des mailles dont on a besoin des infos.
2035 {
2036 UniqueArray<Int64> cell_uids_around((m_mesh->dimension() == 2) ? 9 : 27);
2037 for (Int64 parent_cell : cell_uid_to_create) {
2038 m_num_mng->cellUniqueIdsAroundCell(cell_uids_around, parent_cell, -1);
2039 for (Int64 cell_uid : cell_uids_around) {
2040 // Si -1 alors il n'y a pas de mailles à cette position.
2041 if (cell_uid == -1)
2042 continue;
2043
2044 // TODO C++20 : Mettre map.contains().
2045 // SI on a la maille, on n'a pas besoin de demander d'infos.
2047 continue;
2048
2049 // TODO : Bof
2050 if (!uid_of_cells_needed.contains(cell_uid)) {
2051 uid_of_cells_needed.add(cell_uid);
2052
2053 // Si on a besoin des infos, c'est que l'on ne les possèdent pas :-)
2054 // On en profite pour enregistrer cette information pour distinguer les
2055 // mailles fantômes dont on possède les items (faces/noeuds) de celle dont
2056 // on ne possède rien.
2058 }
2059 }
2060 }
2061 }
2062
2063 // On partage les cell uid nécessaires de tout le monde.
2066
2068
2069 {
2070 // On enregistre le propriétaire des mailles que l'on possède.
2071 for (Integer i = 0; i < uid_of_cells_needed_all_procs.size(); ++i) {
2074 }
2075 else {
2076 // Le ReduceMax fera disparaitre ce -1.
2078 }
2079 }
2080 }
2081
2082 // On récupère les owners de toutes les mailles nécessaires.
2083 pm->reduce(Parallel::eReduceType::ReduceMax, owner_of_cells_needed_all_procs);
2084
2085 // On ne traite que les owners des mailles nécessaires pour nous.
2086 {
2088 Integer my_pos_in_all_procs_arrays = 0;
2092
2093 // On zap les mailles de tous les procs avant nous.
2094 for (Integer i = 0; i < my_rank; ++i) {
2096 }
2097
2098 // On enregistre les owners nécessaires.
2100 for (Integer i = 0; i < size_uid_of_cells_needed; ++i) {
2102
2103 // En rafinnement, il peut y avoir plusieurs niveaux d'écarts entre les patchs.
2104 // En déraffinement, c'est impossible vu que le niveau 0 n'a pas de "trous".
2105 if (owner_of_cells_needed[i] == -1) {
2106 ARCANE_FATAL("En déraffinement, c'est normalement impossible");
2107 }
2108 }
2109 }
2110 }
2111
2112 if (m_mesh->dimension() == 2) {
2113
2114 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2115 // ou si on doit regarder la maille d'à côté avant (false).
2116 // Rappel que le parcours des faces par Arcane est dans l'ordre NumPad{2, 6, 8, 4}.
2117 const bool mask_face_if_cell_left[] = { true, true, true, false };
2118 const bool mask_face_if_cell_bottom[] = { false, true, true, true };
2119
2120 // Rappel que le parcours des nodes par Arcane est dans l'ordre NumPad{1, 3, 9, 7}.
2121 const bool mask_node_if_cell_left[] = { false, true, true, false };
2122 const bool mask_node_if_cell_bottom[] = { false, false, true, true };
2123
2124 // Pour le raffinement, on parcourait les mailles parents existantes.
2125 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2126 for (Int64 parent_cell_uid : cell_uid_to_create) {
2127
2129 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around, parent_cell_uid, -1);
2130
2133
2135 // Attention au "not" dans le nom de la variable.
2137
2138 for (Integer i = 0; i < 9; ++i) {
2139 Int64 uid_cell = cells_uid_around[i];
2140 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2141 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2145 }
2146 else {
2147 cells_uid_around[i] = -1;
2150 }
2151 }
2152
2153 // Ces deux lambdas sont différentes.
2154 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2155 // la première lambda répondra donc forcément true alors que la seconde false.
2156 auto is_cell_around_parent_cell_different_owner = [&](Integer y, Integer x) {
2158 };
2159
2160 auto is_cell_around_parent_cell_exist_and_different_owner = [&](Integer y, Integer x) {
2162 };
2163
2165 debug() << "Parent"
2166 << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2167 << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2168 << " -- level : " << -1
2169 << " -- uid : " << parent_cell_uid;
2170
2171 // On récupère les uniqueIds des nodes et faces à créer.
2172 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2173 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2174
2175 const Integer type_cell = IT_Quad4;
2176 const Integer type_face = IT_Line2;
2177
2178 // Partie Cell.
2181 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2183 }
2184
2185 // Partie Face.
2186 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2187 Integer parent_face_owner = -1;
2188
2189 // On regarde si l'on doit traiter la face.
2190 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2191 // ou si la maille à gauche est dans notre sous-domaine ou non.
2192 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2193 // on doit créer la face en tant que face fantôme.
2194 if (
2199
2200 // Les noeuds de la face sont toujours les noeuds l et l+1
2201 // car on utilise la même exploration pour les deux cas.
2202 for (Integer nc = l; nc < l + 2; nc++) {
2203 faces_infos.add(parent_nodes_uids[nc % m_num_mng->nbNodeByCell()]);
2204 }
2206
2209 }
2212 }
2213 else {
2215 }
2217 debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2218 << " -- level : " << -1
2219 << " -- face : " << l
2220 << " -- uid_face : " << parent_faces_uids[l]
2221 << " -- owner : " << parent_face_owner;
2222 }
2223 }
2224
2225 // Partie Node.
2226 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2227 // plus de propriétaires possibles.
2228 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2229 Integer parent_node_owner = -1;
2230 if (
2235
2236 if ((!mask_node_if_cell_left[l])) {
2237 if ((!mask_node_if_cell_bottom[l])) {
2240 }
2243 }
2246 }
2247 else {
2249 }
2250 }
2251 else {
2254 }
2255 else {
2257 }
2258 }
2259 }
2260 else {
2261 if ((!mask_node_if_cell_bottom[l])) {
2264 }
2267 }
2268 else {
2270 }
2271 }
2272 else {
2274 }
2275 }
2276
2278 debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2279 << " -- level : " << -1
2280 << " -- node : " << l
2281 << " -- uid_node : " << parent_nodes_uids[l]
2282 << " -- owner : " << parent_node_owner;
2283 }
2284 }
2285 }
2286 }
2287 else if (m_mesh->dimension() == 3) {
2288
2289 // Masques permettant de savoir si on doit créer une faces/noeuds (true)
2290 // ou si on doit regarder la maille d'à côté avant (false).
2291 const bool mask_node_if_cell_left[] = { false, true, true, false, false, true, true, false };
2292 const bool mask_node_if_cell_bottom[] = { false, false, true, true, false, false, true, true };
2293 const bool mask_node_if_cell_rear[] = { false, false, false, false, true, true, true, true };
2294
2295 const bool mask_face_if_cell_left[] = { true, false, true, true, true, true };
2296 const bool mask_face_if_cell_bottom[] = { true, true, false, true, true, true };
2297 const bool mask_face_if_cell_rear[] = { false, true, true, true, true, true };
2298
2299 // Petite différence par rapport au 2D. Pour le 2D, la position des noeuds des faces
2300 // dans le tableau "parent_nodes_uids" est toujours pareil (l et l+1, voir le 2D).
2301 // Pour le 3D, ce n'est pas le cas donc on a des tableaux pour avoir une correspondance
2302 // entre les noeuds de chaque face et la position des noeuds dans le tableau "parent_nodes_uids".
2303 // (Exemple : pour la face 1 (même ordre d'énumération qu'Arcane), on doit prendre le
2304 // tableau "nodes_in_face_1" et donc les noeuds "parent_nodes_uids[0]", "parent_nodes_uids[3]",
2305 // "parent_nodes_uids[7]" et "parent_nodes_uids[4]").
2306 const Integer nodes_in_face_0[] = { 0, 1, 2, 3 };
2307 const Integer nodes_in_face_1[] = { 0, 3, 7, 4 };
2308 const Integer nodes_in_face_2[] = { 0, 1, 5, 4 };
2309 const Integer nodes_in_face_3[] = { 4, 5, 6, 7 };
2310 const Integer nodes_in_face_4[] = { 1, 2, 6, 5 };
2311 const Integer nodes_in_face_5[] = { 3, 2, 6, 7 };
2312
2313 const Integer nb_nodes_in_face = 4;
2314
2315 // Pour le raffinement, on parcourait les mailles parents existantes.
2316 // Ici, les mailles parents n'existent pas encore, donc on parcours les uid.
2317 for (Int64 parent_cell_uid : cell_uid_to_create) {
2318
2320 m_num_mng->cellUniqueIdsAroundCell(cells_uid_around, parent_cell_uid, -1);
2321
2324
2326 // Attention au "not" dans le nom de la variable.
2328
2329 for (Integer i = 0; i < 27; ++i) {
2330 Int64 uid_cell = cells_uid_around[i];
2331 // Si uid_cell != -1 alors il y a peut-être une maille (mais on ne sait pas si elle est bien présente).
2332 // Si around_parent_cells_uid_to_owner[uid_cell] != -1 alors il y a bien une maille.
2336 }
2337 else {
2338 cells_uid_around[i] = -1;
2341 }
2342 }
2343
2344 // Ces deux lambdas sont différentes.
2345 // Quand une parent_cell n'existe pas, il y a -1 dans le tableau adéquat,
2346 // la première lambda répondra donc forcément true alors que la seconde false.
2347 auto is_cell_around_parent_cell_different_owner = [&](Integer z, Integer y, Integer x) {
2349 };
2350
2351 auto is_cell_around_parent_cell_exist_and_different_owner = [&](Integer z, Integer y, Integer x) {
2353 };
2354
2356 debug() << "Parent"
2357 << " -- x : " << m_num_mng->cellUniqueIdToCoordX(parent_cell_uid, -1)
2358 << " -- y : " << m_num_mng->cellUniqueIdToCoordY(parent_cell_uid, -1)
2359 << " -- z : " << m_num_mng->cellUniqueIdToCoordZ(parent_cell_uid, -1)
2360 << " -- level : " << -1
2361 << " -- uid : " << parent_cell_uid;
2362
2363 // On récupère les uniqueIds des nodes et faces à créer.
2364 m_num_mng->cellNodeUniqueIds(parent_nodes_uids, -1, parent_cell_uid);
2365 m_num_mng->cellFaceUniqueIds(parent_faces_uids, -1, parent_cell_uid);
2366
2367 const Integer type_cell = IT_Hexaedron8;
2368 const Integer type_face = IT_Quad4;
2369
2370 // Partie Cell.
2373 for (Integer nc = 0; nc < m_num_mng->nbNodeByCell(); nc++) {
2375 }
2376
2377 // Partie Face.
2378 for (Integer l = 0; l < m_num_mng->nbFaceByCell(); ++l) {
2379 Integer parent_face_owner = -1;
2380
2381 // On regarde si l'on doit traiter la face.
2382 // Si mask_face_if_cell_left[l] == false, on doit regarder si la maille à gauche est à nous ou non
2383 // ou si la maille à gauche est dans notre sous-domaine ou non.
2384 // Si cette maille n'est pas à nous et/ou n'est pas sur notre sous-domaine,
2385 // on doit créer la face en tant que face fantôme.
2386 if (
2392
2393 // On récupère la position des noeuds de la face dans le tableau "ua_node_uid".
2395 switch (l) {
2396 case 0:
2398 break;
2399 case 1:
2401 break;
2402 case 2:
2404 break;
2405 case 3:
2407 break;
2408 case 4:
2410 break;
2411 case 5:
2413 break;
2414 default:
2415 ARCANE_FATAL("Bizarre...");
2416 }
2417 for (Integer nc : nodes_in_face_l) {
2419 }
2421
2424 }
2427 }
2430 }
2431 else {
2433 }
2435 debug() << "Parent face (create face) -- parent_cell_uid : " << parent_cell_uid
2436 << " -- level : " << -1
2437 << " -- face : " << l
2438 << " -- uid_face : " << parent_faces_uids[l]
2439 << " -- owner : " << parent_face_owner;
2440 }
2441 }
2442
2443 // Partie Node.
2444 // Cette partie est assez ressemblante à la partie face, mis à part le fait qu'il peut y avoir
2445 // plus de propriétaires possibles.
2446 for (Integer l = 0; l < m_num_mng->nbNodeByCell(); ++l) {
2447 Integer parent_node_owner = -1;
2448 if (
2454
2455 if ((!mask_node_if_cell_left[l])) {
2456 if ((!mask_node_if_cell_bottom[l])) {
2457 if ((!mask_node_if_cell_rear[l])) {
2458
2461 }
2464 }
2467 }
2470 }
2473 }
2476 }
2479 }
2480 else {
2482 }
2483 }
2484 else {
2487 }
2490 }
2493 }
2494 else {
2496 }
2497 }
2498 }
2499 else {
2500 if ((!mask_node_if_cell_rear[l])) {
2503 }
2506 }
2509 }
2512 }
2515 }
2516 else {
2518 }
2519 }
2520 else {
2523 }
2524 else {
2526 }
2527 }
2528 }
2529 }
2530 else {
2531 if ((!mask_node_if_cell_bottom[l])) {
2532 if ((!mask_node_if_cell_rear[l])) {
2535 }
2538 }
2541 }
2544 }
2547 }
2550 }
2551 else {
2553 }
2554 }
2555 else {
2558 }
2561 }
2562 else {
2564 }
2565 }
2566 }
2567 else {
2568 if ((!mask_node_if_cell_rear[l])) {
2571 }
2574 }
2577 }
2580 }
2581 else {
2583 }
2584 }
2585 else {
2587 }
2588 }
2589 }
2590
2592 debug() << "Parent node (create node) -- parent_cell_uid : " << parent_cell_uid
2593 << " -- level : " << -1
2594 << " -- node : " << l
2595 << " -- uid_node : " << parent_nodes_uids[l]
2596 << " -- owner : " << parent_node_owner;
2597 }
2598 }
2599 }
2600 }
2601 else {
2602 ARCANE_FATAL("Bad dimension");
2603 }
2604
2605 // Nodes
2606 {
2607 debug() << "Nb new nodes in patch : " << total_nb_nodes;
2608 {
2609 // Ce tableau contiendra les localIds des nouveaux noeuds.
2611
2612 // On crée les noeuds. On met les localIds des nouveaux noeuds au début du tableau.
2613 m_mesh->modifier()->addNodes(nodes_infos, nodes_lid);
2614
2617 Integer index = 0;
2618
2619 // On attribue les bons propriétaires aux noeuds.
2620 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2621 Node node = *inode;
2622
2623 ARCANE_ASSERT((node_uid_to_owner.find(node.uniqueId()) != node_uid_to_owner.end()), ("No owner found for node"));
2624 ARCANE_ASSERT((node_uid_to_owner[node.uniqueId()] < nb_rank && node_uid_to_owner[node.uniqueId()] >= 0), ("Bad owner found for node"));
2625
2627
2628 if (node_uid_to_owner[node.uniqueId()] == my_rank) {
2629 node.mutableItemBase().addFlags(ItemFlags::II_Own);
2630 }
2631
2632 uid_child_nodes[index++] = m_num_mng->childNodeUniqueIdOfNode(node.uniqueId(), -1);
2633 }
2634 m_mesh->nodeFamily()->itemsUniqueIdToLocalId(lid_child_nodes, uid_child_nodes, false);
2635 NodeInfoListView nodes(m_mesh->nodeFamily());
2636
2637 index = 0;
2638 ENUMERATE_ (Node, inode, m_mesh->nodeFamily()->view(nodes_lid)) {
2639 const Int32 child_lid = lid_child_nodes[index++];
2640 if (child_lid == NULL_ITEM_ID) {
2641 continue;
2642 }
2643
2644 Node child = nodes[child_lid];
2645 Node parent = *inode;
2646
2647 m_mesh->modifier()->addParentNodeToNode(child, parent);
2648 m_mesh->modifier()->addChildNodeToNode(parent, child);
2649 }
2650 }
2651
2652 m_mesh->nodeFamily()->notifyItemsOwnerChanged();
2653 }
2654
2655 // Faces
2656 {
2657 debug() << "Nb new faces in patch : " << total_nb_faces;
2658 {
2659 Integer nb_child = (m_mesh->dimension() == 2 ? 2 : 4);
2661
2662 m_mesh->modifier()->addFaces(total_nb_faces, faces_infos, faces_lid);
2663
2664 UniqueArray<Int64> uid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2665 UniqueArray<Int32> lid_child_faces(total_nb_faces * m_num_mng->nbFaceByCell());
2666 Integer index = 0;
2667
2668 // On attribue les bons propriétaires aux faces.
2669 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2670 Face face = *iface;
2671
2672 ARCANE_ASSERT((face_uid_to_owner.find(face.uniqueId()) != face_uid_to_owner.end()), ("No owner found for face"));
2673 ARCANE_ASSERT((face_uid_to_owner[face.uniqueId()] < nb_rank && face_uid_to_owner[face.uniqueId()] >= 0), ("Bad owner found for face"));
2674
2676
2677 if (face_uid_to_owner[face.uniqueId()] == my_rank) {
2678 face.mutableItemBase().addFlags(ItemFlags::II_Own);
2679 }
2680
2681 for (Integer i = 0; i < nb_child; ++i) {
2682 uid_child_faces[index++] = m_num_mng->childFaceUniqueIdOfFace(face.uniqueId(), -1, i);
2683 }
2684 }
2685
2686 m_mesh->faceFamily()->itemsUniqueIdToLocalId(lid_child_faces, uid_child_faces, false);
2687 FaceInfoListView faces(m_mesh->faceFamily());
2688
2689 index = 0;
2690 ENUMERATE_ (Face, iface, m_mesh->faceFamily()->view(faces_lid)) {
2691 for (Integer i = 0; i < nb_child; ++i) {
2692 const Int32 child_lid = lid_child_faces[index++];
2693 if (child_lid == NULL_ITEM_ID) {
2694 continue;
2695 }
2696
2697 Face child = faces[child_lid];
2698 Face parent = *iface;
2699
2700 m_mesh->modifier()->addParentFaceToFace(child, parent);
2701 m_mesh->modifier()->addChildFaceToFace(parent, child);
2702 }
2703 }
2704 }
2705
2706 m_mesh->faceFamily()->notifyItemsOwnerChanged();
2707 }
2708
2709 // Cells
2711 {
2712 debug() << "Nb new cells in patch : " << total_nb_cells;
2713
2714 m_mesh->modifier()->addCells(total_nb_cells, cells_infos, cells_lid);
2715
2716 // Itération sur les nouvelles mailles.
2717 CellInfoListView cells(m_mesh->cellFamily());
2718 for (Integer i = 0; i < total_nb_cells; ++i) {
2719 Cell parent = cells[cells_lid[i]];
2720
2722
2723 parent.mutableItemBase().addFlags(ItemFlags::II_JustAdded);
2724 parent.mutableItemBase().addFlags(ItemFlags::II_JustCoarsened);
2725 parent.mutableItemBase().addFlags(ItemFlags::II_Inactive);
2726
2728 parent.mutableItemBase().addFlags(ItemFlags::II_Own);
2729 }
2730 if (parent_to_child_cells[parent.uniqueId()][0].itemBase().flags() & ItemFlags::II_Shared) {
2731 parent.mutableItemBase().addFlags(ItemFlags::II_Shared);
2732 }
2733 for (Cell child : parent_to_child_cells[parent.uniqueId()]) {
2734 m_mesh->modifier()->addParentCellToCell(child, parent);
2735 m_mesh->modifier()->addChildCellToCell(parent, child);
2736 }
2737 }
2738 m_mesh->cellFamily()->notifyItemsOwnerChanged();
2739 }
2740
2741 m_mesh->modifier()->endUpdate();
2742 m_num_mng->updateFirstLevel();
2743
2744 // On positionne les noeuds dans l'espace.
2745 CellInfoListView cells(m_mesh->cellFamily());
2746 for (Integer i = 0; i < total_nb_cells; ++i) {
2747 Cell parent_cell = cells[cells_lid[i]];
2748 m_num_mng->setParentNodeCoordinates(parent_cell);
2749
2750 // On ajoute le flag "II_Shared" aux noeuds et aux faces des mailles partagées.
2751 if (parent_cell.mutableItemBase().flags() & ItemFlags::II_Shared) {
2752 for (Node node : parent_cell.nodes()) {
2753 if (node.mutableItemBase().flags() & ItemFlags::II_Own) {
2754 node.mutableItemBase().addFlags(ItemFlags::II_Shared);
2755 }
2756 }
2757 for (Face face : parent_cell.faces()) {
2758 if (face.mutableItemBase().flags() & ItemFlags::II_Own) {
2759 face.mutableItemBase().addFlags(ItemFlags::II_Shared);
2760 }
2761 }
2762 }
2763 }
2764
2766 {
2767 CellGroup parent_cells = m_mesh->allLevelCells(0);
2768 m_cmesh->_internalApi()->addPatchFromExistingChildren(parent_cells.view().localIds());
2769 }
2770
2771 // Recalcule les informations de synchronisation
2772 // Cela n'est pas nécessaire pour l'AMR car ces informations seront recalculées
2773 // lors du raffinement mais comme on ne sais pas si on va faire du raffinement
2774 // après il est préférable de calculer ces informations dans tous les cas.
2775 m_mesh->computeSynchronizeInfos();
2776
2777 // Il faut recalculer les nouvelles directions après les modifications
2778 // et l'ajout de patch.
2779 m_cmesh->computeDirections();
2780
2781 // ENUMERATE_(Cell, icell, m_mesh->allCells()){
2782 // debug() << "\t" << *icell;
2783 // for(Node node : icell->nodes()){
2784 // debug() << "\t\t" << node;
2785 // }
2786 // for(Face face : icell->faces()){
2787 // debug() << "\t\t\t" << face;
2788 // }
2789 // }
2790 // info() << "Résumé :";
2791 // ENUMERATE_ (Cell, icell, m_mesh->allCells()) {
2792 // debug() << "\tCell uniqueId : " << icell->uniqueId() << " -- level : " << icell->level() << " -- nbChildren : " << icell->nbHChildren();
2793 // for (Integer i = 0; i < icell->nbHChildren(); ++i) {
2794 // debug() << "\t\tChild uniqueId : " << icell->hChild(i).uniqueId() << " -- level : " << icell->hChild(i).level() << " -- nbChildren : " << icell->hChild(i).nbHChildren();
2795 // }
2796 // }
2797 // info() << "Résumé node:";
2798 // ENUMERATE_ (Node, inode, m_mesh->allNodes()) {
2799 // debug() << "\tNode uniqueId : " << inode->uniqueId() << " -- level : " << inode->level() << " -- nbChildren : " << inode->nbHChildren();
2800 // for (Integer i = 0; i < inode->nbHChildren(); ++i) {
2801 // debug() << "\t\tNode Child uniqueId : " << inode->hChild(i).uniqueId() << " -- level : " << inode->hChild(i).level() << " -- nbChildren : " << inode->hChild(i).nbHChildren();
2802 // }
2803 // }
2804 //
2805 // info() << "Résumé face:";
2806 // ENUMERATE_ (Face, iface, m_mesh->allFaces()) {
2807 // debug() << "\tFace uniqueId : " << iface->uniqueId() << " -- level : " << iface->level() << " -- nbChildren : " << iface->nbHChildren();
2808 // for (Integer i = 0; i < iface->nbHChildren(); ++i) {
2809 // debug() << "\t\tChild uniqueId : " << iface->hChild(i).uniqueId() << " -- level : " << iface->hChild(i).level() << " -- nbChildren : " << iface->hChild(i).nbHChildren();
2810 // }
2811 // }
2812}
2813
2814/*---------------------------------------------------------------------------*/
2815/*---------------------------------------------------------------------------*/
2816
2817} // End namespace Arcane
2818
2819/*---------------------------------------------------------------------------*/
2820/*---------------------------------------------------------------------------*/
#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:1178
Int32 level() const
Definition Item.h:1328
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:932
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:365
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:229
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:216
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:354
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
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 Dom.h:204
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:24
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.