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"
81namespace Arcane::MeshSubdivider
106 StorageRefine child_faces;
130 this->child_faces = child_faces;
133 Pattern(Pattern&& other) noexcept
140 , child_faces(other.child_faces)
143 Pattern(
const Pattern&) =
delete;
145 Pattern(Pattern& other) noexcept
152 , child_faces(other.child_faces)
154 Pattern& operator=(
const Pattern& other)
156 if (
this != &other) {
163 child_faces = other.child_faces;
168 Pattern& operator=(Pattern&& other)
noexcept
170 if (
this != &other) {
177 child_faces = other.child_faces;
181 Pattern& operator=(Pattern& other)
noexcept
183 if (
this != &other) {
190 child_faces = other.child_faces;
282 StorageRefine nodes({
289 StorageRefine faces({
303 StorageRefine cells({
309 StorageRefine child_faces({
316 return { IT_Quad4, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
343 StorageRefine nodes({});
344 StorageRefine faces({
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 };
384 StorageRefine nodes({
389 StorageRefine faces({
400 StorageRefine cells({ { 3, 0, 5 },
404 StorageRefine child_faces(
408 return { IT_Triangle3, IT_Line2, IT_Triangle3, nodes, faces, cells, child_faces };
417 StorageRefine nodes({
423 StorageRefine faces({
426 StorageRefine cells({
431 StorageRefine child_faces({});
432 return { IT_Triangle3, IT_Line2, IT_Quad4, nodes, faces, cells, child_faces };
442 StorageRefine nodes = {
461 { 0, 1, 5, 4, 3, 2, 7, 6 }
463 StorageRefine faces = {
504 StorageRefine child_faces = {
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 }
522 return { IT_Hexaedron8, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
531 StorageRefine nodes = {
540 StorageRefine faces = {
566 StorageRefine child_faces = {
572 StorageRefine cells = {
582 return { IT_Tetraedron4, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
592 StorageRefine nodes = {};
593 StorageRefine faces = {
613 StorageRefine child_faces = {
621 StorageRefine cells = {
628 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
637 StorageRefine nodes = {
650 StorageRefine faces = {
670 StorageRefine child_faces = {
680 StorageRefine cells = {
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 }
698 return { IT_Tetraedron4, IT_Quad4, IT_Hexaedron8, nodes, faces, cells, child_faces };
707 StorageRefine nodes({
714 { 0, 1, 2, 3, 4, 5, 6, 7 },
716 StorageRefine faces({
779 StorageRefine cells({
811 StorageRefine child_faces({
821 return { IT_Hexaedron8, IT_Triangle3, IT_Tetraedron4, nodes, faces, cells, child_faces };
833class ArcaneBasicMeshSubdividerService
901 void _refineOnce([[maybe_unused]]
IPrimaryMesh*
mesh, std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern>& pattern_manager);
930 info() <<
"begin:_checkMeshUid";
932 const Cell& cell = *icell;
933 if (cell.
uniqueId().asInt64() < 0) {
934 info() <<
"FATAL ERROR UID";
939 const Face& face = *iface;
940 if (face.
uniqueId().asInt64() < 0) {
941 info() <<
"FATAL ERROR UID";
946 const Edge& edge = *iedge;
947 if (edge.
uniqueId().asInt64() < 0) {
948 info() <<
"FATAL ERROR UID";
953 const Node& node = *inode;
954 if (node.
uniqueId().asInt64() < 0) {
955 info() <<
"FATAL ERROR UID";
970 info() <<
"Vars: " <<
mesh->variableMng()->variables().count();
972 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
985 info() <<
"end:_checkMeshUid";
994 if (
mesh->dimension() == 2) {
997 else if (
mesh->dimension() == 3) {
1008 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> pattern_manager;
1010 mesh->faceFamily()->destroyGroups();
1012 pattern_manager[IT_Triangle3] = PatternBuilder::tritotri();
1014 std::string prefix(
"subdivider_pattern2D_");
1015 mesh->utilities()->writeToFile(prefix +
"tritotri.vtk",
"VtkLegacyMeshWriter");
1017 mesh->faceFamily()->destroyGroups();
1019 pattern_manager[IT_Triangle3] = PatternBuilder::tritoquad();
1021 mesh->utilities()->writeToFile(prefix +
"tritoquad.vtk",
"VtkLegacyMeshWriter");
1023 mesh->faceFamily()->destroyGroups();
1025 pattern_manager[IT_Quad4] = PatternBuilder::quadtoquad();
1027 mesh->utilities()->writeToFile(prefix +
"quadtoquad.vtk",
"VtkLegacyMeshWriter");
1029 mesh->faceFamily()->destroyGroups();
1031 pattern_manager[IT_Quad4] = PatternBuilder::quadtotri();
1033 mesh->utilities()->writeToFile(prefix +
"quadtotri.vtk",
"VtkLegacyMeshWriter");
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();
1048 mesh->utilities()->writeToFile(prefix +
"tettotet.vtk",
"VtkLegacyMeshWriter");
1050 mesh->faceFamily()->destroyGroups();
1052 pattern_manager[IT_Tetraedron4] = PatternBuilder::tettohex();
1054 mesh->utilities()->writeToFile(prefix +
"tettohex.vtk",
"VtkLegacyMeshWriter");
1056 mesh->faceFamily()->destroyGroups();
1058 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextohex();
1060 mesh->utilities()->writeToFile(prefix +
"hextohex.vtk",
"VtkLegacyMeshWriter");
1062 mesh->faceFamily()->destroyGroups();
1064 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet24();
1066 mesh->utilities()->writeToFile(prefix +
"hextotet24.vtk",
"VtkLegacyMeshWriter");
1068 mesh->faceFamily()->destroyGroups();
1070 pattern_manager[IT_Hexaedron8] = PatternBuilder::hextotet();
1072 mesh->utilities()->writeToFile(prefix +
"subdivider_hextotet.vtk",
"VtkLegacyMeshWriter");
1125 const VariableList& variables)
1130 auto post_processor = spp.createReference(
1131 "Ensight7PostProcessor");
1132 post_processor->setTimes(
1138 post_processor->setBaseDirectoryName(d.
path() +
"/" + dirname);
1145 arcane_cell_uid[*icell] = icell->uniqueId();
1149 arcane_rank[*icell] =
mesh->parallelMng()->commRank();
1153 arcane_node_uid[*inode] = inode->uniqueId();
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);
1162 post_processor->setVariables(all_variables);
1163 post_processor->setGroups(groups);
1165 vm->writePostProcessing(post_processor.get());
1176 Int64 max_cell_uid = NULL_ITEM_UNIQUE_ID;
1179 if (max_cell_uid < cell.
uniqueId())
1183 global_max_cell_uid++;
1185 info() <<
"#subdivide mesh";
1188 const Cell& cell = *icell;
1196 info() <<
"subdivide mesh with " <<
options()->nbSubdivision() <<
" nb_refine";
1198 Int32 my_rank =
mesh->parallelMng()->commRank();
1234 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1237 std::set<Int64> new_nodes;
1238 std::set<Int64> new_faces;
1240 std::unordered_map<Int64, Int32> node_uid_to_owner;
1241 std::unordered_map<Int64, Int32> edge_uid_to_owner;
1242 std::unordered_map<Int64, Int32> face_uid_to_owner;
1243 std::unordered_map<Int64, Int32> child_cell_owner;
1244 std::unordered_map<Int32, Int32> old_face_lid_to_owner;
1257 ARCANE_ASSERT((
mesh->nbEdge() == 0), (
"Wrong number of edge"));
1265 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_cell;
1266 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces;
1268 Int64 childs_count = 0;
1271 std::unordered_map<Int64, std::pair<Int64, Int64>> parents_to_childs_faces_groups;
1284 debug() <<
"Refining element";
1316 const Cell& cell = *icell;
1319 StorageRefine& node_pattern = p.
nodes;
1322 StorageRefine& child_faces = p.child_faces;
1329 debug() <<
"Initial nodes";
1339 debug() <<
"Generation of node uids";
1341 for (
Integer i = 0; i < node_pattern.
size(); i++) {
1344 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1345 tmp.
add(node_in_cell[node_pattern[i][j]]);
1349 node_in_cell[index_27 + i] = uid;
1351 if (new_nodes.find(node_in_cell[i + index_27]) == new_nodes.end()) {
1354 for (
Integer j = 0; j < node_pattern[i].
size(); j++) {
1356 middle_coord += nodes_coords[cell.
node(
static_cast<Integer>(node_pattern[i][j]))];
1358 if (node_pattern[i].size() == 0) {
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);
1365 new_nodes.insert(node_in_cell[i + index_27]);
1367 nodes_to_add_coords[node_in_cell[i + index_27]] = middle_coord;
1369 nodes_to_add.
add(uid);
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();
1389 StorageRefine& face_refine = p.
faces;
1390 debug() <<
"face_refine.size() " << face_refine.
size();
1392 debug() <<
"Refine face";
1393 for (
Integer i = 0; i < face_refine.
size(); i++) {
1397 for (
Integer j = 0; j < face_refine[i].
size(); j++) {
1398 tmp.
add(node_in_cell[face_refine[i][j]]);
1403 face_in_cell.
add(uid);
1405 if (new_faces.find(uid) == new_faces.end()) {
1408 faces_to_add.
add(uid);
1410 for (
Integer j = 0; j < face_refine[i].
size(); j++) {
1412 faces_to_add.
add(node_in_cell[face_refine[i][j]]);
1415 faces_uids.
add(uid);
1417 new_faces.insert(uid);
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]]);
1435 StorageRefine& cells_refine = p.
cells;
1437 debug() <<
"Generation of child cells";
1439 for (
Integer i = 0; i < cells_refine.
size(); i++) {
1442 for (
Integer j = 0; j < cells_refine[i].
size(); j++) {
1443 tmp.
add(node_in_cell[cells_refine[i][j]]);
1450 ARCANE_ASSERT((cell_uid >= 0), (
"Cell uid generation don't work properly"));
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]]);
1456 child_cell_owner[cell_uid] = cell.
owner();
1458 child_cells.
add(cell_uid);
1463 parents_to_childs_cell[cell.
uniqueId()] = std::pair<Int64, Int64>(childs_count, cells_refine.
size());
1464 childs_count += cells_refine.
size();
1471 mesh->modifier()->addNodes(nodes_to_add, nodes_lid.
view());
1475 debug() <<
"Faces_uids " << faces_uids <<
" faces_to_add " << faces_to_add.
size() <<
" faces_to_add/6 " << faces_to_add.
size() / 6;
1481 debug() <<
"Before addOneFace " << nb_face_to_add;
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();
1493 mesh->modifier()->detachCells(cells_to_detach);
1496 mesh->modifier()->addCells(nb_cell_to_add, cells_to_add.
constView(), cells_lid);
1497 info() <<
"After addCells";
1501 mesh->cellFamily()->itemsUniqueIdToLocalId(child_cells_lid, child_cells,
true);
1532 mesh->faceFamily()->itemsUniqueIdToLocalId(face_external_lid, face_external_uid);
1539 if (group.
isOwn() &&
mesh->parallelMng()->isParallel()) {
1540 info() <<
"#groups: OWN";
1544 info() <<
"#groups: ALLITEMS";
1547 info() <<
"#groups: Added ";
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));
1557 group.
addItems(to_add_to_group,
true);
1564 if (group.
isOwn() &&
mesh->parallelMng()->isParallel()) {
1565 info() <<
"#groups: OWN";
1569 info() <<
"#groups: ALLITEMS";
1573 info() <<
"#groups: Added ";
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));
1582 info() <<
"#Added " << to_add_to_group.
size() <<
" to group " << group.
fullName();
1583 group.
addItems(to_add_to_group,
true);
1586 mesh->modifier()->removeDetachedCells(cells_to_detach.
constView());
1588 mesh->modifier()->endUpdate();
1591 debug() <<
"Debug faces " << faces_to_add;
1603 mesh->cellFamily()->notifyItemsOwnerChanged();
1606 ARCANE_ASSERT((nodes_lid.
size() == nodes_to_add.
size()), (
"End"));
1610 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_to_add,
true);
1619 nodes_coords[node] = nodes_to_add_coords[node.
uniqueId().asInt64()];
1620 debug() <<
"InSBD" << node.
uniqueId().asInt64() <<
" " << nodes_to_add_coords[node.
uniqueId().asInt64()];
1627 mesh->updateGhostLayers(
true);
1635 node_uid_to_owner[node.
uniqueId().asInt64()] = cell.
owner();
1644 face_uid_to_owner[face.
uniqueId().asInt64()] = cell.
owner();
1653 mesh->updateGhostLayers(
true);
1664 debug() <<
"nbface " <<
mesh->nbFace() <<
" " << nb_face_to_add <<
" expected " << nb_face_init * 4 + 12 * nb_cell_init;
1674 mesh->nodeFamily()->notifyItemsOwnerChanged();
1681 mesh->faceFamily()->notifyItemsOwnerChanged();
1685 mesh->updateGhostLayers(
true);
1710 std::unordered_map<Int64, Real3> nodes_to_add_coords;
1714 Int64 max_offset = 0;
1723 info() <<
"#_refineWithArcaneFaces";
1725 const Cell& cell = *icell;
1726 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1727 << icell->type() <<
", nb nodes=" << icell->nbNode();
1730 info() <<
"Face " << face.uniqueId() <<
" nodes ";
1731 for (
Node node : face.nodes()) {
1732 info() << node.uniqueId() <<
" ";
1737 ARCANE_ASSERT((!p.
cells.
empty()), (
"Pattern not init"));
1741 Int64 face_count = 0;
1743 std::map<Int64, Int32> node_uid_to_cell_local_id;
1747 const Cell& cell = *icell;
1750 info() <<
"Get Pattern";
1751 StorageRefine& node_pattern = p.
nodes;
1752 StorageRefine& cells = p.
cells;
1754 info() <<
"Get Nodes";
1759 info() <<
"Node pattern " << node_pattern.
size() <<
"nic " << node_in_cell;
1762 for (
Integer i = 0; i < node_pattern.
size(); i++) {
1763 info() <<
"test " << i;
1768 node_in_cell.
add(uid);
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]));
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;
1783 info() <<
"#node in cell " << node_in_cell;
1802 cells_infos.
add(max_offset);
1804 info() <<
"Cell " << i;
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]]);
1811 info() <<
"test2bisbis ";
1812 for (
Integer i = 0; i < node_in_cell.
size(); i++) {
1813 info() <<
"node_in_cell[ " << i <<
" ] " << node_in_cell[i];
1819 info() <<
"test3 " << nodes_uid.
size() <<
" " << nodes_lid.
size();
1823 modifier->
addNodes(nodes_uid, nodes_lid);
1824 info() <<
"After nodes";
1827 info() <<
"After faces";
1830 modifier->
addCells(cellcount, cells_infos, cells_lid);
1831 info() <<
"cellsize " << cells_infos.
size() <<
" " << cellcount;
1839 mesh->nodeFamily()->itemsUniqueIdToLocalId(to_add_to_nodes, nodes_uid,
true);
1841 info() <<
"#NODESHERE";
1844 coords_bis[node] = nodes_to_add_coords[node.
uniqueId()];
1846 info() << node.
uniqueId() <<
" " << nodes_coords[node];
1851 info() <<
"#coords" << coords_bis.asArray();
1852 info() <<
"#My mesh ";
1856 const Cell& cell = *icell;
1859 for (
Node node : face.nodes()) {
1860 stuff.
add(node.uniqueId());
1862 info() <<
"Faces " << face.uniqueId() <<
" node " << stuff;
1866 info() <<
"#Arcane face numbering:";
1869 const Face& face = *iface;
1871 std::cout <<
"{" << face.
nodes()[0].uniqueId().asInt64();
1874 std::cout <<
"," << face.
nodes()[i].uniqueId().asInt64();
1881 std::cout <<
"}," << std::endl;
1894 (*arcane_cell_uid)[icell] = icell->uniqueId().asInt64();
1897 (*arcane_face_uid)[iface] = iface->uniqueId().asInt64();
1901 (*arcane_node_uid)[inode] = inode->uniqueId().asInt64();
1902 info() << inode->uniqueId().asInt64();
1943 info() <<
"#ENDSUBDV ";
1952 mesh->utilities()->writeToFile(
"subdivider_one_quad_input.vtk",
"VtkLegacyMeshWriter");
1957 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
1958 << icell->type() <<
", nb nodes=" << icell->nbNode();
1959 lids[icell.index()] = icell->localId();
1967 for (
Integer i = 0; i < 4; i++)
1972 mesh->nodeFamily()->endUpdate();
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);
1982 cells_infos[0] = IT_Quad4;
1983 cells_infos[1] = 44;
1984 cells_infos[2] = nodes_uid[0];
1985 cells_infos[3] = nodes_uid[1];
1986 cells_infos[4] = nodes_uid[2];
1987 cells_infos[5] = nodes_uid[3];
1990 modifier->
addCells(1, cells_infos, cells_lid);
1992 mesh->utilities()->writeToFile(
"subdivider_one_quad_ouput.vtk",
"VtkLegacyMeshWriter");
2001 mesh->utilities()->writeToFile(
"subdivider_one_hexa_input.vtk",
"VtkLegacyMeshWriter");
2005 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
2006 << icell->type() <<
", nb nodes=" << icell->nbNode();
2007 lids[icell.index()] = icell->localId();
2014 for (
Integer i = 0; i < 3; i++)
2019 mesh->nodeFamily()->endUpdate();
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);
2028 cells_infos[0] = IT_Triangle3;
2029 cells_infos[1] = 44;
2030 cells_infos[2] = nodes_uid[0];
2031 cells_infos[3] = nodes_uid[1];
2032 cells_infos[4] = nodes_uid[2];
2035 modifier->
addCells(1, cells_infos, cells_lid);
2037 mesh->utilities()->writeToFile(
"subdivider_one_tri.vtk",
"VtkLegacyMeshWriter");
2048 for (
Integer i = 0; i < node_pattern.
size(); 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]]);
2057 node_in_cell.
add(init_size + i);
2058 new_node_uid.
add(node_in_cell[init_size + i]);
2060 return new_node_uid;
2066ArcaneBasicMeshSubdividerService::
2078 mesh->utilities()->writeToFile(
"subdivider_one_hexa_input.vtk",
"VtkLegacyMeshWriter");
2082 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
2083 << icell->type() <<
", nb nodes=" << icell->nbNode();
2084 lids[icell.index()] = icell->localId();
2091 for (
Integer i = 0; i < 8; i++)
2096 mesh->nodeFamily()->endUpdate();
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);
2110 cells_infos[0] = IT_Hexaedron8;
2111 cells_infos[1] = 44;
2112 cells_infos[2] = nodes_uid[0];
2113 cells_infos[3] = nodes_uid[1];
2114 cells_infos[4] = nodes_uid[2];
2115 cells_infos[5] = nodes_uid[3];
2116 cells_infos[6] = nodes_uid[4];
2117 cells_infos[7] = nodes_uid[5];
2118 cells_infos[8] = nodes_uid[6];
2119 cells_infos[9] = nodes_uid[7];
2122 modifier->
addCells(1, cells_infos, cells_lid);
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");
2143 mesh->utilities()->writeToFile(
"subdivider_one_tetra_input.vtk",
"VtkLegacyMeshWriter");
2149 info() <<
"cell[" << icell->localId() <<
"," << icell->uniqueId() <<
"] type="
2150 << icell->type() <<
", nb nodes=" << icell->nbNode();
2151 lids[icell.index()] = icell->localId();
2159 info() <<
"===================== THE MESH IS EMPTY";
2163 for (
Integer i = 0; i < 4; i++)
2168 mesh->nodeFamily()->endUpdate();
2169 info() <<
"===================== THE MESH IS EMPTY";
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);
2181 cells_infos[0] = IT_Tetraedron4;
2182 cells_infos[1] = 44;
2183 cells_infos[2] = nodes_uid[0];
2184 cells_infos[3] = nodes_uid[1];
2185 cells_infos[4] = nodes_uid[2];
2186 cells_infos[5] = nodes_uid[3];
2189 modifier->
addCells(1, cells_infos, cells_lid);
2199 mesh->faceFamily()->itemsUniqueIdToLocalId(face_lid, face_uid,
true);
2200 mesh->faceFamily()->createGroup(
"GroupeTest", face_lid);
2202 info() <<
"===================== THE CELLS ARE ADDED";
2212 mesh->utilities()->writeToFile(
"3D_last_input_seq.vtk",
"VtkLegacyMeshWriter");
2213 info() <<
"#FACE ORDER";
2216 const Cell& cell = *icell;
2219 for (
Node node : face.nodes()) {
2220 n.
add(node.uniqueId().asInt64());
2222 info() << face.uniqueId() <<
" nodes " << n;
2233 info() <<
"Change uniqueId() for family=" << family->
name();
2234 items_new_uid.synchronize();
2236 Item item{ *iitem };
2238 Int64 new_uid = items_new_uid[iitem];
2239 if (new_uid >= 0 && new_uid != current_uid) {
2261 nodes_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2264 auto cells = node.
cells();
2265 Int64 min = cells[0].uniqueId();
2266 for (
auto c : cells) {
2267 if (min > c.uniqueId()) {
2271 nodes_min_cell_uid[node] = min;
2275 faces_min_cell_uid.fill(NULL_ITEM_UNIQUE_ID);
2278 auto cells = face.
cells();
2279 Int64 min = cells[0].uniqueId();
2280 for (
auto c : cells) {
2281 if (min > c.uniqueId()) {
2285 faces_min_cell_uid[face] = min;
2288 nodes_min_cell_uid.synchronize();
2289 faces_min_cell_uid.synchronize();
2295 nodes_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2296 faces_new_uid.fill(NULL_ITEM_UNIQUE_ID);
2300 Int64 count_nodes = 0;
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;
2307 Int64 count_faces = 0;
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;
2327 bool print_hash =
true;
2328 bool with_ghost =
false;
2345 std::unordered_map<Arccore::Int16, MeshSubdivider::Pattern> 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();
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";
2365 timer_subdivide_step.
start();
2369 debug() << i <<
"refine done";
2372 timer_subdivide_step.
stop();
2374 timer_renumbering_step.
start();
2380 timer_renumbering_step.
stop();
2382 timer_renumbering_apply_step.
start();
2384 mesh->properties()->setBool(
"compact",
true);
2385 mesh->properties()->setBool(
"sort",
true);
2386 mesh->modifier()->endUpdate();
2388 timer_renumbering_apply_step.
stop();
2394 traceMng()->
info() <<
"Timers " << timer_renumbering_apply_step.
name() <<
" " << timer_renumbering_apply_step.
totalTime();
2408 info() <<
"subdivider done";
2414ARCANE_REGISTER_SERVICE_ARCANEBASICMESHSUBDIVIDERSERVICE(ArcaneBasicMeshSubdivider,
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
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.
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.
Arcane Service for meshing the dataset.
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.
FaceConnectedListViewType faces() const
List of faces of the cell.
Face face(Int32 i) const
i-th face of the cell
Int32 nbFace() const
Number of faces of the cell.
Integer count() const
Number of elements in the collection.
EnumeratorT< ItemGroup > Enumerator
Class managing a directory.
String path() const override
Returns the path of the directory.
Cell cell(Int32 i) const
i-th cell of the face
CellConnectedListViewType cells() const
List of cells of the face.
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.
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.
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.
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.
bool isOwn() const
Returns whether the group contains only elements belonging to the subdomain.
const String & fullName() const
Group name.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Adds entities.
bool isAllItems() const
Indicates if the group is that of all entities.
Node node(Int32 i) const
i-th node of the entity
NodeConnectedListViewType nodes() const
List of nodes of the entity.
Int32 nbNode() const
Number of nodes of the entity.
NodeLocalIdView nodeIds() const
List of nodes of the entity.
Base class for a mesh element.
impl::MutableItemBase mutableItemBase() const
Mutable internal part of the entity.
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Int32 owner() const
Owner subdomain number of the entity.
ItemUniqueId uniqueId() const
Unique identifier across all domains.
ItemTypeId itemTypeId() const
Entity type.
Int16 type() const
Entity type.
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.
Int16 cell_type
Type of the child cells.
void setOwner(Integer suid, Int32 current_sub_domain)
Sets the sub-domain number of the entity owner.
View of node information.
Cell cell(Int32 i) const
i-th cell of the node
CellConnectedListViewType cells() const
List of cells of the node.
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.
Structure containing the information to create a service.
Utility class for instantiating a service of a given interface.
Unicode character string.
bool null() const
Returns true if the string is null.
const String & name() const
Returns the name of the timer.
Real stop()
Deactivates the timer.
@ TimerReal
Timer using real time.
Real totalTime() const
Returns the total time (in seconds) spent in the timer.
void start()
Activates the timer.
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.
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.
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.
std::int16_t Int16
Signed integer type of 16 bits.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
std::int32_t Int32
Signed integer type of 32 bits.