Arcane  v3.16.0.0
Documentation développeur
Tout Classes Espaces de nommage Fichiers Fonctions Variables Définitions de type Énumérations Valeurs énumérées Amis Macros Groupes Pages Concepts
MshMeshReader.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* Lecture/Ecriture d'un fichier au format MSH. */
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: A partir de juillet 2024 (version 3.13.8), on utilise par défaut
50// la version parallèle du lecteur (MshParallelMshReader.cc). Cette version
51// sera à terme supprimée.
52
53/*
54 * NOTES:
55 * - La bibliothèque `gmsh` fournit un script 'open.py' dans le répertoire
56 * 'demos/api' qui permet de générer un fichier '.msh' à partir d'un '.geo'.
57 * - Il est aussi possible d'utiliser directement l'exécutable 'gmsh' avec
58 * l'option '-save-all' pour sauver un fichier '.msh' à partir d'un '.geo'
59 *
60 * TODO:
61 * - lire les tags des noeuds(uniqueId())
62 * - supporter les partitions
63 * - pouvoir utiliser la bibliothèque 'gmsh' directement.
64 * - améliorer la lecture parallèle en évitant que tous les sous-domaines
65 * lisent le fichier (même si seul le sous-domaine 0 alloue les entités)
66 */
67
68/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
70
71namespace Arcane
72{
73
74/*---------------------------------------------------------------------------*/
75/*---------------------------------------------------------------------------*/
90class MshMeshReader
91: public TraceAccessor
92, public IMshMeshReader
93{
94 public:
95
96 using eReturnType = typename IMeshReader::eReturnType;
97
105 {
111 Int32 entity_tag = -1;
113 UniqueArray<Int64> connectivity;
114 };
115
120 struct MeshPhysicalName
121 {
122 MeshPhysicalName(Int32 _dimension, Int32 _tag, const String& _name)
123 : dimension(_dimension)
124 , tag(_tag)
125 , name(_name)
126 {}
127 MeshPhysicalName() = default;
128 bool isNull() const { return dimension == (-1); }
129 Int32 dimension = -1;
130 Int32 tag = -1;
131 String name;
132 };
133
137 struct MeshPhysicalNameList
138 {
139 MeshPhysicalNameList()
140 : m_physical_names(4)
141 {}
142 void add(Int32 dimension, Int32 tag, String name)
143 {
144 m_physical_names[dimension].add(MeshPhysicalName{ dimension, tag, name });
145 }
146 MeshPhysicalName find(Int32 dimension, Int32 tag) const
147 {
148 for (auto& x : m_physical_names[dimension])
149 if (x.tag == tag)
150 return x;
151 return {};
152 }
153
154 private:
155
157 };
158
160 struct MeshV4EntitiesNodes
161 {
162 MeshV4EntitiesNodes(Int32 _tag, Int32 _physical_tag)
163 : tag(_tag)
164 , physical_tag(_physical_tag)
165 {}
166 Int32 tag;
167 Int32 physical_tag;
168 };
169
171 struct MeshV4EntitiesWithNodes
172 {
173 MeshV4EntitiesWithNodes(Int32 _dim, Int32 _tag, Int32 _physical_tag)
174 : dimension(_dim)
175 , tag(_tag)
176 , physical_tag(_physical_tag)
177 {}
178 Int32 dimension;
179 Int32 tag;
180 Int32 physical_tag;
181 };
182
183 struct MeshInfo
184 {
185 public:
186
187 MeshInfo()
188 : node_coords_map(5000, true)
189 {}
190
191 public:
192
193 MeshV4EntitiesWithNodes* findEntities(Int32 dimension, Int32 tag)
194 {
195 for (auto& x : entities_with_nodes_list[dimension - 1])
196 if (x.tag == tag)
197 return &x;
198 return nullptr;
199 }
200
201 MeshV4EntitiesNodes* findNodeEntities(Int32 tag)
202 {
203 for (auto& x : entities_nodes_list)
204 if (x.tag == tag)
205 return &x;
206 return nullptr;
207 }
208
209 public:
210
211 Integer nb_elements = 0;
212 Integer nb_cell_node = 0;
213 UniqueArray<Int32> cells_nb_node;
214 UniqueArray<Int32> cells_type;
215 UniqueArray<Int64> cells_uid;
216 UniqueArray<Int64> cells_connectivity;
217 UniqueArray<Real3> node_coords;
218 HashTableMapT<Int64, Real3> node_coords_map;
219 MeshPhysicalNameList physical_name_list;
220 UniqueArray<MeshV4EntitiesNodes> entities_nodes_list;
221 UniqueArray<MeshV4EntitiesWithNodes> entities_with_nodes_list[3];
223 };
224
225 public:
226
227 explicit MshMeshReader(ITraceMng* tm)
228 : TraceAccessor(tm)
229 {}
230
231 eReturnType readMeshFromMshFile(IMesh* mesh, const String& file_name, bool use_internal_partition) override;
232
233 private:
234
235 Integer m_version = 0;
236
237 eReturnType _readNodesFromAsciiMshV2File(IosFile&, Array<Real3>&);
238 eReturnType _readNodesFromAsciiMshV4File(IosFile&, MeshInfo& mesh_info);
239 eReturnType _readNodesFromBinaryMshFile(IosFile&, Array<Real3>&);
240 Integer _readElementsFromAsciiMshV2File(IosFile&, MeshInfo& mesh_info);
241 Integer _readElementsFromAsciiMshV4File(IosFile&, MeshInfo& mesh_info);
242 eReturnType _readMeshFromNewMshFile(IMesh*, IosFile&);
243 void _allocateCells(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
244 void _allocateGroups(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
245 void _addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
246 void _addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
247 void _addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
248 Integer _switchMshType(Integer, Integer&);
249 void _readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info);
250 void _readEntitiesV4(IosFile& ios_file, MeshInfo& mesh_info);
251};
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
256extern "C++" Ref<IMshMeshReader>
257createMshMeshReader(ITraceMng* tm)
258{
259 return makeRef<IMshMeshReader>(new MshMeshReader(tm));
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265Integer MshMeshReader::
266_switchMshType(Integer mshElemType, Integer& nNodes)
267{
268 switch (mshElemType) {
269 case (IT_NullType): // used to decode IT_NullType: IT_HemiHexa7|IT_Line9
270 switch (nNodes) {
271 case (7):
272 return IT_HemiHexa7;
273 default:
274 info() << "Could not decode IT_NullType with nNodes=" << nNodes;
275 throw IOException("_switchMshType", "Could not decode IT_NullType with nNodes");
276 }
277 break;
278 case (MSH_PNT):
279 nNodes = 1;
280 return IT_Vertex; //printf("1-node point");
281 case (MSH_LIN_2):
282 nNodes = 2;
283 return IT_Line2; //printf("2-node line");
284 case (MSH_TRI_3):
285 nNodes = 3;
286 return IT_Triangle3; //printf("3-node triangle");
287 case (MSH_QUA_4):
288 nNodes = 4;
289 return IT_Quad4; //printf("4-node quadrangle");
290 case (MSH_TET_4):
291 nNodes = 4;
292 return IT_Tetraedron4; //printf("4-node tetrahedron");
293 case (MSH_HEX_8):
294 nNodes = 8;
295 return IT_Hexaedron8; //printf("8-node hexahedron");
296 case (MSH_PRI_6):
297 nNodes = 6;
298 return IT_Pentaedron6; //printf("6-node prism");
299 case (MSH_PYR_5):
300 nNodes = 5;
301 return IT_Pyramid5; //printf("5-node pyramid");
302 case (MSH_TRI_10):
303 nNodes = 10;
304 return IT_Heptaedron10; //printf("10-node second order tetrahedron")
305 case (MSH_TRI_12):
306 nNodes = 12;
307 return IT_Octaedron12; //printf("Unknown MSH_TRI_12");
308
309 case (MSH_TRI_6):
310 case (MSH_QUA_9):
311 case (MSH_HEX_27):
312 case (MSH_PRI_18):
313 case (MSH_PYR_14):
314 case (MSH_QUA_8):
315 case (MSH_HEX_20):
316 case (MSH_PRI_15):
317 case (MSH_PYR_13):
318 case (MSH_TRI_9):
319 case (MSH_TRI_15):
320 case (MSH_TRI_15I):
321 case (MSH_TRI_21):
322 default:
323 ARCANE_THROW(NotSupportedException, "Unknown GMSH element type '{0}'", mshElemType);
324 }
325 return IT_NullType;
326}
327
328/*---------------------------------------------------------------------------*/
329/*---------------------------------------------------------------------------*/
330
331IMeshReader::eReturnType MshMeshReader::
332_readNodesFromAsciiMshV2File(IosFile& ios_file, Array<Real3>& node_coords)
333{
334 // number-of-nodes & coords
335 info() << "[_readNodesFromAsciiMshV2File] Looking for number-of-nodes";
336 Integer nb_node = ios_file.getInteger();
337 if (nb_node < 0)
338 throw IOException(A_FUNCINFO, String("Invalid number of nodes: n=") + nb_node);
339 info() << "[_readNodesFromAsciiMshV2File] nb_node=" << nb_node;
340 for (Integer i = 0; i < nb_node; ++i) {
341 // Il faut lire l'id même si on ne s'en sert pas.
342 [[maybe_unused]] Int32 id = ios_file.getInteger();
343 Real nx = ios_file.getReal();
344 Real ny = ios_file.getReal();
345 Real nz = ios_file.getReal();
346 node_coords.add(Real3(nx, ny, nz));
347 //info() << "id_" << id << " xyz(" << nx << "," << ny << "," << nz << ")";
348 }
349 ios_file.getNextLine(); // Skip current \n\r
350 return IMeshReader::RTOk;
351}
352
353/*---------------------------------------------------------------------------*/
354/*---------------------------------------------------------------------------*/
375_readNodesFromAsciiMshV4File(IosFile& ios_file, MeshInfo& mesh_info)
376{
377 // Première ligne du fichier
378 Integer nb_entity = ios_file.getInteger();
379 Integer total_nb_node = ios_file.getInteger();
380 Integer min_node_tag = ios_file.getInteger();
381 Integer max_node_tag = ios_file.getInteger();
382 ios_file.getNextLine(); // Skip current \n\r
383 if (total_nb_node < 0)
384 ARCANE_THROW(IOException, "Invalid number of nodes : '{0}'", total_nb_node);
385 info() << "[Nodes] nb_entity=" << nb_entity
386 << " total_nb_node=" << total_nb_node
387 << " min_tag=" << min_node_tag
388 << " max_tag=" << max_node_tag;
389
390 UniqueArray<Int32> nodes_uids;
391 for (Integer i_entity = 0; i_entity < nb_entity; ++i_entity) {
392 // Dimension de l'entité (pas utile)
393 [[maybe_unused]] Integer entity_dim = ios_file.getInteger();
394 // Tag de l'entité (pas utile)
395 [[maybe_unused]] Integer entity_tag = ios_file.getInteger();
396 Integer parametric_coordinates = ios_file.getInteger();
397 Integer nb_node2 = ios_file.getInteger();
398 ios_file.getNextLine();
399
400 info(4) << "[Nodes] index=" << i_entity << " entity_dim=" << entity_dim << " entity_tag=" << entity_tag
401 << " parametric=" << parametric_coordinates
402 << " nb_node2=" << nb_node2;
403 if (parametric_coordinates != 0)
404 ARCANE_THROW(NotSupportedException, "Only 'parametric coordinates' value of '0' is supported (current={0})", parametric_coordinates);
405 // Il est possible que le nombre de noeuds soit 0.
406 // Dans ce cas, il faut directement passer à la ligne suivante
407 if (nb_node2 == 0)
408 continue;
409 nodes_uids.resize(nb_node2);
410 for (Integer i = 0; i < nb_node2; ++i) {
411 // Conserve le uniqueId() du noeuds.
412 nodes_uids[i] = ios_file.getInteger();
413 //info() << "I=" << i << " ID=" << nodes_uids[i];
414 }
415 for (Integer i = 0; i < nb_node2; ++i) {
416 Real nx = ios_file.getReal();
417 Real ny = ios_file.getReal();
418 Real nz = ios_file.getReal();
419 Real3 xyz(nx, ny, nz);
420 mesh_info.node_coords_map.add(nodes_uids[i], xyz);
421 //info() << "I=" << i << " ID=" << nodes_uids[i] << " COORD=" << xyz;
422 }
423 ios_file.getNextLine(); // Skip current \n\r
424 }
425 return IMeshReader::RTOk;
426}
427
428/*---------------------------------------------------------------------------*/
429/*---------------------------------------------------------------------------*/
430
431Integer MshMeshReader::
432_readElementsFromAsciiMshV2File(IosFile& ios_file, MeshInfo& mesh_info)
433{
434 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
435 if (number_of_elements < 0)
436 ARCANE_THROW(IOException, String("Error with the number_of_elements=") + number_of_elements);
437
438 info() << "nb_elements=" << number_of_elements;
439
440 //elm-number elm-type number-of-tags < tag > ... node-number-list
441 // Lecture des infos des mailles & de la connectivité
442 // bool pour voir si on est depuis 0 ou 1
443 bool it_starts_at_zero = false;
444 for (Integer i = 0; i < number_of_elements; ++i) {
445 [[maybe_unused]] Integer elm_number = ios_file.getInteger(); // Index
446 Integer elm_type = ios_file.getInteger(); // Type
447 // info() << elm_number << " " << elm_type;
448 // Now get tags in the case the number of nodes is encoded
449 Integer number_of_tags = ios_file.getInteger();
450 Integer lastTag = 0;
451 for (Integer j = 0; j < number_of_tags; ++j)
452 lastTag = ios_file.getInteger();
453 Integer number_of_nodes = 0; // Set the number of nodes from the discovered type
454 if (elm_type == IT_NullType) {
455 number_of_nodes = lastTag;
456 info() << "We hit the case the number of nodes is encoded (number_of_nodes=" << number_of_nodes << ")";
457 }
458 Integer cell_type = _switchMshType(elm_type, number_of_nodes);
459 //#warning Skipping 2D lines & points
460 // We skip 2-node lines and 1-node points
461 if (number_of_nodes < 3) {
462 for (Integer j = 0; j < number_of_nodes; ++j)
463 ios_file.getInteger();
464 continue;
465 }
466
467 mesh_info.cells_type.add(cell_type);
468 mesh_info.cells_nb_node.add(number_of_nodes);
469 mesh_info.cells_uid.add(i);
470 info() << elm_number << " " << elm_type << " " << number_of_tags << " number_of_nodes=" << number_of_nodes;
471 // printf("%i %i %i %i %i (", elm_number, elm_type, reg_phys, reg_elem, number_of_nodes);
472 for (Integer j = 0; j < number_of_nodes; ++j) {
473 // printf("%i ", node_number);
474 Integer id = ios_file.getInteger();
475 if (id == 0)
476 it_starts_at_zero = true;
477 mesh_info.cells_connectivity.add(id);
478 }
479 // printf(")\n");
480 }
481 if (!it_starts_at_zero)
482 for (Integer j = 0, max = mesh_info.cells_connectivity.size(); j < max; ++j)
483 mesh_info.cells_connectivity[j] = mesh_info.cells_connectivity[j] - 1;
484
485 ios_file.getNextLine(); // Skip current \n\r
486
487 // On ne supporte que les maillage de dimension 3 dans ce vieux format
488 return 3;
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 // Numérote les blocs (pour le débug)
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 // Si le type est un point, le traitement semble
560 // un peu particulier. Il y a dans ce cas
561 // deux entiers dans la ligne suivante:
562 // - un entier qui ne semble
563 // - le numéro unique du noeud qui nous intéresse
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 // Maintenant qu'on a tous les blocks, la dimension du maillage est
580 // la plus grande dimension des 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 // On ne conserve que les blocs de notre dimension
591 // pour créér les mailles
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 // Création des mailles
641 info() << "Building cells, nb_cell=" << nb_elements << " nb_cell_node=" << nb_cell_node;
642 // Infos pour la création des mailles
643 // par maille: 1 pour son unique id,
644 // 1 pour son type,
645 // 1 pour chaque noeud
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 // Positionne les coordonnées
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 // On alloue un groupe s'il a un nom physique associé.
704 // Pour cela, il faut déjà qu'il soit associé à une entité.
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 // Pour l'instant on ne traite pas les nuages
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 // Il peut y avoir plusieurs blocs pour le même groupe.
769 // On récupère le groupe s'il existe déjà.
770 FaceGroup face_group = mesh->faceFamily()->findGroup(group_name, true);
771
772 UniqueArray<Int32> faces_id(nb_entity); // Numéro de la face dans le maillage \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 // Réordonne les identifiants des faces pour se conformer à Arcane et retrouver
789 // la face dans le maillage
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 // Il peut y avoir plusieurs blocs pour le même groupe.
837 // On récupère le groupe s'il existe déjà.
838 IItemFamily* cell_family = mesh->cellFamily();
839 CellGroup cell_group = cell_family->findGroup(group_name, true);
840
841 UniqueArray<Int32> cells_id(nb_entity); // Numéro de la face dans le maillage \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 // Il peut y avoir plusieurs blocs pour le même groupe.
859 // On récupère le groupe s'il existe déjà.
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 // Les noms des groupes peuvent commencer par des espaces et contiennent
907 // des guillemets qu'il faut supprimer.
909 if (s.startsWith(quote_mark))
910 s = s.substring(1);
911 if (s.endsWith(quote_mark))
912 s = s.substring(0, s.length() - 1);
913 mesh_info.physical_name_list.add(dim, tag, s);
914 info(4) << "[PhysicalName] index=" << i << " dim=" << dim << " tag=" << tag << " name='" << s << "'";
915 }
916 StringView s = ios_file.getNextLine();
917 if (s != "$EndPhysicalNames")
918 ARCANE_FATAL("found '{0}' and expected '$EndPhysicalNames'", s);
919}
920
921/*---------------------------------------------------------------------------*/
922/*---------------------------------------------------------------------------*/
923
955_readEntitiesV4(IosFile& ios_file, MeshInfo& mesh_info)
956{
957 Int32 nb_dim_item[4];
958 nb_dim_item[0] = ios_file.getInteger();
959 nb_dim_item[1] = ios_file.getInteger();
960 nb_dim_item[2] = ios_file.getInteger();
961 nb_dim_item[3] = ios_file.getInteger();
962 info(4) << "[Entities] nb_0d=" << nb_dim_item[0] << " nb_1d=" << nb_dim_item[1]
963 << " nb_2d=" << nb_dim_item[2] << " nb_3d=" << nb_dim_item[3];
964 // Après le format, on peut avoir les entités mais cela est optionnel
965 // Si elles sont présentes, on lit le fichier jusqu'à la fin de cette section.
966 StringView next_line = ios_file.getNextLine();
967 for (Int32 i = 0; i < nb_dim_item[0]; ++i) {
968 Int32 tag = ios_file.getInteger();
969 Real x = ios_file.getReal();
970 Real y = ios_file.getReal();
971 Real z = ios_file.getReal();
972 Int32 num_physical_tag = ios_file.getInteger();
973 if (num_physical_tag > 1)
974 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
975 Int32 physical_tag = -1;
976 if (num_physical_tag == 1)
977 physical_tag = ios_file.getInteger();
978 info(4) << "[Entities] point tag=" << tag << " x=" << x << " y=" << y << " z=" << z << " phys_tag=" << physical_tag;
979 mesh_info.entities_nodes_list.add(MeshV4EntitiesNodes(tag, physical_tag));
980 next_line = ios_file.getNextLine();
981 }
982
983 for (Int32 dim = 1; dim <= 3; ++dim) {
984 for (Int32 i = 0; i < nb_dim_item[dim]; ++i) {
985 Int32 tag = ios_file.getInteger();
986 Real min_x = ios_file.getReal();
987 Real min_y = ios_file.getReal();
988 Real min_z = ios_file.getReal();
989 Real max_x = ios_file.getReal();
990 Real max_y = ios_file.getReal();
991 Real max_z = ios_file.getReal();
992 Int32 num_physical_tag = ios_file.getInteger();
993 if (num_physical_tag > 1)
994 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
995 Int32 physical_tag = -1;
996 if (num_physical_tag == 1)
997 physical_tag = ios_file.getInteger();
998 Int32 num_bounding_group = ios_file.getInteger();
999 for (Int32 k = 0; k < num_bounding_group; ++k) {
1000 [[maybe_unused]] Int32 group_tag = ios_file.getInteger();
1001 }
1002 mesh_info.entities_with_nodes_list[dim - 1].add(MeshV4EntitiesWithNodes(dim, tag, physical_tag));
1003 info(4) << "[Entities] dim=" << dim << " tag=" << tag
1004 << " min_x=" << min_x << " min_y=" << min_y << " min_z=" << min_z
1005 << " max_x=" << max_x << " max_y=" << max_y << " max_z=" << max_z
1006 << " phys_tag=" << physical_tag;
1007 next_line = ios_file.getNextLine();
1008 }
1009 }
1010 StringView s = ios_file.getNextLine();
1011 if (s != "$EndEntities")
1012 ARCANE_FATAL("found '{0}' and expected '$EndEntities'", s);
1013}
1014
1015/*---------------------------------------------------------------------------*/
1016/*---------------------------------------------------------------------------*/
1050{
1051 const char* func_name = "MshMeshReader::_readMeshFromNewMshFile()";
1052 info() << "[_readMeshFromNewMshFile] New native mesh file format detected";
1053 MeshInfo mesh_info;
1054#define MSH_BINARY_TYPE 1
1055
1056 Real version = ios_file.getReal();
1057 if (version == 2.0)
1058 m_version = 2;
1059 else if (version == 4.1)
1060 m_version = 4;
1061 else
1062 ARCANE_THROW(IOException, "Wrong msh file version '{0}'. Only versions '2.0' or '4.1' are supported", version);
1063 info() << "Msh mesh_major_version=" << m_version;
1064 Integer file_type = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
1065 if (file_type == MSH_BINARY_TYPE)
1066 ARCANE_THROW(IOException, "Binary mode is not supported!");
1067
1068 Integer data_size = ios_file.getInteger(); // is an integer equal to the size of the floating point numbers used in the file
1069 ARCANE_UNUSED(data_size);
1070
1071 if (file_type == MSH_BINARY_TYPE) {
1072 (void)ios_file.getInteger(); // is an integer of value 1 written in binary form
1073 }
1074 ios_file.getNextLine(); // Skip current \n\r
1075
1076 // $EndMeshFormat
1077 if (!ios_file.lookForString("$EndMeshFormat"))
1078 ARCANE_THROW(IOException, "$EndMeshFormat not found");
1079
1080 // TODO: Les différentes sections ($Nodes, $Entitites, ...) peuvent
1081 // être dans n'importe quel ordre (à part $Nodes qui doit être avant $Elements)
1082 // Faire un méthode qui gère cela.
1083
1084 StringView next_line = ios_file.getNextLine();
1085 // Noms des groupes
1086 if (next_line == "$PhysicalNames") {
1087 _readPhysicalNames(ios_file, mesh_info);
1088 next_line = ios_file.getNextLine();
1089 }
1090 // Après le format, on peut avoir les entités mais cela est optionnel
1091 // Si elles sont présentes, on lit le fichier jusqu'à la fin de cette section.
1092 if (next_line == "$Entities") {
1093 _readEntitiesV4(ios_file, mesh_info);
1094 next_line = ios_file.getNextLine();
1095 }
1096 // $Nodes
1097 if (next_line != "$Nodes")
1098 ARCANE_THROW(IOException, "Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1099
1100 // Fetch nodes number and the coordinates
1101 if (file_type != MSH_BINARY_TYPE) {
1102 if (m_version == 2) {
1103 if (_readNodesFromAsciiMshV2File(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1104 ARCANE_THROW(IOException, "Ascii nodes coords error");
1105 }
1106 else if (m_version == 4) {
1107 if (_readNodesFromAsciiMshV4File(ios_file, mesh_info) != IMeshReader::RTOk)
1108 ARCANE_THROW(IOException, "Ascii nodes coords error");
1109 }
1110 }
1111 else {
1112 if (_readNodesFromBinaryMshFile(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1113 ARCANE_THROW(IOException, "Binary nodes coords error");
1114 }
1115 // $EndNodes
1116 if (!ios_file.lookForString("$EndNodes"))
1117 ARCANE_THROW(IOException, "$EndNodes not found");
1118
1119 // $Elements
1120 Integer mesh_dimension = -1;
1121 {
1122 if (!ios_file.lookForString("$Elements"))
1123 ARCANE_THROW(IOException, "$Elements not found");
1124
1125 if (m_version == 2)
1126 mesh_dimension = _readElementsFromAsciiMshV2File(ios_file, mesh_info);
1127 else if (m_version == 4)
1128 mesh_dimension = _readElementsFromAsciiMshV4File(ios_file, mesh_info);
1129
1130 // $EndElements
1131 if (!ios_file.lookForString("$EndElements"))
1132 throw IOException(func_name, "$EndElements not found");
1133 }
1134
1135 info() << "Computed mesh dimension = " << mesh_dimension;
1136
1137 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
1138 pmesh->setDimension(mesh_dimension);
1139
1140 IParallelMng* pm = mesh->parallelMng();
1141 bool is_parallel = pm->isParallel();
1142 Int32 rank = mesh->meshPartInfo().partRank();
1143 // En parallèle, seul le rang 0 lit le maillage
1144 bool is_read_items = !(is_parallel && rank != 0);
1145 _allocateCells(mesh, mesh_info, is_read_items);
1146 _allocateGroups(mesh, mesh_info, is_read_items);
1147 return IMeshReader::RTOk;
1148}
1149
1150/*---------------------------------------------------------------------------*/
1151/*---------------------------------------------------------------------------*/
1157readMeshFromMshFile(IMesh* mesh, const String& filename, bool use_internal_partition)
1158{
1159 info() << "Trying to read 'msh' file '" << filename << "'"
1160 << " use_internal_partition=" << use_internal_partition;
1161
1162 std::ifstream ifile(filename.localstr());
1163 if (!ifile) {
1164 error() << "Unable to read file '" << filename << "'";
1165 return IMeshReader::RTError;
1166 }
1167 IosFile ios_file(&ifile);
1168 String mesh_format_str = ios_file.getNextLine(); // Comments do not seem to be implemented in .msh files
1169 if (IosFile::isEqualString(mesh_format_str, "$MeshFormat"))
1170 return _readMeshFromNewMshFile(mesh, ios_file);
1171 info() << "The file does not begin with '$MeshFormat' returning RTError";
1172 return IMeshReader::RTError;
1173}
1174
1175/*---------------------------------------------------------------------------*/
1176/*---------------------------------------------------------------------------*/
1177
1178/*---------------------------------------------------------------------------*/
1179/*---------------------------------------------------------------------------*/
1180
1181extern "C++" Ref<IMshMeshReader>
1182createMshParallelMeshReader(ITraceMng* tm);
1183
1184namespace
1185{
1186
1188_internalCreateReader(ITraceMng* tm)
1189{
1190 bool use_new_reader = true;
1191 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_PARALLEL_MSH_READER", true))
1192 use_new_reader = (v.value()!=0);
1193 Ref<IMshMeshReader> reader;
1194 if (use_new_reader)
1195 reader = createMshParallelMeshReader(tm);
1196 else
1197 reader = createMshMeshReader(tm);
1198 return reader;
1199}
1200
1201}
1202
1203/*---------------------------------------------------------------------------*/
1204/*---------------------------------------------------------------------------*/
1205
1206class MshMeshReaderService
1207: public AbstractService
1208, public IMeshReader
1209{
1210 public:
1211
1212 explicit MshMeshReaderService(const ServiceBuildInfo& sbi)
1213 : AbstractService(sbi)
1214 {
1215 }
1216
1217 public:
1218
1219 void build() override {}
1220
1221 bool allowExtension(const String& str) override { return str == "msh"; }
1222
1224 const String& file_name, const String& dir_name,
1225 bool use_internal_partition) override
1226 {
1227 ARCANE_UNUSED(dir_name);
1228 ARCANE_UNUSED(mesh_node);
1229
1230 Ref<IMshMeshReader> reader = _internalCreateReader(traceMng());
1231 return reader->readMeshFromMshFile(mesh, file_name, use_internal_partition);
1232 }
1233};
1234
1235/*---------------------------------------------------------------------------*/
1236/*---------------------------------------------------------------------------*/
1237
1238// Obsolète. Utiliser 'MshMeshReader' à la place
1239ARCANE_REGISTER_SERVICE(MshMeshReaderService,
1240 ServiceProperty("MshNewMeshReader", ST_SubDomain),
1241 ARCANE_SERVICE_INTERFACE(IMeshReader));
1242
1243ARCANE_REGISTER_SERVICE(MshMeshReaderService,
1244 ServiceProperty("MshMeshReader", ST_SubDomain),
1245 ARCANE_SERVICE_INTERFACE(IMeshReader));
1246
1247/*---------------------------------------------------------------------------*/
1248/*---------------------------------------------------------------------------*/
1249
1250class MshCaseMeshReader
1251: public AbstractService
1252, public ICaseMeshReader
1253{
1254 public:
1255
1256 class Builder
1257 : public IMeshBuilder
1258 {
1259 public:
1260
1261 explicit Builder(ITraceMng* tm, const CaseMeshReaderReadInfo& read_info)
1262 : m_trace_mng(tm)
1263 , m_read_info(read_info)
1264 , m_use_internal_partition(read_info.isParallelRead())
1265 {}
1266
1267 public:
1268
1269 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
1270 {
1271 ARCANE_UNUSED(build_info);
1272 }
1274 {
1275 Ref<IMshMeshReader> reader = _internalCreateReader(m_trace_mng);
1276 String fname = m_read_info.fileName();
1277 m_trace_mng->info() << "Msh Reader (ICaseMeshReader) file_name=" << fname;
1278 IMeshReader::eReturnType ret = reader->readMeshFromMshFile(pm, fname, m_use_internal_partition);
1279 if (ret != IMeshReader::RTOk)
1280 ARCANE_FATAL("Can not read MSH File");
1281 }
1282
1283 private:
1284
1285 ITraceMng* m_trace_mng;
1286 CaseMeshReaderReadInfo m_read_info;
1287 bool m_use_internal_partition = false;
1288 };
1289
1290 public:
1291
1292 explicit MshCaseMeshReader(const ServiceBuildInfo& sbi)
1293 : AbstractService(sbi)
1294 {}
1295
1296 public:
1297
1299 {
1300 IMeshBuilder* builder = nullptr;
1301 if (read_info.format() == "msh")
1302 builder = new Builder(traceMng(), read_info);
1303 return makeRef(builder);
1304 }
1305};
1306
1307/*---------------------------------------------------------------------------*/
1308/*---------------------------------------------------------------------------*/
1309
1310ARCANE_REGISTER_SERVICE(MshCaseMeshReader,
1311 ServiceProperty("MshCaseMeshReader", ST_SubDomain),
1312 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1313
1314/*---------------------------------------------------------------------------*/
1315/*---------------------------------------------------------------------------*/
1316
1317} // End namespace Arcane
1318
1319/*---------------------------------------------------------------------------*/
1320/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions utilitaires sur le maillage.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
Classe de base d'un service.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
Tableau d'items de types quelconques.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void addRange(ConstReferenceType val, Int64 n)
Ajoute n élément de valeur val à la fin du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Informations nécessaires pour la lecture d'un fichier de maillage.
Table de hachage pour tableaux associatifs.
Interface du service de lecture du maillage à partir du jeu de données.
Interface d'un service de création/lecture du maillage.
Interface du service gérant la lecture d'un maillage.
Definition IMeshReader.h:37
eReturnType
Types des codes de retour d'une lecture ou écriture.
Definition IMeshReader.h:42
@ RTError
Erreur lors de l'opération.
Definition IMeshReader.h:44
@ RTOk
Opération effectuée avec succès.
Definition IMeshReader.h:43
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Definition IOException.h:32
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual void setDimension(Integer dim)=0
Positionne la dimension du maillage (1D, 2D ou 3D).
Interface du gestionnaire de traces.
Routines des Lecture/Ecriture d'un fichier.
Definition IosFile.h:33
Paramètres nécessaires à la construction d'un maillage.
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Remplit build_info avec les informations nécessaires pour créer le maillage.
void allocateMeshItems(IPrimaryMesh *pm) override
Alloue les entités du maillage géré par ce service.
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Retourne un builder pour créer et lire le maillage dont les informations sont spécifiées dans read_in...
bool allowExtension(const String &str) override
Vérifie si le service supporte les fichiers avec l'extension str.
void build() override
Construction de niveau build du service.
eReturnType readMeshFromFile(IPrimaryMesh *mesh, const XmlNode &mesh_node, const String &file_name, const String &dir_name, bool use_internal_partition) override
Lit un maillage à partir d'un fichier.
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)
Lecture des entités.
eReturnType _readMeshFromNewMshFile(IMesh *, IosFile &)
Integer _readElementsFromAsciiMshV4File(IosFile &, MeshInfo &mesh_info)
Lecture des éléments (mailles,faces,...)
Exception lorsqu'une opération n'est pas supportée.
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Référence à une instance.
Structure contenant les informations pour créer un service.
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:452
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
Noeud d'un arbre DOM.
Definition XmlNode.h:51
T max(const T &a, const T &b, const T &c)
Retourne le maximum de trois éléments.
Definition MathUtils.h:392
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:567
double Real
Type représentant un réel.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.
Infos du bloc '$PhysicalNames'.
Infos d'un bloc pour $Elements pour la version 4.
Int32 nb_entity
Nombre d'entités du bloc.
Int32 item_nb_node
Nombre de noeuds de l'entité.
Int32 index
Index du bloc dans la liste.
Integer item_type
Type Arcane de l'entité
Infos pour les entités 1D, 2D et 3D.