Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcaneBasicMeshSubdividerService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ArcaneBasicMeshSubdividerService.cc (C) 2000-2025 */
9/* */
10/* Service Arcane gérant un maillage du jeu de données. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14// get parameter
15#include "arcane/utils/ApplicationInfo.h"
16#include "arcane/utils/CommandLineArguments.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/MDDim.h"
19
20#include "arcane/core/IMeshSubdivider.h"
21#include "arcane/impl/ArcaneBasicMeshSubdividerService_axl.h"
22
23#include "arcane/core/ItemGroup.h"
24#include "arcane/core/ItemPrinter.h"
25#include "arcane/core/IItemFamily.h"
26#include "arcane/core/IGhostLayerMng.h"
28#include "arcane/core/IMeshModifier.h"
29
30#include "arcane/core/SimpleSVGMeshExporter.h" // Write au format svg pour le 2D
31// Write variables
32
33#include "arcane/core/ServiceBuilder.h"
34#include "arcane/core/Directory.h"
35#include "arcane/core/IVariableMng.h"
36#include "arcane/core/IParallelMng.h"
37#include "arcane/core/BasicService.h"
38#include "arcane/core/IPrimaryMesh.h"
39#include "arcane/core/Item.h"
40// Post processor
41#include "arcane/core/PostProcessorWriterBase.h"
42// Ajouter des variables
43#include "arcane/core/VariableBuildInfo.h"
44#include "arcane/core/IMeshUtilities.h"
45#include "arcane/core/ISubDomain.h"
46#include "arcane/cartesianmesh/ICartesianMesh.h"
47#include "arcane/core/Properties.h"
48#include "arcane/std/IMeshGenerator.h"
49
50// Utils
51#include <unordered_set>
52#include <algorithm>
53#include <iterator>
54#include <map>
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58
59namespace Arcane
60{
61
62typedef UniqueArray<UniqueArray<Int64>> StorageRefine;
63namespace MeshSubdivider
64{
65
66 /*---------------------------------------------------------------------------*/
67 /*---------------------------------------------------------------------------*/
71 class Pattern
72 {
73 public:
74
82 StorageRefine nodes;
84 StorageRefine faces;
86 StorageRefine cells;
87 StorageRefine child_faces; // Lien entre faces de la cellule mère et les faces de la cellule fille.
88 // ^-- Pour la gestion des groups ou des propriétés. Par exemple pour le sod, une face mère dans le groupe "membrane" doit engendrer des faces avec le même groupe.
89 // Les faces internes n'ont pas de face mère mais pourrait avoir besoin de propager ou déposer des propriétés sur ces faces.
90 // Pour l'instant elles ne sont juste pas dans les groupes.
91
92 // En fait les seules informations importantes sont dans 'cells' et 'nodes'. Arcane peut déduire les faces pour nous et on garde le même ordre pour le parallel.
93 // Pour les childs faces
94
95 public:
96
97 Pattern()
98 : type(IT_NullType)
99 , face_type(IT_NullType)
100 , cell_type(IT_NullType)
101 {}
102
103 Pattern(Int16 type, Int16 face_type, Int16 cell_type, StorageRefine nodes, StorageRefine faces, StorageRefine cells, StorageRefine child_faces)
104 {
105 this->type = type;
106 this->face_type = face_type;
107 this->cell_type = cell_type;
108 this->nodes = nodes;
109 this->faces = faces;
110 this->cells = cells;
111 this->child_faces = child_faces;
112 }
113
114 Pattern(Pattern&& other) noexcept
115 : type(other.type)
116 , face_type(other.face_type)
117 , cell_type(other.cell_type)
118 , nodes(other.nodes)
119 , faces(other.faces)
120 , cells(other.cells)
121 , child_faces(other.child_faces)
122 {}
123
124 Pattern(const Pattern&) = delete;
125
126 Pattern(Pattern& other) noexcept
127 : type(other.type)
128 , face_type(other.face_type)
129 , cell_type(other.cell_type)
130 , nodes(other.nodes)
131 , faces(other.faces)
132 , cells(other.cells)
133 , child_faces(other.child_faces)
134 {}
135 Pattern& operator=(const Pattern& other)
136 {
137 if (this != &other) {
138 type = other.type;
139 face_type = other.face_type;
140 cell_type = other.cell_type;
141 nodes = other.nodes; // Référence partagée
142 faces = other.faces; // Référence partagée
143 cells = other.cells; // Référence partagée
144 child_faces = other.child_faces;
145 }
146 return *this;
147 }
148
149 Pattern& operator=(Pattern&& other) noexcept
150 {
151 if (this != &other) {
152 type = other.type;
153 face_type = other.face_type;
154 cell_type = other.cell_type;
155 nodes = other.nodes;
156 faces = other.faces;
157 cells = other.cells;
158 child_faces = other.child_faces;
159 }
160 return *this;
161 }
162 Pattern& operator=(Pattern& other) noexcept
163 {
164 if (this != &other) {
165 type = other.type;
166 face_type = other.face_type;
167 cell_type = other.cell_type;
168 nodes = other.nodes;
169 faces = other.faces;
170 cells = other.cells;
171 child_faces = other.child_faces;
172 }
173 return *this;
174 }
175 };
176
177} // namespace MeshSubdivider
182{
183 public:
184
185 // 2D
186 // TODO test + f + cf
187 static MeshSubdivider::Pattern quadtoquad();
188 // TODO test + f + cf
189 static MeshSubdivider::Pattern quadtotri();
190 // TODO test + f + cf
191 static MeshSubdivider::Pattern tritotri();
192 // TODO test + f + cf
193 static MeshSubdivider::Pattern tritoquad();
194 // 3D
195 // N'utilise pas la numérotation des faces de arcane pour l'instant
196 static MeshSubdivider::Pattern hextohex();
197
198 static MeshSubdivider::Pattern tettotet();
199
200 static MeshSubdivider::Pattern hextotet(); // Ne fonctionne pas car on ne prend pas en compte la rotation.
201
202 static MeshSubdivider::Pattern tettohex();
203
204 static MeshSubdivider::Pattern hextotet24();
205};
206
207/*
208
209Noeuds
210(3) --- (2)
211 | |
212 | |
213(0) --- (1)
214Ordre des arêtes
215(3) -2- (2)
216 | |
217 3 1
218 | |
219(0) -0- (1)
220Nouveaux noeuds
221(3) -6- (2)
222 | |
223 7 8 5
224 | |
225(0) -4- (1)
226Nouveaux noeuds avec ordre nouvelles arêtes
227(3) -5- (6) -7- (2)
228| | |
2294 6 8
230| | |
231(7) -1- (8) -9- (5)
232| | |
2330 2 10
234| | |
235(0) -3- (4) -11- (1)
236 --- ---
237| | |
238| | |
239 --- ---
240| | |
241| | |
242 --- ---
243*/
244MeshSubdivider::Pattern PatternBuilder::quadtoquad()
245{
246 StorageRefine nodes({
247 { 0, 1 }, // 4
248 { 1, 2 }, // 5
249 { 2, 3 }, // 6
250 { 3, 0 }, // 7
251 { 0, 1, 2, 3 }, // 8
252 });
253 StorageRefine faces({
254 { 0, 7 }, // 0
255 { 7, 8 }, // 1
256 { 4, 8 }, // 2
257 { 0, 4 }, // 3
258 { 3, 7 }, // 4
259 { 3, 6 }, // 5
260 { 6, 8 }, // 6
261 { 2, 6 }, // 7
262 { 2, 5 }, // 8
263 { 5, 8 }, // 9
264 { 1, 5 }, // 10
265 { 1, 4 }, // 11
266 });
267 StorageRefine cells({
268 { 0, 7, 8, 4 },
269 { 7, 3, 6, 8 },
270 { 6, 2, 5, 8 },
271 { 5, 1, 4, 8 },
272 });
273 StorageRefine child_faces({
274 // pas testé
275 { 3, 11 },
276 { 10, 8 },
277 { 5, 7 },
278 { 0, 4 },
279 });
280 return { IT_Quad4, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
281}
282
283/*
284 * Pour un quad:
285 * 3 --- 2
286 * | |
287 * | |
288 * 0 --- 1
289 *
290 * 3 --> 2
291 * | / |
292 * | / |
293 * 0 <-- 1
294 *
295 * 3 --- 4 --- 5
296 * | | |
297 * | | |
298 * 0 --- 1 --- 2
299 * Ici on ajoute une seule face arcane (0,2).
300*/
301MeshSubdivider::Pattern PatternBuilder::quadtotri()
302{
303 StorageRefine nodes({}); // Pas de noeud à ajouter
304 StorageRefine faces({
305 /*{0,1},
306 {1,3},
307 {2,3},*/
308 { 0, 2 },
309 //{0,3}
310 });
311 StorageRefine cells({ { 0, 3, 2 }, { 2, 1, 0 } });
312 StorageRefine child_faces({});
313 return { IT_Quad4, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
314}
315
316/*
317 Numérotation nouveaux noeuds
318 2
319 / \
320 / \
321 5 --- 4
322 / \ / \
323 / \ / \
324 0 --- 3 --- 1
325
326 Numérotation arêtes
327 2
328 / \
329 6 7
330 / \
331 + --8-- +
332 / \ / \
333 1 2 5 3
334 / \ / \
335 + --0-- + --4-- +
336 */
337
338MeshSubdivider::Pattern PatternBuilder::tritotri()
339{
340 StorageRefine nodes({
341 { 0, 1 }, // 3
342 { 1, 2 }, // 4
343 { 2, 0 }, // 5
344 });
345 StorageRefine faces({
346 { 0, 3 },
347 { 0, 5 },
348 { 3, 5 },
349 { 1, 4 },
350 { 1, 3 },
351 { 3, 4 },
352 { 2, 5 },
353 { 2, 4 },
354 { 4, 5 },
355 });
356 StorageRefine cells({ { 3, 0, 5 },
357 { 4, 1, 3 },
358 { 5, 2, 4 },
359 { 3, 5, 4 } });
360 StorageRefine child_faces(
361 { { 0, 4 },
362 { 3, 7 },
363 { 1, 6 } });
364 return { IT_Triangle3, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
365}
366
367MeshSubdivider::Pattern PatternBuilder::tritoquad()
368{
369 StorageRefine nodes({
370 { 0, 1 }, // 3
371 { 1, 2 }, // 4
372 { 2, 0 }, // 5
373 { 0, 1, 2 }, // 6
374 });
375 StorageRefine faces({
376
377 });
378 StorageRefine cells({
379 { 0, 3, 6, 5 },
380 { 1, 4, 6, 3 },
381 { 2, 5, 6, 4 },
382 });
383 StorageRefine child_faces({});
384 return { IT_Triangle3, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
385}
386
387// N'utilise pas la numérotation des faces de arcane pour l'instant
388MeshSubdivider::Pattern PatternBuilder::hextohex()
389{
390 StorageRefine nodes = {
391 { 0, 1 }, // 8 // Sur arêtes
392 { 0, 3 }, // 9
393 { 0, 4 }, // 10
394 { 1, 2 }, // 11
395 { 1, 5 }, // 12
396 { 2, 3 }, // 13
397 { 2, 6 }, // 14
398 { 3, 7 }, // 15
399 { 4, 5 }, // 16
400 { 4, 7 }, // 17
401 { 5, 6 }, // 18
402 { 6, 7 }, // 19
403 { 0, 1, 2, 3 }, // 20 // Sur faces
404 { 0, 1, 5, 4 }, // 21
405 { 0, 4, 7, 3 }, // 22
406 { 1, 5, 6, 2 }, // 23
407 { 2, 3, 7, 6 }, // 24
408 { 4, 5, 6, 7 }, // 25
409 { 0, 1, 5, 4, 3, 2, 7, 6 } // 26 // Centroid
410 };
411 StorageRefine faces = {
412 // Externes
413 { 0, 8, 20, 9 }, // Derrière // 0 1 2 3 // 0
414 { 9, 20, 13, 3 },
415 { 8, 1, 11, 20 },
416 { 20, 11, 2, 13 },
417 { 0, 10, 22, 9 }, // Gauche // 0 3 7 4 // 1
418 { 9, 22, 15, 3 },
419 { 10, 4, 17, 22 },
420 { 22, 17, 7, 15 },
421 { 4, 16, 21, 10 }, // Bas // 4 5 0 1 // 2
422 { 10, 21, 8, 0 },
423 { 16, 5, 12, 21 },
424 { 21, 12, 1, 8 },
425 { 4, 16, 25, 17 }, // Devant // 4 5 6 7 // 3
426 { 17, 25, 19, 7 },
427 { 16, 5, 18, 25 },
428 { 25, 18, 6, 19 },
429 { 1, 12, 23, 11 }, // Droite // 1 2 5 6 // 4
430 { 11, 23, 14, 2 },
431 { 12, 5, 18, 23 },
432 { 23, 18, 6, 14 },
433 { 7, 19, 24, 15 }, // Haut // 7 6 2 3 // 5
434 { 19, 6, 14, 24 },
435 { 15, 24, 13, 3 },
436 { 24, 14, 2, 13 },
437 // Internes
438 { 8, 20, 26, 21 },
439 { 20, 13, 24, 26 },
440 { 9, 22, 26, 20 },
441 { 20, 26, 23, 11 },
442 { 21, 16, 25, 26 },
443 { 26, 25, 19, 24 },
444 { 22, 17, 25, 26 },
445 { 26, 25, 18, 23 },
446 { 10, 21, 26, 22 },
447 { 21, 12, 23, 26 },
448 { 22, 26, 24, 15 },
449 { 26, 23, 14, 24 },
450
451 };
452 StorageRefine child_faces = {
453 { 0, 1, 2, 3 },
454 { 4, 5, 6, 7 },
455 { 8, 9, 10, 11 },
456 { 12, 13, 14, 15 },
457 { 16, 17, 18, 19 },
458 { 20, 21, 22, 23 }
459 };
460 StorageRefine cells = {
461 { 0, 8, 20, 9, 10, 21, 26, 22 },
462 { 10, 21, 26, 22, 4, 16, 25, 17 },
463 { 8, 1, 11, 20, 21, 12, 23, 26 },
464 { 21, 12, 23, 26, 16, 5, 18, 25 },
465 { 9, 20, 13, 3, 22, 26, 24, 15 },
466 { 22, 26, 24, 15, 17, 25, 19, 7 },
467 { 20, 11, 2, 13, 26, 23, 14, 24 },
468 { 26, 23, 14, 24, 25, 18, 6, 19 }
469 };
470 return { IT_Hexaedron8, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
471}
472
473MeshSubdivider::Pattern PatternBuilder::tettotet()
474{
475 StorageRefine nodes = {
476 { 0, 1 }, // 4
477 { 1, 2 }, // 5
478 { 0, 2 }, // 6
479 { 0, 3 }, // 7
480 { 2, 3 }, // 8
481 { 1, 3 }, // 9
482 };
483
484 StorageRefine faces = {
485 { 0, 4, 6 }, // 0
486 { 0, 6, 7 }, // 1
487 { 0, 4, 7 }, // 2
488 { 4, 6, 7 }, // 3
489 { 1, 4, 5 }, // 4
490 { 4, 5, 9 }, // 5
491 { 1, 4, 9 }, // 6
492 { 1, 5, 9 }, // 7
493 { 2, 5, 6 }, // 8
494 { 2, 6, 8 }, // 9
495 { 5, 6, 8 }, // 10
496 { 2, 5, 8 }, // 11
497 { 7, 8, 9 }, // 12
498 { 3, 7, 8 }, // 13
499 { 3, 7, 9 }, // 14
500 { 3, 8, 9 }, // 15
501 { 4, 7, 9 }, // 16
502 { 4, 6, 9 }, // 17
503 { 6, 7, 9 }, // 18
504 { 4, 5, 6 }, // 19
505 { 5, 6, 9 }, // 20
506 { 6, 8, 9 }, // 21
507 { 6, 7, 8 }, // 22
508 { 5, 8, 9 }, // 23
509 };
510 StorageRefine child_faces = {
511 { 0, 19, 4, 8 },
512 { 1, 22, 13, 9 },
513 { 2, 16, 6, 14 },
514 { 11, 23, 7, 15 }
515 };
516 StorageRefine cells = {
517 { 0, 4, 6, 7 },
518 { 4, 1, 5, 9 },
519 { 6, 5, 2, 8 },
520 { 7, 9, 8, 3 },
521 { 4, 6, 7, 9 },
522 { 4, 9, 5, 6 },
523 { 6, 7, 9, 8 },
524 { 6, 8, 9, 5 }
525 };
526 return { IT_Tetraedron4, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
527}
528
529// Attention lors de la génération des faces, il ne faut pas utiliser le cartesian (l'ordre du cartesian builder est différent)
530MeshSubdivider::Pattern PatternBuilder::hextotet()
531{
532 StorageRefine nodes = {}; // Pas de nouveaux noeuds
533 StorageRefine faces = {
534 // Ne fonctionne pas avec les même faces que arcane pourtant
535 { 0, 1, 3 }, // 0
536 { 0, 3, 4 }, // 1
537 { 0, 1, 4 }, // 2
538 { 1, 3, 4 }, // 3
539 { 1, 4, 5 }, // 4
540 { 1, 5, 6 }, // 5
541 { 1, 4, 6 }, // 6
542 { 4, 5, 6 }, // 7
543 { 1, 2, 3 }, // 8
544 { 1, 3, 6 }, // 9
545 { 1, 2, 6 }, // 10
546 { 2, 3, 6 }, // 11
547 { 3, 4, 6 }, // 12
548 { 3, 6, 7 }, // 13
549 { 3, 4, 7 }, // 14
550 { 4, 6, 7 }, // 15
551 };
552
553 StorageRefine child_faces = { // 6*2 = 12 faces
554 { 0, 8 },
555 { 1, 14 },
556 { 2, 4 },
557 { 15, 7 },
558 { 10, 5 },
559 { 11, 13 }
560 };
561 StorageRefine cells = {
562 { 0, 1, 3, 4 },
563 { 1, 4, 5, 6 },
564 { 1, 2, 3, 6 },
565 { 3, 4, 6, 7 },
566 { 1, 3, 4, 6 }
567 };
568 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
569}
570
571MeshSubdivider::Pattern PatternBuilder::tettohex()
572{
573 StorageRefine nodes = {
574 { 0, 1 }, // 4
575 { 1, 2 }, // 5
576 { 0, 2 }, // 6
577 { 0, 3 }, // 7
578 { 2, 3 }, // 8
579 { 1, 3 }, // 9
580 { 0, 1, 3 }, // 10
581 { 1, 2, 3 }, // 11
582 { 0, 1, 2 }, // 12
583 { 0, 2, 3 }, // 13
584 { 0, 1, 2, 3 }, // 14
585 };
586 StorageRefine faces = {
587 { 7, 10, 14, 13 }, // 0 x
588 { 0, 6, 13, 7 }, // 1
589 { 0, 4, 10, 7 }, // 2
590 { 0, 4, 12, 6 }, // 3
591 { 4, 10, 14, 12 }, // 4 x
592 { 6, 12, 14, 13 }, // 5 x
593 { 2, 5, 11, 8 }, // 6
594 { 2, 6, 13, 8 }, // 7
595 { 8, 11, 14, 13 }, // 8 x
596 { 5, 11, 14, 12 }, // 9 x
597 { 2, 5, 12, 6 }, // 10
598 { 3, 8, 11, 9 }, // 11
599 { 3, 7, 13, 8 }, // 12
600 { 3, 7, 10, 9 }, // 13
601 { 9, 10, 14, 11 }, // 14 x
602 { 1, 5, 11, 9 }, // 15
603 { 1, 4, 10, 9 }, // 16
604 { 1, 4, 12, 5 }, // 17
605 };
606 StorageRefine child_faces = {
607 /*{0,10,17},
608 {1,6,11},
609 {2,13,15},
610 {8,12,16}*/
611 { 3, 10, 17 },
612 { 1, 7, 12 },
613 { 2, 13, 16 },
614 { 6, 11, 15 },
615 };
616 StorageRefine cells = {
617 /*{0,4,12,6,7,10,14,13},
618 {10,4,12,14,9,1,5,11},
619 {13,14,12,6,8,11,5,2},
620 {7,10,14,13,3,9,11,8},*/
621 /*{13,14,10,7,6,12,4,0},
622 {2,5,11,8,6,12,14,13},
623 {8,11,9,3,13,14,10,7},
624 {11,5,1,9,14,12,4,10},*/
625 /*{6,12,4,0,13,14,10,7},
626 {6,12,14,13,2,5,11,8},
627 {13,14,10,7,8,11,9,3},
628 {14,12,4,10,11,5,1,9},*/
629 { 7, 10, 14, 13, 0, 4, 12, 6 },
630 { 8, 11, 5, 2, 13, 14, 12, 6 },
631 { 3, 9, 11, 8, 7, 10, 14, 13 },
632 { 9, 1, 5, 11, 10, 4, 12, 14 }
633 };
634 return { IT_Tetraedron4, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
635}
636
637MeshSubdivider::Pattern PatternBuilder::hextotet24()
638{
639 StorageRefine nodes({
640 { 0, 1, 2, 3 }, // 8
641 { 0, 3, 7, 4 }, // 9
642 { 0, 1, 4, 5 }, // 10
643 { 4, 5, 6, 7 }, // 11
644 { 1, 2, 5, 6 }, // 12
645 { 2, 3, 7, 6 }, // 13
646 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 14
647 });
648 StorageRefine faces({
649 // OK
650 { 0, 3, 8 }, // 0
651 { 0, 8, 14 }, // 1
652 { 0, 3, 14 }, // 2
653 { 3, 8, 14 }, // 3
654 { 2, 3, 8 }, // 4
655 { 2, 3, 14 }, // 5
656 { 2, 8, 14 }, // 6
657 { 1, 2, 8 }, // 7
658 { 1, 2, 14 }, // 8
659 { 1, 8, 14 }, // 9
660 { 0, 1, 8 }, // 10
661 { 0, 1, 14 }, // 11
662 { 0, 4, 9 }, // 12
663 { 0, 9, 14 }, // 13
664 { 0, 4, 14 }, // 14
665 { 4, 9, 14 }, // 15
666 { 4, 7, 9 }, // 16
667 { 4, 7, 14 }, // 17
668 { 7, 9, 14 }, // 18
669 { 3, 7, 9 }, // 19
670 { 3, 7, 14 }, // 20
671 { 3, 9, 14 }, // 21
672 { 0, 3, 9 }, // 22
673 { 0, 4, 10 }, // 23
674 { 4, 10, 14 }, // 24
675 { 0, 10, 14 }, // 25
676 { 0, 1, 10 }, // 26
677 { 1, 10, 14 }, // 27
678 { 1, 5, 10 }, // 28
679 { 1, 5, 14 }, // 29
680 { 5, 10, 14 }, // 30
681 { 4, 5, 10 }, // 31
682 { 4, 5, 14 }, // 32
683 { 4, 7, 11 }, // 33
684 { 7, 11, 14 }, // 34
685 { 4, 11, 14 }, // 35
686 { 4, 5, 11 }, // 36
687 { 5, 11, 14 }, // 37
688 { 5, 6, 11 }, // 38
689 { 5, 6, 14 }, // 39
690 { 6, 11, 14 }, // 40
691 { 6, 7, 11 }, // 41
692 { 6, 7, 14 }, // 42
693 { 1, 5, 12 }, // 43
694 { 5, 12, 14 }, // 44
695 { 1, 12, 14 }, // 45
696 { 1, 2, 12 }, // 46
697 { 2, 12, 14 }, // 47
698 { 2, 6, 12 }, // 48
699 { 2, 6, 14 }, // 49
700 { 6, 12, 14 }, // 50
701 { 5, 6, 12 }, // 51
702 { 2, 6, 13 }, // 52
703 { 6, 13, 14 }, // 53
704 { 2, 13, 14 }, // 54
705 { 2, 3, 13 }, // 55
706 { 3, 13, 14 }, // 56
707 { 3, 7, 13 }, // 57
708 { 7, 13, 14 }, // 58
709 { 6, 7, 13 }, // 59
710 });
711 StorageRefine cells({
712 { 0, 3, 8, 14 },
713 { 3, 2, 8, 14 },
714 { 2, 1, 8, 14 },
715 { 1, 0, 8, 14 },
716
717 { 0, 4, 9, 14 },
718 { 4, 7, 9, 14 },
719 { 7, 3, 9, 14 },
720 { 3, 0, 9, 14 },
721
722 { 4, 0, 10, 14 },
723 { 0, 1, 10, 14 },
724 { 1, 5, 10, 14 },
725 { 5, 4, 10, 14 },
726
727 { 7, 4, 11, 14 },
728 { 4, 5, 11, 14 },
729 { 5, 6, 11, 14 },
730 { 6, 7, 11, 14 },
731
732 { 5, 1, 12, 14 },
733 { 1, 2, 12, 14 },
734 { 2, 6, 12, 14 },
735 { 6, 5, 12, 14 },
736
737 { 6, 2, 13, 14 },
738 { 2, 3, 13, 14 },
739 { 3, 7, 13, 14 },
740 { 7, 6, 13, 14 },
741 });
742
743 StorageRefine child_faces({
744 // a refaire ancienne numérotation
745 { 0, 4, 7, 10 },
746 { 12, 16, 19, 22 },
747 { 23, 26, 28, 31 },
748
749 { 33, 36, 38, 41 },
750 { 43, 46, 48, 51 },
751 { 52, 55, 57, 59 },
752 });
753 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
754}
755
756/*---------------------------------------------------------------------------*/
757/*---------------------------------------------------------------------------*/
761class ArcaneBasicMeshSubdividerService
763{
764 public:
765
766 explicit ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi);
768 void subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh) override;
769
770 private:
771
772 void _init();
774 static UniqueArray<Int64> _computeNodeUid(UniqueArray<Int64> nodes_uid, const StorageRefine& node_pattern);
775 /*
776 void _computeNodeCoord();
777 void _computeNodeUid();
778 void _computeFaceUid();
779 void _computeCellUid();
780 void _processOwner();
781 void _setOwner();
782 void _processOwnerCell();
783 void _processOwnerFace();
784 void _processOwnerNode();
785 void _getRefinePattern(Int16 type);
786 void _execute();
787 */
788
792 /* Méthode qui permet de récuperer les faces générés par arcanes.
793 * Ces faces doivent donner les indices locaux des noeuds de la cellule initiale.
794 * Pour ça on construit une map global to my_local_index. <Int64,Int64>
795 */
806 void _refineOnce([[maybe_unused]] IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
815};
816
818{
819 if (mesh->dimension() == 2) {
821 }
822 else if (mesh->dimension() == 3) {
824 }
825}
826
828{
829 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
830
831 mesh->faceFamily()->destroyGroups();
833 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
834 _refineOnce(mesh, pattern_manager);
835 std::string prefix("subdivider_pattern2D_");
836 mesh->utilities()->writeToFile(prefix + "tritotri.vtk", "VtkLegacyMeshWriter");
837
838 mesh->faceFamily()->destroyGroups();
840 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
841 _refineOnce(mesh, pattern_manager);
842 mesh->utilities()->writeToFile(prefix + "tritoquad.vtk", "VtkLegacyMeshWriter");
843
844 mesh->faceFamily()->destroyGroups();
846 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
847 _refineOnce(mesh, pattern_manager);
848 mesh->utilities()->writeToFile(prefix + "quadtoquad.vtk", "VtkLegacyMeshWriter");
849
850 mesh->faceFamily()->destroyGroups();
852 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
853 _refineOnce(mesh, pattern_manager);
854 mesh->utilities()->writeToFile(prefix + "quadtotri.vtk", "VtkLegacyMeshWriter");
855}
856
858{
859 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
860 std::string prefix("subdivider_pattern3D_");
861 mesh->faceFamily()->destroyGroups();
863 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
864 _refineOnce(mesh, pattern_manager);
865 mesh->utilities()->writeToFile(prefix + "tettotet.vtk", "VtkLegacyMeshWriter");
866
867 mesh->faceFamily()->destroyGroups();
869 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
870 _refineOnce(mesh, pattern_manager);
871 mesh->utilities()->writeToFile(prefix + "tettohex.vtk", "VtkLegacyMeshWriter");
872
873 mesh->faceFamily()->destroyGroups();
875 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
876 _refineOnce(mesh, pattern_manager);
877 mesh->utilities()->writeToFile(prefix + "hextohex.vtk", "VtkLegacyMeshWriter");
878
879 mesh->faceFamily()->destroyGroups();
881 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
882 _refineOnce(mesh, pattern_manager);
883 mesh->utilities()->writeToFile(prefix + "hextotet24.vtk", "VtkLegacyMeshWriter");
884
885 mesh->faceFamily()->destroyGroups();
887 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
888 _refineOnce(mesh, pattern_manager);
889 mesh->utilities()->writeToFile(prefix + "subdivider_hextotet.vtk", "VtkLegacyMeshWriter");
890}
891
892/*void ArcaneBasicMeshSubdividerService::_getArcaneOrder(IPrimaryMesh* mesh){
893 Tritotri generate faces
894
895 _generateOneTri(mesh);
896 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
897 _refineOnce(mesh,pattern_manager);
898
899
900 Quadtoquad generate faces
901
902 _generateOneQuad(mesh);
903 _refineWithArcaneFaces(mesh,PatternBuilder::quadtoquad());
904 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
905 _refineOnce(mesh,pattern_manager);
906
907
908 Tettotet generate faces
909
910 _generateOneTetra(mesh);
911 _refineWithArcaneFaces(mesh,PatternBuilder::tettotet());
912
913
914
915 _faceOrderArcane(mesh);
916 mesh_utils::writeMeshInfos(mesh,"meshInSubdivide");
917 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
918 _refineOnce(mesh,pattern_manager);
919 mesh_utils::writeMeshInfos(mesh,"meshOutSubdivide");
920
921
922 Tettohex generate faces input one tet
923
924 _generateOneTetra(mesh);
925 _refineWithArcaneFaces(mesh,PatternBuilder::tettohex());
926
927 Hextohex generate faces input one hex
928 _refineWithArcaneFaces(mesh,PatternBuilder::hextotet());
929
930 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
931 _refineOnce(mesh,pattern_manager);
932
933}*/
934
935void ArcaneBasicMeshSubdividerService::_refineOnce(IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager)
936{
937
938 info() << "#subdivide mesh";
939 // On vérifie qu'on sait raffiner les cellules (peut-être pas en même temps)
940 ENUMERATE_CELL (icell, mesh->ownCells()) {
941 const Cell& cell = *icell;
942 // Liste des éléments où les patterns sont implémentés pour l'instant
943 if (cell.itemTypeId() != IT_Hexaedron8 && cell.itemTypeId() != IT_Tetraedron4 && cell.itemTypeId() != IT_Quad4 && cell.itemTypeId() != IT_Triangle3) {
944 ARCANE_FATAL("Not implemented item type '{0}'", cell.itemTypeId());
945 return;
946 }
947 }
948
949 info() << "subdivide mesh with " << options()->nbSubdivision() << " nb_refine";
950
951 Int32 my_rank = mesh->parallelMng()->commRank();
952 IMeshModifier* mesh_modifier = mesh->modifier();
953 IGhostLayerMng* gm = mesh->ghostLayerMng();
954 debug() << "PART 3D nb ghostlayer" << gm->nbGhostLayer();
955 // mesh->utilities()->writeToFile(String::format("3D_last_input{0}.vtk",my_rank), "VtkLegacyMeshWriter");
956 Integer nb_ghost_layer_init = gm->nbGhostLayer(); // On garde le nombre de ghost layer initial pour le remettre à la fin
957 Int32 version = gm->builderVersion();
958 if (version < 3)
959 gm->setBuilderVersion(3);
960
961 gm->setNbGhostLayer(0);
962 mesh_modifier->setDynamic(true);
963 mesh_modifier->updateGhostLayers();
964
965 // Uniquement pour les vérifications asserts à la fin
966 Integer nb_cell_init = mesh->nbCell();
967 Integer nb_face_init = mesh->nbFace();
968 //Integer nb_edge_init = mesh->nbEdge();
969 //Integer nb_node_init = mesh->nbNode();
970
971 // Compter les arêtes
972 // On cherche un moyen de compter les arêtes pour faire un test facile sur le nombre de noeud inséré.
973 // ARCANE_ASSERT((nb_edge_init+ nb_cell_init + nb_face_init)== nb_node_added,("Mauvais nombre de noeuds insérés"));
974 //debug() << "#NOMBRE INITS " << nb_node_init << " " << mesh->allEdges().size() << " " << edg.size() << " " << nb_face_init << " " << nb_cell_init ;
975
976 // VARIABLES
977 // Items à ajouter avec connectivités pour E F et C
978 UniqueArray<Int64> nodes_to_add;
979 UniqueArray<Int64> edges_to_add;
980 UniqueArray<Int64> faces_to_add;
981 UniqueArray<Int64> cells_to_add;
982
983 Integer nb_cell_to_add = 0;
984 Integer nb_face_to_add = 0;
985
986 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
987 std::unordered_map<Int64, Real3> nodes_to_add_coords;
988 debug() << "ARRAY SIZE " << nodes_coords.arraySize();
989 // Noeuds sur les entités
990 std::set<Int64> new_nodes; // Utiliser une map permet s'assurer qu'on ajoute une seule fois un noeud avec un uniqueId()
991 std::set<Int64> new_faces; // ^--- Pareil pour les faces
992 // Maps pour la gestions des propriétaires
993 std::unordered_map<Int64, Int32> node_uid_to_owner;
994 std::unordered_map<Int64, Int32> edge_uid_to_owner; // pas utilisé
995 std::unordered_map<Int64, Int32> face_uid_to_owner;
996 std::unordered_map<Int64, Int32> child_cell_owner; // pas utilisé
997 std::unordered_map<Int32, Int32> old_face_lid_to_owner; // pas utilisé
998
999 UniqueArray<Int32> cells_to_detach; // Cellules à détacher
1000 UniqueArray<Int64> faces_uids; // Contient uniquement les uids pas les connectivités
1001 UniqueArray<Int64> edges_uids; // Idem
1002
1003 // Calcul nombre de noeuds à insérer
1004 // const Integer nb_node_to_add_total = mesh->nbCell()+mesh->nbFace()+mesh->nbEdge(); // Attention pattern dépendant
1005 //nodes_to_add.reserve(nb_node_to_add_total);
1006 //nodes_to_add_coords.reserve(nb_node_to_add_total);
1007
1008 Integer ind_new_cell = 0;
1009
1010 ARCANE_ASSERT((mesh->nbEdge() == 0), ("Wrong number of edge"));
1011
1012 UniqueArray<Int64> parent_faces(mesh->ownFaces().size());
1013 UniqueArray<Int64> parent_cells(mesh->ownCells().size());
1014 UniqueArray<Int64> child_cells; // Toutes les nouvelles cells
1015 UniqueArray<Int64> child_faces; // Au bord de l'élément uniquement (pas de faces interne à l'élément)
1016
1017 // Permet de récupere les entités enfants à partir d'une cellule parent
1018 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_cell; // A partir d'un uid on récupère le premier enfant (pair<index,number of child>)
1019 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces; // A partir d'un uid on récupère le premier enfant (pair<index,number of child>)
1020 // ^--- uniquement pour les faces "externes"
1021 Int64 childs_count = 0; // A chaque nouvelle cellule on se décale du nombre d'enfant ( +4 si quad, +3 ou +4 pour les tri selon le pattern )
1022
1023 // Groups
1024 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces_groups; // Map face parente -> face enfant externe dans array face_external_uid
1025 UniqueArray<Int64> face_external_uid; // Toutes les faces externes du proc uid
1026
1027 // Debug node
1028 /*
1029 ENUMERATE_NODE(inode,mesh->ownNodes())
1030 {
1031 const Node & node = *inode;
1032 nodes_to_add_coords[node.uniqueId().asInt64()] = nodes_coords[node];
1033 }
1034 */
1035 // Traitement pour une cellule²
1036 ENUMERATE_CELL (icell, mesh->ownCells()) {
1037 debug() << "Refining element";
1038 // POUR UN ELEMNT:
1039 // Détacher cellules parente
1040 // Génération des nouveaux noeuds (uid et coordonnées)
1041 // Sur Arêtes
1042 // Sur Faces
1043 // Sur Cellule
1044 // Nouveaux noeuds,coordonnées
1045
1046 // Génération des Faces (uid et composants (Noeuds)) utilises nouveaux noeuds
1047 // Internes
1048 // Externes
1049
1050 // Génération des Cellules (uid et composants (Noeuds))
1051 // Gestion des groupes
1052 // FIN UN ELEMENT
1053
1054 // Détachement des cellules
1055 // Ajout des noeuds enfants
1056 // Ajout des faces enfants
1057 // Ajout des cellules enfants (et assignation propriétaire)
1058
1059 // Ajout d'une couche fantome
1060 // Calcul des propriétaires des noeuds
1061 // Calcul des propriétaires des faces
1062 // Supression de la couche fantome
1063 // ?? Calcul des groupes F C
1064
1065 // Assignation des noeuds au propriétaire
1066 // Assignation des faces au propriétaire
1067
1068 const Cell& cell = *icell;
1069
1070 MeshSubdivider::Pattern& p = pattern_manager[cell.type()]; // Pattern Manager
1071 StorageRefine& node_pattern = p.nodes;
1072
1073 UniqueArray<Int64> face_in_cell; // Toutes les faces de la cellule uid
1074 StorageRefine& child_faces = p.child_faces;
1075
1076 cells_to_detach.add(cell.localId());
1077 // Génération des noeud
1078 UniqueArray<Int64> node_in_cell;
1079 node_in_cell.resize(node_pattern.size() + cell.nbNode()); // pattern dépendant
1080 UniqueArray<Real3> coords_in_cell;
1081 debug() << "Noeuds initiaux";
1082 // Noeuds initiaux
1083 for (Int32 i = 0; i < cell.nbNode(); i++) {
1084 node_in_cell[i] = cell.node(static_cast<Int32>(i)).uniqueId().asInt64();
1085 //debug() << i << " " << node_in_cell[i] << " size " << node_in_cell.size() ;
1086 }
1087
1088 Integer index_27 = cell.nbNode();
1089
1090 // - Génération des uid noeuds
1091 debug() << "Génération des uid noeuds";
1092
1093 for (Integer i = 0; i < node_pattern.size(); i++) {
1094 // uid
1096 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1097 tmp.add(node_in_cell[node_pattern[i][j]]);
1098 }
1099 std::sort(tmp.begin(), tmp.end());
1101 node_in_cell[index_27 + i] = uid;
1102
1103 if (new_nodes.find(node_in_cell[i + index_27]) == new_nodes.end()) {
1104 // Coords
1105 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1106 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1107 info() << "loop" << cell.node(static_cast<Integer>(node_pattern[i][j])) << " " << nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1108 middle_coord += nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1109 }
1110 if (node_pattern[i].size() == 0) {
1111 ARCANE_FATAL("Wrong size for refined pattern with code IT:'{0}'", p.cell_type);
1112 }
1113 middle_coord /= node_pattern[i].size();
1114 if (middle_coord == Real3(0.0, 0.0, 0.0)) {
1115 ARCANE_FATAL("Bad coordinate for new node, the node '{0}' probably has a default coordinate (0.0,0.0,0.0).", uid);
1116 }
1117 new_nodes.insert(node_in_cell[i + index_27]);
1118 // Insertion dans map uid -> coord
1119 nodes_to_add_coords[node_in_cell[i + index_27]] = middle_coord;
1120 // Insertion dans Uarray uid
1121 nodes_to_add.add(uid);
1122 //info() << node_pattern[i];
1123 //debug() << i << " " << uid << " sizenic " << tmp << middle_coord;
1124 }
1125 }
1126 // Est-ce qu'on doit ajouter les anciens noeuds ? Normalement non
1127 // #TAG
1128 /*
1129 for(Integer i = 0 ; i < cell.nbNode() ; i++ ) {
1130 nodes_to_add.add(cell.node(i).uniqueId().asInt64());
1131 new_nodes.insert(cell.node(i).uniqueId().asInt64());
1132 }
1133 */
1134
1135 debug() << "nodetoadd size " << nodes_to_add.size() << " " << nodes_to_add_coords.size();
1136 debug() << "Node coord & nb node to add" << nodes_to_add_coords.size() << " " << nodes_to_add.size();
1137 //ARCANE_ASSERT((nodes_to_add_coords.size() == static_cast<size_t>(nodes_to_add.size())),("Has to be same"));
1138 //ARCANE_ASSERT((nodes_to_add_coords.size() == new_nodes.size()),("Has to be same"));
1139
1140 // Génération des Faces
1141 StorageRefine& face_refine = p.faces;
1142 debug() << "face_refine.size() " << face_refine.size();
1143 //ARCANE_ASSERT((face_refine.size() == 36), ("WRONG NUMBER OF CELL ADDED")); // One cube assert
1144 debug() << "Refine face";
1145 for (Integer i = 0; i < face_refine.size(); i++) {
1146 // Generation du hash de la face
1148 //tmp.resize(face_refine[i].size());
1149 for (Integer j = 0; j < face_refine[i].size(); j++) {
1150 tmp.add(node_in_cell[face_refine[i][j]]);
1151 }
1152 std::sort(tmp.begin(), tmp.end());
1153 //ARCANE_ASSERT(( tmp.size() == 4 ),("Wrong size of UniqueArray")); // one cube assert
1155 face_in_cell.add(uid); // Pour groups
1156 // Vérifier si on l'a déja crée
1157 if (new_faces.find(uid) == new_faces.end()) {
1158 // Ajout
1159 faces_to_add.add(p.face_type);
1160 faces_to_add.add(uid);
1161 //debug() << "Face " << uid << " " << tmp ;
1162 for (Integer j = 0; j < face_refine[i].size(); j++) {
1163 //debug() << node_in_cell[face_refine[i][j]] ;
1164 faces_to_add.add(node_in_cell[face_refine[i][j]]);
1165 }
1166 // Ajouter dans tableau uids faces
1167 faces_uids.add(uid);
1168 nb_face_to_add++;
1169 new_faces.insert(uid);
1170 }
1171 }
1172
1173 // Nouvelle Gestion des groupes
1174 // Pour chaque faces
1175 // Générer hash
1176 // associer hash uid face
1177 // Parcours des faces parentes
1178 debug() << "Gestion face groupe";
1179 for (Integer i = 0; i < child_faces.size(); i++) {
1180 parents_to_childs_faces_groups[cell.face(i).uniqueId()] = std::pair<Int64, Int64>(face_external_uid.size(), child_faces[i].size());
1181 for (Integer j = 0; j < child_faces[i].size(); j++) {
1182 face_external_uid.add(face_in_cell[child_faces[i][j]]); // start c'est l'index des face_in_cell // en fait on fait un array pour chaque élément aussi // face_in_cell (sinon les index seront faux donc on ajoute plusieurs fois les faces)
1183 }
1184 }
1185
1186 // Génération des cells
1187 StorageRefine& cells_refine = p.cells;
1188 // Génération des cellules enfants
1189 debug() << "Génération des cellules enfants";
1190 // L'uid est généré à partir du hash de chaque noeuds triés par ordre croissant
1191 for (Integer i = 0; i < cells_refine.size(); i++) {
1192 // Le nouvel uid est généré avec le hash des nouveaux noeuds qui composent la nouvelle cellule
1194 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1195 tmp.add(node_in_cell[cells_refine[i][j]]);
1196 }
1197 std::sort(tmp.begin(), tmp.end());
1198 Int64 cell_uid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView()); //max_cell_uid+ind_new_cell;
1199
1200 cells_to_add.add(p.cell_type); // Type
1201 cells_to_add.add(cell_uid); // TODO CHANGER par max_uid + cell_uid * max_nb_node
1202 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1203 cells_to_add.add(node_in_cell[cells_refine[i][j]]);
1204 }
1205 child_cell_owner[cell_uid] = cell.owner();
1206 parent_cells.add(cell.uniqueId());
1207 child_cells.add(cell_uid); // groups doublons d'informations avec cells_to_add
1208 nb_cell_to_add++;
1209 ind_new_cell++;
1210 }
1211 // groups
1212 parents_to_childs_cell[cell.uniqueId()] = std::pair<Int64, Int64>(childs_count, cells_refine.size());
1213 childs_count += cells_refine.size(); // à modifier selon le nombre d'enfant associé au motif de rafinement !
1214 }
1215 // Ajout des nouveaux Noeuds
1216 Integer nb_node_added = nodes_to_add.size();
1217 UniqueArray<Int32> nodes_lid(nb_node_added);
1218
1219 info() << "JustBeforeAdd " << nodes_to_add;
1220 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.view());
1221
1222 // Edges: Pas de génération d'arrête
1223
1224 debug() << "Faces_uids " << faces_uids << " faces_to_add " << faces_to_add.size() << " faces_to_add/6 " << faces_to_add.size() / 6;
1225
1226 //ARCANE_ASSERT((nodes_to_add.size() != 0),("End"));
1227 //ARCANE_ASSERT((nb_face_to_add == 68),("WRONG NUMBER OF FACES")); // two hex
1228 // Ajout des Faces enfants
1229 UniqueArray<Int32> face_lid(faces_uids.size());
1230 debug() << "Before addOneFace " << nb_face_to_add;
1231
1232 //Setup faces
1233 mesh->modifier()->addFaces(nb_face_to_add, faces_to_add.constView(), face_lid.view());
1234 debug() << "addOneFace " << nb_face_to_add;
1235 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, faces_uids, true);
1236 debug() << "NB_FACE_ADDED AFTER " << face_lid.size() << " " << new_faces.size();
1237
1238 //ARCANE_ASSERT((nb_face_to_add == (faces_to_add.size()/6)),("non consistant number of faces")); // Pour hex
1239
1240 // Ajout des cellules enfants
1241 mesh->modifier()->detachCells(cells_to_detach);
1242
1243 UniqueArray<Int32> cells_lid(nb_cell_to_add);
1244 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.constView(), cells_lid);
1245 info() << "After addCells";
1246 // mesh->modifier()->addCells()
1247 // Pour tout les itemgroups
1248 UniqueArray<Int32> child_cells_lid(child_cells.size());
1249 mesh->cellFamily()->itemsUniqueIdToLocalId(child_cells_lid, child_cells, true);
1250
1251 // Gestion des itemgroups ici (différents matériaux par exemple)
1252 // - On cherche à ajouter les enfants dans les mêmes groupes que les parents pour :
1253 // - Faces
1254 // - Cells
1255 // - Pas de déduction automatique pour :
1256 // - Noeuds
1257 // - Arêtes
1258 // Algo
1259 // Pour chaque group
1260 // Pour chaque cellules de ce group
1261 // ajouter cellules filles de ce group
1262
1263 // Traiter les groupes pour les faces
1264 //
1265 // En fait on ne peut traiter que les faces externes. Est-ce qu'on doit/peut déduire les groupes des faces internes ?
1266 // Dans le cas du test microhydro on peut car on a que les faces externes aux éléments: XYZ min max
1267 // A ce moment nous n'avons pas fait de lien face_parent_externe -> face_enfant_externe
1268 // Pour le faire nous allons parcourir les faces internes parentes, trier les ids et trier les éléménts
1269
1270 // Problème des groupes.
1271 // Tableau faces_externals
1272 // Pour chaque face parent
1273 // - Ajouter dans une nouvelle variable faces_externals l'uid de chaque nouvelle face
1274 // - dans map sauvegarder uid, et index
1275
1276 IItemFamily* face_family = mesh->faceFamily();
1277 IItemFamily* cell_family = mesh->cellFamily();
1278
1279 UniqueArray<Int32> face_external_lid(face_external_uid.size());
1280 mesh->faceFamily()->itemsUniqueIdToLocalId(face_external_lid, face_external_uid);
1281 // Traiter les groups pour les faces
1282 info() << "#mygroupname face " << face_family->groups().count();
1283 for (ItemGroupCollection::Enumerator igroup(face_family->groups()); ++igroup;) {
1284 ItemGroup group = *igroup;
1285 info() << "#mygroupname face " << group.fullName();
1286 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1287 info() << "#groups: OWN";
1288 continue;
1289 }
1290 if (group.isAllItems()) { // besoin de ça pour seq et //
1291 info() << "#groups: ALLITEMS";
1292 continue;
1293 }
1294 info() << "#groups: Added ";
1295 UniqueArray<Int32> to_add_to_group;
1296
1297 ENUMERATE_ (Item, iitem, group) { // Pour chaque cellule du groupe on ajoute ses 8 enfants ( ou n )
1298 Int64 step = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].first;
1299 Int64 n_childs = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].second;
1300 auto subview = face_external_lid.subView(step, static_cast<Integer>(n_childs));
1301 //ARCANE_ASSERT((subview.size() == 4 ), ("SUBVIEW"));
1302 to_add_to_group.addRange(subview);
1303 }
1304 group.addItems(to_add_to_group, true);
1305 }
1306
1307 // Traiter les groupes pour les cellules
1308 for (ItemGroupCollection::Enumerator igroup(cell_family->groups()); ++igroup;) {
1309 CellGroup group = *igroup;
1310 info() << "#mygroupname" << group.fullName() << "nb item" << cell_family->nbItem();
1311 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1312 info() << "#groups: OWN";
1313 continue;
1314 }
1315 if (group.isAllItems()) { // besoin de ça pour seq et //
1316 info() << "#groups: ALLITEMS";
1317 continue;
1318 }
1319
1320 info() << "#groups: Added ";
1321 UniqueArray<Int32> to_add_to_group;
1322
1323 ENUMERATE_ (Item, iitem, group) { // Pour chaque cellule du groupe on ajoute ses 8 enfants ( ou n )
1324 Int64 step = parents_to_childs_cell[iitem->uniqueId().asInt64()].first;
1325 Int64 n_childs = parents_to_childs_cell[iitem->uniqueId().asInt64()].second;
1326 auto subview = child_cells_lid.subView(step, static_cast<Integer>(n_childs));
1327 to_add_to_group.addRange(subview);
1328 }
1329 info() << "#Added " << to_add_to_group.size() << " to group " << group.fullName();
1330 group.addItems(to_add_to_group, true);
1331 }
1332 // fin gestion itemgroups
1333 mesh->modifier()->removeDetachedCells(cells_to_detach.constView());
1334 //mesh->modifier()->removeCells(cells_to_detach.constView());
1335 mesh->modifier()->endUpdate();
1336
1337 // DEBUG
1338 debug() << "Debug faces " << faces_to_add;
1339 /*for(Integer i = 0 ; i < faces_to_add.size() ; i++){
1340 debug() << new_faces[i] ;
1341 }*/
1342 // ENDEBUG
1343
1344 // Gestion et assignation du propriétaire pour chaque cellule
1345 // Le propriétaire est simplement le sous domaine qui a générer les nouvelles cellules
1346 ENUMERATE_ (Cell, icell, mesh->allCells()) {
1347 Cell cell = *icell;
1348 cell.mutableItemBase().setOwner(my_rank, my_rank);
1349 }
1350 mesh->cellFamily()->notifyItemsOwnerChanged();
1351
1352 // ARCANE_ASSERT((nodes_lid.size() != 0),("End"));
1353 ARCANE_ASSERT((nodes_lid.size() == nodes_to_add.size()), ("End"));
1354 // Assignation des coords aux noeuds
1355
1356 UniqueArray<Int32> to_add_to_nodes(nodes_to_add.size()); // Bis
1357 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_to_add, true);
1358
1359 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) { // recalculer nodes_lid
1360 Node node = *inode;
1361 debug() << node.uniqueId().asInt64();
1362 //ARCANE_ASSERT((new_nodes.find(node.uniqueId().asInt64()) != new_nodes.end()),("Not found in set !"))
1363 //ARCANE_ASSERT((nodes_to_add_coords.find(node.uniqueId().asInt64()) != nodes_to_add_coords.end()),("Not found in map coord!"))
1364 // si il est pas dans la map c'est qu'il existe déja !
1365
1366 nodes_coords[node] = nodes_to_add_coords[node.uniqueId().asInt64()];
1367 debug() << "InSBD" << node.uniqueId().asInt64() << " " << nodes_to_add_coords[node.uniqueId().asInt64()];
1368 }
1369
1370 //info() << "#NODECOORDS" << nodes_coords.asArray() ;
1371 // Ajout d'une couche fantôme
1372 Arcane::IGhostLayerMng* gm2 = mesh->ghostLayerMng();
1373 gm2->setNbGhostLayer(1);
1374 mesh->updateGhostLayers(true);
1375
1376 // Gestion des propriétaires de noeuds
1377 // Le propriétaire est la cellule incidente au noeud avec le plus petit uniqueID()
1378 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1379 Node node = *inode;
1380 auto it = std::min_element(node.cells().begin(), node.cells().end());
1381 Cell cell = node.cell(static_cast<Int32>(std::distance(node.cells().begin(), it)));
1382 node_uid_to_owner[node.uniqueId().asInt64()] = cell.owner();
1383 }
1384
1385 // Gestion des propriétaires des faces
1386 // Le propriétaire est la cellule incidente à la face avec le plus petit uniqueID()
1387 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1388 Face face = *iface;
1389 auto it = std::min_element(face.cells().begin(), face.cells().end());
1390 Cell cell = face.cell(static_cast<Int32>(std::distance(face.cells().begin(), it)));
1391 face_uid_to_owner[face.uniqueId().asInt64()] = cell.owner();
1392 }
1393
1394 // Utiliser les couches fantôme est couteux (construction destruction)
1395 // - Optim: pour les noeuds partager avoir une variable all to all (gather) qui permet de récuper le rank de l'owner pour chaque item shared
1396 // - Déduction possible des owners des faces enfants avec la face parent directement
1397 // - Les cellules enfants ont le même owner que la cellule parent
1398 // Supression de la couche fantôme
1399 gm2->setNbGhostLayer(0);
1400 mesh->updateGhostLayers(true);
1401
1402 // DEBUG
1403 /*debug() << "#Faces mesh";
1404 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1405 Face face = *iface;
1406 debug() << face.uniqueId().asInt64();
1407 }*/
1408
1409 // Quelques sur le nombres d'entités insérés
1410 // ARCANE_ASSERT((mesh->nbCell() == nb_cell_init*8 ),("Wrong number of cell added"));
1411 debug() << "nbface " << mesh->nbFace() << " " << nb_face_to_add << " expected " << nb_face_init * 4 + 12 * nb_cell_init;
1412 // ARCANE_ASSERT((mesh->nbFace() <= nb_face_init*4 + 12 * nb_cell_init ),("Wrong number of face added"));
1413 // A ajouter pour vérifier le nombre de noeud si les arêtes sont crées
1414 // ARCANE_ASSERT((mesh->nbNode() == nb_edge_init + nb_face_init + nb_cell_init ),("Wrong number of node added"))
1415
1416 // Assignation du nouveau propriétaire pour chaque noeud
1417 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1418 Node node = *inode;
1419 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId().asInt64()], my_rank);
1420 }
1421 mesh->nodeFamily()->notifyItemsOwnerChanged();
1422
1423 // Assignation du nouveaux propriétaires pour chaque face
1424 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1425 Face face = *iface;
1426 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId().asInt64()], my_rank);
1427 }
1428 mesh->faceFamily()->notifyItemsOwnerChanged();
1429
1430 // On met de nouveau le ghost layer pour une future simulation
1431 gm2->setNbGhostLayer(nb_ghost_layer_init);
1432 mesh->updateGhostLayers(true);
1433
1434 // Ecriture au format VTK
1435 /*
1436 mesh->utilities()->writeToFile("3Drefined" + std::to_string(my_rank) + ".vtk", "VtkLegacyMeshWriter");
1437 info() << "Writing VTK 3Drefine";
1438 debug() << "END 3D fun";
1439 debug() << "NB CELL " << mesh->nbCell() << " " << nb_cell_init * 8;
1440 debug() << mesh->nbNode() << " " << nb_node_init << " " << nb_edge_init << " " << nb_face_init << " " << nb_cell_init;
1441 debug() << mesh->nbFace() << "nb_face_init " << nb_face_init << " " << nb_face_init << " " << nb_cell_init;
1442 debug() << "Faces: " << mesh->nbFace() << " theorical nb_face_to add: " << nb_face_init * 4 + nb_cell_init * 12 << " nb_face_init " << nb_face_init << " nb_cell_init " << nb_cell_init;
1443 info() << "#NODES_CHECK #all" << mesh->allNodes().size() << " #own " << mesh->ownNodes().size();
1444 */
1445}
1446
1448{
1449 IMeshModifier* modifier = mesh->modifier();
1450 Int64UniqueArray cells_infos;
1451 Int64UniqueArray faces_infos;
1452 Int64UniqueArray nodes_uid;
1453 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1454 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1455
1456 // get max uid for cells
1457 Int64 max_offset = 0;
1458 ENUMERATE_CELL (icell, mesh->allCells()) {
1459 Cell cell = *icell;
1460 info() << cell.uniqueId().asInt64() << " ";
1461 if (max_offset < cell.uniqueId())
1462 max_offset = cell.uniqueId();
1463 }
1464 //ARCANE_ASSERT((max_offset!=0),("BAD OFFSET"));
1465
1466 info() << "#_refineWithArcaneFaces";
1467 ENUMERATE_CELL (icell, mesh->allCells()) {
1468 const Cell& cell = *icell;
1469 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1470 << icell->type() << ", nb nodes=" << icell->nbNode();
1471
1472 for (Face face : cell.faces()) {
1473 info() << "Face " << face.uniqueId() << " nodes ";
1474 for (Node node : face.nodes()) {
1475 info() << node.uniqueId() << " ";
1476 }
1477 }
1478 }
1479 //mesh->utilities()->writeToFile("subdivider_one_tetra_output.vtk", "VtkLegacyMeshWriter");
1480 ARCANE_ASSERT((!p.cells.empty()), ("Pattern not init"));
1481 Integer cellcount = 0;
1482 UniqueArray<Int32> cells_to_detach; // Cellules à détacher
1483
1484 Int64 face_count = 0;
1485
1486 std::map<Int64, Int32> node_uid_to_cell_local_id; // Donne le local id par rapport à une cell
1487
1488 ENUMERATE_CELL (icell, mesh->allCells()) {
1489 UniqueArray<Int64> node_in_cell;
1490 const Cell& cell = *icell;
1491 info() << "Detach";
1492 cells_to_detach.add(cell.localId());
1493 info() << "Get Pattern";
1494 StorageRefine& node_pattern = p.nodes;
1495 StorageRefine& cells = p.cells;
1496
1497 info() << "Get Nodes";
1498 for (Integer i = 0; i < cell.nbNode(); i++) {
1499 node_in_cell.add(cell.node(i).uniqueId().asInt64());
1500 info() << "Node " << cell.node(i).uniqueId().asInt64() << " " << nodes_coords[cell.node(i)];
1501 }
1502 info() << "Node pattern " << node_pattern.size() << "nic " << node_in_cell;
1503 _computeNodeUid(node_in_cell, node_pattern);
1504 // New nodes and coords
1505 for (Integer i = 0; i < node_pattern.size(); i++) {
1506 info() << "test " << i;
1507 UniqueArray<Int64> tmp = node_pattern[i];
1508
1509 // uid == node_in_cell[uid]
1510 Int64 uid = cell.nbNode() + i;
1511 node_in_cell.add(uid); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
1512 nodes_uid.add(uid);
1513 // Coords
1514 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1515
1516 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1517 middle_coord += nodes_coords[cell.node(static_cast<Int32>(node_pattern[i][j]))];
1518 info() << node_pattern[i][j] << cell.node(static_cast<Int32>(node_pattern[i][j]));
1519 }
1520 middle_coord /= node_pattern[i].size();
1521 nodes_to_add_coords[uid] = middle_coord;
1522 info() << "NodeX " << uid << " " << " coord " << nodes_to_add_coords[uid] << " " << middle_coord;
1523 node_uid_to_cell_local_id[uid] = cell.nbNode() + i;
1524 }
1525
1526 info() << "#node in cell " << node_in_cell;
1527 // Génération nouvelles faces et cells
1528 // New faces
1529 /*for( Integer i = 0 ; i < faces.size() ; i++ ){
1530 // Header
1531 faces_infos.add(p.face_pattern); // type // Dépendant pattern //#HERE
1532 faces_infos.add(i); // face uid
1533 for( Integer j = 0 ; j < faces[i].size() ; j++ ) {
1534 faces_infos.add(node_in_cell[faces[i][j]]); // node 0
1535 }
1536 // Face_info
1537 info() << "face " << face_count << " " << node_in_cell[faces[i][0]] << " " << node_in_cell[faces[i][1]] << " " << node_in_cell[faces[i][2]];
1538 face_count++;
1539 }*/
1540 // New cells
1541 for (Integer i = 0; i < cells.size(); i++) {
1542 // Header
1543 max_offset++;
1544 cells_infos.add(p.cell_type); // type // Dépendant pattern
1545 cells_infos.add(max_offset); // cell uid
1546 // Cell_info
1547 info() << "Cell " << i;
1548 for (Integer j = 0; j < cells[i].size(); j++) {
1549 info() << "test2bis " << node_in_cell[cells[i][j]] << " " << node_in_cell.size() << " " << node_pattern.size();
1550 cells_infos.add(node_in_cell[cells[i][j]]);
1551 }
1552 cellcount++;
1553 }
1554 info() << "test2bisbis ";
1555 for (Integer i = 0; i < node_in_cell.size(); i++) {
1556 info() << "node_in_cell[ " << i << " ] " << node_in_cell[i];
1557 }
1558 info() << "test3 ";
1559 }
1560 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1561 // Debug ici
1562 info() << "test3 " << nodes_uid.size() << " " << nodes_lid.size();
1563 nodes_lid.clear();
1564 nodes_lid.reserve(nodes_uid.size());
1565
1566 modifier->addNodes(nodes_uid, nodes_lid);
1567 info() << "After nodes";
1568 UniqueArray<Int32> faces_lid(face_count);
1569 //modifier->addFaces(face_count, faces_infos, faces_lid);
1570 info() << "After faces";
1571 UniqueArray<Int32> cells_lid(cellcount);
1572
1573 modifier->addCells(cellcount, cells_infos, cells_lid);
1574 info() << "cellsize " << cells_infos.size() << " " << cellcount;
1575 modifier->removeCells(cells_to_detach.constView());
1576 modifier->endUpdate();
1577 // Assignation coords aux nouveaux noeuds
1578 VariableNodeReal3 coords_bis = mesh->nodesCoordinates();
1579
1580 info() << nodes_lid.size();
1581 UniqueArray<Int32> to_add_to_nodes(nodes_uid.size()); // Bis
1582 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_uid, true);
1583
1584 info() << "#NODESHERE";
1585 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) {
1586 Node node = *inode;
1587 coords_bis[node] = nodes_to_add_coords[node.uniqueId()];
1588 info() << "node " << node.uniqueId() << " coord " << nodes_to_add_coords[node.uniqueId()];
1589 info() << node.uniqueId() << " " << nodes_coords[node];
1590 }
1591
1592 //mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output1.vtk", "VtkLegacyMeshWriter");
1593
1594 info() << "#coords" << coords_bis.asArray();
1595 info() << "#My mesh ";
1596 UniqueArray<Int64> stuff;
1597 // Affichage maillage
1598 ENUMERATE_CELL (icell, mesh->allCells()) {
1599 const Cell& cell = *icell;
1600 info() << "Cell " << cell.uniqueId() << " " << cell.nodeIds();
1601 for (Face face : cell.faces()) {
1602 for (Node node : face.nodes()) {
1603 stuff.add(node.uniqueId());
1604 }
1605 info() << "Faces " << face.uniqueId() << " node " << stuff;
1606 }
1607 stuff.clear();
1608 }
1609 info() << "#Arcane face numbering:";
1610 std::cout << "{";
1611 ENUMERATE_FACE (iface, mesh->allFaces()) {
1612 const Face& face = *iface;
1613 UniqueArray<Int64> stuff;
1614 std::cout << "{" << face.nodes()[0].uniqueId().asInt64();
1615
1616 for (Integer i = 1; i < face.nodes().size(); i++) {
1617 std::cout << "," << face.nodes()[i].uniqueId().asInt64();
1618 }
1619 //stuff.add(node_uid_to_cell_local_id[node.uniqueId().asInt64()]);
1620 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1621 //std::cout << node_uid_to_cell_local_id[node.uniqueId().asInt64()] ;
1622
1623 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1624 std::cout << "}," << std::endl;
1625 }
1626 std::cout << "}";
1627 Arcane::VariableScalarInteger m_temperature(Arcane::VariableBuildInfo(mesh, "ArcaneCheckpointNextIteration"));
1628
1629 VariableCellInt64* arcane_cell_uid = nullptr;
1630 VariableFaceInt64* arcane_face_uid = nullptr;
1631 VariableNodeInt64* arcane_node_uid = nullptr;
1632 arcane_cell_uid = new VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_cell_uid", mesh->cellFamily()->name()));
1633 arcane_face_uid = new VariableFaceInt64(Arcane::VariableBuildInfo(mesh, "arcane_face_uid", mesh->faceFamily()->name()));
1634 arcane_node_uid = new VariableNodeInt64(Arcane::VariableBuildInfo(mesh, "arcane_node_uid", mesh->nodeFamily()->name()));
1635
1636 ENUMERATE_CELL (icell, mesh->allCells()) {
1637 (*arcane_cell_uid)[icell] = icell->uniqueId().asInt64();
1638 }
1639 ENUMERATE_FACE (iface, mesh->allFaces()) {
1640 (*arcane_face_uid)[iface] = iface->uniqueId().asInt64();
1641 }
1642 info() << "#INODE";
1643 ENUMERATE_NODE (inode, mesh->allNodes()) {
1644 (*arcane_node_uid)[inode] = inode->uniqueId().asInt64();
1645 info() << inode->uniqueId().asInt64();
1646 }
1647 /*
1648 ENUMERATE_(Node, inode, mesh->nodeFamily()->view().subView(4,nodes_uid.size())){
1649 Node node = *inode;
1650 nodes_coords[node] = nodes_to_add_coords[node.uniqueId()];
1651 info() << node.uniqueId() << " " << nodes_coords[node] ;
1652 }
1653 */
1654 //
1655 // On va chercher le service directement sans utiliser dans le .arc
1656 /*Directory d = mesh->subDomain()->exportDirectory();
1657 info() << "Writing at " << d.path() ;
1658 ServiceBuilder<IPostProcessorWriter> spp(mesh->handle());
1659
1660 Ref<IPostProcessorWriter> post_processor = spp.createReference("Ensight7PostProcessor"); // vtkHdf5PostProcessor
1661 //Ref<IPostProcessorWriter> post_processor = spp.createReference("VtkLegacyMeshWriter"); // (valid values = UCDPostProcessor, UCDPostProcessor, Ensight7PostProcessor, Ensight7PostProcessor)
1662 // Path de base
1663 // <fichier-binaire>false</fichier-binaire>
1664 post_processor->setBaseDirectoryName(d.path());
1665
1666 post_processor->setTimes(UniqueArray<Real>{0.1}); // Juste pour fixer le pas de temps
1667
1668 VariableList variables;
1669 variables.add(mesh->nodesCoordinates().variable());
1670 variables.add(*arcane_node_uid);
1671 variables.add(*arcane_face_uid);
1672 variables.add(*arcane_cell_uid);
1673 post_processor->setVariables(variables);
1674
1675 ItemGroupList groups;
1676 groups.add(mesh->allNodes());
1677 groups.add(mesh->allFaces());
1678 groups.add(mesh->allCells());
1679 post_processor->setGroups(groups);
1680
1681 IVariableMng* vm = mesh->subDomain()->variableMng();
1682
1683 vm->writePostProcessing(post_processor.get());
1684 mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output.vtk", "VtkLegacyMeshWriter");
1685 */
1686 info() << "#ENDSUBDV ";
1687}
1688
1690{
1691 mesh->utilities()->writeToFile("subdivider_one_quad_input.vtk", "VtkLegacyMeshWriter");
1692
1693 // On supprime l'ancien maillage
1694 Int32UniqueArray lids(mesh->allCells().size());
1695 ENUMERATE_CELL (icell, mesh->allCells()) {
1696 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1697 << icell->type() << ", nb nodes=" << icell->nbNode();
1698 lids[icell.index()] = icell->localId();
1699 }
1700 IMeshModifier* modifier = mesh->modifier();
1701 modifier->removeCells(lids);
1702 modifier->endUpdate();
1703
1704 // On creer notre Quad
1705 Int64UniqueArray nodes_uid(4);
1706 for (Integer i = 0; i < 4; i++)
1707 nodes_uid[i] = i;
1708
1709 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1710 modifier->addNodes(nodes_uid, nodes_lid.view());
1711 mesh->nodeFamily()->endUpdate();
1712 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1713 NodeInfoListView new_nodes(mesh->nodeFamily());
1714 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1715 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1716 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1717 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
1718
1719 Int64UniqueArray cells_infos(6);
1720 Int64UniqueArray faces_infos;
1721 cells_infos[0] = IT_Quad4; // type
1722 cells_infos[1] = 44; // cell uid
1723 cells_infos[2] = nodes_uid[0]; // node 0
1724 cells_infos[3] = nodes_uid[1]; // ... 1
1725 cells_infos[4] = nodes_uid[2]; // ... 2
1726 cells_infos[5] = nodes_uid[3]; // ... 3
1727
1728 IntegerUniqueArray cells_lid;
1729 modifier->addCells(1, cells_infos, cells_lid);
1730 modifier->endUpdate();
1731 mesh->utilities()->writeToFile("subdivider_one_quad_ouput.vtk", "VtkLegacyMeshWriter");
1732}
1733
1734
1736{
1737 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
1738 // On supprime l'ancien maillage
1739 Int32UniqueArray lids(mesh->allCells().size());
1740 ENUMERATE_CELL (icell, mesh->allCells()) {
1741 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1742 << icell->type() << ", nb nodes=" << icell->nbNode();
1743 lids[icell.index()] = icell->localId();
1744 }
1745 IMeshModifier* modifier = mesh->modifier();
1746 modifier->removeCells(lids);
1747 modifier->endUpdate();
1748 // On creer notre Hexa
1749 Int64UniqueArray nodes_uid(3);
1750 for (Integer i = 0; i < 3; i++)
1751 nodes_uid[i] = i;
1752
1753 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1754 modifier->addNodes(nodes_uid, nodes_lid.view());
1755 mesh->nodeFamily()->endUpdate();
1756 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1757 NodeInfoListView new_nodes(mesh->nodeFamily());
1758 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1759 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1760 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1761
1762 Int64UniqueArray cells_infos(10);
1763 Int64UniqueArray faces_infos;
1764 cells_infos[0] = IT_Triangle3; // type
1765 cells_infos[1] = 44; // cell uid
1766 cells_infos[2] = nodes_uid[0]; // node 0
1767 cells_infos[3] = nodes_uid[1]; // ... 1
1768 cells_infos[4] = nodes_uid[2]; // ... 2
1769
1770 IntegerUniqueArray cells_lid;
1771 modifier->addCells(1, cells_infos, cells_lid);
1772 modifier->endUpdate();
1773 mesh->utilities()->writeToFile("subdivider_one_tri.vtk", "VtkLegacyMeshWriter");
1774}
1775
1777{
1778 UniqueArray<Int64> new_node_uid;
1779 Integer init_size = node_in_cell.size();
1780 for (Integer i = 0; i < node_pattern.size(); i++) {
1781 //info() << "test " << i ;
1782 UniqueArray<Int64> tmp = node_pattern[i];
1783 tmp.resize(node_pattern[i].size());
1784 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1785 tmp.add(node_in_cell[node_pattern[i][j]]);
1786 }
1787 // uid
1788 std::sort(tmp.begin(), tmp.end());
1789 node_in_cell.add(init_size + i); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
1790 new_node_uid.add(node_in_cell[init_size + i]);
1791 }
1792 return new_node_uid;
1793}
1794
1795ArcaneBasicMeshSubdividerService::
1796ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi)
1798{
1799}
1800
1802{
1803 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
1804 // On supprime l'ancien maillage
1805 Int32UniqueArray lids(mesh->allCells().size());
1806 ENUMERATE_CELL (icell, mesh->allCells()) {
1807 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1808 << icell->type() << ", nb nodes=" << icell->nbNode();
1809 lids[icell.index()] = icell->localId();
1810 }
1811 IMeshModifier* modifier = mesh->modifier();
1812 modifier->removeCells(lids);
1813 modifier->endUpdate();
1814 // On creer notre Hexa
1815 Int64UniqueArray nodes_uid(8);
1816 for (Integer i = 0; i < 8; i++)
1817 nodes_uid[i] = i;
1818
1819 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1820 modifier->addNodes(nodes_uid, nodes_lid.view());
1821 mesh->nodeFamily()->endUpdate();
1822 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1823 NodeInfoListView new_nodes(mesh->nodeFamily());
1824 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1825 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1826 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1827 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
1828 nodes_coords[new_nodes[nodes_lid[4]]] = Arcane::Real3(0.0, 0.0, 10.0);
1829 nodes_coords[new_nodes[nodes_lid[5]]] = Arcane::Real3(10.0, 0.0, 10.0);
1830 nodes_coords[new_nodes[nodes_lid[6]]] = Arcane::Real3(10.0, 10.0, 10.0);
1831 nodes_coords[new_nodes[nodes_lid[7]]] = Arcane::Real3(0.0, 10.0, 10.0);
1832
1833 Int64UniqueArray cells_infos(10);
1834 Int64UniqueArray faces_infos;
1835 cells_infos[0] = IT_Hexaedron8; // type
1836 cells_infos[1] = 44; // cell uid
1837 cells_infos[2] = nodes_uid[0]; // node 0
1838 cells_infos[3] = nodes_uid[1]; // ... 1
1839 cells_infos[4] = nodes_uid[2]; // ... 2
1840 cells_infos[5] = nodes_uid[3]; // ... 3
1841 cells_infos[6] = nodes_uid[4]; // ... 4
1842 cells_infos[7] = nodes_uid[5]; // ... 5
1843 cells_infos[8] = nodes_uid[6]; // ... 6
1844 cells_infos[9] = nodes_uid[7]; // ... 7
1845
1846 IntegerUniqueArray cells_lid;
1847 modifier->addCells(1, cells_infos, cells_lid);
1848 modifier->endUpdate();
1849 // On crée un groupe test
1850 UniqueArray<Int64> face_uid;
1851 ENUMERATE_FACE (iface, mesh->allFaces()) {
1852 Face face = *iface;
1853 face_uid.add(face.uniqueId());
1854 }
1855 UniqueArray<Int32> face_lid(face_uid.size());
1856 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
1857 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
1858 mesh->utilities()->writeToFile("subdivider_one_hexa_ouput.vtk", "VtkLegacyMeshWriter");
1859}
1860
1862{
1863
1864 mesh->utilities()->writeToFile("subdivider_one_tetra_input.vtk", "VtkLegacyMeshWriter");
1865
1866 // On supprime l'ancien maillage si besoin
1867 Int32UniqueArray lids(mesh->allCells().size());
1868 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1869 ENUMERATE_CELL (icell, mesh->allCells()) {
1870 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1871 << icell->type() << ", nb nodes=" << icell->nbNode();
1872 lids[icell.index()] = icell->localId();
1873 }
1874 IMeshModifier* modifier = mesh->modifier();
1875 modifier->removeCells(lids);
1876 modifier->endUpdate();
1877
1878 // Maillage vide, on créer notre tetra
1879
1880 info() << "===================== THE MESH IS EMPTY";
1881
1882 // On ajoute des noeuds
1883 Int64UniqueArray nodes_uid(4);
1884 for (Integer i = 0; i < 4; i++)
1885 nodes_uid[i] = i;
1886
1887 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1888 modifier->addNodes(nodes_uid, nodes_lid.view());
1889 mesh->nodeFamily()->endUpdate();
1890 info() << "===================== THE MESH IS EMPTY";
1891
1892 NodeInfoListView new_nodes(mesh->nodeFamily());
1893
1894 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1895 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1896 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(5.0, 5.0 / 3.0, 10.0);
1897 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(5.0, 5.0, 0.0);
1898
1899 Int64UniqueArray cells_infos(1 * 6);
1900 Int64UniqueArray faces_infos;
1901
1902 cells_infos[0] = IT_Tetraedron4; // type
1903 cells_infos[1] = 44; // cell uid
1904 cells_infos[2] = nodes_uid[0]; // node 0
1905 cells_infos[3] = nodes_uid[1]; // ... 1
1906 cells_infos[4] = nodes_uid[2]; // ... 2
1907 cells_infos[5] = nodes_uid[3]; // ... 3
1908
1909 IntegerUniqueArray cells_lid;
1910 modifier->addCells(1, cells_infos, cells_lid);
1911 modifier->endUpdate();
1912
1913 // On crée un groupe test
1914 UniqueArray<Int64> face_uid;
1915 ENUMERATE_FACE (iface, mesh->allFaces()) {
1916 Face face = *iface;
1917 face_uid.add(face.uniqueId());
1918 }
1919 UniqueArray<Int32> face_lid(face_uid.size());
1920 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
1921 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
1922
1923 info() << "===================== THE CELLS ARE ADDED";
1924}
1925
1926/* Le but est simplement d'avoir l'ordre des faces dans un élément*/
1928{
1929 mesh->utilities()->writeToFile("3D_last_input_seq.vtk", "VtkLegacyMeshWriter");
1930 info() << "#ORDRE FACES";
1931 ENUMERATE_CELL (icell, mesh->ownCells()) {
1932
1933 const Cell& cell = *icell;
1934 for (Face face : cell.faces()) {
1936 for (Node node : face.nodes()) {
1937 n.add(node.uniqueId().asInt64());
1938 }
1939 info() << face.uniqueId() << " nodes " << n;
1940 }
1941 }
1942}
1943
1945subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh)
1946{
1947 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
1948 // Default pattern manager
1949 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
1950 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1951 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
1952 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
1953
1954 if(options()->differentElementTypeOutput()){
1955 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
1956 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
1957 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
1958 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
1959 info() << "The refinement patterns have changed for meshes of the following types: Quad4, Triangle3, Hexaedron8, Tetraedron4." ;
1960 info() << "The output element types will be:\nQuad4->Triangle3\nTriangle3->Quad4\nHexaedron8->Tetraedron4\nTetraedron4->Hexaedron8" ;
1961 }
1962
1963 for (Integer i = 0; i < options()->nbSubdivision; i++) {
1964 _refineOnce(mesh, pattern_manager);
1965 debug() << i << "refine done";
1966 }
1967
1968 // Debug After
1969
1970 //mesh->utilities()->writeToFile("subdivider_output_"+std::to_string(mesh->parallelMng()->commRank())+".vtk", "VtkLegacyMeshWriter");
1971
1972
1973 //mesh->utilities()->writeToFile("subdivider_after_" + std::to_string(options()->nbSubdivision) + "refine.vtk", "VtkLegacyMeshWriter");
1974 //debug() << "write file with name:" << "subdivider_after_";
1975 /*
1976 mesh->utilities()->writeToFile("subdivider_output.vtk", "VtkLegacyMeshWriter");
1977 */
1978}
1979
1980/*---------------------------------------------------------------------------*/
1981/*---------------------------------------------------------------------------*/
1982
1983ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
1985
1986/*---------------------------------------------------------------------------*/
1987/*---------------------------------------------------------------------------*/
1988
1989} // End namespace Arcane
1990
1991/*---------------------------------------------------------------------------*/
1992/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions utilitaires sur le maillage.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Génère un identifiant unique à partir d'une liste d'identifiants de noeuds.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
ArcaneArcaneBasicMeshSubdividerServiceObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsArcaneBasicMeshSubdividerService * options() const
Options du jeu de données du service.
Service Arcane un maillage du jeu de données.
static UniqueArray< Int64 > _computeNodeUid(UniqueArray< Int64 > nodes_uid, const StorageRefine &node_pattern)
Calcule le unique id en fonction des noeuds de node_uid.
void _generatePattern2D(IPrimaryMesh *mesh)
Methode pour obtenir les fichier vtk pour les différent pattern disponibles en 2D.
void _generatePattern3D(IPrimaryMesh *mesh)
Methode pour obtenir les fichier vtk pour les différent pattern disponibles en 3D.
void subdivideMesh(IPrimaryMesh *mesh) override
Raffine le maillage un nombre nb-subdivision.
void _generateOneTri(IPrimaryMesh *mesh)
Génère un triangle.
void _generateOneQuad(IPrimaryMesh *mesh)
Génère un quadrilatère.
void _getArcaneOrder(IPrimaryMesh *mesh)
Methode pour avoir la manière dont sont crée les nouvelles faces pour un élément. Utile pour remplir ...
void _generatePattern(IPrimaryMesh *mesh)
Méthode pour générer les motifs sur un seul élément de base.
void _refineOnce(IPrimaryMesh *mesh, std::unordered_map< Arccore::Int16, MeshSubdivider::Pattern > &pattern_manager)
Raffine une fois le maillage avec les motifs présent dans le pattern_manager.
void _generateOneTetra(IPrimaryMesh *mesh)
Génère un tetraèdre.
void _faceOrderArcane(IPrimaryMesh *mesh)
Génère l'ordre des faces arcane pour tout les motifs.
void _refineWithArcaneFaces(IPrimaryMesh *mesh, MeshSubdivider::Pattern p)
Raffine en utilisant les faces d'arcane et le motif (Pattern) p.
void _generateOneHexa(IPrimaryMesh *mesh)
Génère un hexaèdre.
void clear()
Supprime les éléments du tableau.
iterator end()
Itérateur sur le premier élément après la fin du tableau.
ConstArrayView< T > constView() const
Vue constante sur ce tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sous-vue à partir de l'élément abegin et contenant asize éléments.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
ArrayView< T > view() const
Vue mutable sur ce tableau.
iterator begin()
Itérateur sur le premier élément du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Maille d'un maillage.
Definition Item.h:1191
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1272
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1269
Integer count() const
Nombre d'éléments de la collection.
Definition Collection.h:70
EnumeratorT< ItemGroup > Enumerator
Definition Collection.h:129
Face d'une maille.
Definition Item.h:944
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1633
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1025
virtual void setBuilderVersion(Integer n)=0
Positionne la version du constructeur de mailles fantômes. Pour l'instant (version 3....
virtual Integer nbGhostLayer() const =0
Nombre de couches fantômes.
virtual Integer builderVersion() const =0
Version du constructeur de mailles fantômes.
virtual void setNbGhostLayer(Integer n)=0
Positionne le nombre de couches fantômes.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroupCollection groups() const =0
Liste des groupes de cette famille.
virtual Integer nbItem() const =0
Nombre d'entités.
Interface de modification du maillage.
virtual void updateGhostLayers()=0
Mise à jour de la couche fantôme.
virtual void setDynamic(bool v)=0
Positionne la propriété indiquant si le maillage peut évoluer.
virtual void removeCells(Int32ConstArrayView cells_local_id)=0
Supprime des mailles.
virtual void addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes_lid=Int32ArrayView())=0
Ajoute des noeuds.
virtual void addCells(Integer nb_cell, Int64ConstArrayView cell_infos, Int32ArrayView cells_lid=Int32ArrayView())=0
Ajoute des mailles.
virtual void endUpdate()=0
Notifie l'instance de la fin de la modification du maillage.
SentinelType end() const
Itérateur sur après la dernière entité connectée.
const_iterator begin() const
Itérateur sur la première entité connectée.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
Definition ItemGroup.cc:157
const String & fullName() const
Nom du groupe.
Definition ItemGroup.h:82
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Ajoute des entités.
Definition ItemGroup.cc:445
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Definition ItemGroup.cc:609
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:779
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:782
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:776
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Definition Item.h:785
Classe de base d'un élément de maillage.
Definition Item.h:83
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
Definition Item.h:374
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
ItemTypeId itemTypeId() const
Type de l'entité
Definition Item.h:244
Int16 type() const
Type de l'entité
Definition Item.h:241
Classe Pattern qui permet de manipuler un motif (pattern en anglais) de raffinement.
StorageRefine faces
Matrice pour la génération des nouvelles faces.
StorageRefine cells
Matrice pour la génération des nouvelles cellules.
Int16 type
Type de l'élément a rafiner.
StorageRefine nodes
Matrice pour la génération des nouveaux noeuds.
Int16 face_type
Type de la face de l'élément a rafiner.
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:573
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1584
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:680
Classe qui permet de construire des patterns.
Integer arraySize() const
Si la variable est un tableau, retourne sa dimension, sinon retourne 0.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Grandeur au centre des mailles de type entier 64 bits.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
MeshVariableScalarRefT< Node, Int64 > VariableNodeInt64
Grandeur au noeud de type entier 64 bits.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Grandeur aux faces de type entier 64 bits.
VariableRefScalarT< Integer > VariableScalarInteger
Variable scalaire de type entier.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:426
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:428
std::int16_t Int16
Type entier signé sur 16 bits.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:434
std::int32_t Int32
Type entier signé sur 32 bits.