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::
317 s = f->getNextLine();
321 info(4) <<
"BroadcastNextLine: " << s;
322 m_parallel_mng->broadcastString(s, m_master_io_rank);
324 info(4) <<
"GetNextLine: " << s;
338 Int32 is_end_int = 0;
340 is_end_int = f->isEnd() ? 1 : 0;
341 info(4) <<
"IsEndOfFile_Master: " << is_end_int;
345 info(4) <<
"IsEndOfFile: " << is_end_int;
346 m_parallel_mng->broadcast(
ArrayView<Int32>(1, &is_end_int), m_master_io_rank);
348 bool is_end = (is_end_int != 0);
349 info(4) <<
"IsEnd: " << is_end;
358_getIntegerAndBroadcast()
363 v[0] = f->getInteger();
365 m_parallel_mng->broadcast(v.
view(), m_master_io_rank);
373Int64 MshParallelMeshReader::
374_getInt64AndBroadcast()
376 IosFile* f = m_ios_file.get();
377 FixedArray<Int64, 1> v;
381 m_parallel_mng->broadcast(v.view(), m_master_io_rank);
389void MshParallelMeshReader::
392 IosFile* f = m_ios_file.get();
395 f->binaryRead(values);
398 for (
Int64& v : values)
403 m_parallel_mng->broadcast(values, m_master_io_rank);
409void MshParallelMeshReader::
412 IosFile* f = m_ios_file.get();
415 f->binaryRead(values);
418 for (
Int32& v : values)
423 m_parallel_mng->broadcast(values, m_master_io_rank);
429void MshParallelMeshReader::
432 IosFile* f = m_ios_file.get();
435 f->binaryRead(values);
438 for (
double& v : values)
443 m_parallel_mng->broadcast(values, m_master_io_rank);
449Real3 MshParallelMeshReader::
452 IosFile* f = m_ios_file.get();
456 f->binaryRead(SmallSpan<Real3>(&v, 1));
459 Real x = f->getReal();
460 Real y = f->getReal();
461 Real z = f->getReal();
470Int32 MshParallelMeshReader::
473 IosFile* f = m_ios_file.get();
477 f->binaryRead(SmallSpan<Int32>(&v, 1));
486Int64 MshParallelMeshReader::
489 IosFile* f = m_ios_file.get();
493 f->binaryRead(SmallSpan<Int64>(&v, 1));
502void MshParallelMeshReader::
505 if (m_ios_file.get())
506 m_ios_file->goToEndOfLine();
517 Real min_value = -max_value;
518 Real3 min_box(max_value, max_value, max_value);
519 Real3 max_box(min_value, min_value, min_value);
520 const Int64 nb_node = m_mesh_allocate_info.nodes_coordinates.largeSize();
521 for (
Real3 pos : m_mesh_allocate_info.nodes_coordinates) {
535 Real min_x = min_box.
x;
536 Real max_x = max_box.
x;
540 info() <<
"MIN_MAX_X=" << global_min_x <<
" " << global_max_x;
546 for (
Int64 i = 0; i < nb_node; ++i) {
547 Int32 part =
static_cast<Int32>((m_mesh_allocate_info.nodes_coordinates[i].x - global_min_x) / diff_v);
548 part = std::clamp(part, 0,
m_nb_part - 1);
549 nodes_part[i] = part;
554 for (
Int64 i = 0; i < nb_node; ++i) {
556 Int64 uid = m_mesh_allocate_info.nodes_unique_id[i];
557 ++nb_node_per_rank[rank];
558 m_mesh_allocate_info.nodes_rank_map.insert(std::make_pair(uid, rank));
561 info() <<
"NB_NODE_PER_RANK=" << nb_node_per_rank;
595 _getInt64ArrayAndBroadcast(nodes_info.
view());
597 Int64 nb_node_block =
static_cast<Int32>(nodes_info[0]);
598 Int64 total_nb_node = nodes_info[1];
599 Int64 min_node_tag = nodes_info[2];
600 Int64 max_node_tag = nodes_info[3];
605 if (total_nb_node < 0)
608 info() <<
"[Nodes] nb_node_block=" << nb_node_block
609 <<
" total_nb_node=" << total_nb_node
610 <<
" min_tag=" << min_node_tag
611 <<
" max_tag=" << max_node_tag
613 <<
" nb_rank=" << m_parallel_mng->commSize();
616 node_blocks.
resize(nb_node_block);
618 for (
Int32 i = 0; i < nb_node_block; ++i) {
620 node_block.
index = i;
621 _readNodesOneEntity(node_block);
633void MshParallelMeshReader::
634_readNodesOneEntity(MshNodeBlock& node_block)
644 _getInt32ArrayAndBroadcast(entity_infos.
view());
645 Int32 nb_node2 = CheckedConvert::toInt32(_getInt64AndBroadcast());
651 Int32 entity_dim = entity_infos[0];
652 node_block.entity_dim = entity_dim;
654 Int32 entity_tag = entity_infos[1];
655 node_block.entity_tag = entity_tag;
658 node_block.nb_node = nb_node2;
660 Int32 parametric_coordinates = entity_infos[2];
662 info(4) <<
"[Nodes] index=" << node_block.index <<
" entity_dim=" << entity_dim <<
" entity_tag=" << entity_tag
663 <<
" parametric=" << parametric_coordinates
664 <<
" nb_node2=" << nb_node2;
666 if (parametric_coordinates != 0)
680 info(4) <<
"Reading UIDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
681 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
682 nodes_uids.
resize(nb_to_read);
689 ios_file->binaryRead(nodes_uids.
view());
692 for (
Integer i = 0; i < nb_to_read; ++i) {
694 nodes_uids[i] = ios_file->getInt64();
698 if (dest_rank != m_master_io_rank) {
699 pm->send(nodes_uids, dest_rank);
702 else if (my_rank == dest_rank) {
703 pm->
recv(nodes_uids, m_master_io_rank);
707 if (my_rank == dest_rank) {
708 m_mesh_allocate_info.nodes_unique_id.addRange(nodes_uids);
709 node_block.nb_node = nodes_uids.
size();
717 info(4) <<
"Reading COORDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
718 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
719 nodes_coordinates.
resize(nb_to_read);
726 ios_file->binaryRead(nodes_coordinates.
view());
729 for (
Integer i = 0; i < nb_to_read; ++i) {
730 nodes_coordinates[i] = _getReal3();
734 if (dest_rank != m_master_io_rank) {
735 pm->send(nodes_coordinates, dest_rank);
738 else if (my_rank == dest_rank) {
739 pm->
recv(nodes_coordinates, m_master_io_rank);
743 if (my_rank == dest_rank) {
744 m_mesh_allocate_info.nodes_coordinates.addRange(nodes_coordinates);
761 IosFile* ios_file = m_ios_file.get();
770 info() <<
"Reading block nb_entity=" << nb_entity_in_block <<
" item_nb_node=" << item_nb_node;
778 const Int64 nb_to_read = _interval(i_part,
m_nb_part, nb_entity_in_block).second;
782 info(4) <<
"Reading block part i_part=" << i_part
783 <<
" nb_to_read=" << nb_to_read <<
" dest_rank=" << dest_rank;
785 const Int64 nb_uid = nb_to_read;
786 const Int64 nb_connectivity = nb_uid * item_nb_node;
787 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
789 connectivities.
resize(nb_connectivity);
793 Int64 nb_to_read = nb_uid * (item_nb_node + 1);
794 tmp_uid_and_connectivities.
resize(nb_to_read);
795 ios_file->binaryRead(tmp_uid_and_connectivities.
view());
797 for (
Int64 i = 0; i < nb_uid; ++i) {
798 Int64 item_unique_id = tmp_uid_and_connectivities[index];
800 uids[i] = item_unique_id;
801 for (
Int32 j = 0; j < item_nb_node; ++j) {
802 connectivities[(i * item_nb_node) + j] = tmp_uid_and_connectivities[index];
809 for (
Int64 i = 0; i < nb_uid; ++i) {
810 Int64 item_unique_id = ios_file->getInt64();
811 uids[i] = item_unique_id;
812 for (
Int32 j = 0; j < item_nb_node; ++j)
813 connectivities[(i * item_nb_node) + j] = ios_file->getInt64();
816 if (dest_rank != m_master_io_rank) {
817 pm->send(uids, dest_rank);
818 pm->send(connectivities, dest_rank);
821 else if (my_rank == dest_rank) {
822 pm->
recv(uids, m_master_io_rank);
823 pm->
recv(connectivities, m_master_io_rank);
825 if (my_rank == dest_rank) {
866 IosFile* ios_file = m_ios_file.get();
872 _getInt64ArrayAndBroadcast(elements_info.
view());
874 Int64 nb_block = elements_info[0];
875 Int64 number_of_elements = elements_info[1];
876 Int64 min_element_tag = elements_info[2];
877 Int64 max_element_tag = elements_info[3];
882 info() <<
"[Elements] nb_block=" << nb_block
883 <<
" nb_elements=" << number_of_elements
884 <<
" min_element_tag=" << min_element_tag
885 <<
" max_element_tag=" << max_element_tag;
887 if (number_of_elements < 0)
905 _getInt32ArrayAndBroadcast(block_info.
view());
907 Int32 entity_dim = block_info[0];
908 Int32 entity_tag = block_info[1];
909 Int32 entity_type = block_info[2];
910 Int64 nb_entity_in_block = _getInt64AndBroadcast();
918 info() <<
"[Elements] index=" << block.index <<
" entity_dim=" << entity_dim
919 <<
" entity_tag=" << entity_tag
920 <<
" msh_entity_type=" << entity_type <<
" nb_in_block=" << nb_entity_in_block
921 <<
" arcane_item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
923 block.nb_entity = nb_entity_in_block;
924 block.item_type = item_type;
925 block.item_nb_node = item_nb_node;
926 block.dimension = entity_dim;
927 block.entity_tag = entity_tag;
928 block.reorder_infos = msh_tinfo.m_reorder_infos;
929 if (entity_type == MSH_PNT) {
934 Int64 item_unique_id = NULL_ITEM_UNIQUE_ID;
936 [[maybe_unused]]
Int64 unused_id = _getInt64();
937 item_unique_id = _getInt64();
939 info() <<
"Adding unique node uid=" << item_unique_id;
943 block.uids.add(item_unique_id);
959 mesh_dimension =
math::max(mesh_dimension, block.dimension);
960 if (mesh_dimension < 0)
961 ARCANE_FATAL(
"Invalid computed mesh dimension '{0}'", mesh_dimension);
962 if (mesh_dimension != 2 && mesh_dimension != 3)
964 info() <<
"Computed mesh dimension = " << mesh_dimension;
966 bool allow_multi_dim_cell = m_mesh->meshKind().isNonManifold();
967 bool use_experimental_type_for_cell =
false;
968 if (allow_multi_dim_cell) {
970 use_experimental_type_for_cell =
true;
972 use_experimental_type_for_cell = (v.value() != 0);
974 info() <<
"Use experimental cell type?=" << use_experimental_type_for_cell;
975 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
977 const Int32 block_dim = block.dimension;
980 info() <<
"Reading block dim=" << block_dim <<
" type_name=" << item_type_name;
981 if (block_dim == mesh_dimension)
982 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
983 else if (allow_multi_dim_cell) {
986 bool use_sub_dim_cell =
false;
987 if (mesh_dimension == 3 && (block_dim == 2 || block_dim == 1))
989 use_sub_dim_cell =
true;
990 else if (mesh_dimension == 2 && block_dim == 1)
992 use_sub_dim_cell =
true;
993 if (!use_experimental_type_for_cell)
994 use_sub_dim_cell =
false;
995 if (use_sub_dim_cell) {
998 if (mesh_dimension == 3) {
999 if (block.item_type == IT_Triangle3)
1000 block.item_type =
ItemTypeId(IT_Cell3D_Triangle3);
1001 else if (block.item_type == IT_Triangle6)
1002 block.item_type =
ItemTypeId(ITI_Cell3D_Triangle6);
1003 else if (block.item_type == IT_Quad4)
1004 block.item_type =
ItemTypeId(IT_Cell3D_Quad4);
1005 else if (block.item_type == IT_Quad8)
1006 block.item_type =
ItemTypeId(IT_Cell3D_Quad8);
1007 else if (block.item_type == IT_Quad9)
1008 block.item_type =
ItemTypeId(IT_Cell3D_Quad9);
1009 else if (block.item_type == IT_Line2)
1010 block.item_type =
ItemTypeId(IT_Cell3D_Line2);
1011 else if (block.item_type == IT_Line3)
1012 block.item_type =
ItemTypeId(IT_Cell3D_Line3);
1014 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 3D mesh", item_type_name);
1016 else if (mesh_dimension == 2) {
1017 if (block.item_type == IT_Line2)
1019 else if (block.item_type == IT_Line3)
1022 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 2D mesh", item_type_name);
1024 block.is_built_as_cells =
true;
1025 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
1030 return mesh_dimension;
1044 if (my_rank != dest_rank) {
1045 work_values.
resize(size);
1046 view = work_values.
view();
1048 pm->broadcast(view, dest_rank);
1062 const Int32 my_rank = pm->commRank();
1065 if (dest_rank == my_rank)
1066 size = values.size();
1068 return _broadcastArrayWithSize(pm, values, work_values, dest_rank, size);
1076void MshParallelMeshReader::
1077_computeOwnItems(MshElementBlock& block, MshItemKindInfo& item_kind_info,
bool is_generate_uid)
1081 IParallelMng* pm = m_parallel_mng;
1082 const Int32 my_rank = pm->commRank();
1085 const ItemTypeId item_type = block.item_type;
1086 const Int32 item_nb_node = block.item_nb_node;
1088 UniqueArray<Int64> connectivities;
1089 UniqueArray<Int64> uids;
1090 UniqueArray<Int32> nodes_rank;
1092 SmallSpan<const Int16> reorder_infos = block.reorder_infos;
1093 bool has_reorder_info = !reorder_infos.empty();
1095 if (is_print_level1)
1096 info() <<
"Compute own items block_index=" << block.index <<
" nb_part=" << nb_part
1097 <<
" has_reorder?=" << has_reorder_info;
1099 SmallArray<Int64> arcane_reordered_uids;
1100 if (has_reorder_info)
1101 arcane_reordered_uids.resize(item_nb_node);
1102 for (
Int32 i_part = 0; i_part < nb_part; ++i_part) {
1105 ArrayView<Int64> connectivities_view = _broadcastArray(pm, block.connectivities.view(), connectivities, dest_rank);
1106 ArrayView<Int64> uids_view = _broadcastArray(pm, block.uids.view(), uids, dest_rank);
1108 Int32 nb_item = uids_view.size();
1109 nodes_rank.resize(nb_item);
1110 nodes_rank.fill(-1);
1115 for (
Int32 i = 0; i < nb_item; ++i) {
1116 Int64 first_node_uid = connectivities_view[i * item_nb_node];
1117 auto x = m_mesh_allocate_info.nodes_rank_map.find(first_node_uid);
1118 if (x == m_mesh_allocate_info.nodes_rank_map.end())
1121 Int32 rank = x->second;
1122 nodes_rank[i] = rank;
1125 for (
Int32 i = 0; i < nb_item; ++i) {
1126 const Int32 rank = nodes_rank[i];
1127 if (rank != my_rank)
1132 ConstArrayView<Int64> v = connectivities_view.subView(i * item_nb_node, item_nb_node);
1133 Int64 uid = uids_view[i];
1134 if (is_generate_uid)
1136 uid = NULL_ITEM_UNIQUE_ID;
1137 if (has_reorder_info) {
1140 for (
Int32 zz = 0; zz < item_nb_node; ++zz)
1141 arcane_reordered_uids[zz] = v[reorder_infos[zz]];
1142 v = arcane_reordered_uids.view();
1144 item_kind_info.addItem(item_type, uid, v);
1173 const IItemFamily* node_family = m_mesh->nodeFamily();
1177 ConstArrayView<Int64> uids = _broadcastArray(pm, m_mesh_allocate_info.nodes_unique_id.view(), uids_storage, dest_rank);
1178 ConstArrayView<Real3> coords = _broadcastArray(pm, m_mesh_allocate_info.nodes_coordinates.view(), coords_storage, dest_rank);
1181 local_ids.
resize(nb_item);
1187 for (
Int32 i = 0; i < nb_item; ++i) {
1188 NodeLocalId nid(local_ids[i]);
1190 nodes_coord_var[nid] = coords[i];
1198void MshParallelMeshReader::
1202 Integer nb_elements = m_mesh_allocate_info.cells_infos.nb_item;
1203 info() <<
"nb_of_elements=cells_type.size()=" << nb_elements;
1204 Integer nb_cell_node = m_mesh_allocate_info.cells_infos.items_infos.
size();
1205 info() <<
"nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
1208 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
1210 info() <<
"## Allocating ##";
1211 pmesh->
allocateCells(nb_elements, m_mesh_allocate_info.cells_infos.items_infos,
false);
1212 info() <<
"## Ending ##";
1214 info() <<
"## Done ##";
1220void MshParallelMeshReader::
1223 IMesh* mesh = m_mesh;
1225 Int32 face_dim = mesh_dim - 1;
1226 UniqueArray<MshEntitiesWithNodes> entity_list;
1227 UniqueArray<MshPhysicalName> physical_name_list;
1228 IItemFamily* node_family = mesh->nodeFamily();
1230 for (MshElementBlock& block : m_mesh_allocate_info.element_blocks) {
1231 entity_list.clear();
1232 physical_name_list.clear();
1233 Int32 block_index = block.index;
1234 Int32 block_dim = block.dimension;
1237 Int64 block_entity_tag = block.entity_tag;
1238 if (block_entity_tag < 0) {
1239 info(5) <<
"[Groups] Skipping block index=" << block_index <<
" because it has no entity";
1242 if (block_dim == 0) {
1243 const MshEntitiesNodes* entity = m_mesh_info->findNodeEntities(block_entity_tag);
1245 info(5) <<
"[Groups] Skipping block index=" << block_index
1246 <<
" because entity tag is invalid";
1249 Int64 entity_physical_tag = entity->physicalTag();
1250 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1251 physical_name_list.add(physical_name);
1254 m_mesh_info->findEntities(block_dim, block_entity_tag, entity_list);
1255 for (
const MshEntitiesWithNodes& x : entity_list) {
1256 Int64 entity_physical_tag = x.physicalTag();
1257 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1258 physical_name_list.add(physical_name);
1261 for (
const MshPhysicalName& physical_name : physical_name_list) {
1262 if (physical_name.isNull()) {
1263 info(5) <<
"[Groups] Skipping block index=" << block_index
1264 <<
" because entity physical tag is invalid";
1267 String group_name = physical_name.name();
1268 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
1269 <<
" name='" << group_name <<
"' built_as_cells=" << block.is_built_as_cells;
1270 if (block_dim == mesh_dim || block.is_built_as_cells) {
1273 else if (block_dim == face_dim) {
1286 UniqueArray<Int64>& nodes_uids = m_mesh_allocate_info.nodes_unique_id;
1288 for (
const MshNodeBlock& block : m_mesh_allocate_info.node_blocks) {
1289 ArrayView<Int64> block_uids = nodes_uids.subView(block.index_in_allocation_info, block.nb_node);
1290 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block.entity_dim, block.entity_tag);
1291 String group_name = physical_name.name();
1292 info(4) <<
"NodeBlock name=" << group_name <<
" index=" << block.index
1293 <<
" index_in_allocation=" << block.index_in_allocation_info
1294 <<
" nb_node=" << block.nb_node;
1303 if (!group_name.null())
1323 _addFaceGroupOnePart(block, connectivities_view, group_name);
1330void MshParallelMeshReader::
1332 const String& group_name)
1335 const Int32 item_nb_node = block.item_nb_node;
1336 const Int32 block_index = block.index;
1338 const Int32 nb_entity = connectivities.
size() / item_nb_node;
1342 FaceGroup face_group =
mesh->faceFamily()->findGroup(group_name,
true);
1347 const Int32 face_nb_node = nb_entity * item_nb_node;
1352 Integer faces_nodes_unique_id_index = 0;
1365 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1366 for (
Integer z = 0; z < item_nb_node; ++z)
1367 orig_nodes_id[z] = connectivities[faces_nodes_unique_id_index + z];
1368 m_nodes_reorderer.reorder(type_id, orig_nodes_id);
1370 for (
Integer z = 0; z < item_nb_node; ++z)
1371 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = sorted_nodes[z];
1372 faces_first_node_unique_id[i_face] = sorted_nodes[0];
1373 faces_nodes_unique_id_index += item_nb_node;
1379 faces_nodes_unique_id_index = 0;
1380 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1381 const Integer n = item_nb_node;
1382 Int32 face_first_node_lid = faces_first_node_local_id[i_face];
1383 if (face_first_node_lid != NULL_ITEM_LOCAL_ID) {
1384 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
1385 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
1386 Face face = MeshUtils::getFaceFromNodesUniqueId(current_node, face_nodes_id);
1391 if (!m_is_parallel) {
1393 ostr() <<
"(Nodes:";
1394 for (
Integer z = 0; z < n; ++z)
1395 ostr() <<
' ' << face_nodes_id[z];
1396 ostr() <<
" - node_lid=" << current_node.localId() <<
")";
1397 String error_string =
"INTERNAL: MshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity.";
1398 if (!is_non_manifold)
1399 error_string = error_string +
"\n This errors may occur if the mesh is non-manifold."
1400 "\n See Arcane documentation to specify the mesh is a non manifold one.\n";
1405 faces_id.
add(face.localId());
1408 faces_nodes_unique_id_index += n;
1410 info(4) <<
"Adding " << faces_id.
size() <<
" faces from block index=" << block_index
1411 <<
" to group '" << face_group.
name() <<
"'";
1429 ArrayView<Int64> uids_view = _broadcastArray(pm, block_uids, uids, dest_rank);
1430 _addCellOrNodeGroupOnePart(uids_view, group_name, block_index, family, filter_invalid);
1437void MshParallelMeshReader::
1456 if (m_is_parallel || filter_invalid) {
1457 auto items_begin = items_lid.begin();
1458 Int64 new_size = std::remove(items_begin, items_lid.end(), NULL_ITEM_LOCAL_ID) - items_begin;
1459 items_lid.resize(new_size);
1462 info() <<
"Adding " << items_lid.size() <<
" items from block index=" << block_index
1463 <<
" to group '" << group_name <<
"' for family=" << family->
name();
1477void MshParallelMeshReader::
1481 String quote_mark =
"\"";
1482 Int32 nb_name = _getIntegerAndBroadcast();
1483 info() <<
"nb_physical_name=" << nb_name;
1487 for (
Int32 i = 0; i < nb_name; ++i) {
1488 Int32 dim = _getIntegerAndBroadcast();
1489 Int32 tag = _getIntegerAndBroadcast();
1491 if (dim < 0 || dim > 3)
1492 ARCANE_FATAL(
"Invalid value for physical name dimension dim={0}", dim);
1496 if (s.startsWith(quote_mark))
1498 if (s.endsWith(quote_mark))
1499 s = s.substring(0, s.length() - 1);
1500 m_mesh_info->physical_name_list.add(dim, tag, s);
1501 info(4) <<
"[PhysicalName] index=" << i <<
" dim=" << dim <<
" tag=" << tag <<
" name='" << s <<
"'";
1505 if (s !=
"$EndPhysicalNames")
1506 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
1545 IosFile* ios_file = m_ios_file.get();
1548 _getInt64ArrayAndBroadcast(nb_dim_item.
view());
1552 info() <<
"[Entities] nb_0d=" << nb_dim_item[0] <<
" nb_1d=" << nb_dim_item[1]
1553 <<
" nb_2d=" << nb_dim_item[2] <<
" nb_3d=" << nb_dim_item[3];
1560 for (
Int64 i = 0; i < nb_dim_item[0]; ++i) {
1563 Int32 tag = _getInt32();
1564 Real3 xyz = _getReal3();
1565 Int64 num_physical_tag = _getInt64();
1566 if (num_physical_tag > 1)
1567 ARCANE_FATAL(
"NotImplemented numPhysicalTag>1 (n={0}, index={1} xyz={2})",
1568 num_physical_tag, i, xyz);
1570 Int32 physical_tag = -1;
1571 if (num_physical_tag == 1)
1572 physical_tag = _getInt32();
1573 if (is_print_level1)
1574 info() <<
"[Entities] point tag=" << tag <<
" pos=" << xyz <<
" phys_tag=" << physical_tag;
1577 tag_info[1] = physical_tag;
1579 m_parallel_mng->broadcast(tag_info.
view(), m_master_io_rank);
1580 m_mesh_info->entities_nodes_list.add(MshEntitiesNodes(tag_info[0], tag_info[1]));
1586 for (
Int32 i_dim = 1; i_dim <= 3; ++i_dim)
1587 for (
Int32 i = 0; i < nb_dim_item[i_dim]; ++i)
1588 _readOneEntity(i_dim, i);
1599void MshParallelMeshReader::
1600_readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim)
1617 if (is_print_level1)
1618 info() <<
"[Entities] Reading entity dim=" << entity_dim <<
" index_in_dim=" << entity_index_in_dim;
1620 dim_and_tag_info.
add(entity_dim);
1622 Int32 tag = _getInt32();
1623 dim_and_tag_info.
add(tag);
1624 Real3 min_pos = _getReal3();
1625 Real3 max_pos = _getReal3();
1626 Int64 nb_physical_tag = _getInt64();
1627 dim_and_tag_info.
add(nb_physical_tag);
1628 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1629 Int32 physical_tag = _getInt32();
1630 dim_and_tag_info.
add(physical_tag);
1631 if (is_print_level2)
1632 info(4) <<
"[Entities] z=" << z <<
" physical_tag=" << physical_tag;
1635 Int64 nb_bounding_group = _getInt64();
1636 dim_and_tag_info.
add(nb_bounding_group);
1637 for (Int64 z = 0; z < nb_bounding_group; ++z) {
1638 Int32 boundary_tag = _getInt32();
1639 if (is_print_level2)
1640 info(4) <<
"[Entities] z=" << z <<
" boundary_tag=" << boundary_tag;
1642 if (is_print_level2)
1643 info(4) <<
"[Entities] dim=" << entity_dim <<
" tag=" << tag
1644 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
1645 <<
" nb_phys_tag=" << nb_physical_tag
1646 <<
" nb_bounding=" << nb_bounding_group;
1648 Int32 info_size = dim_and_tag_info.
size();
1649 m_parallel_mng->broadcast(ArrayView<Int32>(1, &info_size), m_master_io_rank);
1650 dim_and_tag_info.
resize(info_size);
1651 m_parallel_mng->broadcast(dim_and_tag_info.
view(), m_master_io_rank);
1654 Int32 dim = CheckedConvert::toInt32(dim_and_tag_info[0]);
1655 Int64 tag = dim_and_tag_info[1];
1656 Int64 nb_physical_tag = dim_and_tag_info[2];
1657 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1658 Int64 physical_tag = dim_and_tag_info[3 + z];
1659 if (is_print_level2)
1660 info(4) <<
"[Entities] adding info dim=" << entity_dim <<
" tag=" << tag
1661 <<
" physical_tag=" << physical_tag;
1662 m_mesh_info->entities_with_nodes_list[dim - 1].add(MshEntitiesWithNodes(dim, tag, physical_tag));
1693 Int64 nb_link = _getInt64AndBroadcast();
1694 info() <<
"[Periodic] nb_link=" << nb_link;
1700 MshPeriodicInfo& periodic_info = m_mesh_info->m_periodic_info;
1701 periodic_info.m_periodic_list.resize(nb_link);
1702 for (
Int64 ilink = 0; ilink < nb_link; ++ilink) {
1703 MshPeriodicOneInfo& one_info = periodic_info.m_periodic_list[ilink];
1705 _getInt32ArrayAndBroadcast(entity_info.
view());
1707 if (is_print_level1)
1708 info() <<
"[Periodic] link_index=" << ilink <<
" dim=" << entity_info[0] <<
" entity_tag=" << entity_info[1]
1709 <<
" entity_tag_master=" << entity_info[2];
1710 one_info.m_entity_dim = entity_info[0];
1711 one_info.m_entity_tag = entity_info[1];
1712 one_info.m_entity_tag_master = entity_info[2];
1714 Int64 num_affine = _getInt64AndBroadcast();
1715 if (is_print_level2)
1716 info() <<
"[Periodic] num_affine=" << num_affine;
1719 one_info.m_nb_corresponding_node = CheckedConvert::toInt32(_getInt64AndBroadcast());
1720 if (is_print_level1)
1721 info() <<
"[Periodic] nb_corresponding_node=" << one_info.m_nb_corresponding_node;
1724 if (is_print_level2)
1731 if (s !=
"$EndPeriodic")
1732 ARCANE_FATAL(
"found '{0}' and expected '$EndPeriodic'", s);
1746 constexpr Int32 MAX_SIZE = 128;
1749 Int32 read_size = CheckedConvert::toInt32(expected_bytes.
size());
1751 if (read_size >= MAX_SIZE)
1752 ARCANE_FATAL(
"local buffer is too small (size={0} max={1})", read_size, MAX_SIZE);
1753 IosFile* f = m_ios_file.get();
1755 f->binaryRead(bytes_to_read);
1756 s =
String(bytes_to_read);
1757 info() <<
"S=" << s;
1758 if (m_is_parallel) {
1759 m_parallel_mng->broadcastString(s, m_master_io_rank);
1767 if (s != expected_value)
1768 ARCANE_FATAL(
"found '{0}' and expected '{1}'", s, expected_value);
1775void MshParallelMeshReader::
1780 info() <<
"Reading 'msh' file in parallel";
1784 const int MSH_BINARY_TYPE = 1;
1787 Real version = ios_file->getReal();
1789 ARCANE_THROW(
IOException,
"Wrong msh file version '{0}'. Only version '4.1' is supported in parallel", version);
1790 Integer file_type = ios_file->getInteger();
1791 if (file_type == MSH_BINARY_TYPE)
1794 Int32 data_size = ios_file->getInteger();
1795 ARCANE_UNUSED(data_size);
1797 ARCANE_FATAL(
"Only 'size_t' of size '8' is allowed (current size is '{0}')", data_size);
1802 Int32 int_value_one = 0;
1804 if (int_value_one != 1)
1805 ARCANE_FATAL(
"Bad endianess for file. Read int as value '{0}' (expected=1)", int_value_one);
1811 if (!ios_file->lookForString(
"$EndMeshFormat"))
1821 if (next_line ==
"$PhysicalNames") {
1822 _readPhysicalNames();
1828 if (next_line ==
"$Entities") {
1833 if (next_line !=
"$Nodes")
1834 ARCANE_THROW(IOException,
"Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1840 if (ios_file && !ios_file->lookForString(
"$EndNodes"))
1844 if (ios_file && !ios_file->lookForString(
"$Elements"))
1850 if (ios_file && !ios_file->lookForString(
"$EndElements"))
1853 info() <<
"Computed mesh dimension = " << mesh_dimension;
1858 info() <<
"NextLine=" << next_line;
1864 if (next_line ==
"$Periodic") {
1877void MshParallelMeshReader::
1884 _addMshTypeInfo(MSH_PNT, ITI_Vertex);
1885 _addMshTypeInfo(MSH_LIN_2, ITI_Line2);
1886 _addMshTypeInfo(MSH_LIN_3, ITI_Line3);
1887 _addMshTypeInfo(MSH_TRI_3, ITI_Triangle3);
1888 _addMshTypeInfo(MSH_QUA_4, ITI_Quad4);
1889 _addMshTypeInfo(MSH_QUA_8, ITI_Quad8);
1890 _addMshTypeInfo(MSH_QUA_9, ITI_Quad9);
1891 _addMshTypeInfo(MSH_TET_4, ITI_Tetraedron4);
1892 _addMshTypeInfo(MSH_HEX_8, ITI_Hexaedron8);
1893 _addMshTypeInfo(MSH_PRI_6, ITI_Pentaedron6);
1894 _addMshTypeInfo(MSH_PRI_15, ITI_Pentaedron15);
1895 _addMshTypeInfo(MSH_PYR_5, ITI_Pyramid5);
1896 _addMshTypeInfo(MSH_PYR_13, ITI_Pyramid13);
1897 _addMshTypeInfo(MSH_TRI_6, ITI_Triangle6);
1898 _addMshTypeInfo(MSH_TRI_10, ITI_Triangle10);
1900 FixedArray<Int16, 10> x({ 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 });
1901 _addMshTypeInfo(MSH_TET_10, ITI_Tetraedron10, x.view());
1904 FixedArray<Int16, 20> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1905 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15 });
1906 _addMshTypeInfo(MSH_HEX_20, ITI_Hexaedron20, x.view());
1909 FixedArray<Int16, 27> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1910 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15,
1911 22, 23, 21, 24, 20, 25, 26 });
1912 _addMshTypeInfo(MSH_HEX_27, ITI_Hexaedron27, x.view());
1919void MshParallelMeshReader::
1927 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
1928 ItemTypeInfo* iti = item_type_mng->typeFromId(arcane_type);
1936mshToArcaneTypeInfo(
Int32 msh_type)
const
1940 if (tx.m_arcane_type_info)
1943 ARCANE_THROW(NotSupportedException,
"MSH type '{0}' is not supported in Arcane", msh_type);
1955 m_mesh_info = impl::MshMeshGenerationInfo::getReference(
mesh,
true);
1956 info() <<
"Trying to read in parallel 'msh' file '" << filename <<
"'"
1957 <<
" use_internal_partition=" << use_internal_partition;
1961 if (!use_internal_partition)
1963 m_parallel_mng = pm;
1984 m_master_io_rank = master_io_rank;
1990 info() <<
"Is file readable ?=" << is_readable;
1991 file_readable[0] = is_readable ? 1 : 0;
1993 error() <<
"Unable to read file '" << filename <<
"'";
1995 pm->broadcast(file_readable.
view(), master_io_rank);
1996 if (file_readable[0] == 0) {
2000 std::ifstream ifile;
2005 ifile.open(filename.
localstr(), ios::binary);
2008 m_ios_file = ios_file;
2010 if (IosFile::isEqualString(mesh_format_str,
"$MeshFormat")) {
2011 _readMeshFromFile();
2012 if (!use_internal_partition) {
2013 info() <<
"Synchronize groups and variables";
2014 mesh->synchronizeGroupsAndVariables();
2019 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
2027createMshParallelMeshReader(
ITraceMng* tm)
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
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 add(ConstReferenceType val)
Adds element val to the end of the array.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
ArrayView< T > view() const
Mutable view of this array.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
static std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Template class for converting a type.
constexpr __host__ __device__ ArrayView< T > view()
Modifiable view of the array.
constexpr __host__ __device__ SmallSpan< T, NbElement > span()
Modifiable view of the array.
Information about the floating-point type.
Interface of an entity family.
virtual ItemGroup findGroup(const String &name) const =0
Searches for a group.
virtual String name() const =0
Family name.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
virtual Integer dimension()=0
Mesh dimension (1D, 2D, or 3D).
eReturnType
Types of return codes for a read or write operation.
@ RTError
Error during the operation.
@ RTOk
Operation successfully performed.
virtual const MeshKind meshKind() const =0
Mesh characteristics.
virtual IPrimaryMesh * toPrimaryMesh()=0
Returns the instance in the form of an IPrimaryMesh.
Exception when an input/output error is detected.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual IParallelMng * sequentialParallelMng()=0
Returns a sequential parallelism manager.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual bool isMasterIO() const =0
true if the instance is a master I/O manager.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual Integer masterIORank() const =0
Rank of the instance managing I/O (for which isMasterIO() is true).
virtual bool isParallel() const =0
Returns true if the execution is parallel.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
virtual void endAllocate()=0
Indicates the end of cell allocation.
virtual void allocateCells(Integer nb_cell, Int64ConstArrayView cells_infos, bool one_alloc=true)=0
Allocation of a mesh.
virtual void setDimension(Integer dim)=0
Positions the mesh dimension (1D, 2D, or 3D).
File Read/Write Routines.
const String & name() const
Group name.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Adds entities.
Type of an entity (Item).
Info on a mesh entity type.
Integer nbLocalNode() const
Number of nodes of the entity.
String typeName() const
Type name.
ItemTypeId itemTypeId() const
Type number.
Mesh entity type manager.
ItemTypeInfo * typeFromId(Integer id) const
Type corresponding to the number id.
bool isNonManifold() const
True if the mesh structure is eMeshCellDimensionKind::NonManifold.
Information to create entities of a certain kind.
Information to create Arcane entities.
UniqueArray< Int64 > nodes_unique_id
UniqueId() of the nodes of my part.
std::unordered_map< Int64, Int32 > nodes_rank_map
Associative array (uniqueId(),rank) to which the node will belong.
UniqueArray< Real3 > nodes_coordinates
Coordinates of the nodes of my part.
Mapping information between MSH type and Arcane type.
Mesh file reader in msh format.
bool _getIsEndOfFileAndBroadcast()
Returns true if we are at the end of the file.
Int32 m_verbosity_level
Verbosity level.
void _readPeriodic()
Reading periodic information.
Integer _readElementsFromFile()
Reading of elements (cells, faces, ...).
void _addCellOrNodeGroup(ArrayView< Int64 > block_uids, Int32 block_index, const String &group_name, IItemFamily *family, bool filter_invalid)
Adds cells or nodes to the group group_name.
void _readAndCheck(const String &expected_value)
Tries to read the value value.
UniqueArray< Int32 > m_parts_rank
List of ranks participating in data conservation.
void _readEntities()
Reading entities.
Int32 m_nb_part
Number of partitions for reading nodes and blocks.
UniqueArray< MshToArcaneTypeInfo > m_msh_to_arcane_type_infos
Conversion information between MSH and Arcane types for entities.
eReturnType readMeshFromMshFile(IMesh *mesh, const String &filename, bool use_internal_partition) override
Reads the mesh contained in the file filename and constructs it in mesh.
void _readNodesFromFile()
Reads mesh nodes.
void _setNodesCoordinates()
Positions the node coordinates.
bool m_is_binary
True if the format is binary.
void _addFaceGroup(const MshElementBlock &block, const String &group_name)
Adds faces to the group group_name.
void _computeNodesPartition()
void _readOneElementBlock(MshElementBlock &block)
Reads an 'Element' type block.
String _getNextLineAndBroadcast()
Reads the next line value and broadcasts it to other ranks.
View of node information.
Utility class to reorder the nodes of an entity.
Exception when an operation is not supported.
Class managing a 3-dimensional real vector.
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
1D data array with pre-allocated stack buffer.
View of an array of elements of type T.
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
View of an array of elements of type T.
Unicode character string.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Span< const Byte > bytes() const
Returns the conversion of the instance into UTF-8 encoding.
static String collapseWhiteSpace(const String &rhs)
Performs whitespace character normalization.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
1D data vector with value semantics (STL style).
Info for 1D, 2D, and 3D entities.
Information on periodicity.
UniqueArray< double > m_affine_values
List of affine values.
UniqueArray< Int64 > m_corresponding_nodes
List of pairs (slave node uniqueId, master node unique()).
Brief information about a physical name.
Brief information about a mesh derived from the 'msh' format.
void resize(Int64 s)
Changes the number of elements in the array to s.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
ItemGroupT< Face > FaceGroup
Group of faces.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
@ ReduceSum
Sum of values.
@ ReduceMin
Minimum of values.
@ ReduceMax
Maximum of values.
constexpr __host__ __device__ bool isNearlyEqual(const _Type &a, const _Type &b)
Tests if two values are approximately equal. For integer types, this function is equivalent to IsEqua...
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
std::int16_t Int16
Signed integer type of 16 bits.
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.
Info of a block for $Elements for version 4.
ItemTypeId item_type
Arcane type of the entity.
UniqueArray< Int64 > connectivities
< List of uniqueId() of the block
Int64 nb_entity
Number of entities in the block.
Int32 item_nb_node
Number of nodes of the entity.
SmallSpan< const Int16 > reorder_infos
If not empty, contains the indirections for renumbering.
Int32 dimension
Dimension of the entity.
Int32 index
Block index in the list.
Info of a block for $Nodes.
Int32 index
Block index in the list.
Int32 entity_dim
Dimension of the associated entity.
Int64 index_in_allocation_info
Index in MshMeshAllocateInfo of the nodes of this block.
Int32 nb_node
Number of entities in the block.
Real x
first component of the triplet