14#include "arcane/utils/ITraceMng.h"
15#include "arcane/utils/SmallArray.h"
16#include "arcane/utils/FixedArray.h"
17#include "arcane/utils/Convert.h"
18#include "arcane/utils/CheckedConvert.h"
20#include "arcane/core/IMeshReader.h"
21#include "arcane/core/BasicService.h"
23#include "arcane/core/IPrimaryMesh.h"
24#include "arcane/core/IItemFamily.h"
25#include "arcane/core/ICaseMeshReader.h"
26#include "arcane/core/IMeshBuilder.h"
27#include "arcane/core/IParallelMng.h"
28#include "arcane/core/MeshPartInfo.h"
29#include "arcane/core/NodesOfItemReorderer.h"
31#include "arcane/core/ItemPrinter.h"
32#include "arcane/core/internal/ItemTypeMngInternal.h"
65 class MEDToArcaneItemInfo
69 MEDToArcaneItemInfo(
int dimension,
int nb_node, med_int med_type,
71 : m_dimension(dimension)
73 , m_med_type(med_type)
74 , m_arcane_type(arcane_type)
75 , m_indirection(indirection)
80 int dimension()
const {
return m_dimension; }
81 int nbNode()
const {
return m_nb_node; }
82 med_int medType()
const {
return m_med_type; }
83 Int16 arcaneType()
const {
return m_arcane_type; }
84 const Int32* indirection()
const {
return m_indirection; }
90 med_int m_med_type = {};
92 const Int32* m_indirection =
nullptr;
100 explicit MEDFamilyInfo(
Int32 family_id)
124 explicit MEDGroupInfo(
Int32 index)
145 _initMEDToArcaneTypes();
162 explicit AutoCloseMED(med_idt
id)
175 IPrimaryMesh* m_mesh =
nullptr;
177 UniqueArray<MEDToArcaneItemInfo> m_med_to_arcane_types;
179 std::unordered_map<med_int, Int32> m_med_geotype_to_arcane_type_index;
181 std::unordered_map<Int32, MEDFamilyInfo> m_med_families_map;
183 UniqueArray<MEDGroupInfo> m_med_groups;
185 UniqueArray<med_int> m_med_geotypes_in_mesh;
190 Array<Int16>& poly_nb_nodes, Array<Int16>& poly_types, Array<med_int>& connectivity, Array<med_int>& family_values);
191 void _initMEDToArcaneTypes();
192 void _addTypeInfo(
int dimension,
int nb_node, med_int med_type, ItemTypeId arcane_type)
194 _addTypeInfo(dimension, nb_node, med_type, arcane_type,
nullptr);
196 void _addTypeInfo(
int dimension,
int nb_node, med_int med_type, ItemTypeId arcane_type,
197 const Int32* indirection)
200 Int32 index = m_med_to_arcane_types.size();
201 m_med_to_arcane_types.add(t);
202 m_med_geotype_to_arcane_type_index.insert(std::make_pair(med_type, index));
204 void _readAndCreateCells(IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname);
205 void _readFaces(IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname);
208 _readNodesCoordinates(IPrimaryMesh* mesh,
Int64 nb_node,
Int32 spacedim,
209 med_idt fid,
const char* meshname);
210 void _readFamilies(med_idt fid,
const char* meshname);
211 void _readAvailableTypes(med_idt fid,
const char* meshname);
212 void _clearItemsInGroups()
215 g.m_unique_ids.clear();
216 g.m_local_ids.clear();
219 void _broadcastGroups(ConstArrayView<String> names, IItemFamily* family);
220 med_int _readPolyhedrons(IPrimaryMesh* mesh, med_idt fid,
const char* meshname,
221 Array<Int16>& poly_nb_nodes,
222 Array<Int16>& poly_types_id,
223 Array<med_int>& connectivity);
233 const Int32 Hexaedron8_indirection[] = { 1, 0, 3, 2, 5, 4, 7, 6 };
234 const Int32 Hexaedron20_indirection[] = { 1, 8, 10, 3, 9, 2, 0, 11, 5, 14, 18, 7, 6, 4, 16, 15, 13, 12, 17, 19 };
235 const Int32 Pyramid5_indirection[] = { 1, 0, 3, 2, 4 };
236 const Int32 Quad4_indirection[] = { 1, 0, 3, 2 };
237 const Int32 Quad8_indirection[] = { 1, 0, 3, 2, 4, 7, 6, 5 };
238 const Int32 Triangle3_indirection[] = { 1, 0, 2 };
240 const Int32 Tetraedron4_indirection[] = { 1, 0, 2, 3 };
247_initMEDToArcaneTypes()
249 m_med_to_arcane_types.clear();
254 _addTypeInfo(1, 2, MED_SEG2, ITI_Line2);
255 _addTypeInfo(1, 3, MED_SEG3, ITI_Line3);
256 _addTypeInfo(1, 4, MED_SEG4, ITI_NullType);
259 _addTypeInfo(2, 3, MED_TRIA3, ITI_Triangle3, Triangle3_indirection);
260 _addTypeInfo(2, 4, MED_QUAD4, ITI_Quad4, Quad4_indirection);
261 _addTypeInfo(2, 6, MED_TRIA6, ITI_NullType);
262 _addTypeInfo(2, 7, MED_TRIA7, ITI_NullType);
263 _addTypeInfo(2, 8, MED_QUAD8, ITI_Quad8, Quad8_indirection);
264 _addTypeInfo(2, 9, MED_QUAD9, ITI_NullType);
267 _addTypeInfo(3, 4, MED_TETRA4, ITI_Tetraedron4);
268 _addTypeInfo(3, 5, MED_PYRA5, ITI_Pyramid5, Pyramid5_indirection);
269 _addTypeInfo(3, 6, MED_PENTA6, ITI_Pentaedron6);
270 _addTypeInfo(3, 8, MED_HEXA8, ITI_Hexaedron8);
271 _addTypeInfo(3, 10, MED_TETRA10, ITI_Tetraedron10);
272 _addTypeInfo(3, 12, MED_OCTA12, ITI_Octaedron12);
273 _addTypeInfo(3, 13, MED_PYRA13, ITI_NullType);
274 _addTypeInfo(3, 15, MED_PENTA15, ITI_NullType);
275 _addTypeInfo(3, 18, MED_PENTA18, ITI_NullType);
276 _addTypeInfo(3, 20, MED_HEXA20, ITI_Hexaedron20);
277 _addTypeInfo(3, 27, MED_HEXA27, ITI_NullType);
285 _addTypeInfo(2, 0, MED_POLYGON, ITI_GenericPolygon);
286 _addTypeInfo(2, 0, MED_POLYGON2, ITI_NullType);
287 _addTypeInfo(3, 0, MED_POLYHEDRON, ITI_GenericPolyhedron);
301 info() <<
"Trying to read MED File name=" << file_name;
303 return _readMesh(mesh, file_name);
312 const med_idt fid = MEDfileOpen(filename.localstr(), MED_ACC_RDONLY);
314 MESSAGE(
"ERROR: can not open MED file ");
315 error() <<
"ERROR: can not open MED file '" << filename <<
"'";
319 AutoCloseMED auto_close_med(fid);
321 int nb_mesh = MEDnMesh(fid);
323 error() <<
"Error reading number of meshes";
326 info() <<
"MED: nb_mesh=" << nb_mesh;
328 error() <<
"No mesh is present";
336 int nb_axis = MEDmeshnAxis(fid, mesh_index);
338 error() <<
"Can not read number of axis (MEDmeshnAxis)";
341 info() <<
"MED: nb_axis=" << nb_axis;
343 UniqueArray<char> axisname(MED_SNAME_SIZE * nb_axis + 1,
'\0');
344 UniqueArray<char> unitname(MED_SNAME_SIZE * nb_axis + 1,
'\0');
346 char meshname[MED_NAME_SIZE + 1];
348 char meshdescription[MED_COMMENT_SIZE + 1];
349 meshdescription[0] =
'\0';
350 char dtunit[MED_SNAME_SIZE + 1];
352 med_int spacedim = 0;
354 med_mesh_type meshtype = MED_UNDEF_MESH_TYPE;
355 med_sorting_type sortingtype = MED_SORT_UNDEF;
357 med_axis_type axistype = MED_UNDEF_AXIS_TYPE;
359 err = MEDmeshInfo(fid, mesh_index, meshname, &spacedim, &meshdim, &meshtype, meshdescription,
360 dtunit, &sortingtype, &nstep, &axistype, axisname.data(), unitname.data());
362 error() <<
"Can not read mesh info (MEDmeshInfo) r=" << err;
365 if (meshtype != MED_UNSTRUCTURED_MESH) {
366 error() <<
"Arcane handle only MED unstructured mesh (MED_UNSTRUCTURED_MESH) type=" << meshtype;
369 Integer mesh_dimension = meshdim;
370 if (mesh_dimension != 2 && mesh_dimension != 3)
371 ARCANE_FATAL(
"MED reader handles only 2D or 3D meshes");
373 info() <<
"MED: name=" << meshname;
374 info() <<
"MED: description=" << meshdescription;
375 info() <<
"MED: spacedim=" << spacedim;
376 info() <<
"MED: meshdim=" << meshdim;
377 info() <<
"MED: dtunit=" << dtunit;
378 info() <<
"MED: meshtype=" << meshtype;
379 info() <<
"MED: sortingtype=" << sortingtype;
380 info() <<
"MED: axistype=" << axistype;
381 info() <<
"MED: nstep=" << nstep;
386 med_bool coordinatechangement;
387 med_bool geotransformation;
390 med_int med_nb_node = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE,
391 MED_COORDINATE, MED_NO_CMODE, &coordinatechangement,
393 if (med_nb_node < 0) {
394 error() <<
"Can not read number of nodes (MEDmeshnEntity) err=" << med_nb_node;
397 nb_node = med_nb_node;
399 info() <<
"MED: nb_node=" << nb_node;
401 mesh->setDimension(mesh_dimension);
406 mesh->itemTypeMng()->buildPolygonTypes();
408 IParallelMng* pm = mesh->parallelMng();
409 bool is_parallel = pm->isParallel();
410 Int32 rank = mesh->meshPartInfo().partRank();
412 bool is_read_items = !(is_parallel && rank != 0);
414 _readAvailableTypes(fid, meshname);
415 _readFamilies(fid, meshname);
416 _readAndCreateCells(mesh, mesh_dimension, fid, meshname);
425 UniqueArray<String> cell_group_names;
426 IItemFamily* cell_family = mesh->cellFamily();
433 UniqueArray<Int32> cell_local_ids;
435 Int32 nb_cell_in_group = g.m_unique_ids.size();
436 cell_local_ids.resize(nb_cell_in_group);
437 cell_family->itemsUniqueIdToLocalId(cell_local_ids, g.m_unique_ids);
438 for (
const String& name : g.m_names) {
439 info() <<
"Group=" << name <<
" index=" << g.m_index <<
" nb_item=" << nb_cell_in_group;
440 CellGroup cell_group = cell_family->findGroup(name,
true);
441 cell_group.
addItems(cell_local_ids);
442 cell_group_names.add(name);
446 _broadcastGroups(cell_group_names, cell_family);
453 bool is_face_group_disabled =
false;
455 is_face_group_disabled = (v.value());
456 if (!is_face_group_disabled)
457 _readFaces(mesh, mesh_dimension, fid, meshname);
460 UniqueArray<String> face_group_names;
461 IItemFamily* face_family = mesh->faceFamily();
465 Int32 nb_face_in_group = g.m_local_ids.size();
466 info() <<
"Check Group index=" << g.m_index <<
" nb_item=" << nb_face_in_group;
467 if (nb_face_in_group == 0)
469 for (
const String& name : g.m_names) {
470 info() <<
"FaceGroup=" << name <<
" index=" << g.m_index <<
" nb_item=" << nb_face_in_group;
471 FaceGroup face_group = face_family->findGroup(name,
true);
473 face_group_names.add(name);
477 _broadcastGroups(face_group_names, face_family);
481 return _readNodesCoordinates(mesh, nb_node, spacedim, fid, meshname);
492_readAvailableTypes(med_idt fid,
const char* meshname)
495 med_bool coordinatechangement;
496 med_bool geotransformation;
497 med_int nb_geo = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_GEO_ALL,
498 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
501 ARCANE_FATAL(
"Can not read number of geometric entities nb_geo={0}", nb_geo);
502 info() <<
"MED: nb_geotype = " << nb_geo;
505 for (med_int it = 1; it <= nb_geo; it++) {
507 med_geometry_type geotype = MED_GEO_ALL;
508 FixedArray<char, MED_NAME_SIZE + 1> geotype_name;
511 med_int type_ret = MEDmeshEntityInfo(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, it,
512 geotype_name.data(), &geotype);
514 ARCANE_FATAL(
"Can not read informations for geotype index={0} ret={1}", it, type_ret);
516 med_int nb_item = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, geotype,
517 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
520 ARCANE_FATAL(
"Can not read number of items for geotype={0} name={1} ret={2}",
521 geotype, geotype_name.data(), nb_item);
522 info() <<
"MED: type=" << geotype <<
" '" << geotype_name.data() <<
"' nb_item=" << nb_item;
523 m_med_geotypes_in_mesh.add(geotype);
531_readAndCreateCells(
IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname)
533 _clearItemsInGroups();
538 Int64 cell_unique_id = 0;
541 UniqueArray<Int16> poly_nb_nodes;
543 UniqueArray<Int16> poly_types_id;
544 UniqueArray<med_int> med_connectivity;
545 UniqueArray<med_int> med_family_values;
550 for (med_int geotype : m_med_geotypes_in_mesh) {
551 Int32 index_in_list = m_med_geotype_to_arcane_type_index[geotype];
554 Int32 item_dimension = iinfo.dimension();
556 if (item_dimension != mesh_dimension)
558 Int32 nb_item = _readItems(mesh, fid, meshname, iinfo, poly_nb_nodes, poly_types_id, med_connectivity, med_family_values);
562 Int16 arcane_type = iinfo.arcaneType();
563 Int32 nb_item_node = iinfo.nbNode();
564 Int32 nb_family_values = med_family_values.size();
565 if (arcane_type == IT_NullType) {
567 ARCANE_FATAL(
"MED type '{0}' is not supported by Arcane", iinfo.medType());
569 Int64 cells_infos_index = 0;
570 Int64 med_connectivity_index = 0;
571 const bool is_poly = (iinfo.medType() == MED_POLYGON) || (iinfo.medType() == MED_POLYHEDRON);
574 mesh->itemTypeMng()->setMeshWithGeneralCells(mesh);
575 UniqueArray<Int64> cells_infos;
577 cells_infos.resize(2 * nb_item + med_connectivity.size());
579 cells_infos.resize((2 + nb_item_node) * nb_item);
581 info() <<
"CELL_INFOS size=" << cells_infos.size() <<
" nb_item=" << nb_item
582 <<
" type=" << arcane_type;
584 const Int32* indirection = iinfo.indirection();
585 for (
Int32 i = 0; i < nb_item; ++i) {
586 Int64 current_cell_unique_id = cell_unique_id;
589 nb_item_node = poly_nb_nodes[i];
590 arcane_type = poly_types_id[i];
591 cells_infos[cells_infos_index] = arcane_type;
593 cells_infos[cells_infos_index] = current_cell_unique_id;
595 Span<Int64> cinfo_span(cells_infos.span().subspan(cells_infos_index, nb_item_node));
596 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
597 for (
Integer k = 0; k < nb_item_node; ++k) {
598 cinfo_span[k] = med_cinfo_span[k];
602 cells_infos[cells_infos_index] = arcane_type;
604 cells_infos[cells_infos_index] = current_cell_unique_id;
606 Span<Int64> cinfo_span(cells_infos.span().subspan(cells_infos_index, nb_item_node));
607 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
609 for (
Integer k = 0; k < nb_item_node; ++k) {
610 cinfo_span[k] = med_cinfo_span[indirection[k]];
614 for (
Integer k = 0; k < nb_item_node; ++k)
615 cinfo_span[k] = med_cinfo_span[k];
618 if (i < nb_family_values) {
620 med_int f = med_family_values[i];
621 auto x = m_med_families_map.find(f);
622 if (x == m_med_families_map.end()) {
623 ARCANE_FATAL(
"Can not find family id '{0}' for cell '{1}' of geotype '{2}'",
624 f, i, iinfo.medType());
626 m_med_groups[x->second.m_index].m_unique_ids.add(current_cell_unique_id);
629 med_connectivity_index += nb_item_node;
630 cells_infos_index += nb_item_node;
632 mesh->allocateCells(nb_item, cells_infos,
false);
646_readFaces(
IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname)
648 _clearItemsInGroups();
649 ItemTypeMng* itm = mesh->itemTypeMng();
650 NodesOfItemReorderer nodes_reorderer(itm);
652 IItemFamily* node_family = mesh->nodeFamily();
653 NodeInfoListView mesh_nodes(node_family);
655 UniqueArray<Int16> poly_nb_nodes;
656 UniqueArray<Int16> poly_types_id;
657 UniqueArray<med_int> med_connectivity;
658 UniqueArray<med_int> med_family_values;
661 for (med_int geotype : m_med_geotypes_in_mesh) {
662 Int32 index_in_list = m_med_geotype_to_arcane_type_index[geotype];
665 Int32 item_dimension = iinfo.dimension();
667 if (item_dimension != (mesh_dimension - 1))
669 ItemTypeInfo* iti = itm->typeFromId(iinfo.arcaneType());
670 info() <<
"Reading faces geotype=" << geotype <<
" arcane_type=" << iinfo.arcaneType()
671 <<
" " << iti->typeName();
673 const bool is_polygon = (iinfo.medType() == MED_POLYGON);
675 Int32 nb_item = _readItems(mesh, fid, meshname, iinfo, poly_nb_nodes, poly_types_id, med_connectivity, med_family_values);
679 ItemTypeId arcane_type(iinfo.arcaneType());
680 Int32 nb_item_node = iinfo.nbNode();
681 Int32 nb_family_values = med_family_values.size();
682 if (arcane_type == IT_NullType) {
684 ARCANE_FATAL(
"MED type '{0}' is not supported by Arcane", iinfo.medType());
687 SmallArray<Int64> orig_nodes_id(nb_item_node);
688 info() <<
"FACES_INFOS nb_item=" << nb_item <<
" type=" << arcane_type
689 <<
" nb_family_values=" << nb_family_values <<
" connectivity_size=" << med_connectivity.size();
691 const Int32* indirection = iinfo.indirection();
692 Int64 med_connectivity_index = 0;
694 for (
Int32 i = 0; i < nb_item; ++i) {
695 ArrayView<Int64> cinfo_span(orig_nodes_id);
698 nb_item_node = poly_nb_nodes[i];
699 orig_nodes_id.resize(nb_item_node);
700 cinfo_span = orig_nodes_id;
701 arcane_type = ItemTypeId(poly_types_id[i]);
703 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
705 for (
Integer k = 0; k < nb_item_node; ++k) {
706 cinfo_span[k] = med_cinfo_span[indirection[k]];
710 for (
Integer k = 0; k < nb_item_node; ++k)
711 cinfo_span[k] = med_cinfo_span[k];
714 med_connectivity_index += nb_item_node;
716 nodes_reorderer.reorder(arcane_type, cinfo_span);
717 ConstArrayView<Int64> ordered_nodes = nodes_reorderer.sortedNodes();
721 Node first_node(MeshUtils::findOneItem(node_family, ordered_nodes[0]));
722 if (first_node.null())
723 ARCANE_FATAL(
"Can not find node uid={0} for face index '{1}'", ordered_nodes[0], i);
724 Face face = MeshUtils::getFaceFromNodesUniqueId(first_node, ordered_nodes);
726 info() <<
"ERROR: Can not find face in mesh i=" << i <<
" nodes=" << ordered_nodes;
727 info() <<
"List of faces for node=" << ItemPrinter(first_node);
728 for (Face subface : first_node.faces()) {
729 info() <<
"Face=" << ItemPrinter(subface);
730 for (Node subnode : subface.nodes()) {
731 info() <<
" Node=" << ItemPrinter(subnode);
734 ARCANE_FATAL(
"Can not find face with nodes=", ordered_nodes);
739 if (i < nb_family_values) {
741 med_int f = med_family_values[i];
742 auto x = m_med_families_map.find(f);
743 if (x == m_med_families_map.end()) {
744 ARCANE_FATAL(
"Can not find family id '{0}' for face '{1}' of geotype '{2}'",
745 f, i, iinfo.medType());
748 m_med_groups[x->second.m_index].m_local_ids.add(face.localId());
751 info() <<
"END_READING_ITEMS";
760 med_idt fid,
const char* meshname)
762 const bool do_verbose =
false;
767 UniqueArray<Real3> nodes_coordinates(nb_node + 1);
769 UniqueArray<med_float> coordinates(nb_node * spacedim);
770 int err = MEDmeshNodeCoordinateRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE,
773 error() <<
"Can not read nodes coordinates err=" << err;
778 for (
Int64 i = 0; i < nb_node; ++i) {
779 Real3 xyz(coordinates[i * 3], coordinates[(i * 3) + 1], coordinates[(i * 3) + 2]);
781 info() <<
"I=" << i <<
" XYZ=" << xyz;
782 nodes_coordinates[i + 1] = xyz;
785 else if (spacedim == 2) {
786 for (
Int64 i = 0; i < nb_node; ++i) {
787 Real3 xyz(coordinates[i * 2], coordinates[(i * 2) + 1], 0.0);
789 info() <<
"I=" << i <<
" XYZ=" << xyz;
790 nodes_coordinates[i + 1] = xyz;
794 ARCANE_THROW(NotImplementedException,
"spacedim!=2 && spacedim!=3");
802 nodes_coord_var[inode] = nodes_coordinates[node.uniqueId()];
825_readItems(
IPrimaryMesh* mesh, med_idt fid,
const char* meshname,
826 const MEDToArcaneItemInfo& iinfo,
832 constexpr bool is_verbose =
false;
834 connectivity.clear();
835 family_values.clear();
837 ItemTypeMng* itm = mesh->itemTypeMng();
838 int med_item_type = iinfo.medType();
839 med_bool coordinatechangement = {};
840 med_bool geotransformation = {};
841 med_int nb_med_item = 0;
842 if (iinfo.medType() == MED_POLYHEDRON) {
843 nb_med_item = _readPolyhedrons(mesh, fid, meshname, poly_nb_nodes, poly_types_id, connectivity);
845 else if (iinfo.medType() == MED_POLYGON) {
848 med_int nb_index = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
849 MED_INDEX_NODE, MED_NODAL, &coordinatechangement,
852 ARCANE_FATAL(
"Can not read MED med_item_type '{0}' error={1}", med_item_type, nb_index);
854 info() <<
"MED: Reading items";
855 info() <<
"MED: type=" << med_item_type <<
" nb_index=" << nb_index;
858 nb_med_item = nb_index - 1;
859 poly_nb_nodes.resize(nb_med_item);
860 poly_types_id.resize(nb_med_item);
862 med_int nb_connectivity = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
863 MED_CELL, MED_POLYGON, MED_CONNECTIVITY, MED_NODAL,
864 &coordinatechangement, &geotransformation);
865 if (nb_connectivity < 0)
866 ARCANE_FATAL(
"Can not get connectivity size for MED_POLYGON err={0}", nb_connectivity);
871 UniqueArray<med_int> indexes(nb_index);
872 connectivity.resize(nb_connectivity);
873 info() <<
"Reading polygons nb_connectivity=" << nb_connectivity;
874 int r = MEDmeshPolygonRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_NODAL,
875 indexes.data(), connectivity.data());
877 ARCANE_FATAL(
"Can not read connectivity for MED_POLYGON err={0}", r);
878 info() <<
"INDEXES=" << indexes;
879 for (
Int32 i = 0; i < nb_med_item; ++i) {
880 Int16 nb_node_for_cell = CheckedConvert::toInt16(indexes[i + 1] - indexes[i]);
881 poly_nb_nodes[i] = nb_node_for_cell;
882 poly_types_id[i] = itm->getPolygonType(
static_cast<Int16>(nb_node_for_cell));
886 nb_med_item = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
887 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
890 ARCANE_FATAL(
"Can not read MED med_item_type '{0}' error={1}", med_item_type, nb_med_item);
892 info() <<
"MED: Reading items";
893 info() <<
"MED: type=" << med_item_type <<
" nb_item=" << nb_med_item;
894 if (nb_med_item == 0)
897 Int64 nb_node = iinfo.nbNode();
900 ARCANE_THROW(NotImplementedException,
"Reading items with MED type '{0}'", med_item_type);
902 connectivity.resize(nb_node * nb_med_item);
903 int err = MEDmeshElementConnectivityRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL,
904 med_item_type, MED_NODAL, MED_FULL_INTERLACE,
905 connectivity.data());
907 ARCANE_FATAL(
"Can not read connectivity MED med_item_type '{0}' error={1}",
911 info() <<
"CON: " << connectivity;
913 med_int nb_med_family = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
914 MED_CELL, med_item_type, MED_FAMILY_NUMBER, MED_NODAL,
915 &coordinatechangement, &geotransformation);
916 info() <<
"nb_family=" << nb_med_family;
917 if (nb_med_family < 0)
918 ARCANE_FATAL(
"Can not read family size for type med_item_type={0} error={1}", med_item_type, nb_med_family);
919 if (nb_med_family > 0) {
920 family_values.resize(nb_med_family);
921 int r = MEDmeshEntityFamilyNumberRd(fid, meshname, MED_NO_DT, MED_NO_IT,
922 MED_CELL, med_item_type, family_values.data());
924 ARCANE_FATAL(
"Can not read family values for type med_item_type={0} error={1}", med_item_type, nb_med_family);
926 info() <<
"FAM: " << family_values;
935med_int MEDMeshReader::
936_readPolyhedrons(
IPrimaryMesh* mesh, med_idt fid,
const char* meshname,
941 if (mesh->parallelMng()->commSize() > 1)
942 ARCANE_FATAL(
"MED polyhedral mesh in not support in parallel");
943 const bool is_verbose =
false;
944 ItemTypeMngInternal* itmi = mesh->itemTypeMng()->_internalApi();
945 med_bool coordinatechangement = {};
946 med_bool geotransformation = {};
947 const med_int med_item_type = MED_POLYHEDRON;
948 info() <<
"MED: Reading polyhedron items";
950 med_int nb_face_index = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
951 MED_INDEX_FACE, MED_NODAL, &coordinatechangement,
953 if (nb_face_index < 0)
954 ARCANE_FATAL(
"Can not read MED_INDEX_FACE for Polyhedron type error={0}", nb_face_index);
955 info() <<
"MED: type=" << med_item_type <<
" nb_face_index=" << nb_face_index;
956 if (nb_face_index < 1)
959 med_int nb_node_index = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
960 MED_INDEX_NODE, MED_NODAL, &coordinatechangement,
962 if (nb_node_index < 0)
963 ARCANE_FATAL(
"Can not read MED_INDEX_NODE for Polyhedron type error={0}", nb_node_index);
965 info() <<
"MED: type=" << med_item_type <<
" nb_face_index=" << nb_face_index <<
" nb_node_index=" << nb_node_index;
966 med_int nb_med_item = nb_face_index - 1;
967 poly_nb_nodes.resize(nb_med_item);
968 poly_types_id.resize(nb_med_item);
970 med_int nb_connectivity = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
971 MED_CELL, MED_POLYHEDRON, MED_CONNECTIVITY, MED_NODAL,
972 &coordinatechangement, &geotransformation);
973 if (nb_connectivity < 0)
974 ARCANE_FATAL(
"Can not get connectivity size for MED_POLYHEDRON err={0}", nb_connectivity);
979 UniqueArray<med_int> face_indexes(nb_face_index);
980 UniqueArray<med_int> node_indexes(nb_node_index);
981 connectivity.clear();
982 connectivity.reserve(nb_connectivity);
983 UniqueArray<med_int> med_connectivity(nb_connectivity);
984 info() <<
"Reading polyhedron nb_connectivity=" << nb_connectivity;
985 int r = MEDmeshPolyhedronRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_NODAL,
986 face_indexes.data(), node_indexes.data(), med_connectivity.data());
988 ARCANE_FATAL(
"Can not read connectivity for MED_POLYGON err={0}", r);
990 info() <<
"FACE_INDEXES=" << face_indexes;
991 info() <<
"NODE_INDEXES=" << node_indexes;
992 info() <<
"CONNECTIVITY=" << med_connectivity;
994 UniqueArray<Int16> local_nodes_of_cell;
995 UniqueArray<Int32> nodes_of_cell;
996 UniqueArray<Int32> nodes_of_face;
999 UniqueArray<Int16> arcane_faces_nb_node;
1000 UniqueArray<Int16> arcane_faces_nodes;
1002 std::map<Int32, Int16> connectivity_to_local_index;
1003 for (
Int32 z = 0; z < nb_med_item; ++z) {
1004 Int16 nb_local_node = 0;
1005 nodes_of_cell.clear();
1006 connectivity_to_local_index.clear();
1007 local_nodes_of_cell.clear();
1008 arcane_faces_nb_node.clear();
1009 arcane_faces_nodes.clear();
1010 Int32 connectivity_index = connectivity.size();
1012 Int32 first_face_index = face_indexes[z] - 1;
1013 Int32 next_face_index = face_indexes[z + 1] - 1;
1014 Int32 cell_nb_face = next_face_index - first_face_index;
1015 Int32 cell_nb_node = node_indexes[next_face_index] - node_indexes[first_face_index];
1017 info() <<
"POLYHEDRAL_CELL=" << z <<
" nb_face=" << cell_nb_face
1018 <<
" nb_node=" << cell_nb_node <<
" first_face_index=" << first_face_index
1019 <<
" nb_info_in_connectivity=" << node_indexes[cell_nb_face];
1020 Int16 nb_connectivity_for_cell = 3 + cell_nb_node + cell_nb_face;
1021 connectivity.add(nb_connectivity_for_cell);
1022 const Int64 scheme_version = 1;
1023 connectivity.add(scheme_version);
1024 connectivity.add(cell_nb_face);
1025 for (
Int32 k = 0; k < cell_nb_face; ++k) {
1026 Int32 first_node_index = node_indexes[first_face_index + k] - 1;
1027 Int32 next_node_index = node_indexes[first_face_index + k + 1] - 1;
1028 Int16 face_nb_node = CheckedConvert::toInt16(next_node_index - first_node_index);
1029 nodes_of_face.resize(face_nb_node);
1030 arcane_faces_nb_node.add(face_nb_node);
1031 connectivity.add(face_nb_node);
1032 for (
Int32 p = 0; p < face_nb_node; ++p) {
1034 Int32 node_id = med_connectivity[first_node_index + p];
1035 auto x = connectivity_to_local_index.find(node_id);
1036 Int16 local_node_index = -1;
1037 if (x == connectivity_to_local_index.end()) {
1038 local_node_index = nb_local_node;
1039 connectivity_to_local_index[node_id] = nb_local_node;
1041 local_nodes_of_cell.add(local_node_index);
1042 nodes_of_cell.add(node_id);
1045 local_node_index = x->second;
1046 connectivity.add(node_id);
1047 nodes_of_face[p] = local_node_index;
1048 arcane_faces_nodes.add(local_node_index);
1051 info() <<
" POLYHEDRAL_FACE=" << k <<
" nb_node=" << face_nb_node <<
" nodes=" << nodes_of_face.view();
1055 info() <<
"POLYHEDRAL_CELL=" << z <<
" nb_local_node=" << nodes_of_cell.size() <<
" nodes=" << nodes_of_cell
1056 <<
" nb_connectivity_for_cell=" << nb_connectivity_for_cell;
1057 info() <<
"POLYHEDRAL_CELL=" << z <<
" arcane_faces_nb_node=" << arcane_faces_nb_node <<
" nodes=" << arcane_faces_nodes;
1059 poly_types_id[z] = IT_GenericPolyhedron;
1060 poly_nb_nodes[z] = nb_connectivity_for_cell;
1069_readFamilies(med_idt fid,
const char* meshname)
1071 FixedArray<char, MED_NAME_SIZE + 1> familyname;
1073 info() <<
"Read families";
1076 med_int nb_family = MEDnFamily(fid, meshname);
1078 ARCANE_FATAL(
"Can not read number of families (error={0})", nb_family);
1080 info() <<
"MED: nb_family= " << nb_family;
1081 for (med_int i = 0; i < nb_family; i++) {
1082 info() <<
"MED: Read family i=" << i;
1084 med_int nb_group = MEDnFamilyGroup(fid, meshname, i + 1);
1086 ARCANE_FATAL(
"Can not read number of groups for family index={0}", i);
1087 info() <<
"MED: family index=" << i <<
" nb_group=" << nb_group;
1094 UniqueArray<char> all_group_names(MED_LNAME_SIZE * nb_group + 1);
1095 med_int family_number = 0;
1096 if (MEDfamilyInfo(fid, meshname, i + 1, familyname.data(), &family_number, all_group_names.data()) < 0)
1097 ARCANE_FATAL(
"Can not read group names from family index={0}", i);
1100 Int32 group_index = m_med_groups.size();
1101 med_family.m_index = group_index;
1105 for (
Int32 z = 0; z < nb_group; ++z) {
1107 SmallSpan<char> med_group_name = all_group_names.smallSpan().subSpan(MED_LNAME_SIZE * z, MED_LNAME_SIZE);
1110 SmallArray<Byte, MED_LNAME_SIZE + 1> valid_name;
1112 for (; pos < MED_LNAME_SIZE; ++pos) {
1113 char c = med_group_name[pos];
1116 if (c ==
' ' || c ==
'_')
1118 valid_name.add(
static_cast<Byte>(c));
1120 String name(valid_name.view());
1121 med_group.m_names.add(name);
1122 info() <<
"Family id=" << family_number <<
" group='" << name <<
"'";
1125 m_med_families_map.insert(std::make_pair(family_number, med_family));
1126 m_med_groups.add(med_group);
1140 IParallelMng* pm = m_mesh->parallelMng();
1142 Int32 rank = pm->commRank();
1145 Int32 nb_group = group_names.size();
1146 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
1147 for (String name : group_names)
1148 pm->broadcastString(name, 0);
1152 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
1153 String current_group_name;
1154 for (
Int32 i = 0; i < nb_group; ++i) {
1155 pm->broadcastString(current_group_name, 0);
1156 CellGroup cell_group = family->findGroup(current_group_name,
true);
1169class MEDMeshReaderService
1170:
public BasicService
1184 return str ==
"med";
1187 [[maybe_unused]]
const XmlNode& mesh_element,
1190 [[maybe_unused]]
bool use_internal_partition)
override
1192 ARCANE_UNUSED(dir_name);
1194 return reader.readMesh(mesh, file_name);
1213class MEDCaseMeshReader
1226 , m_read_info(read_info)
1233 ARCANE_UNUSED(build_info);
1238 String fname = m_read_info.fileName();
1239 m_trace_mng->info() <<
"MED Reader (ICaseMeshReader) file_name=" << fname;
1262 if (read_info.format() ==
"med")
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Utility functions for the mesh.
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Base class for 1D data vectors.
Necessary information for reading a mesh file.
Constant view of an array of type T.
static std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Interface for the mesh reading service from the dataset.
Interface of an entity family.
Interface of a mesh creation/reading service.
Interface of the service managing the reading of a mesh.
eReturnType
Types of return codes for a read or write operation.
@ RTError
Error during the operation.
@ RTOk
Operation successfully performed.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Adds entities.
Type of an entity (Item).
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Fills build_info with the necessary information to create the mesh.
Service for reading a mesh in MED format from the dataset.
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Returns a builder to create and read the mesh whose information is specified in read_info.
bool allowExtension(const String &str) override
Checks if the service supports files with the extension str.
void build() override
Build-level construction of the service.
eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_element, const String &file_name, const String &dir_name, bool use_internal_partition) override
Reads a mesh from a file.
Information about a MED entity family.
Int32 m_family_id
Family ID for MED.
Int32 m_index
Index in the Arcane group list.
List of groups and the entities belonging to them.
Int32 m_index
Index of the group in the group list.
UniqueArray< Int64 > m_unique_ids
List of uniqueId() of the group's entities.
UniqueArray< String > m_names
Associated group names.
UniqueArray< Int32 > m_local_ids
List of localId() of the group's entities.
Information for mapping MED types to Arcane types for entities.
Parameters necessary for building a mesh.
Reference to an instance.
Structure containing the information to create a service.
Unicode character string.
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.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
ItemGroupT< Cell > CellGroup
Group of cells.
ItemGroupT< Face > FaceGroup
Group of faces.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
-- 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.
@ ST_SubDomain
The service is used at the subdomain level.
std::int16_t Int16
Signed integer type of 16 bits.
unsigned char Byte
Type of a byte.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.