Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
MshMeshReader.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/* MshMeshReader.cc (C) 2000-2025 */
9/* */
10/* Reading/Writing of an MSH format file. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Iostream.h"
15#include "arcane/utils/StdHeader.h"
16#include "arcane/utils/HashTableMap.h"
17#include "arcane/utils/ValueConvert.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/String.h"
20#include "arcane/utils/IOException.h"
21#include "arcane/utils/Collection.h"
22#include "arcane/utils/Real3.h"
23#include "arcane/utils/OStringStream.h"
24
25#include "arcane/core/AbstractService.h"
26#include "arcane/core/FactoryService.h"
27#include "arcane/core/IMeshReader.h"
28#include "arcane/core/IMesh.h"
29#include "arcane/core/IMeshSubMeshTransition.h"
30#include "arcane/core/IItemFamily.h"
31#include "arcane/core/Item.h"
33#include "arcane/core/VariableTypes.h"
34#include "arcane/core/IVariableAccessor.h"
35#include "arcane/core/IParallelMng.h"
36#include "arcane/core/MeshPartInfo.h"
38#include "arcane/core/ICaseMeshReader.h"
39#include "arcane/core/IMeshBuilder.h"
40#include "arcane/core/ItemPrinter.h"
41
42// Element types in .msh file format, found in gmsh-2.0.4/Common/GmshDefines.h
43#include "arcane/std/internal/IosFile.h"
44#include "arcane/std/internal/IosGmsh.h"
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49// NOTE: Starting in July 2024 (version 3.13.8), the parallel version of the reader
50// (MshParallelMshReader.cc) is used by default. This version will eventually be removed.
51
52/*
53 * NOTES:
54 * - The `gmsh` library provides an 'open.py' script in the 'demos/api' directory
55 * that allows generating a '.msh' file from a '.geo'.
56 * - It is also possible to use the 'gmsh' executable directly with
57 * the '-save-all' option to save a '.msh' file from a '.geo'
58 *
59 * TODO:
60 * - read node tags (uniqueId())
61 * - support partitions
62 * - be able to use the 'gmsh' library directly.
63 * - improve parallel reading by preventing all subdomains
64 * from reading the file (even if only subdomain 0 allocates entities)
65 */
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70namespace Arcane
71{
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
89class MshMeshReader
90: public TraceAccessor
91, public IMshMeshReader
92{
93 public:
94
95 using eReturnType = typename IMeshReader::eReturnType;
96
104 {
110 Int32 entity_tag = -1;
112 UniqueArray<Int64> connectivity;
113 };
114
119 struct MeshPhysicalName
120 {
121 MeshPhysicalName(Int32 _dimension, Int32 _tag, const String& _name)
122 : dimension(_dimension)
123 , tag(_tag)
124 , name(_name)
125 {}
126 MeshPhysicalName() = default;
127 bool isNull() const { return dimension == (-1); }
128 Int32 dimension = -1;
129 Int32 tag = -1;
130 String name;
131 };
132
136 struct MeshPhysicalNameList
137 {
138 MeshPhysicalNameList()
139 : m_physical_names(4)
140 {}
141 void add(Int32 dimension, Int32 tag, String name)
142 {
143 m_physical_names[dimension].add(MeshPhysicalName{ dimension, tag, name });
144 }
145 MeshPhysicalName find(Int32 dimension, Int32 tag) const
146 {
147 for (auto& x : m_physical_names[dimension])
148 if (x.tag == tag)
149 return x;
150 return {};
151 }
152
153 private:
154
156 };
157
159 struct MeshV4EntitiesNodes
160 {
161 MeshV4EntitiesNodes(Int32 _tag, Int32 _physical_tag)
162 : tag(_tag)
163 , physical_tag(_physical_tag)
164 {}
165 Int32 tag;
166 Int32 physical_tag;
167 };
168
170 struct MeshV4EntitiesWithNodes
171 {
172 MeshV4EntitiesWithNodes(Int32 _dim, Int32 _tag, Int32 _physical_tag)
173 : dimension(_dim)
174 , tag(_tag)
175 , physical_tag(_physical_tag)
176 {}
177 Int32 dimension;
178 Int32 tag;
179 Int32 physical_tag;
180 };
181
182 struct MeshInfo
183 {
184 public:
185
186 MeshInfo()
187 : node_coords_map(5000, true)
188 {}
189
190 public:
191
192 MeshV4EntitiesWithNodes* findEntities(Int32 dimension, Int32 tag)
193 {
194 for (auto& x : entities_with_nodes_list[dimension - 1])
195 if (x.tag == tag)
196 return &x;
197 return nullptr;
198 }
199
200 MeshV4EntitiesNodes* findNodeEntities(Int32 tag)
201 {
202 for (auto& x : entities_nodes_list)
203 if (x.tag == tag)
204 return &x;
205 return nullptr;
206 }
207
208 public:
209
210 Integer nb_elements = 0;
211 Integer nb_cell_node = 0;
212 UniqueArray<Int32> cells_nb_node;
213 UniqueArray<Int32> cells_type;
214 UniqueArray<Int64> cells_uid;
215 UniqueArray<Int64> cells_connectivity;
216 UniqueArray<Real3> node_coords;
217 HashTableMapT<Int64, Real3> node_coords_map;
218 MeshPhysicalNameList physical_name_list;
219 UniqueArray<MeshV4EntitiesNodes> entities_nodes_list;
220 UniqueArray<MeshV4EntitiesWithNodes> entities_with_nodes_list[3];
222 };
223
224 public:
225
226 explicit MshMeshReader(ITraceMng* tm)
227 : TraceAccessor(tm)
228 {}
229
230 eReturnType readMeshFromMshFile(IMesh* mesh, const String& file_name, bool use_internal_partition) override;
231
232 private:
233
234 Integer m_version = 0;
235
236 eReturnType _readNodesFromAsciiMshV2File(IosFile&, Array<Real3>&);
237 eReturnType _readNodesFromAsciiMshV4File(IosFile&, MeshInfo& mesh_info);
238 eReturnType _readNodesFromBinaryMshFile(IosFile&, Array<Real3>&);
239 Integer _readElementsFromAsciiMshV2File(IosFile&, MeshInfo& mesh_info);
240 Integer _readElementsFromAsciiMshV4File(IosFile&, MeshInfo& mesh_info);
241 eReturnType _readMeshFromNewMshFile(IMesh*, IosFile&);
242 void _allocateCells(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
243 void _allocateGroups(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
244 void _addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
245 void _addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
246 void _addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
247 Integer _switchMshType(Integer, Integer&);
248 void _readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info);
249 void _readEntitiesV4(IosFile& ios_file, MeshInfo& mesh_info);
250};
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255extern "C++" Ref<IMshMeshReader>
256createMshMeshReader(ITraceMng* tm)
257{
258 return makeRef<IMshMeshReader>(new MshMeshReader(tm));
259}
260
261/*---------------------------------------------------------------------------*/
262/*---------------------------------------------------------------------------*/
263
264Integer MshMeshReader::
265_switchMshType(Integer mshElemType, Integer& nNodes)
266{
267 switch (mshElemType) {
268 case (IT_NullType): // used to decode IT_NullType: IT_HemiHexa7|IT_Line9
269 switch (nNodes) {
270 case (7):
271 return IT_HemiHexa7;
272 default:
273 info() << "Could not decode IT_NullType with nNodes=" << nNodes;
274 throw IOException("_convertToMshType", "Could not decode IT_NullType with nNodes");
275 }
276 break;
277 case (MSH_PNT):
278 nNodes = 1;
279 return IT_Vertex; //printf("1-node point");
280 case (MSH_LIN_2):
281 nNodes = 2;
282 return IT_Line2; //printf("2-node line");
283 case (MSH_TRI_3):
284 nNodes = 3;
285 return IT_Triangle3; //printf("3-node triangle");
286 case (MSH_QUA_4):
287 nNodes = 4;
288 return IT_Quad4; //printf("4-node quadrangle");
289 case (MSH_TET_4):
290 nNodes = 4;
291 return IT_Tetraedron4; //printf("4-node tetrahedron");
292 case (MSH_HEX_8):
293 nNodes = 8;
294 return IT_Hexaedron8; //printf("8-node hexahedron");
295 case (MSH_PRI_6):
296 nNodes = 6;
297 return IT_Pentaedron6; //printf("6-node prism");
298 case (MSH_PYR_5):
299 nNodes = 5;
300 return IT_Pyramid5; //printf("5-node pyramid");
301 case (MSH_TRI_10):
302 nNodes = 10;
303 return IT_Heptaedron10; //printf("10-node second order tetrahedron")
304 case (MSH_TRI_12):
305 nNodes = 12;
306 return IT_Octaedron12; //printf("Unknown MSH_TRI_12");
307
308 case (MSH_TRI_6):
309 case (MSH_QUA_9):
310 case (MSH_HEX_27):
311 case (MSH_PRI_18):
312 case (MSH_PYR_14):
313 case (MSH_QUA_8):
314 case (MSH_HEX_20):
315 case (MSH_PRI_15):
316 case (MSH_PYR_13):
317 case (MSH_TRI_9):
318 case (MSH_TRI_15):
319 case (MSH_TRI_15I):
320 case (MSH_TRI_21):
321 default:
322 ARCANE_THROW(NotSupportedException, "Unknown GMSH element type '{0}'", mshElemType);
323 }
324 return IT_NullType;
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
330IMeshReader::eReturnType MshMeshReader::
331_readNodesFromAsciiMshV2File(IosFile& ios_file, Array<Real3>& node_coords)
332{
333 // number-of-nodes & coords
334 info() << "[_readNodesFromAsciiMshV2File] Looking for number-of-nodes";
335 Integer nb_node = ios_file.getInteger();
336 if (nb_node < 0)
337 throw IOException(A_FUNCINFO, String("Invalid number of nodes: n=") + nb_node);
338 info() << "[_readNodesFromAsciiMshV2File] nb_node=" << nb_node;
339 for (Integer i = 0; i < nb_node; ++i) {
340 // Must read the ID even if it is not used.
341 [[maybe_unused]] Int32 id = ios_file.getInteger();
342 Real nx = ios_file.getReal();
343 Real ny = ios_file.getReal();
344 Real nz = ios_file.getReal();
345 node_coords.add(Real3(nx, ny, nz));
346 //info() << "id_" << id << " xyz(" << nx << "," << ny << "," << nz << ")";
347 }
348 ios_file.getNextLine(); // Skip current \n\r
349 return IMeshReader::RTOk;
350}
351
352/*---------------------------------------------------------------------------*/
353/*---------------------------------------------------------------------------*/
374_readNodesFromAsciiMshV4File(IosFile& ios_file, MeshInfo& mesh_info)
375{
376 // First line of the file
377 Integer nb_entity = ios_file.getInteger();
378 Integer total_nb_node = ios_file.getInteger();
379 Integer min_node_tag = ios_file.getInteger();
380 Integer max_node_tag = ios_file.getInteger();
381 ios_file.getNextLine(); // Skip current \n\r
382 if (total_nb_node < 0)
383 ARCANE_THROW(IOException, "Invalid number of nodes : '{0}'", total_nb_node);
384 info() << "[Nodes] nb_entity=" << nb_entity
385 << " total_nb_node=" << total_nb_node
386 << " min_tag=" << min_node_tag
387 << " max_tag=" << max_node_tag;
388
389 UniqueArray<Int32> nodes_uids;
390 for (Integer i_entity = 0; i_entity < nb_entity; ++i_entity) {
391 // Entity dimension (not useful)
392 [[maybe_unused]] Integer entity_dim = ios_file.getInteger();
393 // Entity tag (not useful)
394 [[maybe_unused]] Integer entity_tag = ios_file.getInteger();
395 Integer parametric_coordinates = ios_file.getInteger();
396 Integer nb_node2 = ios_file.getInteger();
397 ios_file.getNextLine();
398
399 info(4) << "[Nodes] index=" << i_entity << " entity_dim=" << entity_dim << " entity_tag=" << entity_tag
400 << " parametric=" << parametric_coordinates
401 << " nb_node2=" << nb_node2;
402 if (parametric_coordinates != 0)
403 ARCANE_THROW(NotSupportedException, "Only 'parametric coordinates' value of '0' is supported (current={0})", parametric_coordinates);
404 // It is possible that the number of nodes is 0.
405 // In this case, we must directly proceed to the next line
406 if (nb_node2 == 0)
407 continue;
408 nodes_uids.resize(nb_node2);
409 for (Integer i = 0; i < nb_node2; ++i) {
410 // Keep the node's uniqueId().
411 nodes_uids[i] = ios_file.getInteger();
412 //info() << "I=" << i << " ID=" << nodes_uids[i];
413 }
414 for (Integer i = 0; i < nb_node2; ++i) {
415 Real nx = ios_file.getReal();
416 Real ny = ios_file.getReal();
417 Real nz = ios_file.getReal();
418 Real3 xyz(nx, ny, nz);
419 mesh_info.node_coords_map.add(nodes_uids[i], xyz);
420 //info() << "I=" << i << " ID=" << nodes_uids[i] << " COORD=" << xyz;
421 }
422 ios_file.getNextLine(); // Skip current \n\r
423 }
424 return IMeshReader::RTOk;
425}
426
427/*---------------------------------------------------------------------------*/
428/*---------------------------------------------------------------------------*/
429
430Integer MshMeshReader::
431_readElementsFromAsciiMshV2File(IosFile& ios_file, MeshInfo& mesh_info)
432{
433 Integer number_of_elements = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
434 if (number_of_elements < 0)
435 ARCANE_THROW(IOException, String("Error with the number_of_elements=") + number_of_elements);
436
437 info() << "nb_elements=" << number_of_elements;
438
439 //elm-number elm-type number-of-tags < tag > ... node-number-list
440 // Reading mesh and connectivity info
441 // bool to check if we start from 0 or 1
442 bool it_starts_at_zero = false;
443 for (Integer i = 0; i < number_of_elements; ++i) {
444 [[maybe_unused]] Integer elm_number = ios_file.getInteger(); // Index
445 Integer elm_type = ios_file.getInteger(); // Type
446 // info() << elm_number << " " << elm_type;
447 // Now get tags in the case the number of nodes is encoded
448 Integer number_of_tags = ios_file.getInteger();
449 Integer lastTag = 0;
450 for (Integer j = 0; j < number_of_tags; ++j)
451 lastTag = ios_file.getInteger();
452 Integer number_of_nodes = 0; // Set the number of nodes from the discovered type
453 if (elm_type == IT_NullType) {
454 number_of_nodes = lastTag;
455 info() << "We hit the case the number of nodes is encoded (number_of_nodes=" << number_of_nodes << ")";
456 }
457 Integer cell_type = _switchMshType(elm_type, number_of_nodes);
458 //#warning Skipping 2D lines & points
459 // We skip 2-node lines and 1-node points
460 if (number_of_nodes < 3) {
461 for (Integer j = 0; j < number_of_nodes; ++j)
462 ios_file.getInteger();
463 continue;
464 }
465
466 mesh_info.cells_type.add(cell_type);
467 mesh_info.cells_nb_node.add(number_of_nodes);
468 mesh_info.cells_uid.add(i);
469 info() << elm_number << " " << elm_type << " " << number_of_tags << " number_of_nodes=" << number_of_nodes;
470 // printf("%i %i %i %i %i (", elm_number, elm_type, reg_phys, reg_elem, number_of_nodes);
471 for (Integer j = 0; j < number_of_nodes; ++j) {
472 // printf("%i ", node_number);
473 Integer id = ios_file.getInteger();
474 if (id == 0)
475 it_starts_at_zero = true;
476 mesh_info.cells_connectivity.add(id);
477 }
478 // printf(")\n");
479 }
480 if (!it_starts_at_zero)
481 for (Integer j = 0, max = mesh_info.cells_connectivity.size(); j < max; ++j)
482 mesh_info.cells_connectivity[j] = mesh_info.cells_connectivity[j] - 1;
483
484 ios_file.getNextLine(); // Skip current \n\r
485
486 // Only 3D meshes are supported in this old format
487 return 3;
488}
489
490/*---------------------------------------------------------------------------*/
491/*---------------------------------------------------------------------------*/
492
512{
513 Integer nb_block = ios_file.getInteger();
514
515 Integer number_of_elements = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
516 Integer min_element_tag = ios_file.getInteger();
517 Integer max_element_tag = ios_file.getInteger();
518 ios_file.getNextLine(); // Skip current \n\r
519 info() << "[Elements] nb_block=" << nb_block
520 << " nb_elements=" << number_of_elements
521 << " min_element_tag=" << min_element_tag
522 << " max_element_tag=" << max_element_tag;
523
524 if (number_of_elements < 0)
525 ARCANE_THROW(IOException, "Invalid number of elements: {0}", number_of_elements);
526
527 UniqueArray<MeshV4ElementsBlock>& blocks = mesh_info.blocks;
528 blocks.resize(nb_block);
529
530 {
531 // Number the blocks (for debugging)
532 Integer index = 0;
533 for (MeshV4ElementsBlock& block : blocks) {
534 block.index = index;
535 ++index;
536 }
537 }
538 for (MeshV4ElementsBlock& block : blocks) {
539 Integer entity_dim = ios_file.getInteger();
540 Integer entity_tag = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
541 Integer entity_type = ios_file.getInteger();
542 Integer nb_entity_in_block = ios_file.getInteger();
543
544 Integer item_nb_node = 0;
545 Integer item_type = _switchMshType(entity_type, item_nb_node);
546
547 info(4) << "[Elements] index=" << block.index << " entity_dim=" << entity_dim
548 << " entity_tag=" << entity_tag
549 << " entity_type=" << entity_type << " nb_in_block=" << nb_entity_in_block
550 << " item_type=" << item_type << " item_nb_node=" << item_nb_node;
551
552 block.nb_entity = nb_entity_in_block;
553 block.item_type = item_type;
554 block.item_nb_node = item_nb_node;
555 block.dimension = entity_dim;
556 block.entity_tag = entity_tag;
557
558 if (entity_type == MSH_PNT) {
559 // If the type is a point, the processing seems
560 // a bit particular. In this case, there are
561 // two integers in the next line:
562 // - an integer that doesn't seem
563 // - the unique node number we are interested in
564 [[maybe_unused]] Int64 unused_id = ios_file.getInt64();
565 Int64 item_unique_id = ios_file.getInt64();
566 info(4) << "Adding unique node uid=" << item_unique_id;
567 block.uids.add(item_unique_id);
568 }
569 else {
570 for (Integer i = 0; i < nb_entity_in_block; ++i) {
571 Int64 item_unique_id = ios_file.getInt64();
572 block.uids.add(item_unique_id);
573 for (Integer j = 0; j < item_nb_node; ++j)
574 block.connectivity.add(ios_file.getInt64());
575 }
576 }
577 ios_file.getNextLine(); // Skip current \n\r
578 }
579 // Now that we have all the blocks, the mesh dimension is
580 // the largest dimension of the blocks
581 Integer mesh_dimension = -1;
582 for (MeshV4ElementsBlock& block : blocks)
583 mesh_dimension = math::max(mesh_dimension, block.dimension);
584 if (mesh_dimension < 0)
585 ARCANE_FATAL("Invalid computed mesh dimension '{0}'", mesh_dimension);
586 if (mesh_dimension != 2 && mesh_dimension != 3)
587 ARCANE_THROW(NotSupportedException, "mesh dimension '{0}'. Only 2D or 3D meshes are supported", mesh_dimension);
588 info() << "Computed mesh dimension = " << mesh_dimension;
589
590 // We only keep blocks of our dimension
591 // to create the cells
592 for (MeshV4ElementsBlock& block : blocks) {
593 if (block.dimension != mesh_dimension)
594 continue;
595
596 info(4) << "Keeping block index=" << block.index;
597
598 Integer item_type = block.item_type;
599 Integer item_nb_node = block.item_nb_node;
600
601 for (Integer i = 0; i < block.nb_entity; ++i) {
602 mesh_info.cells_type.add(item_type);
603 mesh_info.cells_nb_node.add(item_nb_node);
604 mesh_info.cells_uid.add(block.uids[i]);
605 auto v = block.connectivity.subView(i * item_nb_node, item_nb_node);
606 mesh_info.cells_connectivity.addRange(v);
607 }
608 }
609
610 return mesh_dimension;
611}
612
613/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615/*
616 * nodes-binary is the list of nodes in binary form, i.e., a array of
617 * number-of-nodes *(4+3*data-size) bytes. For each node, the first 4 bytes
618 * contain the node number and the next (3*data-size) bytes contain the three
619 * floating point coordinates.
620 */
621IMeshReader::eReturnType MshMeshReader::
622_readNodesFromBinaryMshFile(IosFile& ios_file, Array<Real3>& node_coords)
623{
624 ARCANE_UNUSED(ios_file);
625 ARCANE_UNUSED(node_coords);
627}
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
631
632void MshMeshReader::
633_allocateCells(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items)
634{
635 Integer nb_elements = mesh_info.cells_type.size();
636 info() << "nb_of_elements=cells_type.size()=" << nb_elements;
637 Integer nb_cell_node = mesh_info.cells_connectivity.size();
638 info() << "nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
639
640 // Creating the cells
641 info() << "Building cells, nb_cell=" << nb_elements << " nb_cell_node=" << nb_cell_node;
642 // Info for cell creation
643 // per cell: 1 for its unique id,
644 // 1 for its type,
645 // 1 for each node
646 UniqueArray<Int64> cells_infos;
647 Integer connectivity_index = 0;
648 UniqueArray<Real3> local_coords;
649 for (Integer i = 0; i < nb_elements; ++i) {
650 Integer current_cell_nb_node = mesh_info.cells_nb_node[i];
651 Integer cell_type = mesh_info.cells_type[i];
652 Int64 cell_uid = mesh_info.cells_uid[i];
653 cells_infos.add(cell_type);
654 cells_infos.add(cell_uid); //cell_unique_id
655
656 ArrayView<Int64> local_info(current_cell_nb_node, &mesh_info.cells_connectivity[connectivity_index]);
657 cells_infos.addRange(local_info);
658 connectivity_index += current_cell_nb_node;
659 }
660
661 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
662 info() << "## Allocating ##";
663
664 if (is_read_items)
665 pmesh->allocateCells(nb_elements, cells_infos, false);
666 else
667 pmesh->allocateCells(0, UniqueArray<Int64>(0), false);
668
669 info() << "## Ending ##";
670 pmesh->endAllocate();
671 info() << "## Done ##";
672
673 // Positioning the coordinates
674 {
675 VariableNodeReal3& nodes_coord_var(pmesh->nodesCoordinates());
676 bool has_map = mesh_info.node_coords.empty();
677 if (has_map) {
678 ENUMERATE_NODE (i, mesh->ownNodes()) {
679 Node node = *i;
680 nodes_coord_var[node] = mesh_info.node_coords_map.lookupValue(node.uniqueId().asInt64());
681 }
682 nodes_coord_var.synchronize();
683 }
684 else {
685 ENUMERATE_NODE (node, mesh->allNodes()) {
686 nodes_coord_var[node] = mesh_info.node_coords.item(node->uniqueId().asInt32());
687 }
688 }
689 }
690}
691
692/*---------------------------------------------------------------------------*/
693/*---------------------------------------------------------------------------*/
694
695void MshMeshReader::
696_allocateGroups(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items)
697{
698 Int32 mesh_dim = mesh->dimension();
699 Int32 face_dim = mesh_dim - 1;
700 for (MeshV4ElementsBlock& block : mesh_info.blocks) {
701 Int32 block_index = block.index;
702 Int32 block_dim = block.dimension;
703 // Allocate a group if it has an associated physical name.
704 // For this, it must already be associated with an entity.
705 Int32 block_entity_tag = block.entity_tag;
706 if (block_entity_tag < 0) {
707 info(5) << "[Groups] Skipping block index=" << block_index << " because it has no entity";
708 continue;
709 }
710 MeshPhysicalName physical_name;
711 // For now, we do not process clouds
712 if (block_dim == 0) {
713 MeshV4EntitiesNodes* entity = mesh_info.findNodeEntities(block_entity_tag);
714 if (!entity) {
715 info(5) << "[Groups] Skipping block index=" << block_index
716 << " because entity tag is invalid";
717 continue;
718 }
719 Int32 entity_physical_tag = entity->physical_tag;
720 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
721 }
722 else {
723 MeshV4EntitiesWithNodes* entity = mesh_info.findEntities(block_dim, block_entity_tag);
724 if (!entity) {
725 info(5) << "[Groups] Skipping block index=" << block_index
726 << " because entity tag is invalid";
727 continue;
728 }
729 Int32 entity_physical_tag = entity->physical_tag;
730 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
731 }
732 if (physical_name.isNull()) {
733 info(5) << "[Groups] Skipping block index=" << block_index
734 << " because entity physical tag is invalid";
735 continue;
736 }
737 info(4) << "[Groups] Block index=" << block_index << " dim=" << block_dim
738 << " name='" << physical_name.name << "'";
739 if (block_dim == mesh_dim) {
740 if (is_read_items)
741 _addCellGroup(mesh, block, physical_name.name);
742 else
743 mesh->cellFamily()->findGroup(physical_name.name, true);
744 }
745 else if (block_dim == face_dim) {
746 if (is_read_items)
747 _addFaceGroup(mesh, block, physical_name.name);
748 else
749 mesh->faceFamily()->findGroup(physical_name.name, true);
750 }
751 else {
752 if (is_read_items)
753 _addNodeGroup(mesh, block, physical_name.name);
754 else
755 mesh->nodeFamily()->findGroup(physical_name.name, true);
756 }
757 }
758}
759
760/*---------------------------------------------------------------------------*/
761/*---------------------------------------------------------------------------*/
762
763void MshMeshReader::
764_addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
765{
766 const Int32 nb_entity = block.nb_entity;
767
768 // There may be several blocks for the same group.
769 // We retrieve the group if it already exists.
770 FaceGroup face_group = mesh->faceFamily()->findGroup(group_name, true);
771
772 UniqueArray<Int32> faces_id(nb_entity); // Face number in the mesh \a mesh
773
774 const Int32 item_nb_node = block.item_nb_node;
775 const Int32 face_nb_node = nb_entity * item_nb_node;
776
777 UniqueArray<Int64> faces_first_node_unique_id(nb_entity);
778 UniqueArray<Int32> faces_first_node_local_id(nb_entity);
779 UniqueArray<Int64> faces_nodes_unique_id(face_nb_node);
780 Integer faces_nodes_unique_id_index = 0;
781
782 UniqueArray<Int64> orig_nodes_id(item_nb_node);
783 UniqueArray<Integer> face_nodes_index(item_nb_node);
784
785 IItemFamily* node_family = mesh->nodeFamily();
786 NodeInfoListView mesh_nodes(node_family);
787
788 // Reorder face IDs to conform to Arcane and find
789 // the face in the mesh
790 for (Integer i_face = 0; i_face < nb_entity; ++i_face) {
791 for (Integer z = 0; z < item_nb_node; ++z)
792 orig_nodes_id[z] = block.connectivity[faces_nodes_unique_id_index + z];
793
794 mesh_utils::reorderNodesOfFace2(orig_nodes_id, face_nodes_index);
795 for (Integer z = 0; z < item_nb_node; ++z)
796 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = orig_nodes_id[face_nodes_index[z]];
797 faces_first_node_unique_id[i_face] = orig_nodes_id[face_nodes_index[0]];
798 faces_nodes_unique_id_index += item_nb_node;
799 }
800
801 node_family->itemsUniqueIdToLocalId(faces_first_node_local_id, faces_first_node_unique_id);
802
803 faces_nodes_unique_id_index = 0;
804 for (Integer i_face = 0; i_face < nb_entity; ++i_face) {
805 const Integer n = item_nb_node;
806 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
807 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
808 Face face = mesh_utils::getFaceFromNodesUnique(current_node, face_nodes_id);
809
810 if (face.null()) {
811 OStringStream ostr;
812 ostr() << "(Nodes:";
813 for (Integer z = 0; z < n; ++z)
814 ostr() << ' ' << face_nodes_id[z];
815 ostr() << " - " << current_node.localId() << ")";
816 ARCANE_FATAL("INTERNAL: MeshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity",
817 i_face, ostr.str());
818 }
819 faces_id[i_face] = face.localId();
820
821 faces_nodes_unique_id_index += n;
822 }
823 info(4) << "Adding " << faces_id.size() << " faces from block index=" << block.index
824 << " to group '" << face_group.name() << "'";
825 face_group.addItems(faces_id);
826}
827
828/*---------------------------------------------------------------------------*/
829/*---------------------------------------------------------------------------*/
830
831void MshMeshReader::
832_addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
833{
834 const Int32 nb_entity = block.nb_entity;
835
836 // There may be several blocks for the same group.
837 // We retrieve the group if it already exists.
838 IItemFamily* cell_family = mesh->cellFamily();
839 CellGroup cell_group = cell_family->findGroup(group_name, true);
840
841 UniqueArray<Int32> cells_id(nb_entity); // Cell number in the mesh \a mesh
842
843 cell_family->itemsUniqueIdToLocalId(cells_id, block.uids);
844
845 info(4) << "Adding " << cells_id.size() << " cells from block index=" << block.index
846 << " to group '" << cell_group.name() << "'";
847 cell_group.addItems(cells_id);
848}
849
850/*---------------------------------------------------------------------------*/
851/*---------------------------------------------------------------------------*/
852
853void MshMeshReader::
854_addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
855{
856 const Int32 nb_entity = block.nb_entity;
857
858 // There may be several blocks for the same group.
859 // We retrieve the group if it already exists.
860 IItemFamily* node_family = mesh->nodeFamily();
861 NodeGroup node_group = node_family->findGroup(group_name, true);
862
863 UniqueArray<Int32> nodes_id(nb_entity);
864
865 node_family->itemsUniqueIdToLocalId(nodes_id, block.uids);
866
867 info(4) << "Adding " << nodes_id.size() << " nodes from block index=" << block.index
868 << " to group '" << node_group.name() << "'";
869
870 if (nb_entity < 10) {
871 info(4) << "Nodes UIDS=" << block.uids;
872 info(4) << "Nodes LIDS=" << nodes_id;
873 }
874 node_group.addItems(nodes_id);
875
876 if (nb_entity < 10) {
877 VariableNodeReal3& coords(mesh->nodesCoordinates());
878 ENUMERATE_ (Node, inode, node_group) {
879 info(4) << "Node id=" << ItemPrinter(*inode) << " coord=" << coords[inode];
880 }
881 }
882}
883
884/*---------------------------------------------------------------------------*/
885/*---------------------------------------------------------------------------*/
886/*
887 * $PhysicalNames // same as MSH version 2
888 * numPhysicalNames(ASCII int)
889 * dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
890 * ...
891 * $EndPhysicalNames
892 */
893void MshMeshReader::
894_readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info)
895{
896 String quote_mark = "\"";
897 Int32 nb_name = ios_file.getInteger();
898 info() << "nb_physical_name=" << nb_name;
899 ios_file.getNextLine();
900 for (Int32 i = 0; i < nb_name; ++i) {
901 Int32 dim = ios_file.getInteger();
902 Int32 tag = ios_file.getInteger();
903 String s = ios_file.getNextLine();
904 if (dim < 0 || dim > 3)
905 ARCANE_FATAL("Invalid value for physical name dimension dim={0}", dim);
906 // Group names may start with spaces and contain quotes that must be removed.
908 if (s.startsWith(quote_mark))
909 s = s.substring(1);
910 if (s.endsWith(quote_mark))
911 s = s.substring(0, s.length() - 1);
912 mesh_info.physical_name_list.add(dim, tag, s);
913 info(4) << "[PhysicalName] index=" << i << " dim=" << dim << " tag=" << tag << " name='" << s << "'";
914 }
915 StringView s = ios_file.getNextLine();
916 if (s != "$EndPhysicalNames")
917 ARCANE_FATAL("found '{0}' and expected '$EndPhysicalNames'", s);
918}
919
920/*---------------------------------------------------------------------------*/
921/*---------------------------------------------------------------------------*/
922
954_readEntitiesV4(IosFile& ios_file, MeshInfo& mesh_info)
955{
956 Int32 nb_dim_item[4];
957 nb_dim_item[0] = ios_file.getInteger();
958 nb_dim_item[1] = ios_file.getInteger();
959 nb_dim_item[2] = ios_file.getInteger();
960 nb_dim_item[3] = ios_file.getInteger();
961 info(4) << "[Entities] nb_0d=" << nb_dim_item[0] << " nb_1d=" << nb_dim_item[1]
962 << " nb_2d=" << nb_dim_item[2] << " nb_3d=" << nb_dim_item[3];
963 // After the format, entities may be present, but this is optional.
964 // If they are present, we read the file until the end of this section.
965 StringView next_line = ios_file.getNextLine();
966 for (Int32 i = 0; i < nb_dim_item[0]; ++i) {
967 Int32 tag = ios_file.getInteger();
968 Real x = ios_file.getReal();
969 Real y = ios_file.getReal();
970 Real z = ios_file.getReal();
971 Int32 num_physical_tag = ios_file.getInteger();
972 if (num_physical_tag > 1)
973 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
974 Int32 physical_tag = -1;
975 if (num_physical_tag == 1)
976 physical_tag = ios_file.getInteger();
977 info(4) << "[Entities] point tag=" << tag << " x=" << x << " y=" << y << " z=" << z << " phys_tag=" << physical_tag;
978 mesh_info.entities_nodes_list.add(MeshV4EntitiesNodes(tag, physical_tag));
979 next_line = ios_file.getNextLine();
980 }
981
982 for (Int32 dim = 1; dim <= 3; ++dim) {
983 for (Int32 i = 0; i < nb_dim_item[dim]; ++i) {
984 Int32 tag = ios_file.getInteger();
985 Real min_x = ios_file.getReal();
986 Real min_y = ios_file.getReal();
987 Real min_z = ios_file.getReal();
988 Real max_x = ios_file.getReal();
989 Real max_y = ios_file.getReal();
990 Real max_z = ios_file.getReal();
991 Int32 num_physical_tag = ios_file.getInteger();
992 if (num_physical_tag > 1)
993 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
994 Int32 physical_tag = -1;
995 if (num_physical_tag == 1)
996 physical_tag = ios_file.getInteger();
997 Int32 num_bounding_group = ios_file.getInteger();
998 for (Int32 k = 0; k < num_bounding_group; ++k) {
999 [[maybe_unused]] Int32 group_tag = ios_file.getInteger();
1000 }
1001 mesh_info.entities_with_nodes_list[dim - 1].add(MeshV4EntitiesWithNodes(dim, tag, physical_tag));
1002 info(4) << "[Entities] dim=" << dim << " tag=" << tag
1003 << " min_x=" << min_x << " min_y=" << min_y << " min_z=" << min_z
1004 << " max_x=" << max_x << " max_y=" << max_y << " max_z=" << max_z
1005 << " phys_tag=" << physical_tag;
1006 next_line = ios_file.getNextLine();
1007 }
1008 }
1009 StringView s = ios_file.getNextLine();
1010 if (s != "$EndEntities")
1011 ARCANE_FATAL("found '{0}' and expected '$EndEntities'", s);
1012}
1013
1014/*---------------------------------------------------------------------------*/
1015/*---------------------------------------------------------------------------*/
1049{
1050 const char* func_name = "MshMeshReader::_readMeshFromNewMshFile()";
1051 info() << "[_readMeshFromNewMshFile] New native mesh file format detected";
1052 MeshInfo mesh_info;
1053#define MSH_BINARY_TYPE 1
1054
1055 Real version = ios_file.getReal();
1056 if (version == 2.0)
1057 m_version = 2;
1058 else if (version == 4.1)
1059 m_version = 4;
1060 else
1061 ARCANE_THROW(IOException, "Wrong msh file version '{0}'. Only versions '2.0' or '4.1' are supported", version);
1062 info() << "Msh mesh_major_version=" << m_version;
1063 Integer file_type = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
1064 if (file_type == MSH_BINARY_TYPE)
1065 ARCANE_THROW(IOException, "Binary mode is not supported!");
1066
1067 Integer data_size = ios_file.getInteger(); // is an integer equal to the size of the floating point numbers used in the file
1068 ARCANE_UNUSED(data_size);
1069
1070 if (file_type == MSH_BINARY_TYPE) {
1071 (void)ios_file.getInteger(); // is an integer of value 1 written in binary form
1072 }
1073 ios_file.getNextLine(); // Skip current \n\r
1074
1075 // $EndMeshFormat
1076 if (!ios_file.lookForString("$EndMeshFormat"))
1077 ARCANE_THROW(IOException, "$EndMeshFormat not found");
1078
1079 // TODO: The different sections ($Nodes, $Entities, ...) can
1080 // be in any order (except $Nodes which must be before $Elements)
1081 // Implement a method that handles this.
1082
1083 StringView next_line = ios_file.getNextLine();
1084 // Group names
1085 if (next_line == "$PhysicalNames") {
1086 _readPhysicalNames(ios_file, mesh_info);
1087 next_line = ios_file.getNextLine();
1088 }
1089 // After the format, entities may be present, but this is optional.
1090 // If they are present, we read the file until the end of this section.
1091 if (next_line == "$Entities") {
1092 _readEntitiesV4(ios_file, mesh_info);
1093 next_line = ios_file.getNextLine();
1094 }
1095 // $Nodes
1096 if (next_line != "$Nodes")
1097 ARCANE_THROW(IOException, "Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1098
1099 // Fetch nodes number and the coordinates
1100 if (file_type != MSH_BINARY_TYPE) {
1101 if (m_version == 2) {
1102 if (_readNodesFromAsciiMshV2File(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1103 ARCANE_THROW(IOException, "Ascii nodes coords error");
1104 }
1105 else if (m_version == 4) {
1106 if (_readNodesFromAsciiMshV4File(ios_file, mesh_info) != IMeshReader::RTOk)
1107 ARCANE_THROW(IOException, "Ascii nodes coords error");
1108 }
1109 }
1110 else {
1111 if (_readNodesFromBinaryMshFile(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1112 ARCANE_THROW(IOException, "Binary nodes coords error");
1113 }
1114 // $EndNodes
1115 if (!ios_file.lookForString("$EndNodes"))
1116 ARCANE_THROW(IOException, "$EndNodes not found");
1117
1118 // $Elements
1119 Integer mesh_dimension = -1;
1120 {
1121 if (!ios_file.lookForString("$Elements"))
1122 ARCANE_THROW(IOException, "$Elements not found");
1123
1124 if (m_version == 2)
1125 mesh_dimension = _readElementsFromAsciiMshV2File(ios_file, mesh_info);
1126 else if (m_version == 4)
1127 mesh_dimension = _readElementsFromAsciiMshV4File(ios_file, mesh_info);
1128
1129 // $EndElements
1130 if (!ios_file.lookForString("$EndElements"))
1131 throw IOException(func_name, "$EndElements not found");
1132 }
1133
1134 info() << "Computed mesh dimension = " << mesh_dimension;
1135
1136 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
1137 pmesh->setDimension(mesh_dimension);
1138
1139 IParallelMng* pm = mesh->parallelMng();
1140 bool is_parallel = pm->isParallel();
1141 Int32 rank = mesh->meshPartInfo().partRank();
1142 // In parallel, only rank 0 reads the mesh
1143 bool is_read_items = !(is_parallel && rank != 0);
1144 _allocateCells(mesh, mesh_info, is_read_items);
1145 _allocateGroups(mesh, mesh_info, is_read_items);
1146 return IMeshReader::RTOk;
1147}
1148
1149/*---------------------------------------------------------------------------*/
1150/*---------------------------------------------------------------------------*/
1156readMeshFromMshFile(IMesh* mesh, const String& filename, bool use_internal_partition)
1157{
1158 info() << "Trying to read 'msh' file '" << filename << "'"
1159 << " use_internal_partition=" << use_internal_partition;
1160
1161 std::ifstream ifile(filename.localstr());
1162 if (!ifile) {
1163 error() << "Unable to read file '" << filename << "'";
1164 return IMeshReader::RTError;
1165 }
1166 IosFile ios_file(&ifile);
1167 String mesh_format_str = ios_file.getNextLine(); // Comments do not seem to be implemented in .msh files
1168 if (IosFile::isEqualString(mesh_format_str, "$MeshFormat"))
1169 return _readMeshFromNewMshFile(mesh, ios_file);
1170 info() << "The file does not begin with '$MeshFormat' returning RTError";
1171 return IMeshReader::RTError;
1172}
1173
1174/*---------------------------------------------------------------------------*/
1175/*---------------------------------------------------------------------------*/
1176
1177/*---------------------------------------------------------------------------*/
1178/*---------------------------------------------------------------------------*/
1179
1180extern "C++" Ref<IMshMeshReader>
1181createMshParallelMeshReader(ITraceMng* tm);
1182
1183namespace
1184{
1185
1187 _internalCreateReader(ITraceMng* tm)
1188 {
1189 bool use_new_reader = true;
1190 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_PARALLEL_MSH_READER", true))
1191 use_new_reader = (v.value() != 0);
1192 Ref<IMshMeshReader> reader;
1193 if (use_new_reader)
1194 reader = createMshParallelMeshReader(tm);
1195 else
1196 reader = createMshMeshReader(tm);
1197 return reader;
1198 }
1199
1200} // namespace
1201
1202/*---------------------------------------------------------------------------*/
1203/*---------------------------------------------------------------------------*/
1204
1205class MshMeshReaderService
1206: public AbstractService
1207, public IMeshReader
1208{
1209 public:
1210
1211 explicit MshMeshReaderService(const ServiceBuildInfo& sbi)
1212 : AbstractService(sbi)
1213 {
1214 }
1215
1216 public:
1217
1218 void build() override {}
1219
1220 bool allowExtension(const String& str) override { return str == "msh"; }
1221
1223 const String& file_name, const String& dir_name,
1224 bool use_internal_partition) override
1225 {
1226 ARCANE_UNUSED(dir_name);
1227 ARCANE_UNUSED(mesh_node);
1228
1229 Ref<IMshMeshReader> reader = _internalCreateReader(traceMng());
1230 return reader->readMeshFromMshFile(mesh, file_name, use_internal_partition);
1231 }
1232};
1233
1234/*---------------------------------------------------------------------------*/
1235/*---------------------------------------------------------------------------*/
1236
1237// Obsolete. Use 'MshMeshReader' instead
1238ARCANE_REGISTER_SERVICE(MshMeshReaderService,
1239 ServiceProperty("MshNewMeshReader", ST_SubDomain),
1240 ARCANE_SERVICE_INTERFACE(IMeshReader));
1241
1242ARCANE_REGISTER_SERVICE(MshMeshReaderService,
1243 ServiceProperty("MshMeshReader", ST_SubDomain),
1244 ARCANE_SERVICE_INTERFACE(IMeshReader));
1245
1246/*---------------------------------------------------------------------------*/
1247/*---------------------------------------------------------------------------*/
1248
1249class MshCaseMeshReader
1250: public AbstractService
1251, public ICaseMeshReader
1252{
1253 public:
1254
1255 class Builder
1256 : public IMeshBuilder
1257 {
1258 public:
1259
1260 explicit Builder(ITraceMng* tm, const CaseMeshReaderReadInfo& read_info)
1261 : m_trace_mng(tm)
1262 , m_read_info(read_info)
1263 , m_use_internal_partition(read_info.isParallelRead())
1264 {}
1265
1266 public:
1267
1268 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1269 {
1270 ARCANE_UNUSED(build_info);
1271 }
1273 {
1274 Ref<IMshMeshReader> reader = _internalCreateReader(m_trace_mng);
1275 String fname = m_read_info.fileName();
1276 m_trace_mng->info() << "Msh Reader (ICaseMeshReader) file_name=" << fname;
1277 IMeshReader::eReturnType ret = reader->readMeshFromMshFile(pm, fname, m_use_internal_partition);
1278 if (ret != IMeshReader::RTOk)
1279 ARCANE_FATAL("Can not read MSH File");
1280 }
1281
1282 private:
1283
1284 ITraceMng* m_trace_mng;
1285 CaseMeshReaderReadInfo m_read_info;
1286 bool m_use_internal_partition = false;
1287 };
1288
1289 public:
1290
1291 explicit MshCaseMeshReader(const ServiceBuildInfo& sbi)
1292 : AbstractService(sbi)
1293 {}
1294
1295 public:
1296
1298 {
1299 IMeshBuilder* builder = nullptr;
1300 if (read_info.format() == "msh")
1301 builder = new Builder(traceMng(), read_info);
1302 return makeRef(builder);
1303 }
1304};
1305
1306/*---------------------------------------------------------------------------*/
1307/*---------------------------------------------------------------------------*/
1308
1309ARCANE_REGISTER_SERVICE(MshCaseMeshReader,
1310 ServiceProperty("MshCaseMeshReader", ST_SubDomain),
1311 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1312
1313/*---------------------------------------------------------------------------*/
1314/*---------------------------------------------------------------------------*/
1315
1316} // End namespace Arcane
1317
1318/*---------------------------------------------------------------------------*/
1319/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_(type, name, group)
Generic enumerator for an entity group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Base class of a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Base class for 1D data vectors.
void addRange(ConstReferenceType val, Int64 n)
Adds n elements of value val to the end of the array.
void resize(Int64 s)
Changes the number of elements in the array to s.
void add(ConstReferenceType val)
Adds element val to the end of the array.
Necessary information for reading a mesh file.
Template class for converting a type.
Hash table for associative arrays.
Interface for the mesh reading service from the dataset.
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
Exception when an input/output error is detected.
Definition IOException.h:34
Interface of the parallelism manager for a subdomain.
virtual bool isParallel() const =0
Returns true if the execution is parallel.
virtual void setDimension(Integer dim)=0
Positions the mesh dimension (1D, 2D, or 3D).
File Read/Write Routines.
Definition IosFile.h:33
Parameters necessary for building a mesh.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Fills build_info with the necessary information to create the mesh.
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
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_node, const String &file_name, const String &dir_name, bool use_internal_partition) override
Reads a mesh from a file.
eReturnType _readNodesFromAsciiMshV4File(IosFile &, MeshInfo &mesh_info)
eReturnType readMeshFromMshFile(IMesh *mesh, const String &file_name, bool use_internal_partition) override
void _readEntitiesV4(IosFile &ios_file, MeshInfo &mesh_info)
Reading of entities.
eReturnType _readMeshFromNewMshFile(IMesh *, IosFile &)
Integer _readElementsFromAsciiMshV4File(IosFile &, MeshInfo &mesh_info)
Reading elements (cells, faces, ...).
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Reference to an instance.
Structure containing the information to create a service.
View of a UTF-8 character string.
Definition StringView.h:44
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
static String collapseWhiteSpace(const String &rhs)
Performs whitespace character normalization.
Definition String.cc:454
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
T max(const T &a, const T &b, const T &c)
Returns the maximum of three elements.
Definition MathUtils.h:407
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
ItemGroupT< Face > FaceGroup
Group of faces.
Definition ItemTypes.h:179
ItemGroupT< Node > NodeGroup
Group of nodes.
Definition ItemTypes.h:168
#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.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:480
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.
Information about the '$PhysicalNames' block.
Information about a physical name.
Information about a block for $Elements for version 4.
Int32 nb_entity
Number of entities in the block.
Int32 dimension
Dimension of the entity.
Int32 item_nb_node
Number of nodes in the entity.
Int32 index
Block index in the list.
Integer item_type
Arcane type of the entity.
Info for 1D, 2D, and 3D entities.