Arcane  v4.1.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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("_convertToMshType", "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.
Classe template pour convertir un type.
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:32
eReturnType
Types des codes de retour d'une lecture ou écriture.
Definition IMeshReader.h:37
@ RTError
Erreur lors de l'opération.
Definition IMeshReader.h:39
@ RTOk
Opération effectuée avec succès.
Definition IMeshReader.h:38
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:228
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:453
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:496
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.