Arcane  4.1.12.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
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 to automatically close open MED files
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 // MED numbering conventions are different from those used in Arcane.
223 // These arrays allow for renumbering.
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 // Not used for now. To be tested.
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: check the connectivity correspondence between
243 // Arcane and MED for quadrilateral elements
244 // 1D Types
245 _addTypeInfo(1, 2, MED_SEG2, ITI_Line2);
246 _addTypeInfo(1, 3, MED_SEG3, ITI_Line3); // Not supported
247 _addTypeInfo(1, 4, MED_SEG4, ITI_NullType); // Not supported
248
249 // 2D Types.
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); // Not supported
253 _addTypeInfo(2, 7, MED_TRIA7, ITI_NullType); // Not supported
254 _addTypeInfo(2, 8, MED_QUAD8, ITI_Quad8, Quad8_indirection);
255 _addTypeInfo(2, 9, MED_QUAD9, ITI_NullType); // Not supported
256
257 // 3D Types
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); // Not supported
265 _addTypeInfo(3, 15, MED_PENTA15, ITI_NullType); // Not supported
266 _addTypeInfo(3, 18, MED_PENTA18, ITI_NullType); // Not supported
267 _addTypeInfo(3, 20, MED_HEXA20, ITI_Hexaedron20);
268 _addTypeInfo(3, 27, MED_HEXA27, ITI_NullType); // Not supported
269
270 // Cells whose geometry has variable connectivity.
271 // For now, we do not support any of these types in Arcane.
272 // We still process these elements to display an error if they are
273 // present in the mesh. By setting the node count to (0), we signal to _readItems()
274 // that we cannot process these elements.
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 // Cells whose geometry is dynamic (model discovery in the file)
281 // TODO: check how to process them
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 // To guarantee file closure.
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 // The mesh we read is always the first one
324 int mesh_index = 1;
325
326 // Get the space dimension. This is necessary to dimension axisname and 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 // Reading the number of nodes.
376 {
377 med_bool coordinatechangement;
378 med_bool geotransformation;
379 // TODO: process information such as coordinatechangement
380 // and geotransformation if needed
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 // MED meshes can contain polygons.
395 // We therefore build the corresponding types.
396 // (NOTE: all subdomains must do this)
397 mesh->itemTypeMng()->buildPolygonTypes();
398
399 IParallelMng* pm = mesh->parallelMng();
400 bool is_parallel = pm->isParallel();
401 Int32 rank = mesh->meshPartInfo().partRank();
402 // In parallel, only rank 0 reads the mesh
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 // The IPrimaryMesh::endAllocate() method is collective, so everyone
410 // must call it even if ranks other than rank 0
411 // do not have cells.
412 mesh->endAllocate();
413
414 // List of names of created cell groups
415 // It will be used to transfer the list of groups to all ranks.
416 UniqueArray<String> cell_group_names;
417 IItemFamily* cell_family = mesh->cellFamily();
418 if (is_read_items) {
419 // Now that all cells have been created, we create the corresponding groups
420 // To do this, we iterate through all instances of 'm_med_groups' and if one has entities
421 // then they are cells to be added to a group.
422 // ATTENTION ATTENTION:
423 // NOTE: The groups must be common to all ranks. They must be broadcasted
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 // Reading the faces
440 if (is_read_items) {
441 // Since the face numbering is not necessarily correct for all
442 // entity types (especially for order 2), we add an option to
443 // not read the 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 // Now add the faces to the groups.
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 // Reading the coordinates
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 // Retrieves the number of geometric types
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 // Loop through the present types
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 // As a matter of principle, there is no uniqueId() for entities in MED (TODO: to verify)
527 // So we number the cells starting from zero and increment for each
528 // cell created.
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 // Allocates cells type by type.
537 // Iterates through the available types and processes those that match the dimension
538 // of the mesh.
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 // We only process entities of the mesh dimension.
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 // Indicates a type supported by MED but not by 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 // There is a family associated with the entity
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/*---------------------------------------------------------------------------*/
633_readFaces(IPrimaryMesh* mesh, Int32 mesh_dimension, med_idt fid, const char* meshname)
634{
635 _clearItemsInGroups();
636 ItemTypeMng* itm = mesh->itemTypeMng();
637 NodesOfItemReorderer nodes_reorderer(itm);
638
639 IItemFamily* node_family = mesh->nodeFamily();
640 NodeInfoListView mesh_nodes(node_family);
641
642 UniqueArray<Int16> polygon_nb_nodes;
643 UniqueArray<med_int> med_connectivity;
644 UniqueArray<med_int> med_family_values;
645 // Iterates through the available types and processes those that correspond to the dimension
646 // of the mesh minus 1.
647 for (med_int geotype : m_med_geotypes_in_mesh) {
648 Int32 index_in_list = m_med_geotype_to_arcane_type_index[geotype];
649 const MEDToArcaneItemInfo& iinfo = m_med_to_arcane_types[index_in_list];
650
651 Int32 item_dimension = iinfo.dimension();
652 // We only process entities of the mesh dimension.
653 if (item_dimension != (mesh_dimension - 1))
654 continue;
655 ItemTypeInfo* iti = itm->typeFromId(iinfo.arcaneType());
656 info() << "Reading faces geotype=" << geotype << " arcane_type=" << iinfo.arcaneType()
657 << " " << iti->typeName();
658
659 Int32 nb_item = _readItems(fid, meshname, iinfo, polygon_nb_nodes, med_connectivity, med_family_values);
660 if (nb_item == 0)
661 continue;
662 ItemTypeId arcane_type(iinfo.arcaneType());
663 Int32 nb_item_node = iinfo.nbNode();
664 Int32 nb_family_values = med_family_values.size();
665 if (arcane_type == IT_NullType) {
666 // Indicates a type supported by MED but not by Arcane
667 ARCANE_FATAL("MED type '{0}' is not supported by Arcane", iinfo.medType());
668 }
669
670 SmallArray<Int64> orig_nodes_id(nb_item_node);
671 info() << "FACES_INFOS nb_item=" << nb_item << " type=" << arcane_type
672 << " nb_family_values=" << nb_family_values;
673
674 const Int32* indirection = iinfo.indirection();
675 Int64 med_connectivity_index = 0;
676
677 for (Int32 i = 0; i < nb_item; ++i) {
678 ArrayView<Int64> cinfo_span(orig_nodes_id);
679 Span<med_int> med_cinfo_span(med_connectivity.span().subspan(med_connectivity_index, nb_item_node));
680 if (indirection) {
681 for (Integer k = 0; k < nb_item_node; ++k) {
682 cinfo_span[k] = med_cinfo_span[indirection[k]];
683 }
684 }
685 else {
686 for (Integer k = 0; k < nb_item_node; ++k)
687 cinfo_span[k] = med_cinfo_span[k];
688 }
689 med_connectivity_index += nb_item_node;
690 // Search for the face in the mesh starting from the sorted uniqueIds of its nodes
691 nodes_reorderer.reorder(arcane_type, cinfo_span);
692 ConstArrayView<Int64> ordered_nodes = nodes_reorderer.sortedNodes();
693 //info() << "OrigMedNodes=" << med_cinfo_span;
694 //info() << "OrigNodes=" << orig_nodes_id;
695 //info() << "Nodes=" << ordered_nodes;
696 Node first_node(MeshUtils::findOneItem(node_family, ordered_nodes[0]));
697 if (first_node.null())
698 ARCANE_FATAL("Can not find node uid={0} for face index '{1}'", ordered_nodes[0], i);
699 Face face = MeshUtils::getFaceFromNodesUniqueId(first_node, ordered_nodes);
700 if (face.null()) {
701 info() << "ERROR: Can not find face in mesh i=" << i << " nodes=" << ordered_nodes;
702 info() << "List of faces for node=" << ItemPrinter(first_node);
703 for (Face subface : first_node.faces()) {
704 info() << "Face=" << ItemPrinter(subface);
705 for (Node subnode : subface.nodes()) {
706 info() << " Node=" << ItemPrinter(subnode);
707 }
708 }
709 ARCANE_FATAL("Can not find face with nodes=", ordered_nodes);
710 }
711 //info() << "Face=" << ItemPrinter(face);
712
713 // Add the face to the corresponding groups
714 if (i < nb_family_values) {
715 // There is a family associated with the entity
716 med_int f = med_family_values[i];
717 auto x = m_med_families_map.find(f);
718 if (x == m_med_families_map.end()) {
719 ARCANE_FATAL("Can not find family id '{0}' for face '{1}' of geotype '{2}'",
720 f, i, iinfo.medType());
721 }
722 //info() << "Add face to group_index=" << x->second.m_index;
723 m_med_groups[x->second.m_index].m_local_ids.add(face.localId());
724 }
725 }
726 info() << "END_READING_ITEMS";
727 }
728}
729
730/*---------------------------------------------------------------------------*/
731/*---------------------------------------------------------------------------*/
732
733IMeshReader::eReturnType MEDMeshReader::
734_readNodesCoordinates(IPrimaryMesh* mesh, Int64 nb_node, Int32 spacedim,
735 med_idt fid, const char* meshname)
736{
737 const bool do_verbose = false;
738 // Reads the node coordinates and positions the coordinates in Arcane
739
740 // Connectivity in MED starts at 1 and in Arcane at 0.
741 // The first node therefore has the value for uniqueId()
742 UniqueArray<Real3> nodes_coordinates(nb_node + 1);
743 {
744 UniqueArray<med_float> coordinates(nb_node * spacedim);
745 int err = MEDmeshNodeCoordinateRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE,
746 coordinates.data());
747 if (err < 0) {
748 error() << "Can not read nodes coordinates err=" << err;
750 }
751
752 if (spacedim == 3) {
753 for (Int64 i = 0; i < nb_node; ++i) {
754 Real3 xyz(coordinates[i * 3], coordinates[(i * 3) + 1], coordinates[(i * 3) + 2]);
755 if (do_verbose)
756 info() << "I=" << i << " XYZ=" << xyz;
757 nodes_coordinates[i + 1] = xyz;
758 }
759 }
760 else if (spacedim == 2) {
761 for (Int64 i = 0; i < nb_node; ++i) {
762 Real3 xyz(coordinates[i * 2], coordinates[(i * 2) + 1], 0.0);
763 if (do_verbose)
764 info() << "I=" << i << " XYZ=" << xyz;
765 nodes_coordinates[i + 1] = xyz;
766 }
767 }
768 else
769 ARCANE_THROW(NotImplementedException, "spacedim!=2 && spacedim!=3");
770 }
771
772 // Positions the coordinates
773 {
774 VariableNodeReal3& nodes_coord_var(mesh->nodesCoordinates());
775 ENUMERATE_NODE (inode, mesh->allNodes()) {
776 Node node = *inode;
777 nodes_coord_var[inode] = nodes_coordinates[node.uniqueId()];
778 }
779 }
780 return IMeshReader::RTOk;
781}
782
783/*---------------------------------------------------------------------------*/
784/*---------------------------------------------------------------------------*/
800_readItems(med_idt fid, const char* meshname, const MEDToArcaneItemInfo& iinfo,
801 Array<Int16>& polygon_nb_nodes, Array<med_int>& connectivity,
802 Array<med_int>& family_values)
803{
804 constexpr bool is_verbose = false;
805
806 connectivity.clear();
807 family_values.clear();
808
809 int med_item_type = iinfo.medType();
810 med_bool coordinatechangement = {};
811 med_bool geotransformation = {};
812 med_int nb_med_item = 0;
813 if (iinfo.medType() == MED_POLYGON) {
814 // For polygons, a specific call is needed for the number of indices.
815 // This number corresponds to the number of entities plus one.
816 med_int nb_index = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
817 MED_INDEX_NODE, MED_NODAL, &coordinatechangement,
818 &geotransformation);
819 if (nb_index < 0)
820 ARCANE_FATAL("Can not read MED med_item_type '{0}' error={1}", med_item_type, nb_index);
821
822 info() << "MED: Reading items";
823 info() << "MED: type=" << med_item_type << " nb_index=" << nb_index;
824 if (nb_index < 1)
825 return 0;
826 nb_med_item = nb_index - 1;
827 polygon_nb_nodes.resize(nb_med_item);
828 // how many nodes for the polygon connectivity ?
829 med_int nb_connectivity = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
830 MED_CELL, MED_POLYGON, MED_CONNECTIVITY, MED_NODAL,
831 &coordinatechangement, &geotransformation);
832 if (nb_connectivity < 0)
833 ARCANE_FATAL("Can not get connectivity size for MED_POLYGON err={0}", nb_connectivity);
834
835 // The table \a indexes contains for each cell the index of its first
836 // node in the connectivity. The number of nodes of the i-th entity
837 // is therefore equal to (indexes[i+1]-indexes[i]).
838 UniqueArray<med_int> indexes(nb_index);
839 connectivity.resize(nb_connectivity);
840 info() << "Reading polygons nb_connectivity=" << nb_connectivity;
841 int r = MEDmeshPolygonRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, MED_NODAL,
842 indexes.data(), connectivity.data());
843 if (r < 0)
844 ARCANE_FATAL("Can not read connectivity for MED_POLYGON err={0}", r);
845 info() << "INDEXES=" << indexes;
846 for (Int32 i = 0; i < nb_med_item; ++i)
847 polygon_nb_nodes[i] = static_cast<Int16>(indexes[i + 1] - indexes[i]);
848 }
849 else {
850 nb_med_item = ::MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL, med_item_type,
851 MED_CONNECTIVITY, MED_NODAL, &coordinatechangement,
852 &geotransformation);
853 if (nb_med_item < 0)
854 ARCANE_FATAL("Can not read MED med_item_type '{0}' error={1}", med_item_type, nb_med_item);
855
856 info() << "MED: Reading items";
857 info() << "MED: type=" << med_item_type << " nb_item=" << nb_med_item;
858 if (nb_med_item == 0)
859 return 0;
860
861 Int64 nb_node = iinfo.nbNode();
862 if (nb_node == 0)
863 // Indicates an element that we do not know how to process.
864 ARCANE_THROW(NotImplementedException, "Reading items with MED type '{0}'", med_item_type);
865
866 connectivity.resize(nb_node * nb_med_item);
867 int err = MEDmeshElementConnectivityRd(fid, meshname, MED_NO_DT, MED_NO_IT, MED_CELL,
868 med_item_type, MED_NODAL, MED_FULL_INTERLACE,
869 connectivity.data());
870 if (err < 0)
871 ARCANE_FATAL("Can not read connectivity MED med_item_type '{0}' error={1}",
872 med_item_type, err);
873 }
874 if (is_verbose)
875 info() << "CON: " << connectivity;
876 {
877 med_int nb_med_family = MEDmeshnEntity(fid, meshname, MED_NO_DT, MED_NO_IT,
878 MED_CELL, med_item_type, MED_FAMILY_NUMBER, MED_NODAL,
879 &coordinatechangement, &geotransformation);
880 info() << "nb_family=" << nb_med_family;
881 if (nb_med_family < 0)
882 ARCANE_FATAL("Can not read family size for type med_item_type={0} error={1}", med_item_type, nb_med_family);
883 if (nb_med_family > 0) {
884 family_values.resize(nb_med_family);
885 int r = MEDmeshEntityFamilyNumberRd(fid, meshname, MED_NO_DT, MED_NO_IT,
886 MED_CELL, med_item_type, family_values.data());
887 if (r < 0)
888 ARCANE_FATAL("Can not read family values for type med_item_type={0} error={1}", med_item_type, nb_med_family);
889 if (is_verbose)
890 info() << "FAM: " << family_values;
891 }
892 }
893 return nb_med_item;
894}
895
896/*---------------------------------------------------------------------------*/
897/*---------------------------------------------------------------------------*/
898
899void MEDMeshReader::
900_readFamilies(med_idt fid, const char* meshname)
901{
903
904 info() << "Read families";
905
906 // Retrieves the number of families
907 med_int nb_family = MEDnFamily(fid, meshname);
908 if (nb_family < 0)
909 ARCANE_FATAL("Can not read number of families (error={0})", nb_family);
910
911 info() << "MED: nb_family= " << nb_family;
912 for (med_int i = 0; i < nb_family; i++) {
913 info() << "MED: Read family i=" << i;
914
915 med_int nb_group = MEDnFamilyGroup(fid, meshname, i + 1);
916 if (nb_group < 0)
917 ARCANE_FATAL("Can not read number of groups for family index={0}", i);
918 info() << "MED: family index=" << i << " nb_group=" << nb_group;
919
920 // Reads the family groups
921 // Even if there are no groups associated with the family, we continue
922 // the processing because entities may reference families without groups.
923
924 // In MED, groups have a fixed maximum size MED_LNAME_SIZE
925 UniqueArray<char> all_group_names(MED_LNAME_SIZE * nb_group + 1);
926 med_int family_number = 0;
927 if (MEDfamilyInfo(fid, meshname, i + 1, familyname.data(), &family_number, all_group_names.data()) < 0)
928 ARCANE_FATAL("Can not read group names from family index={0}", i);
929
930 MEDFamilyInfo med_family(family_number);
931 Int32 group_index = m_med_groups.size();
932 med_family.m_index = group_index;
933 MEDGroupInfo med_group(group_index);
934
935 // Retrieves the names of the family groups
936 for (Int32 z = 0; z < nb_group; ++z) {
937 //info() << " groupname=" << group_names << " number=" << familynumber;
938 SmallSpan<char> med_group_name = all_group_names.smallSpan().subSpan(MED_LNAME_SIZE * z, MED_LNAME_SIZE);
939 // Groups in MED may contain characters not supported by Arcane.
940 // We remove them.
942 Int32 pos = 0;
943 for (; pos < MED_LNAME_SIZE; ++pos) {
944 char c = med_group_name[pos];
945 if (c == '\0')
946 break;
947 if (c == ' ' || c == '_')
948 continue;
949 valid_name.add(static_cast<Byte>(c));
950 }
951 String name(valid_name.view());
952 med_group.m_names.add(name);
953 info() << "Family id=" << family_number << " group='" << name << "'";
954 }
955
956 m_med_families_map.insert(std::make_pair(family_number, med_family));
957 m_med_groups.add(med_group);
958 }
959}
960
961/*---------------------------------------------------------------------------*/
962/*---------------------------------------------------------------------------*/
970{
971 IParallelMng* pm = m_mesh->parallelMng();
972
973 Int32 rank = pm->commRank();
974 // Ensures that all ranks know the groups
975 if (rank == 0) {
976 Int32 nb_group = group_names.size();
977 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
978 for (String name : group_names)
979 pm->broadcastString(name, 0);
980 }
981 else {
982 Int32 nb_group = 0;
983 pm->broadcast(ArrayView<Int32>(1, &nb_group), 0);
984 String current_group_name;
985 for (Int32 i = 0; i < nb_group; ++i) {
986 pm->broadcastString(current_group_name, 0);
987 CellGroup cell_group = family->findGroup(current_group_name, true);
988 }
989 }
990}
991
992/*---------------------------------------------------------------------------*/
993/*---------------------------------------------------------------------------*/
994
995/*---------------------------------------------------------------------------*/
996/*---------------------------------------------------------------------------*/
1000class MEDMeshReaderService
1001: public BasicService
1002, public IMeshReader
1003{
1004 public:
1005
1006 explicit MEDMeshReaderService(const ServiceBuildInfo& sbi)
1007 : BasicService(sbi)
1008 {}
1009
1010 public:
1011
1012 void build() override {}
1013 bool allowExtension(const String& str) override
1014 {
1015 return str == "med";
1016 }
1018 [[maybe_unused]] const XmlNode& mesh_element,
1019 const String& file_name,
1020 const String& dir_name,
1021 [[maybe_unused]] bool use_internal_partition) override
1022 {
1023 ARCANE_UNUSED(dir_name);
1024 MEDMeshReader reader(traceMng());
1025 return reader.readMesh(mesh, file_name);
1026 }
1027};
1028
1029/*---------------------------------------------------------------------------*/
1030/*---------------------------------------------------------------------------*/
1031
1032ARCANE_REGISTER_SERVICE(MEDMeshReaderService,
1033 ServiceProperty("MEDMeshReader", ST_SubDomain),
1034 ARCANE_SERVICE_INTERFACE(IMeshReader));
1035
1036/*---------------------------------------------------------------------------*/
1037/*---------------------------------------------------------------------------*/
1038
1039/*---------------------------------------------------------------------------*/
1040/*---------------------------------------------------------------------------*/
1044class MEDCaseMeshReader
1045: public AbstractService
1046, public ICaseMeshReader
1047{
1048 public:
1049
1050 class Builder
1051 : public IMeshBuilder
1052 {
1053 public:
1054
1055 explicit Builder(ITraceMng* tm, const CaseMeshReaderReadInfo& read_info)
1056 : m_trace_mng(tm)
1057 , m_read_info(read_info)
1058 {}
1059
1060 public:
1061
1062 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1063 {
1064 ARCANE_UNUSED(build_info);
1065 }
1067 {
1068 MEDMeshReader reader(m_trace_mng);
1069 String fname = m_read_info.fileName();
1070 m_trace_mng->info() << "MED Reader (ICaseMeshReader) file_name=" << fname;
1071 IMeshReader::eReturnType ret = reader.readMesh(pm, fname);
1072 if (ret != IMeshReader::RTOk)
1073 ARCANE_FATAL("Can not read MED File");
1074 }
1075
1076 private:
1077
1078 ITraceMng* m_trace_mng;
1079 CaseMeshReaderReadInfo m_read_info;
1080 };
1081
1082 public:
1083
1084 explicit MEDCaseMeshReader(const ServiceBuildInfo& sbi)
1085 : AbstractService(sbi)
1086 {}
1087
1088 public:
1089
1091 {
1092 IMeshBuilder* builder = nullptr;
1093 if (read_info.format() == "med")
1094 builder = new Builder(traceMng(), read_info);
1095 return makeRef(builder);
1096 }
1097};
1098
1099/*---------------------------------------------------------------------------*/
1100/*---------------------------------------------------------------------------*/
1101
1102ARCANE_REGISTER_SERVICE(MEDCaseMeshReader,
1103 ServiceProperty("MEDCaseMeshReader", ST_SubDomain),
1104 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1105
1106/*---------------------------------------------------------------------------*/
1107/*---------------------------------------------------------------------------*/
1108
1109} // namespace Arcane
1110
1111/*---------------------------------------------------------------------------*/
1112/*---------------------------------------------------------------------------*/
#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:805
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:899
View of an array of elements of type T.
Definition Span.h:635
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:43
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.