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/internal/MshMeshGenerationInfo.h"
39#include "arcane/std/internal/IosFile.h"
40#include "arcane/std/internal/IosGmsh.h"
81class MshParallelMeshReader
100 class MshToArcaneTypeInfo
104 MshToArcaneTypeInfo() =
default;
106 : m_msh_type(msh_type)
107 , m_arcane_type_info(iti)
108 , m_reorder_infos(reorder_infos)
114 Int32 m_msh_type = -1;
135 Int64 entity_tag = -1;
168 items_infos.add(type_id);
169 items_infos.add(unique_id);
170 items_infos.addRange(nodes_uid);
198 explicit MshParallelMeshReader(
ITraceMng* tm)
207 IMesh* m_mesh =
nullptr;
209 Int32 m_master_io_rank = A_NULL_RANK;
210 bool m_is_parallel =
false;
213 MshMeshAllocateInfo m_mesh_allocate_info;
228 void _readMeshFromFile();
230 void _allocateCells();
231 void _allocateGroups();
239 void _readPhysicalNames();
242 void _readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim);
245 Int32 _getIntegerAndBroadcast();
246 Int64 _getInt64AndBroadcast();
256 void _goToNextLine();
259 const MshToArcaneTypeInfo& mshToArcaneTypeInfo(
Int32 msh_type)
const;
274 inline std::pair<Int64, Int64>
275 _interval(Int32 index, Int32 nb_interval, Int64 size)
277 Int64 isize = size / nb_interval;
278 Int64 ibegin = index * isize;
280 if ((index + 1) == nb_interval)
281 isize = size - ibegin;
282 return { ibegin, isize };
297 s = f->getNextLine();
301 info() <<
"BroadcastNextLine: " << s;
302 m_parallel_mng->broadcastString(s, m_master_io_rank);
304 info() <<
"GetNextLine: " << s;
317 Int32 is_end_int = 0;
319 is_end_int = f->isEnd() ? 1 : 0;
320 info() <<
"IsEndOfFile_Master: " << is_end_int;
324 info() <<
"IsEndOfFile: " << is_end_int;
325 m_parallel_mng->broadcast(
ArrayView<Int32>(1, &is_end_int), m_master_io_rank);
327 bool is_end = (is_end_int != 0);
328 info() <<
"IsEnd: " << is_end;
337_getIntegerAndBroadcast()
342 v[0] = f->getInteger();
344 m_parallel_mng->broadcast(v.
view(), m_master_io_rank);
352Int64 MshParallelMeshReader::
353_getInt64AndBroadcast()
355 IosFile* f = m_ios_file.get();
356 FixedArray<Int64, 1> v;
360 m_parallel_mng->broadcast(v.view(), m_master_io_rank);
368void MshParallelMeshReader::
371 IosFile* f = m_ios_file.get();
374 f->binaryRead(values);
377 for (
Int64& v : values)
382 m_parallel_mng->broadcast(values, m_master_io_rank);
388void MshParallelMeshReader::
391 IosFile* f = m_ios_file.get();
394 f->binaryRead(values);
397 for (
Int32& v : values)
402 m_parallel_mng->broadcast(values, m_master_io_rank);
408void MshParallelMeshReader::
411 IosFile* f = m_ios_file.get();
414 f->binaryRead(values);
417 for (
double& v : values)
422 m_parallel_mng->broadcast(values, m_master_io_rank);
428Real3 MshParallelMeshReader::
431 IosFile* f = m_ios_file.get();
435 f->binaryRead(SmallSpan<Real3>(&v, 1));
438 Real x = f->getReal();
439 Real y = f->getReal();
440 Real z = f->getReal();
449Int32 MshParallelMeshReader::
452 IosFile* f = m_ios_file.get();
456 f->binaryRead(SmallSpan<Int32>(&v, 1));
465Int64 MshParallelMeshReader::
468 IosFile* f = m_ios_file.get();
472 f->binaryRead(SmallSpan<Int64>(&v, 1));
481void MshParallelMeshReader::
484 if (m_ios_file.get())
485 m_ios_file->getNextLine();
496 Real min_value = -max_value;
497 Real3 min_box(max_value, max_value, max_value);
498 Real3 max_box(min_value, min_value, min_value);
499 const Int64 nb_node = m_mesh_allocate_info.nodes_coordinates.largeSize();
500 for (
Real3 pos : m_mesh_allocate_info.nodes_coordinates) {
514 Real min_x = min_box.
x;
515 Real max_x = max_box.
x;
519 info() <<
"MIN_MAX_X=" << global_min_x <<
" " << global_max_x;
525 for (
Int64 i = 0; i < nb_node; ++i) {
526 Int32 part =
static_cast<Int32>((m_mesh_allocate_info.nodes_coordinates[i].x - global_min_x) / diff_v);
527 part = std::clamp(part, 0,
m_nb_part - 1);
528 nodes_part[i] = part;
533 for (
Int64 i = 0; i < nb_node; ++i) {
535 Int64 uid = m_mesh_allocate_info.nodes_unique_id[i];
536 ++nb_node_per_rank[rank];
537 m_mesh_allocate_info.nodes_rank_map.insert(std::make_pair(uid, rank));
540 info() <<
"NB_NODE_PER_RANK=" << nb_node_per_rank;
573 _getInt64ArrayAndBroadcast(nodes_info.
view());
575 Int64 nb_node_block =
static_cast<Int32>(nodes_info[0]);
576 Int64 total_nb_node = nodes_info[1];
577 Int64 min_node_tag = nodes_info[2];
578 Int64 max_node_tag = nodes_info[3];
583 if (total_nb_node < 0)
586 info() <<
"[Nodes] nb_node_block=" << nb_node_block
587 <<
" total_nb_node=" << total_nb_node
588 <<
" min_tag=" << min_node_tag
589 <<
" max_tag=" << max_node_tag
591 <<
" nb_rank=" << m_parallel_mng->commSize();
594 node_blocks.
resize(nb_node_block);
596 for (
Int32 i = 0; i < nb_node_block; ++i) {
598 node_block.
index = i;
599 _readNodesOneEntity(node_block);
611void MshParallelMeshReader::
612_readNodesOneEntity(MshNodeBlock& node_block)
622 _getInt32ArrayAndBroadcast(entity_infos.
view());
629 Int32 entity_dim = entity_infos[0];
630 node_block.entity_dim = entity_dim;
632 Int32 entity_tag = entity_infos[1];
633 node_block.entity_tag = entity_tag;
635 node_block.index_in_allocation_info = m_mesh_allocate_info.nodes_coordinates.
size();
636 node_block.nb_node = nb_node2;
638 Int32 parametric_coordinates = entity_infos[2];
640 info() <<
"[Nodes] index=" << node_block.index <<
" entity_dim=" << entity_dim <<
" entity_tag=" << entity_tag
641 <<
" parametric=" << parametric_coordinates
642 <<
" nb_node2=" << nb_node2;
644 if (parametric_coordinates != 0)
658 info() <<
"Reading UIDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
659 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
660 nodes_uids.
resize(nb_to_read);
667 ios_file->binaryRead(nodes_uids.
view());
670 for (
Integer i = 0; i < nb_to_read; ++i) {
672 nodes_uids[i] = ios_file->getInt64();
676 if (dest_rank != m_master_io_rank) {
677 pm->send(nodes_uids, dest_rank);
680 else if (my_rank == dest_rank) {
681 pm->
recv(nodes_uids, m_master_io_rank);
685 if (my_rank == dest_rank) {
686 m_mesh_allocate_info.nodes_unique_id.addRange(nodes_uids);
694 info() <<
"Reading COORDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
695 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
696 nodes_coordinates.
resize(nb_to_read);
703 ios_file->binaryRead(nodes_coordinates.
view());
706 for (
Integer i = 0; i < nb_to_read; ++i) {
707 nodes_coordinates[i] = _getReal3();
711 if (dest_rank != m_master_io_rank) {
712 pm->send(nodes_coordinates, dest_rank);
715 else if (my_rank == dest_rank) {
716 pm->
recv(nodes_coordinates, m_master_io_rank);
720 if (my_rank == dest_rank) {
721 m_mesh_allocate_info.nodes_coordinates.addRange(nodes_coordinates);
737 IosFile* ios_file = m_ios_file.get();
743 info() <<
"Reading block nb_entity=" << nb_entity_in_block <<
" item_nb_node=" << item_nb_node;
751 const Int64 nb_to_read = _interval(i_part,
m_nb_part, nb_entity_in_block).second;
754 info() <<
"Reading block part i_part=" << i_part
755 <<
" nb_to_read=" << nb_to_read <<
" dest_rank=" << dest_rank;
757 const Int64 nb_uid = nb_to_read;
758 const Int64 nb_connectivity = nb_uid * item_nb_node;
759 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
761 connectivities.
resize(nb_connectivity);
765 Int64 nb_to_read = nb_uid * (item_nb_node + 1);
766 tmp_uid_and_connectivities.
resize(nb_to_read);
767 ios_file->binaryRead(tmp_uid_and_connectivities.
view());
769 for (
Int64 i = 0; i < nb_uid; ++i) {
770 Int64 item_unique_id = tmp_uid_and_connectivities[index];
772 uids[i] = item_unique_id;
773 for (
Int32 j = 0; j < item_nb_node; ++j) {
774 connectivities[(i * item_nb_node) + j] = tmp_uid_and_connectivities[index];
781 for (
Int64 i = 0; i < nb_uid; ++i) {
782 Int64 item_unique_id = ios_file->getInt64();
783 uids[i] = item_unique_id;
784 for (
Int32 j = 0; j < item_nb_node; ++j)
785 connectivities[(i * item_nb_node) + j] = ios_file->getInt64();
788 if (dest_rank != m_master_io_rank) {
789 pm->send(uids, dest_rank);
790 pm->send(connectivities, dest_rank);
793 else if (my_rank == dest_rank) {
794 pm->
recv(uids, m_master_io_rank);
795 pm->
recv(connectivities, m_master_io_rank);
797 if (my_rank == dest_rank) {
837 IosFile* ios_file = m_ios_file.get();
841 _getInt64ArrayAndBroadcast(elements_info.
view());
843 Int64 nb_block = elements_info[0];
844 Int64 number_of_elements = elements_info[1];
845 Int64 min_element_tag = elements_info[2];
846 Int64 max_element_tag = elements_info[3];
851 info() <<
"[Elements] nb_block=" << nb_block
852 <<
" nb_elements=" << number_of_elements
853 <<
" min_element_tag=" << min_element_tag
854 <<
" max_element_tag=" << max_element_tag;
856 if (number_of_elements < 0)
874 _getInt32ArrayAndBroadcast(block_info.
view());
876 Int32 entity_dim = block_info[0];
877 Int32 entity_tag = block_info[1];
878 Int32 entity_type = block_info[2];
879 Int64 nb_entity_in_block = _getInt64AndBroadcast();
886 info() <<
"[Elements] index=" << block.index <<
" entity_dim=" << entity_dim
887 <<
" entity_tag=" << entity_tag
888 <<
" msh_entity_type=" << entity_type <<
" nb_in_block=" << nb_entity_in_block
889 <<
" arcane_item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
891 block.nb_entity = nb_entity_in_block;
892 block.item_type = item_type;
893 block.item_nb_node = item_nb_node;
894 block.dimension = entity_dim;
895 block.entity_tag = entity_tag;
896 block.reorder_infos = msh_tinfo.m_reorder_infos;
897 if (entity_type == MSH_PNT) {
902 Int64 item_unique_id = NULL_ITEM_UNIQUE_ID;
904 [[maybe_unused]]
Int64 unused_id = _getInt64();
905 item_unique_id = _getInt64();
906 info() <<
"Adding unique node uid=" << item_unique_id;
910 block.uids.add(item_unique_id);
926 mesh_dimension =
math::max(mesh_dimension, block.dimension);
927 if (mesh_dimension < 0)
928 ARCANE_FATAL(
"Invalid computed mesh dimension '{0}'", mesh_dimension);
929 if (mesh_dimension != 2 && mesh_dimension != 3)
931 info() <<
"Computed mesh dimension = " << mesh_dimension;
933 bool allow_multi_dim_cell = m_mesh->meshKind().isNonManifold();
934 bool use_experimental_type_for_cell =
false;
935 if (allow_multi_dim_cell) {
937 use_experimental_type_for_cell =
true;
939 use_experimental_type_for_cell = (v.value() != 0);
941 info() <<
"Use experimental cell type?=" << use_experimental_type_for_cell;
942 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
944 const Int32 block_dim = block.dimension;
946 info() <<
"Reading block dim=" << block_dim <<
" type_name=" << item_type_name;
947 if (block_dim == mesh_dimension)
948 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
949 else if (allow_multi_dim_cell) {
952 bool use_sub_dim_cell =
false;
953 if (mesh_dimension == 3 && (block_dim == 2 || block_dim == 1))
955 use_sub_dim_cell =
true;
956 else if (mesh_dimension == 2 && block_dim == 1)
958 use_sub_dim_cell =
true;
959 if (!use_experimental_type_for_cell)
960 use_sub_dim_cell =
false;
961 if (use_sub_dim_cell) {
964 if (mesh_dimension == 3) {
965 if (block.item_type == IT_Triangle3)
966 block.item_type =
ItemTypeId(IT_Cell3D_Triangle3);
967 else if (block.item_type == IT_Quad4)
968 block.item_type =
ItemTypeId(IT_Cell3D_Quad4);
969 else if (block.item_type == IT_Line2)
970 block.item_type =
ItemTypeId(IT_Cell3D_Line2);
972 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 3D mesh", item_type_name);
974 else if (mesh_dimension == 2) {
975 if (block.item_type == IT_Line2)
978 ARCANE_FATAL(
"Not supported sub dimension cell type={0} for 2D mesh", item_type_name);
980 block.is_built_as_cells =
true;
981 _computeOwnItems(block, m_mesh_allocate_info.cells_infos,
false);
986 return mesh_dimension;
1000 if (my_rank != dest_rank) {
1001 work_values.
resize(size);
1002 view = work_values.
view();
1004 pm->broadcast(view, dest_rank);
1018 const Int32 my_rank = pm->commRank();
1021 if (dest_rank == my_rank)
1022 size = values.size();
1024 return _broadcastArrayWithSize(pm, values, work_values, dest_rank, size);
1032void MshParallelMeshReader::
1033_computeOwnItems(MshElementBlock& block, MshItemKindInfo& item_kind_info,
bool is_generate_uid)
1037 IParallelMng* pm = m_parallel_mng;
1038 const Int32 my_rank = pm->commRank();
1040 const ItemTypeId item_type = block.item_type;
1041 const Int32 item_nb_node = block.item_nb_node;
1043 UniqueArray<Int64> connectivities;
1044 UniqueArray<Int64> uids;
1045 UniqueArray<Int32> nodes_rank;
1047 SmallSpan<const Int16> reorder_infos = block.reorder_infos;
1048 bool has_reorder_info = !reorder_infos.empty();
1050 info() <<
"Compute own items block_index=" << block.index <<
" nb_part=" << nb_part
1051 <<
" has_reorder?=" << has_reorder_info;
1053 SmallArray<Int64> arcane_reordered_uids;
1054 if (has_reorder_info)
1055 arcane_reordered_uids.resize(item_nb_node);
1056 for (
Int32 i_part = 0; i_part < nb_part; ++i_part) {
1059 ArrayView<Int64> connectivities_view = _broadcastArray(pm, block.connectivities.view(), connectivities, dest_rank);
1060 ArrayView<Int64> uids_view = _broadcastArray(pm, block.uids.view(), uids, dest_rank);
1062 Int32 nb_item = uids_view.size();
1063 nodes_rank.resize(nb_item);
1064 nodes_rank.fill(-1);
1069 for (
Int32 i = 0; i < nb_item; ++i) {
1070 Int64 first_node_uid = connectivities_view[i * item_nb_node];
1071 auto x = m_mesh_allocate_info.nodes_rank_map.find(first_node_uid);
1072 if (x == m_mesh_allocate_info.nodes_rank_map.end())
1075 Int32 rank = x->second;
1076 nodes_rank[i] = rank;
1079 for (
Int32 i = 0; i < nb_item; ++i) {
1080 const Int32 rank = nodes_rank[i];
1081 if (rank != my_rank)
1086 ConstArrayView<Int64> v = connectivities_view.subView(i * item_nb_node, item_nb_node);
1087 Int64 uid = uids_view[i];
1088 if (is_generate_uid)
1090 uid = NULL_ITEM_UNIQUE_ID;
1091 if (has_reorder_info) {
1094 for (
Int32 zz = 0; zz < item_nb_node; ++zz)
1095 arcane_reordered_uids[zz] = v[reorder_infos[zz]];
1096 v = arcane_reordered_uids.view();
1098 item_kind_info.addItem(item_type, uid, v);
1128 const IItemFamily* node_family = m_mesh->nodeFamily();
1132 ConstArrayView<Int64> uids = _broadcastArray(pm, m_mesh_allocate_info.nodes_unique_id.view(), uids_storage, dest_rank);
1133 ConstArrayView<Real3> coords = _broadcastArray(pm, m_mesh_allocate_info.nodes_coordinates.view(), coords_storage, dest_rank);
1136 local_ids.
resize(nb_item);
1142 for (
Int32 i = 0; i < nb_item; ++i) {
1143 NodeLocalId nid(local_ids[i]);
1145 nodes_coord_var[nid] = coords[i];
1153void MshParallelMeshReader::
1157 Integer nb_elements = m_mesh_allocate_info.cells_infos.nb_item;
1158 info() <<
"nb_of_elements=cells_type.size()=" << nb_elements;
1159 Integer nb_cell_node = m_mesh_allocate_info.cells_infos.items_infos.size();
1160 info() <<
"nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
1163 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
1165 info() <<
"## Allocating ##";
1166 pmesh->
allocateCells(nb_elements, m_mesh_allocate_info.cells_infos.items_infos,
false);
1167 info() <<
"## Ending ##";
1169 info() <<
"## Done ##";
1175void MshParallelMeshReader::
1178 IMesh* mesh = m_mesh;
1180 Int32 face_dim = mesh_dim - 1;
1181 UniqueArray<MshEntitiesWithNodes> entity_list;
1182 UniqueArray<MshPhysicalName> physical_name_list;
1183 IItemFamily* node_family = mesh->nodeFamily();
1185 for (MshElementBlock& block : m_mesh_allocate_info.element_blocks) {
1186 entity_list.clear();
1187 physical_name_list.clear();
1188 Int32 block_index = block.index;
1189 Int32 block_dim = block.dimension;
1192 Int64 block_entity_tag = block.entity_tag;
1193 if (block_entity_tag < 0) {
1194 info(5) <<
"[Groups] Skipping block index=" << block_index <<
" because it has no entity";
1197 if (block_dim == 0) {
1198 const MshEntitiesNodes* entity = m_mesh_info->findNodeEntities(block_entity_tag);
1200 info(5) <<
"[Groups] Skipping block index=" << block_index
1201 <<
" because entity tag is invalid";
1204 Int64 entity_physical_tag = entity->physicalTag();
1205 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1206 physical_name_list.add(physical_name);
1209 m_mesh_info->findEntities(block_dim, block_entity_tag, entity_list);
1210 for (
const MshEntitiesWithNodes& x : entity_list) {
1211 Int64 entity_physical_tag = x.physicalTag();
1212 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block_dim, entity_physical_tag);
1213 physical_name_list.add(physical_name);
1216 for (
const MshPhysicalName& physical_name : physical_name_list) {
1217 if (physical_name.isNull()) {
1218 info(5) <<
"[Groups] Skipping block index=" << block_index
1219 <<
" because entity physical tag is invalid";
1222 String group_name = physical_name.name();
1223 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
1224 <<
" name='" << group_name <<
"' built_as_cells=" << block.is_built_as_cells;
1225 if (block_dim == mesh_dim || block.is_built_as_cells) {
1228 else if (block_dim == face_dim) {
1241 UniqueArray<Int64>& nodes_uids = m_mesh_allocate_info.nodes_unique_id;
1243 for (
const MshNodeBlock& block : m_mesh_allocate_info.node_blocks) {
1244 ArrayView<Int64> block_uids = nodes_uids.subView(block.index_in_allocation_info, block.nb_node);
1245 MshPhysicalName physical_name = m_mesh_info->findPhysicalName(block.entity_dim, block.entity_tag);
1246 String group_name = physical_name.name();
1255 if (!group_name.null())
1275 _addFaceGroupOnePart(connectivities_view, item_nb_node, group_name, block.
index);
1282void MshParallelMeshReader::
1287 const Int32 nb_entity = connectivities.
size() / item_nb_node;
1291 FaceGroup face_group =
mesh->faceFamily()->findGroup(group_name,
true);
1296 const Int32 face_nb_node = nb_entity * item_nb_node;
1301 Integer faces_nodes_unique_id_index = 0;
1313 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1314 for (
Integer z = 0; z < item_nb_node; ++z)
1315 orig_nodes_id[z] = connectivities[faces_nodes_unique_id_index + z];
1318 for (
Integer z = 0; z < item_nb_node; ++z)
1319 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = orig_nodes_id[face_nodes_index[z]];
1320 faces_first_node_unique_id[i_face] = orig_nodes_id[face_nodes_index[0]];
1321 faces_nodes_unique_id_index += item_nb_node;
1326 const bool is_non_manifold = m_mesh->
meshKind().isNonManifold();
1327 faces_nodes_unique_id_index = 0;
1328 for (
Integer i_face = 0; i_face < nb_entity; ++i_face) {
1329 const Integer n = item_nb_node;
1330 Int32 face_first_node_lid = faces_first_node_local_id[i_face];
1331 if (face_first_node_lid != NULL_ITEM_LOCAL_ID) {
1332 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
1333 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
1334 Face face = MeshUtils::getFaceFromNodesUniqueId(current_node, face_nodes_id);
1339 if (!m_is_parallel) {
1341 ostr() <<
"(Nodes:";
1342 for (
Integer z = 0; z < n; ++z)
1343 ostr() <<
' ' << face_nodes_id[z];
1344 ostr() <<
" - " << current_node.localId() <<
")";
1345 String error_string =
"INTERNAL: MeshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity.";
1346 if (!is_non_manifold)
1347 error_string = error_string +
"\n This errors may occur if the mesh is non-manifold."
1348 "\n See Arcane documentation to specify the mesh is a non manifold one.\n";
1353 faces_id.
add(face.localId());
1356 faces_nodes_unique_id_index += n;
1358 info(4) <<
"Adding " << faces_id.
size() <<
" faces from block index=" << block_index
1359 <<
" to group '" << face_group.
name() <<
"'";
1376 ArrayView<Int64> uids_view = _broadcastArray(pm, block_uids, uids, dest_rank);
1377 _addCellOrNodeGroupOnePart(uids_view, group_name, block_index, family, filter_invalid);
1384void MshParallelMeshReader::
1403 if (m_is_parallel || filter_invalid) {
1404 auto items_begin = items_lid.begin();
1405 Int64 new_size = std::remove(items_begin, items_lid.end(), NULL_ITEM_LOCAL_ID) - items_begin;
1406 items_lid.resize(new_size);
1409 info() <<
"Adding " << items_lid.size() <<
" items from block index=" << block_index
1410 <<
" to group '" << group_name <<
"' for family=" << family->
name();
1424void MshParallelMeshReader::
1428 String quote_mark =
"\"";
1429 Int32 nb_name = _getIntegerAndBroadcast();
1430 info() <<
"nb_physical_name=" << nb_name;
1434 for (
Int32 i = 0; i < nb_name; ++i) {
1435 Int32 dim = _getIntegerAndBroadcast();
1436 Int32 tag = _getIntegerAndBroadcast();
1438 if (dim < 0 || dim > 3)
1439 ARCANE_FATAL(
"Invalid value for physical name dimension dim={0}", dim);
1443 if (s.startsWith(quote_mark))
1445 if (s.endsWith(quote_mark))
1446 s = s.substring(0, s.length() - 1);
1447 m_mesh_info->physical_name_list.add(dim, tag, s);
1448 info(4) <<
"[PhysicalName] index=" << i <<
" dim=" << dim <<
" tag=" << tag <<
" name='" << s <<
"'";
1452 if (s !=
"$EndPhysicalNames")
1453 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
1491 IosFile* ios_file = m_ios_file.get();
1494 _getInt64ArrayAndBroadcast(nb_dim_item.
view());
1496 info() <<
"[Entities] nb_0d=" << nb_dim_item[0] <<
" nb_1d=" << nb_dim_item[1]
1497 <<
" nb_2d=" << nb_dim_item[2] <<
" nb_3d=" << nb_dim_item[3];
1504 for (
Int64 i = 0; i < nb_dim_item[0]; ++i) {
1507 Int32 tag = _getInt32();
1508 Real3 xyz = _getReal3();
1509 Int64 num_physical_tag = _getInt64();
1510 if (num_physical_tag > 1)
1511 ARCANE_FATAL(
"NotImplemented numPhysicalTag>1 (n={0}, index={1} xyz={2})",
1512 num_physical_tag, i, xyz);
1514 Int32 physical_tag = -1;
1515 if (num_physical_tag == 1)
1516 physical_tag = _getInt32();
1517 info() <<
"[Entities] point tag=" << tag <<
" pos=" << xyz <<
" phys_tag=" << physical_tag;
1520 tag_info[1] = physical_tag;
1522 m_parallel_mng->broadcast(tag_info.
view(), m_master_io_rank);
1523 m_mesh_info->entities_nodes_list.add(MshEntitiesNodes(tag_info[0], tag_info[1]));
1529 for (
Int32 i_dim = 1; i_dim <= 3; ++i_dim)
1530 for (
Int32 i = 0; i < nb_dim_item[i_dim]; ++i)
1531 _readOneEntity(i_dim, i);
1542void MshParallelMeshReader::
1543_readOneEntity(
Int32 entity_dim,
Int32 entity_index_in_dim)
1558 info() <<
"[Entities] Reading entity dim=" << entity_dim <<
" index_in_dim=" << entity_index_in_dim;
1560 dim_and_tag_info.
add(entity_dim);
1562 Int32 tag = _getInt32();
1563 dim_and_tag_info.
add(tag);
1564 Real3 min_pos = _getReal3();
1565 Real3 max_pos = _getReal3();
1566 Int64 nb_physical_tag = _getInt64();
1567 dim_and_tag_info.
add(nb_physical_tag);
1568 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1569 Int32 physical_tag = _getInt32();
1570 dim_and_tag_info.
add(physical_tag);
1571 info(4) <<
"[Entities] z=" << z <<
" physical_tag=" << physical_tag;
1574 Int64 nb_bounding_group = _getInt64();
1575 dim_and_tag_info.
add(nb_bounding_group);
1576 for (Int64 z = 0; z < nb_bounding_group; ++z) {
1577 Int32 boundary_tag = _getInt32();
1578 info(4) <<
"[Entities] z=" << z <<
" boundary_tag=" << boundary_tag;
1580 info(4) <<
"[Entities] dim=" << entity_dim <<
" tag=" << tag
1581 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
1582 <<
" nb_phys_tag=" << nb_physical_tag
1583 <<
" nb_bounding=" << nb_bounding_group;
1585 Int32 info_size = dim_and_tag_info.
size();
1586 m_parallel_mng->broadcast(ArrayView<Int32>(1, &info_size), m_master_io_rank);
1587 dim_and_tag_info.
resize(info_size);
1588 m_parallel_mng->broadcast(dim_and_tag_info.
view(), m_master_io_rank);
1592 Int64 tag = dim_and_tag_info[1];
1593 Int64 nb_physical_tag = dim_and_tag_info[2];
1594 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1595 Int64 physical_tag = dim_and_tag_info[3 + z];
1596 info(4) <<
"[Entities] adding info dim=" << entity_dim <<
" tag=" << tag
1597 <<
" physical_tag=" << physical_tag;
1598 m_mesh_info->entities_with_nodes_list[dim - 1].add(MshEntitiesWithNodes(dim, tag, physical_tag));
1628 Int64 nb_link = _getInt64AndBroadcast();
1629 info() <<
"[Periodic] nb_link=" << nb_link;
1634 MshPeriodicInfo& periodic_info = m_mesh_info->m_periodic_info;
1635 periodic_info.m_periodic_list.resize(nb_link);
1636 for (
Int64 ilink = 0; ilink < nb_link; ++ilink) {
1637 MshPeriodicOneInfo& one_info = periodic_info.m_periodic_list[ilink];
1639 _getInt32ArrayAndBroadcast(entity_info.
view());
1641 info() <<
"[Periodic] link_index=" << ilink <<
" dim=" << entity_info[0] <<
" entity_tag=" << entity_info[1]
1642 <<
" entity_tag_master=" << entity_info[2];
1643 one_info.m_entity_dim = entity_info[0];
1644 one_info.m_entity_tag = entity_info[1];
1645 one_info.m_entity_tag_master = entity_info[2];
1647 Int64 num_affine = _getInt64AndBroadcast();
1648 info() <<
"[Periodic] num_affine=" << num_affine;
1652 info() <<
"[Periodic] nb_corresponding_node=" << one_info.m_nb_corresponding_node;
1661 if (s !=
"$EndPeriodic")
1662 ARCANE_FATAL(
"found '{0}' and expected '$EndPeriodic'", s);
1675 constexpr Int32 MAX_SIZE = 128;
1680 if (read_size >= MAX_SIZE)
1681 ARCANE_FATAL(
"local buffer is too small (size={0} max={1})", read_size, MAX_SIZE);
1682 IosFile* f = m_ios_file.get();
1684 f->binaryRead(bytes_to_read);
1685 s =
String(bytes_to_read);
1686 info() <<
"S=" << s;
1687 if (m_is_parallel) {
1688 m_parallel_mng->broadcastString(s, m_master_io_rank);
1696 if (s != expected_value)
1697 ARCANE_FATAL(
"found '{0}' and expected '{1}'", s, expected_value);
1704void MshParallelMeshReader::
1709 info() <<
"Reading 'msh' file in parallel";
1713 const int MSH_BINARY_TYPE = 1;
1716 Real version = ios_file->getReal();
1718 ARCANE_THROW(
IOException,
"Wrong msh file version '{0}'. Only version '4.1' is supported in parallel", version);
1719 Integer file_type = ios_file->getInteger();
1720 if (file_type == MSH_BINARY_TYPE)
1724 pwarning() <<
"MSH reader for binary format is experimental";
1725 Int32 data_size = ios_file->getInteger();
1726 ARCANE_UNUSED(data_size);
1728 ARCANE_FATAL(
"Only 'size_t' of size '8' is allowed (current size is '{0}')", data_size);
1733 Int32 int_value_one = 0;
1735 if (int_value_one != 1)
1736 ARCANE_FATAL(
"Bad endianess for file. Read int as value '{0}' (expected=1)", int_value_one);
1739 ios_file->getNextLine();
1742 if (!ios_file->lookForString(
"$EndMeshFormat"))
1752 if (next_line ==
"$PhysicalNames") {
1753 _readPhysicalNames();
1759 if (next_line ==
"$Entities") {
1764 if (next_line !=
"$Nodes")
1765 ARCANE_THROW(IOException,
"Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1771 if (ios_file && !ios_file->lookForString(
"$EndNodes"))
1775 if (ios_file && !ios_file->lookForString(
"$Elements"))
1781 if (ios_file && !ios_file->lookForString(
"$EndElements"))
1784 info() <<
"Computed mesh dimension = " << mesh_dimension;
1789 info() <<
"NextLine=" << next_line;
1795 if (next_line ==
"$Periodic") {
1808void MshParallelMeshReader::
1813 _addMshTypeInfo(MSH_PNT, ITI_Vertex);
1814 _addMshTypeInfo(MSH_LIN_2, ITI_Line2);
1815 _addMshTypeInfo(MSH_TRI_3, ITI_Triangle3);
1816 _addMshTypeInfo(MSH_QUA_4, ITI_Quad4);
1817 _addMshTypeInfo(MSH_TET_4, ITI_Tetraedron4);
1818 _addMshTypeInfo(MSH_HEX_8, ITI_Hexaedron8);
1819 _addMshTypeInfo(MSH_PRI_6, ITI_Pentaedron6);
1820 _addMshTypeInfo(MSH_PYR_5, ITI_Pyramid5);
1821 _addMshTypeInfo(MSH_TRI_6, ITI_Triangle6);
1823 FixedArray<Int16, 10> x({ 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 });
1824 _addMshTypeInfo(MSH_TET_10, ITI_Tetraedron10, x.view());
1827 FixedArray<Int16, 20> x({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 13, 9, 16, 18, 19, 17, 10, 12, 14, 15 });
1828 _addMshTypeInfo(MSH_HEX_20, ITI_Hexaedron20, x.view());
1835void MshParallelMeshReader::
1842 ItemTypeMng* item_type_mng = m_mesh->itemTypeMng();
1843 ItemTypeInfo* iti = item_type_mng->typeFromId(arcane_type);
1851mshToArcaneTypeInfo(
Int32 msh_type)
const
1855 if (tx.m_arcane_type_info)
1858 ARCANE_THROW(NotSupportedException,
"MSH type '{0}' is not supported in Arcane", msh_type);
1869 m_mesh_info = impl::MshMeshGenerationInfo::getReference(
mesh,
true);
1870 info() <<
"Trying to read in parallel 'msh' file '" << filename <<
"'"
1871 <<
" use_internal_partition=" << use_internal_partition;
1875 if (!use_internal_partition)
1877 m_parallel_mng = pm;
1898 m_master_io_rank = master_io_rank;
1904 info() <<
"Is file readable ?=" << is_readable;
1905 file_readable[0] = is_readable ? 1 : 0;
1907 error() <<
"Unable to read file '" << filename <<
"'";
1909 pm->broadcast(file_readable.
view(), master_io_rank);
1910 if (file_readable[0] == 0) {
1914 std::ifstream ifile;
1920 m_ios_file = ios_file;
1922 if (IosFile::isEqualString(mesh_format_str,
"$MeshFormat")) {
1923 _readMeshFromFile();
1924 if (!use_internal_partition) {
1925 info() <<
"Synchronize groups and variables";
1926 mesh->synchronizeGroupsAndVariables();
1931 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
1939createMshParallelMeshReader(
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.
bool reorderNodesOfFace2(Int64ConstArrayView nodes_unique_id, IntegerArrayView new_index)
Réordonne les noeuds d'une face.
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.
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.
static constexpr Int32 size()
Nombre d'éléments tu 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.
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 _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.
void _addFaceGroup(MshElementBlock &block, const String &group_name)
Ajoute des faces au groupe group_name.
Vue sur les informations des noeuds.
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.
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.
TraceMessage pwarning() const
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