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());
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);
713 info(4) <<
"Reading COORDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
714 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
715 nodes_coordinates.
resize(nb_to_read);
722 ios_file->binaryRead(nodes_coordinates.
view());
725 for (
Integer i = 0; i < nb_to_read; ++i) {
726 nodes_coordinates[i] = _getReal3();
730 if (dest_rank != m_master_io_rank) {
731 pm->send(nodes_coordinates, dest_rank);
734 else if (my_rank == dest_rank) {
735 pm->
recv(nodes_coordinates, m_master_io_rank);
739 if (my_rank == dest_rank) {
740 m_mesh_allocate_info.nodes_coordinates.addRange(nodes_coordinates);
756 IosFile* ios_file = m_ios_file.get();
765 info() <<
"Reading block nb_entity=" << nb_entity_in_block <<
" item_nb_node=" << item_nb_node;
773 const Int64 nb_to_read = _interval(i_part,
m_nb_part, nb_entity_in_block).second;
777 info(4) <<
"Reading block part i_part=" << i_part
778 <<
" nb_to_read=" << nb_to_read <<
" dest_rank=" << dest_rank;
780 const Int64 nb_uid = nb_to_read;
781 const Int64 nb_connectivity = nb_uid * item_nb_node;
782 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
784 connectivities.
resize(nb_connectivity);
788 Int64 nb_to_read = nb_uid * (item_nb_node + 1);
789 tmp_uid_and_connectivities.
resize(nb_to_read);
790 ios_file->binaryRead(tmp_uid_and_connectivities.
view());
792 for (
Int64 i = 0; i < nb_uid; ++i) {
793 Int64 item_unique_id = tmp_uid_and_connectivities[index];
795 uids[i] = item_unique_id;
796 for (
Int32 j = 0; j < item_nb_node; ++j) {
797 connectivities[(i * item_nb_node) + j] = tmp_uid_and_connectivities[index];
804 for (
Int64 i = 0; i < nb_uid; ++i) {
805 Int64 item_unique_id = ios_file->getInt64();
806 uids[i] = item_unique_id;
807 for (
Int32 j = 0; j < item_nb_node; ++j)
808 connectivities[(i * item_nb_node) + j] = ios_file->getInt64();
811 if (dest_rank != m_master_io_rank) {
812 pm->send(uids, dest_rank);
813 pm->send(connectivities, dest_rank);
816 else if (my_rank == dest_rank) {
817 pm->
recv(uids, m_master_io_rank);
818 pm->
recv(connectivities, m_master_io_rank);
820 if (my_rank == dest_rank) {
860 IosFile* ios_file = m_ios_file.get();
866 _getInt64ArrayAndBroadcast(elements_info.
view());
868 Int64 nb_block = elements_info[0];
869 Int64 number_of_elements = elements_info[1];
870 Int64 min_element_tag = elements_info[2];
871 Int64 max_element_tag = elements_info[3];
876 info() <<
"[Elements] nb_block=" << nb_block
877 <<
" nb_elements=" << number_of_elements
878 <<
" min_element_tag=" << min_element_tag
879 <<
" max_element_tag=" << max_element_tag;
881 if (number_of_elements < 0)
899 _getInt32ArrayAndBroadcast(block_info.
view());
901 Int32 entity_dim = block_info[0];
902 Int32 entity_tag = block_info[1];
903 Int32 entity_type = block_info[2];
904 Int64 nb_entity_in_block = _getInt64AndBroadcast();
912 info() <<
"[Elements] index=" << block.index <<
" entity_dim=" << entity_dim
913 <<
" entity_tag=" << entity_tag
914 <<
" msh_entity_type=" << entity_type <<
" nb_in_block=" << nb_entity_in_block
915 <<
" arcane_item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
917 block.nb_entity = nb_entity_in_block;
918 block.item_type = item_type;
919 block.item_nb_node = item_nb_node;
920 block.dimension = entity_dim;
921 block.entity_tag = entity_tag;
922 block.reorder_infos = msh_tinfo.m_reorder_infos;
923 if (entity_type == MSH_PNT) {
928 Int64 item_unique_id = NULL_ITEM_UNIQUE_ID;
930 [[maybe_unused]]
Int64 unused_id = _getInt64();
931 item_unique_id = _getInt64();
933 info() <<
"Adding unique node uid=" << item_unique_id;
937 block.uids.add(item_unique_id);
953 mesh_dimension =
math::max(mesh_dimension, block.dimension);
954 if (mesh_dimension < 0)
955 ARCANE_FATAL(
"Invalid computed mesh dimension '{0}'", mesh_dimension);
956 if (mesh_dimension != 2 && mesh_dimension != 3)
958 info() <<
"Computed mesh dimension = " << mesh_dimension;
960 bool allow_multi_dim_cell = m_mesh->meshKind().isNonManifold();
961 bool use_experimental_type_for_cell =
false;
962 if (allow_multi_dim_cell) {
964 use_experimental_type_for_cell =
true;
966 use_experimental_type_for_cell = (v.value() != 0);
968 info() <<
"Use experimental cell type?=" << use_experimental_type_for_cell;
969 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
971 const Int32 block_dim = block.dimension;
974 info() <<
"Reading block dim=" << block_dim <<
" type_name=" << item_type_name;
975 if (block_dim == mesh_dimension)
976 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
977 else if (allow_multi_dim_cell) {
980 bool use_sub_dim_cell =
false;
981 if (mesh_dimension == 3 && (block_dim == 2 || block_dim == 1))
983 use_sub_dim_cell =
true;
984 else if (mesh_dimension == 2 && block_dim == 1)
986 use_sub_dim_cell =
true;
987 if (!use_experimental_type_for_cell)
988 use_sub_dim_cell =
false;
989 if (use_sub_dim_cell) {
992 if (mesh_dimension == 3) {
993 if (block.item_type == IT_Triangle3)
994 block.item_type =
ItemTypeId(IT_Cell3D_Triangle3);
995 else if (block.item_type == IT_Triangle6)
996 block.item_type =
ItemTypeId(ITI_Cell3D_Triangle6);
997 else if (block.item_type == IT_Quad4)
998 block.item_type =
ItemTypeId(IT_Cell3D_Quad4);
999 else if (block.item_type == IT_Quad8)
1000 block.item_type =
ItemTypeId(IT_Cell3D_Quad8);
1001 else if (block.item_type == IT_Quad9)
1002 block.item_type =
ItemTypeId(IT_Cell3D_Quad9);
1003 else if (block.item_type == IT_Line2)
1004 block.item_type =
ItemTypeId(IT_Cell3D_Line2);
1005 else if (block.item_type == IT_Line3)
1006 block.item_type =
ItemTypeId(IT_Cell3D_Line3);
1008 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 3D mesh", item_type_name);
1010 else if (mesh_dimension == 2) {
1011 if (block.item_type == IT_Line2)
1014 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 2D mesh", item_type_name);
1016 block.is_built_as_cells =
true;
1017 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
1022 return mesh_dimension;
1036 if (my_rank != dest_rank) {
1037 work_values.
resize(size);
1038 view = work_values.
view();
1040 pm->broadcast(view, dest_rank);
1054 const Int32 my_rank = pm->commRank();
1057 if (dest_rank == my_rank)
1058 size = values.size();
1060 return _broadcastArrayWithSize(pm, values, work_values, dest_rank, size);
1068void MshParallelMeshReader::
1069_computeOwnItems(MshElementBlock& block, MshItemKindInfo& item_kind_info,
bool is_generate_uid)
1073 IParallelMng* pm = m_parallel_mng;
1074 const Int32 my_rank = pm->commRank();
1077 const ItemTypeId item_type = block.item_type;
1078 const Int32 item_nb_node = block.item_nb_node;
1080 UniqueArray<Int64> connectivities;
1081 UniqueArray<Int64> uids;
1082 UniqueArray<Int32> nodes_rank;
1084 SmallSpan<const Int16> reorder_infos = block.reorder_infos;
1085 bool has_reorder_info = !reorder_infos.empty();
1087 if (is_print_level1)
1088 info() <<
"Compute own items block_index=" << block.index <<
" nb_part=" << nb_part
1089 <<
" has_reorder?=" << has_reorder_info;
1091 SmallArray<Int64> arcane_reordered_uids;
1092 if (has_reorder_info)
1093 arcane_reordered_uids.resize(item_nb_node);
1094 for (
Int32 i_part = 0; i_part < nb_part; ++i_part) {
1097 ArrayView<Int64> connectivities_view = _broadcastArray(pm, block.connectivities.view(), connectivities, dest_rank);
1098 ArrayView<Int64> uids_view = _broadcastArray(pm, block.uids.view(), uids, dest_rank);
1100 Int32 nb_item = uids_view.size();
1101 nodes_rank.resize(nb_item);
1102 nodes_rank.fill(-1);
1107 for (
Int32 i = 0; i < nb_item; ++i) {
1108 Int64 first_node_uid = connectivities_view[i * item_nb_node];
1109 auto x = m_mesh_allocate_info.nodes_rank_map.find(first_node_uid);
1110 if (x == m_mesh_allocate_info.nodes_rank_map.end())
1113 Int32 rank = x->second;
1114 nodes_rank[i] = rank;
1117 for (
Int32 i = 0; i < nb_item; ++i) {
1118 const Int32 rank = nodes_rank[i];
1119 if (rank != my_rank)
1124 ConstArrayView<Int64> v = connectivities_view.subView(i * item_nb_node, item_nb_node);
1125 Int64 uid = uids_view[i];
1126 if (is_generate_uid)
1128 uid = NULL_ITEM_UNIQUE_ID;
1129 if (has_reorder_info) {
1132 for (
Int32 zz = 0; zz < item_nb_node; ++zz)
1133 arcane_reordered_uids[zz] = v[reorder_infos[zz]];
1134 v = arcane_reordered_uids.view();
1136 item_kind_info.addItem(item_type, uid, v);
1166 const IItemFamily* node_family = m_mesh->nodeFamily();
1170 ConstArrayView<Int64> uids = _broadcastArray(pm, m_mesh_allocate_info.nodes_unique_id.view(), uids_storage, dest_rank);
1171 ConstArrayView<Real3> coords = _broadcastArray(pm, m_mesh_allocate_info.nodes_coordinates.view(), coords_storage, dest_rank);
1174 local_ids.
resize(nb_item);
1180 for (
Int32 i = 0; i < nb_item; ++i) {
1181 NodeLocalId nid(local_ids[i]);
1183 nodes_coord_var[nid] = coords[i];
1191void MshParallelMeshReader::
1195 Integer nb_elements = m_mesh_allocate_info.cells_infos.nb_item;
1196 info() <<
"nb_of_elements=cells_type.size()=" << nb_elements;
1197 Integer nb_cell_node = m_mesh_allocate_info.cells_infos.items_infos.
size();
1198 info() <<
"nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
1201 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
1203 info() <<
"## Allocating ##";
1204 pmesh->
allocateCells(nb_elements, m_mesh_allocate_info.cells_infos.items_infos,
false);
1205 info() <<
"## Ending ##";
1207 info() <<
"## Done ##";
1213void MshParallelMeshReader::
1216 IMesh* mesh = m_mesh;
1218 Int32 face_dim = mesh_dim - 1;
1219 UniqueArray<MshEntitiesWithNodes> entity_list;
1220 UniqueArray<MshPhysicalName> physical_name_list;
1221 IItemFamily* node_family = mesh->nodeFamily();
1223 for (MshElementBlock& block : m_mesh_allocate_info.element_blocks) {
1224 entity_list.clear();
1225 physical_name_list.clear();
1226 Int32 block_index = block.index;
1227 Int32 block_dim = block.dimension;
1230 Int64 block_entity_tag = block.entity_tag;
1231 if (block_entity_tag < 0) {
1232 info(5) <<
"[Groups] Skipping block index=" << block_index <<
" because it has no entity";
1235 if (block_dim == 0) {
1236 const MshEntitiesNodes* entity = m_mesh_info->findNodeEntities(block_entity_tag);
1238 info(5) <<
"[Groups] Skipping block index=" << block_index
1239 <<
" because entity tag is invalid";
1242 Int64 entity_physical_tag = entity->physicalTag();
1243 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1244 physical_name_list.add(physical_name);
1247 m_mesh_info->findEntities(block_dim, block_entity_tag, entity_list);
1248 for (
const MshEntitiesWithNodes& x : entity_list) {
1249 Int64 entity_physical_tag = x.physicalTag();
1250 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1251 physical_name_list.add(physical_name);
1254 for (
const MshPhysicalName& physical_name : physical_name_list) {
1255 if (physical_name.isNull()) {
1256 info(5) <<
"[Groups] Skipping block index=" << block_index
1257 <<
" because entity physical tag is invalid";
1260 String group_name = physical_name.name();
1261 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
1262 <<
" name='" << group_name <<
"' built_as_cells=" << block.is_built_as_cells;
1263 if (block_dim == mesh_dim || block.is_built_as_cells) {
1266 else if (block_dim == face_dim) {
1279 UniqueArray<Int64>& nodes_uids = m_mesh_allocate_info.nodes_unique_id;
1281 for (
const MshNodeBlock& block : m_mesh_allocate_info.node_blocks) {
1282 ArrayView<Int64> block_uids = nodes_uids.subView(block.index_in_allocation_info, block.nb_node);
1283 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block.entity_dim, block.entity_tag);
1284 String group_name = physical_name.name();
1293 if (!group_name.null())
1313 _addFaceGroupOnePart(block, connectivities_view, group_name);
1320void MshParallelMeshReader::
1322 const String& group_name)
1325 const Int32 item_nb_node = block.item_nb_node;
1326 const Int32 block_index = block.index;
1328 const Int32 nb_entity = connectivities.
size() / item_nb_node;
1332 FaceGroup face_group =
mesh->faceFamily()->findGroup(group_name,
true);
1337 const Int32 face_nb_node = nb_entity * item_nb_node;
1342 Integer faces_nodes_unique_id_index = 0;
1355 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1356 for (
Integer z = 0; z < item_nb_node; ++z)
1357 orig_nodes_id[z] = connectivities[faces_nodes_unique_id_index + z];
1358 m_nodes_reorderer.reorder(type_id, orig_nodes_id);
1360 for (
Integer z = 0; z < item_nb_node; ++z)
1361 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = sorted_nodes[z];
1362 faces_first_node_unique_id[i_face] = sorted_nodes[0];
1363 faces_nodes_unique_id_index += item_nb_node;
1368 const bool is_non_manifold = m_mesh->
meshKind().isNonManifold();
1369 faces_nodes_unique_id_index = 0;
1370 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1371 const Integer n = item_nb_node;
1372 Int32 face_first_node_lid = faces_first_node_local_id[i_face];
1373 if (face_first_node_lid != NULL_ITEM_LOCAL_ID) {
1374 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
1375 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
1376 Face face = MeshUtils::getFaceFromNodesUniqueId(current_node, face_nodes_id);
1381 if (!m_is_parallel) {
1383 ostr() <<
"(Nodes:";
1384 for (
Integer z = 0; z < n; ++z)
1385 ostr() <<
' ' << face_nodes_id[z];
1386 ostr() <<
" - node_lid=" << current_node.localId() <<
")";
1387 String error_string =
"INTERNAL: MshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity.";
1388 if (!is_non_manifold)
1389 error_string = error_string +
"\n This errors may occur if the mesh is non-manifold."
1390 "\n See Arcane documentation to specify the mesh is a non manifold one.\n";
1395 faces_id.
add(face.localId());
1398 faces_nodes_unique_id_index += n;
1400 info(4) <<
"Adding " << faces_id.
size() <<
" faces from block index=" << block_index
1401 <<
" to group '" << face_group.
name() <<
"'";
1418 ArrayView<Int64> uids_view = _broadcastArray(pm, block_uids, uids, dest_rank);
1419 _addCellOrNodeGroupOnePart(uids_view, group_name, block_index, family, filter_invalid);
1426void MshParallelMeshReader::
1445 if (m_is_parallel || filter_invalid) {
1446 auto items_begin = items_lid.begin();
1447 Int64 new_size = std::remove(items_begin, items_lid.end(), NULL_ITEM_LOCAL_ID) - items_begin;
1448 items_lid.resize(new_size);
1451 info() <<
"Adding " << items_lid.size() <<
" items from block index=" << block_index
1452 <<
" to group '" << group_name <<
"' for family=" << family->
name();
1466void MshParallelMeshReader::
1470 String quote_mark =
"\"";
1471 Int32 nb_name = _getIntegerAndBroadcast();
1472 info() <<
"nb_physical_name=" << nb_name;
1476 for (
Int32 i = 0; i < nb_name; ++i) {
1477 Int32 dim = _getIntegerAndBroadcast();
1478 Int32 tag = _getIntegerAndBroadcast();
1480 if (dim < 0 || dim > 3)
1481 ARCANE_FATAL(
"Invalid value for physical name dimension dim={0}", dim);
1485 if (s.startsWith(quote_mark))
1487 if (s.endsWith(quote_mark))
1488 s = s.substring(0, s.length() - 1);
1489 m_mesh_info->physical_name_list.add(dim, tag, s);
1490 info(4) <<
"[PhysicalName] index=" << i <<
" dim=" << dim <<
" tag=" << tag <<
" name='" << s <<
"'";
1494 if (s !=
"$EndPhysicalNames")
1495 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
1533 IosFile* ios_file = m_ios_file.get();
1536 _getInt64ArrayAndBroadcast(nb_dim_item.
view());
1540 info() <<
"[Entities] nb_0d=" << nb_dim_item[0] <<
" nb_1d=" << nb_dim_item[1]
1541 <<
" nb_2d=" << nb_dim_item[2] <<
" nb_3d=" << nb_dim_item[3];
1548 for (
Int64 i = 0; i < nb_dim_item[0]; ++i) {
1551 Int32 tag = _getInt32();
1552 Real3 xyz = _getReal3();
1553 Int64 num_physical_tag = _getInt64();
1554 if (num_physical_tag > 1)
1555 ARCANE_FATAL(
"NotImplemented numPhysicalTag>1 (n={0}, index={1} xyz={2})",
1556 num_physical_tag, i, xyz);
1558 Int32 physical_tag = -1;
1559 if (num_physical_tag == 1)
1560 physical_tag = _getInt32();
1561 if (is_print_level1)
1562 info() <<
"[Entities] point tag=" << tag <<
" pos=" << xyz <<
" phys_tag=" << physical_tag;
1565 tag_info[1] = physical_tag;
1567 m_parallel_mng->broadcast(tag_info.
view(), m_master_io_rank);
1568 m_mesh_info->entities_nodes_list.add(MshEntitiesNodes(tag_info[0], tag_info[1]));
1574 for (
Int32 i_dim = 1; i_dim <= 3; ++i_dim)
1575 for (
Int32 i = 0; i < nb_dim_item[i_dim]; ++i)
1576 _readOneEntity(i_dim, i);
1587void MshParallelMeshReader::
1588_readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim)
1605 if (is_print_level1)
1606 info() <<
"[Entities] Reading entity dim=" << entity_dim <<
" index_in_dim=" << entity_index_in_dim;
1608 dim_and_tag_info.
add(entity_dim);
1610 Int32 tag = _getInt32();
1611 dim_and_tag_info.
add(tag);
1612 Real3 min_pos = _getReal3();
1613 Real3 max_pos = _getReal3();
1614 Int64 nb_physical_tag = _getInt64();
1615 dim_and_tag_info.
add(nb_physical_tag);
1616 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1617 Int32 physical_tag = _getInt32();
1618 dim_and_tag_info.
add(physical_tag);
1619 if (is_print_level2)
1620 info(4) <<
"[Entities] z=" << z <<
" physical_tag=" << physical_tag;
1623 Int64 nb_bounding_group = _getInt64();
1624 dim_and_tag_info.
add(nb_bounding_group);
1625 for (Int64 z = 0; z < nb_bounding_group; ++z) {
1626 Int32 boundary_tag = _getInt32();
1627 if (is_print_level2)
1628 info(4) <<
"[Entities] z=" << z <<
" boundary_tag=" << boundary_tag;
1630 if (is_print_level2)
1631 info(4) <<
"[Entities] dim=" << entity_dim <<
" tag=" << tag
1632 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
1633 <<
" nb_phys_tag=" << nb_physical_tag
1634 <<
" nb_bounding=" << nb_bounding_group;
1636 Int32 info_size = dim_and_tag_info.
size();
1637 m_parallel_mng->broadcast(ArrayView<Int32>(1, &info_size), m_master_io_rank);
1638 dim_and_tag_info.
resize(info_size);
1639 m_parallel_mng->broadcast(dim_and_tag_info.
view(), m_master_io_rank);
1643 Int64 tag = dim_and_tag_info[1];
1644 Int64 nb_physical_tag = dim_and_tag_info[2];
1645 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1646 Int64 physical_tag = dim_and_tag_info[3 + z];
1647 if (is_print_level2)
1648 info(4) <<
"[Entities] adding info dim=" << entity_dim <<
" tag=" << tag
1649 <<
" physical_tag=" << physical_tag;
1650 m_mesh_info->entities_with_nodes_list[dim - 1].add(MshEntitiesWithNodes(dim, tag, physical_tag));
1680 Int64 nb_link = _getInt64AndBroadcast();
1681 info() <<
"[Periodic] nb_link=" << nb_link;
1687 MshPeriodicInfo& periodic_info = m_mesh_info->m_periodic_info;
1688 periodic_info.m_periodic_list.resize(nb_link);
1689 for (
Int64 ilink = 0; ilink < nb_link; ++ilink) {
1690 MshPeriodicOneInfo& one_info = periodic_info.m_periodic_list[ilink];
1692 _getInt32ArrayAndBroadcast(entity_info.
view());
1694 if (is_print_level1)
1695 info() <<
"[Periodic] link_index=" << ilink <<
" dim=" << entity_info[0] <<
" entity_tag=" << entity_info[1]
1696 <<
" entity_tag_master=" << entity_info[2];
1697 one_info.m_entity_dim = entity_info[0];
1698 one_info.m_entity_tag = entity_info[1];
1699 one_info.m_entity_tag_master = entity_info[2];
1701 Int64 num_affine = _getInt64AndBroadcast();
1702 if (is_print_level2)
1703 info() <<
"[Periodic] num_affine=" << num_affine;
1707 if (is_print_level1)
1708 info() <<
"[Periodic] nb_corresponding_node=" << one_info.m_nb_corresponding_node;
1711 if (is_print_level2)
1718 if (s !=
"$EndPeriodic")
1719 ARCANE_FATAL(
"found '{0}' and expected '$EndPeriodic'", s);
1732 constexpr Int32 MAX_SIZE = 128;
1737 if (read_size >= MAX_SIZE)
1738 ARCANE_FATAL(
"local buffer is too small (size={0} max={1})", read_size, MAX_SIZE);
1739 IosFile* f = m_ios_file.get();
1741 f->binaryRead(bytes_to_read);
1742 s =
String(bytes_to_read);
1743 info() <<
"S=" << s;
1744 if (m_is_parallel) {
1745 m_parallel_mng->broadcastString(s, m_master_io_rank);
1753 if (s != expected_value)
1754 ARCANE_FATAL(
"found '{0}' and expected '{1}'", s, expected_value);
1761void MshParallelMeshReader::
1766 info() <<
"Reading 'msh' file in parallel";
1770 const int MSH_BINARY_TYPE = 1;
1773 Real version = ios_file->getReal();
1775 ARCANE_THROW(
IOException,
"Wrong msh file version '{0}'. Only version '4.1' is supported in parallel", version);
1776 Integer file_type = ios_file->getInteger();
1777 if (file_type == MSH_BINARY_TYPE)
1780 Int32 data_size = ios_file->getInteger();
1781 ARCANE_UNUSED(data_size);
1783 ARCANE_FATAL(
"Only 'size_t' of size '8' is allowed (current size is '{0}')", data_size);
1788 Int32 int_value_one = 0;
1790 if (int_value_one != 1)
1791 ARCANE_FATAL(
"Bad endianess for file. Read int as value '{0}' (expected=1)", int_value_one);
1797 if (!ios_file->lookForString(
"$EndMeshFormat"))
1807 if (next_line ==
"$PhysicalNames") {
1808 _readPhysicalNames();
1814 if (next_line ==
"$Entities") {
1819 if (next_line !=
"$Nodes")
1820 ARCANE_THROW(IOException,
"Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1826 if (ios_file && !ios_file->lookForString(
"$EndNodes"))
1830 if (ios_file && !ios_file->lookForString(
"$Elements"))
1836 if (ios_file && !ios_file->lookForString(
"$EndElements"))
1839 info() <<
"Computed mesh dimension = " << mesh_dimension;
1844 info() <<
"NextLine=" << next_line;
1850 if (next_line ==
"$Periodic") {
1863void MshParallelMeshReader::
1870 _addMshTypeInfo(MSH_PNT, ITI_Vertex);
1871 _addMshTypeInfo(MSH_LIN_2, ITI_Line2);
1872 _addMshTypeInfo(MSH_LIN_3, ITI_Line3);
1873 _addMshTypeInfo(MSH_TRI_3, ITI_Triangle3);
1874 _addMshTypeInfo(MSH_QUA_4, ITI_Quad4);
1875 _addMshTypeInfo(MSH_QUA_8, ITI_Quad8);
1876 _addMshTypeInfo(MSH_QUA_9, ITI_Quad9);
1877 _addMshTypeInfo(MSH_TET_4, ITI_Tetraedron4);
1878 _addMshTypeInfo(MSH_HEX_8, ITI_Hexaedron8);
1879 _addMshTypeInfo(MSH_PRI_6, ITI_Pentaedron6);
1880 _addMshTypeInfo(MSH_PRI_15, ITI_Pentaedron15);
1881 _addMshTypeInfo(MSH_PYR_5, ITI_Pyramid5);
1882 _addMshTypeInfo(MSH_PYR_13, ITI_Pyramid13);
1883 _addMshTypeInfo(MSH_TRI_6, ITI_Triangle6);
1885 FixedArray<Int16, 10> x({ 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 });
1886 _addMshTypeInfo(MSH_TET_10, ITI_Tetraedron10, x.view());
1889 FixedArray<Int16, 20> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1890 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15 });
1891 _addMshTypeInfo(MSH_HEX_20, ITI_Hexaedron20, x.view());
1894 FixedArray<Int16, 27> x({ 0, 1, 2, 3, 4, 5, 6, 7,
1895 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15,
1896 22, 23, 21, 24, 20, 25, 26 });
1897 _addMshTypeInfo(MSH_HEX_27, ITI_Hexaedron27, x.view());
1904void MshParallelMeshReader::
1912 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
1913 ItemTypeInfo* iti = item_type_mng->typeFromId(arcane_type);
1921mshToArcaneTypeInfo(
Int32 msh_type)
const
1925 if (tx.m_arcane_type_info)
1928 ARCANE_THROW(NotSupportedException,
"MSH type '{0}' is not supported in Arcane", msh_type);
1939 m_mesh_info = impl::MshMeshGenerationInfo::getReference(
mesh,
true);
1940 info() <<
"Trying to read in parallel 'msh' file '" << filename <<
"'"
1941 <<
" use_internal_partition=" << use_internal_partition;
1945 if (!use_internal_partition)
1947 m_parallel_mng = pm;
1968 m_master_io_rank = master_io_rank;
1974 info() <<
"Is file readable ?=" << is_readable;
1975 file_readable[0] = is_readable ? 1 : 0;
1977 error() <<
"Unable to read file '" << filename <<
"'";
1979 pm->broadcast(file_readable.
view(), master_io_rank);
1980 if (file_readable[0] == 0) {
1984 std::ifstream ifile;
1989 ifile.open(filename.
localstr(), ios::binary);
1992 m_ios_file = ios_file;
1994 if (IosFile::isEqualString(mesh_format_str,
"$MeshFormat")) {
1995 _readMeshFromFile();
1996 if (!use_internal_partition) {
1997 info() <<
"Synchronize groups and variables";
1998 mesh->synchronizeGroupsAndVariables();
2003 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
2011createMshParallelMeshReader(
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 std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
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.
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.
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
@ 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