Arcane  v3.15.3.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
76 Int16 type;
78 Int16 face_type;
80 Int16 cell_type;
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
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/*---------------------------------------------------------------------------*/
763{
764 public:
765
768 void subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh) override;
769
770 private:
771
772 void _init();
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
790 void _faceOrderArcane(IPrimaryMesh* mesh);
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 */
798 void _generateOneTri(IPrimaryMesh* mesh);
800 void _generateOneQuad(IPrimaryMesh* mesh);
804 void _generateOneHexa(IPrimaryMesh* mesh);
806 void _refineOnce([[maybe_unused]] IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
814 void _generatePattern(IPrimaryMesh* mesh);
815};
816
818{
819 if (mesh->dimension() == 2) {
820 _generatePattern2D(mesh);
821 }
822 else if (mesh->dimension() == 3) {
823 _generatePattern3D(mesh);
824 }
825}
826
828{
829 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
830
831 mesh->faceFamily()->destroyGroups();
832 _generateOneTri(mesh);
833 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
835 std::string prefix("subdivider_pattern2D_");
836 mesh->utilities()->writeToFile(prefix + "tritotri.vtk", "VtkLegacyMeshWriter");
837
838 mesh->faceFamily()->destroyGroups();
839 _generateOneTri(mesh);
840 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
842 mesh->utilities()->writeToFile(prefix + "tritoquad.vtk", "VtkLegacyMeshWriter");
843
844 mesh->faceFamily()->destroyGroups();
845 _generateOneQuad(mesh);
846 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
848 mesh->utilities()->writeToFile(prefix + "quadtoquad.vtk", "VtkLegacyMeshWriter");
849
850 mesh->faceFamily()->destroyGroups();
851 _generateOneQuad(mesh);
852 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
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();
862 _generateOneTetra(mesh);
863 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
865 mesh->utilities()->writeToFile(prefix + "tettotet.vtk", "VtkLegacyMeshWriter");
866
867 mesh->faceFamily()->destroyGroups();
868 _generateOneTetra(mesh);
869 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
871 mesh->utilities()->writeToFile(prefix + "tettohex.vtk", "VtkLegacyMeshWriter");
872
873 mesh->faceFamily()->destroyGroups();
874 _generateOneHexa(mesh);
875 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
877 mesh->utilities()->writeToFile(prefix + "hextohex.vtk", "VtkLegacyMeshWriter");
878
879 mesh->faceFamily()->destroyGroups();
880 _generateOneHexa(mesh);
881 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
883 mesh->utilities()->writeToFile(prefix + "hextotet24.vtk", "VtkLegacyMeshWriter");
884
885 mesh->faceFamily()->destroyGroups();
886 _generateOneHexa(mesh);
887 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
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();
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
982
983 Integer nb_cell_to_add = 0;
984 Integer nb_face_to_add = 0;
985
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
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
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
1079 node_in_cell.resize(node_pattern.size() + cell.nbNode()); // pattern dépendant
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());
1100 Int64 uid = MeshUtils::generateHashUniqueId(tmp.constView());
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
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
1154 Int64 uid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
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]] ;
1165 }
1166 // Ajouter dans tableau uids faces
1167 faces_uids.add(uid);
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++) {
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
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();
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
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
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
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
1278
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();
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 ";
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
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 ";
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;
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
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
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 << " Attendu " << 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;
1453 std::unordered_map<Int64, Real3> nodes_to_add_coords;
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() << " Noeuds ";
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()) {
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;
1504 // New nodes and coords
1505 for (Integer i = 0; i < node_pattern.size(); i++) {
1506 info() << "test " << 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();
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 }
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";
1569 //modifier->addFaces(face_count, faces_infos, faces_lid);
1570 info() << "After faces";
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
1579
1580 info() << nodes_lid.size();
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 ";
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;
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
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
1706 for (Integer i = 0; i < 4; i++)
1707 nodes_uid[i] = i;
1708
1710 modifier->addNodes(nodes_uid, nodes_lid.view());
1711 mesh->nodeFamily()->endUpdate();
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
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
1750 for (Integer i = 0; i < 3; i++)
1751 nodes_uid[i] = i;
1752
1754 modifier->addNodes(nodes_uid, nodes_lid.view());
1755 mesh->nodeFamily()->endUpdate();
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
1771 modifier->addCells(1, cells_infos, cells_lid);
1772 modifier->endUpdate();
1773 mesh->utilities()->writeToFile("subdivider_one_tri.vtk", "VtkLegacyMeshWriter");
1774}
1775
1777{
1779 Integer init_size = node_in_cell.size();
1780 for (Integer i = 0; i < node_pattern.size(); i++) {
1781 //info() << "test " << 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());
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
1816 for (Integer i = 0; i < 8; i++)
1817 nodes_uid[i] = i;
1818
1820 modifier->addNodes(nodes_uid, nodes_lid.view());
1821 mesh->nodeFamily()->endUpdate();
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
1847 modifier->addCells(1, cells_infos, cells_lid);
1848 modifier->endUpdate();
1849 // On crée un groupe test
1851 ENUMERATE_FACE (iface, mesh->allFaces()) {
1852 Face face = *iface;
1853 face_uid.add(face.uniqueId());
1854 }
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());
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
1884 for (Integer i = 0; i < 4; i++)
1885 nodes_uid[i] = i;
1886
1888 modifier->addNodes(nodes_uid, nodes_lid.view());
1889 mesh->nodeFamily()->endUpdate();
1890 info() << "===================== THE MESH IS EMPTY";
1891
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
1910 modifier->addCells(1, cells_infos, cells_lid);
1911 modifier->endUpdate();
1912
1913 // On crée un groupe test
1915 ENUMERATE_FACE (iface, mesh->allFaces()) {
1916 Face face = *iface;
1917 face_uid.add(face.uniqueId());
1918 }
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
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 for (Integer i = 0; i < options()->nbSubdivision; i++) {
1956 debug() << i << "refine done";
1957 }
1958 /*
1959 // Debug After
1960 mesh->utilities()->writeToFile("subdivider_after_" + std::to_string(options()->nbSubdivision) + "refine.vtk", "VtkLegacyMeshWriter");
1961 mesh->utilities()->writeToFile("subdivider_output.vtk", "VtkLegacyMeshWriter");
1962 */
1963}
1964
1965/*---------------------------------------------------------------------------*/
1966/*---------------------------------------------------------------------------*/
1967
1968ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
1970
1971/*---------------------------------------------------------------------------*/
1972/*---------------------------------------------------------------------------*/
1973
1974} // End namespace Arcane
1975
1976/*---------------------------------------------------------------------------*/
1977/*---------------------------------------------------------------------------*/
#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.
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.
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
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
Interface d'une famille d'entités.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual Integer nbCell()=0
Nombre de mailles du maillage.
virtual CellGroup ownCells()=0
Groupe de toutes les mailles propres au domaine.
virtual FaceGroup ownFaces()=0
Groupe de toutes les faces propres au domaine.
virtual FaceGroup allFaces()=0
Groupe de toutes les faces.
virtual Integer nbEdge()=0
Nombre d'arêtes du maillage.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual Integer nbFace()=0
Nombre de faces du maillage.
virtual IItemFamily * cellFamily()=0
Retourne la famille des mailles.
Interface de modification du maillage.
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.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IMeshModifier * modifier()=0
Interface de modification associée.
virtual IMeshUtilities * utilities()=0
Interface des fonctions utilitaires associée.
virtual IGhostLayerMng * ghostLayerMng() const =0
Gestionnare de couche fantômes associé
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
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
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
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.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
Paramètres nécessaires à la construction d'une variable.
Integer size() const
Nombre d'éléments du vecteur.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
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).
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Grandeur au centre des mailles de type entier 64 bits.
MeshVariableScalarRefT< Node, Int64 > VariableNodeInt64
Grandeur au noeud de type entier 64 bits.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Grandeur aux faces de type entier 64 bits.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-