14#include "arcane/utils/ITraceMng.h"
16#include "arcane/IMeshReader.h"
17#include "arcane/BasicService.h"
18#include "arcane/ServiceFactory.h"
19#include "arcane/IPrimaryMesh.h"
20#include "arcane/ICaseMeshReader.h"
21#include "arcane/IMeshBuilder.h"
22#include "arcane/IParallelMng.h"
23#include "arcane/MeshPartInfo.h"
61 : m_dimension(dimension)
65 , m_indirection(indirection)
70 int dimension()
const {
return m_dimension; }
71 int nbNode()
const {
return m_nb_node; }
72 med_int medType()
const {
return m_med_type; }
73 Integer arcaneType()
const {
return m_arcane_type; }
74 const Int32* indirection()
const {
return m_indirection; }
81 Integer m_arcane_type;
82 const Int32* m_indirection;
90 _initMEDToArcaneTypes();
124 void _initMEDToArcaneTypes();
128 m_med_to_arcane_types.add(
t);
131 const Int32* indirection)
134 m_med_to_arcane_types.add(
t);
136 void _readAndAllocateCells(IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname);
139 _readNodesCoordinates(IPrimaryMesh* mesh,
Int64 nb_node,
Int32 spacedim,
140 med_idt fid,
const char* meshname);
148 const Int32 Hexaedron8_indirection[] = { 1, 0, 3, 2, 5, 4, 7, 6 };
149 const Int32 Pyramid5_indirection[] = { 1, 0, 3, 2, 4 };
150 const Int32 Quad4_indirection[] = { 1, 0, 3, 2 };
151 const Int32 Triangle3_indirection[] = { 1, 0, 2 };
153 const Int32 Tetraedron4_indirection[] = { 1, 0, 2, 3 };
157_initMEDToArcaneTypes()
159 m_med_to_arcane_types.clear();
164 _addTypeInfo(1, 2, MED_SEG2, IT_Line2);
165 _addTypeInfo(1, 3, MED_SEG3, IT_Line3);
166 _addTypeInfo(1, 4, MED_SEG4, IT_NullType);
169 _addTypeInfo(2, 3, MED_TRIA3, IT_Triangle3, Triangle3_indirection);
170 _addTypeInfo(2, 4, MED_QUAD4, IT_Quad4, Quad4_indirection);
171 _addTypeInfo(2, 6, MED_TRIA6, IT_NullType);
172 _addTypeInfo(2, 7, MED_TRIA7, IT_NullType);
173 _addTypeInfo(2, 8, MED_QUAD8, IT_Quad8);
174 _addTypeInfo(2, 9, MED_QUAD9, IT_NullType);
177 _addTypeInfo(3, 4, MED_TETRA4, IT_Tetraedron4);
178 _addTypeInfo(3, 5, MED_PYRA5, IT_Pyramid5, Pyramid5_indirection);
179 _addTypeInfo(3, 6, MED_PENTA6, IT_Pentaedron6);
180 _addTypeInfo(3, 8, MED_HEXA8, IT_Hexaedron8, Hexaedron8_indirection);
181 _addTypeInfo(3, 10, MED_TETRA10, IT_Tetraedron10);
182 _addTypeInfo(3, 12, MED_OCTA12, IT_Octaedron12);
183 _addTypeInfo(3, 13, MED_PYRA13, IT_NullType);
184 _addTypeInfo(3, 15, MED_PENTA15, IT_NullType);
185 _addTypeInfo(3, 18, MED_PENTA18, IT_NullType);
186 _addTypeInfo(3, 20, MED_HEXA20, IT_Hexaedron20);
187 _addTypeInfo(3, 27, MED_HEXA27, IT_NullType);
195 _addTypeInfo(2, 0, MED_POLYGON, IT_NullType);
196 _addTypeInfo(2, 0, MED_POLYGON2, IT_NullType);
197 _addTypeInfo(3, 0, MED_POLYHEDRON, IT_NullType);
209readMesh(IPrimaryMesh* mesh,
const String& file_name)
211 info() <<
"Trying to read MED File name=" << file_name;
212 return _readMesh(mesh, file_name);
219_readMesh(IPrimaryMesh* mesh,
const String& filename)
221 const med_idt fid = MEDfileOpen(filename.localstr(), MED_ACC_RDONLY);
223 MESSAGE(
"ERROR: can not open MED file ");
224 error() <<
"ERROR: can not open MED file '" << filename <<
"'";
228 AutoCloseMED auto_close_med(fid);
230 int nb_mesh = MEDnMesh(fid);
232 error() <<
"Error reading number of meshes";
235 info() <<
"MED: nb_mesh=" << nb_mesh;
237 error() <<
"No mesh is present";
245 int nb_axis = MEDmeshnAxis(fid, mesh_index);
247 error() <<
"Can not read number of axis (MEDmeshnAxis)";
250 info() <<
"MED: nb_axis=" << nb_axis;
252 UniqueArray<char> axisname(MED_SNAME_SIZE * nb_axis + 1,
'\0');
253 UniqueArray<char> unitname(MED_SNAME_SIZE * nb_axis + 1,
'\0');
255 char meshname[MED_NAME_SIZE + 1];
257 char meshdescription[MED_COMMENT_SIZE + 1];
258 meshdescription[0] =
'\0';
259 char dtunit[MED_SNAME_SIZE + 1];
261 med_int spacedim = 0;
263 med_mesh_type meshtype = MED_UNDEF_MESH_TYPE;
264 med_sorting_type sortingtype = MED_SORT_UNDEF;
266 med_axis_type axistype = MED_UNDEF_AXIS_TYPE;
268 err = MEDmeshInfo(fid, mesh_index, meshname, &spacedim, &meshdim, &meshtype, meshdescription,
269 dtunit, &sortingtype, &nstep, &axistype, axisname.data(), unitname.data());
271 error() <<
"Can not read mesh info (MEDmeshInfo) r=" << err;
274 if (meshtype != MED_UNSTRUCTURED_MESH) {
275 error() <<
"Arcane handle only MED unstructured mesh (MED_UNSTRUCTURED_MESH) type=" << meshtype;
278 Integer mesh_dimension = meshdim;
279 if (mesh_dimension != 2 && mesh_dimension != 3)
280 ARCANE_FATAL(
"MED reader handles only 2D or 3D meshes");
282 info() <<
"MED: name=" << meshname;
283 info() <<
"MED: description=" << meshdescription;
284 info() <<
"MED: spacedim=" << spacedim;
285 info() <<
"MED: meshdim=" << meshdim;
286 info() <<
"MED: dtunit=" << dtunit;
287 info() <<
"MED: meshtype=" << meshtype;
288 info() <<
"MED: sortingtype=" << sortingtype;
289 info() <<
"MED: axistype=" << axistype;
290 info() <<
"MED: nstep=" << nstep;
295 med_bool coordinatechangement;
296 med_bool geotransformation;
299 med_int med_nb_node = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE,
300 MED_COORDINATE, MED_NO_CMODE, &coordinatechangement,
302 if (med_nb_node < 0) {
303 error() <<
"Can not read number of nodes (MEDmeshnEntity) err=" << med_nb_node;
306 nb_node = med_nb_node;
308 info() <<
"MED: nb_node=" << nb_node;
310 mesh->setDimension(mesh_dimension);
312 IParallelMng* pm = mesh->parallelMng();
314 Int32 rank = mesh->meshPartInfo().partRank();
316 bool is_read_items = !(is_parallel && rank != 0);
318 _readAndAllocateCells(mesh, mesh_dimension, fid, meshname);
320 return _readNodesCoordinates(mesh, nb_node, spacedim, fid, meshname);
324 mesh->allocateCells(0, {},
true);
333_readAndAllocateCells(IPrimaryMesh* mesh,
Int32 mesh_dimension, med_idt fid,
const char* meshname)
335 Int64 cell_unique_id = 0;
337 for (
const auto& iinfo : m_med_to_arcane_types) {
338 Integer item_dimension = iinfo.dimension();
340 if (item_dimension != mesh_dimension)
342 UniqueArray<med_int> med_connectivity;
343 Int32 nb_item = _readItems(fid, meshname, iinfo, med_connectivity);
346 Integer arcane_type = iinfo.arcaneType();
347 Integer nb_item_node = iinfo.nbNode();
348 if (arcane_type == IT_NullType) {
350 ARCANE_FATAL(
"MED type '{0}' is not supported by Arcane", iinfo.medType());
352 Int64 cells_infos_index = 0;
353 Int64 med_connectivity_index = 0;
354 UniqueArray<Int64> cells_infos((2 + nb_item_node) * nb_item);
355 info() <<
"CELL_INFOS size=" << cells_infos.size() <<
" nb_item=" << nb_item
356 <<
" type=" << arcane_type;
357 const Int32* indirection = iinfo.indirection();
358 for (
Int32 i = 0; i < nb_item; ++i) {
359 cells_infos[cells_infos_index] = arcane_type;
361 cells_infos[cells_infos_index] = cell_unique_id;
366 Span<Int64> cinfo_span(cells_infos.span().subspan(cells_infos_index, nb_item_node));
367 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
369 for (Integer k = 0; k < nb_item_node; ++k) {
370 cinfo_span[k] = med_cinfo_span[indirection[k]] - 1;
374 for (Integer k = 0; k < nb_item_node; ++k)
375 cinfo_span[k] = med_cinfo_span[k] - 1;
378 med_connectivity_index += nb_item_node;
379 cells_infos_index += nb_item_node;
382 mesh->allocateCells(nb_item, cells_infos,
false);
390_readNodesCoordinates(IPrimaryMesh* mesh,
Int64 nb_node,
Int32 spacedim,
391 med_idt fid,
const char* meshname)
393 const bool do_verbose =
false;
395 UniqueArray<Real3> nodes_coordinates(nb_node);
397 UniqueArray<med_float> coordinates(nb_node * spacedim);
398 int err = MEDmeshNodeCoordinateRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE,
401 error() <<
"Can not read nodes coordinates err=" << err;
406 for (
Int64 i = 0; i < nb_node; ++i) {
407 Real3 xyz(coordinates[i * 3], coordinates[(i * 3) + 1], coordinates[(i * 3) + 2]);
409 info() <<
"I=" << i <<
" XYZ=" << xyz;
410 nodes_coordinates[i] = xyz;
413 else if (spacedim == 2) {
414 for (
Int64 i = 0; i < nb_node; ++i) {
415 Real3 xyz(coordinates[i * 2], coordinates[(i * 2) + 1], 0.0);
417 info() <<
"I=" << i <<
" XYZ=" << xyz;
418 nodes_coordinates[i] = xyz;
422 ARCANE_THROW(NotImplementedException,
"spacedim!=2 && spacedim!=3");
430 nodes_coord_var[inode] = nodes_coordinates[node.uniqueId()];
440_readItems(med_idt fid,
const char* meshname,
const MEDToArcaneItemInfo& iinfo,
441 Array<med_int>& connectivity)
443 int med_item_type = iinfo.medType();
444 med_bool coordinatechangement;
445 med_bool geotransformation;
446 med_int nb_med_item = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
447 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
449 if (nb_med_item < 0) {
450 ARCANE_FATAL(
"Can not read MED med_item_type '{0}' error={1}", med_item_type, nb_med_item);
452 info() <<
"MED: type=" << med_item_type <<
" nb_item=" << nb_med_item;
453 if (nb_med_item == 0)
455 Int64 nb_node = iinfo.nbNode();
458 ARCANE_THROW(NotImplementedException,
"Reading items with MED type '{0}'", med_item_type);
460 connectivity.resize(nb_node * nb_med_item);
461 int err = MEDmeshElementConnectivityRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL,
462 med_item_type, MED_NODAL, MED_FULL_INTERLACE,
463 connectivity.data());
465 ARCANE_FATAL(
"Can not read connectivity MED med_item_type '{0}' error={1}",
468 info() <<
"CON: " << connectivity;
542 m_trace_mng->
info() <<
"MED Reader (ICaseMeshReader) file_name=" <<
fname;
567 return makeRef(builder);
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Classe de base d'un service.
Classe de base de service lié à un sous-domaine.
Informations nécessaires pour la lecture d'un fichier de maillage.
Interface du service de lecture du maillage à partir du jeu de données.
Interface d'un service de création/lecture du maillage.
Interface du service gérant la lecture d'un maillage.
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 bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Retourne un builder pour créer et lire le maillage dont les informations sont spécifiées dans read_in...
bool allowExtension(const String &str) override
Vérifie si le service supporte les fichiers avec l'extension str.
void build() override
Construction de niveau build du service.
eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_element, const String &file_name, const String &dir_name, bool use_internal_partition) override
Lit un maillage à partir d'un fichier.
Lecteur de maillages au format MED.
Paramètres nécessaires à la construction d'un maillage.
Structure contenant les informations pour créer un service.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Chaîne de caractères unicode.
Classe d'accès aux traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage info() const
Flot pour un message d'information.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
Int32 Integer
Type représentant un entier.
Informations pour passer des types MED aux types Arcane pour les entités.