Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
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/* Reading a mesh in MED format. */
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 to automatically close open MED files
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 // MED numbering conventions are different from those used in Arcane.
224 // These arrays allow for renumbering.
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 // Not used for now. To be tested.
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: check the connectivity correspondence between
244 // Arcane and MED for quadrilateral elements
245 // 1D Types
246 _addTypeInfo(1, 2, MED_SEG2, ITI_Line2);
247 _addTypeInfo(1, 3, MED_SEG3, ITI_Line3); // Not supported
248 _addTypeInfo(1, 4, MED_SEG4, ITI_NullType); // Not supported
249
250 // 2D Types.
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); // Not supported
254 _addTypeInfo(2, 7, MED_TRIA7, ITI_NullType); // Not supported
255 _addTypeInfo(2, 8, MED_QUAD8, ITI_Quad8, Quad8_indirection);
256 _addTypeInfo(2, 9, MED_QUAD9, ITI_NullType); // Not supported
257
258 // 3D Types
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); // Not supported
266 _addTypeInfo(3, 15, MED_PENTA15, ITI_NullType); // Not supported
267 _addTypeInfo(3, 18, MED_PENTA18, ITI_NullType); // Not supported
268 _addTypeInfo(3, 20, MED_HEXA20, ITI_Hexaedron20);
269 _addTypeInfo(3, 27, MED_HEXA27, ITI_NullType); // Not supported
270
271 // Cells whose geometry has variable connectivity.
272 // For now, we do not support any of these types in Arcane.
273 // We still process these elements to display an error if they are
274 // present in the mesh. By setting the node count to (0), we signal to _readItems()
275 // that we cannot process these elements.
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 // Cells whose geometry is dynamic (model discovery in the file)
282 // TODO: check how to process them
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() << "Trying to read MED File name=" << 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 // To guarantee file closure.
311 AutoCloseMED auto_close_med(fid);
312
313 int nb_mesh = MEDnMesh(fid);
314 if (nb_mesh < 0) {
315 error() << "Error reading number of meshes";
317 }
318 info() << "MED: nb_mesh=" << nb_mesh;
319 if (nb_mesh == 0) {
320 error() << "No mesh is present";
322 }
323
324 // The mesh we read is always the first one
325 int mesh_index = 1;
326
327 // Get the space dimension. This is necessary to dimension axisname and unitname
328 int nb_axis = MEDmeshnAxis(fid, mesh_index);
329 if (nb_axis < 0) {
330 error() << "Can not read number of axis (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() << "Can not read mesh info (MEDmeshInfo) r=" << err;
356 }
357 if (meshtype != MED_UNSTRUCTURED_MESH) {
358 error() << "Arcane handle only MED unstructured mesh (MED_UNSTRUCTURED_MESH) type=" << meshtype;
360 }
361 Integer mesh_dimension = meshdim;
362 if (mesh_dimension != 2 && mesh_dimension != 3)
363 ARCANE_FATAL("MED reader handles only 2D or 3D meshes");
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 // Reading the number of nodes.
377 {
378 med_bool coordinatechangement;
379 med_bool geotransformation;
380 // TODO: process information such as coordinatechangement
381 // and geotransformation if needed
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() << "Can not read number of nodes (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 // MED meshes can contain polygons.
396 // We therefore build the corresponding types.
397 // (NOTE: all subdomains must do this)
398 mesh->itemTypeMng()->buildPolygonTypes();
399
400 IParallelMng* pm = mesh->parallelMng();
401 bool is_parallel = pm->isParallel();
402 Int32 rank = mesh->meshPartInfo().partRank();
403 // In parallel, only rank 0 reads the mesh
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 // The IPrimaryMesh::endAllocate() method is collective, so everyone
411 // must call it even if ranks other than rank 0
412 // do not have cells.
413 mesh->endAllocate();
414
415 // List of names of created cell groups
416 // It will be used to transfer the list of groups to all ranks.
417 UniqueArray<String> cell_group_names;
418 IItemFamily* cell_family = mesh->cellFamily();
419 if (is_read_items) {
420 // Now that all cells have been created, we create the corresponding groups
421 // To do this, we iterate through all instances of 'm_med_groups' and if one has entities
422 // then they are cells to be added to a group.
423 // ATTENTION ATTENTION:
424 // NOTE: The groups must be common to all ranks. They must be broadcasted
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 // Reading the faces
441 if (is_read_items) {
442 // Since the face numbering is not necessarily correct for all
443 // entity types (especially for order 2), we add an option to
444 // not read the 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 // Now add the faces to the groups.
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() << "Check Group 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 // Reading the coordinates
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 // Retrieves the number of geometric types
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("Can not read number of geometric entities nb_geo={0}", nb_geo);
494 info() << "MED: nb_geotype = " << nb_geo;
495
496 // Loop through the present types
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("Can not read informations for geotype index={0} ret={1}", it, type_ret);
507 /* how many cells of type geotype ? */
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("Can not read number of items for geotype={0} name={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 // As a matter of principle, there is no uniqueId() for entities in MED (TODO: to verify)
528 // So we number the cells starting from zero and increment for each
529 // cell created.
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 // Allocates cells type by type.
538 // Iterates through the available types and processes those that match the dimension
539 // of the mesh.
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 // We only process entities of the mesh dimension.
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 // Indicates a type supported by MED but not by Arcane
556 ARCANE_FATAL("MED type '{0}' is not supported by 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 // There is a family associated with the entity
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("Can not find family id '{0}' for cell '{1}' of geotype '{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/*---------------------------------------------------------------------------*/
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 // Iterates through the available types and processes those that correspond to the dimension
647 // of the mesh minus 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 // We only process entities of the mesh dimension.
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 // Indicates a type supported by MED but not by 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 // Search for the face in the mesh starting from the sorted uniqueIds of its nodes
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 // Add the face to the corresponding groups
715 if (i < nb_family_values) {
716 // There is a family associated with the entity
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 // Reads the node coordinates and positions the coordinates in Arcane
740
741 // Connectivity in MED starts at 1 and in Arcane at 0.
742 // The first node therefore has the value for uniqueId()
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 // Positions the coordinates
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 // For polygons, a specific call is needed for the number of indices.
816 // This number corresponds to the number of entities plus one.
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 // The table \a indexes contains for each cell the index of its first
837 // node in the connectivity. The number of nodes of the i-th entity
838 // is therefore equal to (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 // Indicates an element that we do not know how to process.
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 // Retrieves the number of families
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 // Reads the family groups
922 // Even if there are no groups associated with the family, we continue
923 // the processing because entities may reference families without groups.
924
925 // In MED, groups have a fixed maximum size 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 // Retrieves the names of the family groups
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 // Groups in MED may contain characters not supported by Arcane.
941 // We remove them.
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 // Ensures that all ranks know the groups
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 for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
Face getFaceFromNodesUniqueId(Node node, Int64ConstArrayView face_nodes_unique_id)
Searches for a face entity using the unique numbers of these nodes.
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Integer size() const
Number of elements in the vector.
Base class of a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Modifiable view of an array of type T.
Base class for 1D data vectors.
Span< const T > span() const
Immutable view of this array.
void resize(Int64 s)
Changes the number of elements in the array to s.
void clear()
Removes the elements from the array.
void add(ConstReferenceType val)
Adds element val to the end of the array.
const T * data() const
Access to the root of the array without any protection.
ArrayView< T > view() const
Mutable view of this array.
Necessary information for reading a mesh file.
Constant view of an array of type T.
constexpr Integer size() const noexcept
Number of elements in the array.
static std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Face of a cell.
Definition Item.h:1032
Interface for the mesh reading service from the dataset.
Interface of an entity family.
Definition IItemFamily.h:83
virtual ItemGroup findGroup(const String &name) const =0
Searches for a group.
virtual NodeGroup allNodes()=0
Group of all nodes.
Interface of a mesh creation/reading service.
Interface of the service managing the reading of a mesh.
Definition IMeshReader.h:33
eReturnType
Types of return codes for a read or write operation.
Definition IMeshReader.h:38
@ RTError
Error during the operation.
Definition IMeshReader.h:40
@ RTOk
Operation successfully performed.
Definition IMeshReader.h:39
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual VariableNodeReal3 & nodesCoordinates()=0
Node coordinates.
virtual void allocateCells(Integer nb_cell, Int64ConstArrayView cells_infos, bool one_alloc=true)=0
Allocation of a mesh.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Adds entities.
Definition ItemGroup.cc:439
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
Type of an entity (Item).
Definition ItemTypeId.h:33
Info on a mesh entity type.
String typeName() const
Type name.
Mesh entity type manager.
Definition ItemTypeMng.h:66
ItemTypeId getPolygonType(Int16 nb_node) const
Returns the type for a polygon having nb_node.
ItemTypeInfo * typeFromId(Integer id) const
Type corresponding to the number id.
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
constexpr bool null() const
true if the entity is null (i.e. not connected to the mesh)
Definition Item.h:230
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Fills build_info with the necessary information to create the mesh.
Service for reading a mesh in MED format from the dataset.
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Returns a builder to create and read the mesh whose information is specified in read_info.
bool allowExtension(const String &str) override
Checks if the service supports files with the extension str.
void build() override
Build-level construction of the service.
eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_element, const String &file_name, const String &dir_name, bool use_internal_partition) override
Reads a mesh from a file.
Int32 m_index
Index in the Arcane group list.
List of groups and the entities belonging to them.
Int32 m_index
Index of the group in the group list.
UniqueArray< Int64 > m_unique_ids
List of uniqueId() of the group's entities.
UniqueArray< String > m_names
Associated group names.
UniqueArray< Int32 > m_local_ids
List of localId() of the group's entities.
Information for mapping MED types to Arcane types for entities.
MED format mesh reader.
void _broadcastGroups(ConstArrayView< String > names, IItemFamily *family)
Broadcast the groups of group_names for the family family.
UniqueArray< MEDToArcaneItemInfo > m_med_to_arcane_types
Conversion table between MED and Arcane types.
void _readAvailableTypes(med_idt fid, const char *meshname)
Retrieves the list of geometric types present in the mesh.
IPrimaryMesh * m_mesh
Mesh currently being read.
UniqueArray< MEDGroupInfo > m_med_groups
List of group information.
std::unordered_map< Int32, MEDFamilyInfo > m_med_families_map
List of families.
std::unordered_map< med_int, Int32 > m_med_geotype_to_arcane_type_index
Table of indices in m_med_to_arcane_type for each geotype.
UniqueArray< med_int > m_med_geotypes_in_mesh
List of 'geotypes' present in the mesh.
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)
Reads information about entities of a given type.
void _readFaces(IPrimaryMesh *mesh, Int32 mesh_dimension, med_idt fid, const char *meshname)
Reads the faces.
Parameters necessary for building a mesh.
View of node information.
Node of a mesh.
Definition Item.h:598
FaceConnectedListViewType faces() const
List of faces of the node.
Definition Item.h:725
Utility class to reorder the nodes of an entity.
Reference to an instance.
Structure containing the information to create a service.
1D data array with pre-allocated stack buffer.
View of an array of elements of type T.
Definition Span.h:803
constexpr __host__ __device__ SmallSpan< T, DynExtent > subSpan(Int32 abegin, Int32 asize) const
Sub-view starting from element abegin and containing asize elements.
Definition Span.h:897
View of an array of elements of type T.
Definition Span.h:633
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage error() const
Flow for an error message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Node of a DOM tree.
Definition XmlNode.h:51
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
@ ST_SubDomain
The service is used at the subdomain level.
std::int16_t Int16
Signed integer type of 16 bits.
unsigned char Byte
Type of a byte.
Definition BaseTypes.h:42
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.