14#include "arcane/utils/TraceAccessor.h"
15#include "arcane/utils/Array.h"
16#include "arcane/utils/IOException.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/NotSupportedException.h"
20#include "arcane/utils/Real3.h"
21#include "arcane/utils/OStringStream.h"
22#include "arcane/utils/FixedArray.h"
23#include "arcane/utils/SmallArray.h"
24#include "arcane/utils/PlatformUtils.h"
25#include "arcane/utils/CheckedConvert.h"
27#include "arcane/core/IMeshReader.h"
28#include "arcane/core/IPrimaryMesh.h"
29#include "arcane/core/IItemFamily.h"
30#include "arcane/core/ItemGroup.h"
31#include "arcane/core/VariableTypes.h"
32#include "arcane/core/IParallelMng.h"
34#include "arcane/core/IMeshModifier.h"
35#include "arcane/core/MeshKind.h"
36#include "arcane/core/NodesOfItemReorderer.h"
37#include "arcane/core/internal/MshMeshGenerationInfo.h"
40#include "arcane/std/internal/IosFile.h"
41#include "arcane/std/internal/IosGmsh.h"
82class MshParallelMeshReader
101 class MshToArcaneTypeInfo
105 MshToArcaneTypeInfo() =
default;
107 : m_msh_type(msh_type)
108 , m_arcane_type_info(iti)
109 , m_reorder_infos(reorder_infos)
115 Int32 m_msh_type = -1;
136 Int64 entity_tag = -1;
169 items_infos.add(type_id);
170 items_infos.add(unique_id);
171 items_infos.addRange(nodes_uid);
199 explicit MshParallelMeshReader(
ITraceMng* tm);
207 IMesh* m_mesh =
nullptr;
209 Int32 m_master_io_rank = A_NULL_RANK;
210 bool m_is_parallel =
false;
230 void _readMeshFromFile();
232 void _allocateCells();
233 void _allocateGroups();
240 void _readPhysicalNames();
243 void _readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim);
246 Int32 _getIntegerAndBroadcast();
247 Int64 _getInt64AndBroadcast();
257 void _goToNextLine();
260 const MshToArcaneTypeInfo& mshToArcaneTypeInfo(
Int32 msh_type)
const;
275 inline std::pair<Int64, Int64>
276 _interval(Int32 index, Int32 nb_interval, Int64 size)
278 Int64 isize = size / nb_interval;
279 Int64 ibegin = index * isize;
281 if ((index + 1) == nb_interval)
282 isize = size - ibegin;
283 return { ibegin, isize };
293MshParallelMeshReader::
316 s = f->getNextLine();
320 info(4) <<
"BroadcastNextLine: " << s;
321 m_parallel_mng->broadcastString(s, m_master_io_rank);
323 info(4) <<
"GetNextLine: " << s;
336 Int32 is_end_int = 0;
338 is_end_int = f->isEnd() ? 1 : 0;
339 info(4) <<
"IsEndOfFile_Master: " << is_end_int;
343 info(4) <<
"IsEndOfFile: " << is_end_int;
344 m_parallel_mng->broadcast(
ArrayView<Int32>(1, &is_end_int), m_master_io_rank);
346 bool is_end = (is_end_int != 0);
347 info(4) <<
"IsEnd: " << is_end;
356_getIntegerAndBroadcast()
361 v[0] = f->getInteger();
363 m_parallel_mng->broadcast(v.
view(), m_master_io_rank);
371Int64 MshParallelMeshReader::
372_getInt64AndBroadcast()
374 IosFile* f = m_ios_file.get();
375 FixedArray<Int64, 1> v;
379 m_parallel_mng->broadcast(v.view(), m_master_io_rank);
387void MshParallelMeshReader::
390 IosFile* f = m_ios_file.get();
393 f->binaryRead(values);
396 for (
Int64& v : values)
401 m_parallel_mng->broadcast(values, m_master_io_rank);
407void MshParallelMeshReader::
410 IosFile* f = m_ios_file.get();
413 f->binaryRead(values);
416 for (
Int32& v : values)
421 m_parallel_mng->broadcast(values, m_master_io_rank);
427void MshParallelMeshReader::
430 IosFile* f = m_ios_file.get();
433 f->binaryRead(values);
436 for (
double& v : values)
441 m_parallel_mng->broadcast(values, m_master_io_rank);
447Real3 MshParallelMeshReader::
450 IosFile* f = m_ios_file.get();
454 f->binaryRead(SmallSpan<Real3>(&v, 1));
457 Real x = f->getReal();
458 Real y = f->getReal();
459 Real z = f->getReal();
468Int32 MshParallelMeshReader::
471 IosFile* f = m_ios_file.get();
475 f->binaryRead(SmallSpan<Int32>(&v, 1));
484Int64 MshParallelMeshReader::
487 IosFile* f = m_ios_file.get();
491 f->binaryRead(SmallSpan<Int64>(&v, 1));
500void MshParallelMeshReader::
503 if (m_ios_file.get())
504 m_ios_file->goToEndOfLine();
515 Real min_value = -max_value;
516 Real3 min_box(max_value, max_value, max_value);
517 Real3 max_box(min_value, min_value, min_value);
518 const Int64 nb_node = m_mesh_allocate_info.nodes_coordinates.largeSize();
519 for (
Real3 pos : m_mesh_allocate_info.nodes_coordinates) {
533 Real min_x = min_box.
x;
534 Real max_x = max_box.
x;
538 info() <<
"MIN_MAX_X=" << global_min_x <<
" " << global_max_x;
544 for (
Int64 i = 0; i < nb_node; ++i) {
545 Int32 part =
static_cast<Int32>((m_mesh_allocate_info.nodes_coordinates[i].x - global_min_x) / diff_v);
546 part = std::clamp(part, 0,
m_nb_part - 1);
547 nodes_part[i] = part;
552 for (
Int64 i = 0; i < nb_node; ++i) {
554 Int64 uid = m_mesh_allocate_info.nodes_unique_id[i];
555 ++nb_node_per_rank[rank];
556 m_mesh_allocate_info.nodes_rank_map.insert(std::make_pair(uid, rank));
559 info() <<
"NB_NODE_PER_RANK=" << nb_node_per_rank;
592 _getInt64ArrayAndBroadcast(nodes_info.
view());
594 Int64 nb_node_block =
static_cast<Int32>(nodes_info[0]);
595 Int64 total_nb_node = nodes_info[1];
596 Int64 min_node_tag = nodes_info[2];
597 Int64 max_node_tag = nodes_info[3];
602 if (total_nb_node < 0)
605 info() <<
"[Nodes] nb_node_block=" << nb_node_block
606 <<
" total_nb_node=" << total_nb_node
607 <<
" min_tag=" << min_node_tag
608 <<
" max_tag=" << max_node_tag
610 <<
" nb_rank=" << m_parallel_mng->commSize();
613 node_blocks.
resize(nb_node_block);
615 for (
Int32 i = 0; i < nb_node_block; ++i) {
617 node_block.
index = i;
618 _readNodesOneEntity(node_block);
630void MshParallelMeshReader::
631_readNodesOneEntity(MshNodeBlock& node_block)
641 _getInt32ArrayAndBroadcast(entity_infos.
view());
642 Int32 nb_node2 = CheckedConvert::toInt32(_getInt64AndBroadcast());
648 Int32 entity_dim = entity_infos[0];
649 node_block.entity_dim = entity_dim;
651 Int32 entity_tag = entity_infos[1];
652 node_block.entity_tag = entity_tag;
655 node_block.nb_node = nb_node2;
657 Int32 parametric_coordinates = entity_infos[2];
659 info(4) <<
"[Nodes] index=" << node_block.index <<
" entity_dim=" << entity_dim <<
" entity_tag=" << entity_tag
660 <<
" parametric=" << parametric_coordinates
661 <<
" nb_node2=" << nb_node2;
663 if (parametric_coordinates != 0)
677 info(4) <<
"Reading UIDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
678 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
679 nodes_uids.
resize(nb_to_read);
686 ios_file->binaryRead(nodes_uids.
view());
689 for (
Integer i = 0; i < nb_to_read; ++i) {
691 nodes_uids[i] = ios_file->getInt64();
695 if (dest_rank != m_master_io_rank) {
696 pm->send(nodes_uids, dest_rank);
699 else if (my_rank == dest_rank) {
700 pm->
recv(nodes_uids, m_master_io_rank);
704 if (my_rank == dest_rank) {
705 m_mesh_allocate_info.nodes_unique_id.addRange(nodes_uids);
706 node_block.nb_node = nodes_uids.
size();
714 info(4) <<
"Reading COORDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
715 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
716 nodes_coordinates.
resize(nb_to_read);
723 ios_file->binaryRead(nodes_coordinates.
view());
726 for (
Integer i = 0; i < nb_to_read; ++i) {
727 nodes_coordinates[i] = _getReal3();
731 if (dest_rank != m_master_io_rank) {
732 pm->send(nodes_coordinates, dest_rank);
735 else if (my_rank == dest_rank) {
736 pm->
recv(nodes_coordinates, m_master_io_rank);
740 if (my_rank == dest_rank) {
741 m_mesh_allocate_info.nodes_coordinates.addRange(nodes_coordinates);
757 IosFile* ios_file = m_ios_file.get();
766 info() <<
"Reading block nb_entity=" << nb_entity_in_block <<
" item_nb_node=" << item_nb_node;
774 const Int64 nb_to_read = _interval(i_part,
m_nb_part, nb_entity_in_block).second;
778 info(4) <<
"Reading block part i_part=" << i_part
779 <<
" nb_to_read=" << nb_to_read <<
" dest_rank=" << dest_rank;
781 const Int64 nb_uid = nb_to_read;
782 const Int64 nb_connectivity = nb_uid * item_nb_node;
783 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
785 connectivities.
resize(nb_connectivity);
789 Int64 nb_to_read = nb_uid * (item_nb_node + 1);
790 tmp_uid_and_connectivities.
resize(nb_to_read);
791 ios_file->binaryRead(tmp_uid_and_connectivities.
view());
793 for (
Int64 i = 0; i < nb_uid; ++i) {
794 Int64 item_unique_id = tmp_uid_and_connectivities[index];
796 uids[i] = item_unique_id;
797 for (
Int32 j = 0; j < item_nb_node; ++j) {
798 connectivities[(i * item_nb_node) + j] = tmp_uid_and_connectivities[index];
805 for (
Int64 i = 0; i < nb_uid; ++i) {
806 Int64 item_unique_id = ios_file->getInt64();
807 uids[i] = item_unique_id;
808 for (
Int32 j = 0; j < item_nb_node; ++j)
809 connectivities[(i * item_nb_node) + j] = ios_file->getInt64();
812 if (dest_rank != m_master_io_rank) {
813 pm->send(uids, dest_rank);
814 pm->send(connectivities, dest_rank);
817 else if (my_rank == dest_rank) {
818 pm->
recv(uids, m_master_io_rank);
819 pm->
recv(connectivities, m_master_io_rank);
821 if (my_rank == dest_rank) {
861 IosFile* ios_file = m_ios_file.get();
867 _getInt64ArrayAndBroadcast(elements_info.
view());
869 Int64 nb_block = elements_info[0];
870 Int64 number_of_elements = elements_info[1];
871 Int64 min_element_tag = elements_info[2];
872 Int64 max_element_tag = elements_info[3];
877 info() <<
"[Elements] nb_block=" << nb_block
878 <<
" nb_elements=" << number_of_elements
879 <<
" min_element_tag=" << min_element_tag
880 <<
" max_element_tag=" << max_element_tag;
882 if (number_of_elements < 0)
900 _getInt32ArrayAndBroadcast(block_info.
view());
902 Int32 entity_dim = block_info[0];
903 Int32 entity_tag = block_info[1];
904 Int32 entity_type = block_info[2];
905 Int64 nb_entity_in_block = _getInt64AndBroadcast();
913 info() <<
"[Elements] index=" << block.index <<
" entity_dim=" << entity_dim
914 <<
" entity_tag=" << entity_tag
915 <<
" msh_entity_type=" << entity_type <<
" nb_in_block=" << nb_entity_in_block
916 <<
" arcane_item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
918 block.nb_entity = nb_entity_in_block;
919 block.item_type = item_type;
920 block.item_nb_node = item_nb_node;
921 block.dimension = entity_dim;
922 block.entity_tag = entity_tag;
923 block.reorder_infos = msh_tinfo.m_reorder_infos;
924 if (entity_type == MSH_PNT) {
929 Int64 item_unique_id = NULL_ITEM_UNIQUE_ID;
931 [[maybe_unused]]
Int64 unused_id = _getInt64();
932 item_unique_id = _getInt64();
934 info() <<
"Adding unique node uid=" << item_unique_id;
938 block.uids.add(item_unique_id);
954 mesh_dimension =
math::max(mesh_dimension, block.dimension);
955 if (mesh_dimension < 0)
956 ARCANE_FATAL(
"Invalid computed mesh dimension '{0}'", mesh_dimension);
957 if (mesh_dimension != 2 && mesh_dimension != 3)
959 info() <<
"Computed mesh dimension = " << mesh_dimension;
961 bool allow_multi_dim_cell = m_mesh->meshKind().isNonManifold();
962 bool use_experimental_type_for_cell =
false;
963 if (allow_multi_dim_cell) {
965 use_experimental_type_for_cell =
true;
967 use_experimental_type_for_cell = (v.value() != 0);
969 info() <<
"Use experimental cell type?=" << use_experimental_type_for_cell;
970 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
972 const Int32 block_dim = block.dimension;
975 info() <<
"Reading block dim=" << block_dim <<
" type_name=" << item_type_name;
976 if (block_dim == mesh_dimension)
977 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
978 else if (allow_multi_dim_cell) {
981 bool use_sub_dim_cell =
false;
982 if (mesh_dimension == 3 && (block_dim == 2 || block_dim == 1))
984 use_sub_dim_cell =
true;
985 else if (mesh_dimension == 2 && block_dim == 1)
987 use_sub_dim_cell =
true;
988 if (!use_experimental_type_for_cell)
989 use_sub_dim_cell =
false;
990 if (use_sub_dim_cell) {
993 if (mesh_dimension == 3) {
994 if (block.item_type == IT_Triangle3)
995 block.item_type =
ItemTypeId(IT_Cell3D_Triangle3);
996 else if (block.item_type == IT_Triangle6)
997 block.item_type =
ItemTypeId(ITI_Cell3D_Triangle6);
998 else if (block.item_type == IT_Quad4)
999 block.item_type =
ItemTypeId(IT_Cell3D_Quad4);
1000 else if (block.item_type == IT_Quad8)
1001 block.item_type =
ItemTypeId(IT_Cell3D_Quad8);
1002 else if (block.item_type == IT_Quad9)
1003 block.item_type =
ItemTypeId(IT_Cell3D_Quad9);
1004 else if (block.item_type == IT_Line2)
1005 block.item_type =
ItemTypeId(IT_Cell3D_Line2);
1006 else if (block.item_type == IT_Line3)
1007 block.item_type =
ItemTypeId(IT_Cell3D_Line3);
1009 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 3D mesh", item_type_name);
1011 else if (mesh_dimension == 2) {
1012 if (block.item_type == IT_Line2)
1014 else if (block.item_type == IT_Line3)
1017 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 2D mesh", item_type_name);
1019 block.is_built_as_cells =
true;
1020 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
1025 return mesh_dimension;
1039 if (my_rank != dest_rank) {
1040 work_values.
resize(size);
1041 view = work_values.
view();
1043 pm->broadcast(view, dest_rank);
1057 const Int32 my_rank = pm->commRank();
1060 if (dest_rank == my_rank)
1061 size = values.size();
1063 return _broadcastArrayWithSize(pm, values, work_values, dest_rank, size);
1071void MshParallelMeshReader::
1072_computeOwnItems(MshElementBlock& block, MshItemKindInfo& item_kind_info,
bool is_generate_uid)
1076 IParallelMng* pm = m_parallel_mng;
1077 const Int32 my_rank = pm->commRank();
1080 const ItemTypeId item_type = block.item_type;
1081 const Int32 item_nb_node = block.item_nb_node;
1083 UniqueArray<Int64> connectivities;
1084 UniqueArray<Int64> uids;
1085 UniqueArray<Int32> nodes_rank;
1087 SmallSpan<const Int16> reorder_infos = block.reorder_infos;
1088 bool has_reorder_info = !reorder_infos.empty();
1090 if (is_print_level1)
1091 info() <<
"Compute own items block_index=" << block.index <<
" nb_part=" << nb_part
1092 <<
" has_reorder?=" << has_reorder_info;
1094 SmallArray<Int64> arcane_reordered_uids;
1095 if (has_reorder_info)
1096 arcane_reordered_uids.resize(item_nb_node);
1097 for (
Int32 i_part = 0; i_part < nb_part; ++i_part) {
1100 ArrayView<Int64> connectivities_view = _broadcastArray(pm, block.connectivities.view(), connectivities, dest_rank);
1101 ArrayView<Int64> uids_view = _broadcastArray(pm, block.uids.view(), uids, dest_rank);
1103 Int32 nb_item = uids_view.size();
1104 nodes_rank.resize(nb_item);
1105 nodes_rank.fill(-1);
1110 for (
Int32 i = 0; i < nb_item; ++i) {
1111 Int64 first_node_uid = connectivities_view[i * item_nb_node];
1112 auto x = m_mesh_allocate_info.nodes_rank_map.find(first_node_uid);
1113 if (x == m_mesh_allocate_info.nodes_rank_map.end())
1116 Int32 rank = x->second;
1117 nodes_rank[i] = rank;
1120 for (
Int32 i = 0; i < nb_item; ++i) {
1121 const Int32 rank = nodes_rank[i];
1122 if (rank != my_rank)
1127 ConstArrayView<Int64> v = connectivities_view.subView(i * item_nb_node, item_nb_node);
1128 Int64 uid = uids_view[i];
1129 if (is_generate_uid)
1131 uid = NULL_ITEM_UNIQUE_ID;
1132 if (has_reorder_info) {
1135 for (
Int32 zz = 0; zz < item_nb_node; ++zz)
1136 arcane_reordered_uids[zz] = v[reorder_infos[zz]];
1137 v = arcane_reordered_uids.view();
1139 item_kind_info.addItem(item_type, uid, v);
1169 const IItemFamily* node_family = m_mesh->nodeFamily();
1173 ConstArrayView<Int64> uids = _broadcastArray(pm, m_mesh_allocate_info.nodes_unique_id.view(), uids_storage, dest_rank);
1174 ConstArrayView<Real3> coords = _broadcastArray(pm, m_mesh_allocate_info.nodes_coordinates.view(), coords_storage, dest_rank);
1177 local_ids.
resize(nb_item);
1183 for (
Int32 i = 0; i < nb_item; ++i) {
1184 NodeLocalId nid(local_ids[i]);
1186 nodes_coord_var[nid] = coords[i];
1194void MshParallelMeshReader::
1198 Integer nb_elements = m_mesh_allocate_info.cells_infos.nb_item;
1199 info() <<
"nb_of_elements=cells_type.size()=" << nb_elements;
1200 Integer nb_cell_node = m_mesh_allocate_info.cells_infos.items_infos.
size();
1201 info() <<
"nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
1204 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
1206 info() <<
"## Allocating ##";
1207 pmesh->
allocateCells(nb_elements, m_mesh_allocate_info.cells_infos.items_infos,
false);
1208 info() <<
"## Ending ##";
1210 info() <<
"## Done ##";
1216void MshParallelMeshReader::
1219 IMesh* mesh = m_mesh;
1221 Int32 face_dim = mesh_dim - 1;
1222 UniqueArray<MshEntitiesWithNodes> entity_list;
1223 UniqueArray<MshPhysicalName> physical_name_list;
1224 IItemFamily* node_family = mesh->nodeFamily();
1226 for (MshElementBlock& block : m_mesh_allocate_info.element_blocks) {
1227 entity_list.clear();
1228 physical_name_list.clear();
1229 Int32 block_index = block.index;
1230 Int32 block_dim = block.dimension;
1233 Int64 block_entity_tag = block.entity_tag;
1234 if (block_entity_tag < 0) {
1235 info(5) <<
"[Groups] Skipping block index=" << block_index <<
" because it has no entity";
1238 if (block_dim == 0) {
1239 const MshEntitiesNodes* entity = m_mesh_info->findNodeEntities(block_entity_tag);
1241 info(5) <<
"[Groups] Skipping block index=" << block_index
1242 <<
" because entity tag is invalid";
1245 Int64 entity_physical_tag = entity->physicalTag();
1246 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1247 physical_name_list.add(physical_name);
1250 m_mesh_info->findEntities(block_dim, block_entity_tag, entity_list);
1251 for (
const MshEntitiesWithNodes& x : entity_list) {
1252 Int64 entity_physical_tag = x.physicalTag();
1253 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1254 physical_name_list.add(physical_name);
1257 for (
const MshPhysicalName& physical_name : physical_name_list) {
1258 if (physical_name.isNull()) {
1259 info(5) <<
"[Groups] Skipping block index=" << block_index
1260 <<
" because entity physical tag is invalid";
1263 String group_name = physical_name.name();
1264 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
1265 <<
" name='" << group_name <<
"' built_as_cells=" << block.is_built_as_cells;
1266 if (block_dim == mesh_dim || block.is_built_as_cells) {
1269 else if (block_dim == face_dim) {
1282 UniqueArray<Int64>& nodes_uids = m_mesh_allocate_info.nodes_unique_id;
1284 for (
const MshNodeBlock& block : m_mesh_allocate_info.node_blocks) {
1285 ArrayView<Int64> block_uids = nodes_uids.subView(block.index_in_allocation_info, block.nb_node);
1286 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block.entity_dim, block.entity_tag);
1287 String group_name = physical_name.name();
1288 info(4) <<
"NodeBlock name=" << group_name <<
" index=" << block.index
1289 <<
" index_in_allocation=" << block.index_in_allocation_info
1290 <<
" nb_node=" << block.nb_node;
1299 if (!group_name.null())
1318 _addFaceGroupOnePart(block, connectivities_view, group_name);
1325void MshParallelMeshReader::
1327 const String& group_name)
1330 const Int32 item_nb_node = block.item_nb_node;
1331 const Int32 block_index = block.index;
1333 const Int32 nb_entity = connectivities.
size() / item_nb_node;
1337 FaceGroup face_group =
mesh->faceFamily()->findGroup(group_name,
true);
1342 const Int32 face_nb_node = nb_entity * item_nb_node;
1347 Integer faces_nodes_unique_id_index = 0;
1360 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1361 for (
Integer z = 0; z < item_nb_node; ++z)
1362 orig_nodes_id[z] = connectivities[faces_nodes_unique_id_index + z];
1363 m_nodes_reorderer.reorder(type_id, orig_nodes_id);
1365 for (
Integer z = 0; z < item_nb_node; ++z)
1366 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = sorted_nodes[z];
1367 faces_first_node_unique_id[i_face] = sorted_nodes[0];
1368 faces_nodes_unique_id_index += item_nb_node;
1374 faces_nodes_unique_id_index = 0;
1375 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1376 const Integer n = item_nb_node;
1377 Int32 face_first_node_lid = faces_first_node_local_id[i_face];
1378 if (face_first_node_lid != NULL_ITEM_LOCAL_ID) {
1379 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
1380 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
1381 Face face = MeshUtils::getFaceFromNodesUniqueId(current_node, face_nodes_id);
1386 if (!m_is_parallel) {
1388 ostr() <<
"(Nodes:";
1389 for (
Integer z = 0; z < n; ++z)
1390 ostr() <<
' ' << face_nodes_id[z];
1391 ostr() <<
" - node_lid=" << current_node.localId() <<
")";
1392 String error_string =
"INTERNAL: MshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity.";
1393 if (!is_non_manifold)
1394 error_string = error_string +
"\n This errors may occur if the mesh is non-manifold."
1395 "\n See Arcane documentation to specify the mesh is a non manifold one.\n";
1400 faces_id.
add(face.localId());
1403 faces_nodes_unique_id_index += n;
1405 info(4) <<
"Adding " << faces_id.
size() <<
" faces from block index=" << block_index
1406 <<
" to group '" << face_group.
name() <<
"'";
1423 ArrayView<Int64> uids_view = _broadcastArray(pm, block_uids, uids, dest_rank);
1424 _addCellOrNodeGroupOnePart(uids_view, group_name, block_index, family, filter_invalid);
1431void MshParallelMeshReader::
1450 if (m_is_parallel || filter_invalid) {
1451 auto items_begin = items_lid.begin();
1452 Int64 new_size = std::remove(items_begin, items_lid.end(), NULL_ITEM_LOCAL_ID) - items_begin;
1453 items_lid.resize(new_size);
1456 info() <<
"Adding " << items_lid.size() <<
" items from block index=" << block_index
1457 <<
" to group '" << group_name <<
"' for family=" << family->
name();
1471void MshParallelMeshReader::
1475 String quote_mark =
"\"";
1476 Int32 nb_name = _getIntegerAndBroadcast();
1477 info() <<
"nb_physical_name=" << nb_name;
1481 for (
Int32 i = 0; i < nb_name; ++i) {
1482 Int32 dim = _getIntegerAndBroadcast();
1483 Int32 tag = _getIntegerAndBroadcast();
1485 if (dim < 0 || dim > 3)
1486 ARCANE_FATAL(
"Invalid value for physical name dimension dim={0}", dim);
1490 if (s.startsWith(quote_mark))
1492 if (s.endsWith(quote_mark))
1493 s = s.substring(0, s.length() - 1);
1494 m_mesh_info->physical_name_list.add(dim, tag, s);
1495 info(4) <<
"[PhysicalName] index=" << i <<
" dim=" << dim <<
" tag=" << tag <<
" name='" << s <<
"'";
1499 if (s !=
"$EndPhysicalNames")
1500 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
1538 IosFile* ios_file = m_ios_file.get();
1541 _getInt64ArrayAndBroadcast(nb_dim_item.
view());
1545 info() <<
"[Entities] nb_0d=" << nb_dim_item[0] <<
" nb_1d=" << nb_dim_item[1]
1546 <<
" nb_2d=" << nb_dim_item[2] <<
" nb_3d=" << nb_dim_item[3];
1553 for (
Int64 i = 0; i < nb_dim_item[0]; ++i) {
1556 Int32 tag = _getInt32();
1557 Real3 xyz = _getReal3();
1558 Int64 num_physical_tag = _getInt64();
1559 if (num_physical_tag > 1)
1560 ARCANE_FATAL(
"NotImplemented numPhysicalTag>1 (n={0}, index={1} xyz={2})",
1561 num_physical_tag, i, xyz);
1563 Int32 physical_tag = -1;
1564 if (num_physical_tag == 1)
1565 physical_tag = _getInt32();
1566 if (is_print_level1)
1567 info() <<
"[Entities] point tag=" << tag <<
" pos=" << xyz <<
" phys_tag=" << physical_tag;
1570 tag_info[1] = physical_tag;
1572 m_parallel_mng->broadcast(tag_info.
view(), m_master_io_rank);
1573 m_mesh_info->entities_nodes_list.add(MshEntitiesNodes(tag_info[0], tag_info[1]));
1579 for (
Int32 i_dim = 1; i_dim <= 3; ++i_dim)
1580 for (
Int32 i = 0; i < nb_dim_item[i_dim]; ++i)
1581 _readOneEntity(i_dim, i);
1592void MshParallelMeshReader::
1593_readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim)
1610 if (is_print_level1)
1611 info() <<
"[Entities] Reading entity dim=" << entity_dim <<
" index_in_dim=" << entity_index_in_dim;
1613 dim_and_tag_info.
add(entity_dim);
1615 Int32 tag = _getInt32();
1616 dim_and_tag_info.
add(tag);
1617 Real3 min_pos = _getReal3();
1618 Real3 max_pos = _getReal3();
1619 Int64 nb_physical_tag = _getInt64();
1620 dim_and_tag_info.
add(nb_physical_tag);
1621 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1622 Int32 physical_tag = _getInt32();
1623 dim_and_tag_info.
add(physical_tag);
1624 if (is_print_level2)
1625 info(4) <<
"[Entities] z=" << z <<
" physical_tag=" << physical_tag;
1628 Int64 nb_bounding_group = _getInt64();
1629 dim_and_tag_info.
add(nb_bounding_group);
1630 for (Int64 z = 0; z < nb_bounding_group; ++z) {
1631 Int32 boundary_tag = _getInt32();
1632 if (is_print_level2)
1633 info(4) <<
"[Entities] z=" << z <<
" boundary_tag=" << boundary_tag;
1635 if (is_print_level2)
1636 info(4) <<
"[Entities] dim=" << entity_dim <<
" tag=" << tag
1637 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
1638 <<
" nb_phys_tag=" << nb_physical_tag
1639 <<
" nb_bounding=" << nb_bounding_group;
1641 Int32 info_size = dim_and_tag_info.
size();
1642 m_parallel_mng->broadcast(ArrayView<Int32>(1, &info_size), m_master_io_rank);
1643 dim_and_tag_info.
resize(info_size);
1644 m_parallel_mng->broadcast(dim_and_tag_info.
view(), m_master_io_rank);
1647 Int32 dim = CheckedConvert::toInt32(dim_and_tag_info[0]);
1648 Int64 tag = dim_and_tag_info[1];
1649 Int64 nb_physical_tag = dim_and_tag_info[2];
1650 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1651 Int64 physical_tag = dim_and_tag_info[3 + z];
1652 if (is_print_level2)
1653 info(4) <<
"[Entities] adding info dim=" << entity_dim <<
" tag=" << tag
1654 <<
" physical_tag=" << physical_tag;
1655 m_mesh_info->entities_with_nodes_list[dim - 1].add(MshEntitiesWithNodes(dim, tag, physical_tag));
1685 Int64 nb_link = _getInt64AndBroadcast();
1686 info() <<
"[Periodic] nb_link=" << nb_link;
1692 MshPeriodicInfo& periodic_info = m_mesh_info->m_periodic_info;
1693 periodic_info.m_periodic_list.resize(nb_link);
1694 for (
Int64 ilink = 0; ilink < nb_link; ++ilink) {
1695 MshPeriodicOneInfo& one_info = periodic_info.m_periodic_list[ilink];
1697 _getInt32ArrayAndBroadcast(entity_info.
view());
1699 if (is_print_level1)
1700 info() <<
"[Periodic] link_index=" << ilink <<
" dim=" << entity_info[0] <<
" entity_tag=" << entity_info[1]
1701 <<
" entity_tag_master=" << entity_info[2];
1702 one_info.m_entity_dim = entity_info[0];
1703 one_info.m_entity_tag = entity_info[1];
1704 one_info.m_entity_tag_master = entity_info[2];
1706 Int64 num_affine = _getInt64AndBroadcast();
1707 if (is_print_level2)
1708 info() <<
"[Periodic] num_affine=" << num_affine;
1711 one_info.m_nb_corresponding_node = CheckedConvert::toInt32(_getInt64AndBroadcast());
1712 if (is_print_level1)
1713 info() <<
"[Periodic] nb_corresponding_node=" << one_info.m_nb_corresponding_node;
1716 if (is_print_level2)
1723 if (s !=
"$EndPeriodic")
1724 ARCANE_FATAL(
"found '{0}' and expected '$EndPeriodic'", s);
1737 constexpr Int32 MAX_SIZE = 128;
1740 Int32 read_size = CheckedConvert::toInt32(expected_bytes.
size());
1742 if (read_size >= MAX_SIZE)
1743 ARCANE_FATAL(
"local buffer is too small (size={0} max={1})", read_size, MAX_SIZE);
1744 IosFile* f = m_ios_file.get();
1746 f->binaryRead(bytes_to_read);
1747 s =
String(bytes_to_read);
1748 info() <<
"S=" << s;
1749 if (m_is_parallel) {
1750 m_parallel_mng->broadcastString(s, m_master_io_rank);
1758 if (s != expected_value)
1759 ARCANE_FATAL(
"found '{0}' and expected '{1}'", s, expected_value);
1766void MshParallelMeshReader::
1771 info() <<
"Reading 'msh' file in parallel";
1775 const int MSH_BINARY_TYPE = 1;
1778 Real version = ios_file->getReal();
1780 ARCANE_THROW(
IOException,
"Wrong msh file version '{0}'. Only version '4.1' is supported in parallel", version);
1781 Integer file_type = ios_file->getInteger();
1782 if (file_type == MSH_BINARY_TYPE)
1785 Int32 data_size = ios_file->getInteger();
1786 ARCANE_UNUSED(data_size);
1788 ARCANE_FATAL(
"Only 'size_t' of size '8' is allowed (current size is '{0}')", data_size);
1793 Int32 int_value_one = 0;
1795 if (int_value_one != 1)
1796 ARCANE_FATAL(
"Bad endianess for file. Read int as value '{0}' (expected=1)", int_value_one);
1802 if (!ios_file->lookForString(
"$EndMeshFormat"))
1812 if (next_line ==
"$PhysicalNames") {
1813 _readPhysicalNames();
1819 if (next_line ==
"$Entities") {
1824 if (next_line !=
"$Nodes")
1825 ARCANE_THROW(IOException,
"Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1831 if (ios_file && !ios_file->lookForString(
"$EndNodes"))
1835 if (ios_file && !ios_file->lookForString(
"$Elements"))
1841 if (ios_file && !ios_file->lookForString(
"$EndElements"))
1844 info() <<
"Computed mesh dimension = " << mesh_dimension;
1849 info() <<
"NextLine=" << next_line;
1855 if (next_line ==
"$Periodic") {
1868void MshParallelMeshReader::
1875 _addMshTypeInfo(MSH_PNT, ITI_Vertex);
1876 _addMshTypeInfo(MSH_LIN_2, ITI_Line2);
1877 _addMshTypeInfo(MSH_LIN_3, ITI_Line3);
1878 _addMshTypeInfo(MSH_TRI_3, ITI_Triangle3);
1879 _addMshTypeInfo(MSH_QUA_4, ITI_Quad4);
1880 _addMshTypeInfo(MSH_QUA_8, ITI_Quad8);
1881 _addMshTypeInfo(MSH_QUA_9, ITI_Quad9);
1882 _addMshTypeInfo(MSH_TET_4, ITI_Tetraedron4);
1883 _addMshTypeInfo(MSH_HEX_8, ITI_Hexaedron8);
1884 _addMshTypeInfo(MSH_PRI_6, ITI_Pentaedron6);
1885 _addMshTypeInfo(MSH_PRI_15, ITI_Pentaedron15);
1886 _addMshTypeInfo(MSH_PYR_5, ITI_Pyramid5);
1887 _addMshTypeInfo(MSH_PYR_13, ITI_Pyramid13);
1888 _addMshTypeInfo(MSH_TRI_6, ITI_Triangle6);
1889 _addMshTypeInfo(MSH_TRI_10, ITI_Triangle10);
1891 FixedArray<Int16, 10> x({ 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 });
1892 _addMshTypeInfo(MSH_TET_10, ITI_Tetraedron10, x.view());
1895 FixedArray<Int16, 20> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1896 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15 });
1897 _addMshTypeInfo(MSH_HEX_20, ITI_Hexaedron20, x.view());
1900 FixedArray<Int16, 27> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1901 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15,
1902 22, 23, 21, 24, 20, 25, 26 });
1903 _addMshTypeInfo(MSH_HEX_27, ITI_Hexaedron27, x.view());
1910void MshParallelMeshReader::
1918 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
1919 ItemTypeInfo* iti = item_type_mng->typeFromId(arcane_type);
1927mshToArcaneTypeInfo(
Int32 msh_type)
const
1931 if (tx.m_arcane_type_info)
1934 ARCANE_THROW(NotSupportedException,
"MSH type '{0}' is not supported in Arcane", msh_type);
1945 m_mesh_info = impl::MshMeshGenerationInfo::getReference(
mesh,
true);
1946 info() <<
"Trying to read in parallel 'msh' file '" << filename <<
"'"
1947 <<
" use_internal_partition=" << use_internal_partition;
1951 if (!use_internal_partition)
1953 m_parallel_mng = pm;
1974 m_master_io_rank = master_io_rank;
1980 info() <<
"Is file readable ?=" << is_readable;
1981 file_readable[0] = is_readable ? 1 : 0;
1983 error() <<
"Unable to read file '" << filename <<
"'";
1985 pm->broadcast(file_readable.
view(), master_io_rank);
1986 if (file_readable[0] == 0) {
1990 std::ifstream ifile;
1995 ifile.open(filename.
localstr(), ios::binary);
1998 m_ios_file = ios_file;
2000 if (IosFile::isEqualString(mesh_format_str,
"$MeshFormat")) {
2001 _readMeshFromFile();
2002 if (!use_internal_partition) {
2003 info() <<
"Synchronize groups and variables";
2004 mesh->synchronizeGroupsAndVariables();
2009 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
2017createMshParallelMeshReader(
ITraceMng* tm)
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Fonctions utilitaires sur le maillage.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable d'un tableau d'un type T.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
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.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
static ARCCORE_BASE_EXPORT std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Classe template pour convertir un type.
Tableau 1D de taille fixe.
constexpr __host__ __device__ ArrayView< T > view()
Vue modifiable sur le tableau.
constexpr __host__ __device__ SmallSpan< T, NbElement > span()
Vue modifiable sur le tableau.
Informations sur le type flottant.
Interface d'une famille d'entités.
virtual ItemGroup findGroup(const String &name) const =0
Recherche un groupe.
virtual String name() const =0
Nom de la famille.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
virtual Integer dimension()=0
Dimension du maillage (1D, 2D ou 3D).
eReturnType
Types des codes de retour d'une lecture ou écriture.
@ RTError
Erreur lors de l'opération.
@ RTOk
Opération effectuée avec succès.
virtual const MeshKind meshKind() const =0
Caractéristiques du maillage.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual IParallelMng * sequentialParallelMng()=0
Retourne un gestionnaire de parallélisme séquentiel.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
virtual void endAllocate()=0
Indique une fin d'allocation de mailles.
virtual void allocateCells(Integer nb_cell, Int64ConstArrayView cells_infos, bool one_alloc=true)=0
Allocation d'un maillage.
virtual void setDimension(Integer dim)=0
Positionne la dimension du maillage (1D, 2D ou 3D).
Interface du gestionnaire de traces.
Routines des Lecture/Ecriture d'un fichier.
Groupe d'entités de maillage.
const String & name() const
Nom du groupe.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Ajoute des entités.
Type d'une entité (Item).
Infos sur un type d'entité du maillage.
Integer nbLocalNode() const
Nombre de noeuds de l'entité
String typeName() const
Nom du type.
ItemTypeId itemTypeId() const
Numéro du type.
Gestionnaire des types d'entités d'un maillage.
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
bool isNonManifold() const
Vrai si la structure du maillage est eMeshCellDimensionKind::NonManifold.
Informations pour créer les entités d'un genre.
Informations pour créer les entités Arcane.
UniqueArray< Int64 > nodes_unique_id
UniqueId() des noeuds de ma partie.
std::unordered_map< Int64, Int32 > nodes_rank_map
Tableau associatif (uniqueId(),rang) auquel le noeud appartiendra.
UniqueArray< Real3 > nodes_coordinates
Coordonnées des noeuds de ma partie.
Informations de correspondance entre le type MSH et le type Arcane.
Lecteur de fichiers de maillage au format msh.
bool _getIsEndOfFileAndBroadcast()
Retourne true si on est à la fin du fichier.
Int32 m_verbosity_level
Niveau de verbosité
void _readPeriodic()
Lecture des informations périodiques.
Integer _readElementsFromFile()
Lecture des éléments (mailles,faces,...)
void _addCellOrNodeGroup(ArrayView< Int64 > block_uids, Int32 block_index, const String &group_name, IItemFamily *family, bool filter_invalid)
Ajoute des mailles ou noeuds au groupe group_name.
void _readAndCheck(const String &expected_value)
Tente de lire la valeur value.
UniqueArray< Int32 > m_parts_rank
Liste des rangs qui participent à la conservation des données.
void _readEntities()
Lecture des entités.
Int32 m_nb_part
Nombre de partitions pour la lecture des noeuds et blocs.
UniqueArray< MshToArcaneTypeInfo > m_msh_to_arcane_type_infos
Informations de conversion entre les types MSH et Arcane pour les entités.
eReturnType readMeshFromMshFile(IMesh *mesh, const String &filename, bool use_internal_partition) override
Lit le maillage contenu dans le fichier filename et le construit dans mesh.
void _readNodesFromFile()
Lecture des noeuds du maillage.
void _setNodesCoordinates()
Positionne les coordonnées des noeuds.
bool m_is_binary
Vrai si le format est binaire.
void _addFaceGroup(const MshElementBlock &block, const String &group_name)
Ajoute des faces au groupe group_name.
void _computeNodesPartition()
void _readOneElementBlock(MshElementBlock &block)
Lit un bloc d'entité de type 'Element'.
String _getNextLineAndBroadcast()
Lis la valeur de la prochaine ligne et la broadcast aux autres rangs.
Vue sur les informations des noeuds.
Classe utilitaire pour réordonner les noeuds d'une entité.
Exception lorsqu'une opération n'est pas supportée.
Classe gérant un vecteur de réel de dimension 3.
Référence à une instance.
InstanceType * get() const
Instance associée ou nullptr si aucune.
Tableau 1D de données avec buffer pré-alloué sur la pile.
Vue d'un tableau d'éléments de type T.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Vue d'un tableau d'éléments de type T.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Span< const Byte > bytes() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Classe d'accès aux traces.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
Vecteur 1D de données avec sémantique par valeur (style STL).
Infos pour les entités 0D.
Infos pour les entités 1D, 2D et 3D.
Informations sur la périodicité
UniqueArray< double > m_affine_values
Liste des valeurs affines.
UniqueArray< Int64 > m_corresponding_nodes
Liste de couples (uniqueId noeud esclave, unique() noeud maître)
Infos sur un nom physique.
Informations d'un maillage issu du format 'msh'.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
ItemGroupT< Face > FaceGroup
Groupe de faces.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
@ ReduceSum
Somme des valeurs.
@ ReduceMin
Minimum des valeurs.
@ ReduceMax
Maximum des valeurs.
constexpr __host__ __device__ bool isNearlyEqual(const _Type &a, const _Type &b)
Teste si deux valeurs sont à un peu près égales. Pour les types entiers, cette fonction est équivalen...
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
std::int16_t Int16
Type entier signé sur 16 bits.
double Real
Type représentant un réel.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.
Infos d'un bloc pour $Elements pour la version 4.
ItemTypeId item_type
Type Arcane de l'entité
UniqueArray< Int64 > connectivities
< Liste des uniqueId() du bloc
Int64 nb_entity
Nombre d'entités du bloc.
Int32 item_nb_node
Nombre de noeuds de l'entité.
SmallSpan< const Int16 > reorder_infos
Si non vide, contient les indirections pour la renumérotation.
Int32 dimension
Dimension de l'entité
Int32 index
Index du bloc dans la liste.
Infos d'un bloc pour $Nodes.
Int32 index
Index du bloc dans la liste.
Int32 entity_dim
Dimension de l'entité associée.
Int64 index_in_allocation_info
Index dans MshMeshAllocateInfo des noeuds de ce bloc.
Int32 nb_node
Nombre d'entités du bloc.
Real x
première composante du triplet