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