Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
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/* Arcane Service managing a dataset mesh. */
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 in SVG format for 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// Add 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{
75typedef UniqueArray<UniqueArray<Int64>> StorageRefine;
76}
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
81namespace Arcane::MeshSubdivider
82{
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
90class Pattern
91{
92 public:
93
101 StorageRefine nodes;
103 StorageRefine faces;
105 StorageRefine cells;
106 StorageRefine child_faces; // Link between parent cell faces and child cell faces.
107 // ^-- For managing groups or properties. For example, for the sod, a parent face in the "membrane" group must generate faces with the same group.
108 // Internal faces do not have a parent face but might need to propagate or deposit properties on these faces.
109 // For now, they are simply not in the groups.
110
111 // In fact, the only important information is in 'cells' and 'nodes'. Arcane can deduce the faces for us, and we keep the same order for the parallel execution.
112 // For child faces
113
114 public:
115
116 Pattern()
117 : type(IT_NullType)
118 , face_type(IT_NullType)
119 , cell_type(IT_NullType)
120 {}
121
122 Pattern(Int16 type, Int16 face_type, Int16 cell_type, StorageRefine nodes, StorageRefine faces, StorageRefine cells, StorageRefine child_faces)
123 {
124 this->type = type;
125 this->face_type = face_type;
126 this->cell_type = cell_type;
127 this->nodes = nodes;
128 this->faces = faces;
129 this->cells = cells;
130 this->child_faces = child_faces;
131 }
132
133 Pattern(Pattern&& other) noexcept
134 : type(other.type)
135 , face_type(other.face_type)
136 , cell_type(other.cell_type)
137 , nodes(other.nodes)
138 , faces(other.faces)
139 , cells(other.cells)
140 , child_faces(other.child_faces)
141 {}
142
143 Pattern(const Pattern&) = delete;
144
145 Pattern(Pattern& other) noexcept
146 : type(other.type)
147 , face_type(other.face_type)
148 , cell_type(other.cell_type)
149 , nodes(other.nodes)
150 , faces(other.faces)
151 , cells(other.cells)
152 , child_faces(other.child_faces)
153 {}
154 Pattern& operator=(const Pattern& other)
155 {
156 if (this != &other) {
157 type = other.type;
158 face_type = other.face_type;
159 cell_type = other.cell_type;
160 nodes = other.nodes; // Shared reference
161 faces = other.faces; // Shared reference
162 cells = other.cells; // Shared reference
163 child_faces = other.child_faces;
164 }
165 return *this;
166 }
167
168 Pattern& operator=(Pattern&& other) noexcept
169 {
170 if (this != &other) {
171 type = other.type;
172 face_type = other.face_type;
173 cell_type = other.cell_type;
174 nodes = other.nodes;
175 faces = other.faces;
176 cells = other.cells;
177 child_faces = other.child_faces;
178 }
179 return *this;
180 }
181 Pattern& operator=(Pattern& other) noexcept
182 {
183 if (this != &other) {
184 type = other.type;
185 face_type = other.face_type;
186 cell_type = other.cell_type;
187 nodes = other.nodes;
188 faces = other.faces;
189 cells = other.cells;
190 child_faces = other.child_faces;
191 }
192 return *this;
193 }
194};
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199} // namespace Arcane::MeshSubdivider
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204namespace Arcane
205{
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
209
214{
215 public:
216
217 // 2D
218 // TODO test + f + cf
219 static MeshSubdivider::Pattern quadtoquad();
220 // TODO test + f + cf
221 static MeshSubdivider::Pattern quadtotri();
222 // TODO test + f + cf
223 static MeshSubdivider::Pattern tritotri();
224 // TODO test + f + cf
225 static MeshSubdivider::Pattern tritoquad();
226 // 3D
227 // Does not use Arcane's face numbering for now
228 static MeshSubdivider::Pattern hextohex();
229
230 static MeshSubdivider::Pattern tettotet();
231
232 static MeshSubdivider::Pattern hextotet(); // Does not work because rotation is not taken into account.
233
234 static MeshSubdivider::Pattern tettohex();
235
236 static MeshSubdivider::Pattern hextotet24();
237};
238
239/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242/*
243
244Nodes
245(3) --- (2)
246 | |
247 | |
248(0) --- (1)
249Edge order
250(3) -2- (2)
251 | |
252 3 1
253 | |
254(0) -0- (1)
255New nodes
256(3) -6- (2)
257 | |
258 7 8 5
259 | |
260(0) -4- (1)
261New nodes with new edge order
262(3) -5- (6) -7- (2)
263| | |
2644 6 8
265| | |
266(7) -1- (8) -9- (5)
267| | |
2680 2 10
269| | |
270(0) -3- (4) -11- (1)
271 --- ---
272| | |
273| | |
274 --- ---
275| | |
276| | |
277 --- ---
278*/
279MeshSubdivider::Pattern PatternBuilder::
280quadtoquad()
281{
282 StorageRefine nodes({
283 { 0, 1 }, // 4
284 { 1, 2 }, // 5
285 { 2, 3 }, // 6
286 { 3, 0 }, // 7
287 { 0, 1, 2, 3 }, // 8
288 });
289 StorageRefine faces({
290 { 0, 7 }, // 0
291 { 7, 8 }, // 1
292 { 4, 8 }, // 2
293 { 0, 4 }, // 3
294 { 3, 7 }, // 4
295 { 3, 6 }, // 5
296 { 6, 8 }, // 6
297 { 2, 6 }, // 7
298 { 2, 5 }, // 8
299 { 5, 8 }, // 9
300 { 1, 5 }, // 10
301 { 1, 4 }, // 11
302 });
303 StorageRefine cells({
304 { 0, 7, 8, 4 },
305 { 7, 3, 6, 8 },
306 { 6, 2, 5, 8 },
307 { 5, 1, 4, 8 },
308 });
309 StorageRefine child_faces({
310 // not tested
311 { 3, 11 },
312 { 10, 8 },
313 { 5, 7 },
314 { 0, 4 },
315 });
316 return { IT_Quad4, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
317}
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322/*
323 * For a quad:
324 * 3 --- 2
325 * | |
326 * | |
327 * 0 --- 1
328 *
329 * 3 --> 2
330 * | / |
331 * | / |
332 * 0 <-- 1
333 *
334 * 3 --- 4 --- 5
335 * | | |
336 * | | |
337 * 0 --- 1 --- 2
338 * Here we add a single arcane face (0,2).
339*/
340MeshSubdivider::Pattern PatternBuilder::
341quadtotri()
342{
343 StorageRefine nodes({}); // No node to add
344 StorageRefine faces({
345 /*{0,1},
346 {1,3},
347 {2,3},*/
348 { 0, 2 },
349 //{0,3}
350 });
351 StorageRefine cells({ { 0, 3, 2 }, { 2, 1, 0 } });
352 StorageRefine child_faces({});
353 return { IT_Quad4, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
354}
355
356/*---------------------------------------------------------------------------*/
357/*---------------------------------------------------------------------------*/
358
359/*
360 New node numbering
361 2
362 / \
363 / \
364 5 --- 4
365 / \ / \
366 / \ / \
367 0 --- 3 --- 1
368
369 Edge numbering
370 2
371 / \
372 6 7
373 / \
374 + --8-- +
375 / \ / \
376 1 2 5 3
377 / \ / \
378 + --0-- + --4-- +
379 */
380
381MeshSubdivider::Pattern PatternBuilder::
382tritotri()
383{
384 StorageRefine nodes({
385 { 0, 1 }, // 3
386 { 1, 2 }, // 4
387 { 2, 0 }, // 5
388 });
389 StorageRefine faces({
390 { 0, 3 },
391 { 0, 5 },
392 { 3, 5 },
393 { 1, 4 },
394 { 1, 3 },
395 { 3, 4 },
396 { 2, 5 },
397 { 2, 4 },
398 { 4, 5 },
399 });
400 StorageRefine cells({ { 3, 0, 5 },
401 { 4, 1, 3 },
402 { 5, 2, 4 },
403 { 3, 5, 4 } });
404 StorageRefine child_faces(
405 { { 0, 4 },
406 { 3, 7 },
407 { 1, 6 } });
408 return { IT_Triangle3, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
409}
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
413
414MeshSubdivider::Pattern PatternBuilder::
415tritoquad()
416{
417 StorageRefine nodes({
418 { 0, 1 }, // 3
419 { 1, 2 }, // 4
420 { 2, 0 }, // 5
421 { 0, 1, 2 }, // 6
422 });
423 StorageRefine faces({
424
425 });
426 StorageRefine cells({
427 { 0, 3, 6, 5 },
428 { 1, 4, 6, 3 },
429 { 2, 5, 6, 4 },
430 });
431 StorageRefine child_faces({});
432 return { IT_Triangle3, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
433}
434
435/*---------------------------------------------------------------------------*/
436/*---------------------------------------------------------------------------*/
437
438// Does not use Arcane's face numbering for now
439MeshSubdivider::Pattern PatternBuilder::
440hextohex()
441{
442 StorageRefine nodes = {
443 { 0, 1 }, // 8 // On edges
444 { 0, 3 }, // 9
445 { 0, 4 }, // 10
446 { 1, 2 }, // 11
447 { 1, 5 }, // 12
448 { 2, 3 }, // 13
449 { 2, 6 }, // 14
450 { 3, 7 }, // 15
451 { 4, 5 }, // 16
452 { 4, 7 }, // 17
453 { 5, 6 }, // 18
454 { 6, 7 }, // 19
455 { 0, 1, 2, 3 }, // 20 // On faces
456 { 0, 1, 5, 4 }, // 21
457 { 0, 4, 7, 3 }, // 22
458 { 1, 5, 6, 2 }, // 23
459 { 2, 3, 7, 6 }, // 24
460 { 4, 5, 6, 7 }, // 25
461 { 0, 1, 5, 4, 3, 2, 7, 6 } // 26 // Centroid
462 };
463 StorageRefine faces = {
464 // External
465 { 0, 8, 20, 9 }, // Back // 0 1 2 3 // 0
466 { 9, 20, 13, 3 },
467 { 8, 1, 11, 20 },
468 { 20, 11, 2, 13 },
469 { 0, 10, 22, 9 }, // Left // 0 3 7 4 // 1
470 { 9, 22, 15, 3 },
471 { 10, 4, 17, 22 },
472 { 22, 17, 7, 15 },
473 { 4, 16, 21, 10 }, // Bottom // 4 5 0 1 // 2
474 { 10, 21, 8, 0 },
475 { 16, 5, 12, 21 },
476 { 21, 12, 1, 8 },
477 { 4, 16, 25, 17 }, // Front // 4 5 6 7 // 3
478 { 17, 25, 19, 7 },
479 { 16, 5, 18, 25 },
480 { 25, 18, 6, 19 },
481 { 1, 12, 23, 11 }, // Right // 1 2 5 6 // 4
482 { 11, 23, 14, 2 },
483 { 12, 5, 18, 23 },
484 { 23, 18, 6, 14 },
485 { 7, 19, 24, 15 }, // Top // 7 6 2 3 // 5
486 { 19, 6, 14, 24 },
487 { 15, 24, 13, 3 },
488 { 24, 14, 2, 13 },
489 // Internal
490 { 8, 20, 26, 21 },
491 { 20, 13, 24, 26 },
492 { 9, 22, 26, 20 },
493 { 20, 26, 23, 11 },
494 { 21, 16, 25, 26 },
495 { 26, 25, 19, 24 },
496 { 22, 17, 25, 26 },
497 { 26, 25, 18, 23 },
498 { 10, 21, 26, 22 },
499 { 21, 12, 23, 26 },
500 { 22, 26, 24, 15 },
501 { 26, 23, 14, 24 },
502
503 };
504 StorageRefine child_faces = {
505 { 0, 1, 2, 3 },
506 { 4, 5, 6, 7 },
507 { 8, 9, 10, 11 },
508 { 12, 13, 14, 15 },
509 { 16, 17, 18, 19 },
510 { 20, 21, 22, 23 }
511 };
512 StorageRefine cells = {
513 { 0, 8, 20, 9, 10, 21, 26, 22 },
514 { 10, 21, 26, 22, 4, 16, 25, 17 },
515 { 8, 1, 11, 20, 21, 12, 23, 26 },
516 { 21, 12, 23, 26, 16, 5, 18, 25 },
517 { 9, 20, 13, 3, 22, 26, 24, 15 },
518 { 22, 26, 24, 15, 17, 25, 19, 7 },
519 { 20, 11, 2, 13, 26, 23, 14, 24 },
520 { 26, 23, 14, 24, 25, 18, 6, 19 }
521 };
522 return { IT_Hexaedron8, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
523}
524
525/*---------------------------------------------------------------------------*/
526/*---------------------------------------------------------------------------*/
527
528MeshSubdivider::Pattern PatternBuilder::
529tettotet()
530{
531 StorageRefine nodes = {
532 { 0, 1 }, // 4
533 { 1, 2 }, // 5
534 { 0, 2 }, // 6
535 { 0, 3 }, // 7
536 { 2, 3 }, // 8
537 { 1, 3 }, // 9
538 };
539
540 StorageRefine faces = {
541 { 0, 4, 6 }, // 0
542 { 0, 6, 7 }, // 1
543 { 0, 4, 7 }, // 2
544 { 4, 6, 7 }, // 3
545 { 1, 4, 5 }, // 4
546 { 4, 5, 9 }, // 5
547 { 1, 4, 9 }, // 6
548 { 1, 5, 9 }, // 7
549 { 2, 5, 6 }, // 8
550 { 2, 6, 8 }, // 9
551 { 5, 6, 8 }, // 10
552 { 2, 5, 8 }, // 11
553 { 7, 8, 9 }, // 12
554 { 3, 7, 8 }, // 13
555 { 3, 7, 9 }, // 14
556 { 3, 8, 9 }, // 15
557 { 4, 7, 9 }, // 16
558 { 4, 6, 9 }, // 17
559 { 6, 7, 9 }, // 18
560 { 4, 5, 6 }, // 19
561 { 5, 6, 9 }, // 20
562 { 6, 8, 9 }, // 21
563 { 6, 7, 8 }, // 22
564 { 5, 8, 9 }, // 23
565 };
566 StorageRefine child_faces = {
567 { 0, 19, 4, 8 },
568 { 1, 22, 13, 9 },
569 { 2, 16, 6, 14 },
570 { 11, 23, 7, 15 }
571 };
572 StorageRefine cells = {
573 { 0, 4, 6, 7 },
574 { 4, 1, 5, 9 },
575 { 6, 5, 2, 8 },
576 { 7, 9, 8, 3 },
577 { 4, 6, 7, 9 },
578 { 4, 9, 5, 6 },
579 { 6, 7, 9, 8 },
580 { 6, 8, 9, 5 }
581 };
582 return { IT_Tetraedron4, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
583}
584
585/*---------------------------------------------------------------------------*/
586/*---------------------------------------------------------------------------*/
587
588// Attention lors de la génération des faces, il ne faut pas utiliser le cartesian (l'ordre du cartesian builder est différent)
589MeshSubdivider::Pattern PatternBuilder::
590hextotet()
591{
592 StorageRefine nodes = {}; // No new nodes
593 StorageRefine faces = {
594 // Doesn't work with the same faces as arcane though
595 { 0, 1, 3 }, // 0
596 { 0, 3, 4 }, // 1
597 { 0, 1, 4 }, // 2
598 { 1, 3, 4 }, // 3
599 { 1, 4, 5 }, // 4
600 { 1, 5, 6 }, // 5
601 { 1, 4, 6 }, // 6
602 { 4, 5, 6 }, // 7
603 { 1, 2, 3 }, // 8
604 { 1, 3, 6 }, // 9
605 { 1, 2, 6 }, // 10
606 { 2, 3, 6 }, // 11
607 { 3, 4, 6 }, // 12
608 { 3, 6, 7 }, // 13
609 { 3, 4, 7 }, // 14
610 { 4, 6, 7 }, // 15
611 };
612
613 StorageRefine child_faces = { // 6*2 = 12 faces
614 { 0, 8 },
615 { 1, 14 },
616 { 2, 4 },
617 { 15, 7 },
618 { 10, 5 },
619 { 11, 13 }
620 };
621 StorageRefine cells = {
622 { 0, 1, 3, 4 },
623 { 1, 4, 5, 6 },
624 { 1, 2, 3, 6 },
625 { 3, 4, 6, 7 },
626 { 1, 3, 4, 6 }
627 };
628 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
629}
630
631/*---------------------------------------------------------------------------*/
632/*---------------------------------------------------------------------------*/
633
634MeshSubdivider::Pattern PatternBuilder::
635tettohex()
636{
637 StorageRefine nodes = {
638 { 0, 1 }, // 4
639 { 1, 2 }, // 5
640 { 0, 2 }, // 6
641 { 0, 3 }, // 7
642 { 2, 3 }, // 8
643 { 1, 3 }, // 9
644 { 0, 1, 3 }, // 10
645 { 1, 2, 3 }, // 11
646 { 0, 1, 2 }, // 12
647 { 0, 2, 3 }, // 13
648 { 0, 1, 2, 3 }, // 14
649 };
650 StorageRefine faces = {
651 { 7, 10, 14, 13 }, // 0 x
652 { 0, 6, 13, 7 }, // 1
653 { 0, 4, 10, 7 }, // 2
654 { 0, 4, 12, 6 }, // 3
655 { 4, 10, 14, 12 }, // 4 x
656 { 6, 12, 14, 13 }, // 5 x
657 { 2, 5, 11, 8 }, // 6
658 { 2, 6, 13, 8 }, // 7
659 { 8, 11, 14, 13 }, // 8 x
660 { 5, 11, 14, 12 }, // 9 x
661 { 2, 5, 12, 6 }, // 10
662 { 3, 8, 11, 9 }, // 11
663 { 3, 7, 13, 8 }, // 12
664 { 3, 7, 10, 9 }, // 13
665 { 9, 10, 14, 11 }, // 14 x
666 { 1, 5, 11, 9 }, // 15
667 { 1, 4, 10, 9 }, // 16
668 { 1, 4, 12, 5 }, // 17
669 };
670 StorageRefine child_faces = {
671 /*{0,10,17},
672 {1,6,11},
673 {2,13,15},
674 {8,12,16}*/
675 { 3, 10, 17 },
676 { 1, 7, 12 },
677 { 2, 13, 16 },
678 { 6, 11, 15 },
679 };
680 StorageRefine cells = {
681 /*{0,4,12,6,7,10,14,13},
682 {10,4,12,14,9,1,5,11},
683 {13,14,12,6,8,11,5,2},
684 {7,10,14,13,3,9,11,8},*/
685 /*{13,14,10,7,6,12,4,0},
686 {2,5,11,8,6,12,14,13},
687 {8,11,9,3,13,14,10,7},
688 {11,5,1,9,14,12,4,10},*/
689 /*{6,12,4,0,13,14,10,7},
690 {6,12,14,13,2,5,11,8},
691 {13,14,10,7,8,11,9,3},
692 {14,12,4,10,11,5,1,9},*/
693 { 7, 10, 14, 13, 0, 4, 12, 6 },
694 { 8, 11, 5, 2, 13, 14, 12, 6 },
695 { 3, 9, 11, 8, 7, 10, 14, 13 },
696 { 9, 1, 5, 11, 10, 4, 12, 14 }
697 };
698 return { IT_Tetraedron4, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
699}
700
701/*---------------------------------------------------------------------------*/
702/*---------------------------------------------------------------------------*/
703
704MeshSubdivider::Pattern PatternBuilder::
705hextotet24()
706{
707 StorageRefine nodes({
708 { 0, 1, 2, 3 }, // 8
709 { 0, 3, 7, 4 }, // 9
710 { 0, 1, 4, 5 }, // 10
711 { 4, 5, 6, 7 }, // 11
712 { 1, 2, 5, 6 }, // 12
713 { 2, 3, 7, 6 }, // 13
714 { 0, 1, 2, 3, 4, 5, 6, 7 }, // 14
715 });
716 StorageRefine faces({
717 // OK
718 { 0, 3, 8 }, // 0
719 { 0, 8, 14 }, // 1
720 { 0, 3, 14 }, // 2
721 { 3, 8, 14 }, // 3
722 { 2, 3, 8 }, // 4
723 { 2, 3, 14 }, // 5
724 { 2, 8, 14 }, // 6
725 { 1, 2, 8 }, // 7
726 { 1, 2, 14 }, // 8
727 { 1, 8, 14 }, // 9
728 { 0, 1, 8 }, // 10
729 { 0, 1, 14 }, // 11
730 { 0, 4, 9 }, // 12
731 { 0, 9, 14 }, // 13
732 { 0, 4, 14 }, // 14
733 { 4, 9, 14 }, // 15
734 { 4, 7, 9 }, // 16
735 { 4, 7, 14 }, // 17
736 { 7, 9, 14 }, // 18
737 { 3, 7, 9 }, // 19
738 { 3, 7, 14 }, // 20
739 { 3, 9, 14 }, // 21
740 { 0, 3, 9 }, // 22
741 { 0, 4, 10 }, // 23
742 { 4, 10, 14 }, // 24
743 { 0, 10, 14 }, // 25
744 { 0, 1, 10 }, // 26
745 { 1, 10, 14 }, // 27
746 { 1, 5, 10 }, // 28
747 { 1, 5, 14 }, // 29
748 { 5, 10, 14 }, // 30
749 { 4, 5, 10 }, // 31
750 { 4, 5, 14 }, // 32
751 { 4, 7, 11 }, // 33
752 { 7, 11, 14 }, // 34
753 { 4, 11, 14 }, // 35
754 { 4, 5, 11 }, // 36
755 { 5, 11, 14 }, // 37
756 { 5, 6, 11 }, // 38
757 { 5, 6, 14 }, // 39
758 { 6, 11, 14 }, // 40
759 { 6, 7, 11 }, // 41
760 { 6, 7, 14 }, // 42
761 { 1, 5, 12 }, // 43
762 { 5, 12, 14 }, // 44
763 { 1, 12, 14 }, // 45
764 { 1, 2, 12 }, // 46
765 { 2, 12, 14 }, // 47
766 { 2, 6, 12 }, // 48
767 { 2, 6, 14 }, // 49
768 { 6, 12, 14 }, // 50
769 { 5, 6, 12 }, // 51
770 { 2, 6, 13 }, // 52
771 { 6, 13, 14 }, // 53
772 { 2, 13, 14 }, // 54
773 { 2, 3, 13 }, // 55
774 { 3, 13, 14 }, // 56
775 { 3, 7, 13 }, // 57
776 { 7, 13, 14 }, // 58
777 { 6, 7, 13 }, // 59
778 });
779 StorageRefine cells({
780 { 0, 3, 8, 14 },
781 { 3, 2, 8, 14 },
782 { 2, 1, 8, 14 },
783 { 1, 0, 8, 14 },
784
785 { 0, 4, 9, 14 },
786 { 4, 7, 9, 14 },
787 { 7, 3, 9, 14 },
788 { 3, 0, 9, 14 },
789
790 { 4, 0, 10, 14 },
791 { 0, 1, 10, 14 },
792 { 1, 5, 10, 14 },
793 { 5, 4, 10, 14 },
794
795 { 7, 4, 11, 14 },
796 { 4, 5, 11, 14 },
797 { 5, 6, 11, 14 },
798 { 6, 7, 11, 14 },
799
800 { 5, 1, 12, 14 },
801 { 1, 2, 12, 14 },
802 { 2, 6, 12, 14 },
803 { 6, 5, 12, 14 },
804
805 { 6, 2, 13, 14 },
806 { 2, 3, 13, 14 },
807 { 3, 7, 13, 14 },
808 { 7, 6, 13, 14 },
809 });
810
811 StorageRefine child_faces({
812 // need to redo the old numbering
813 { 0, 4, 7, 10 },
814 { 12, 16, 19, 22 },
815 { 23, 26, 28, 31 },
816
817 { 33, 36, 38, 41 },
818 { 43, 46, 48, 51 },
819 { 52, 55, 57, 59 },
820 });
821 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
822}
823
824/*---------------------------------------------------------------------------*/
825/*---------------------------------------------------------------------------*/
826
827/*---------------------------------------------------------------------------*/
828/*---------------------------------------------------------------------------*/
829
833class ArcaneBasicMeshSubdividerService
835{
836 public:
837
838 explicit ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi);
840 void subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh) override;
841
842 private:
843
844 void _init();
846 static UniqueArray<Int64> _computeNodeUid(UniqueArray<Int64> nodes_uid, const StorageRefine& node_pattern);
847 /*
848 void _computeNodeCoord();
849 void _computeNodeUid();
850 void _computeFaceUid();
851 void _computeCellUid();
852 void _processOwner();
853 void _setOwner();
854 void _processOwnerCell();
855 void _processOwnerFace();
856 void _processOwnerNode();
857 void _getRefinePattern(Int16 type);
858 void _execute();
859 */
860
861 /*
862 bool test_recompact = true;
863 Ref<VariableNodeInt64> var = Arcane::makeRef(
864 new Arcane::VariableNodeInt64(
865 Arcane::VariableBuildInfo(mesh, "arcane_node_local_id", mesh->nodeFamily()->name()))); ;
866
867 if( test_recompact ) {
868 // * If a node's previous local id == new local id, then its memory location has not changed
869 mesh->properties()->setBool("compact",true);
870 mesh->properties()->setBool("sort",true);
871 mesh->modifier()->endUpdate();
872 }
873 // We write the local IDs
874 ENUMERATE_NODE(inode, mesh->allNodes() ){
875 (*var.get())[*inode] = inode.localId();
876 }
877 // Write the node local IDs and see if it changes
878
879 VariableList vl;
880 vl.add(*var.get());
881 _writeEnsight(mesh,"SubdividerWithCompact",vl);
882 */
883
887 /* Method that allows retrieving faces generated by arcane.
888 * These faces must provide the local indices of the nodes of the initial cell.
889 * For this, we build a map from global to my_local_index. <Int64,Int64>
890 */
901 void _refineOnce([[maybe_unused]] IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
916 void _applyFamilyRenumbering(IItemFamily* family, VariableItemInt64& items_new_uid);
919};
920
921/*---------------------------------------------------------------------------*/
922/*---------------------------------------------------------------------------*/
923
924/*---------------------------------------------------------------------------*/
925/*---------------------------------------------------------------------------*/
926
928{
929 // C F E N
930 info() << "begin:_checkMeshUid";
931 ENUMERATE_CELL (icell, mesh->allCells()) {
932 const Cell& cell = *icell;
933 if (cell.uniqueId().asInt64() < 0) {
934 info() << "FATAL ERROR UID";
935 exit(0);
936 }
937 }
938 ENUMERATE_FACE (iface, mesh->allFaces()) {
939 const Face& face = *iface;
940 if (face.uniqueId().asInt64() < 0) {
941 info() << "FATAL ERROR UID";
942 exit(0);
943 }
944 }
945 ENUMERATE_EDGE (iedge, mesh->allEdges()) {
946 const Edge& edge = *iedge;
947 if (edge.uniqueId().asInt64() < 0) {
948 info() << "FATAL ERROR UID";
949 exit(0);
950 }
951 }
952 ENUMERATE_NODE (inode, mesh->allNodes()) {
953 const Node& node = *inode;
954 if (node.uniqueId().asInt64() < 0) {
955 info() << "FATAL ERROR UID";
956 exit(0);
957 }
958 }
959
960 /*
961 ENUMERATE_DOF(idof,mesh) {
962 dof_id = idof->uniqueId().asInt64();
963 info() << "= Dof id : " << dof_id;
964 if(dof_id < 0){
965 info() << "FATAL ERROR UID DOF";
966 exit(0);
967 }
968 }
969 */
970 info() << "Vars: " << mesh->variableMng()->variables().count();
971 VariableCollection vars = mesh->variableMng()->variables();
972 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
973 IVariable* var = *ivar;
974 if (var->isUsed())
975 continue;
976 if ((var->property() & IVariable::PNoDump) != 0)
977 continue;
978 // Does not process variables that are not on families.
979 if (var->itemFamilyName().null())
980 continue;
981 //var->setUsed(true);
982 info() << "LIST_VAR name=" << var->fullName();
983 }
984
985 info() << "end:_checkMeshUid";
986}
987
988/*---------------------------------------------------------------------------*/
989/*---------------------------------------------------------------------------*/
990
993{
994 if (mesh->dimension() == 2) {
996 }
997 else if (mesh->dimension() == 3) {
999 }
1000}
1001
1002/*---------------------------------------------------------------------------*/
1003/*---------------------------------------------------------------------------*/
1004
1007{
1008 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
1009
1010 mesh->faceFamily()->destroyGroups();
1012 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1013 _refineOnce(mesh, pattern_manager);
1014 std::string prefix("subdivider_pattern2D_");
1015 mesh->utilities()->writeToFile(prefix + "tritotri.vtk", "VtkLegacyMeshWriter");
1016
1017 mesh->faceFamily()->destroyGroups();
1019 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
1020 _refineOnce(mesh, pattern_manager);
1021 mesh->utilities()->writeToFile(prefix + "tritoquad.vtk", "VtkLegacyMeshWriter");
1022
1023 mesh->faceFamily()->destroyGroups();
1025 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
1026 _refineOnce(mesh, pattern_manager);
1027 mesh->utilities()->writeToFile(prefix + "quadtoquad.vtk", "VtkLegacyMeshWriter");
1028
1029 mesh->faceFamily()->destroyGroups();
1031 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
1032 _refineOnce(mesh, pattern_manager);
1033 mesh->utilities()->writeToFile(prefix + "quadtotri.vtk", "VtkLegacyMeshWriter");
1034}
1035
1036/*---------------------------------------------------------------------------*/
1037/*---------------------------------------------------------------------------*/
1038
1041{
1042 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
1043 std::string prefix("subdivider_pattern3D_");
1044 mesh->faceFamily()->destroyGroups();
1046 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
1047 _refineOnce(mesh, pattern_manager);
1048 mesh->utilities()->writeToFile(prefix + "tettotet.vtk", "VtkLegacyMeshWriter");
1049
1050 mesh->faceFamily()->destroyGroups();
1052 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
1053 _refineOnce(mesh, pattern_manager);
1054 mesh->utilities()->writeToFile(prefix + "tettohex.vtk", "VtkLegacyMeshWriter");
1055
1056 mesh->faceFamily()->destroyGroups();
1058 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
1059 _refineOnce(mesh, pattern_manager);
1060 mesh->utilities()->writeToFile(prefix + "hextohex.vtk", "VtkLegacyMeshWriter");
1061
1062 mesh->faceFamily()->destroyGroups();
1064 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
1065 _refineOnce(mesh, pattern_manager);
1066 mesh->utilities()->writeToFile(prefix + "hextotet24.vtk", "VtkLegacyMeshWriter");
1067
1068 mesh->faceFamily()->destroyGroups();
1070 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
1071 _refineOnce(mesh, pattern_manager);
1072 mesh->utilities()->writeToFile(prefix + "subdivider_hextotet.vtk", "VtkLegacyMeshWriter");
1073}
1074
1075/*---------------------------------------------------------------------------*/
1076/*---------------------------------------------------------------------------*/
1077
1078/*void ArcaneBasicMeshSubdividerService::_getArcaneOrder(IPrimaryMesh* mesh){
1079 Tritotri generate faces
1080
1081 _generateOneTri(mesh);
1082 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1083 _refineOnce(mesh,pattern_manager);
1084
1085
1086 Quadtoquad generate faces
1087
1088 _generateOneQuad(mesh);
1089 _refineWithArcaneFaces(mesh,PatternBuilder::quadtoquad());
1090 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
1091 _refineOnce(mesh,pattern_manager);
1092
1093
1094 Tettotet generate faces
1095
1096 _generateOneTetra(mesh);
1097 _refineWithArcaneFaces(mesh,PatternBuilder::tettotet());
1098
1099
1100
1101 _faceOrderArcane(mesh);
1102 mesh_utils::writeMeshInfos(mesh,"meshInSubdivide");
1103 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1104 _refineOnce(mesh,pattern_manager);
1105 mesh_utils::writeMeshInfos(mesh,"meshOutSubdivide");
1106
1107
1108 Tettohex generate faces input one tet
1109
1110 _generateOneTetra(mesh);
1111 _refineWithArcaneFaces(mesh,PatternBuilder::tettohex());
1112
1113 Hextohex generate faces input one hex
1114 _refineWithArcaneFaces(mesh,PatternBuilder::hextotet());
1115
1116 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
1117 _refineOnce(mesh,pattern_manager);
1118
1119}*/
1120
1121/*---------------------------------------------------------------------------*/
1122/*---------------------------------------------------------------------------*/
1123
1124static void _writeEnsight(IMesh* mesh, const String& dirname,
1125 const VariableList& variables)
1126{
1127
1128 Directory d = mesh->subDomain()->exportDirectory();
1130 auto post_processor = spp.createReference(
1131 "Ensight7PostProcessor"); // others but less good VtkHdfV2PostProcessor or Ensight7PostProcessor
1132 post_processor->setTimes(
1133 UniqueArray<Real>{ 0.0 }); // Just to fix the time step
1134
1135 ItemGroupList groups;
1136 groups.add(mesh->allCells());
1137 groups.add(mesh->allNodes());
1138 post_processor->setBaseDirectoryName(d.path() + "/" + dirname);
1139
1140 VariableNodeInt64 arcane_node_uid(VariableNodeInt64(Arcane::VariableBuildInfo(mesh, "arcane_node_uid", mesh->nodeFamily()->name())));
1141 VariableCellInt64 arcane_cell_uid(VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_cell_uid", mesh->cellFamily()->name())));
1142 VariableCellInt64 arcane_rank(VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_rank", mesh->cellFamily()->name())));
1143
1144 ENUMERATE_CELL (icell, mesh->allCells()) {
1145 arcane_cell_uid[*icell] = icell->uniqueId();
1146 }
1147
1148 ENUMERATE_CELL (icell, mesh->allCells()) {
1149 arcane_rank[*icell] = mesh->parallelMng()->commRank();
1150 }
1151
1152 ENUMERATE_NODE (inode, mesh->allNodes()) {
1153 arcane_node_uid[*inode] = inode->uniqueId();
1154 }
1155
1156 VariableList all_variables = variables.clone();
1157 all_variables.add(mesh->nodesCoordinates().variable());
1158 all_variables.add(arcane_rank);
1159 all_variables.add(arcane_cell_uid);
1160 all_variables.add(arcane_node_uid);
1161
1162 post_processor->setVariables(all_variables);
1163 post_processor->setGroups(groups);
1164 IVariableMng* vm = mesh->subDomain()->variableMng();
1165 vm->writePostProcessing(post_processor.get());
1166}
1167
1168/*---------------------------------------------------------------------------*/
1169/*---------------------------------------------------------------------------*/
1170
1172_refineOnce(IPrimaryMesh* mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager)
1173{
1174
1175 // Compute max_cell_uid
1176 Int64 max_cell_uid = NULL_ITEM_UNIQUE_ID;
1177 ENUMERATE_ (Cell, icell, mesh->ownCells()) {
1178 Cell cell = *icell;
1179 if (max_cell_uid < cell.uniqueId())
1180 max_cell_uid = cell.uniqueId();
1181 }
1182 Int64 global_max_cell_uid = mesh->parallelMng()->reduce(Parallel::ReduceMax, max_cell_uid);
1183 global_max_cell_uid++; // on prend le suivant
1184
1185 info() << "#subdivide mesh";
1186 // We check that we know how to refine the cells (maybe not at the same time)
1187 ENUMERATE_CELL (icell, mesh->ownCells()) {
1188 const Cell& cell = *icell;
1189 // List of items where patterns are implemented for now
1190 if (cell.itemTypeId() != IT_Hexaedron8 && cell.itemTypeId() != IT_Tetraedron4 && cell.itemTypeId() != IT_Quad4 && cell.itemTypeId() != IT_Triangle3) {
1191 ARCANE_FATAL("Not implemented item type '{0}'", cell.itemTypeId());
1192 return;
1193 }
1194 }
1195
1196 info() << "subdivide mesh with " << options()->nbSubdivision() << " nb_refine";
1197
1198 Int32 my_rank = mesh->parallelMng()->commRank();
1199 IMeshModifier* mesh_modifier = mesh->modifier();
1200 IGhostLayerMng* gm = mesh->ghostLayerMng();
1201 debug() << "PART 3D nb ghostlayer" << gm->nbGhostLayer();
1202 // mesh->utilities()->writeToFile(String::format("3D_last_input{0}.vtk",my_rank), "VtkLegacyMeshWriter");
1203 Integer nb_ghost_layer_init = gm->nbGhostLayer(); // We keep the initial number of ghost layers to restore it at the end
1204 Int32 version = gm->builderVersion();
1205 if (version < 3)
1206 gm->setBuilderVersion(3);
1207
1208 gm->setNbGhostLayer(0);
1209 mesh_modifier->setDynamic(true);
1210 mesh_modifier->updateGhostLayers();
1211
1212 // Only for final assert checks
1213 Integer nb_cell_init = mesh->nbCell();
1214 Integer nb_face_init = mesh->nbFace();
1215 //Integer nb_edge_init = mesh->nbEdge();
1216 //Integer nb_node_init = mesh->nbNode();
1217
1218 // Count edges
1219 // We are looking for a way to count edges to perform an easy test on the number of inserted nodes.
1220 // ARCANE_ASSERT((nb_edge_init+ nb_cell_init + nb_face_init)== nb_node_added,("Wrong number of inserted nodes"));
1221 //debug() << "#INITIAL COUNT " << nb_node_init << " " << mesh->allEdges().size() << " " << edg.size() << " " << nb_face_init << " " << nb_cell_init ;
1222
1223 // VARIABLES
1224 // Items to add with connectivities for E F and C
1225 UniqueArray<Int64> nodes_to_add;
1226 UniqueArray<Int64> edges_to_add;
1227 UniqueArray<Int64> faces_to_add;
1228 UniqueArray<Int64> cells_to_add;
1229
1230 Integer nb_cell_to_add = 0;
1231 Integer nb_face_to_add = 0;
1232
1233 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1234 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1235 debug() << "ARRAY SIZE " << nodes_coords.arraySize();
1236 // Nodes on entities
1237 std::set<Int64> new_nodes; // Using a map ensures that a node is added only once with a uniqueId()
1238 std::set<Int64> new_faces; // ^--- Same for faces
1239 // Maps for owner management
1240 std::unordered_map<Int64, Int32> node_uid_to_owner;
1241 std::unordered_map<Int64, Int32> edge_uid_to_owner; // not used
1242 std::unordered_map<Int64, Int32> face_uid_to_owner;
1243 std::unordered_map<Int64, Int32> child_cell_owner; // not used
1244 std::unordered_map<Int32, Int32> old_face_lid_to_owner; // not used
1245
1246 UniqueArray<Int32> cells_to_detach; // Cells to detach
1247 UniqueArray<Int64> faces_uids; // Contains only the uids, not the connectivities
1248 UniqueArray<Int64> edges_uids; // Same
1249
1250 // Calculate number of nodes to insert
1251 // const Integer nb_node_to_add_total = mesh->nbCell()+mesh->nbFace()+mesh->nbEdge(); // Note pattern dependent
1252 //nodes_to_add.reserve(nb_node_to_add_total);
1253 //nodes_to_add_coords.reserve(nb_node_to_add_total);
1254
1255 Integer ind_new_cell = 0;
1256
1257 ARCANE_ASSERT((mesh->nbEdge() == 0), ("Wrong number of edge"));
1258
1259 UniqueArray<Int64> parent_faces(mesh->ownFaces().size());
1260 UniqueArray<Int64> parent_cells(mesh->ownCells().size());
1261 UniqueArray<Int64> child_cells; // All new cells
1262 UniqueArray<Int64> child_faces; // Only at the element boundary (no internal faces)
1263
1264 // Allows retrieving child entities from a parent cell
1265 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_cell; // From a uid, we retrieve the first child (pair<index,number of child>)
1266 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces; // From a uid, we retrieve the first child (pair<index,number of child>)
1267 // ^--- only for "external" faces
1268 Int64 childs_count = 0; // For each new cell, we shift by the number of children (+4 if quad, +3 or +4 for tri depending on the pattern)
1269
1270 // Groups
1271 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces_groups; // Map parent face -> external child face in face_external_uid array
1272 UniqueArray<Int64> face_external_uid; // All external faces of the proc uid
1273
1274 // Debug node
1275 /*
1276 ENUMERATE_NODE(inode,mesh->ownNodes())
1277 {
1278 const Node & node = *inode;
1279 nodes_to_add_coords[node.uniqueId().asInt64()] = nodes_coords[node];
1280 }
1281 */
1282 // Processing for a cell
1283 ENUMERATE_CELL (icell, mesh->ownCells()) {
1284 debug() << "Refining element";
1285 // FOR AN ELEMENT:
1286 // Detach parent cells
1287 // Generation of new nodes (uid and coordinates)
1288 // On Edges
1289 // On Faces
1290 // On Cell
1291 // New nodes, coordinates
1292
1293 // Generation of Faces (uid and components (Nodes)) using new nodes
1294 // Internal
1295 // External
1296
1297 // Generation of Cells (uid and components (Nodes))
1298 // Group management
1299 // END OF ONE ELEMENT
1300
1301 // Detachment of cells
1302 // Addition of child nodes
1303 // Addition of child faces
1304 // Addition of child cells (and owner assignment)
1305
1306 // Addition of a ghost layer
1307 // Calculation of node owners
1308 // Calculation of face owners
1309 // Removal of the ghost layer
1310 // ?? Calculation of F C groups
1311
1312 // Assignment of nodes to owner
1313 // Assignment of faces to owner
1314 // Addition of initial cell layer count
1315
1316 const Cell& cell = *icell;
1317
1318 MeshSubdivider::Pattern& p = pattern_manager[cell.type()]; // Pattern Manager
1319 StorageRefine& node_pattern = p.nodes;
1320
1321 UniqueArray<Int64> face_in_cell; // All faces of the cell uid
1322 StorageRefine& child_faces = p.child_faces;
1323
1324 cells_to_detach.add(cell.localId());
1325 // Generation of nodes
1326 UniqueArray<Int64> node_in_cell;
1327 node_in_cell.resize(node_pattern.size() + cell.nbNode()); // pattern dependent
1328 UniqueArray<Real3> coords_in_cell;
1329 debug() << "Initial nodes";
1330 // Initial nodes
1331 for (Int32 i = 0; i < cell.nbNode(); i++) {
1332 node_in_cell[i] = cell.node(static_cast<Int32>(i)).uniqueId().asInt64();
1333 //debug() << i << " " << node_in_cell[i] << " size " << node_in_cell.size() ;
1334 }
1335
1336 Integer index_27 = cell.nbNode();
1337
1338 // - Generation of node uids
1339 debug() << "Generation of node uids";
1340
1341 for (Integer i = 0; i < node_pattern.size(); i++) {
1342 // uid
1344 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1345 tmp.add(node_in_cell[node_pattern[i][j]]);
1346 }
1347 std::sort(tmp.begin(), tmp.end());
1349 node_in_cell[index_27 + i] = uid;
1350
1351 if (new_nodes.find(node_in_cell[i + index_27]) == new_nodes.end()) {
1352 // Coords
1353 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1354 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1355 //info() << "loop" << cell.node(static_cast<Integer>(node_pattern[i][j])) << " " << nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1356 middle_coord += nodes_coords[cell.node(static_cast<Integer>(node_pattern[i][j]))];
1357 }
1358 if (node_pattern[i].size() == 0) {
1359 ARCANE_FATAL("Wrong size for refined pattern with code IT:'{0}'", p.cell_type);
1360 }
1361 middle_coord /= node_pattern[i].size();
1362 if (middle_coord == Real3(0.0, 0.0, 0.0)) {
1363 ARCANE_FATAL("Bad coordinate for new node, the node '{0}' probably has a default coordinate (0.0,0.0,0.0).", uid);
1364 }
1365 new_nodes.insert(node_in_cell[i + index_27]);
1366 // Insertion into map uid -> coord
1367 nodes_to_add_coords[node_in_cell[i + index_27]] = middle_coord;
1368 // Insertion into Uarray uid
1369 nodes_to_add.add(uid);
1370 //info() << node_pattern[i];
1371 //debug() << i << " " << uid << " sizenic " << tmp << middle_coord;
1372 }
1373 }
1374 // Should we add the old nodes? Normally no
1375 // #TAG
1376 /*
1377 for(Integer i = 0 ; i < cell.nbNode() ; i++ ) {
1378 nodes_to_add.add(cell.node(i).uniqueId().asInt64());
1379 new_nodes.insert(cell.node(i).uniqueId().asInt64());
1380 }
1381 */
1382
1383 debug() << "nodetoadd size " << nodes_to_add.size() << " " << nodes_to_add_coords.size();
1384 debug() << "Node coord & nb node to add" << nodes_to_add_coords.size() << " " << nodes_to_add.size();
1385 //ARCANE_ASSERT((nodes_to_add_coords.size() == static_cast<size_t>(nodes_to_add.size())),("Has to be same"));
1386 //ARCANE_ASSERT((nodes_to_add_coords.size() == new_nodes.size()),("Has to be same"));
1387
1388 // Generation of Faces
1389 StorageRefine& face_refine = p.faces;
1390 debug() << "face_refine.size() " << face_refine.size();
1391 //ARCANE_ASSERT((face_refine.size() == 36), ("WRONG NUMBER OF CELL ADDED")); // One cube assert
1392 debug() << "Refine face";
1393 for (Integer i = 0; i < face_refine.size(); i++) {
1394 // Generation of the face hash
1396 //tmp.resize(face_refine[i].size());
1397 for (Integer j = 0; j < face_refine[i].size(); j++) {
1398 tmp.add(node_in_cell[face_refine[i][j]]);
1399 }
1400 std::sort(tmp.begin(), tmp.end());
1401 //ARCANE_ASSERT(( tmp.size() == 4 ),("Wrong size of UniqueArray")); // one cube assert
1403 face_in_cell.add(uid); // For groups
1404 // Check if it has already been created
1405 if (new_faces.find(uid) == new_faces.end()) {
1406 // Addition
1407 faces_to_add.add(p.face_type);
1408 faces_to_add.add(uid);
1409 //debug() << "Face " << uid << " " << tmp ;
1410 for (Integer j = 0; j < face_refine[i].size(); j++) {
1411 //debug() << node_in_cell[face_refine[i][j]] ;
1412 faces_to_add.add(node_in_cell[face_refine[i][j]]);
1413 }
1414 // Add to uids faces array
1415 faces_uids.add(uid);
1416 nb_face_to_add++;
1417 new_faces.insert(uid);
1418 }
1419 }
1420
1421 // New Group Management
1422 // For each face
1423 // Generate hash
1424 // associate hash uid face
1425 // Iteration over parent faces
1426 debug() << "Group face management";
1427 for (Integer i = 0; i < child_faces.size(); i++) {
1428 parents_to_childs_faces_groups[cell.face(i).uniqueId()] = std::pair<Int64, Int64>(face_external_uid.size(), child_faces[i].size());
1429 for (Integer j = 0; j < child_faces[i].size(); j++) {
1430 face_external_uid.add(face_in_cell[child_faces[i][j]]); // start this is the index of face_in_cell // in fact we make an array for each element too // face_in_cell (otherwise the indices will be wrong, so we add the faces multiple times)
1431 }
1432 }
1433
1434 // Generation of cells
1435 StorageRefine& cells_refine = p.cells;
1436 // Generation of child cells
1437 debug() << "Generation of child cells";
1438 // The uid is generated from the hash of each node sorted in ascending order
1439 for (Integer i = 0; i < cells_refine.size(); i++) {
1440 // The new uid is generated with the hash of the new nodes that compose the new cell
1442 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1443 tmp.add(node_in_cell[cells_refine[i][j]]);
1444 }
1445 std::sort(tmp.begin(), tmp.end());
1446 //Int64 cell_uid = Arcane::MeshUtils::generateHashUniqueId(tmp.constView()); //max_cell_uid+ind_new_cell;
1447 //info() << "global_max_cell_uid" << global_max_cell_uid ;
1448 Int64 cell_uid = cell.uniqueId().asInt64() * p.cells.size() + i + global_max_cell_uid;
1449 //info() << "#old new uid" << cell.uniqueId().asInt64() << " " << cell_uid ;
1450 ARCANE_ASSERT((cell_uid >= 0), ("Cell uid generation don't work properly"));
1451 cells_to_add.add(p.cell_type); // Type
1452 cells_to_add.add(cell_uid);
1453 for (Integer j = 0; j < cells_refine[i].size(); j++) {
1454 cells_to_add.add(node_in_cell[cells_refine[i][j]]);
1455 }
1456 child_cell_owner[cell_uid] = cell.owner();
1457 parent_cells.add(cell.uniqueId());
1458 child_cells.add(cell_uid); // groups duplicate information with cells_to_add
1459 nb_cell_to_add++;
1460 ind_new_cell++;
1461 }
1462 // groups
1463 parents_to_childs_cell[cell.uniqueId()] = std::pair<Int64, Int64>(childs_count, cells_refine.size());
1464 childs_count += cells_refine.size(); // to be modified according to the number of children associated with the refinement pattern!
1465 }
1466 // Adding new Nodes
1467 Integer nb_node_added = nodes_to_add.size();
1468 UniqueArray<Int32> nodes_lid(nb_node_added);
1469
1470 // info() << "JustBeforeAdd " << nodes_to_add;
1471 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.view());
1472
1473 // Edges: No edge generation
1474
1475 debug() << "Faces_uids " << faces_uids << " faces_to_add " << faces_to_add.size() << " faces_to_add/6 " << faces_to_add.size() / 6;
1476
1477 //ARCANE_ASSERT((nodes_to_add.size() != 0),("End"));
1478 //ARCANE_ASSERT((nb_face_to_add == 68),("WRONG NUMBER OF FACES")); // two hex
1479 // Adding child Faces
1480 UniqueArray<Int32> face_lid(faces_uids.size());
1481 debug() << "Before addOneFace " << nb_face_to_add;
1482
1483 //Setup faces
1484
1485 mesh->modifier()->addFaces(nb_face_to_add, faces_to_add.constView(), face_lid.view());
1486 debug() << "addOneFace " << nb_face_to_add;
1487 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, faces_uids, true);
1488 debug() << "NB_FACE_ADDED AFTER " << face_lid.size() << " " << new_faces.size();
1489
1490 //ARCANE_ASSERT((nb_face_to_add == (faces_to_add.size()/6)),("non consistant number of faces")); // For hex
1491
1492 // Adding child cells
1493 mesh->modifier()->detachCells(cells_to_detach);
1494
1495 UniqueArray<Int32> cells_lid(nb_cell_to_add);
1496 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.constView(), cells_lid);
1497 info() << "After addCells";
1498 // mesh->modifier()->addCells()
1499 // For all item groups
1500 UniqueArray<Int32> child_cells_lid(child_cells.size());
1501 mesh->cellFamily()->itemsUniqueIdToLocalId(child_cells_lid, child_cells, true);
1502
1503 // Item group management here (different materials for example)
1504 // - We seek to add the children in the same groups as the parents for:
1505 // - Faces
1506 // - Cells
1507 // - No automatic deduction for:
1508 // - Nodes
1509 // - Edges
1510 // Algo
1511 // For each group
1512 // For each cell in this group
1513 // add child cells of this group
1514
1515 // Process groups for faces
1516 //
1517 // In fact, we can only process external faces. Should/can we deduce the groups of internal faces?
1518 // In the case of the microhydro test, we can because we only have external faces to the elements: XYZ min max
1519 // At this moment, we have not made a link face_parent_external -> face_child_external
1520 // To do this, we will iterate through the parent internal faces, sort the IDs, and sort the elements
1521
1522 // Group problem.
1523 // faces_externals array
1524 // For each parent face
1525 // - Add the uid of each new face to a new variable faces_externals
1526 // - save uid and index in map
1527
1528 IItemFamily* face_family = mesh->faceFamily();
1529 IItemFamily* cell_family = mesh->cellFamily();
1530
1531 UniqueArray<Int32> face_external_lid(face_external_uid.size());
1532 mesh->faceFamily()->itemsUniqueIdToLocalId(face_external_lid, face_external_uid);
1533 // Process groups for faces
1534 info() << "#mygroupname face " << face_family->groups().count();
1535 for (ItemGroupCollection::Enumerator igroup(face_family->groups()); ++igroup;) {
1536 ItemGroup group = *igroup;
1537
1538 info() << "#mygroupname face " << group.fullName();
1539 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1540 info() << "#groups: OWN";
1541 continue;
1542 }
1543 if (group.isAllItems()) { // need this for seq and //
1544 info() << "#groups: ALLITEMS";
1545 continue;
1546 }
1547 info() << "#groups: Added ";
1548 UniqueArray<Int32> to_add_to_group;
1549
1550 ENUMERATE_ (Item, iitem, group) { // For each cell in the group, we add its 8 children (or n)
1551 Int64 step = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].first;
1552 Int64 n_childs = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].second;
1553 auto subview = face_external_lid.subView(step, static_cast<Integer>(n_childs));
1554 //ARCANE_ASSERT((subview.size() == 4 ), ("SUBVIEW"));
1555 to_add_to_group.addRange(subview);
1556 }
1557 group.addItems(to_add_to_group, true);
1558 }
1559
1560 // Process groups for cells
1561 for (ItemGroupCollection::Enumerator igroup(cell_family->groups()); ++igroup;) {
1562 CellGroup group = *igroup;
1563 info() << "#mygroupname" << group.fullName() << "nb item" << cell_family->nbItem();
1564 if (group.isOwn() && mesh->parallelMng()->isParallel()) {
1565 info() << "#groups: OWN";
1566 continue;
1567 }
1568 if (group.isAllItems()) { // need this for seq and //
1569 info() << "#groups: ALLITEMS";
1570 continue;
1571 }
1572
1573 info() << "#groups: Added ";
1574 UniqueArray<Int32> to_add_to_group;
1575
1576 ENUMERATE_ (Item, iitem, group) { // For each cell in the group, we add its 8 children (or n)
1577 Int64 step = parents_to_childs_cell[iitem->uniqueId().asInt64()].first;
1578 Int64 n_childs = parents_to_childs_cell[iitem->uniqueId().asInt64()].second;
1579 auto subview = child_cells_lid.subView(step, static_cast<Integer>(n_childs));
1580 to_add_to_group.addRange(subview);
1581 }
1582 info() << "#Added " << to_add_to_group.size() << " to group " << group.fullName();
1583 group.addItems(to_add_to_group, true);
1584 }
1585 // end item group management
1586 mesh->modifier()->removeDetachedCells(cells_to_detach.constView());
1587 //mesh->modifier()->removeCells(cells_to_detach.constView());
1588 mesh->modifier()->endUpdate();
1589
1590 // DEBUG
1591 debug() << "Debug faces " << faces_to_add;
1592 /*for(Integer i = 0 ; i < faces_to_add.size() ; i++){
1593 debug() << new_faces[i] ;
1594 }*/
1595 // END DEBUG
1596
1597 // Management and assignment of owner for each cell
1598 // The owner is simply the subdomain that generated the new cells
1599 ENUMERATE_ (Cell, icell, mesh->allCells()) {
1600 Cell cell = *icell;
1601 cell.mutableItemBase().setOwner(my_rank, my_rank);
1602 }
1603 mesh->cellFamily()->notifyItemsOwnerChanged();
1604
1605 // ARCANE_ASSERT((nodes_lid.size() != 0),("End"));
1606 ARCANE_ASSERT((nodes_lid.size() == nodes_to_add.size()), ("End"));
1607 // Assigning coordinates to nodes
1608
1609 UniqueArray<Int32> to_add_to_nodes(nodes_to_add.size()); // Bis
1610 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_to_add, true);
1611
1612 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) { // recalculate nodes_lid
1613 Node node = *inode;
1614 debug() << node.uniqueId().asInt64();
1615 //ARCANE_ASSERT((new_nodes.find(node.uniqueId().asInt64()) != new_nodes.end()),("Not found in set !"))
1616 //ARCANE_ASSERT((nodes_to_add_coords.find(node.uniqueId().asInt64()) != nodes_to_add_coords.end()),("Not found in map coord!"))
1617 // if it is not in the map, it already exists!
1618
1619 nodes_coords[node] = nodes_to_add_coords[node.uniqueId().asInt64()];
1620 debug() << "InSBD" << node.uniqueId().asInt64() << " " << nodes_to_add_coords[node.uniqueId().asInt64()];
1621 }
1622
1623 //info() << "#NODECOORDS" << nodes_coords.asArray() ;
1624 // Adding a ghost layer
1625 Arcane::IGhostLayerMng* gm2 = mesh->ghostLayerMng();
1626 gm2->setNbGhostLayer(1);
1627 mesh->updateGhostLayers(true);
1628
1629 // Management of node owners
1630 // The owner is the cell incident to the node with the smallest uniqueID()
1631 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1632 Node node = *inode;
1633 auto it = std::min_element(node.cells().begin(), node.cells().end());
1634 Cell cell = node.cell(static_cast<Int32>(std::distance(node.cells().begin(), it)));
1635 node_uid_to_owner[node.uniqueId().asInt64()] = cell.owner();
1636 }
1637
1638 // Management of face owners
1639 // The owner is the cell incident to the face with the smallest uniqueID()
1640 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1641 Face face = *iface;
1642 auto it = std::min_element(face.cells().begin(), face.cells().end());
1643 Cell cell = face.cell(static_cast<Int32>(std::distance(face.cells().begin(), it)));
1644 face_uid_to_owner[face.uniqueId().asInt64()] = cell.owner();
1645 }
1646
1647 // Using ghost layers is costly (construction destruction)
1648 // - Optim: for shared nodes, have an all-to-all (gather) variable that allows retrieving the owner rank for each shared item
1649 // - Possible deduction of child face owners from the parent face directly
1650 // - Child cells have the same owner as the parent cell
1651 // Deleting the ghost layer
1652 gm2->setNbGhostLayer(0);
1653 mesh->updateGhostLayers(true);
1654
1655 // DEBUG
1656 /*debug() << "#Faces mesh";
1657 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1658 Face face = *iface;
1659 debug() << face.uniqueId().asInt64();
1660 }*/
1661
1662 // Some checks on the number of inserted entities
1663 // ARCANE_ASSERT((mesh->nbCell() == nb_cell_init*8 ),("Wrong number of cell added"));
1664 debug() << "nbface " << mesh->nbFace() << " " << nb_face_to_add << " expected " << nb_face_init * 4 + 12 * nb_cell_init;
1665 // ARCANE_ASSERT((mesh->nbFace() <= nb_face_init*4 + 12 * nb_cell_init ),("Wrong number of face added"));
1666 // To add to check the number of nodes if edges are created
1667 // ARCANE_ASSERT((mesh->nbNode() == nb_edge_init + nb_face_init + nb_cell_init ),("Wrong number of node added"))
1668
1669 // Assignment of the new owner for each node
1670 ENUMERATE_ (Node, inode, mesh->allNodes()) {
1671 Node node = *inode;
1672 node.mutableItemBase().setOwner(node_uid_to_owner[node.uniqueId().asInt64()], my_rank);
1673 }
1674 mesh->nodeFamily()->notifyItemsOwnerChanged();
1675
1676 // Assignment of the new owners for each face
1677 ENUMERATE_ (Face, iface, mesh->allFaces()) {
1678 Face face = *iface;
1679 face.mutableItemBase().setOwner(face_uid_to_owner[face.uniqueId().asInt64()], my_rank);
1680 }
1681 mesh->faceFamily()->notifyItemsOwnerChanged();
1682
1683 // We set the ghost layer again for a future simulation
1684 gm2->setNbGhostLayer(nb_ghost_layer_init);
1685 mesh->updateGhostLayers(true);
1686
1687 // Writing in VTK format
1688 /*
1689 mesh->utilities()->writeToFile("3Drefined" + std::to_string(my_rank) + ".vtk", "VtkLegacyMeshWriter");
1690 info() << "Writing VTK 3Drefine";
1691 debug() << "END 3D fun";
1692 debug() << "NB CELL " << mesh->nbCell() << " " << nb_cell_init * 8;
1693 debug() << mesh->nbNode() << " " << nb_node_init << " " << nb_edge_init << " " << nb_face_init << " " << nb_cell_init;
1694 debug() << mesh->nbFace() << "nb_face_init " << nb_face_init << " " << nb_face_init << " " << nb_cell_init;
1695 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;
1696 info() << "#NODES_CHECK #all" << mesh->allNodes().size() << " #own " << mesh->ownNodes().size();
1697 */
1698}
1699
1700/*---------------------------------------------------------------------------*/
1701/*---------------------------------------------------------------------------*/
1702
1705{
1706 IMeshModifier* modifier = mesh->modifier();
1707 Int64UniqueArray cells_infos;
1708 Int64UniqueArray faces_infos;
1709 Int64UniqueArray nodes_uid;
1710 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1711 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1712
1713 // get max uid for cells
1714 Int64 max_offset = 0;
1715 ENUMERATE_CELL (icell, mesh->allCells()) {
1716 Cell cell = *icell;
1717 info() << cell.uniqueId().asInt64() << " ";
1718 if (max_offset < cell.uniqueId())
1719 max_offset = cell.uniqueId();
1720 }
1721 //ARCANE_ASSERT((max_offset!=0),("BAD OFFSET"));
1722
1723 info() << "#_refineWithArcaneFaces";
1724 ENUMERATE_CELL (icell, mesh->allCells()) {
1725 const Cell& cell = *icell;
1726 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1727 << icell->type() << ", nb nodes=" << icell->nbNode();
1728
1729 for (Face face : cell.faces()) {
1730 info() << "Face " << face.uniqueId() << " nodes ";
1731 for (Node node : face.nodes()) {
1732 info() << node.uniqueId() << " ";
1733 }
1734 }
1735 }
1736 //mesh->utilities()->writeToFile("subdivider_one_tetra_output.vtk", "VtkLegacyMeshWriter");
1737 ARCANE_ASSERT((!p.cells.empty()), ("Pattern not init"));
1738 Integer cellcount = 0;
1739 UniqueArray<Int32> cells_to_detach; // Cells to detach
1740
1741 Int64 face_count = 0;
1742
1743 std::map<Int64, Int32> node_uid_to_cell_local_id; // Gives the local id relative to a cell
1744
1745 ENUMERATE_CELL (icell, mesh->allCells()) {
1746 UniqueArray<Int64> node_in_cell;
1747 const Cell& cell = *icell;
1748 info() << "Detach";
1749 cells_to_detach.add(cell.localId());
1750 info() << "Get Pattern";
1751 StorageRefine& node_pattern = p.nodes;
1752 StorageRefine& cells = p.cells;
1753
1754 info() << "Get Nodes";
1755 for (Integer i = 0; i < cell.nbNode(); i++) {
1756 node_in_cell.add(cell.node(i).uniqueId().asInt64());
1757 info() << "Node " << cell.node(i).uniqueId().asInt64() << " " << nodes_coords[cell.node(i)];
1758 }
1759 info() << "Node pattern " << node_pattern.size() << "nic " << node_in_cell;
1760 _computeNodeUid(node_in_cell, node_pattern);
1761 // New nodes and coords
1762 for (Integer i = 0; i < node_pattern.size(); i++) {
1763 info() << "test " << i;
1764 UniqueArray<Int64> tmp = node_pattern[i];
1765
1766 // uid == node_in_cell[uid]
1767 Int64 uid = cell.nbNode() + i;
1768 node_in_cell.add(uid); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
1769 nodes_uid.add(uid);
1770 // Coords
1771 Arcane::Real3 middle_coord(0.0, 0.0, 0.0);
1772
1773 for (Integer j = 0; j < node_pattern[i].size(); j++) {
1774 middle_coord += nodes_coords[cell.node(static_cast<Int32>(node_pattern[i][j]))];
1775 info() << node_pattern[i][j] << cell.node(static_cast<Int32>(node_pattern[i][j]));
1776 }
1777 middle_coord /= node_pattern[i].size();
1778 nodes_to_add_coords[uid] = middle_coord;
1779 info() << "NodeX " << uid << " " << " coord " << nodes_to_add_coords[uid] << " " << middle_coord;
1780 node_uid_to_cell_local_id[uid] = cell.nbNode() + i;
1781 }
1782
1783 info() << "#node in cell " << node_in_cell;
1784 // Generating new faces and cells
1785 // New faces
1786 /*for( Integer i = 0 ; i < faces.size() ; i++ ){
1787 // Header
1788 faces_infos.add(p.face_pattern); // type // Dependent pattern //#HERE
1789 faces_infos.add(i); // face uid
1790 for( Integer j = 0 ; j < faces[i].size() ; j++ ) {
1791 faces_infos.add(node_in_cell[faces[i][j]]); // node 0
1792 }
1793 // Face_info
1794 info() << "face " << face_count << " " << node_in_cell[faces[i][0]] << " " << node_in_cell[faces[i][1]] << " " << node_in_cell[faces[i][2]];
1795 face_count++;
1796 }*/
1797 // New cells
1798 for (Integer i = 0; i < cells.size(); i++) {
1799 // Header
1800 max_offset++;
1801 cells_infos.add(p.cell_type); // type // Dependent pattern
1802 cells_infos.add(max_offset); // cell uid
1803 // Cell_info
1804 info() << "Cell " << i;
1805 for (Integer j = 0; j < cells[i].size(); j++) {
1806 info() << "test2bis " << node_in_cell[cells[i][j]] << " " << node_in_cell.size() << " " << node_pattern.size();
1807 cells_infos.add(node_in_cell[cells[i][j]]);
1808 }
1809 cellcount++;
1810 }
1811 info() << "test2bisbis ";
1812 for (Integer i = 0; i < node_in_cell.size(); i++) {
1813 info() << "node_in_cell[ " << i << " ] " << node_in_cell[i];
1814 }
1815 info() << "test3 ";
1816 }
1817 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1818 // Debug here
1819 info() << "test3 " << nodes_uid.size() << " " << nodes_lid.size();
1820 nodes_lid.clear();
1821 nodes_lid.reserve(nodes_uid.size());
1822
1823 modifier->addNodes(nodes_uid, nodes_lid);
1824 info() << "After nodes";
1825 UniqueArray<Int32> faces_lid(face_count);
1826 //modifier->addFaces(face_count, faces_infos, faces_lid);
1827 info() << "After faces";
1828 UniqueArray<Int32> cells_lid(cellcount);
1829
1830 modifier->addCells(cellcount, cells_infos, cells_lid);
1831 info() << "cellsize " << cells_infos.size() << " " << cellcount;
1832 modifier->removeCells(cells_to_detach.constView());
1833 modifier->endUpdate();
1834 // Assigning coordinates to new nodes
1835 VariableNodeReal3 coords_bis = mesh->nodesCoordinates();
1836
1837 info() << nodes_lid.size();
1838 UniqueArray<Int32> to_add_to_nodes(nodes_uid.size()); // Bis
1839 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_uid, true);
1840
1841 info() << "#NODESHERE";
1842 ENUMERATE_ (Node, inode, mesh->nodeFamily()->view(to_add_to_nodes)) {
1843 Node node = *inode;
1844 coords_bis[node] = nodes_to_add_coords[node.uniqueId()];
1845 info() << "node " << node.uniqueId() << " coord " << nodes_to_add_coords[node.uniqueId()];
1846 info() << node.uniqueId() << " " << nodes_coords[node];
1847 }
1848
1849 //mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output1.vtk", "VtkLegacyMeshWriter");
1850
1851 info() << "#coords" << coords_bis.asArray();
1852 info() << "#My mesh ";
1853 UniqueArray<Int64> stuff;
1854 // Mesh display
1855 ENUMERATE_CELL (icell, mesh->allCells()) {
1856 const Cell& cell = *icell;
1857 info() << "Cell " << cell.uniqueId() << " " << cell.nodeIds();
1858 for (Face face : cell.faces()) {
1859 for (Node node : face.nodes()) {
1860 stuff.add(node.uniqueId());
1861 }
1862 info() << "Faces " << face.uniqueId() << " node " << stuff;
1863 }
1864 stuff.clear();
1865 }
1866 info() << "#Arcane face numbering:";
1867 std::cout << "{";
1868 ENUMERATE_FACE (iface, mesh->allFaces()) {
1869 const Face& face = *iface;
1870 UniqueArray<Int64> stuff;
1871 std::cout << "{" << face.nodes()[0].uniqueId().asInt64();
1872
1873 for (Integer i = 1; i < face.nodes().size(); i++) {
1874 std::cout << "," << face.nodes()[i].uniqueId().asInt64();
1875 }
1876 //stuff.add(node_uid_to_cell_local_id[node.uniqueId().asInt64()]);
1877 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1878 //std::cout << node_uid_to_cell_local_id[node.uniqueId().asInt64()] ;
1879
1880 //info() << "Faces " << face.uniqueId() << " node " << stuff ;
1881 std::cout << "}," << std::endl;
1882 }
1883 std::cout << "}";
1884 Arcane::VariableScalarInteger m_temperature(Arcane::VariableBuildInfo(mesh, "ArcaneCheckpointNextIteration"));
1885
1886 VariableCellInt64* arcane_cell_uid = nullptr;
1887 VariableFaceInt64* arcane_face_uid = nullptr;
1888 VariableNodeInt64* arcane_node_uid = nullptr;
1889 arcane_cell_uid = new VariableCellInt64(Arcane::VariableBuildInfo(mesh, "arcane_cell_uid", mesh->cellFamily()->name()));
1890 arcane_face_uid = new VariableFaceInt64(Arcane::VariableBuildInfo(mesh, "arcane_face_uid", mesh->faceFamily()->name()));
1891 arcane_node_uid = new VariableNodeInt64(Arcane::VariableBuildInfo(mesh, "arcane_node_uid", mesh->nodeFamily()->name()));
1892
1893 ENUMERATE_CELL (icell, mesh->allCells()) {
1894 (*arcane_cell_uid)[icell] = icell->uniqueId().asInt64();
1895 }
1896 ENUMERATE_FACE (iface, mesh->allFaces()) {
1897 (*arcane_face_uid)[iface] = iface->uniqueId().asInt64();
1898 }
1899 info() << "#INODE";
1900 ENUMERATE_NODE (inode, mesh->allNodes()) {
1901 (*arcane_node_uid)[inode] = inode->uniqueId().asInt64();
1902 info() << inode->uniqueId().asInt64();
1903 }
1904 /*
1905 ENUMERATE_(Node, inode, mesh->nodeFamily()->view().subView(4,nodes_uid.size())){
1906 Node node = *inode;
1907 nodes_coords[node] = nodes_to_add_coords[node.uniqueId()];
1908 info() << node.uniqueId() << " " << nodes_coords[node] ;
1909 }
1910 */
1911 //
1912 // We will look for the service directly without using the .arc
1913 /*Directory d = mesh->subDomain()->exportDirectory();
1914 info() << "Writing at " << d.path() ;
1915 ServiceBuilder<IPostProcessorWriter> spp(mesh->handle());
1916
1917 Ref<IPostProcessorWriter> post_processor = spp.createReference("Ensight7PostProcessor"); // vtkHdf5PostProcessor
1918 //Ref<IPostProcessorWriter> post_processor = spp.createReference("VtkLegacyMeshWriter"); // (valid values = UCDPostProcessor, UCDPostProcessor, Ensight7PostProcessor, Ensight7PostProcessor)
1919 // Base path
1920 // <fichier-binaire>false</fichier-binaire>
1921 post_processor->setBaseDirectoryName(d.path());
1922
1923 post_processor->setTimes(UniqueArray<Real>{0.1}); // Just to fix the time step
1924
1925 VariableList variables;
1926 variables.add(mesh->nodesCoordinates().variable());
1927 variables.add(*arcane_node_uid);
1928 variables.add(*arcane_face_uid);
1929 variables.add(*arcane_cell_uid);
1930 post_processor->setVariables(variables);
1931
1932 ItemGroupList groups;
1933 groups.add(mesh->allNodes());
1934 groups.add(mesh->allFaces());
1935 groups.add(mesh->allCells());
1936 post_processor->setGroups(groups);
1937
1938 IVariableMng* vm = mesh->subDomain()->variableMng();
1939
1940 vm->writePostProcessing(post_processor.get());
1941 mesh->utilities()->writeToFile("subdivider_one_tetra_refine_output.vtk", "VtkLegacyMeshWriter");
1942 */
1943 info() << "#ENDSUBDV ";
1944}
1945
1946/*---------------------------------------------------------------------------*/
1947/*---------------------------------------------------------------------------*/
1948
1951{
1952 mesh->utilities()->writeToFile("subdivider_one_quad_input.vtk", "VtkLegacyMeshWriter");
1953
1954 // We delete the old mesh
1955 Int32UniqueArray lids(mesh->allCells().size());
1956 ENUMERATE_CELL (icell, mesh->allCells()) {
1957 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
1958 << icell->type() << ", nb nodes=" << icell->nbNode();
1959 lids[icell.index()] = icell->localId();
1960 }
1961 IMeshModifier* modifier = mesh->modifier();
1962 modifier->removeCells(lids);
1963 modifier->endUpdate();
1964
1965 // We create our Quad
1966 Int64UniqueArray nodes_uid(4);
1967 for (Integer i = 0; i < 4; i++)
1968 nodes_uid[i] = i;
1969
1970 UniqueArray<Int32> nodes_lid(nodes_uid.size());
1971 modifier->addNodes(nodes_uid, nodes_lid.view());
1972 mesh->nodeFamily()->endUpdate();
1973 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
1974 NodeInfoListView new_nodes(mesh->nodeFamily());
1975 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
1976 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
1977 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
1978 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
1979
1980 Int64UniqueArray cells_infos(6);
1981 Int64UniqueArray faces_infos;
1982 cells_infos[0] = IT_Quad4; // type
1983 cells_infos[1] = 44; // cell uid
1984 cells_infos[2] = nodes_uid[0]; // node 0
1985 cells_infos[3] = nodes_uid[1]; // ... 1
1986 cells_infos[4] = nodes_uid[2]; // ... 2
1987 cells_infos[5] = nodes_uid[3]; // ... 3
1988
1989 IntegerUniqueArray cells_lid;
1990 modifier->addCells(1, cells_infos, cells_lid);
1991 modifier->endUpdate();
1992 mesh->utilities()->writeToFile("subdivider_one_quad_ouput.vtk", "VtkLegacyMeshWriter");
1993}
1994
1995/*---------------------------------------------------------------------------*/
1996/*---------------------------------------------------------------------------*/
1997
2000{
2001 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
2002 // We delete the old mesh
2003 Int32UniqueArray lids(mesh->allCells().size());
2004 ENUMERATE_CELL (icell, mesh->allCells()) {
2005 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
2006 << icell->type() << ", nb nodes=" << icell->nbNode();
2007 lids[icell.index()] = icell->localId();
2008 }
2009 IMeshModifier* modifier = mesh->modifier();
2010 modifier->removeCells(lids);
2011 modifier->endUpdate();
2012 // We create our Hexa
2013 Int64UniqueArray nodes_uid(3);
2014 for (Integer i = 0; i < 3; i++)
2015 nodes_uid[i] = i;
2016
2017 UniqueArray<Int32> nodes_lid(nodes_uid.size());
2018 modifier->addNodes(nodes_uid, nodes_lid.view());
2019 mesh->nodeFamily()->endUpdate();
2020 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
2021 NodeInfoListView new_nodes(mesh->nodeFamily());
2022 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
2023 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
2024 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
2025
2026 Int64UniqueArray cells_infos(10);
2027 Int64UniqueArray faces_infos;
2028 cells_infos[0] = IT_Triangle3; // type
2029 cells_infos[1] = 44; // cell uid
2030 cells_infos[2] = nodes_uid[0]; // node 0
2031 cells_infos[3] = nodes_uid[1]; // ... 1
2032 cells_infos[4] = nodes_uid[2]; // ... 2
2033
2034 IntegerUniqueArray cells_lid;
2035 modifier->addCells(1, cells_infos, cells_lid);
2036 modifier->endUpdate();
2037 mesh->utilities()->writeToFile("subdivider_one_tri.vtk", "VtkLegacyMeshWriter");
2038}
2039
2040/*---------------------------------------------------------------------------*/
2041/*---------------------------------------------------------------------------*/
2042
2044_computeNodeUid(UniqueArray<Int64> node_in_cell, const StorageRefine& node_pattern)
2045{
2046 UniqueArray<Int64> new_node_uid;
2047 Integer init_size = node_in_cell.size();
2048 for (Integer i = 0; i < node_pattern.size(); i++) {
2049 //info() << "test " << i ;
2050 UniqueArray<Int64> tmp = node_pattern[i];
2051 tmp.resize(node_pattern[i].size());
2052 for (Integer j = 0; j < node_pattern[i].size(); j++) {
2053 tmp.add(node_in_cell[node_pattern[i][j]]);
2054 }
2055 // uid
2056 std::sort(tmp.begin(), tmp.end());
2057 node_in_cell.add(init_size + i); //= 4+i;// = 4+i; //Arcane::MeshUtils::generateHashUniqueId(tmp.constView());
2058 new_node_uid.add(node_in_cell[init_size + i]);
2059 }
2060 return new_node_uid;
2061}
2062
2063/*---------------------------------------------------------------------------*/
2064/*---------------------------------------------------------------------------*/
2065
2066ArcaneBasicMeshSubdividerService::
2067ArcaneBasicMeshSubdividerService(const ServiceBuildInfo& sbi)
2069{
2070}
2071
2072/*---------------------------------------------------------------------------*/
2073/*---------------------------------------------------------------------------*/
2074
2077{
2078 mesh->utilities()->writeToFile("subdivider_one_hexa_input.vtk", "VtkLegacyMeshWriter");
2079 // We delete the old mesh
2080 Int32UniqueArray lids(mesh->allCells().size());
2081 ENUMERATE_CELL (icell, mesh->allCells()) {
2082 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
2083 << icell->type() << ", nb nodes=" << icell->nbNode();
2084 lids[icell.index()] = icell->localId();
2085 }
2086 IMeshModifier* modifier = mesh->modifier();
2087 modifier->removeCells(lids);
2088 modifier->endUpdate();
2089 // We create our Hexa
2090 Int64UniqueArray nodes_uid(8);
2091 for (Integer i = 0; i < 8; i++)
2092 nodes_uid[i] = i;
2093
2094 UniqueArray<Int32> nodes_lid(nodes_uid.size());
2095 modifier->addNodes(nodes_uid, nodes_lid.view());
2096 mesh->nodeFamily()->endUpdate();
2097 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
2098 NodeInfoListView new_nodes(mesh->nodeFamily());
2099 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
2100 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
2101 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(10.0, 10.0, 0.0);
2102 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(0.0, 10.0, 0.0);
2103 nodes_coords[new_nodes[nodes_lid[4]]] = Arcane::Real3(0.0, 0.0, 10.0);
2104 nodes_coords[new_nodes[nodes_lid[5]]] = Arcane::Real3(10.0, 0.0, 10.0);
2105 nodes_coords[new_nodes[nodes_lid[6]]] = Arcane::Real3(10.0, 10.0, 10.0);
2106 nodes_coords[new_nodes[nodes_lid[7]]] = Arcane::Real3(0.0, 10.0, 10.0);
2107
2108 Int64UniqueArray cells_infos(10);
2109 Int64UniqueArray faces_infos;
2110 cells_infos[0] = IT_Hexaedron8; // type
2111 cells_infos[1] = 44; // cell uid
2112 cells_infos[2] = nodes_uid[0]; // node 0
2113 cells_infos[3] = nodes_uid[1]; // ... 1
2114 cells_infos[4] = nodes_uid[2]; // ... 2
2115 cells_infos[5] = nodes_uid[3]; // ... 3
2116 cells_infos[6] = nodes_uid[4]; // ... 4
2117 cells_infos[7] = nodes_uid[5]; // ... 5
2118 cells_infos[8] = nodes_uid[6]; // ... 6
2119 cells_infos[9] = nodes_uid[7]; // ... 7
2120
2121 IntegerUniqueArray cells_lid;
2122 modifier->addCells(1, cells_infos, cells_lid);
2123 modifier->endUpdate();
2124 // We create a test group
2125 UniqueArray<Int64> face_uid;
2126 ENUMERATE_FACE (iface, mesh->allFaces()) {
2127 Face face = *iface;
2128 face_uid.add(face.uniqueId());
2129 }
2130 UniqueArray<Int32> face_lid(face_uid.size());
2131 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
2132 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
2133 mesh->utilities()->writeToFile("subdivider_one_hexa_ouput.vtk", "VtkLegacyMeshWriter");
2134}
2135
2136/*---------------------------------------------------------------------------*/
2137/*---------------------------------------------------------------------------*/
2138
2141{
2142
2143 mesh->utilities()->writeToFile("subdivider_one_tetra_input.vtk", "VtkLegacyMeshWriter");
2144
2145 // We delete the old mesh if necessary
2146 Int32UniqueArray lids(mesh->allCells().size());
2147 VariableNodeReal3& nodes_coords = mesh->nodesCoordinates();
2148 ENUMERATE_CELL (icell, mesh->allCells()) {
2149 info() << "cell[" << icell->localId() << "," << icell->uniqueId() << "] type="
2150 << icell->type() << ", nb nodes=" << icell->nbNode();
2151 lids[icell.index()] = icell->localId();
2152 }
2153 IMeshModifier* modifier = mesh->modifier();
2154 modifier->removeCells(lids);
2155 modifier->endUpdate();
2156
2157 // Empty mesh, we create our tetra
2158
2159 info() << "===================== THE MESH IS EMPTY";
2160
2161 // We add nodes
2162 Int64UniqueArray nodes_uid(4);
2163 for (Integer i = 0; i < 4; i++)
2164 nodes_uid[i] = i;
2165
2166 UniqueArray<Int32> nodes_lid(nodes_uid.size());
2167 modifier->addNodes(nodes_uid, nodes_lid.view());
2168 mesh->nodeFamily()->endUpdate();
2169 info() << "===================== THE MESH IS EMPTY";
2170
2171 NodeInfoListView new_nodes(mesh->nodeFamily());
2172
2173 nodes_coords[new_nodes[nodes_lid[0]]] = Arcane::Real3(0.0, 0.0, 0.0);
2174 nodes_coords[new_nodes[nodes_lid[1]]] = Arcane::Real3(10.0, 0.0, 0.0);
2175 nodes_coords[new_nodes[nodes_lid[2]]] = Arcane::Real3(5.0, 5.0 / 3.0, 10.0);
2176 nodes_coords[new_nodes[nodes_lid[3]]] = Arcane::Real3(5.0, 5.0, 0.0);
2177
2178 Int64UniqueArray cells_infos(1 * 6);
2179 Int64UniqueArray faces_infos;
2180
2181 cells_infos[0] = IT_Tetraedron4; // type
2182 cells_infos[1] = 44; // cell uid
2183 cells_infos[2] = nodes_uid[0]; // node 0
2184 cells_infos[3] = nodes_uid[1]; // ... 1
2185 cells_infos[4] = nodes_uid[2]; // ... 2
2186 cells_infos[5] = nodes_uid[3]; // ... 3
2187
2188 IntegerUniqueArray cells_lid;
2189 modifier->addCells(1, cells_infos, cells_lid);
2190 modifier->endUpdate();
2191
2192 // We create a test group
2193 UniqueArray<Int64> face_uid;
2194 ENUMERATE_FACE (iface, mesh->allFaces()) {
2195 Face face = *iface;
2196 face_uid.add(face.uniqueId());
2197 }
2198 UniqueArray<Int32> face_lid(face_uid.size());
2199 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid, true);
2200 mesh->faceFamily()->createGroup("GroupeTest", face_lid);
2201
2202 info() << "===================== THE CELLS ARE ADDED";
2203}
2204
2205/*---------------------------------------------------------------------------*/
2206/*---------------------------------------------------------------------------*/
2207
2208/* The goal is simply to have the order of faces in an element*/
2211{
2212 mesh->utilities()->writeToFile("3D_last_input_seq.vtk", "VtkLegacyMeshWriter");
2213 info() << "#FACE ORDER";
2214 ENUMERATE_CELL (icell, mesh->ownCells()) {
2215
2216 const Cell& cell = *icell;
2217 for (Face face : cell.faces()) {
2219 for (Node node : face.nodes()) {
2220 n.add(node.uniqueId().asInt64());
2221 }
2222 info() << face.uniqueId() << " nodes " << n;
2223 }
2224 }
2225}
2226
2227/*---------------------------------------------------------------------------*/
2228/*---------------------------------------------------------------------------*/
2229
2232{
2233 info() << "Change uniqueId() for family=" << family->name();
2234 items_new_uid.synchronize();
2235 ENUMERATE_ (Item, iitem, family->allItems()) {
2236 Item item{ *iitem };
2237 Int64 current_uid = item.uniqueId();
2238 Int64 new_uid = items_new_uid[iitem];
2239 if (new_uid >= 0 && new_uid != current_uid) {
2240 item.mutableItemBase().setUniqueId(new_uid);
2241 }
2242 }
2244}
2245
2246/*---------------------------------------------------------------------------*/
2247/*---------------------------------------------------------------------------*/
2248
2258{
2259 // For each node, we set the incident cell with the smallest uid
2260 VariableNodeInt64 nodes_min_cell_uid(VariableBuildInfo(mesh, "ArcaneNodeMinCellUid"));
2261 nodes_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2262 ENUMERATE_NODE (inode, mesh->ownNodes()) {
2263 Node node = *inode;
2264 auto cells = node.cells();
2265 Int64 min = cells[0].uniqueId();
2266 for (auto c : cells) {
2267 if (min > c.uniqueId()) {
2268 min = c.uniqueId();
2269 }
2270 }
2271 nodes_min_cell_uid[node] = min;
2272 }
2273 // same for face
2274 VariableFaceInt64 faces_min_cell_uid(VariableBuildInfo(mesh, "ArcaneFaceMinCellUid"));
2275 faces_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2276 ENUMERATE_FACE (iface, mesh->ownFaces()) {
2277 Face face = *iface;
2278 auto cells = face.cells();
2279 Int64 min = cells[0].uniqueId();
2280 for (auto c : cells) {
2281 if (min > c.uniqueId()) {
2282 min = c.uniqueId();
2283 }
2284 }
2285 faces_min_cell_uid[face] = min;
2286 }
2287 //
2288 nodes_min_cell_uid.synchronize();
2289 faces_min_cell_uid.synchronize();
2290
2291 VariableNodeInt64 nodes_new_uid(VariableBuildInfo(mesh, "ArcaneRenumberNodesNewUid"));
2292 VariableFaceInt64 faces_new_uid(VariableBuildInfo(mesh, "ArcaneRenumberFacesNewUid"));
2293 // Renumbering according to C of F and N in vars
2294 // ?? Attention to ghost layer ??
2295 nodes_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2296 faces_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2297
2298 ENUMERATE_CELL (icell, mesh->ownCells()) {
2299 Cell cell = *icell;
2300 Int64 count_nodes = 0;
2301 for (Node node : cell.nodes()) {
2302 if (nodes_new_uid[node] == NULL_ITEM_UNIQUE_ID && cell.uniqueId() == nodes_min_cell_uid[node]) {
2303 nodes_new_uid[node] = cell.uniqueId().asInt64() * cell.nbNode() + count_nodes;
2304 count_nodes++;
2305 }
2306 }
2307 Int64 count_faces = 0;
2308 for (Face face : cell.faces()) {
2309 if (faces_new_uid[face] == NULL_ITEM_UNIQUE_ID && cell.uniqueId() == faces_min_cell_uid[face]) {
2310 faces_new_uid[face] = cell.uniqueId().asInt64() * cell.nbFace() + count_faces;
2311 count_faces++;
2312 }
2313 }
2314 }
2315 // Application
2316 _applyFamilyRenumbering(mesh->nodeFamily(), nodes_new_uid);
2317 _applyFamilyRenumbering(mesh->faceFamily(), faces_new_uid);
2318 // mesh->checkValidMesh();
2319}
2320
2321/*---------------------------------------------------------------------------*/
2322/*---------------------------------------------------------------------------*/
2323
2326{
2327 bool print_hash = true;
2328 bool with_ghost = false;
2329 MD5HashAlgorithm hash_algo;
2330 MeshUtils::checkUniqueIdsHashCollective(mesh->nodeFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2331 MeshUtils::checkUniqueIdsHashCollective(mesh->faceFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2332 MeshUtils::checkUniqueIdsHashCollective(mesh->cellFamily(), &hash_algo, Arcane::String(), print_hash, with_ghost);
2333}
2334
2335/*---------------------------------------------------------------------------*/
2336/*---------------------------------------------------------------------------*/
2337
2339subdivideMesh([[maybe_unused]] IPrimaryMesh* mesh)
2340{
2341 Arcane::Timer total_time(mesh->subDomain(), "TimerSubdividerTotal", Timer::eTimerType::TimerReal);
2342 total_time.start();
2343 //exit(0);
2344 //_generateOneTetra(mesh);
2345 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
2346 // Default pattern manager
2347 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
2348 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
2349 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
2350 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
2351
2352 if (options()->differentElementTypeOutput()) {
2353 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
2354 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
2355 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
2356 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
2357 info() << "The refinement patterns have changed for meshes of the following types: Quad4, Triangle3, Hexaedron8, Tetraedron4.";
2358 info() << "The output element types will be:\nQuad4->Triangle3\nTriangle3->Quad4\nHexaedron8->Tetraedron4\nTetraedron4->Hexaedron8";
2359 }
2360
2361 Arcane::Timer timer_subdivide_step(mesh->subDomain(), "TimerSubdivider", Timer::eTimerType::TimerReal);
2362 Arcane::Timer timer_renumbering_step(mesh->subDomain(), "TimerRenumbering", Timer::eTimerType::TimerReal);
2363 Arcane::Timer timer_renumbering_apply_step(mesh->subDomain(), "TimerRenumberingApply", Timer::eTimerType::TimerReal);
2364
2365 timer_subdivide_step.start();
2366
2367 for (Integer i = 0; i < options()->nbSubdivision; i++) {
2368 _refineOnce(mesh, pattern_manager);
2369 debug() << i << "refine done";
2370 }
2371
2372 timer_subdivide_step.stop();
2373
2374 timer_renumbering_step.start();
2375
2376 // Renumbering Node, Faces, using Cells uids
2378 // * Transform in option <without-renumber-compact>
2379
2380 timer_renumbering_step.stop();
2381
2382 timer_renumbering_apply_step.start();
2383
2384 mesh->properties()->setBool("compact", true);
2385 mesh->properties()->setBool("sort", true);
2386 mesh->modifier()->endUpdate();
2387
2388 timer_renumbering_apply_step.stop();
2389
2390 total_time.stop();
2391
2392 traceMng()->info() << "Timers " << timer_subdivide_step.name() << " " << timer_subdivide_step.totalTime();
2393 traceMng()->info() << "Timers " << timer_renumbering_step.name() << " " << timer_renumbering_step.totalTime();
2394 traceMng()->info() << "Timers " << timer_renumbering_apply_step.name() << " " << timer_renumbering_apply_step.totalTime();
2395 traceMng()->info() << "Timers " << total_time.name() << " " << total_time.totalTime();
2396
2397 // VariableList vl;
2398 //_writeEnsight(mesh,"SubdividerRenumberTests",vl);
2399 // Debug After
2400 // mesh->utilities()->writeToFile("subdivider_output_"+std::to_string(mesh->parallelMng()->commRank())+".vtk", "VtkLegacyMeshWriter");
2401 //mesh->utilities()->writeToFile("subdivider_after_" + std::to_string(options()->nbSubdivision) + "refine.vtk", "VtkLegacyMeshWriter");
2402 //debug() << "write file with name:" << "subdivider_after_";
2403 /*
2404 mesh->utilities()->writeToFile("subdivider_output.vtk", "VtkLegacyMeshWriter");
2405 */
2406 //_checkMeshUid(mesh);
2407 //MeshUtils::writeMeshInfosSorted(mesh,"vp_meshinfo"+std::to_string(mesh->parallelMng()->commRank()));
2408 info() << "subdivider done";
2409}
2410
2411/*---------------------------------------------------------------------------*/
2412/*---------------------------------------------------------------------------*/
2413
2414ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
2416
2417/*---------------------------------------------------------------------------*/
2418/*---------------------------------------------------------------------------*/
2419
2420} // End namespace Arcane
2421
2422/*---------------------------------------------------------------------------*/
2423/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
#define ENUMERATE_EDGE(name, group)
Generic enumerator for an edge group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Generates a unique identifier from a list of node identifiers.
void checkUniqueIdsHashCollective(IItemFamily *family, IHashAlgorithm *hash_algo, const String &expected_hash, bool print_hash_value, bool include_ghost)
Checks the hash of the uniqueId() of entities in a family.
Integer size() const
Number of elements in the vector.
bool empty() const
Capacity (number of allocated elements) of the vector.
ArcaneArcaneBasicMeshSubdividerServiceObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsArcaneBasicMeshSubdividerService * options() const
Options du jeu de données du service.
static UniqueArray< Int64 > _computeNodeUid(UniqueArray< Int64 > nodes_uid, const StorageRefine &node_pattern)
Calculates the unique ID based on node_uid.
void _applyFamilyRenumbering(IItemFamily *family, VariableItemInt64 &items_new_uid)
Renumbers the family TODO share with AMR.
void _checkHashNodesFacesCells(IPrimaryMesh *mesh)
Calculates the hash of N F C.
void _generatePattern2D(IPrimaryMesh *mesh)
Method to obtain the vtk files for the different patterns available in 2D.
void _generatePattern3D(IPrimaryMesh *mesh)
Method to obtain the vtk files for the different patterns available in 3D.
void subdivideMesh(IPrimaryMesh *mesh) override
Refines the mesh by nb-subdivision.
void _generateOneTri(IPrimaryMesh *mesh)
Generates a triangle.
void _generateOneQuad(IPrimaryMesh *mesh)
Generates a quadrilateral.
void _renumberNodesFaces(IPrimaryMesh *mesh)
Renumbers nodes and faces based on cells This method does not compact, meaning For now,...
void _getArcaneOrder(IPrimaryMesh *mesh)
Method to get how new faces are created for an element. Useful for filling the child faces array in t...
void _checkMeshUid(IPrimaryMesh *mesh)
Verification that all uids are >= 0.
void _generatePattern(IPrimaryMesh *mesh)
Method to generate patterns on a single base element.
void _refineOnce(IPrimaryMesh *mesh, std::unordered_map< Arccore::Int16, MeshSubdivider::Pattern > &pattern_manager)
Refines the mesh once with the patterns present in the pattern_manager.
void _generateOneTetra(IPrimaryMesh *mesh)
Generates a tetrahedron.
void _faceOrderArcane(IPrimaryMesh *mesh)
Generates the arcane face order for all patterns.
void _refineWithArcaneFaces(IPrimaryMesh *mesh, MeshSubdivider::Pattern p)
Refines using arcane faces and the pattern (Pattern) p.
void _generateOneHexa(IPrimaryMesh *mesh)
Generates a hexahedron.
void addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
iterator begin()
Iterator over the first element of the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
ConstArrayView< T > constView() const
Constant view of this array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sub-view starting from element abegin and containing asize elements.
iterator end()
Iterator over the first element after the end of the array.
ArrayView< T > view() const
Mutable view of this array.
Cell of a mesh.
Definition Item.h:1300
FaceConnectedListViewType faces() const
List of faces of the cell.
Definition Item.h:1403
Face face(Int32 i) const
i-th face of the cell
Definition Item.h:1400
Int32 nbFace() const
Number of faces of the cell.
Definition Item.h:1397
Integer count() const
Number of elements in the collection.
Class managing a directory.
Definition Directory.h:36
String path() const override
Returns the path of the directory.
Definition Directory.cc:111
Edge of a cell.
Definition Item.h:875
Face of a cell.
Definition Item.h:1032
Cell cell(Int32 i) const
i-th cell of the face
Definition Item.h:1793
CellConnectedListViewType cells() const
List of cells of the face.
Definition Item.h:1135
virtual void setBuilderVersion(Integer n)=0
Sets the version of the ghost cell builder. For now (version 3.3), the possible values are 2,...
virtual Integer nbGhostLayer() const =0
Number of ghost layers.
virtual Integer builderVersion() const =0
Ghost cell builder version.
virtual void setNbGhostLayer(Integer n)=0
Sets the number of ghost layers.
Interface of an entity family.
Definition IItemFamily.h:83
virtual void notifyItemsUniqueIdChanged()=0
Notifies that the unique IDs of the entities have been modified.
virtual ItemGroupCollection groups() const =0
Collection of groups in this family.
virtual ItemGroup allItems() const =0
Group of all entities.
virtual String name() const =0
Family name.
virtual Integer nbItem() const =0
Number of entities.
virtual IItemFamily * nodeFamily()=0
Returns the node family.
virtual NodeGroup allNodes()=0
Group of all nodes.
virtual CellGroup allCells()=0
Group of all cells.
virtual IItemFamily * cellFamily()=0
Returns the cell family.
Mesh modification interface.
virtual void updateGhostLayers()=0
Updates the ghost layer.
virtual void setDynamic(bool v)=0
Sets the property indicating whether the mesh can evolve.
virtual void removeCells(Int32ConstArrayView cells_local_id)=0
Removes cells.
virtual void addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes_lid=Int32ArrayView())=0
Adds nodes.
virtual void addCells(Integer nb_cell, Int64ConstArrayView cell_infos, Int32ArrayView cells_lid=Int32ArrayView())=0
Adds cells.
virtual void endUpdate()=0
Notifies the instance that mesh modification is finished.
virtual TraceMessage info()=0
Stream for an information message.
Variable manager interface.
Interface of a variable.
Definition IVariable.h:40
virtual String itemFamilyName() const =0
Name of the associated family (null if none).
virtual String fullName() const =0
Full variable name (with family prefix).
@ PNoDump
Indicates that the variable should not be saved.
Definition IVariable.h:62
virtual int property() const =0
Returns the properties of the variable.
virtual bool isUsed() const =0
Usage state of the variable.
SentinelType end() const
Iterator after the last connected entity.
const_iterator begin() const
Iterator over the first connected entity.
Mesh entity group.
Definition ItemGroup.h:51
bool isOwn() const
Returns whether the group contains only elements belonging to the subdomain.
Definition ItemGroup.cc:149
const String & fullName() const
Group name.
Definition ItemGroup.h:87
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Adds entities.
Definition ItemGroup.cc:439
bool isAllItems() const
Indicates if the group is that of all entities.
Definition ItemGroup.cc:607
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Definition Item.h:843
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
NodeLocalIdView nodeIds() const
List of nodes of the entity.
Definition Item.h:846
Base class for a mesh element.
Definition Item.h:84
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
Definition Item.h:394
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
ItemTypeId itemTypeId() const
Entity type.
Definition Item.h:258
Int16 type() const
Entity type.
Definition Item.h:255
Calculates the MD5 hashing function of an array.
Class Pattern which allows manipulation of a refinement pattern (pattern in English).
StorageRefine faces
Matrix for the generation of new faces.
StorageRefine cells
Matrix for the generation of new cells.
Int16 type
Type of the element to refine.
StorageRefine nodes
Matrix for the generation of new nodes.
Int16 face_type
Type of the face of the element to refine.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
View of node information.
Node of a mesh.
Definition Item.h:598
Cell cell(Int32 i) const
i-th cell of the node
Definition Item.h:1744
CellConnectedListViewType cells() const
List of cells of the node.
Definition Item.h:728
Class which allows building patterns.
Integer arraySize() const
If the variable is an array, returns its dimension, otherwise returns 0.
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Structure containing the information to create a service.
Utility class for instantiating a service of a given interface.
bool null() const
Returns true if the string is null.
Definition String.cc:306
Management of a timer.
Definition Timer.h:63
const String & name() const
Returns the name of the timer.
Definition Timer.h:237
Real stop()
Deactivates the timer.
Definition Timer.cc:87
@ TimerReal
Timer using real time.
Definition Timer.h:77
Real totalTime() const
Returns the total time (in seconds) spent in the timer.
Definition Timer.h:240
void start()
Activates the timer.
Definition Timer.cc:70
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Quantity at the cell center of 64-bit integer type.
MeshVariableScalarRefT< Node, Int64 > VariableNodeInt64
Quantity at the node of 64-bit integer type.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
ItemVariableScalarRefT< Int64 > VariableItemInt64
Quantity of 64-bit integer type.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Quantity at the face of 64-bit integer type.
VariableRefScalarT< Integer > VariableScalarInteger
Scalar variable of integer type.
@ ReduceMax
Maximum of values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
List< ItemGroup > ItemGroupList
Array of mesh item groups.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
std::int16_t Int16
Signed integer type of 16 bits.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
std::int32_t Int32
Signed integer type of 32 bits.