Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MEDMeshReaderService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MEDMeshReaderService.cc (C) 2000-2026 */
9/* */
10/* Lecture d'un maillage au format MED. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
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
19#include "arcane/core/IMeshReader.h"
20#include "arcane/core/BasicService.h"
22#include "arcane/core/IPrimaryMesh.h"
23#include "arcane/core/IItemFamily.h"
24#include "arcane/core/ICaseMeshReader.h"
25#include "arcane/core/IMeshBuilder.h"
26#include "arcane/core/IParallelMng.h"
27#include "arcane/core/MeshPartInfo.h"
28#include "arcane/core/NodesOfItemReorderer.h"
30#include "arcane/core/ItemPrinter.h"
31
32#include <med.h>
33#define MESGERR 1
34#include <med_utils.h>
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
50class MEDMeshReader
51: public TraceAccessor
52{
53 public:
54
61 class MEDToArcaneItemInfo
62 {
63 public:
64
65 MEDToArcaneItemInfo(int dimension, int nb_node, med_int med_type,
66 ItemTypeId arcane_type, const Int32* indirection)
67 : m_dimension(dimension)
68 , m_nb_node(nb_node)
69 , m_med_type(med_type)
70 , m_arcane_type(arcane_type)
71 , m_indirection(indirection)
72 {}
73
74 public:
75
76 int dimension() const { return m_dimension; }
77 int nbNode() const { return m_nb_node; }
78 med_int medType() const { return m_med_type; }
79 Int16 arcaneType() const { return m_arcane_type; }
80 const Int32* indirection() const { return m_indirection; }
81
82 private:
83
84 int m_dimension = -1;
85 int m_nb_node = -1;
86 med_int m_med_type = {};
87 ItemTypeId m_arcane_type = ITI_NullType;
88 const Int32* m_indirection = nullptr;
89 };
90
92 class MEDFamilyInfo
93 {
94 public:
95
96 explicit MEDFamilyInfo(Int32 family_id)
97 : m_family_id(family_id)
98 {}
99
100 public:
101
106 };
107
116 class MEDGroupInfo
117 {
118 public:
119
120 explicit MEDGroupInfo(Int32 index)
121 : m_index(index)
122 {}
123
124 public:
125
134 };
135
136 public:
137
138 explicit MEDMeshReader(ITraceMng* tm)
139 : TraceAccessor(tm)
140 {
141 _initMEDToArcaneTypes();
142 }
143
144 public:
145
146 [[nodiscard]] IMeshReader::eReturnType
147 readMesh(IPrimaryMesh* mesh, const String& file_name);
148
149 private:
150
151 IMeshReader::eReturnType _readMesh(IPrimaryMesh* mesh, const String& filename);
152
153 private:
154
155 // Structure pour fermer automatiquement les fichiers MED ouverts
156 struct AutoCloseMED
157 {
158 explicit AutoCloseMED(med_idt id)
159 : fid(id)
160 {}
161 ~AutoCloseMED()
162 {
163 if (fid >= 0)
164 ::MEDfileClose(fid);
165 }
166
167 med_idt fid;
168 };
169
175 std::unordered_map<med_int, Int32> m_med_geotype_to_arcane_type_index;
177 std::unordered_map<Int32, MEDFamilyInfo> m_med_families_map;
182
183 private:
184
185 Int32 _readItems(med_idt fid, const char* meshnane, const MEDToArcaneItemInfo& iinfo,
186 Array<Int16>& polygon_nb_nodes, Array<med_int>& connectivity, Array<med_int>& family_values);
187 void _initMEDToArcaneTypes();
188 void _addTypeInfo(int dimension, int nb_node, med_int med_type, ItemTypeId arcane_type)
189 {
190 _addTypeInfo(dimension, nb_node, med_type, arcane_type, nullptr);
191 }
192 void _addTypeInfo(int dimension, int nb_node, med_int med_type, ItemTypeId arcane_type,
193 const Int32* indirection)
194 {
195 MEDToArcaneItemInfo t(dimension, nb_node, med_type, arcane_type, indirection);
196 Int32 index = m_med_to_arcane_types.size();
198 m_med_geotype_to_arcane_type_index.insert(std::make_pair(med_type, index));
199 }
200 void _readAndCreateCells(IPrimaryMesh* mesh, Int32 mesh_dimension, med_idt fid, const char* meshname);
201 void _readFaces(IPrimaryMesh* mesh, Int32 mesh_dimension, med_idt fid, const char* meshname);
202
203 [[nodiscard]] IMeshReader::eReturnType
204 _readNodesCoordinates(IPrimaryMesh* mesh, Int64 nb_node, Int32 spacedim,
205 med_idt fid, const char* meshname);
206 void _readFamilies(med_idt fid, const char* meshname);
207 void _readAvailableTypes(med_idt fid, const char* meshname);
208 void _clearItemsInGroups()
209 {
210 for (MEDGroupInfo& g : m_med_groups) {
211 g.m_unique_ids.clear();
212 g.m_local_ids.clear();
213 }
214 }
215 void _broadcastGroups(ConstArrayView<String> names, IItemFamily* family);
216};
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
221namespace
222{
223 // Les conventions de numérotations de MED sont différentes de celles
224 // utilisées dans Arcane. Ces tableaux permettent d'effectuer la renumérotation.
225 const Int32 Hexaedron8_indirection[] = { 1, 0, 3, 2, 5, 4, 7, 6 };
226 const Int32 Hexaedron20_indirection[] = { 1, 8, 10, 3, 9, 2, 0, 11, 5, 14, 18, 7, 6, 4, 16, 15, 13, 12, 17, 19 };
227 const Int32 Pyramid5_indirection[] = { 1, 0, 3, 2, 4 };
228 const Int32 Quad4_indirection[] = { 1, 0, 3, 2 };
229 const Int32 Quad8_indirection[] = { 1, 0, 3, 2, 4, 7, 6, 5 };
230 const Int32 Triangle3_indirection[] = { 1, 0, 2 };
231 // PAS utilisé pour l'instant. À tester.
232 const Int32 Tetraedron4_indirection[] = { 1, 0, 2, 3 };
233} // namespace
234
235/*---------------------------------------------------------------------------*/
236/*---------------------------------------------------------------------------*/
237
238void MEDMeshReader::
239_initMEDToArcaneTypes()
240{
241 m_med_to_arcane_types.clear();
242
243 // TODO: regarder la correspondance de connectivité entre
244 // Arcane et MED pour les éléments quadratiques
245 // Types 1D
246 _addTypeInfo(1, 2, MED_SEG2, ITI_Line2);
247 _addTypeInfo(1, 3, MED_SEG3, ITI_Line3); // Non supporté
248 _addTypeInfo(1, 4, MED_SEG4, ITI_NullType); // Non supporté
249
250 // Types 2D.
251 _addTypeInfo(2, 3, MED_TRIA3, ITI_Triangle3, Triangle3_indirection);
252 _addTypeInfo(2, 4, MED_QUAD4, ITI_Quad4, Quad4_indirection);
253 _addTypeInfo(2, 6, MED_TRIA6, ITI_NullType); // Non supporté
254 _addTypeInfo(2, 7, MED_TRIA7, ITI_NullType); // Non supporté
255 _addTypeInfo(2, 8, MED_QUAD8, ITI_Quad8, Quad8_indirection);
256 _addTypeInfo(2, 9, MED_QUAD9, ITI_NullType); // Non supporté
257
258 // Types 3D
259 _addTypeInfo(3, 4, MED_TETRA4, ITI_Tetraedron4);
260 _addTypeInfo(3, 5, MED_PYRA5, ITI_Pyramid5, Pyramid5_indirection);
261 _addTypeInfo(3, 6, MED_PENTA6, ITI_Pentaedron6);
262 _addTypeInfo(3, 8, MED_HEXA8, ITI_Hexaedron8);
263 _addTypeInfo(3, 10, MED_TETRA10, ITI_Tetraedron10);
264 _addTypeInfo(3, 12, MED_OCTA12, ITI_Octaedron12);
265 _addTypeInfo(3, 13, MED_PYRA13, ITI_NullType); // Non supporté
266 _addTypeInfo(3, 15, MED_PENTA15, ITI_NullType); // Non supporté
267 _addTypeInfo(3, 18, MED_PENTA18, ITI_NullType); // Non supporté
268 _addTypeInfo(3, 20, MED_HEXA20, ITI_Hexaedron20);
269 _addTypeInfo(3, 27, MED_HEXA27, ITI_NullType); // Non supporté
270
271 // Mailles dont la géométrie à une connectivité variable.
272 // Pour l'instant, on ne supporte aucun de ces types dans Arcane.
273 // On traite quand même ces éléments pour afficher une erreur s'ils sont
274 // présents dans le maillage. En mettant la valeur (0) pour le nombre
275 // de noeuds, on signale à _readItems() qu'on ne sait pas traiter ces éléments.
276
277 _addTypeInfo(2, 0, MED_POLYGON, ITI_GenericPolygon);
278 _addTypeInfo(2, 0, MED_POLYGON2, ITI_NullType);
279 _addTypeInfo(3, 0, MED_POLYHEDRON, ITI_NullType);
280
281 // Mailles dont la géométrie est dynamique (découverte du modèle dans le fichier)
282 // TODO: regarder comment les traiter
283 //#define MED_STRUCT_GEO_INTERNAL 600
284 //#define MED_STRUCT_GEO_SUP_INTERNAL 700
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290IMeshReader::eReturnType MEDMeshReader::
291readMesh(IPrimaryMesh* mesh, const String& file_name)
292{
293 info() << "Tentative de lecture du fichier MED nommé=" << file_name;
294 m_mesh = mesh;
295 return _readMesh(mesh, file_name);
296}
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300
301IMeshReader::eReturnType MEDMeshReader::
302_readMesh(IPrimaryMesh* mesh, const String& filename)
303{
304 const med_idt fid = MEDfileOpen(filename.localstr(), MED_ACC_RDONLY);
305 if (fid < 0) {
306 MESSAGE("ERROR: can not open MED file ");
307 error() << "ERROR: can not open MED file '" << filename << "'";
309 }
310 // Pour garantir la fermeture du fichier.
311 AutoCloseMED auto_close_med(fid);
312
313 int nb_mesh = MEDnMesh(fid);
314 if (nb_mesh < 0) {
315 error() << "Erreur lors de la lecture du nombre de maillages";
317 }
318 info() << "MED: nb_mesh=" << nb_mesh;
319 if (nb_mesh == 0) {
320 error() << "Aucun maillage n'est présent";
322 }
323
324 // Le maillage qu'on lit est toujours le premier
325 int mesh_index = 1;
326
327 // Récupère la dimension d'espace. Cela est nécessaire pour dimensionner axisname eet unitname
328 int nb_axis = MEDmeshnAxis(fid, mesh_index);
329 if (nb_axis < 0) {
330 error() << "Impossible de lire le nombre d'axes (MEDmeshnAxis)";
332 }
333 info() << "MED: nb_axis=" << nb_axis;
334
335 UniqueArray<char> axisname(MED_SNAME_SIZE * nb_axis + 1, '\0');
336 UniqueArray<char> unitname(MED_SNAME_SIZE * nb_axis + 1, '\0');
337
338 char meshname[MED_NAME_SIZE + 1];
339 meshname[0] = '\0';
340 char meshdescription[MED_COMMENT_SIZE + 1];
341 meshdescription[0] = '\0';
342 char dtunit[MED_SNAME_SIZE + 1];
343 dtunit[0] = '\0';
344 med_int spacedim = 0;
345 med_int meshdim = 0;
346 med_mesh_type meshtype = MED_UNDEF_MESH_TYPE;
347 med_sorting_type sortingtype = MED_SORT_UNDEF;
348 med_int nstep = 0;
349 med_axis_type axistype = MED_UNDEF_AXIS_TYPE;
350 int err = 0;
351 err = MEDmeshInfo(fid, mesh_index, meshname, &spacedim, &meshdim, &meshtype, meshdescription,
352 dtunit, &sortingtype, &nstep, &axistype, axisname.data(), unitname.data());
353 if (err < 0) {
354 error() << "Impossible de lire les informations du maillage (MEDmeshInfo) r=" << err;
356 }
357 if (meshtype != MED_UNSTRUCTURED_MESH) {
358 error() << "Arcane ne gère que les maillages non structurés MED (MED_UNSTRUCTURED_MESH) type=" << meshtype;
360 }
361 Integer mesh_dimension = meshdim;
362 if (mesh_dimension != 2 && mesh_dimension != 3)
363 ARCANE_FATAL("Le lecteur MED ne gère que les maillages 2D ou 3D");
364
365 info() << "MED: name=" << meshname;
366 info() << "MED: description=" << meshdescription;
367 info() << "MED: spacedim=" << spacedim;
368 info() << "MED: meshdim=" << meshdim;
369 info() << "MED: dtunit=" << dtunit;
370 info() << "MED: meshtype=" << meshtype;
371 info() << "MED: sortingtype=" << sortingtype;
372 info() << "MED: axistype=" << axistype;
373 info() << "MED: nstep=" << nstep;
374
375 Int64 nb_node = 0;
376 // Lecture du nombre de noeuds.
377 {
378 med_bool coordinatechangement;
379 med_bool geotransformation;
380 // TODO: traiter les informations telles que coordinatechangement
381 // et geotransformation si besoin
382 med_int med_nb_node = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE,
383 MED_COORDINATE, MED_NO_CMODE, &coordinatechangement,
384 &geotransformation);
385 if (med_nb_node < 0) {
386 error() << "Impossible de lire le nombre de nœuds (MEDmeshnEntity) err=" << med_nb_node;
388 }
389 nb_node = med_nb_node;
390 }
391 info() << "MED: nb_node=" << nb_node;
392
393 mesh->setDimension(mesh_dimension);
394
395 // Les maillages MED peuvent contenir des polygones.
396 // On construit donc les types correspondants.
397 // (NOTE : tous les sous-domaines doivent faire cela)
398 mesh->itemTypeMng()->buildPolygonTypes();
399
400 IParallelMng* pm = mesh->parallelMng();
401 bool is_parallel = pm->isParallel();
402 Int32 rank = mesh->meshPartInfo().partRank();
403 // En parallèle, seul le rang 0 lit le maillage
404 bool is_read_items = !(is_parallel && rank != 0);
405 if (is_read_items) {
406 _readAvailableTypes(fid, meshname);
407 _readFamilies(fid, meshname);
408 _readAndCreateCells(mesh, mesh_dimension, fid, meshname);
409 }
410 // La méthode IPrimaryMesh::endAllocate() est collective donc tout
411 // le monde doit l'appeler même si les rangs autres que le rang 0
412 // qui n'ont pas de mailles.
413 mesh->endAllocate();
414
415 // Liste des noms des groupes de mailles créées
416 // Elle servira à transférer la liste des groupes à tous les rangs.
417 UniqueArray<String> cell_group_names;
418 IItemFamily* cell_family = mesh->cellFamily();
419 if (is_read_items) {
420 // Maintenant qu'on a créé toutes les mailles, on crée les groupes correspondants
421 // Pour cela, on parcourt toutes les instances de 'm_med_groups' et si une a des entités
422 // alors ce sont des mailles à ajouter à un groupe.
423 // ATTENTION ATTENTION:
424 // NOTE: Les groupes doivent être communs à tous les rangs. Il faut les broadcaster
425 UniqueArray<Int32> cell_local_ids;
426 for (const MEDGroupInfo& g : m_med_groups) {
427 Int32 nb_cell_in_group = g.m_unique_ids.size();
428 cell_local_ids.resize(nb_cell_in_group);
429 cell_family->itemsUniqueIdToLocalId(cell_local_ids, g.m_unique_ids);
430 for (const String& name : g.m_names) {
431 info() << "Group=" << name << " index=" << g.m_index << " nb_item=" << nb_cell_in_group;
432 CellGroup cell_group = cell_family->findGroup(name, true);
433 cell_group.addItems(cell_local_ids);
434 cell_group_names.add(name);
435 }
436 }
437 }
438 _broadcastGroups(cell_group_names, cell_family);
439
440 // Lit les faces
441 if (is_read_items) {
442 // Comme la numérotation des faces n'est pas forcément correcte pour tous
443 // les types d'entités (notamment pour l'ordre 2), on ajoute une option pour
444 // ne pas lire les faces.
445 bool is_face_group_disabled = false;
446 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_MED_DISABLE_FACEGROUP", true))
447 is_face_group_disabled = (v.value());
448 if (!is_face_group_disabled)
449 _readFaces(mesh, mesh_dimension, fid, meshname);
450 }
451
452 UniqueArray<String> face_group_names;
453 IItemFamily* face_family = mesh->faceFamily();
454 // Maintenant ajoute les faces aux groupes.
455 if (is_read_items) {
456 for (const MEDGroupInfo& g : m_med_groups) {
457 Int32 nb_face_in_group = g.m_local_ids.size();
458 info() << "Vérification du groupe index=" << g.m_index << " nb_item=" << nb_face_in_group;
459 if (nb_face_in_group == 0)
460 continue;
461 for (const String& name : g.m_names) {
462 info() << "FaceGroup=" << name << " index=" << g.m_index << " nb_item=" << nb_face_in_group;
463 FaceGroup face_group = face_family->findGroup(name, true);
464 face_group.addItems(g.m_local_ids);
465 face_group_names.add(name);
466 }
467 }
468 }
469 _broadcastGroups(face_group_names, face_family);
470
471 if (is_read_items) {
472 // Lit les coordonnées
473 return _readNodesCoordinates(mesh, nb_node, spacedim, fid, meshname);
474 }
475 return IMeshReader::RTOk;
476}
477
478/*---------------------------------------------------------------------------*/
479/*---------------------------------------------------------------------------*/
484_readAvailableTypes(med_idt fid, const char* meshname)
485{
486 // Récupère le nombre de types géométriques
487 med_bool coordinatechangement;
488 med_bool geotransformation;
489 med_int nb_geo = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_GEO_ALL,
490 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
491 &geotransformation);
492 if (nb_geo < 0)
493 ARCANE_FATAL("Impossible de lire le nombre d'entités géométriques nb_geo={0}", nb_geo);
494 info() << "MED: nb_geotype = " << nb_geo;
495
496 // Boucle sur les types présents
497 for (med_int it = 1; it <= nb_geo; it++) {
498
499 med_geometry_type geotype = MED_GEO_ALL;
501
502 /* get geometry type */
503 med_int type_ret = MEDmeshEntityInfo(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, it,
504 geotype_name.data(), &geotype);
505 if (type_ret < 0)
506 ARCANE_FATAL("Impossible de lire les informations pour le géotype index={0} ret={1}", it, type_ret);
507 /* combien de mailles de type géotype ? */
508 med_int nb_item = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, geotype,
509 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
510 &geotransformation);
511 if (nb_item < 0)
512 ARCANE_FATAL("Impossible de lire le nombre d'éléments pour le géotype={0} nom={1} ret={2}",
513 geotype, geotype_name.data(), nb_item);
514 info() << "MED: type=" << geotype << " '" << geotype_name.data() << "' nb_item=" << nb_item;
515 m_med_geotypes_in_mesh.add(geotype);
516 }
517}
518
519/*---------------------------------------------------------------------------*/
520/*---------------------------------------------------------------------------*/
521
522void MEDMeshReader::
523_readAndCreateCells(IPrimaryMesh* mesh, Int32 mesh_dimension, med_idt fid, const char* meshname)
524{
525 _clearItemsInGroups();
526
527 // A priori il n'y a pas de uniqueId() pour les entités dans MED (TODO: à vérifier)
528 // Donc on numérote les mailles en commencant par zéro et on incrémente à chaque
529 // maille créée.
530 Int64 cell_unique_id = 0;
531
532 UniqueArray<Int16> polygon_nb_nodes;
533 UniqueArray<med_int> med_connectivity;
534 UniqueArray<med_int> med_family_values;
535
536 ItemTypeMng* itm = mesh->itemTypeMng();
537 // Alloue les mailles types par type.
538 // Parcours les types disponibles et traite ceux qui correspondent à la dimension
539 // du maillage.
540 for (med_int geotype : m_med_geotypes_in_mesh) {
541 Int32 index_in_list = m_med_geotype_to_arcane_type_index[geotype];
542 const MEDToArcaneItemInfo& iinfo = m_med_to_arcane_types[index_in_list];
543
544 Int32 item_dimension = iinfo.dimension();
545 // On ne traite que les entités de la dimension du maillage.
546 if (item_dimension != mesh_dimension)
547 continue;
548 Int32 nb_item = _readItems(fid, meshname, iinfo, polygon_nb_nodes, med_connectivity, med_family_values);
549 if (nb_item == 0)
550 continue;
551 Int16 arcane_type = iinfo.arcaneType();
552 Int32 nb_item_node = iinfo.nbNode();
553 Int32 nb_family_values = med_family_values.size();
554 if (arcane_type == IT_NullType) {
555 // Indique un type pris en charge par MED mais pas par Arcane
556 ARCANE_FATAL("Le type MED '{0}' n'est pas pris en charge par Arcane", iinfo.medType());
557 }
558 Int64 cells_infos_index = 0;
559 Int64 med_connectivity_index = 0;
560 const bool is_polygon = (iinfo.medType() == MED_POLYGON);
561
562 UniqueArray<Int64> cells_infos;
563 if (is_polygon)
564 cells_infos.resize(2 * nb_item + med_connectivity.size());
565 else
566 cells_infos.resize((2 + nb_item_node) * nb_item);
567
568 info() << "CELL_INFOS size=" << cells_infos.size() << " nb_item=" << nb_item
569 << " type=" << arcane_type;
570
571 const Int32* indirection = iinfo.indirection();
572 for (Int32 i = 0; i < nb_item; ++i) {
573 Int64 current_cell_unique_id = cell_unique_id;
574 ++cell_unique_id;
575 if (is_polygon) {
576 nb_item_node = polygon_nb_nodes[i];
577 arcane_type = itm->getPolygonType(static_cast<Int16>(nb_item_node));
578 cells_infos[cells_infos_index] = arcane_type;
579 ++cells_infos_index;
580 cells_infos[cells_infos_index] = current_cell_unique_id;
581 ++cells_infos_index;
582 Span<Int64> cinfo_span(cells_infos.span().subspan(cells_infos_index, nb_item_node));
583 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
584 for (Integer k = 0; k < nb_item_node; ++k) {
585 cinfo_span[k] = med_cinfo_span[k];
586 }
587 }
588 else {
589 cells_infos[cells_infos_index] = arcane_type;
590 ++cells_infos_index;
591
592 cells_infos[cells_infos_index] = current_cell_unique_id;
593 ++cells_infos_index;
594 Span<Int64> cinfo_span(cells_infos.span().subspan(cells_infos_index, nb_item_node));
595 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
596 if (indirection) {
597 for (Integer k = 0; k < nb_item_node; ++k) {
598 cinfo_span[k] = med_cinfo_span[indirection[k]];
599 }
600 }
601 else {
602 for (Integer k = 0; k < nb_item_node; ++k)
603 cinfo_span[k] = med_cinfo_span[k];
604 }
605 }
606 if (i < nb_family_values) {
607 // Il y a une famille associée à l'entité
608 med_int f = med_family_values[i];
609 auto x = m_med_families_map.find(f);
610 if (x == m_med_families_map.end()) {
611 ARCANE_FATAL("Impossible de trouver l'ID de famille '{0}' pour la maille '{1}' de géotype '{2}'",
612 f, i, iinfo.medType());
613 }
614 m_med_groups[x->second.m_index].m_unique_ids.add(current_cell_unique_id);
615 }
616
617 med_connectivity_index += nb_item_node;
618 cells_infos_index += nb_item_node;
619 }
620 mesh->allocateCells(nb_item, cells_infos, false);
621 }
622}
623
624/*---------------------------------------------------------------------------*/
625/*---------------------------------------------------------------------------*/
635_readFaces(IPrimaryMesh* mesh, Int32 mesh_dimension, med_idt fid, const char* meshname)
636{
637 _clearItemsInGroups();
638 ItemTypeMng* itm = mesh->itemTypeMng();
639 NodesOfItemReorderer nodes_reorderer(itm);
640
641 IItemFamily* node_family = mesh->nodeFamily();
642 NodeInfoListView mesh_nodes(node_family);
643
644 UniqueArray<Int16> polygon_nb_nodes;
645 UniqueArray<med_int> med_connectivity;
646 UniqueArray<med_int> med_family_values;
647 // Parcours les types disponibles et traite ceux qui correspondent à la dimension
648 // du maillage moins 1.
649 for (med_int geotype : m_med_geotypes_in_mesh) {
650 Int32 index_in_list = m_med_geotype_to_arcane_type_index[geotype];
651 const MEDToArcaneItemInfo& iinfo = m_med_to_arcane_types[index_in_list];
652
653 Int32 item_dimension = iinfo.dimension();
654 // On ne traite que les entités de la dimension du maillage.
655 if (item_dimension != (mesh_dimension - 1))
656 continue;
657 ItemTypeInfo* iti = itm->typeFromId(iinfo.arcaneType());
658 info() << "Lecture des faces géotype=" << geotype << " arcane_type=" << iinfo.arcaneType()
659 << " " << iti->typeName();
660
661 Int32 nb_item = _readItems(fid, meshname, iinfo, polygon_nb_nodes, med_connectivity, med_family_values);
662 if (nb_item == 0)
663 continue;
664 ItemTypeId arcane_type(iinfo.arcaneType());
665 Int32 nb_item_node = iinfo.nbNode();
666 Int32 nb_family_values = med_family_values.size();
667 if (arcane_type == IT_NullType) {
668 // Indique un type pris en charge par MED mais pas par Arcane
669 ARCANE_FATAL("Le type MED '{0}' n'est pas pris en charge par Arcane", iinfo.medType());
670 }
671
672 SmallArray<Int64> orig_nodes_id(nb_item_node);
673 info() << "FACES_INFOS nb_item=" << nb_item << " type=" << arcane_type
674 << " nb_family_values=" << nb_family_values;
675
676 const Int32* indirection = iinfo.indirection();
677 Int64 med_connectivity_index = 0;
678
679 for (Int32 i = 0; i < nb_item; ++i) {
680 ArrayView<Int64> cinfo_span(orig_nodes_id);
681 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
682 if (indirection) {
683 for (Integer k = 0; k < nb_item_node; ++k) {
684 cinfo_span[k] = med_cinfo_span[indirection[k]];
685 }
686 }
687 else {
688 for (Integer k = 0; k < nb_item_node; ++k)
689 cinfo_span[k] = med_cinfo_span[k];
690 }
691 med_connectivity_index += nb_item_node;
692 // Recherche la face dans le maillage à partir des uniqueId() triés de ses noeuds
693 nodes_reorderer.reorder(arcane_type, cinfo_span);
694 ConstArrayView<Int64> ordered_nodes = nodes_reorderer.sortedNodes();
695 //info() << "OrigMedNodes=" << med_cinfo_span;
696 //info() << "OrigNodes=" << orig_nodes_id;
697 //info() << "Nodes=" << ordered_nodes;
698 Node first_node(MeshUtils::findOneItem(node_family, ordered_nodes[0]));
699 if (first_node.null())
700 ARCANE_FATAL("Impossible de trouver le nœud uid={0} pour l'indice de face '{1}'", ordered_nodes[0], i);
701 Face face = MeshUtils::getFaceFromNodesUniqueId(first_node, ordered_nodes);
702 if (face.null()) {
703 info() << "ERREUR: Impossible de trouver la face dans le maillage i=" << i << " nœuds=" << ordered_nodes;
704 info() << "Liste des faces pour le nœud=" << ItemPrinter(first_node);
705 for (Face subface : first_node.faces()) {
706 info() << "Face=" << ItemPrinter(subface);
707 for (Node subnode : subface.nodes()) {
708 info() << " Nœud=" << ItemPrinter(subnode);
709 }
710 }
711 ARCANE_FATAL("Impossible de trouver la face avec les nœuds=", ordered_nodes);
712 }
713 //info() << "Face=" << ItemPrinter(face);
714
715 // Ajoute la face dans les groupes correspondants
716 if (i < nb_family_values) {
717 // Il y a une famille associée à l'entité
718 med_int f = med_family_values[i];
719 auto x = m_med_families_map.find(f);
720 if (x == m_med_families_map.end()) {
721 ARCANE_FATAL("Impossible de trouver l'ID de famille '{0}' pour la face '{1}' de géotype '{2}'",
722 f, i, iinfo.medType());
723 }
724 //info() << "Ajout de la face au groupe_index=" << x->second.m_index;
725 m_med_groups[x->second.m_index].m_local_ids.add(face.localId());
726 }
727 }
728 info() << "FIN_LECTURE_DES_ENTITES";
729 }
730}
731
732/*---------------------------------------------------------------------------*/
733/*---------------------------------------------------------------------------*/
734
735IMeshReader::eReturnType MEDMeshReader::
736_readNodesCoordinates(IPrimaryMesh* mesh, Int64 nb_node, Int32 spacedim,
737 med_idt fid, const char* meshname)
738{
739 const bool do_verbose = false;
740 // Lit les coordonnées des noeuds et positionne les coordonnées dans Arcane
741
742 // La connectivité dans MED commence à 1 et Arcane à 0.
743 // Le premier noeud a donc un pour uniqueId() la valeur
744 UniqueArray<Real3> nodes_coordinates(nb_node + 1);
745 {
746 UniqueArray<med_float> coordinates(nb_node * spacedim);
747 int err = MEDmeshNodeCoordinateRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE,
748 coordinates.data());
749 if (err < 0) {
750 error() << "Impossible de lire les coordonnées des nœuds err=" << err;
752 }
753
754 if (spacedim == 3) {
755 for (Int64 i = 0; i < nb_node; ++i) {
756 Real3 xyz(coordinates[i * 3], coordinates[(i * 3) + 1], coordinates[(i * 3) + 2]);
757 if (do_verbose)
758 info() << "I=" << i << " XYZ=" << xyz;
759 nodes_coordinates[i + 1] = xyz;
760 }
761 }
762 else if (spacedim == 2) {
763 for (Int64 i = 0; i < nb_node; ++i) {
764 Real3 xyz(coordinates[i * 2], coordinates[(i * 2) + 1], 0.0);
765 if (do_verbose)
766 info() << "I=" << i << " XYZ=" << xyz;
767 nodes_coordinates[i + 1] = xyz;
768 }
769 }
770 else
771 ARCANE_THROW(NotImplementedException, "spacedim!=2 && spacedim!=3");
772 }
773
774 // Positionne les coordonnées
775 {
776 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
777 ENUMERATE_NODE (inode, mesh->allNodes()) {
778 Node node = *inode;
779 nodes_coord_var[inode] = nodes_coordinates[node.uniqueId()];
780 }
781 }
782 return IMeshReader::RTOk;
783}
784
785/*---------------------------------------------------------------------------*/
786/*---------------------------------------------------------------------------*/
802_readItems(med_idt fid, const char* meshname, const MEDToArcaneItemInfo& iinfo,
803 Array<Int16>& polygon_nb_nodes, Array<med_int>& connectivity,
804 Array<med_int>& family_values)
805{
806 constexpr bool is_verbose = false;
807
808 connectivity.clear();
809 family_values.clear();
810
811 int med_item_type = iinfo.medType();
812 med_bool coordinatechangement = {};
813 med_bool geotransformation = {};
814 med_int nb_med_item = 0;
815 if (iinfo.medType() == MED_POLYGON) {
816 // Pour les polygones, il faut un appel spécifique pour le nombre d'index.
817 // Ce nombre correspond au nombre d'entités plus un.
818 med_int nb_index = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
819 MED_INDEX_NODE, MED_NODAL, &coordinatechangement,
820 &geotransformation);
821 if (nb_index < 0)
822 ARCANE_FATAL("Impossible de lire le med_item_type MED '{0}' erreur={1}", med_item_type, nb_index);
823
824 info() << "MED: Lecture des entités";
825 info() << "MED: type=" << med_item_type << " nb_index=" << nb_index;
826 if (nb_index < 1)
827 return 0;
828 nb_med_item = nb_index - 1;
829 polygon_nb_nodes.resize(nb_med_item);
830 // Combien de nœuds pour la connectivité du polygone ?
831 med_int nb_connectivity = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
832 MED_CELL, MED_POLYGON, MED_CONNECTIVITY, MED_NODAL,
833 &coordinatechangement, &geotransformation);
834 if (nb_connectivity < 0)
835 ARCANE_FATAL("Impossible d'obtenir la taille de connectivité pour MED_POLYGON err={0}", nb_connectivity);
836
837 // La table \a indexes contient pour chaque maille l'indice de son premier
838 // noeud dans la connectivité. Le nombre de noeuds de la i-ème entité
839 // est donc égal à (indexes[i+1]-indexes[i]).
840 UniqueArray<med_int> indexes(nb_index);
841 connectivity.resize(nb_connectivity);
842 info() << "Lecture des polygones nb_connectivity=" << nb_connectivity;
843 int r = MEDmeshPolygonRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_NODAL,
844 indexes.data(), connectivity.data());
845 if (r < 0)
846 ARCANE_FATAL("Impossible de lire la connectivité pour MED_POLYGON err={0}", r);
847 info() << "INDEXES=" << indexes;
848 for (Int32 i = 0; i < nb_med_item; ++i)
849 polygon_nb_nodes[i] = static_cast<Int16>(indexes[i + 1] - indexes[i]);
850 }
851 else {
852 nb_med_item = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
853 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
854 &geotransformation);
855 if (nb_med_item < 0)
856 ARCANE_FATAL("Impossible de lire le med_item_type MED '{0}' erreur={1}", med_item_type, nb_med_item);
857
858 info() << "MED: Lecture des entités";
859 info() << "MED: type=" << med_item_type << " nb_item=" << nb_med_item;
860 if (nb_med_item == 0)
861 return 0;
862
863 Int64 nb_node = iinfo.nbNode();
864 if (nb_node == 0)
865 // Indique un élément que nous ne savons pas comment traiter.
866 ARCANE_THROW(NotImplementedException, "Lecture des entités avec le type MED '{0}'", med_item_type);
867
868 connectivity.resize(nb_node * nb_med_item);
869 int err = MEDmeshElementConnectivityRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL,
870 med_item_type, MED_NODAL, MED_FULL_INTERLACE,
871 connectivity.data());
872 if (err < 0)
873 ARCANE_FATAL("Impossible de lire la connectivité MED med_item_type '{0}' erreur={1}",
874 med_item_type, err);
875 }
876 if (is_verbose)
877 info() << "CON: " << connectivity;
878 {
879 med_int nb_med_family = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
880 MED_CELL, med_item_type, MED_FAMILY_NUMBER, MED_NODAL,
881 &coordinatechangement, &geotransformation);
882 info() << "nb_family=" << nb_med_family;
883 if (nb_med_family < 0)
884 ARCANE_FATAL("Impossible de lire la taille de la famille pour le type med_item_type={0} erreur={1}", med_item_type, nb_med_family);
885 if (nb_med_family > 0) {
886 family_values.resize(nb_med_family);
887 int r = MEDmeshEntityFamilyNumberRd(fid, meshname, MED_NO_DT, MED_NO_IT,
888 MED_CELL, med_item_type, family_values.data());
889 if (r < 0)
890 ARCANE_FATAL("Impossible de lire les valeurs de famille pour le type med_item_type={0} erreur={1}", med_item_type, nb_med_family);
891 if (is_verbose)
892 info() << "FAM: " << family_values;
893 }
894 }
895 return nb_med_item;
896}
897
898/*---------------------------------------------------------------------------*/
899/*---------------------------------------------------------------------------*/
900
901void MEDMeshReader::
902_readFamilies(med_idt fid, const char* meshname)
903{
905
906 info() << "Lecture des familles";
907
908 // Récupère le nombre de familles
909 med_int nb_family = MEDnFamily(fid, meshname);
910 if (nb_family < 0)
911 ARCANE_FATAL("Impossible de lire le nombre de familles (erreur={0})", nb_family);
912
913 info() << "MED: nb_family= " << nb_family;
914 for (med_int i = 0; i < nb_family; i++) {
915 info() << "MED: Lecture de la famille i=" << i;
916
917 med_int nb_group = MEDnFamilyGroup(fid, meshname, i + 1);
918 if (nb_group < 0)
919 ARCANE_FATAL("Impossible de lire le nombre de groupes pour l'indice de famille={0}", i);
920 info() << "MED: indice de famille=" << i << " nb_group=" << nb_group;
921
922 // Lit les groupes de la famille
923 // Même s'il n'y a pas de groupes associés à la famille on continue
924 // le traitement car les entités peuvent référencer des familles sans groupe.
925
926 // Dans MED, les groupes ont une taille fixe maximale MED_LNAME_SIZE
927 UniqueArray<char> all_group_names(MED_LNAME_SIZE * nb_group + 1);
928 med_int family_number = 0;
929 if (MEDfamilyInfo(fid, meshname, i + 1, familyname.data(), &family_number, all_group_names.data()) < 0)
930 ARCANE_FATAL("Impossible de lire les noms de groupes à partir de l'indice de famille={0}", i);
931
932 MEDFamilyInfo med_family(family_number);
933 Int32 group_index = m_med_groups.size();
934 med_family.m_index = group_index;
935 MEDGroupInfo med_group(group_index);
936
937 // Récupère les noms des groupes de la famille
938 for (Int32 z = 0; z < nb_group; ++z) {
939 //info() << " groupname=" << group_names << " number=" << familynumber;
940 SmallSpan<char> med_group_name = all_group_names.smallSpan().subSpan(MED_LNAME_SIZE * z, MED_LNAME_SIZE);
941 // Les groupes dans MED peuvent contenir des caractères non supportés par Arcane.
942 // On les enlève.
944 Int32 pos = 0;
945 for (; pos < MED_LNAME_SIZE; ++pos) {
946 char c = med_group_name[pos];
947 if (c == '\0')
948 break;
949 if (c == ' ' || c == '_')
950 continue;
951 valid_name.add(static_cast<Byte>(c));
952 }
953 String name(valid_name.view());
954 med_group.m_names.add(name);
955 info() << "ID de famille=" << family_number << " groupe='" << name << "'";
956 }
957
958 m_med_families_map.insert(std::make_pair(family_number, med_family));
959 m_med_groups.add(med_group);
960 }
961}
962
963/*---------------------------------------------------------------------------*/
964/*---------------------------------------------------------------------------*/
972{
973 IParallelMng* pm = m_mesh->parallelMng();
974
975 Int32 rank = pm->commRank();
976 // S'assure que tous les rangs connaissent les groupes
977 if (rank == 0) {
978 Int32 nb_group = group_names.size();
979 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
980 for (String name : group_names)
981 pm->broadcastString(name, 0);
982 }
983 else {
984 Int32 nb_group = 0;
985 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
986 String current_group_name;
987 for (Int32 i = 0; i < nb_group; ++i) {
988 pm->broadcastString(current_group_name, 0);
989 CellGroup cell_group = family->findGroup(current_group_name, true);
990 }
991 }
992}
993
994/*---------------------------------------------------------------------------*/
995/*---------------------------------------------------------------------------*/
996
997/*---------------------------------------------------------------------------*/
998/*---------------------------------------------------------------------------*/
1002class MEDMeshReaderService
1003: public BasicService
1004, public IMeshReader
1005{
1006 public:
1007
1008 explicit MEDMeshReaderService(const ServiceBuildInfo& sbi)
1009 : BasicService(sbi)
1010 {}
1011
1012 public:
1013
1014 void build() override {}
1015 bool allowExtension(const String& str) override
1016 {
1017 return str == "med";
1018 }
1020 [[maybe_unused]] const XmlNode& mesh_element,
1021 const String& file_name,
1022 const String& dir_name,
1023 [[maybe_unused]] bool use_internal_partition) override
1024 {
1025 ARCANE_UNUSED(dir_name);
1026 MEDMeshReader reader(traceMng());
1027 return reader.readMesh(mesh, file_name);
1028 }
1029};
1030
1031/*---------------------------------------------------------------------------*/
1032/*---------------------------------------------------------------------------*/
1033
1034ARCANE_REGISTER_SERVICE(MEDMeshReaderService,
1035 ServiceProperty("MEDMeshReader", ST_SubDomain),
1036 ARCANE_SERVICE_INTERFACE(IMeshReader));
1037
1038/*---------------------------------------------------------------------------*/
1039/*---------------------------------------------------------------------------*/
1040
1041/*---------------------------------------------------------------------------*/
1042/*---------------------------------------------------------------------------*/
1046class MEDCaseMeshReader
1047: public AbstractService
1048, public ICaseMeshReader
1049{
1050 public:
1051
1052 class Builder
1053 : public IMeshBuilder
1054 {
1055 public:
1056
1057 explicit Builder(ITraceMng* tm, const CaseMeshReaderReadInfo& read_info)
1058 : m_trace_mng(tm)
1059 , m_read_info(read_info)
1060 {}
1061
1062 public:
1063
1064 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1065 {
1066 ARCANE_UNUSED(build_info);
1067 }
1069 {
1070 MEDMeshReader reader(m_trace_mng);
1071 String fname = m_read_info.fileName();
1072 m_trace_mng->info() << "Lecteur MED (ICaseMeshReader) file_name=" << fname;
1073 IMeshReader::eReturnType ret = reader.readMesh(pm, fname);
1074 if (ret != IMeshReader::RTOk)
1075 ARCANE_FATAL("Impossible de lire le fichier MED");
1076 }
1077
1078 private:
1079
1080 ITraceMng* m_trace_mng;
1081 CaseMeshReaderReadInfo m_read_info;
1082 };
1083
1084 public:
1085
1086 explicit MEDCaseMeshReader(const ServiceBuildInfo& sbi)
1087 : AbstractService(sbi)
1088 {}
1089
1090 public:
1091
1093 {
1094 IMeshBuilder* builder = nullptr;
1095 if (read_info.format() == "med")
1096 builder = new Builder(traceMng(), read_info);
1097 return makeRef(builder);
1098 }
1099};
1100
1101/*---------------------------------------------------------------------------*/
1102/*---------------------------------------------------------------------------*/
1103
1104ARCANE_REGISTER_SERVICE(MEDCaseMeshReader,
1105 ServiceProperty("MEDCaseMeshReader", ST_SubDomain),
1106 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1107
1108/*---------------------------------------------------------------------------*/
1109/*---------------------------------------------------------------------------*/
1110
1111} // namespace Arcane
1112
1113/*---------------------------------------------------------------------------*/
1114/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions utilitaires sur le maillage.
Face getFaceFromNodesUniqueId(Node node, Int64ConstArrayView face_nodes_unique_id)
Recherche une entité face à partir des numéros uniques de ces noeuds.
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Integer size() const
Nombre d'éléments du vecteur.
Classe de base d'un service.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
Vue modifiable d'un tableau d'un type T.
Tableau d'items de types quelconques.
void clear()
Supprime les éléments du tableau.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
ArrayView< T > view() const
Vue mutable sur ce tableau.
Span< const T > span() const
Vue immutable sur ce tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Informations nécessaires pour la lecture d'un fichier de maillage.
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)
Face d'une maille.
Definition Item.h:964
Interface du service de lecture du maillage à partir du jeu de données.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroup findGroup(const String &name) const =0
Recherche un groupe.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
Interface d'un service de création/lecture du maillage.
Interface du service gérant la lecture d'un maillage.
Definition IMeshReader.h:32
eReturnType
Types des codes de retour d'une lecture ou écriture.
Definition IMeshReader.h:37
@ RTError
Erreur lors de l'opération.
Definition IMeshReader.h:39
@ RTOk
Opération effectuée avec succès.
Definition IMeshReader.h:38
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual void allocateCells(Integer nb_cell, Int64ConstArrayView cells_infos, bool one_alloc=true)=0
Allocation d'un maillage.
Interface du gestionnaire de traces.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Ajoute des entités.
Definition ItemGroup.cc:446
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:34
Type d'une entité (Item).
Definition ItemTypeId.h:32
Infos sur un type d'entité du maillage.
String typeName() const
Nom du type.
Gestionnaire des types d'entités d'un maillage.
Definition ItemTypeMng.h:65
ItemTypeId getPolygonType(Int16 nb_node) const
Retourne le type pour un polygone ayant nb_node.
ItemTypeInfo * typeFromId(Integer id) const
Type correspondant au numéro id.
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
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.
Service de lecture d'un maillage au format MED depuis le jeu de données.
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.
Int32 m_family_id
Id de la famille pour MED.
Int32 m_index
Index dans la liste des groupes Arcane.
Liste des groupes et des entités leur appartenant.
Int32 m_index
Index du groupe dans la liste des groupes.
UniqueArray< Int64 > m_unique_ids
Liste des uniqueId() des entités du groupe.
UniqueArray< String > m_names
Nom des groupes associés.
UniqueArray< Int32 > m_local_ids
Liste des localId() des entités du groupe.
Informations pour passer des types MED aux types Arcane pour les entités.
Lecteur de maillages au format MED.
void _broadcastGroups(ConstArrayView< String > names, IItemFamily *family)
Broadcast les groupes de group_names pour la famille family.
UniqueArray< MEDToArcaneItemInfo > m_med_to_arcane_types
Tableau de conversion entre les types MED et Arcane.
void _readAvailableTypes(med_idt fid, const char *meshname)
Récupère la liste des types géométriques présents dans le maillage.
IPrimaryMesh * m_mesh
Maillage en cours de lecture.
UniqueArray< MEDGroupInfo > m_med_groups
Liste des informations sur les groupes.
std::unordered_map< Int32, MEDFamilyInfo > m_med_families_map
Liste des familles.
std::unordered_map< med_int, Int32 > m_med_geotype_to_arcane_type_index
Table des index dans m_med_to_arcane_type de chaque geotype.
UniqueArray< med_int > m_med_geotypes_in_mesh
Liste des 'geotype' présents dans le maillage.
Int32 _readItems(med_idt fid, const char *meshnane, const MEDToArcaneItemInfo &iinfo, Array< Int16 > &polygon_nb_nodes, Array< med_int > &connectivity, Array< med_int > &family_values)
Lit les informations des entités d'un type donné.
void _readFaces(IPrimaryMesh *mesh, Int32 mesh_dimension, med_idt fid, const char *meshname)
Lit les faces.
Paramètres nécessaires à la construction d'un maillage.
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:582
FaceConnectedListViewType faces() const
Liste des faces du noeud.
Definition Item.h:689
Classe utilitaire pour réordonner les noeuds d'une entité.
Exception lorsqu'une fonction n'est pas implémentée.
Référence à une instance.
Structure contenant les informations pour créer un service.
Tableau 1D de données avec buffer pré-alloué sur la pile.
Vue d'un tableau d'éléments de type T.
Definition Span.h:802
constexpr __host__ __device__ SmallSpan< T, DynExtent > subSpan(Int32 abegin, Int32 asize) const
Sous-vue à partir de l'élément abegin et contenant asize éléments.
Definition Span.h:895
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Chaîne de caractères unicode.
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.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Noeud d'un arbre DOM.
Definition XmlNode.h:51
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
#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 --
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
std::int16_t Int16
Type entier signé sur 16 bits.
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:42
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.