Arcane  v4.1.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-2026 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-2026 */
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// renumbering
50#include "arcane/core/IndexedItemConnectivityView.h"
51#include "arcane/core/IIndexedIncrementalItemConnectivityMng.h"
52#include "arcane/core/IIndexedIncrementalItemConnectivity.h"
53#include "arcane/core/IIncrementalItemConnectivity.h"
54
55//
56#include "arcane/utils/IHashAlgorithm.h"
57#include "arcane/utils/MD5HashAlgorithm.h"
58
59// Utils
60#include <unordered_set>
61#include <algorithm>
62#include <iterator>
63#include <map>
64
65#include "arcane/core/Timer.h"
66#include "arccore/trace/ITraceMng.h"
67
68//#include <parmetis.h>
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73namespace Arcane
74{
75
76typedef UniqueArray<UniqueArray<Int64>> StorageRefine;
77namespace MeshSubdivider
78{
79
80 /*---------------------------------------------------------------------------*/
81 /*---------------------------------------------------------------------------*/
85 class Pattern
86 {
87 public:
88
96 StorageRefine nodes;
98 StorageRefine faces;
100 StorageRefine cells;
101 StorageRefine child_faces; // Lien entre faces de la cellule mère et les faces de la cellule fille.
102 // ^-- 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.
103 // 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.
104 // Pour l'instant elles ne sont juste pas dans les groupes.
105
106 // 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.
107 // Pour les childs faces
108
109 public:
110
111 Pattern()
112 : type(IT_NullType)
113 , face_type(IT_NullType)
114 , cell_type(IT_NullType)
115 {}
116
117 Pattern(Int16 type, Int16 face_type, Int16 cell_type, StorageRefine nodes, StorageRefine faces, StorageRefine cells, StorageRefine child_faces)
118 {
119 this->type = type;
120 this->face_type = face_type;
121 this->cell_type = cell_type;
122 this->nodes = nodes;
123 this->faces = faces;
124 this->cells = cells;
125 this->child_faces = child_faces;
126 }
127
128 Pattern(Pattern&& other) noexcept
129 : type(other.type)
130 , face_type(other.face_type)
131 , cell_type(other.cell_type)
132 , nodes(other.nodes)
133 , faces(other.faces)
134 , cells(other.cells)
135 , child_faces(other.child_faces)
136 {}
137
138 Pattern(const Pattern&) = delete;
139
140 Pattern(Pattern& other) noexcept
141 : type(other.type)
142 , face_type(other.face_type)
143 , cell_type(other.cell_type)
144 , nodes(other.nodes)
145 , faces(other.faces)
146 , cells(other.cells)
147 , child_faces(other.child_faces)
148 {}
149 Pattern& operator=(const Pattern& other)
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; // Référence partagée
156 faces = other.faces; // Référence partagée
157 cells = other.cells; // Référence partagée
158 child_faces = other.child_faces;
159 }
160 return *this;
161 }
162
163 Pattern& operator=(Pattern&& other) noexcept
164 {
165 if (this != &other) {
166 type = other.type;
167 face_type = other.face_type;
168 cell_type = other.cell_type;
169 nodes = other.nodes;
170 faces = other.faces;
171 cells = other.cells;
172 child_faces = other.child_faces;
173 }
174 return *this;
175 }
176 Pattern& operator=(Pattern& other) noexcept
177 {
178 if (this != &other) {
179 type = other.type;
180 face_type = other.face_type;
181 cell_type = other.cell_type;
182 nodes = other.nodes;
183 faces = other.faces;
184 cells = other.cells;
185 child_faces = other.child_faces;
186 }
187 return *this;
188 }
189 };
190
191} // namespace MeshSubdivider
196{
197 public:
198
199 // 2D
200 // TODO test + f + cf
201 static MeshSubdivider::Pattern quadtoquad();
202 // TODO test + f + cf
203 static MeshSubdivider::Pattern quadtotri();
204 // TODO test + f + cf
205 static MeshSubdivider::Pattern tritotri();
206 // TODO test + f + cf
207 static MeshSubdivider::Pattern tritoquad();
208 // 3D
209 // N'utilise pas la numérotation des faces de arcane pour l'instant
210 static MeshSubdivider::Pattern hextohex();
211
212 static MeshSubdivider::Pattern tettotet();
213
214 static MeshSubdivider::Pattern hextotet(); // Ne fonctionne pas car on ne prend pas en compte la rotation.
215
216 static MeshSubdivider::Pattern tettohex();
217
218 static MeshSubdivider::Pattern hextotet24();
219};
220
221/*
222
223Noeuds
224(3) --- (2)
225 | |
226 | |
227(0) --- (1)
228Ordre des arêtes
229(3) -2- (2)
230 | |
231 3 1
232 | |
233(0) -0- (1)
234Nouveaux noeuds
235(3) -6- (2)
236 | |
237 7 8 5
238 | |
239(0) -4- (1)
240Nouveaux noeuds avec ordre nouvelles arêtes
241(3) -5- (6) -7- (2)
242| | |
2434 6 8
244| | |
245(7) -1- (8) -9- (5)
246| | |
2470 2 10
248| | |
249(0) -3- (4) -11- (1)
250 --- ---
251| | |
252| | |
253 --- ---
254| | |
255| | |
256 --- ---
257*/
258MeshSubdivider::Pattern PatternBuilder::quadtoquad()
259{
260 StorageRefine nodes({
261 { 0, 1 }, // 4
262 { 1, 2 }, // 5
263 { 2, 3 }, // 6
264 { 3, 0 }, // 7
265 { 0, 1, 2, 3 }, // 8
266 });
267 StorageRefine faces({
268 { 0, 7 }, // 0
269 { 7, 8 }, // 1
270 { 4, 8 }, // 2
271 { 0, 4 }, // 3
272 { 3, 7 }, // 4
273 { 3, 6 }, // 5
274 { 6, 8 }, // 6
275 { 2, 6 }, // 7
276 { 2, 5 }, // 8
277 { 5, 8 }, // 9
278 { 1, 5 }, // 10
279 { 1, 4 }, // 11
280 });
281 StorageRefine cells({
282 { 0, 7, 8, 4 },
283 { 7, 3, 6, 8 },
284 { 6, 2, 5, 8 },
285 { 5, 1, 4, 8 },
286 });
287 StorageRefine child_faces({
288 // pas testé
289 { 3, 11 },
290 { 10, 8 },
291 { 5, 7 },
292 { 0, 4 },
293 });
294 return { IT_Quad4, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
295}
296
297/*
298 * Pour un quad:
299 * 3 --- 2
300 * | |
301 * | |
302 * 0 --- 1
303 *
304 * 3 --> 2
305 * | / |
306 * | / |
307 * 0 <-- 1
308 *
309 * 3 --- 4 --- 5
310 * | | |
311 * | | |
312 * 0 --- 1 --- 2
313 * Ici on ajoute une seule face arcane (0,2).
314*/
315MeshSubdivider::Pattern PatternBuilder::quadtotri()
316{
317 StorageRefine nodes({}); // Pas de noeud à ajouter
318 StorageRefine faces({
319 /*{0,1},
320 {1,3},
321 {2,3},*/
322 { 0, 2 },
323 //{0,3}
324 });
325 StorageRefine cells({ { 0, 3, 2 }, { 2, 1, 0 } });
326 StorageRefine child_faces({});
327 return { IT_Quad4, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
328}
329
330/*
331 Numérotation nouveaux noeuds
332 2
333 / \
334 / \
335 5 --- 4
336 / \ / \
337 / \ / \
338 0 --- 3 --- 1
339
340 Numérotation arêtes
341 2
342 / \
343 6 7
344 / \
345 + --8-- +
346 / \ / \
347 1 2 5 3
348 / \ / \
349 + --0-- + --4-- +
350 */
351
352MeshSubdivider::Pattern PatternBuilder::tritotri()
353{
354 StorageRefine nodes({
355 { 0, 1 }, // 3
356 { 1, 2 }, // 4
357 { 2, 0 }, // 5
358 });
359 StorageRefine faces({
360 { 0, 3 },
361 { 0, 5 },
362 { 3, 5 },
363 { 1, 4 },
364 { 1, 3 },
365 { 3, 4 },
366 { 2, 5 },
367 { 2, 4 },
368 { 4, 5 },
369 });
370 StorageRefine cells({ { 3, 0, 5 },
371 { 4, 1, 3 },
372 { 5, 2, 4 },
373 { 3, 5, 4 } });
374 StorageRefine child_faces(
375 { { 0, 4 },
376 { 3, 7 },
377 { 1, 6 } });
378 return { IT_Triangle3, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
379}
380
381MeshSubdivider::Pattern PatternBuilder::tritoquad()
382{
383 StorageRefine nodes({
384 { 0, 1 }, // 3
385 { 1, 2 }, // 4
386 { 2, 0 }, // 5
387 { 0, 1, 2 }, // 6
388 });
389 StorageRefine faces({
390
391 });
392 StorageRefine cells({
393 { 0, 3, 6, 5 },
394 { 1, 4, 6, 3 },
395 { 2, 5, 6, 4 },
396 });
397 StorageRefine child_faces({});
398 return { IT_Triangle3, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
399}
400
401// N'utilise pas la numérotation des faces de arcane pour l'instant
402MeshSubdivider::Pattern PatternBuilder::hextohex()
403{
404 StorageRefine nodes = {
405 { 0, 1 }, // 8 // Sur arêtes
406 { 0, 3 }, // 9
407 { 0, 4 }, // 10
408 { 1, 2 }, // 11
409 { 1, 5 }, // 12
410 { 2, 3 }, // 13
411 { 2, 6 }, // 14
412 { 3, 7 }, // 15
413 { 4, 5 }, // 16
414 { 4, 7 }, // 17
415 { 5, 6 }, // 18
416 { 6, 7 }, // 19
417 { 0, 1, 2, 3 }, // 20 // Sur faces
418 { 0, 1, 5, 4 }, // 21
419 { 0, 4, 7, 3 }, // 22
420 { 1, 5, 6, 2 }, // 23
421 { 2, 3, 7, 6 }, // 24
422 { 4, 5, 6, 7 }, // 25
423 { 0, 1, 5, 4, 3, 2, 7, 6 } // 26 // Centroid
424 };
425 StorageRefine faces = {
426 // Externes
427 { 0, 8, 20, 9 }, // Derrière // 0 1 2 3 // 0
428 { 9, 20, 13, 3 },
429 { 8, 1, 11, 20 },
430 { 20, 11, 2, 13 },
431 { 0, 10, 22, 9 }, // Gauche // 0 3 7 4 // 1
432 { 9, 22, 15, 3 },
433 { 10, 4, 17, 22 },
434 { 22, 17, 7, 15 },
435 { 4, 16, 21, 10 }, // Bas // 4 5 0 1 // 2
436 { 10, 21, 8, 0 },
437 { 16, 5, 12, 21 },
438 { 21, 12, 1, 8 },
439 { 4, 16, 25, 17 }, // Devant // 4 5 6 7 // 3
440 { 17, 25, 19, 7 },
441 { 16, 5, 18, 25 },
442 { 25, 18, 6, 19 },
443 { 1, 12, 23, 11 }, // Droite // 1 2 5 6 // 4
444 { 11, 23, 14, 2 },
445 { 12, 5, 18, 23 },
446 { 23, 18, 6, 14 },
447 { 7, 19, 24, 15 }, // Haut // 7 6 2 3 // 5
448 { 19, 6, 14, 24 },
449 { 15, 24, 13, 3 },
450 { 24, 14, 2, 13 },
451 // Internes
452 { 8, 20, 26, 21 },
453 { 20, 13, 24, 26 },
454 { 9, 22, 26, 20 },
455 { 20, 26, 23, 11 },
456 { 21, 16, 25, 26 },
457 { 26, 25, 19, 24 },
458 { 22, 17, 25, 26 },
459 { 26, 25, 18, 23 },
460 { 10, 21, 26, 22 },
461 { 21, 12, 23, 26 },
462 { 22, 26, 24, 15 },
463 { 26, 23, 14, 24 },
464
465 };
466 StorageRefine child_faces = {
467 { 0, 1, 2, 3 },
468 { 4, 5, 6, 7 },
469 { 8, 9, 10, 11 },
470 { 12, 13, 14, 15 },
471 { 16, 17, 18, 19 },
472 { 20, 21, 22, 23 }
473 };
474 StorageRefine cells = {
475 { 0, 8, 20, 9, 10, 21, 26, 22 },
476 { 10, 21, 26, 22, 4, 16, 25, 17 },
477 { 8, 1, 11, 20, 21, 12, 23, 26 },
478 { 21, 12, 23, 26, 16, 5, 18, 25 },
479 { 9, 20, 13, 3, 22, 26, 24, 15 },
480 { 22, 26, 24, 15, 17, 25, 19, 7 },
481 { 20, 11, 2, 13, 26, 23, 14, 24 },
482 { 26, 23, 14, 24, 25, 18, 6, 19 }
483 };
484 return { IT_Hexaedron8, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
485}
486
487MeshSubdivider::Pattern PatternBuilder::tettotet()
488{
489 StorageRefine nodes = {
490 { 0, 1 }, // 4
491 { 1, 2 }, // 5
492 { 0, 2 }, // 6
493 { 0, 3 }, // 7
494 { 2, 3 }, // 8
495 { 1, 3 }, // 9
496 };
497
498 StorageRefine faces = {
499 { 0, 4, 6 }, // 0
500 { 0, 6, 7 }, // 1
501 { 0, 4, 7 }, // 2
502 { 4, 6, 7 }, // 3
503 { 1, 4, 5 }, // 4
504 { 4, 5, 9 }, // 5
505 { 1, 4, 9 }, // 6
506 { 1, 5, 9 }, // 7
507 { 2, 5, 6 }, // 8
508 { 2, 6, 8 }, // 9
509 { 5, 6, 8 }, // 10
510 { 2, 5, 8 }, // 11
511 { 7, 8, 9 }, // 12
512 { 3, 7, 8 }, // 13
513 { 3, 7, 9 }, // 14
514 { 3, 8, 9 }, // 15
515 { 4, 7, 9 }, // 16
516 { 4, 6, 9 }, // 17
517 { 6, 7, 9 }, // 18
518 { 4, 5, 6 }, // 19
519 { 5, 6, 9 }, // 20
520 { 6, 8, 9 }, // 21
521 { 6, 7, 8 }, // 22
522 { 5, 8, 9 }, // 23
523 };
524 StorageRefine child_faces = {
525 { 0, 19, 4, 8 },
526 { 1, 22, 13, 9 },
527 { 2, 16, 6, 14 },
528 { 11, 23, 7, 15 }
529 };
530 StorageRefine cells = {
531 { 0, 4, 6, 7 },
532 { 4, 1, 5, 9 },
533 { 6, 5, 2, 8 },
534 { 7, 9, 8, 3 },
535 { 4, 6, 7, 9 },
536 { 4, 9, 5, 6 },
537 { 6, 7, 9, 8 },
538 { 6, 8, 9, 5 }
539 };
540 return { IT_Tetraedron4, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
541}
542
543// Attention lors de la génération des faces, il ne faut pas utiliser le cartesian (l'ordre du cartesian builder est différent)
544MeshSubdivider::Pattern PatternBuilder::hextotet()
545{
546 StorageRefine nodes = {}; // Pas de nouveaux noeuds
547 StorageRefine faces = {
548 // Ne fonctionne pas avec les mêmes faces que arcane pourtant
549 { 0, 1, 3 }, // 0
550 { 0, 3, 4 }, // 1
551 { 0, 1, 4 }, // 2
552 { 1, 3, 4 }, // 3
553 { 1, 4, 5 }, // 4
554 { 1, 5, 6 }, // 5
555 { 1, 4, 6 }, // 6
556 { 4, 5, 6 }, // 7
557 { 1, 2, 3 }, // 8
558 { 1, 3, 6 }, // 9
559 { 1, 2, 6 }, // 10
560 { 2, 3, 6 }, // 11
561 { 3, 4, 6 }, // 12
562 { 3, 6, 7 }, // 13
563 { 3, 4, 7 }, // 14
564 { 4, 6, 7 }, // 15
565 };
566
567 StorageRefine child_faces = { // 6*2 = 12 faces
568 { 0, 8 },
569 { 1, 14 },
570 { 2, 4 },
571 { 15, 7 },
572 { 10, 5 },
573 { 11, 13 }
574 };
575 StorageRefine cells = {
576 { 0, 1, 3, 4 },
577 { 1, 4, 5, 6 },
578 { 1, 2, 3, 6 },
579 { 3, 4, 6, 7 },
580 { 1, 3, 4, 6 }
581 };
582 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
583}
584
585MeshSubdivider::Pattern PatternBuilder::tettohex()
586{
587 StorageRefine nodes = {
588 { 0, 1 }, // 4
589 { 1, 2 }, // 5
590 { 0, 2 }, // 6
591 { 0, 3 }, // 7
592 { 2, 3 }, // 8
593 { 1, 3 }, // 9
594 { 0, 1, 3 }, // 10
595 { 1, 2, 3 }, // 11
596 { 0, 1, 2 }, // 12
597 { 0, 2, 3 }, // 13
598 { 0, 1, 2, 3 }, // 14
599 };
600 StorageRefine faces = {
601 { 7, 10, 14, 13 }, // 0 x
602 { 0, 6, 13, 7 }, // 1
603 { 0, 4, 10, 7 }, // 2
604 { 0, 4, 12, 6 }, // 3
605 { 4, 10, 14, 12 }, // 4 x
606 { 6, 12, 14, 13 }, // 5 x
607 { 2, 5, 11, 8 }, // 6
608 { 2, 6, 13, 8 }, // 7
609 { 8, 11, 14, 13 }, // 8 x
610 { 5, 11, 14, 12 }, // 9 x
611 { 2, 5, 12, 6 }, // 10
612 { 3, 8, 11, 9 }, // 11
613 { 3, 7, 13, 8 }, // 12
614 { 3, 7, 10, 9 }, // 13
615 { 9, 10, 14, 11 }, // 14 x
616 { 1, 5, 11, 9 }, // 15
617 { 1, 4, 10, 9 }, // 16
618 { 1, 4, 12, 5 }, // 17
619 };
620 StorageRefine child_faces = {
621 /*{0,10,17},
622 {1,6,11},
623 {2,13,15},
624 {8,12,16}*/
625 { 3, 10, 17 },
626 { 1, 7, 12 },
627 { 2, 13, 16 },
628 { 6, 11, 15 },
629 };
630 StorageRefine cells = {
631 /*{0,4,12,6,7,10,14,13},
632 {10,4,12,14,9,1,5,11},
633 {13,14,12,6,8,11,5,2},
634 {7,10,14,13,3,9,11,8},*/
635 /*{13,14,10,7,6,12,4,0},
636 {2,5,11,8,6,12,14,13},
637 {8,11,9,3,13,14,10,7},
638 {11,5,1,9,14,12,4,10},*/
639 /*{6,12,4,0,13,14,10,7},
640 {6,12,14,13,2,5,11,8},
641 {13,14,10,7,8,11,9,3},
642 {14,12,4,10,11,5,1,9},*/
643 { 7, 10, 14, 13, 0, 4, 12, 6 },
644 { 8, 11, 5, 2, 13, 14, 12, 6 },
645 { 3, 9, 11, 8, 7, 10, 14, 13 },
646 { 9, 1, 5, 11, 10, 4, 12, 14 }
647 };
648 return { IT_Tetraedron4, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
649}
650
651MeshSubdivider::Pattern PatternBuilder::hextotet24()
652{
653 StorageRefine nodes({
654 { 0, 1, 2, 3 }, // 8
655 { 0, 3, 7, 4 }, // 9
656 { 0, 1, 4, 5 }, // 10
657 { 4, 5, 6, 7 }, // 11
658 { 1, 2, 5, 6 }, // 12
659 { 2, 3, 7, 6 }, // 13
660 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 14
661 });
662 StorageRefine faces({
663 // OK
664 { 0, 3, 8 }, // 0
665 { 0, 8, 14 }, // 1
666 { 0, 3, 14 }, // 2
667 { 3, 8, 14 }, // 3
668 { 2, 3, 8 }, // 4
669 { 2, 3, 14 }, // 5
670 { 2, 8, 14 }, // 6
671 { 1, 2, 8 }, // 7
672 { 1, 2, 14 }, // 8
673 { 1, 8, 14 }, // 9
674 { 0, 1, 8 }, // 10
675 { 0, 1, 14 }, // 11
676 { 0, 4, 9 }, // 12
677 { 0, 9, 14 }, // 13
678 { 0, 4, 14 }, // 14
679 { 4, 9, 14 }, // 15
680 { 4, 7, 9 }, // 16
681 { 4, 7, 14 }, // 17
682 { 7, 9, 14 }, // 18
683 { 3, 7, 9 }, // 19
684 { 3, 7, 14 }, // 20
685 { 3, 9, 14 }, // 21
686 { 0, 3, 9 }, // 22
687 { 0, 4, 10 }, // 23
688 { 4, 10, 14 }, // 24
689 { 0, 10, 14 }, // 25
690 { 0, 1, 10 }, // 26
691 { 1, 10, 14 }, // 27
692 { 1, 5, 10 }, // 28
693 { 1, 5, 14 }, // 29
694 { 5, 10, 14 }, // 30
695 { 4, 5, 10 }, // 31
696 { 4, 5, 14 }, // 32
697 { 4, 7, 11 }, // 33
698 { 7, 11, 14 }, // 34
699 { 4, 11, 14 }, // 35
700 { 4, 5, 11 }, // 36
701 { 5, 11, 14 }, // 37
702 { 5, 6, 11 }, // 38
703 { 5, 6, 14 }, // 39
704 { 6, 11, 14 }, // 40
705 { 6, 7, 11 }, // 41
706 { 6, 7, 14 }, // 42
707 { 1, 5, 12 }, // 43
708 { 5, 12, 14 }, // 44
709 { 1, 12, 14 }, // 45
710 { 1, 2, 12 }, // 46
711 { 2, 12, 14 }, // 47
712 { 2, 6, 12 }, // 48
713 { 2, 6, 14 }, // 49
714 { 6, 12, 14 }, // 50
715 { 5, 6, 12 }, // 51
716 { 2, 6, 13 }, // 52
717 { 6, 13, 14 }, // 53
718 { 2, 13, 14 }, // 54
719 { 2, 3, 13 }, // 55
720 { 3, 13, 14 }, // 56
721 { 3, 7, 13 }, // 57
722 { 7, 13, 14 }, // 58
723 { 6, 7, 13 }, // 59
724 });
725 StorageRefine cells({
726 { 0, 3, 8, 14 },
727 { 3, 2, 8, 14 },
728 { 2, 1, 8, 14 },
729 { 1, 0, 8, 14 },
730
731 { 0, 4, 9, 14 },
732 { 4, 7, 9, 14 },
733 { 7, 3, 9, 14 },
734 { 3, 0, 9, 14 },
735
736 { 4, 0, 10, 14 },
737 { 0, 1, 10, 14 },
738 { 1, 5, 10, 14 },
739 { 5, 4, 10, 14 },
740
741 { 7, 4, 11, 14 },
742 { 4, 5, 11, 14 },
743 { 5, 6, 11, 14 },
744 { 6, 7, 11, 14 },
745
746 { 5, 1, 12, 14 },
747 { 1, 2, 12, 14 },
748 { 2, 6, 12, 14 },
749 { 6, 5, 12, 14 },
750
751 { 6, 2, 13, 14 },
752 { 2, 3, 13, 14 },
753 { 3, 7, 13, 14 },
754 { 7, 6, 13, 14 },
755 });
756
757 StorageRefine child_faces({
758 // a refaire ancienne numérotation
759 { 0, 4, 7, 10 },
760 { 12, 16, 19, 22 },
761 { 23, 26, 28, 31 },
762
763 { 33, 36, 38, 41 },
764 { 43, 46, 48, 51 },
765 { 52, 55, 57, 59 },
766 });
767 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
768}
769
770/*---------------------------------------------------------------------------*/
771/*---------------------------------------------------------------------------*/
775class ArcaneBasicMeshSubdividerService
777{
778 public:
779
780 explicit ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi);
782 void subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh) override;
783
784 private:
785
786 void _init();
788 static UniqueArray<Int64> _computeNodeUid(UniqueArray<Int64> nodes_uid, const StorageRefine& node_pattern);
789 /*
790 void _computeNodeCoord();
791 void _computeNodeUid();
792 void _computeFaceUid();
793 void _computeCellUid();
794 void _processOwner();
795 void _setOwner();
796 void _processOwnerCell();
797 void _processOwnerFace();
798 void _processOwnerNode();
799 void _getRefinePattern(Int16 type);
800 void _execute();
801 */
802
803 /*
804 bool test_recompact = true;
805 Ref<VariableNodeInt64> var = Arcane::makeRef(
806 new Arcane::VariableNodeInt64(
807 Arcane::VariableBuildInfo(mesh, "arcane_node_local_id", mesh->nodeFamily()->name()))); ;
808
809 if( test_recompact ) {
810 // * Si local id d'un noeud avant == local id nouveau alors on a pas changé l'emplacement mémoire
811 mesh->properties()->setBool("compact",true);
812 mesh->properties()->setBool("sort",true);
813 mesh->modifier()->endUpdate();
814 }
815 // On écris les localID
816 ENUMERATE_NODE(inode, mesh->allNodes() ){
817 (*var.get())[*inode] = inode.localId();
818 }
819 // Write les local id des noeuds et on voit si ça change
820
821 VariableList vl;
822 vl.add(*var.get());
823 _writeEnsight(mesh,"SubdividerWithCompact",vl);
824 */
825
829 /* Méthode qui permet de récuperer les faces générés par arcanes.
830 * Ces faces doivent donner les indices locaux des noeuds de la cellule initiale.
831 * Pour ça on construit une map global to my_local_index. <Int64,Int64>
832 */
843 void _refineOnce([[maybe_unused]] IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
858 void _applyFamilyRenumbering(IItemFamily* family, VariableItemInt64& items_new_uid);
861};
862
864{
865 // C F E N
866 info() << "begin:_checkMeshUid";
867 ENUMERATE_CELL (icell, mesh->allCells()) {
868 const Cell& cell = *icell;
869 if (cell.uniqueId().asInt64() < 0) {
870 info() << "FATAL ERROR UID";
871 exit(0);
872 }
873 }
874 ENUMERATE_FACE (iface, mesh->allFaces()) {
875 const Face& face = *iface;
876 if (face.uniqueId().asInt64() < 0) {
877 info() << "FATAL ERROR UID";
878 exit(0);
879 }
880 }
881 ENUMERATE_EDGE (iedge, mesh->allEdges()) {
882 const Edge& edge = *iedge;
883 if (edge.uniqueId().asInt64() < 0) {
884 info() << "FATAL ERROR UID";
885 exit(0);
886 }
887 }
888 ENUMERATE_NODE (inode, mesh->allNodes()) {
889 const Node& node = *inode;
890 if (node.uniqueId().asInt64() < 0) {
891 info() << "FATAL ERROR UID";
892 exit(0);
893 }
894 }
895
896 /*
897 ENUMERATE_DOF(idof,mesh) {
898 dof_id = idof->uniqueId().asInt64();
899 info() << "= Dof id : " << dof_id;
900 if(dof_id < 0){
901 info() << "FATAL ERROR UID DOF";
902 exit(0);
903 }
904 }
905 */
906 info() << "Vars: " << mesh->variableMng()->variables().count();
907 VariableCollection vars = mesh->variableMng()->variables();
908 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
909 IVariable* var = *ivar;
910 if (var->isUsed())
911 continue;
912 if ((var->property() & IVariable::PNoDump) != 0)
913 continue;
914 // Ne traite pas les variables qui ne sont pas sur des familles.
915 if (var->itemFamilyName().null())
916 continue;
917 //var->setUsed(true);
918 info() << "LIST_VAR name=" << var->fullName();
919 }
920
921 info() << "end:_checkMeshUid";
922}
923
925{
926 if (mesh->dimension() == 2) {
928 }
929 else if (mesh->dimension() == 3) {
931 }
932}
933
935{
936 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
937
938 mesh->faceFamily()->destroyGroups();
940 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
941 _refineOnce(mesh, pattern_manager);
942 std::string prefix("subdivider_pattern2D_");
943 mesh->utilities()->writeToFile(prefix + "tritotri.vtk", "VtkLegacyMeshWriter");
944
945 mesh->faceFamily()->destroyGroups();
947 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
948 _refineOnce(mesh, pattern_manager);
949 mesh->utilities()->writeToFile(prefix + "tritoquad.vtk", "VtkLegacyMeshWriter");
950
951 mesh->faceFamily()->destroyGroups();
953 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
954 _refineOnce(mesh, pattern_manager);
955 mesh->utilities()->writeToFile(prefix + "quadtoquad.vtk", "VtkLegacyMeshWriter");
956
957 mesh->faceFamily()->destroyGroups();
959 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
960 _refineOnce(mesh, pattern_manager);
961 mesh->utilities()->writeToFile(prefix + "quadtotri.vtk", "VtkLegacyMeshWriter");
962}
963
965{
966 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
967 std::string prefix("subdivider_pattern3D_");
968 mesh->faceFamily()->destroyGroups();
970 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
971 _refineOnce(mesh, pattern_manager);
972 mesh->utilities()->writeToFile(prefix + "tettotet.vtk", "VtkLegacyMeshWriter");
973
974 mesh->faceFamily()->destroyGroups();
976 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
977 _refineOnce(mesh, pattern_manager);
978 mesh->utilities()->writeToFile(prefix + "tettohex.vtk", "VtkLegacyMeshWriter");
979
980 mesh->faceFamily()->destroyGroups();
982 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
983 _refineOnce(mesh, pattern_manager);
984 mesh->utilities()->writeToFile(prefix + "hextohex.vtk", "VtkLegacyMeshWriter");
985
986 mesh->faceFamily()->destroyGroups();
988 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
989 _refineOnce(mesh, pattern_manager);
990 mesh->utilities()->writeToFile(prefix + "hextotet24.vtk", "VtkLegacyMeshWriter");
991
992 mesh->faceFamily()->destroyGroups();
994 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
995 _refineOnce(mesh, pattern_manager);
996 mesh->utilities()->writeToFile(prefix + "subdivider_hextotet.vtk", "VtkLegacyMeshWriter");
997}
998
999/*void ArcaneBasicMeshSubdividerService::_getArcaneOrder(IPrimaryMesh* mesh){
1000 Tritotri generate faces
1001
1002 _generateOneTri(mesh);
1003 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1004 _refineOnce(mesh,pattern_manager);
1005
1006
1007 Quadtoquad generate faces
1008
1009 _generateOneQuad(mesh);
1010 _refineWithArcaneFaces(mesh,PatternBuilder::quadtoquad());
1011 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
1012 _refineOnce(mesh,pattern_manager);
1013
1014
1015 Tettotet generate faces
1016
1017 _generateOneTetra(mesh);
1018 _refineWithArcaneFaces(mesh,PatternBuilder::tettotet());
1019
1020
1021
1022 _faceOrderArcane(mesh);
1023 mesh_utils::writeMeshInfos(mesh,"meshInSubdivide");
1024 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1025 _refineOnce(mesh,pattern_manager);
1026 mesh_utils::writeMeshInfos(mesh,"meshOutSubdivide");
1027
1028
1029 Tettohex generate faces input one tet
1030
1031 _generateOneTetra(mesh);
1032 _refineWithArcaneFaces(mesh,PatternBuilder::tettohex());
1033
1034 Hextohex generate faces input one hex
1035 _refineWithArcaneFaces(mesh,PatternBuilder::hextotet());
1036
1037 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
1038 _refineOnce(mesh,pattern_manager);
1039
1040}*/
1041
1042static void _writeEnsight(IMesh* mesh, const String& dirname,
1043 const VariableList& variables)
1044{
1045
1046 Directory d = mesh->subDomain()->exportDirectory();
1048 auto post_processor = spp.createReference(
1049 "Ensight7PostProcessor"); // autres mais moins bien VtkHdfV2PostProcessor ou Ensight7PostProcessor
1050 post_processor->setTimes(
1051 UniqueArray<Real>{ 0.0 }); // Juste pour fixer le pas de temps
1052
1053 ItemGroupList groups;
1054 groups.add(mesh->allCells());
1055 groups.add(mesh->allNodes());
1056 post_processor->setBaseDirectoryName(d.path() + "/" + dirname);
1057
1058 VariableNodeInt64 arcane_node_uid(VariableNodeInt64(Arcane::VariableBuildInfo(mesh, "arcane_node_uid", mesh->nodeFamily()->name())));
1059 VariableCellInt64 arcane_cell_uid(VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_cell_uid", mesh->cellFamily()->name())));
1060 VariableCellInt64 arcane_rank(VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_rank", mesh->cellFamily()->name())));
1061
1062 ENUMERATE_CELL(icell, mesh->allCells()) {
1063 arcane_cell_uid[*icell] = icell->uniqueId();
1064 }
1065
1066 ENUMERATE_CELL(icell, mesh->allCells()) {
1067 arcane_rank[*icell] = mesh->parallelMng()->commRank();
1068 }
1069
1070 ENUMERATE_NODE(inode, mesh->allNodes()) {
1071 arcane_node_uid[*inode] = inode->uniqueId();
1072 }
1073
1074 VariableList all_variables = variables.clone();
1075 all_variables.add(mesh->nodesCoordinates().variable());
1076 all_variables.add(arcane_rank);
1077 all_variables.add(arcane_cell_uid);
1078 all_variables.add(arcane_node_uid);
1079
1080 post_processor->setVariables(all_variables);
1081 post_processor->setGroups(groups);
1082 IVariableMng* vm = mesh->subDomain()->variableMng();
1083 vm->writePostProcessing(post_processor.get());
1084}
1085
1086void ArcaneBasicMeshSubdividerService::_refineOnce(IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager)
1087{
1088
1089 // Compute max_cell_uid
1090 Int64 max_cell_uid = NULL_ITEM_UNIQUE_ID;
1091 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
1092 Cell cell = *icell;
1093 if (max_cell_uid < cell.uniqueId())
1094 max_cell_uid = cell.uniqueId();
1095 }
1096 Int64 global_max_cell_uid = mesh->parallelMng()->reduce(Parallel::ReduceMax, max_cell_uid);
1097 global_max_cell_uid++; // on prend le suivant
1098
1099 info() << "#subdivide mesh";
1100 // On vérifie qu'on sait raffiner les cellules (peut-être pas en même temps)
1101 ENUMERATE_CELL (icell, mesh->ownCells()) {
1102 const Cell& cell = *icell;
1103 // Liste des éléments où les patterns sont implémentés pour l'instant
1104 if (cell.itemTypeId() != IT_Hexaedron8 && cell.itemTypeId() != IT_Tetraedron4 && cell.itemTypeId() != IT_Quad4 && cell.itemTypeId() != IT_Triangle3) {
1105 ARCANE_FATAL("Not implemented item type '{0}'", cell.itemTypeId());
1106 return;
1107 }
1108 }
1109
1110 info() << "subdivide mesh with " << options()->nbSubdivision() << " nb_refine";
1111
1112 Int32 my_rank = mesh->parallelMng()->commRank();
1113 IMeshModifier* mesh_modifier = mesh->modifier();
1114 IGhostLayerMng* gm = mesh->ghostLayerMng();
1115 debug() << "PART 3D nb ghostlayer" << gm->nbGhostLayer();
1116 // mesh->utilities()->writeToFile(String::format("3D_last_input{0}.vtk",my_rank), "VtkLegacyMeshWriter");
1117 Integer nb_ghost_layer_init = gm->nbGhostLayer(); // On garde le nombre de ghost layer initial pour le remettre à la fin
1118 Int32 version = gm->builderVersion();
1119 if (version < 3)
1120 gm->setBuilderVersion(3);
1121
1122 gm->setNbGhostLayer(0);
1123 mesh_modifier->setDynamic(true);
1124 mesh_modifier->updateGhostLayers();
1125
1126 // Uniquement pour les vérifications asserts à la fin
1127 Integer nb_cell_init = mesh->nbCell();
1128 Integer nb_face_init = mesh->nbFace();
1129 //Integer nb_edge_init = mesh->nbEdge();
1130 //Integer nb_node_init = mesh->nbNode();
1131
1132 // Compter les arêtes
1133 // On cherche un moyen de compter les arêtes pour faire un test facile sur le nombre de noeud inséré.
1134 // ARCANE_ASSERT((nb_edge_init+ nb_cell_init + nb_face_init)== nb_node_added,("Mauvais nombre de noeuds insérés"));
1135 //debug() << "#NOMBRE INITS " << nb_node_init << " " << mesh->allEdges().size() << " " << edg.size() << " " << nb_face_init << " " << nb_cell_init ;
1136
1137 // VARIABLES
1138 // Items à ajouter avec connectivités pour E F et C
1139 UniqueArray<Int64> nodes_to_add;
1140 UniqueArray<Int64> edges_to_add;
1141 UniqueArray<Int64> faces_to_add;
1142 UniqueArray<Int64> cells_to_add;
1143
1144 Integer nb_cell_to_add = 0;
1145 Integer nb_face_to_add = 0;
1146
1147 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1148 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1149 debug() << "ARRAY SIZE " << nodes_coords.arraySize();
1150 // Noeuds sur les entités
1151 std::set<Int64> new_nodes; // Utiliser une map permet s'assurer qu'on ajoute une seule fois un noeud avec un uniqueId()
1152 std::set<Int64> new_faces; // ^--- Pareil pour les faces
1153 // Maps pour la gestions des propriétaires
1154 std::unordered_map<Int64, Int32> node_uid_to_owner;
1155 std::unordered_map<Int64, Int32> edge_uid_to_owner; // pas utilisé
1156 std::unordered_map<Int64, Int32> face_uid_to_owner;
1157 std::unordered_map<Int64, Int32> child_cell_owner; // pas utilisé
1158 std::unordered_map<Int32, Int32> old_face_lid_to_owner; // pas utilisé
1159
1160 UniqueArray<Int32> cells_to_detach; // Cellules à détacher
1161 UniqueArray<Int64> faces_uids; // Contient uniquement les uids pas les connectivités
1162 UniqueArray<Int64> edges_uids; // Idem
1163
1164 // Calcul nombre de noeuds à insérer
1165 // const Integer nb_node_to_add_total = mesh->nbCell()+mesh->nbFace()+mesh->nbEdge(); // Attention pattern dépendant
1166 //nodes_to_add.reserve(nb_node_to_add_total);
1167 //nodes_to_add_coords.reserve(nb_node_to_add_total);
1168
1169 Integer ind_new_cell = 0;
1170
1171 ARCANE_ASSERT((mesh->nbEdge() == 0), ("Wrong number of edge"));
1172
1173 UniqueArray<Int64> parent_faces(mesh->ownFaces().size());
1174 UniqueArray<Int64> parent_cells(mesh->ownCells().size());
1175 UniqueArray<Int64> child_cells; // Toutes les nouvelles cells
1176 UniqueArray<Int64> child_faces; // Au bord de l'élément uniquement (pas de faces interne à l'élément)
1177
1178 // Permet de récupere les entités enfants à partir d'une cellule parent
1179 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>)
1180 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>)
1181 // ^--- uniquement pour les faces "externes"
1182 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 )
1183
1184 // Groups
1185 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces_groups; // Map face parente -> face enfant externe dans array face_external_uid
1186 UniqueArray<Int64> face_external_uid; // Toutes les faces externes du proc uid
1187
1188 // Debug node
1189 /*
1190 ENUMERATE_NODE(inode,mesh->ownNodes())
1191 {
1192 const Node & node = *inode;
1193 nodes_to_add_coords[node.uniqueId().asInt64()] = nodes_coords[node];
1194 }
1195 */
1196 // Traitement pour une cellule
1197 ENUMERATE_CELL (icell, mesh->ownCells()) {
1198 debug() << "Refining element";
1199 // POUR UN ELEMNT:
1200 // Détacher cellules parente
1201 // Génération des nouveaux noeuds (uid et coordonnées)
1202 // Sur Arêtes
1203 // Sur Faces
1204 // Sur Cellule
1205 // Nouveaux noeuds,coordonnées
1206
1207 // Génération des Faces (uid et composants (Noeuds)) utilises nouveaux noeuds
1208 // Internes
1209 // Externes
1210
1211 // Génération des Cellules (uid et composants (Noeuds))
1212 // Gestion des groupes
1213 // FIN UN ELEMENT
1214
1215 // Détachement des cellules
1216 // Ajout des noeuds enfants
1217 // Ajout des faces enfants
1218 // Ajout des cellules enfants (et assignation propriétaire)
1219
1220 // Ajout d'une couche fantome
1221 // Calcul des propriétaires des noeuds
1222 // Calcul des propriétaires des faces
1223 // Supression de la couche fantome
1224 // ?? Calcul des groupes F C
1225
1226 // Assignation des noeuds au propriétaire
1227 // Assignation des faces au propriétaire
1228 // Ajout nombre de couche de maille initial
1229
1230 const Cell& cell = *icell;
1231
1232 MeshSubdivider::Pattern& p = pattern_manager[cell.type()]; // Pattern Manager
1233 StorageRefine& node_pattern = p.nodes;
1234
1235 UniqueArray<Int64> face_in_cell; // Toutes les faces de la cellule uid
1236 StorageRefine& child_faces = p.child_faces;
1237
1238 cells_to_detach.add(cell.localId());
1239 // Génération des noeud
1240 UniqueArray<Int64> node_in_cell;
1241 node_in_cell.resize(node_pattern.size() + cell.nbNode()); // pattern dépendant
1242 UniqueArray<Real3> coords_in_cell;
1243 debug() << "Noeuds initiaux";
1244 // Noeuds initiaux
1245 for (Int32 i = 0; i < cell.nbNode(); i++) {
1246 node_in_cell[i] = cell.node(static_cast<Int32>(i)).uniqueId().asInt64();
1247 //debug() << i << " " << node_in_cell[i] << " size " << node_in_cell.size() ;
1248 }
1249
1250 Integer index_27 = cell.nbNode();
1251
1252 // - Génération des uid noeuds
1253 debug() << "Génération des uid noeuds";
1254
1255 for (Integer i = 0; i < node_pattern.size(); i++) {
1256 // uid
1258 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1259 tmp.add(node_in_cell[node_pattern[i][j]]);
1260 }
1261 std::sort(tmp.begin(), tmp.end());
1263 node_in_cell[index_27 + i] = uid;
1264
1265 if (new_nodes.find(node_in_cell[i + index_27]) == new_nodes.end()) {
1266 // Coords
1267 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1268 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1269 //info() << "loop" << cell.node(static_cast<Integer>(node_pattern[i][j])) << " " << nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1270 middle_coord += nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1271 }
1272 if (node_pattern[i].size() == 0) {
1273 ARCANE_FATAL("Wrong size for refined pattern with code IT:'{0}'", p.cell_type);
1274 }
1275 middle_coord /= node_pattern[i].size();
1276 if (middle_coord == Real3(0.0, 0.0, 0.0)) {
1277 ARCANE_FATAL("Bad coordinate for new node, the node '{0}' probably has a default coordinate (0.0,0.0,0.0).", uid);
1278 }
1279 new_nodes.insert(node_in_cell[i + index_27]);
1280 // Insertion dans map uid -> coord
1281 nodes_to_add_coords[node_in_cell[i + index_27]] = middle_coord;
1282 // Insertion dans Uarray uid
1283 nodes_to_add.add(uid);
1284 //info() << node_pattern[i];
1285 //debug() << i << " " << uid << " sizenic " << tmp << middle_coord;
1286 }
1287 }
1288 // Est-ce qu'on doit ajouter les anciens noeuds ? Normalement non
1289 // #TAG
1290 /*
1291 for(Integer i = 0 ; i < cell.nbNode() ; i++ ) {
1292 nodes_to_add.add(cell.node(i).uniqueId().asInt64());
1293 new_nodes.insert(cell.node(i).uniqueId().asInt64());
1294 }
1295 */
1296
1297 debug() << "nodetoadd size " << nodes_to_add.size() << " " << nodes_to_add_coords.size();
1298 debug() << "Node coord & nb node to add" << nodes_to_add_coords.size() << " " << nodes_to_add.size();
1299 //ARCANE_ASSERT((nodes_to_add_coords.size() == static_cast<size_t>(nodes_to_add.size())),("Has to be same"));
1300 //ARCANE_ASSERT((nodes_to_add_coords.size() == new_nodes.size()),("Has to be same"));
1301
1302 // Génération des Faces
1303 StorageRefine& face_refine = p.faces;
1304 debug() << "face_refine.size() " << face_refine.size();
1305 //ARCANE_ASSERT((face_refine.size() == 36), ("WRONG NUMBER OF CELL ADDED")); // One cube assert
1306 debug() << "Refine face";
1307 for (Integer i = 0; i < face_refine.size(); i++) {
1308 // Generation du hash de la face
1310 //tmp.resize(face_refine[i].size());
1311 for (Integer j = 0; j < face_refine[i].size(); j++) {
1312 tmp.add(node_in_cell[face_refine[i][j]]);
1313 }
1314 std::sort(tmp.begin(), tmp.end());
1315 //ARCANE_ASSERT(( tmp.size() == 4 ),("Wrong size of UniqueArray")); // one cube assert
1317 face_in_cell.add(uid); // Pour groups
1318 // Vérifier si on l'a déja crée
1319 if (new_faces.find(uid) == new_faces.end()) {
1320 // Ajout
1321 faces_to_add.add(p.face_type);
1322 faces_to_add.add(uid);
1323 //debug() << "Face " << uid << " " << tmp ;
1324 for (Integer j = 0; j < face_refine[i].size(); j++) {
1325 //debug() << node_in_cell[face_refine[i][j]] ;
1326 faces_to_add.add(node_in_cell[face_refine[i][j]]);
1327 }
1328 // Ajouter dans tableau uids faces
1329 faces_uids.add(uid);
1330 nb_face_to_add++;
1331 new_faces.insert(uid);
1332 }
1333 }
1334
1335 // Nouvelle Gestion des groupes
1336 // Pour chaque faces
1337 // Générer hash
1338 // associer hash uid face
1339 // Parcours des faces parentes
1340 debug() << "Gestion face groupe";
1341 for (Integer i = 0; i < child_faces.size(); i++) {
1342 parents_to_childs_faces_groups[cell.face(i).uniqueId()] = std::pair<Int64, Int64>(face_external_uid.size(), child_faces[i].size());
1343 for (Integer j = 0; j < child_faces[i].size(); j++) {
1344 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)
1345 }
1346 }
1347
1348 // Génération des cells
1349 StorageRefine& cells_refine = p.cells;
1350 // Génération des cellules enfants
1351 debug() << "Génération des cellules enfants";
1352 // L'uid est généré à partir du hash de chaque noeuds triés par ordre croissant
1353 for (Integer i = 0; i < cells_refine.size(); i++) {
1354 // Le nouvel uid est généré avec le hash des nouveaux noeuds qui composent la nouvelle cellule
1356 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1357 tmp.add(node_in_cell[cells_refine[i][j]]);
1358 }
1359 std::sort(tmp.begin(), tmp.end());
1360 //Int64 cell_uid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView()); //max_cell_uid+ind_new_cell;
1361 //info() << "global_max_cell_uid" << global_max_cell_uid ;
1362 Int64 cell_uid = cell.uniqueId().asInt64() * p.cells.size() + i + global_max_cell_uid;
1363 //info() << "#old new uid" << cell.uniqueId().asInt64() << " " << cell_uid ;
1364 ARCANE_ASSERT((cell_uid >= 0), ("Cell uid generation don't work properly"));
1365 cells_to_add.add(p.cell_type); // Type
1366 cells_to_add.add(cell_uid);
1367 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1368 cells_to_add.add(node_in_cell[cells_refine[i][j]]);
1369 }
1370 child_cell_owner[cell_uid] = cell.owner();
1371 parent_cells.add(cell.uniqueId());
1372 child_cells.add(cell_uid); // groups doublons d'informations avec cells_to_add
1373 nb_cell_to_add++;
1374 ind_new_cell++;
1375 }
1376 // groups
1377 parents_to_childs_cell[cell.uniqueId()] = std::pair<Int64, Int64>(childs_count, cells_refine.size());
1378 childs_count += cells_refine.size(); // à modifier selon le nombre d'enfant associé au motif de rafinement !
1379 }
1380 // Ajout des nouveaux Noeuds
1381 Integer nb_node_added = nodes_to_add.size();
1382 UniqueArray<Int32> nodes_lid(nb_node_added);
1383
1384 // info() << "JustBeforeAdd " << nodes_to_add;
1385 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.view());
1386
1387 // Edges: Pas de génération d'arrête
1388
1389 debug() << "Faces_uids " << faces_uids << " faces_to_add " << faces_to_add.size() << " faces_to_add/6 " << faces_to_add.size() / 6;
1390
1391 //ARCANE_ASSERT((nodes_to_add.size() != 0),("End"));
1392 //ARCANE_ASSERT((nb_face_to_add == 68),("WRONG NUMBER OF FACES")); // two hex
1393 // Ajout des Faces enfants
1394 UniqueArray<Int32> face_lid(faces_uids.size());
1395 debug() << "Before addOneFace " << nb_face_to_add;
1396
1397 //Setup faces
1398
1399 mesh->modifier()->addFaces(nb_face_to_add, faces_to_add.constView(), face_lid.view());
1400 debug() << "addOneFace " << nb_face_to_add;
1401 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, faces_uids, true);
1402 debug() << "NB_FACE_ADDED AFTER " << face_lid.size() << " " << new_faces.size();
1403
1404 //ARCANE_ASSERT((nb_face_to_add == (faces_to_add.size()/6)),("non consistant number of faces")); // Pour hex
1405
1406 // Ajout des cellules enfants
1407 mesh->modifier()->detachCells(cells_to_detach);
1408
1409 UniqueArray<Int32> cells_lid(nb_cell_to_add);
1410 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.constView(), cells_lid);
1411 info() << "After addCells";
1412 // mesh->modifier()->addCells()
1413 // Pour tout les itemgroups
1414 UniqueArray<Int32> child_cells_lid(child_cells.size());
1415 mesh->cellFamily()->itemsUniqueIdToLocalId(child_cells_lid, child_cells, true);
1416
1417 // Gestion des itemgroups ici (différents matériaux par exemple)
1418 // - On cherche à ajouter les enfants dans les mêmes groupes que les parents pour :
1419 // - Faces
1420 // - Cells
1421 // - Pas de déduction automatique pour :
1422 // - Noeuds
1423 // - Arêtes
1424 // Algo
1425 // Pour chaque group
1426 // Pour chaque cellules de ce group
1427 // ajouter cellules filles de ce group
1428
1429 // Traiter les groupes pour les faces
1430 //
1431 // En fait on ne peut traiter que les faces externes. Est-ce qu'on doit/peut déduire les groupes des faces internes ?
1432 // Dans le cas du test microhydro on peut car on a que les faces externes aux éléments: XYZ min max
1433 // A ce moment nous n'avons pas fait de lien face_parent_externe -> face_enfant_externe
1434 // Pour le faire nous allons parcourir les faces internes parentes, trier les ids et trier les éléménts
1435
1436 // Problème des groupes.
1437 // Tableau faces_externals
1438 // Pour chaque face parent
1439 // - Ajouter dans une nouvelle variable faces_externals l'uid de chaque nouvelle face
1440 // - dans map sauvegarder uid, et index
1441
1442 IItemFamily* face_family = mesh->faceFamily();
1443 IItemFamily* cell_family = mesh->cellFamily();
1444
1445 UniqueArray<Int32> face_external_lid(face_external_uid.size());
1446 mesh->faceFamily()->itemsUniqueIdToLocalId(face_external_lid, face_external_uid);
1447 // Traiter les groups pour les faces
1448 info() << "#mygroupname face " << face_family->groups().count();
1449 for (ItemGroupCollection::Enumerator igroup(face_family->groups()); ++igroup;) {
1450 ItemGroup group = *igroup;
1451
1452 info() << "#mygroupname face " << group.fullName();
1453 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1454 info() << "#groups: OWN";
1455 continue;
1456 }
1457 if (group.isAllItems()) { // besoin de ça pour seq et //
1458 info() << "#groups: ALLITEMS";
1459 continue;
1460 }
1461 info() << "#groups: Added ";
1462 UniqueArray<Int32> to_add_to_group;
1463
1464 ENUMERATE_ (Item, iitem, group) { // Pour chaque cellule du groupe on ajoute ses 8 enfants ( ou n )
1465 Int64 step = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].first;
1466 Int64 n_childs = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].second;
1467 auto subview = face_external_lid.subView(step, static_cast<Integer>(n_childs));
1468 //ARCANE_ASSERT((subview.size() == 4 ), ("SUBVIEW"));
1469 to_add_to_group.addRange(subview);
1470 }
1471 group.addItems(to_add_to_group, true);
1472 }
1473
1474 // Traiter les groupes pour les cellules
1475 for (ItemGroupCollection::Enumerator igroup(cell_family->groups()); ++igroup;) {
1476 CellGroup group = *igroup;
1477 info() << "#mygroupname" << group.fullName() << "nb item" << cell_family->nbItem();
1478 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1479 info() << "#groups: OWN";
1480 continue;
1481 }
1482 if (group.isAllItems()) { // besoin de ça pour seq et //
1483 info() << "#groups: ALLITEMS";
1484 continue;
1485 }
1486
1487 info() << "#groups: Added ";
1488 UniqueArray<Int32> to_add_to_group;
1489
1490 ENUMERATE_ (Item, iitem, group) { // Pour chaque cellule du groupe on ajoute ses 8 enfants ( ou n )
1491 Int64 step = parents_to_childs_cell[iitem->uniqueId().asInt64()].first;
1492 Int64 n_childs = parents_to_childs_cell[iitem->uniqueId().asInt64()].second;
1493 auto subview = child_cells_lid.subView(step, static_cast<Integer>(n_childs));
1494 to_add_to_group.addRange(subview);
1495 }
1496 info() << "#Added " << to_add_to_group.size() << " to group " << group.fullName();
1497 group.addItems(to_add_to_group, true);
1498 }
1499 // fin gestion itemgroups
1500 mesh->modifier()->removeDetachedCells(cells_to_detach.constView());
1501 //mesh->modifier()->removeCells(cells_to_detach.constView());
1502 mesh->modifier()->endUpdate();
1503
1504 // DEBUG
1505 debug() << "Debug faces " << faces_to_add;
1506 /*for(Integer i = 0 ; i < faces_to_add.size() ; i++){
1507 debug() << new_faces[i] ;
1508 }*/
1509 // ENDEBUG
1510
1511 // Gestion et assignation du propriétaire pour chaque cellule
1512 // Le propriétaire est simplement le sous domaine qui a générer les nouvelles cellules
1513 ENUMERATE_ (Cell, icell, mesh->allCells()) {
1514 Cell cell = *icell;
1515 cell.mutableItemBase().setOwner(my_rank, my_rank);
1516 }
1517 mesh->cellFamily()->notifyItemsOwnerChanged();
1518
1519 // ARCANE_ASSERT((nodes_lid.size() != 0),("End"));
1520 ARCANE_ASSERT((nodes_lid.size() == nodes_to_add.size()), ("End"));
1521 // Assignation des coords aux noeuds
1522
1523 UniqueArray<Int32> to_add_to_nodes(nodes_to_add.size()); // Bis
1524 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_to_add, true);
1525
1526 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) { // recalculer nodes_lid
1527 Node node = *inode;
1528 debug() << node.uniqueId().asInt64();
1529 //ARCANE_ASSERT((new_nodes.find(node.uniqueId().asInt64()) != new_nodes.end()),("Not found in set !"))
1530 //ARCANE_ASSERT((nodes_to_add_coords.find(node.uniqueId().asInt64()) != nodes_to_add_coords.end()),("Not found in map coord!"))
1531 // si il est pas dans la map c'est qu'il existe déja !
1532
1533 nodes_coords[node] = nodes_to_add_coords[node.uniqueId().asInt64()];
1534 debug() << "InSBD" << node.uniqueId().asInt64() << " " << nodes_to_add_coords[node.uniqueId().asInt64()];
1535 }
1536
1537 //info() << "#NODECOORDS" << nodes_coords.asArray() ;
1538 // Ajout d'une couche fantôme
1539 Arcane::IGhostLayerMng* gm2 = mesh->ghostLayerMng();
1540 gm2->setNbGhostLayer(1);
1541 mesh->updateGhostLayers(true);
1542
1543 // Gestion des propriétaires de noeuds
1544 // Le propriétaire est la cellule incidente au noeud avec le plus petit uniqueID()
1545 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1546 Node node = *inode;
1547 auto it = std::min_element(node.cells().begin(), node.cells().end());
1548 Cell cell = node.cell(static_cast<Int32>(std::distance(node.cells().begin(), it)));
1549 node_uid_to_owner[node.uniqueId().asInt64()] = cell.owner();
1550 }
1551
1552 // Gestion des propriétaires des faces
1553 // Le propriétaire est la cellule incidente à la face avec le plus petit uniqueID()
1554 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1555 Face face = *iface;
1556 auto it = std::min_element(face.cells().begin(), face.cells().end());
1557 Cell cell = face.cell(static_cast<Int32>(std::distance(face.cells().begin(), it)));
1558 face_uid_to_owner[face.uniqueId().asInt64()] = cell.owner();
1559 }
1560
1561 // Utiliser les couches fantôme est couteux (construction destruction)
1562 // - 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
1563 // - Déduction possible des owners des faces enfants avec la face parent directement
1564 // - Les cellules enfants ont le même owner que la cellule parent
1565 // Supression de la couche fantôme
1566 gm2->setNbGhostLayer(0);
1567 mesh->updateGhostLayers(true);
1568
1569 // DEBUG
1570 /*debug() << "#Faces mesh";
1571 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1572 Face face = *iface;
1573 debug() << face.uniqueId().asInt64();
1574 }*/
1575
1576 // Quelques sur le nombres d'entités insérés
1577 // ARCANE_ASSERT((mesh->nbCell() == nb_cell_init*8 ),("Wrong number of cell added"));
1578 debug() << "nbface " << mesh->nbFace() << " " << nb_face_to_add << " expected " << nb_face_init * 4 + 12 * nb_cell_init;
1579 // ARCANE_ASSERT((mesh->nbFace() <= nb_face_init*4 + 12 * nb_cell_init ),("Wrong number of face added"));
1580 // A ajouter pour vérifier le nombre de noeud si les arêtes sont crées
1581 // ARCANE_ASSERT((mesh->nbNode() == nb_edge_init + nb_face_init + nb_cell_init ),("Wrong number of node added"))
1582
1583 // Assignation du nouveau propriétaire pour chaque noeud
1584 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1585 Node node = *inode;
1586 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId().asInt64()], my_rank);
1587 }
1588 mesh->nodeFamily()->notifyItemsOwnerChanged();
1589
1590 // Assignation du nouveaux propriétaires pour chaque face
1591 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1592 Face face = *iface;
1593 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId().asInt64()], my_rank);
1594 }
1595 mesh->faceFamily()->notifyItemsOwnerChanged();
1596
1597 // On met de nouveau le ghost layer pour une future simulation
1598 gm2->setNbGhostLayer(nb_ghost_layer_init);
1599 mesh->updateGhostLayers(true);
1600
1601 // Ecriture au format VTK
1602 /*
1603 mesh->utilities()->writeToFile("3Drefined" + std::to_string(my_rank) + ".vtk", "VtkLegacyMeshWriter");
1604 info() << "Writing VTK 3Drefine";
1605 debug() << "END 3D fun";
1606 debug() << "NB CELL " << mesh->nbCell() << " " << nb_cell_init * 8;
1607 debug() << mesh->nbNode() << " " << nb_node_init << " " << nb_edge_init << " " << nb_face_init << " " << nb_cell_init;
1608 debug() << mesh->nbFace() << "nb_face_init " << nb_face_init << " " << nb_face_init << " " << nb_cell_init;
1609 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;
1610 info() << "#NODES_CHECK #all" << mesh->allNodes().size() << " #own " << mesh->ownNodes().size();
1611 */
1612}
1613
1615{
1616 IMeshModifier* modifier = mesh->modifier();
1617 Int64UniqueArray cells_infos;
1618 Int64UniqueArray faces_infos;
1619 Int64UniqueArray nodes_uid;
1620 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1621 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1622
1623 // get max uid for cells
1624 Int64 max_offset = 0;
1625 ENUMERATE_CELL (icell, mesh->allCells()) {
1626 Cell cell = *icell;
1627 info() << cell.uniqueId().asInt64() << " ";
1628 if (max_offset < cell.uniqueId())
1629 max_offset = cell.uniqueId();
1630 }
1631 //ARCANE_ASSERT((max_offset!=0),("BAD OFFSET"));
1632
1633 info() << "#_refineWithArcaneFaces";
1634 ENUMERATE_CELL (icell, mesh->allCells()) {
1635 const Cell& cell = *icell;
1636 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1637 << icell->type() << ", nb nodes=" << icell->nbNode();
1638
1639 for (Face face : cell.faces()) {
1640 info() << "Face " << face.uniqueId() << " nodes ";
1641 for (Node node : face.nodes()) {
1642 info() << node.uniqueId() << " ";
1643 }
1644 }
1645 }
1646 //mesh->utilities()->writeToFile("subdivider_one_tetra_output.vtk", "VtkLegacyMeshWriter");
1647 ARCANE_ASSERT((!p.cells.empty()), ("Pattern not init"));
1648 Integer cellcount = 0;
1649 UniqueArray<Int32> cells_to_detach; // Cellules à détacher
1650
1651 Int64 face_count = 0;
1652
1653 std::map<Int64, Int32> node_uid_to_cell_local_id; // Donne le local id par rapport à une cell
1654
1655 ENUMERATE_CELL (icell, mesh->allCells()) {
1656 UniqueArray<Int64> node_in_cell;
1657 const Cell& cell = *icell;
1658 info() << "Detach";
1659 cells_to_detach.add(cell.localId());
1660 info() << "Get Pattern";
1661 StorageRefine& node_pattern = p.nodes;
1662 StorageRefine& cells = p.cells;
1663
1664 info() << "Get Nodes";
1665 for (Integer i = 0; i < cell.nbNode(); i++) {
1666 node_in_cell.add(cell.node(i).uniqueId().asInt64());
1667 info() << "Node " << cell.node(i).uniqueId().asInt64() << " " << nodes_coords[cell.node(i)];
1668 }
1669 info() << "Node pattern " << node_pattern.size() << "nic " << node_in_cell;
1670 _computeNodeUid(node_in_cell, node_pattern);
1671 // New nodes and coords
1672 for (Integer i = 0; i < node_pattern.size(); i++) {
1673 info() << "test " << i;
1674 UniqueArray<Int64> tmp = node_pattern[i];
1675
1676 // uid == node_in_cell[uid]
1677 Int64 uid = cell.nbNode() + i;
1678 node_in_cell.add(uid); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
1679 nodes_uid.add(uid);
1680 // Coords
1681 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1682
1683 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1684 middle_coord += nodes_coords[cell.node(static_cast<Int32>(node_pattern[i][j]))];
1685 info() << node_pattern[i][j] << cell.node(static_cast<Int32>(node_pattern[i][j]));
1686 }
1687 middle_coord /= node_pattern[i].size();
1688 nodes_to_add_coords[uid] = middle_coord;
1689 info() << "NodeX " << uid << " " << " coord " << nodes_to_add_coords[uid] << " " << middle_coord;
1690 node_uid_to_cell_local_id[uid] = cell.nbNode() + i;
1691 }
1692
1693 info() << "#node in cell " << node_in_cell;
1694 // Génération nouvelles faces et cells
1695 // New faces
1696 /*for( Integer i = 0 ; i < faces.size() ; i++ ){
1697 // Header
1698 faces_infos.add(p.face_pattern); // type // Dépendant pattern //#HERE
1699 faces_infos.add(i); // face uid
1700 for( Integer j = 0 ; j < faces[i].size() ; j++ ) {
1701 faces_infos.add(node_in_cell[faces[i][j]]); // node 0
1702 }
1703 // Face_info
1704 info() << "face " << face_count << " " << node_in_cell[faces[i][0]] << " " << node_in_cell[faces[i][1]] << " " << node_in_cell[faces[i][2]];
1705 face_count++;
1706 }*/
1707 // New cells
1708 for (Integer i = 0; i < cells.size(); i++) {
1709 // Header
1710 max_offset++;
1711 cells_infos.add(p.cell_type); // type // Dépendant pattern
1712 cells_infos.add(max_offset); // cell uid
1713 // Cell_info
1714 info() << "Cell " << i;
1715 for (Integer j = 0; j < cells[i].size(); j++) {
1716 info() << "test2bis " << node_in_cell[cells[i][j]] << " " << node_in_cell.size() << " " << node_pattern.size();
1717 cells_infos.add(node_in_cell[cells[i][j]]);
1718 }
1719 cellcount++;
1720 }
1721 info() << "test2bisbis ";
1722 for (Integer i = 0; i < node_in_cell.size(); i++) {
1723 info() << "node_in_cell[ " << i << " ] " << node_in_cell[i];
1724 }
1725 info() << "test3 ";
1726 }
1727 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1728 // Debug ici
1729 info() << "test3 " << nodes_uid.size() << " " << nodes_lid.size();
1730 nodes_lid.clear();
1731 nodes_lid.reserve(nodes_uid.size());
1732
1733 modifier->addNodes(nodes_uid, nodes_lid);
1734 info() << "After nodes";
1735 UniqueArray<Int32> faces_lid(face_count);
1736 //modifier->addFaces(face_count, faces_infos, faces_lid);
1737 info() << "After faces";
1738 UniqueArray<Int32> cells_lid(cellcount);
1739
1740 modifier->addCells(cellcount, cells_infos, cells_lid);
1741 info() << "cellsize " << cells_infos.size() << " " << cellcount;
1742 modifier->removeCells(cells_to_detach.constView());
1743 modifier->endUpdate();
1744 // Assignation coords aux nouveaux noeuds
1745 VariableNodeReal3 coords_bis = mesh->nodesCoordinates();
1746
1747 info() << nodes_lid.size();
1748 UniqueArray<Int32> to_add_to_nodes(nodes_uid.size()); // Bis
1749 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_uid, true);
1750
1751 info() << "#NODESHERE";
1752 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) {
1753 Node node = *inode;
1754 coords_bis[node] = nodes_to_add_coords[node.uniqueId()];
1755 info() << "node " << node.uniqueId() << " coord " << nodes_to_add_coords[node.uniqueId()];
1756 info() << node.uniqueId() << " " << nodes_coords[node];
1757 }
1758
1759 //mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output1.vtk", "VtkLegacyMeshWriter");
1760
1761 info() << "#coords" << coords_bis.asArray();
1762 info() << "#My mesh ";
1763 UniqueArray<Int64> stuff;
1764 // Affichage maillage
1765 ENUMERATE_CELL (icell, mesh->allCells()) {
1766 const Cell& cell = *icell;
1767 info() << "Cell " << cell.uniqueId() << " " << cell.nodeIds();
1768 for (Face face : cell.faces()) {
1769 for (Node node : face.nodes()) {
1770 stuff.add(node.uniqueId());
1771 }
1772 info() << "Faces " << face.uniqueId() << " node " << stuff;
1773 }
1774 stuff.clear();
1775 }
1776 info() << "#Arcane face numbering:";
1777 std::cout << "{";
1778 ENUMERATE_FACE (iface, mesh->allFaces()) {
1779 const Face& face = *iface;
1780 UniqueArray<Int64> stuff;
1781 std::cout << "{" << face.nodes()[0].uniqueId().asInt64();
1782
1783 for (Integer i = 1; i < face.nodes().size(); i++) {
1784 std::cout << "," << face.nodes()[i].uniqueId().asInt64();
1785 }
1786 //stuff.add(node_uid_to_cell_local_id[node.uniqueId().asInt64()]);
1787 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1788 //std::cout << node_uid_to_cell_local_id[node.uniqueId().asInt64()] ;
1789
1790 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1791 std::cout << "}," << std::endl;
1792 }
1793 std::cout << "}";
1794 Arcane::VariableScalarInteger m_temperature(Arcane::VariableBuildInfo(mesh, "ArcaneCheckpointNextIteration"));
1795
1796 VariableCellInt64* arcane_cell_uid = nullptr;
1797 VariableFaceInt64* arcane_face_uid = nullptr;
1798 VariableNodeInt64* arcane_node_uid = nullptr;
1799 arcane_cell_uid = new VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_cell_uid", mesh->cellFamily()->name()));
1800 arcane_face_uid = new VariableFaceInt64(Arcane::VariableBuildInfo(mesh, "arcane_face_uid", mesh->faceFamily()->name()));
1801 arcane_node_uid = new VariableNodeInt64(Arcane::VariableBuildInfo(mesh, "arcane_node_uid", mesh->nodeFamily()->name()));
1802
1803 ENUMERATE_CELL (icell, mesh->allCells()) {
1804 (*arcane_cell_uid)[icell] = icell->uniqueId().asInt64();
1805 }
1806 ENUMERATE_FACE (iface, mesh->allFaces()) {
1807 (*arcane_face_uid)[iface] = iface->uniqueId().asInt64();
1808 }
1809 info() << "#INODE";
1810 ENUMERATE_NODE (inode, mesh->allNodes()) {
1811 (*arcane_node_uid)[inode] = inode->uniqueId().asInt64();
1812 info() << inode->uniqueId().asInt64();
1813 }
1814 /*
1815 ENUMERATE_(Node, inode, mesh->nodeFamily()->view().subView(4,nodes_uid.size())){
1816 Node node = *inode;
1817 nodes_coords[node] = nodes_to_add_coords[node.uniqueId()];
1818 info() << node.uniqueId() << " " << nodes_coords[node] ;
1819 }
1820 */
1821 //
1822 // On va chercher le service directement sans utiliser dans le .arc
1823 /*Directory d = mesh->subDomain()->exportDirectory();
1824 info() << "Writing at " << d.path() ;
1825 ServiceBuilder<IPostProcessorWriter> spp(mesh->handle());
1826
1827 Ref<IPostProcessorWriter> post_processor = spp.createReference("Ensight7PostProcessor"); // vtkHdf5PostProcessor
1828 //Ref<IPostProcessorWriter> post_processor = spp.createReference("VtkLegacyMeshWriter"); // (valid values = UCDPostProcessor, UCDPostProcessor, Ensight7PostProcessor, Ensight7PostProcessor)
1829 // Path de base
1830 // <fichier-binaire>false</fichier-binaire>
1831 post_processor->setBaseDirectoryName(d.path());
1832
1833 post_processor->setTimes(UniqueArray<Real>{0.1}); // Juste pour fixer le pas de temps
1834
1835 VariableList variables;
1836 variables.add(mesh->nodesCoordinates().variable());
1837 variables.add(*arcane_node_uid);
1838 variables.add(*arcane_face_uid);
1839 variables.add(*arcane_cell_uid);
1840 post_processor->setVariables(variables);
1841
1842 ItemGroupList groups;
1843 groups.add(mesh->allNodes());
1844 groups.add(mesh->allFaces());
1845 groups.add(mesh->allCells());
1846 post_processor->setGroups(groups);
1847
1848 IVariableMng* vm = mesh->subDomain()->variableMng();
1849
1850 vm->writePostProcessing(post_processor.get());
1851 mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output.vtk", "VtkLegacyMeshWriter");
1852 */
1853 info() << "#ENDSUBDV ";
1854}
1855
1857{
1858 mesh->utilities()->writeToFile("subdivider_one_quad_input.vtk", "VtkLegacyMeshWriter");
1859
1860 // On supprime l'ancien maillage
1861 Int32UniqueArray lids(mesh->allCells().size());
1862 ENUMERATE_CELL (icell, mesh->allCells()) {
1863 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1864 << icell->type() << ", nb nodes=" << icell->nbNode();
1865 lids[icell.index()] = icell->localId();
1866 }
1867 IMeshModifier* modifier = mesh->modifier();
1868 modifier->removeCells(lids);
1869 modifier->endUpdate();
1870
1871 // On creer notre Quad
1872 Int64UniqueArray nodes_uid(4);
1873 for (Integer i = 0; i < 4; i++)
1874 nodes_uid[i] = i;
1875
1876 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1877 modifier->addNodes(nodes_uid, nodes_lid.view());
1878 mesh->nodeFamily()->endUpdate();
1879 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1880 NodeInfoListView new_nodes(mesh->nodeFamily());
1881 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1882 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1883 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1884 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
1885
1886 Int64UniqueArray cells_infos(6);
1887 Int64UniqueArray faces_infos;
1888 cells_infos[0] = IT_Quad4; // type
1889 cells_infos[1] = 44; // cell uid
1890 cells_infos[2] = nodes_uid[0]; // node 0
1891 cells_infos[3] = nodes_uid[1]; // ... 1
1892 cells_infos[4] = nodes_uid[2]; // ... 2
1893 cells_infos[5] = nodes_uid[3]; // ... 3
1894
1895 IntegerUniqueArray cells_lid;
1896 modifier->addCells(1, cells_infos, cells_lid);
1897 modifier->endUpdate();
1898 mesh->utilities()->writeToFile("subdivider_one_quad_ouput.vtk", "VtkLegacyMeshWriter");
1899}
1900
1902{
1903 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
1904 // On supprime l'ancien maillage
1905 Int32UniqueArray lids(mesh->allCells().size());
1906 ENUMERATE_CELL (icell, mesh->allCells()) {
1907 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1908 << icell->type() << ", nb nodes=" << icell->nbNode();
1909 lids[icell.index()] = icell->localId();
1910 }
1911 IMeshModifier* modifier = mesh->modifier();
1912 modifier->removeCells(lids);
1913 modifier->endUpdate();
1914 // On creer notre Hexa
1915 Int64UniqueArray nodes_uid(3);
1916 for (Integer i = 0; i < 3; i++)
1917 nodes_uid[i] = i;
1918
1919 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1920 modifier->addNodes(nodes_uid, nodes_lid.view());
1921 mesh->nodeFamily()->endUpdate();
1922 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1923 NodeInfoListView new_nodes(mesh->nodeFamily());
1924 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1925 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1926 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1927
1928 Int64UniqueArray cells_infos(10);
1929 Int64UniqueArray faces_infos;
1930 cells_infos[0] = IT_Triangle3; // type
1931 cells_infos[1] = 44; // cell uid
1932 cells_infos[2] = nodes_uid[0]; // node 0
1933 cells_infos[3] = nodes_uid[1]; // ... 1
1934 cells_infos[4] = nodes_uid[2]; // ... 2
1935
1936 IntegerUniqueArray cells_lid;
1937 modifier->addCells(1, cells_infos, cells_lid);
1938 modifier->endUpdate();
1939 mesh->utilities()->writeToFile("subdivider_one_tri.vtk", "VtkLegacyMeshWriter");
1940}
1941
1943{
1944 UniqueArray<Int64> new_node_uid;
1945 Integer init_size = node_in_cell.size();
1946 for (Integer i = 0; i < node_pattern.size(); i++) {
1947 //info() << "test " << i ;
1948 UniqueArray<Int64> tmp = node_pattern[i];
1949 tmp.resize(node_pattern[i].size());
1950 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1951 tmp.add(node_in_cell[node_pattern[i][j]]);
1952 }
1953 // uid
1954 std::sort(tmp.begin(), tmp.end());
1955 node_in_cell.add(init_size + i); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
1956 new_node_uid.add(node_in_cell[init_size + i]);
1957 }
1958 return new_node_uid;
1959}
1960
1961ArcaneBasicMeshSubdividerService::
1962ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi)
1964{
1965}
1966
1968{
1969 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
1970 // On supprime l'ancien maillage
1971 Int32UniqueArray lids(mesh->allCells().size());
1972 ENUMERATE_CELL (icell, mesh->allCells()) {
1973 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1974 << icell->type() << ", nb nodes=" << icell->nbNode();
1975 lids[icell.index()] = icell->localId();
1976 }
1977 IMeshModifier* modifier = mesh->modifier();
1978 modifier->removeCells(lids);
1979 modifier->endUpdate();
1980 // On creer notre Hexa
1981 Int64UniqueArray nodes_uid(8);
1982 for (Integer i = 0; i < 8; i++)
1983 nodes_uid[i] = i;
1984
1985 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1986 modifier->addNodes(nodes_uid, nodes_lid.view());
1987 mesh->nodeFamily()->endUpdate();
1988 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1989 NodeInfoListView new_nodes(mesh->nodeFamily());
1990 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1991 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1992 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1993 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
1994 nodes_coords[new_nodes[nodes_lid[4]]] = Arcane::Real3(0.0, 0.0, 10.0);
1995 nodes_coords[new_nodes[nodes_lid[5]]] = Arcane::Real3(10.0, 0.0, 10.0);
1996 nodes_coords[new_nodes[nodes_lid[6]]] = Arcane::Real3(10.0, 10.0, 10.0);
1997 nodes_coords[new_nodes[nodes_lid[7]]] = Arcane::Real3(0.0, 10.0, 10.0);
1998
1999 Int64UniqueArray cells_infos(10);
2000 Int64UniqueArray faces_infos;
2001 cells_infos[0] = IT_Hexaedron8; // type
2002 cells_infos[1] = 44; // cell uid
2003 cells_infos[2] = nodes_uid[0]; // node 0
2004 cells_infos[3] = nodes_uid[1]; // ... 1
2005 cells_infos[4] = nodes_uid[2]; // ... 2
2006 cells_infos[5] = nodes_uid[3]; // ... 3
2007 cells_infos[6] = nodes_uid[4]; // ... 4
2008 cells_infos[7] = nodes_uid[5]; // ... 5
2009 cells_infos[8] = nodes_uid[6]; // ... 6
2010 cells_infos[9] = nodes_uid[7]; // ... 7
2011
2012 IntegerUniqueArray cells_lid;
2013 modifier->addCells(1, cells_infos, cells_lid);
2014 modifier->endUpdate();
2015 // On crée un groupe test
2016 UniqueArray<Int64> face_uid;
2017 ENUMERATE_FACE (iface, mesh->allFaces()) {
2018 Face face = *iface;
2019 face_uid.add(face.uniqueId());
2020 }
2021 UniqueArray<Int32> face_lid(face_uid.size());
2022 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
2023 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
2024 mesh->utilities()->writeToFile("subdivider_one_hexa_ouput.vtk", "VtkLegacyMeshWriter");
2025}
2026
2028{
2029
2030 mesh->utilities()->writeToFile("subdivider_one_tetra_input.vtk", "VtkLegacyMeshWriter");
2031
2032 // On supprime l'ancien maillage si besoin
2033 Int32UniqueArray lids(mesh->allCells().size());
2034 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
2035 ENUMERATE_CELL (icell, mesh->allCells()) {
2036 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
2037 << icell->type() << ", nb nodes=" << icell->nbNode();
2038 lids[icell.index()] = icell->localId();
2039 }
2040 IMeshModifier* modifier = mesh->modifier();
2041 modifier->removeCells(lids);
2042 modifier->endUpdate();
2043
2044 // Maillage vide, on créer notre tetra
2045
2046 info() << "===================== THE MESH IS EMPTY";
2047
2048 // On ajoute des noeuds
2049 Int64UniqueArray nodes_uid(4);
2050 for (Integer i = 0; i < 4; i++)
2051 nodes_uid[i] = i;
2052
2053 UniqueArray<Int32> nodes_lid(nodes_uid.size());
2054 modifier->addNodes(nodes_uid, nodes_lid.view());
2055 mesh->nodeFamily()->endUpdate();
2056 info() << "===================== THE MESH IS EMPTY";
2057
2058 NodeInfoListView new_nodes(mesh->nodeFamily());
2059
2060 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
2061 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
2062 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(5.0, 5.0 / 3.0, 10.0);
2063 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(5.0, 5.0, 0.0);
2064
2065 Int64UniqueArray cells_infos(1 * 6);
2066 Int64UniqueArray faces_infos;
2067
2068 cells_infos[0] = IT_Tetraedron4; // type
2069 cells_infos[1] = 44; // cell uid
2070 cells_infos[2] = nodes_uid[0]; // node 0
2071 cells_infos[3] = nodes_uid[1]; // ... 1
2072 cells_infos[4] = nodes_uid[2]; // ... 2
2073 cells_infos[5] = nodes_uid[3]; // ... 3
2074
2075 IntegerUniqueArray cells_lid;
2076 modifier->addCells(1, cells_infos, cells_lid);
2077 modifier->endUpdate();
2078
2079 // On crée un groupe test
2080 UniqueArray<Int64> face_uid;
2081 ENUMERATE_FACE (iface, mesh->allFaces()) {
2082 Face face = *iface;
2083 face_uid.add(face.uniqueId());
2084 }
2085 UniqueArray<Int32> face_lid(face_uid.size());
2086 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
2087 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
2088
2089 info() << "===================== THE CELLS ARE ADDED";
2090}
2091
2092/* Le but est simplement d'avoir l'ordre des faces dans un élément*/
2094{
2095 mesh->utilities()->writeToFile("3D_last_input_seq.vtk", "VtkLegacyMeshWriter");
2096 info() << "#ORDRE FACES";
2097 ENUMERATE_CELL (icell, mesh->ownCells()) {
2098
2099 const Cell& cell = *icell;
2100 for (Face face : cell.faces()) {
2102 for (Node node : face.nodes()) {
2103 n.add(node.uniqueId().asInt64());
2104 }
2105 info() << face.uniqueId() << " nodes " << n;
2106 }
2107 }
2108}
2109
2111{
2112 info() << "Change uniqueId() for family=" << family->name();
2113 items_new_uid.synchronize();
2114 ENUMERATE_ (Item, iitem, family->allItems()) {
2115 Item item{ *iitem };
2116 Int64 current_uid = item.uniqueId();
2117 Int64 new_uid = items_new_uid[iitem];
2118 if (new_uid >= 0 && new_uid != current_uid) {
2119 item.mutableItemBase().setUniqueId(new_uid);
2120 }
2121 }
2123}
2124
2133{
2134 // Pour chaque noeud, on met la cell incidente avec l'uid le plus petit
2135 VariableNodeInt64 nodes_min_cell_uid(VariableBuildInfo(mesh, "ArcaneNodeMinCellUid"));
2136 nodes_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2137 ENUMERATE_NODE (inode, mesh->ownNodes()) {
2138 Node node = *inode;
2139 auto cells = node.cells();
2140 Int64 min = cells[0].uniqueId();
2141 for (auto c : cells) {
2142 if (min > c.uniqueId()) {
2143 min = c.uniqueId();
2144 }
2145 }
2146 nodes_min_cell_uid[node] = min;
2147 }
2148 // idem pour face
2149 VariableFaceInt64 faces_min_cell_uid(VariableBuildInfo(mesh, "ArcaneFaceMinCellUid"));
2150 faces_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2151 ENUMERATE_FACE (iface, mesh->ownFaces()) {
2152 Face face = *iface;
2153 auto cells = face.cells();
2154 Int64 min = cells[0].uniqueId();
2155 for (auto c : cells) {
2156 if (min > c.uniqueId()) {
2157 min = c.uniqueId();
2158 }
2159 }
2160 faces_min_cell_uid[face] = min;
2161 }
2162 //
2163 nodes_min_cell_uid.synchronize();
2164 faces_min_cell_uid.synchronize();
2165
2166 VariableNodeInt64 nodes_new_uid(VariableBuildInfo(mesh, "ArcaneRenumberNodesNewUid"));
2167 VariableFaceInt64 faces_new_uid(VariableBuildInfo(mesh, "ArcaneRenumberFacesNewUid"));
2168 // Renumérotation selon C des F et N dans vars
2169 // ?? Attention au ghost layer ??
2170 nodes_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2171 faces_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2172
2173 ENUMERATE_CELL (icell, mesh->ownCells()) {
2174 Cell cell = *icell;
2175 Int64 count_nodes = 0;
2176 for (Node node : cell.nodes()) {
2177 if (nodes_new_uid[node] == NULL_ITEM_UNIQUE_ID && cell.uniqueId() == nodes_min_cell_uid[node]) {
2178 nodes_new_uid[node] = cell.uniqueId().asInt64() * cell.nbNode() + count_nodes;
2179 count_nodes++;
2180 }
2181 }
2182 Int64 count_faces = 0;
2183 for (Face face : cell.faces()) {
2184 if (faces_new_uid[face] == NULL_ITEM_UNIQUE_ID && cell.uniqueId() == faces_min_cell_uid[face]) {
2185 faces_new_uid[face] = cell.uniqueId().asInt64() * cell.nbFace() + count_faces;
2186 count_faces++;
2187 }
2188 }
2189 }
2190 // Application
2191 _applyFamilyRenumbering(mesh->nodeFamily(), nodes_new_uid);
2192 _applyFamilyRenumbering(mesh->faceFamily(), faces_new_uid);
2193 // mesh->checkValidMesh();
2194
2195}
2196
2198{
2199 bool print_hash = true;
2200 bool with_ghost = false;
2201 MD5HashAlgorithm hash_algo;
2202 MeshUtils::checkUniqueIdsHashCollective(mesh->nodeFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2203 MeshUtils::checkUniqueIdsHashCollective(mesh->faceFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2204 MeshUtils::checkUniqueIdsHashCollective(mesh->cellFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2205}
2206
2207
2208
2209
2211subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh)
2212{
2213 Arcane::Timer total_time(mesh->subDomain(),"TimerSubdividerTotal",Timer::eTimerType::TimerReal);
2214 total_time.start();
2215 //exit(0);
2216 //_generateOneTetra(mesh);
2217 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
2218 // Default pattern manager
2219 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
2220 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
2221 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
2222 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
2223
2224
2225 if (options()->differentElementTypeOutput()) {
2226 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
2227 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
2228 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
2229 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
2230 info() << "The refinement patterns have changed for meshes of the following types: Quad4, Triangle3, Hexaedron8, Tetraedron4.";
2231 info() << "The output element types will be:\nQuad4->Triangle3\nTriangle3->Quad4\nHexaedron8->Tetraedron4\nTetraedron4->Hexaedron8";
2232 }
2233
2234 Arcane::Timer timer_subdivide_step(mesh->subDomain(),"TimerSubdivider",Timer::eTimerType::TimerReal);
2235 Arcane::Timer timer_renumbering_step(mesh->subDomain(),"TimerRenumbering",Timer::eTimerType::TimerReal);
2236 Arcane::Timer timer_renumbering_apply_step(mesh->subDomain(),"TimerRenumberingApply",Timer::eTimerType::TimerReal);
2237
2238 timer_subdivide_step.start();
2239
2240 for (Integer i = 0; i < options()->nbSubdivision; i++) {
2241 _refineOnce(mesh, pattern_manager);
2242 debug() << i << "refine done";
2243 }
2244
2245 timer_subdivide_step.stop();
2246
2247 timer_renumbering_step.start();
2248
2249 // Renumbering Node, Faces, using Cells uids
2251 // * Transform in option <without-renumber-compact>
2252
2253 timer_renumbering_step.stop();
2254
2255 timer_renumbering_apply_step.start();
2256
2257 mesh->properties()->setBool("compact",true);
2258 mesh->properties()->setBool("sort",true);
2259 mesh->modifier()->endUpdate();
2260
2261 timer_renumbering_apply_step.stop();
2262
2263
2264 total_time.stop();
2265
2266 traceMng()->info() << "Timers " << timer_subdivide_step.name() << " " << timer_subdivide_step.totalTime() ;
2267 traceMng()->info() << "Timers " << timer_renumbering_step.name() << " " << timer_renumbering_step.totalTime() ;
2268 traceMng()->info() << "Timers " << timer_renumbering_apply_step.name() << " " << timer_renumbering_apply_step.totalTime() ;
2269 traceMng()->info() << "Timers " << total_time.name() << " " << total_time.totalTime() ;
2270
2271 // VariableList vl;
2272 //_writeEnsight(mesh,"SubdividerRenumberTests",vl);
2273 // Debug After
2274 // mesh->utilities()->writeToFile("subdivider_output_"+std::to_string(mesh->parallelMng()->commRank())+".vtk", "VtkLegacyMeshWriter");
2275 //mesh->utilities()->writeToFile("subdivider_after_" + std::to_string(options()->nbSubdivision) + "refine.vtk", "VtkLegacyMeshWriter");
2276 //debug() << "write file with name:" << "subdivider_after_";
2277 /*
2278 mesh->utilities()->writeToFile("subdivider_output.vtk", "VtkLegacyMeshWriter");
2279 */
2280 //_checkMeshUid(mesh);
2281 //MeshUtils::writeMeshInfosSorted(mesh,"vp_meshinfo"+std::to_string(mesh->parallelMng()->commRank()));
2282 info() << "subdivider done";
2283}
2284
2285/*---------------------------------------------------------------------------*/
2286/*---------------------------------------------------------------------------*/
2287
2288ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
2290
2291/*---------------------------------------------------------------------------*/
2292/*---------------------------------------------------------------------------*/
2293
2294} // End namespace Arcane
2295
2296/*---------------------------------------------------------------------------*/
2297/*---------------------------------------------------------------------------*/
#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_EDGE(name, group)
Enumérateur générique d'un groupe d'arêtes.
#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.
void checkUniqueIdsHashCollective(IItemFamily *family, IHashAlgorithm *hash_algo, const String &expected_hash, bool print_hash_value, bool include_ghost)
Vérifie le hash des uniqueId() des entités d'une famille.
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 _applyFamilyRenumbering(IItemFamily *family, VariableItemInt64 &items_new_uid)
Renumérote la famille TODO mettre en commun avec AMR.
void _checkHashNodesFacesCells(IPrimaryMesh *mesh)
Calcul du hash des N F C.
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 _renumberNodesFaces(IPrimaryMesh *mesh)
Renumérote les noeuds et les faces en fonction des cellules Cette méthode ne compacte pas,...
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 _checkMeshUid(IPrimaryMesh *mesh)
Vérification que tout les uids sont >= 0.
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:1214
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Definition Item.h:1298
Face face(Int32 i) const
i-ème face de la maille
Definition Item.h:1295
Int32 nbFace() const
Nombre de faces de la maille.
Definition Item.h:1292
Integer count() const
Nombre d'éléments de la collection.
Classe gérant un répertoire.
Definition Directory.h:35
String path() const override
Retourne le chemin du répertoire.
Definition Directory.cc:111
Arête d'une maille.
Definition Item.h:826
Face d'une maille.
Definition Item.h:964
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1665
CellConnectedListViewType cells() const
Liste des mailles de la face.
Definition Item.h:1048
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 void notifyItemsUniqueIdChanged()=0
Notifie que les numéros uniques des entités ont été modifiées.
virtual ItemGroupCollection groups() const =0
Liste des groupes de cette famille.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual String name() const =0
Nom de la 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.
virtual TraceMessage info()=0
Flot pour un message d'information.
Interface du gestionnaire de variables.
Interface d'une variable.
Definition IVariable.h:39
virtual String itemFamilyName() const =0
Nom de la famille associée (nul si aucune).
virtual String fullName() const =0
Nom complet de la variable (avec le préfixe de la famille)
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
Definition IVariable.h:57
virtual int property() const =0
Retourne les propriétés de la variable.
virtual bool isUsed() const =0
Etat d'utilisation de la variable.
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:158
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:446
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Definition ItemGroup.cc:610
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Definition Item.h:794
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Definition Item.h:797
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:380
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
Calcule la fonction de hashage MD5 d'un tableau.
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 à raffiner.
StorageRefine nodes
Matrice pour la génération des nouveaux noeuds.
Int16 face_type
Type de la face de l'élément à raffiner.
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:582
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1616
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:692
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.
Classe utilitaire pour instantier un service d'une interface donnée.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
Gestion d'un timer.
Definition Timer.h:62
const String & name() const
Retourne le nom du timer.
Definition Timer.h:213
Real stop()
Désactive le timer.
Definition Timer.cc:87
@ TimerReal
Timer utilisant le temps réel.
Definition Timer.h:76
Real totalTime() const
Retourne le temps total (en secondes) passé dans le timer.
Definition Timer.h:216
void start()
Active le timer.
Definition Timer.cc:70
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
Collection de variables.
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, Int64 > VariableNodeInt64
Grandeur au noeud de type entier 64 bits.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
ItemVariableScalarRefT< Int64 > VariableItemInt64
Grandeur 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.
@ ReduceMax
Maximum des valeurs.
-*- 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:339
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:341
std::int16_t Int16
Type entier signé sur 16 bits.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:347
std::int32_t Int32
Type entier signé sur 32 bits.