15#include "arcane/utils/ApplicationInfo.h"
16#include "arcane/utils/CommandLineArguments.h"
17#include "arcane/utils/List.h"
18#include "arcane/utils/MDDim.h"
20#include "arcane/core/IMeshSubdivider.h"
21#include "arcane/impl/ArcaneBasicMeshSubdividerService_axl.h"
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"
30#include "arcane/core/SimpleSVGMeshExporter.h"
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"
41#include "arcane/core/PostProcessorWriterBase.h"
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"
50#include "arcane/core/IndexedItemConnectivityView.h"
51#include "arcane/core/IIndexedIncrementalItemConnectivityMng.h"
52#include "arcane/core/IIndexedIncrementalItemConnectivity.h"
53#include "arcane/core/IIncrementalItemConnectivity.h"
56#include "arcane/utils/IHashAlgorithm.h"
57#include "arcane/utils/MD5HashAlgorithm.h"
60#include <unordered_set>
65#include "arcane/core/Timer.h"
66#include "arccore/trace/ITraceMng.h"
77namespace MeshSubdivider
101 StorageRefine child_faces;
125 this->child_faces = child_faces;
128 Pattern(Pattern&& other) noexcept
135 , child_faces(other.child_faces)
138 Pattern(
const Pattern&) =
delete;
140 Pattern(Pattern& other) noexcept
147 , child_faces(other.child_faces)
149 Pattern& operator=(
const Pattern& other)
151 if (
this != &other) {
158 child_faces = other.child_faces;
163 Pattern& operator=(Pattern&& other)
noexcept
165 if (
this != &other) {
172 child_faces = other.child_faces;
176 Pattern& operator=(Pattern& other)
noexcept
178 if (
this != &other) {
185 child_faces = other.child_faces;
260 StorageRefine nodes({
267 StorageRefine faces({
281 StorageRefine cells({
287 StorageRefine child_faces({
294 return { IT_Quad4, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
317 StorageRefine nodes({});
318 StorageRefine faces({
325 StorageRefine cells({ { 0, 3, 2 }, { 2, 1, 0 } });
326 StorageRefine child_faces({});
327 return { IT_Quad4, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
354 StorageRefine nodes({
359 StorageRefine faces({
370 StorageRefine cells({ { 3, 0, 5 },
374 StorageRefine child_faces(
378 return { IT_Triangle3, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
383 StorageRefine nodes({
389 StorageRefine faces({
392 StorageRefine cells({
397 StorageRefine child_faces({});
398 return { IT_Triangle3, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
404 StorageRefine nodes = {
423 { 0, 1, 5, 4, 3, 2, 7, 6 }
425 StorageRefine faces = {
466 StorageRefine child_faces = {
474 StorageRefine cells = {
475 { 0, 8, 20, 9, 10, 21, 26, 22 },
476 { 10, 21, 26, 22, 4, 16, 25, 17 },
477 { 8, 1, 11, 20, 21, 12, 23, 26 },
478 { 21, 12, 23, 26, 16, 5, 18, 25 },
479 { 9, 20, 13, 3, 22, 26, 24, 15 },
480 { 22, 26, 24, 15, 17, 25, 19, 7 },
481 { 20, 11, 2, 13, 26, 23, 14, 24 },
482 { 26, 23, 14, 24, 25, 18, 6, 19 }
484 return { IT_Hexaedron8, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
489 StorageRefine nodes = {
498 StorageRefine faces = {
524 StorageRefine child_faces = {
530 StorageRefine cells = {
540 return { IT_Tetraedron4, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
546 StorageRefine nodes = {};
547 StorageRefine faces = {
567 StorageRefine child_faces = {
575 StorageRefine cells = {
582 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
587 StorageRefine nodes = {
600 StorageRefine faces = {
620 StorageRefine child_faces = {
630 StorageRefine cells = {
643 { 7, 10, 14, 13, 0, 4, 12, 6 },
644 { 8, 11, 5, 2, 13, 14, 12, 6 },
645 { 3, 9, 11, 8, 7, 10, 14, 13 },
646 { 9, 1, 5, 11, 10, 4, 12, 14 }
648 return { IT_Tetraedron4, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
653 StorageRefine nodes({
660 { 0, 1, 2, 3, 4, 5, 6, 7 },
662 StorageRefine faces({
725 StorageRefine cells({
757 StorageRefine child_faces({
767 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
775class ArcaneBasicMeshSubdividerService
843 void _refineOnce([[maybe_unused]]
IPrimaryMesh*
mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
866 info() <<
"begin:_checkMeshUid";
868 const Cell& cell = *icell;
869 if (cell.
uniqueId().asInt64() < 0) {
870 info() <<
"FATAL ERROR UID";
875 const Face& face = *iface;
876 if (face.
uniqueId().asInt64() < 0) {
877 info() <<
"FATAL ERROR UID";
882 const Edge& edge = *iedge;
883 if (edge.
uniqueId().asInt64() < 0) {
884 info() <<
"FATAL ERROR UID";
889 const Node& node = *inode;
890 if (node.
uniqueId().asInt64() < 0) {
891 info() <<
"FATAL ERROR UID";
906 info() <<
"Vars: " <<
mesh->variableMng()->variables().count();
908 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
921 info() <<
"end:_checkMeshUid";
926 if (
mesh->dimension() == 2) {
929 else if (
mesh->dimension() == 3) {
936 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
938 mesh->faceFamily()->destroyGroups();
940 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
942 std::string prefix(
"subdivider_pattern2D_");
943 mesh->utilities()->writeToFile(prefix +
"tritotri.vtk",
"VtkLegacyMeshWriter");
945 mesh->faceFamily()->destroyGroups();
947 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
949 mesh->utilities()->writeToFile(prefix +
"tritoquad.vtk",
"VtkLegacyMeshWriter");
951 mesh->faceFamily()->destroyGroups();
953 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
955 mesh->utilities()->writeToFile(prefix +
"quadtoquad.vtk",
"VtkLegacyMeshWriter");
957 mesh->faceFamily()->destroyGroups();
959 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
961 mesh->utilities()->writeToFile(prefix +
"quadtotri.vtk",
"VtkLegacyMeshWriter");
966 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
967 std::string prefix(
"subdivider_pattern3D_");
968 mesh->faceFamily()->destroyGroups();
970 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
972 mesh->utilities()->writeToFile(prefix +
"tettotet.vtk",
"VtkLegacyMeshWriter");
974 mesh->faceFamily()->destroyGroups();
976 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
978 mesh->utilities()->writeToFile(prefix +
"tettohex.vtk",
"VtkLegacyMeshWriter");
980 mesh->faceFamily()->destroyGroups();
982 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
984 mesh->utilities()->writeToFile(prefix +
"hextohex.vtk",
"VtkLegacyMeshWriter");
986 mesh->faceFamily()->destroyGroups();
988 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
990 mesh->utilities()->writeToFile(prefix +
"hextotet24.vtk",
"VtkLegacyMeshWriter");
992 mesh->faceFamily()->destroyGroups();
994 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
996 mesh->utilities()->writeToFile(prefix +
"subdivider_hextotet.vtk",
"VtkLegacyMeshWriter");
1043 const VariableList& variables)
1048 auto post_processor = spp.createReference(
1049 "Ensight7PostProcessor");
1050 post_processor->setTimes(
1054 groups.add(mesh->allCells());
1055 groups.add(mesh->allNodes());
1056 post_processor->setBaseDirectoryName(d.
path() +
"/" + dirname);
1063 arcane_cell_uid[*icell] = icell->uniqueId();
1067 arcane_rank[*icell] =
mesh->parallelMng()->commRank();
1071 arcane_node_uid[*inode] = inode->uniqueId();
1074 VariableList all_variables = variables.clone();
1075 all_variables.add(
mesh->nodesCoordinates().variable());
1076 all_variables.add(arcane_rank);
1077 all_variables.add(arcane_cell_uid);
1078 all_variables.add(arcane_node_uid);
1080 post_processor->setVariables(all_variables);
1081 post_processor->setGroups(groups);
1083 vm->writePostProcessing(post_processor.get());
1090 Int64 max_cell_uid = NULL_ITEM_UNIQUE_ID;
1093 if (max_cell_uid < cell.
uniqueId())
1097 global_max_cell_uid++;
1099 info() <<
"#subdivide mesh";
1102 const Cell& cell = *icell;
1110 info() <<
"subdivide mesh with " <<
options()->nbSubdivision() <<
" nb_refine";
1112 Int32 my_rank =
mesh->parallelMng()->commRank();
1148 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1151 std::set<Int64> new_nodes;
1152 std::set<Int64> new_faces;
1154 std::unordered_map<Int64, Int32> node_uid_to_owner;
1155 std::unordered_map<Int64, Int32> edge_uid_to_owner;
1156 std::unordered_map<Int64, Int32> face_uid_to_owner;
1157 std::unordered_map<Int64, Int32> child_cell_owner;
1158 std::unordered_map<Int32, Int32> old_face_lid_to_owner;
1171 ARCANE_ASSERT((
mesh->nbEdge() == 0), (
"Wrong number of edge"));
1179 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_cell;
1180 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces;
1182 Int64 childs_count = 0;
1185 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces_groups;
1198 debug() <<
"Refining element";
1230 const Cell& cell = *icell;
1233 StorageRefine& node_pattern = p.
nodes;
1236 StorageRefine& child_faces = p.child_faces;
1243 debug() <<
"Noeuds initiaux";
1253 debug() <<
"Génération des uid noeuds";
1255 for (
Integer i = 0; i < node_pattern.
size(); i++) {
1258 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1259 tmp.
add(node_in_cell[node_pattern[i][j]]);
1263 node_in_cell[index_27 + i] = uid;
1265 if (new_nodes.find(node_in_cell[i + index_27]) == new_nodes.end()) {
1268 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1270 middle_coord += nodes_coords[cell.
node(
static_cast<Integer>(node_pattern[i][j]))];
1272 if (node_pattern[i].size() == 0) {
1275 middle_coord /= node_pattern[i].
size();
1276 if (middle_coord ==
Real3(0.0, 0.0, 0.0)) {
1277 ARCANE_FATAL(
"Bad coordinate for new node, the node '{0}' probably has a default coordinate (0.0,0.0,0.0).", uid);
1279 new_nodes.insert(node_in_cell[i + index_27]);
1281 nodes_to_add_coords[node_in_cell[i + index_27]] = middle_coord;
1283 nodes_to_add.
add(uid);
1297 debug() <<
"nodetoadd size " << nodes_to_add.
size() <<
" " << nodes_to_add_coords.size();
1298 debug() <<
"Node coord & nb node to add" << nodes_to_add_coords.size() <<
" " << nodes_to_add.
size();
1303 StorageRefine& face_refine = p.
faces;
1304 debug() <<
"face_refine.size() " << face_refine.
size();
1306 debug() <<
"Refine face";
1307 for (
Integer i = 0; i < face_refine.
size(); i++) {
1311 for (
Integer j = 0; j < face_refine[i].
size(); j++) {
1312 tmp.
add(node_in_cell[face_refine[i][j]]);
1317 face_in_cell.
add(uid);
1319 if (new_faces.find(uid) == new_faces.end()) {
1322 faces_to_add.
add(uid);
1324 for (
Integer j = 0; j < face_refine[i].
size(); j++) {
1326 faces_to_add.
add(node_in_cell[face_refine[i][j]]);
1329 faces_uids.
add(uid);
1331 new_faces.insert(uid);
1340 debug() <<
"Gestion face groupe";
1341 for (
Integer i = 0; i < child_faces.
size(); i++) {
1342 parents_to_childs_faces_groups[cell.
face(i).
uniqueId()] = std::pair<Int64, Int64>(face_external_uid.
size(), child_faces[i].
size());
1343 for (
Integer j = 0; j < child_faces[i].
size(); j++) {
1344 face_external_uid.
add(face_in_cell[child_faces[i][j]]);
1349 StorageRefine& cells_refine = p.
cells;
1351 debug() <<
"Génération des cellules enfants";
1353 for (
Integer i = 0; i < cells_refine.
size(); i++) {
1356 for (
Integer j = 0; j < cells_refine[i].
size(); j++) {
1357 tmp.
add(node_in_cell[cells_refine[i][j]]);
1364 ARCANE_ASSERT((cell_uid >= 0), (
"Cell uid generation don't work properly"));
1366 cells_to_add.
add(cell_uid);
1367 for (
Integer j = 0; j < cells_refine[i].
size(); j++) {
1368 cells_to_add.
add(node_in_cell[cells_refine[i][j]]);
1370 child_cell_owner[cell_uid] = cell.
owner();
1372 child_cells.
add(cell_uid);
1377 parents_to_childs_cell[cell.
uniqueId()] = std::pair<Int64, Int64>(childs_count, cells_refine.
size());
1378 childs_count += cells_refine.
size();
1385 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.
view());
1389 debug() <<
"Faces_uids " << faces_uids <<
" faces_to_add " << faces_to_add.
size() <<
" faces_to_add/6 " << faces_to_add.
size() / 6;
1395 debug() <<
"Before addOneFace " << nb_face_to_add;
1399 mesh->modifier()->addFaces(nb_face_to_add, faces_to_add.
constView(), face_lid.
view());
1400 debug() <<
"addOneFace " << nb_face_to_add;
1401 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, faces_uids,
true);
1402 debug() <<
"NB_FACE_ADDED AFTER " << face_lid.
size() <<
" " << new_faces.size();
1407 mesh->modifier()->detachCells(cells_to_detach);
1410 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.
constView(), cells_lid);
1411 info() <<
"After addCells";
1415 mesh->cellFamily()->itemsUniqueIdToLocalId(child_cells_lid, child_cells,
true);
1446 mesh->faceFamily()->itemsUniqueIdToLocalId(face_external_lid, face_external_uid);
1453 if (group.
isOwn() &&
mesh->parallelMng()->isParallel()) {
1454 info() <<
"#groups: OWN";
1458 info() <<
"#groups: ALLITEMS";
1461 info() <<
"#groups: Added ";
1465 Int64 step = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].first;
1466 Int64 n_childs = parents_to_childs_faces_groups[iitem->uniqueId().asInt64()].second;
1467 auto subview = face_external_lid.
subView(step,
static_cast<Integer>(n_childs));
1471 group.
addItems(to_add_to_group,
true);
1478 if (group.
isOwn() &&
mesh->parallelMng()->isParallel()) {
1479 info() <<
"#groups: OWN";
1483 info() <<
"#groups: ALLITEMS";
1487 info() <<
"#groups: Added ";
1491 Int64 step = parents_to_childs_cell[iitem->uniqueId().asInt64()].first;
1492 Int64 n_childs = parents_to_childs_cell[iitem->uniqueId().asInt64()].second;
1493 auto subview = child_cells_lid.
subView(step,
static_cast<Integer>(n_childs));
1496 info() <<
"#Added " << to_add_to_group.
size() <<
" to group " << group.
fullName();
1497 group.
addItems(to_add_to_group,
true);
1500 mesh->modifier()->removeDetachedCells(cells_to_detach.
constView());
1502 mesh->modifier()->endUpdate();
1505 debug() <<
"Debug faces " << faces_to_add;
1517 mesh->cellFamily()->notifyItemsOwnerChanged();
1520 ARCANE_ASSERT((nodes_lid.
size() == nodes_to_add.
size()), (
"End"));
1524 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_to_add,
true);
1533 nodes_coords[node] = nodes_to_add_coords[node.
uniqueId().asInt64()];
1534 debug() <<
"InSBD" << node.
uniqueId().asInt64() <<
" " << nodes_to_add_coords[node.
uniqueId().asInt64()];
1541 mesh->updateGhostLayers(
true);
1549 node_uid_to_owner[node.
uniqueId().asInt64()] = cell.
owner();
1558 face_uid_to_owner[face.
uniqueId().asInt64()] = cell.
owner();
1567 mesh->updateGhostLayers(
true);
1578 debug() <<
"nbface " <<
mesh->nbFace() <<
" " << nb_face_to_add <<
" expected " << nb_face_init * 4 + 12 * nb_cell_init;
1588 mesh->nodeFamily()->notifyItemsOwnerChanged();
1595 mesh->faceFamily()->notifyItemsOwnerChanged();
1599 mesh->updateGhostLayers(
true);
1620 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1624 Int64 max_offset = 0;
1633 info() <<
"#_refineWithArcaneFaces";
1635 const Cell& cell = *icell;
1636 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1637 << icell->type() <<
", nb nodes=" << icell->nbNode();
1640 info() <<
"Face " << face.uniqueId() <<
" nodes ";
1641 for (
Node node : face.nodes()) {
1642 info() << node.uniqueId() <<
" ";
1647 ARCANE_ASSERT((!p.
cells.
empty()), (
"Pattern not init"));
1651 Int64 face_count = 0;
1653 std::map<Int64, Int32> node_uid_to_cell_local_id;
1657 const Cell& cell = *icell;
1660 info() <<
"Get Pattern";
1661 StorageRefine& node_pattern = p.
nodes;
1662 StorageRefine& cells = p.
cells;
1664 info() <<
"Get Nodes";
1669 info() <<
"Node pattern " << node_pattern.
size() <<
"nic " << node_in_cell;
1672 for (
Integer i = 0; i < node_pattern.
size(); i++) {
1673 info() <<
"test " << i;
1678 node_in_cell.
add(uid);
1683 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1684 middle_coord += nodes_coords[cell.
node(
static_cast<Int32>(node_pattern[i][j]))];
1685 info() << node_pattern[i][j] << cell.
node(
static_cast<Int32>(node_pattern[i][j]));
1687 middle_coord /= node_pattern[i].
size();
1688 nodes_to_add_coords[uid] = middle_coord;
1689 info() <<
"NodeX " << uid <<
" " <<
" coord " << nodes_to_add_coords[uid] <<
" " << middle_coord;
1690 node_uid_to_cell_local_id[uid] = cell.
nbNode() + i;
1693 info() <<
"#node in cell " << node_in_cell;
1712 cells_infos.
add(max_offset);
1714 info() <<
"Cell " << i;
1716 info() <<
"test2bis " << node_in_cell[cells[i][j]] <<
" " << node_in_cell.
size() <<
" " << node_pattern.
size();
1717 cells_infos.
add(node_in_cell[cells[i][j]]);
1721 info() <<
"test2bisbis ";
1722 for (
Integer i = 0; i < node_in_cell.
size(); i++) {
1723 info() <<
"node_in_cell[ " << i <<
" ] " << node_in_cell[i];
1729 info() <<
"test3 " << nodes_uid.
size() <<
" " << nodes_lid.
size();
1733 modifier->
addNodes(nodes_uid, nodes_lid);
1734 info() <<
"After nodes";
1737 info() <<
"After faces";
1740 modifier->
addCells(cellcount, cells_infos, cells_lid);
1741 info() <<
"cellsize " << cells_infos.
size() <<
" " << cellcount;
1749 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_uid,
true);
1751 info() <<
"#NODESHERE";
1754 coords_bis[node] = nodes_to_add_coords[node.
uniqueId()];
1756 info() << node.
uniqueId() <<
" " << nodes_coords[node];
1761 info() <<
"#coords" << coords_bis.asArray();
1762 info() <<
"#My mesh ";
1766 const Cell& cell = *icell;
1769 for (
Node node : face.nodes()) {
1770 stuff.
add(node.uniqueId());
1772 info() <<
"Faces " << face.uniqueId() <<
" node " << stuff;
1776 info() <<
"#Arcane face numbering:";
1779 const Face& face = *iface;
1781 std::cout <<
"{" << face.
nodes()[0].uniqueId().asInt64();
1784 std::cout <<
"," << face.
nodes()[i].uniqueId().asInt64();
1791 std::cout <<
"}," << std::endl;
1804 (*arcane_cell_uid)[icell] = icell->uniqueId().asInt64();
1807 (*arcane_face_uid)[iface] = iface->uniqueId().asInt64();
1811 (*arcane_node_uid)[inode] = inode->uniqueId().asInt64();
1812 info() << inode->uniqueId().asInt64();
1853 info() <<
"#ENDSUBDV ";
1858 mesh->utilities()->writeToFile(
"subdivider_one_quad_input.vtk",
"VtkLegacyMeshWriter");
1863 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1864 << icell->type() <<
", nb nodes=" << icell->nbNode();
1865 lids[icell.index()] = icell->localId();
1873 for (
Integer i = 0; i < 4; i++)
1878 mesh->nodeFamily()->endUpdate();
1881 nodes_coords[new_nodes[nodes_lid[0]]] =
Arcane::Real3(0.0, 0.0, 0.0);
1882 nodes_coords[new_nodes[nodes_lid[1]]] =
Arcane::Real3(10.0, 0.0, 0.0);
1883 nodes_coords[new_nodes[nodes_lid[2]]] =
Arcane::Real3(10.0, 10.0, 0.0);
1884 nodes_coords[new_nodes[nodes_lid[3]]] =
Arcane::Real3(0.0, 10.0, 0.0);
1888 cells_infos[0] = IT_Quad4;
1889 cells_infos[1] = 44;
1890 cells_infos[2] = nodes_uid[0];
1891 cells_infos[3] = nodes_uid[1];
1892 cells_infos[4] = nodes_uid[2];
1893 cells_infos[5] = nodes_uid[3];
1896 modifier->
addCells(1, cells_infos, cells_lid);
1898 mesh->utilities()->writeToFile(
"subdivider_one_quad_ouput.vtk",
"VtkLegacyMeshWriter");
1903 mesh->utilities()->writeToFile(
"subdivider_one_hexa_input.vtk",
"VtkLegacyMeshWriter");
1907 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1908 << icell->type() <<
", nb nodes=" << icell->nbNode();
1909 lids[icell.index()] = icell->localId();
1916 for (
Integer i = 0; i < 3; i++)
1921 mesh->nodeFamily()->endUpdate();
1924 nodes_coords[new_nodes[nodes_lid[0]]] =
Arcane::Real3(0.0, 0.0, 0.0);
1925 nodes_coords[new_nodes[nodes_lid[1]]] =
Arcane::Real3(10.0, 0.0, 0.0);
1926 nodes_coords[new_nodes[nodes_lid[2]]] =
Arcane::Real3(10.0, 10.0, 0.0);
1930 cells_infos[0] = IT_Triangle3;
1931 cells_infos[1] = 44;
1932 cells_infos[2] = nodes_uid[0];
1933 cells_infos[3] = nodes_uid[1];
1934 cells_infos[4] = nodes_uid[2];
1937 modifier->
addCells(1, cells_infos, cells_lid);
1939 mesh->utilities()->writeToFile(
"subdivider_one_tri.vtk",
"VtkLegacyMeshWriter");
1946 for (
Integer i = 0; i < node_pattern.
size(); i++) {
1949 tmp.
resize(node_pattern[i].size());
1950 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1951 tmp.
add(node_in_cell[node_pattern[i][j]]);
1955 node_in_cell.
add(init_size + i);
1956 new_node_uid.
add(node_in_cell[init_size + i]);
1958 return new_node_uid;
1961ArcaneBasicMeshSubdividerService::
1969 mesh->utilities()->writeToFile(
"subdivider_one_hexa_input.vtk",
"VtkLegacyMeshWriter");
1973 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1974 << icell->type() <<
", nb nodes=" << icell->nbNode();
1975 lids[icell.index()] = icell->localId();
1982 for (
Integer i = 0; i < 8; i++)
1987 mesh->nodeFamily()->endUpdate();
1990 nodes_coords[new_nodes[nodes_lid[0]]] =
Arcane::Real3(0.0, 0.0, 0.0);
1991 nodes_coords[new_nodes[nodes_lid[1]]] =
Arcane::Real3(10.0, 0.0, 0.0);
1992 nodes_coords[new_nodes[nodes_lid[2]]] =
Arcane::Real3(10.0, 10.0, 0.0);
1993 nodes_coords[new_nodes[nodes_lid[3]]] =
Arcane::Real3(0.0, 10.0, 0.0);
1994 nodes_coords[new_nodes[nodes_lid[4]]] =
Arcane::Real3(0.0, 0.0, 10.0);
1995 nodes_coords[new_nodes[nodes_lid[5]]] =
Arcane::Real3(10.0, 0.0, 10.0);
1996 nodes_coords[new_nodes[nodes_lid[6]]] =
Arcane::Real3(10.0, 10.0, 10.0);
1997 nodes_coords[new_nodes[nodes_lid[7]]] =
Arcane::Real3(0.0, 10.0, 10.0);
2001 cells_infos[0] = IT_Hexaedron8;
2002 cells_infos[1] = 44;
2003 cells_infos[2] = nodes_uid[0];
2004 cells_infos[3] = nodes_uid[1];
2005 cells_infos[4] = nodes_uid[2];
2006 cells_infos[5] = nodes_uid[3];
2007 cells_infos[6] = nodes_uid[4];
2008 cells_infos[7] = nodes_uid[5];
2009 cells_infos[8] = nodes_uid[6];
2010 cells_infos[9] = nodes_uid[7];
2013 modifier->
addCells(1, cells_infos, cells_lid);
2022 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid,
true);
2023 mesh->faceFamily()->createGroup(
"GroupeTest", face_lid);
2024 mesh->utilities()->writeToFile(
"subdivider_one_hexa_ouput.vtk",
"VtkLegacyMeshWriter");
2030 mesh->utilities()->writeToFile(
"subdivider_one_tetra_input.vtk",
"VtkLegacyMeshWriter");
2036 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
2037 << icell->type() <<
", nb nodes=" << icell->nbNode();
2038 lids[icell.index()] = icell->localId();
2046 info() <<
"===================== THE MESH IS EMPTY";
2050 for (
Integer i = 0; i < 4; i++)
2055 mesh->nodeFamily()->endUpdate();
2056 info() <<
"===================== THE MESH IS EMPTY";
2060 nodes_coords[new_nodes[nodes_lid[0]]] =
Arcane::Real3(0.0, 0.0, 0.0);
2061 nodes_coords[new_nodes[nodes_lid[1]]] =
Arcane::Real3(10.0, 0.0, 0.0);
2062 nodes_coords[new_nodes[nodes_lid[2]]] =
Arcane::Real3(5.0, 5.0 / 3.0, 10.0);
2063 nodes_coords[new_nodes[nodes_lid[3]]] =
Arcane::Real3(5.0, 5.0, 0.0);
2068 cells_infos[0] = IT_Tetraedron4;
2069 cells_infos[1] = 44;
2070 cells_infos[2] = nodes_uid[0];
2071 cells_infos[3] = nodes_uid[1];
2072 cells_infos[4] = nodes_uid[2];
2073 cells_infos[5] = nodes_uid[3];
2076 modifier->
addCells(1, cells_infos, cells_lid);
2086 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid,
true);
2087 mesh->faceFamily()->createGroup(
"GroupeTest", face_lid);
2089 info() <<
"===================== THE CELLS ARE ADDED";
2095 mesh->utilities()->writeToFile(
"3D_last_input_seq.vtk",
"VtkLegacyMeshWriter");
2096 info() <<
"#ORDRE FACES";
2099 const Cell& cell = *icell;
2102 for (
Node node : face.nodes()) {
2103 n.
add(node.uniqueId().asInt64());
2105 info() << face.uniqueId() <<
" nodes " << n;
2112 info() <<
"Change uniqueId() for family=" << family->
name();
2113 items_new_uid.synchronize();
2115 Item item{ *iitem };
2116 Int64 current_uid = item.uniqueId();
2117 Int64 new_uid = items_new_uid[iitem];
2118 if (new_uid >= 0 && new_uid != current_uid) {
2119 item.mutableItemBase().setUniqueId(new_uid);
2136 nodes_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2139 auto cells = node.
cells();
2140 Int64 min = cells[0].uniqueId();
2141 for (
auto c : cells) {
2142 if (min > c.uniqueId()) {
2146 nodes_min_cell_uid[node] = min;
2150 faces_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2153 auto cells = face.
cells();
2154 Int64 min = cells[0].uniqueId();
2155 for (
auto c : cells) {
2156 if (min > c.uniqueId()) {
2160 faces_min_cell_uid[face] = min;
2163 nodes_min_cell_uid.synchronize();
2164 faces_min_cell_uid.synchronize();
2170 nodes_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2171 faces_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2175 Int64 count_nodes = 0;
2177 if (nodes_new_uid[node] == NULL_ITEM_UNIQUE_ID && cell.
uniqueId() == nodes_min_cell_uid[node]) {
2178 nodes_new_uid[node] = cell.
uniqueId().asInt64() * cell.
nbNode() + count_nodes;
2182 Int64 count_faces = 0;
2184 if (faces_new_uid[face] == NULL_ITEM_UNIQUE_ID && cell.
uniqueId() == faces_min_cell_uid[face]) {
2185 faces_new_uid[face] = cell.
uniqueId().asInt64() * cell.
nbFace() + count_faces;
2199 bool print_hash =
true;
2200 bool with_ghost =
false;
2217 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
2219 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
2220 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
2221 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
2222 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettotet();
2225 if (
options()->differentElementTypeOutput()) {
2226 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
2227 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
2228 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
2229 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
2230 info() <<
"The refinement patterns have changed for meshes of the following types: Quad4, Triangle3, Hexaedron8, Tetraedron4.";
2231 info() <<
"The output element types will be:\nQuad4->Triangle3\nTriangle3->Quad4\nHexaedron8->Tetraedron4\nTetraedron4->Hexaedron8";
2238 timer_subdivide_step.
start();
2242 debug() << i <<
"refine done";
2245 timer_subdivide_step.
stop();
2247 timer_renumbering_step.
start();
2253 timer_renumbering_step.
stop();
2255 timer_renumbering_apply_step.
start();
2257 mesh->properties()->setBool(
"compact",
true);
2258 mesh->properties()->setBool(
"sort",
true);
2259 mesh->modifier()->endUpdate();
2261 timer_renumbering_apply_step.
stop();
2268 traceMng()->
info() <<
"Timers " << timer_renumbering_apply_step.
name() <<
" " << timer_renumbering_apply_step.
totalTime() ;
2282 info() <<
"subdivider done";
2288ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
Int64 generateHashUniqueId(SmallSpan< const Int64 > nodes_unique_id)
Génère un identifiant unique à partir d'une liste d'identifiants de noeuds.
void checkUniqueIdsHashCollective(IItemFamily *family, IHashAlgorithm *hash_algo, const String &expected_hash, bool print_hash_value, bool include_ghost)
Vérifie le hash des uniqueId() des entités d'une famille.
Integer size() const
Nombre d'éléments du vecteur.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Generation de la classe de base du Service.
ArcaneArcaneBasicMeshSubdividerServiceObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
CaseOptionsArcaneBasicMeshSubdividerService * options() const
Options du jeu de données du service.
Service Arcane un maillage du jeu de données.
static UniqueArray< Int64 > _computeNodeUid(UniqueArray< Int64 > nodes_uid, const StorageRefine &node_pattern)
Calcule le unique id en fonction des noeuds de node_uid.
void _applyFamilyRenumbering(IItemFamily *family, VariableItemInt64 &items_new_uid)
Renumérote la famille TODO mettre en commun avec AMR.
void _checkHashNodesFacesCells(IPrimaryMesh *mesh)
Calcul du hash des N F C.
void _generatePattern2D(IPrimaryMesh *mesh)
Methode pour obtenir les fichier vtk pour les différent pattern disponibles en 2D.
void _generatePattern3D(IPrimaryMesh *mesh)
Methode pour obtenir les fichier vtk pour les différent pattern disponibles en 3D.
void subdivideMesh(IPrimaryMesh *mesh) override
Raffine le maillage un nombre nb-subdivision.
void _generateOneTri(IPrimaryMesh *mesh)
Génère un triangle.
void _generateOneQuad(IPrimaryMesh *mesh)
Génère un quadrilatère.
void _renumberNodesFaces(IPrimaryMesh *mesh)
Renumérote les noeuds et les faces en fonction des cellules Cette méthode ne compacte pas,...
void _getArcaneOrder(IPrimaryMesh *mesh)
Methode pour avoir la manière dont sont crée les nouvelles faces pour un élément. Utile pour remplir ...
void _checkMeshUid(IPrimaryMesh *mesh)
Vérification que tout les uids sont >= 0.
void _generatePattern(IPrimaryMesh *mesh)
Méthode pour générer les motifs sur un seul élément de base.
void _refineOnce(IPrimaryMesh *mesh, std::unordered_map< Arccore::Int16, MeshSubdivider::Pattern > &pattern_manager)
Raffine une fois le maillage avec les motifs présent dans le pattern_manager.
void _generateOneTetra(IPrimaryMesh *mesh)
Génère un tetraèdre.
void _faceOrderArcane(IPrimaryMesh *mesh)
Génère l'ordre des faces arcane pour tout les motifs.
void _refineWithArcaneFaces(IPrimaryMesh *mesh, MeshSubdivider::Pattern p)
Raffine en utilisant les faces d'arcane et le motif (Pattern) p.
void _generateOneHexa(IPrimaryMesh *mesh)
Génère un hexaèdre.
void clear()
Supprime les éléments du tableau.
iterator end()
Itérateur sur le premier élément après la fin du tableau.
ConstArrayView< T > constView() const
Vue constante sur ce tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
ArrayView< T > subView(Int64 abegin, Integer asize)
Sous-vue à partir de l'élément abegin et contenant asize éléments.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
void addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
ArrayView< T > view() const
Vue mutable sur ce tableau.
iterator begin()
Itérateur sur le premier élément du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
FaceConnectedListViewType faces() const
Liste des faces de la maille.
Face face(Int32 i) const
i-ème face de la maille
Int32 nbFace() const
Nombre de faces de la maille.
Integer count() const
Nombre d'éléments de la collection.
EnumeratorT< ItemGroup > Enumerator
Classe gérant un répertoire.
String path() const override
Retourne le chemin du répertoire.
Cell cell(Int32 i) const
i-ème maille de la face
CellConnectedListViewType cells() const
Liste des mailles de la face.
virtual void setBuilderVersion(Integer n)=0
Positionne la version du constructeur de mailles fantômes. Pour l'instant (version 3....
virtual Integer nbGhostLayer() const =0
Nombre de couches fantômes.
virtual Integer builderVersion() const =0
Version du constructeur de mailles fantômes.
virtual void setNbGhostLayer(Integer n)=0
Positionne le nombre de couches fantômes.
Interface d'une famille d'entités.
virtual void notifyItemsUniqueIdChanged()=0
Notifie que les numéros uniques des entités ont été modifiées.
virtual ItemGroupCollection groups() const =0
Liste des groupes de cette famille.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual String name() const =0
Nom de la famille.
virtual Integer nbItem() const =0
Nombre d'entités.
Interface de modification du maillage.
virtual void updateGhostLayers()=0
Mise à jour de la couche fantôme.
virtual void setDynamic(bool v)=0
Positionne la propriété indiquant si le maillage peut évoluer.
virtual void removeCells(Int32ConstArrayView cells_local_id)=0
Supprime des mailles.
virtual void addNodes(Int64ConstArrayView nodes_uid, Int32ArrayView nodes_lid=Int32ArrayView())=0
Ajoute des noeuds.
virtual void addCells(Integer nb_cell, Int64ConstArrayView cell_infos, Int32ArrayView cells_lid=Int32ArrayView())=0
Ajoute des mailles.
virtual void endUpdate()=0
Notifie l'instance de la fin de la modification du maillage.
virtual TraceMessage info()=0
Flot pour un message d'information.
Interface du gestionnaire de variables.
Interface d'une variable.
virtual String itemFamilyName() const =0
Nom de la famille associée (nul si aucune).
virtual String fullName() const =0
Nom complet de la variable (avec le préfixe de la famille)
@ PNoDump
Indique que la variable ne doit pas être sauvegardée.
virtual int property() const =0
Retourne les propriétés de la variable.
virtual bool isUsed() const =0
Etat d'utilisation de la variable.
SentinelType end() const
Itérateur sur après la dernière entité connectée.
const_iterator begin() const
Itérateur sur la première entité connectée.
Groupe d'entités de maillage.
bool isOwn() const
Retourne si le groupe contient uniquement des éléments propres au sous-domaine.
const String & fullName() const
Nom du groupe.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Ajoute des entités.
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Node node(Int32 i) const
i-ème noeud de l'entité
NodeConnectedListViewType nodes() const
Liste des noeuds de l'entité
Int32 nbNode() const
Nombre de noeuds de l'entité
NodeLocalIdView nodeIds() const
Liste des noeuds de l'entité
Classe de base d'un élément de maillage.
impl::MutableItemBase mutableItemBase() const
Partie interne modifiable de l'entité.
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
ItemTypeId itemTypeId() const
Type de l'entité
Int16 type() const
Type de l'entité
Calcule la fonction de hashage MD5 d'un tableau.
Classe Pattern qui permet de manipuler un motif (pattern en anglais) de raffinement.
StorageRefine faces
Matrice pour la génération des nouvelles faces.
StorageRefine cells
Matrice pour la génération des nouvelles cellules.
Int16 type
Type de l'élément à raffiner.
StorageRefine nodes
Matrice pour la génération des nouveaux noeuds.
Int16 face_type
Type de la face de l'élément à raffiner.
Int16 cell_type
Type des cellules enfants.
void setOwner(Integer suid, Int32 current_sub_domain)
Positionne le numéro du sous-domaine propriétaire de l'entité.
Vue sur les informations des noeuds.
Cell cell(Int32 i) const
i-ème maille du noeud
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Classe qui permet de construire des patterns.
Integer arraySize() const
Si la variable est un tableau, retourne sa dimension, sinon retourne 0.
Classe gérant un vecteur de réel de dimension 3.
Structure contenant les informations pour créer un service.
Classe utilitaire pour instantier un service d'une interface donnée.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
const String & name() const
Retourne le nom du timer.
Real stop()
Désactive le timer.
@ TimerReal
Timer utilisant le temps réel.
Real totalTime() const
Retourne le temps total (en secondes) passé dans le timer.
void start()
Active le timer.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Paramètres nécessaires à la construction d'une variable.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
MeshVariableScalarRefT< Cell, Int64 > VariableCellInt64
Grandeur au centre des mailles de type entier 64 bits.
MeshVariableScalarRefT< Node, Int64 > VariableNodeInt64
Grandeur au noeud de type entier 64 bits.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
ItemVariableScalarRefT< Int64 > VariableItemInt64
Grandeur de type entier 64 bits.
MeshVariableScalarRefT< Face, Int64 > VariableFaceInt64
Grandeur aux faces de type entier 64 bits.
VariableRefScalarT< Integer > VariableScalarInteger
Variable scalaire de type entier.
@ ReduceMax
Maximum des valeurs.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
std::int16_t Int16
Type entier signé sur 16 bits.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
std::int32_t Int32
Type entier signé sur 32 bits.