Arcane  v3.14.10.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-2024 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-2024 */
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/ScopedPtr.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/String.h"
21#include "arcane/utils/IOException.h"
22#include "arcane/utils/Collection.h"
23#include "arcane/utils/Enumerator.h"
24#include "arcane/utils/NotImplementedException.h"
25#include "arcane/utils/Real3.h"
26#include "arcane/utils/OStringStream.h"
27
28#include "arcane/core/AbstractService.h"
29#include "arcane/core/FactoryService.h"
30#include "arcane/core/IMainFactory.h"
31#include "arcane/core/IMeshReader.h"
32#include "arcane/core/ISubDomain.h"
33#include "arcane/core/IMesh.h"
34#include "arcane/core/IMeshSubMeshTransition.h"
35#include "arcane/core/IItemFamily.h"
36#include "arcane/core/Item.h"
38#include "arcane/core/VariableTypes.h"
39#include "arcane/core/IVariableAccessor.h"
40#include "arcane/core/IParallelMng.h"
41#include "arcane/core/IIOMng.h"
42#include "arcane/core/IXmlDocumentHolder.h"
43#include "arcane/core/XmlNodeList.h"
44#include "arcane/core/XmlNode.h"
45#include "arcane/core/IMeshUtilities.h"
46#include "arcane/core/IMeshWriter.h"
47#include "arcane/core/BasicService.h"
48#include "arcane/core/MeshPartInfo.h"
50#include "arcane/core/ICaseMeshReader.h"
51#include "arcane/core/IMeshBuilder.h"
52#include "arcane/core/ItemPrinter.h"
53
54// Element types in .msh file format, found in gmsh-2.0.4/Common/GmshDefines.h
55#include "arcane/std/internal/IosFile.h"
56#include "arcane/std/internal/IosGmsh.h"
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61// NOTE: A partir de juillet 2024 (version 3.13.8), on utilise par défaut
62// la version parallèle du lecteur (MshParallelMshReader.cc). Cette version
63// sera à terme supprimée.
64
65/*
66 * NOTES:
67 * - La bibliothèque `gmsh` fournit un script 'open.py' dans le répertoire
68 * 'demos/api' qui permet de générer un fichier '.msh' à partir d'un '.geo'.
69 * - Il est aussi possible d'utiliser directement l'exécutable 'gmsh' avec
70 * l'option '-save-all' pour sauver un fichier '.msh' à partir d'un '.geo'
71 *
72 * TODO:
73 * - lire les tags des noeuds(uniqueId())
74 * - supporter les partitions
75 * - pouvoir utiliser la bibliothèque 'gmsh' directement.
76 * - améliorer la lecture parallèle en évitant que tous les sous-domaines
77 * lisent le fichier (même si seul le sous-domaine 0 alloue les entités)
78 */
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
82
83namespace Arcane
84{
85
86/*---------------------------------------------------------------------------*/
87/*---------------------------------------------------------------------------*/
103: public TraceAccessor
104, public IMshMeshReader
105{
106 public:
107
108 using eReturnType = typename IMeshReader::eReturnType;
109
117 {
118 Int32 index = 0;
119 Int32 nb_entity = 0;
120 Integer item_type = -1;
121 Int32 dimension = -1;
122 Int32 item_nb_node = 0;
123 Int32 entity_tag = -1;
125 UniqueArray<Int64> connectivity;
126 };
127
133 {
134 MeshPhysicalName(Int32 _dimension, Int32 _tag, const String& _name)
135 : dimension(_dimension)
136 , tag(_tag)
137 , name(_name)
138 {}
139 MeshPhysicalName() = default;
140 bool isNull() const { return dimension == (-1); }
141 Int32 dimension = -1;
142 Int32 tag = -1;
143 String name;
144 };
145
150 {
152 : m_physical_names(4)
153 {}
154 void add(Int32 dimension, Int32 tag, String name)
155 {
156 m_physical_names[dimension].add(MeshPhysicalName{ dimension, tag, name });
157 }
158 MeshPhysicalName find(Int32 dimension, Int32 tag) const
159 {
160 for (auto& x : m_physical_names[dimension])
161 if (x.tag == tag)
162 return x;
163 return {};
164 }
165
166 private:
167
169 };
170
173 {
174 MeshV4EntitiesNodes(Int32 _tag, Int32 _physical_tag)
175 : tag(_tag)
176 , physical_tag(_physical_tag)
177 {}
178 Int32 tag;
179 Int32 physical_tag;
180 };
181
184 {
185 MeshV4EntitiesWithNodes(Int32 _dim, Int32 _tag, Int32 _physical_tag)
186 : dimension(_dim)
187 , tag(_tag)
188 , physical_tag(_physical_tag)
189 {}
190 Int32 dimension;
191 Int32 tag;
192 Int32 physical_tag;
193 };
194
195 struct MeshInfo
196 {
197 public:
198
199 MeshInfo()
200 : node_coords_map(5000, true)
201 {}
202
203 public:
204
205 MeshV4EntitiesWithNodes* findEntities(Int32 dimension, Int32 tag)
206 {
207 for (auto& x : entities_with_nodes_list[dimension - 1])
208 if (x.tag == tag)
209 return &x;
210 return nullptr;
211 }
212
213 MeshV4EntitiesNodes* findNodeEntities(Int32 tag)
214 {
215 for (auto& x : entities_nodes_list)
216 if (x.tag == tag)
217 return &x;
218 return nullptr;
219 }
220
221 public:
222
223 Integer nb_elements = 0;
224 Integer nb_cell_node = 0;
225 UniqueArray<Int32> cells_nb_node;
226 UniqueArray<Int32> cells_type;
227 UniqueArray<Int64> cells_uid;
228 UniqueArray<Int64> cells_connectivity;
229 UniqueArray<Real3> node_coords;
230 HashTableMapT<Int64, Real3> node_coords_map;
231 MeshPhysicalNameList physical_name_list;
232 UniqueArray<MeshV4EntitiesNodes> entities_nodes_list;
233 UniqueArray<MeshV4EntitiesWithNodes> entities_with_nodes_list[3];
235 };
236
237 public:
238
239 explicit MshMeshReader(ITraceMng* tm)
241 {}
242
243 eReturnType readMeshFromMshFile(IMesh* mesh, const String& file_name) override;
244
245 private:
246
247 Integer m_version = 0;
248
249 eReturnType _readNodesFromAsciiMshV2File(IosFile&, Array<Real3>&);
250 eReturnType _readNodesFromAsciiMshV4File(IosFile&, MeshInfo& mesh_info);
251 eReturnType _readNodesFromBinaryMshFile(IosFile&, Array<Real3>&);
252 Integer _readElementsFromAsciiMshV2File(IosFile&, MeshInfo& mesh_info);
254 eReturnType _readMeshFromNewMshFile(IMesh*, IosFile&);
255 void _allocateCells(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
256 void _allocateGroups(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items);
257 void _addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
258 void _addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
259 void _addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name);
260 Integer _switchMshType(Integer, Integer&);
261 void _readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info);
262 void _readEntitiesV4(IosFile& ios_file, MeshInfo& mesh_info);
263};
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
267
268extern "C++" Ref<IMshMeshReader>
269createMshMeshReader(ITraceMng* tm)
270{
271 return makeRef<IMshMeshReader>(new MshMeshReader(tm));
272}
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
277Integer MshMeshReader::
278_switchMshType(Integer mshElemType, Integer& nNodes)
279{
280 switch (mshElemType) {
281 case (IT_NullType): // used to decode IT_NullType: IT_HemiHexa7|IT_Line9
282 switch (nNodes) {
283 case (7):
284 return IT_HemiHexa7;
285 default:
286 info() << "Could not decode IT_NullType with nNodes=" << nNodes;
287 throw IOException("_switchMshType", "Could not decode IT_NullType with nNodes");
288 }
289 break;
290 case (MSH_PNT):
291 nNodes = 1;
292 return IT_Vertex; //printf("1-node point");
293 case (MSH_LIN_2):
294 nNodes = 2;
295 return IT_Line2; //printf("2-node line");
296 case (MSH_TRI_3):
297 nNodes = 3;
298 return IT_Triangle3; //printf("3-node triangle");
299 case (MSH_QUA_4):
300 nNodes = 4;
301 return IT_Quad4; //printf("4-node quadrangle");
302 case (MSH_TET_4):
303 nNodes = 4;
304 return IT_Tetraedron4; //printf("4-node tetrahedron");
305 case (MSH_HEX_8):
306 nNodes = 8;
307 return IT_Hexaedron8; //printf("8-node hexahedron");
308 case (MSH_PRI_6):
309 nNodes = 6;
310 return IT_Pentaedron6; //printf("6-node prism");
311 case (MSH_PYR_5):
312 nNodes = 5;
313 return IT_Pyramid5; //printf("5-node pyramid");
314 case (MSH_TRI_10):
315 nNodes = 10;
316 return IT_Heptaedron10; //printf("10-node second order tetrahedron")
317 case (MSH_TRI_12):
318 nNodes = 12;
319 return IT_Octaedron12; //printf("Unknown MSH_TRI_12");
320
321 case (MSH_TRI_6):
322 case (MSH_QUA_9):
323 case (MSH_HEX_27):
324 case (MSH_PRI_18):
325 case (MSH_PYR_14):
326 case (MSH_QUA_8):
327 case (MSH_HEX_20):
328 case (MSH_PRI_15):
329 case (MSH_PYR_13):
330 case (MSH_TRI_9):
331 case (MSH_TRI_15):
332 case (MSH_TRI_15I):
333 case (MSH_TRI_21):
334 default:
335 ARCANE_THROW(NotSupportedException, "Unknown GMSH element type '{0}'", mshElemType);
336 }
337 return IT_NullType;
338}
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
342
343IMeshReader::eReturnType MshMeshReader::
344_readNodesFromAsciiMshV2File(IosFile& ios_file, Array<Real3>& node_coords)
345{
346 // number-of-nodes & coords
347 info() << "[_readNodesFromAsciiMshV2File] Looking for number-of-nodes";
348 Integer nb_node = ios_file.getInteger();
349 if (nb_node < 0)
350 throw IOException(A_FUNCINFO, String("Invalid number of nodes: n=") + nb_node);
351 info() << "[_readNodesFromAsciiMshV2File] nb_node=" << nb_node;
352 for (Integer i = 0; i < nb_node; ++i) {
353 // Il faut lire l'id même si on ne s'en sert pas.
354 [[maybe_unused]] Int32 id = ios_file.getInteger();
355 Real nx = ios_file.getReal();
356 Real ny = ios_file.getReal();
357 Real nz = ios_file.getReal();
358 node_coords.add(Real3(nx, ny, nz));
359 //info() << "id_" << id << " xyz(" << nx << "," << ny << "," << nz << ")";
360 }
361 ios_file.getNextLine(); // Skip current \n\r
362 return IMeshReader::RTOk;
363}
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
388{
389 // Première ligne du fichier
390 Integer nb_entity = ios_file.getInteger();
391 Integer total_nb_node = ios_file.getInteger();
392 Integer min_node_tag = ios_file.getInteger();
393 Integer max_node_tag = ios_file.getInteger();
394 ios_file.getNextLine(); // Skip current \n\r
395 if (total_nb_node < 0)
396 ARCANE_THROW(IOException, "Invalid number of nodes : '{0}'", total_nb_node);
397 info() << "[Nodes] nb_entity=" << nb_entity
398 << " total_nb_node=" << total_nb_node
399 << " min_tag=" << min_node_tag
400 << " max_tag=" << max_node_tag;
401
403 for (Integer i_entity = 0; i_entity < nb_entity; ++i_entity) {
404 // Dimension de l'entité (pas utile)
405 [[maybe_unused]] Integer entity_dim = ios_file.getInteger();
406 // Tag de l'entité (pas utile)
407 [[maybe_unused]] Integer entity_tag = ios_file.getInteger();
408 Integer parametric_coordinates = ios_file.getInteger();
409 Integer nb_node2 = ios_file.getInteger();
410 ios_file.getNextLine();
411
412 info(4) << "[Nodes] index=" << i_entity << " entity_dim=" << entity_dim << " entity_tag=" << entity_tag
413 << " parametric=" << parametric_coordinates
414 << " nb_node2=" << nb_node2;
415 if (parametric_coordinates != 0)
416 ARCANE_THROW(NotSupportedException, "Only 'parametric coordinates' value of '0' is supported (current={0})", parametric_coordinates);
417 // Il est possible que le nombre de noeuds soit 0.
418 // Dans ce cas, il faut directement passer à la ligne suivante
419 if (nb_node2 == 0)
420 continue;
421 nodes_uids.resize(nb_node2);
422 for (Integer i = 0; i < nb_node2; ++i) {
423 // Conserve le uniqueId() du noeuds.
424 nodes_uids[i] = ios_file.getInteger();
425 //info() << "I=" << i << " ID=" << nodes_uids[i];
426 }
427 for (Integer i = 0; i < nb_node2; ++i) {
428 Real nx = ios_file.getReal();
429 Real ny = ios_file.getReal();
430 Real nz = ios_file.getReal();
431 Real3 xyz(nx, ny, nz);
432 mesh_info.node_coords_map.add(nodes_uids[i], xyz);
433 //info() << "I=" << i << " ID=" << nodes_uids[i] << " COORD=" << xyz;
434 }
435 ios_file.getNextLine(); // Skip current \n\r
436 }
437 return IMeshReader::RTOk;
438}
439
440/*---------------------------------------------------------------------------*/
441/*---------------------------------------------------------------------------*/
442
443Integer MshMeshReader::
444_readElementsFromAsciiMshV2File(IosFile& ios_file, MeshInfo& mesh_info)
445{
446 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
447 if (number_of_elements < 0)
448 ARCANE_THROW(IOException, String("Error with the number_of_elements=") + number_of_elements);
449
450 info() << "nb_elements=" << number_of_elements;
451
452 //elm-number elm-type number-of-tags < tag > ... node-number-list
453 // Lecture des infos des mailles & de la connectivité
454 // bool pour voir si on est depuis 0 ou 1
455 bool it_starts_at_zero = false;
456 for (Integer i = 0; i < number_of_elements; ++i) {
457 [[maybe_unused]] Integer elm_number = ios_file.getInteger(); // Index
458 Integer elm_type = ios_file.getInteger(); // Type
459 // info() << elm_number << " " << elm_type;
460 // Now get tags in the case the number of nodes is encoded
461 Integer number_of_tags = ios_file.getInteger();
462 Integer lastTag = 0;
463 for (Integer j = 0; j < number_of_tags; ++j)
464 lastTag = ios_file.getInteger();
465 Integer number_of_nodes = 0; // Set the number of nodes from the discovered type
466 if (elm_type == IT_NullType) {
468 info() << "We hit the case the number of nodes is encoded (number_of_nodes=" << number_of_nodes << ")";
469 }
470 Integer cell_type = _switchMshType(elm_type, number_of_nodes);
471 //#warning Skipping 2D lines & points
472 // We skip 2-node lines and 1-node points
473 if (number_of_nodes < 3) {
474 for (Integer j = 0; j < number_of_nodes; ++j)
475 ios_file.getInteger();
476 continue;
477 }
478
479 mesh_info.cells_type.add(cell_type);
480 mesh_info.cells_nb_node.add(number_of_nodes);
481 mesh_info.cells_uid.add(i);
482 info() << elm_number << " " << elm_type << " " << number_of_tags << " number_of_nodes=" << number_of_nodes;
483 // printf("%i %i %i %i %i (", elm_number, elm_type, reg_phys, reg_elem, number_of_nodes);
484 for (Integer j = 0; j < number_of_nodes; ++j) {
485 // printf("%i ", node_number);
486 Integer id = ios_file.getInteger();
487 if (id == 0)
488 it_starts_at_zero = true;
489 mesh_info.cells_connectivity.add(id);
490 }
491 // printf(")\n");
492 }
493 if (!it_starts_at_zero)
494 for (Integer j = 0, max = mesh_info.cells_connectivity.size(); j < max; ++j)
495 mesh_info.cells_connectivity[j] = mesh_info.cells_connectivity[j] - 1;
496
497 ios_file.getNextLine(); // Skip current \n\r
498
499 // On ne supporte que les maillage de dimension 3 dans ce vieux format
500 return 3;
501}
502
503/*---------------------------------------------------------------------------*/
504/*---------------------------------------------------------------------------*/
524{
525 Integer nb_block = ios_file.getInteger();
526
527 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
528 Integer min_element_tag = ios_file.getInteger();
529 Integer max_element_tag = ios_file.getInteger();
530 ios_file.getNextLine(); // Skip current \n\r
531 info() << "[Elements] nb_block=" << nb_block
532 << " nb_elements=" << number_of_elements
533 << " min_element_tag=" << min_element_tag
534 << " max_element_tag=" << max_element_tag;
535
536 if (number_of_elements < 0)
537 ARCANE_THROW(IOException, "Invalid number of elements: {0}", number_of_elements);
538
540 blocks.resize(nb_block);
541
542 {
543 // Numérote les blocs (pour le débug)
544 Integer index = 0;
545 for (MeshV4ElementsBlock& block : blocks) {
546 block.index = index;
547 ++index;
548 }
549 }
550 for (MeshV4ElementsBlock& block : blocks) {
551 Integer entity_dim = ios_file.getInteger();
552 Integer entity_tag = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
553 Integer entity_type = ios_file.getInteger();
554 Integer nb_entity_in_block = ios_file.getInteger();
555
556 Integer item_nb_node = 0;
557 Integer item_type = _switchMshType(entity_type, item_nb_node);
558
559 info(4) << "[Elements] index=" << block.index << " entity_dim=" << entity_dim
560 << " entity_tag=" << entity_tag
561 << " entity_type=" << entity_type << " nb_in_block=" << nb_entity_in_block
562 << " item_type=" << item_type << " item_nb_node=" << item_nb_node;
563
564 block.nb_entity = nb_entity_in_block;
565 block.item_type = item_type;
566 block.item_nb_node = item_nb_node;
567 block.dimension = entity_dim;
568 block.entity_tag = entity_tag;
569
570 if (entity_type==MSH_PNT){
571 // Si le type est un point, le traitement semble
572 // un peu particulier. Il y a dans ce cas
573 // deux entiers dans la ligne suivante:
574 // - un entier qui ne semble
575 // - le numéro unique du noeud qui nous intéresse
576 [[maybe_unused]] Int64 unused_id = ios_file.getInt64();
577 Int64 item_unique_id = ios_file.getInt64();
578 info(4) << "Adding unique node uid=" << item_unique_id;
579 block.uids.add(item_unique_id);
580 }
581 else{
582 for (Integer i = 0; i < nb_entity_in_block; ++i) {
583 Int64 item_unique_id = ios_file.getInt64();
584 block.uids.add(item_unique_id);
585 for (Integer j = 0; j < item_nb_node; ++j)
586 block.connectivity.add(ios_file.getInt64());
587 }
588 }
589 ios_file.getNextLine(); // Skip current \n\r
590 }
591 // Maintenant qu'on a tous les blocks, la dimension du maillage est
592 // la plus grande dimension des blocks
593 Integer mesh_dimension = -1;
594 for (MeshV4ElementsBlock& block : blocks)
595 mesh_dimension = math::max(mesh_dimension, block.dimension);
596 if (mesh_dimension < 0)
597 ARCANE_FATAL("Invalid computed mesh dimension '{0}'", mesh_dimension);
598 if (mesh_dimension != 2 && mesh_dimension != 3)
599 ARCANE_THROW(NotSupportedException, "mesh dimension '{0}'. Only 2D or 3D meshes are supported", mesh_dimension);
600 info() << "Computed mesh dimension = " << mesh_dimension;
601
602 // On ne conserve que les blocs de notre dimension
603 // pour créér les mailles
604 for (MeshV4ElementsBlock& block : blocks) {
605 if (block.dimension != mesh_dimension)
606 continue;
607
608 info(4) << "Keeping block index=" << block.index;
609
610 Integer item_type = block.item_type;
611 Integer item_nb_node = block.item_nb_node;
612
613 for (Integer i = 0; i < block.nb_entity; ++i) {
614 mesh_info.cells_type.add(item_type);
615 mesh_info.cells_nb_node.add(item_nb_node);
616 mesh_info.cells_uid.add(block.uids[i]);
617 auto v = block.connectivity.subView(i * item_nb_node, item_nb_node);
618 mesh_info.cells_connectivity.addRange(v);
619 }
620 }
621
622 return mesh_dimension;
623}
624
625/*---------------------------------------------------------------------------*/
626/*---------------------------------------------------------------------------*/
627/*
628 * nodes-binary is the list of nodes in binary form, i.e., a array of
629 * number-of-nodes *(4+3*data-size) bytes. For each node, the first 4 bytes
630 * contain the node number and the next (3*data-size) bytes contain the three
631 * floating point coordinates.
632 */
633IMeshReader::eReturnType MshMeshReader::
634_readNodesFromBinaryMshFile(IosFile& ios_file, Array<Real3>& node_coords)
635{
636 ARCANE_UNUSED(ios_file);
637 ARCANE_UNUSED(node_coords);
639}
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
644void MshMeshReader::
645_allocateCells(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items)
646{
647 Integer nb_elements = mesh_info.cells_type.size();
648 info() << "nb_of_elements=cells_type.size()=" << nb_elements;
649 Integer nb_cell_node = mesh_info.cells_connectivity.size();
650 info() << "nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
651
652 // Création des mailles
653 info() << "Building cells, nb_cell=" << nb_elements << " nb_cell_node=" << nb_cell_node;
654 // Infos pour la création des mailles
655 // par maille: 1 pour son unique id,
656 // 1 pour son type,
657 // 1 pour chaque noeud
658 UniqueArray<Int64> cells_infos;
659 Integer connectivity_index = 0;
660 UniqueArray<Real3> local_coords;
661 for (Integer i = 0; i < nb_elements; ++i) {
662 Integer current_cell_nb_node = mesh_info.cells_nb_node[i];
663 Integer cell_type = mesh_info.cells_type[i];
664 Int64 cell_uid = mesh_info.cells_uid[i];
665 cells_infos.add(cell_type);
666 cells_infos.add(cell_uid); //cell_unique_id
667
668 ArrayView<Int64> local_info(current_cell_nb_node, &mesh_info.cells_connectivity[connectivity_index]);
669 cells_infos.addRange(local_info);
670 connectivity_index += current_cell_nb_node;
671 }
672
673 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
674 info() << "## Allocating ##";
675
676 if (is_read_items)
677 pmesh->allocateCells(nb_elements, cells_infos, false);
678 else
679 pmesh->allocateCells(0, UniqueArray<Int64>(0), false);
680
681 info() << "## Ending ##";
682 pmesh->endAllocate();
683 info() << "## Done ##";
684
685 // Positionne les coordonnées
686 {
687 VariableNodeReal3& nodes_coord_var(pmesh->nodesCoordinates());
688 bool has_map = mesh_info.node_coords.empty();
689 if (has_map) {
690 ENUMERATE_NODE (i, mesh->ownNodes()) {
691 Node node = *i;
692 nodes_coord_var[node] = mesh_info.node_coords_map.lookupValue(node.uniqueId().asInt64());
693 }
694 nodes_coord_var.synchronize();
695 }
696 else {
697 ENUMERATE_NODE (node, mesh->allNodes()) {
698 nodes_coord_var[node] = mesh_info.node_coords.item(node->uniqueId().asInt32());
699 }
700 }
701 }
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706
707void MshMeshReader::
708_allocateGroups(IMesh* mesh, MeshInfo& mesh_info, bool is_read_items)
709{
710 Int32 mesh_dim = mesh->dimension();
711 Int32 face_dim = mesh_dim - 1;
712 for (MeshV4ElementsBlock& block : mesh_info.blocks) {
713 Int32 block_index = block.index;
714 Int32 block_dim = block.dimension;
715 // On alloue un groupe s'il a un nom physique associé.
716 // Pour cela, il faut déjà qu'il soit associé à une entité.
717 Int32 block_entity_tag = block.entity_tag;
718 if (block_entity_tag < 0) {
719 info(5) << "[Groups] Skipping block index=" << block_index << " because it has no entity";
720 continue;
721 }
722 MeshPhysicalName physical_name;
723 // Pour l'instant on ne traite pas les nuages
724 if (block_dim == 0) {
725 MeshV4EntitiesNodes* entity = mesh_info.findNodeEntities(block_entity_tag);
726 if (!entity) {
727 info(5) << "[Groups] Skipping block index=" << block_index
728 << " because entity tag is invalid";
729 continue;
730 }
731 Int32 entity_physical_tag = entity->physical_tag;
732 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
733 }
734 else{
735 MeshV4EntitiesWithNodes* entity = mesh_info.findEntities(block_dim, block_entity_tag);
736 if (!entity) {
737 info(5) << "[Groups] Skipping block index=" << block_index
738 << " because entity tag is invalid";
739 continue;
740 }
741 Int32 entity_physical_tag = entity->physical_tag;
742 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
743 }
744 if (physical_name.isNull()) {
745 info(5) << "[Groups] Skipping block index=" << block_index
746 << " because entity physical tag is invalid";
747 continue;
748 }
749 info(4) << "[Groups] Block index=" << block_index << " dim=" << block_dim
750 << " name='" << physical_name.name << "'";
751 if (block_dim == mesh_dim) {
752 if (is_read_items)
753 _addCellGroup(mesh, block, physical_name.name);
754 else
755 mesh->cellFamily()->findGroup(physical_name.name, true);
756 }
757 else if (block_dim == face_dim) {
758 if (is_read_items)
759 _addFaceGroup(mesh, block, physical_name.name);
760 else
761 mesh->faceFamily()->findGroup(physical_name.name, true);
762 }
763 else {
764 if (is_read_items)
765 _addNodeGroup(mesh, block, physical_name.name);
766 else
767 mesh->nodeFamily()->findGroup(physical_name.name, true);
768 }
769 }
770}
771
772/*---------------------------------------------------------------------------*/
773/*---------------------------------------------------------------------------*/
774
775void MshMeshReader::
776_addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
777{
778 const Int32 nb_entity = block.nb_entity;
779
780 // Il peut y avoir plusieurs blocs pour le même groupe.
781 // On récupère le groupe s'il existe déjà.
782 FaceGroup face_group = mesh->faceFamily()->findGroup(group_name, true);
783
784 UniqueArray<Int32> faces_id(nb_entity); // Numéro de la face dans le maillage \a mesh
785
786 const Int32 item_nb_node = block.item_nb_node;
787 const Int32 face_nb_node = nb_entity * item_nb_node;
788
789 UniqueArray<Int64> faces_first_node_unique_id(nb_entity);
790 UniqueArray<Int32> faces_first_node_local_id(nb_entity);
791 UniqueArray<Int64> faces_nodes_unique_id(face_nb_node);
792 Integer faces_nodes_unique_id_index = 0;
793
794 UniqueArray<Int64> orig_nodes_id(item_nb_node);
795 UniqueArray<Integer> face_nodes_index(item_nb_node);
796
797 IItemFamily* node_family = mesh->nodeFamily();
798 NodeInfoListView mesh_nodes(node_family);
799
800 // Réordonne les identifiants des faces pour se conformer à Arcane et retrouver
801 // la face dans le maillage
802 for (Integer i_face = 0; i_face < nb_entity; ++i_face) {
803 for (Integer z = 0; z < item_nb_node; ++z)
804 orig_nodes_id[z] = block.connectivity[faces_nodes_unique_id_index + z];
805
806 mesh_utils::reorderNodesOfFace2(orig_nodes_id, face_nodes_index);
807 for (Integer z = 0; z < item_nb_node; ++z)
808 faces_nodes_unique_id[faces_nodes_unique_id_index + z] = orig_nodes_id[face_nodes_index[z]];
809 faces_first_node_unique_id[i_face] = orig_nodes_id[face_nodes_index[0]];
810 faces_nodes_unique_id_index += item_nb_node;
811 }
812
813 node_family->itemsUniqueIdToLocalId(faces_first_node_local_id, faces_first_node_unique_id);
814
815 faces_nodes_unique_id_index = 0;
816 for (Integer i_face = 0; i_face < nb_entity; ++i_face) {
817 const Integer n = item_nb_node;
818 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
819 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
820 Face face = mesh_utils::getFaceFromNodesUnique(current_node, face_nodes_id);
821
822 if (face.null()) {
823 OStringStream ostr;
824 ostr() << "(Nodes:";
825 for (Integer z = 0; z < n; ++z)
826 ostr() << ' ' << face_nodes_id[z];
827 ostr() << " - " << current_node.localId() << ")";
828 ARCANE_FATAL("INTERNAL: MeshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity",
829 i_face, ostr.str());
830 }
831 faces_id[i_face] = face.localId();
832
833 faces_nodes_unique_id_index += n;
834 }
835 info(4) << "Adding " << faces_id.size() << " faces from block index=" << block.index
836 << " to group '" << face_group.name() << "'";
837 face_group.addItems(faces_id);
838}
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
842
843void MshMeshReader::
844_addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
845{
846 const Int32 nb_entity = block.nb_entity;
847
848 // Il peut y avoir plusieurs blocs pour le même groupe.
849 // On récupère le groupe s'il existe déjà.
850 IItemFamily* cell_family = mesh->cellFamily();
851 CellGroup cell_group = cell_family->findGroup(group_name, true);
852
853 UniqueArray<Int32> cells_id(nb_entity); // Numéro de la face dans le maillage \a mesh
854
855 cell_family->itemsUniqueIdToLocalId(cells_id, block.uids);
856
857 info(4) << "Adding " << cells_id.size() << " cells from block index=" << block.index
858 << " to group '" << cell_group.name() << "'";
859 cell_group.addItems(cells_id);
860}
861
862/*---------------------------------------------------------------------------*/
863/*---------------------------------------------------------------------------*/
864
865void MshMeshReader::
866_addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block, const String& group_name)
867{
868 const Int32 nb_entity = block.nb_entity;
869
870 // Il peut y avoir plusieurs blocs pour le même groupe.
871 // On récupère le groupe s'il existe déjà.
872 IItemFamily* node_family = mesh->nodeFamily();
873 NodeGroup node_group = node_family->findGroup(group_name, true);
874
875 UniqueArray<Int32> nodes_id(nb_entity);
876
877 node_family->itemsUniqueIdToLocalId(nodes_id, block.uids);
878
879 info(4) << "Adding " << nodes_id.size() << " nodes from block index=" << block.index
880 << " to group '" << node_group.name() << "'";
881
882 if (nb_entity<10){
883 info(4) << "Nodes UIDS=" << block.uids;
884 info(4) << "Nodes LIDS=" << nodes_id;
885 }
886 node_group.addItems(nodes_id);
887
888 if (nb_entity<10){
889 VariableNodeReal3& coords(mesh->nodesCoordinates());
890 ENUMERATE_(Node,inode,node_group){
891 info(4) << "Node id=" << ItemPrinter(*inode) << " coord=" << coords[inode];
892 }
893 }
894}
895
896/*---------------------------------------------------------------------------*/
897/*---------------------------------------------------------------------------*/
898/*
899 * $PhysicalNames // same as MSH version 2
900 * numPhysicalNames(ASCII int)
901 * dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max)
902 * ...
903 * $EndPhysicalNames
904 */
905void MshMeshReader::
906_readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info)
907{
908 String quote_mark = "\"";
909 Int32 nb_name = ios_file.getInteger();
910 info() << "nb_physical_name=" << nb_name;
911 ios_file.getNextLine();
912 for (Int32 i = 0; i < nb_name; ++i) {
913 Int32 dim = ios_file.getInteger();
914 Int32 tag = ios_file.getInteger();
915 String s = ios_file.getNextLine();
916 if (dim < 0 || dim > 3)
917 ARCANE_FATAL("Invalid value for physical name dimension dim={0}", dim);
918 // Les noms des groupes peuvent commencer par des espaces et contiennent
919 // des guillemets qu'il faut supprimer.
921 if (s.startsWith(quote_mark))
922 s = s.substring(1);
923 if (s.endsWith(quote_mark))
924 s = s.substring(0, s.length() - 1);
925 mesh_info.physical_name_list.add(dim, tag, s);
926 info(4) << "[PhysicalName] index=" << i << " dim=" << dim << " tag=" << tag << " name='" << s << "'";
927 }
928 StringView s = ios_file.getNextLine();
929 if (s != "$EndPhysicalNames")
930 ARCANE_FATAL("found '{0}' and expected '$EndPhysicalNames'", s);
931}
932
933/*---------------------------------------------------------------------------*/
934/*---------------------------------------------------------------------------*/
935
968{
969 Int32 nb_dim_item[4];
970 nb_dim_item[0] = ios_file.getInteger();
971 nb_dim_item[1] = ios_file.getInteger();
972 nb_dim_item[2] = ios_file.getInteger();
973 nb_dim_item[3] = ios_file.getInteger();
974 info(4) << "[Entities] nb_0d=" << nb_dim_item[0] << " nb_1d=" << nb_dim_item[1]
975 << " nb_2d=" << nb_dim_item[2] << " nb_3d=" << nb_dim_item[3];
976 // Après le format, on peut avoir les entités mais cela est optionnel
977 // Si elles sont présentes, on lit le fichier jusqu'à la fin de cette section.
978 StringView next_line = ios_file.getNextLine();
979 for (Int32 i = 0; i < nb_dim_item[0]; ++i) {
980 Int32 tag = ios_file.getInteger();
981 Real x = ios_file.getReal();
982 Real y = ios_file.getReal();
983 Real z = ios_file.getReal();
984 Int32 num_physical_tag = ios_file.getInteger();
985 if (num_physical_tag > 1)
986 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
987 Int32 physical_tag = -1;
988 if (num_physical_tag == 1)
989 physical_tag = ios_file.getInteger();
990 info(4) << "[Entities] point tag=" << tag << " x=" << x << " y=" << y << " z=" << z << " phys_tag=" << physical_tag;
991 mesh_info.entities_nodes_list.add(MeshV4EntitiesNodes(tag, physical_tag));
992 next_line = ios_file.getNextLine();
993 }
994
995 for (Int32 dim = 1; dim <= 3; ++dim) {
996 for (Int32 i = 0; i < nb_dim_item[dim]; ++i) {
997 Int32 tag = ios_file.getInteger();
998 Real min_x = ios_file.getReal();
999 Real min_y = ios_file.getReal();
1000 Real min_z = ios_file.getReal();
1001 Real max_x = ios_file.getReal();
1002 Real max_y = ios_file.getReal();
1003 Real max_z = ios_file.getReal();
1004 Int32 num_physical_tag = ios_file.getInteger();
1005 if (num_physical_tag > 1)
1006 ARCANE_FATAL("NotImplemented numPhysicalTag>1 (n={0})", num_physical_tag);
1007 Int32 physical_tag = -1;
1008 if (num_physical_tag == 1)
1009 physical_tag = ios_file.getInteger();
1010 Int32 num_bounding_group = ios_file.getInteger();
1011 for (Int32 k = 0; k < num_bounding_group; ++k) {
1012 [[maybe_unused]] Int32 group_tag = ios_file.getInteger();
1013 }
1014 mesh_info.entities_with_nodes_list[dim - 1].add(MeshV4EntitiesWithNodes(dim, tag, physical_tag));
1015 info(4) << "[Entities] dim=" << dim << " tag=" << tag
1016 << " min_x=" << min_x << " min_y=" << min_y << " min_z=" << min_z
1017 << " max_x=" << max_x << " max_y=" << max_y << " max_z=" << max_z
1018 << " phys_tag=" << physical_tag;
1019 next_line = ios_file.getNextLine();
1020 }
1021 }
1022 StringView s = ios_file.getNextLine();
1023 if (s != "$EndEntities")
1024 ARCANE_FATAL("found '{0}' and expected '$EndEntities'", s);
1025}
1026
1027/*---------------------------------------------------------------------------*/
1028/*---------------------------------------------------------------------------*/
1062{
1063 const char* func_name = "MshMeshReader::_readMeshFromNewMshFile()";
1064 info() << "[_readMeshFromNewMshFile] New native mesh file format detected";
1066#define MSH_BINARY_TYPE 1
1067
1068 Real version = ios_file.getReal();
1069 if (version == 2.0)
1070 m_version = 2;
1071 else if (version == 4.1)
1072 m_version = 4;
1073 else
1074 ARCANE_THROW(IOException, "Wrong msh file version '{0}'. Only versions '2.0' or '4.1' are supported", version);
1075 info() << "Msh mesh_major_version=" << m_version;
1076 Integer file_type = ios_file.getInteger(); // is an integer equal to 0 in the ASCII file format, equal to 1 for the binary format
1077 if (file_type == MSH_BINARY_TYPE)
1078 ARCANE_THROW(IOException, "Binary mode is not supported!");
1079
1080 Integer data_size = ios_file.getInteger(); // is an integer equal to the size of the floating point numbers used in the file
1081 ARCANE_UNUSED(data_size);
1082
1083 if (file_type == MSH_BINARY_TYPE) {
1084 (void)ios_file.getInteger(); // is an integer of value 1 written in binary form
1085 }
1086 ios_file.getNextLine(); // Skip current \n\r
1087
1088 // $EndMeshFormat
1089 if (!ios_file.lookForString("$EndMeshFormat"))
1090 ARCANE_THROW(IOException, "$EndMeshFormat not found");
1091
1092 // TODO: Les différentes sections ($Nodes, $Entitites, ...) peuvent
1093 // être dans n'importe quel ordre (à part $Nodes qui doit être avant $Elements)
1094 // Faire un méthode qui gère cela.
1095
1096 StringView next_line = ios_file.getNextLine();
1097 // Noms des groupes
1098 if (next_line == "$PhysicalNames") {
1099 _readPhysicalNames(ios_file, mesh_info);
1100 next_line = ios_file.getNextLine();
1101 }
1102 // Après le format, on peut avoir les entités mais cela est optionnel
1103 // Si elles sont présentes, on lit le fichier jusqu'à la fin de cette section.
1104 if (next_line == "$Entities") {
1106 next_line = ios_file.getNextLine();
1107 }
1108 // $Nodes
1109 if (next_line != "$Nodes")
1110 ARCANE_THROW(IOException, "Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1111
1112 // Fetch nodes number and the coordinates
1113 if (file_type != MSH_BINARY_TYPE) {
1114 if (m_version == 2) {
1115 if (_readNodesFromAsciiMshV2File(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1116 ARCANE_THROW(IOException, "Ascii nodes coords error");
1117 }
1118 else if (m_version == 4) {
1120 ARCANE_THROW(IOException, "Ascii nodes coords error");
1121 }
1122 }
1123 else {
1124 if (_readNodesFromBinaryMshFile(ios_file, mesh_info.node_coords) != IMeshReader::RTOk)
1125 ARCANE_THROW(IOException, "Binary nodes coords error");
1126 }
1127 // $EndNodes
1128 if (!ios_file.lookForString("$EndNodes"))
1129 ARCANE_THROW(IOException, "$EndNodes not found");
1130
1131 // $Elements
1132 Integer mesh_dimension = -1;
1133 {
1134 if (!ios_file.lookForString("$Elements"))
1135 ARCANE_THROW(IOException, "$Elements not found");
1136
1137 if (m_version == 2)
1138 mesh_dimension = _readElementsFromAsciiMshV2File(ios_file, mesh_info);
1139 else if (m_version == 4)
1141
1142 // $EndElements
1143 if (!ios_file.lookForString("$EndElements"))
1144 throw IOException(func_name, "$EndElements not found");
1145 }
1146
1147 info() << "Computed mesh dimension = " << mesh_dimension;
1148
1149 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
1150 pmesh->setDimension(mesh_dimension);
1151
1152 IParallelMng* pm = mesh->parallelMng();
1153 bool is_parallel = pm->isParallel();
1154 Int32 rank = mesh->meshPartInfo().partRank();
1155 // En parallèle, seul le rang 0 lit le maillage
1156 bool is_read_items = !(is_parallel && rank != 0);
1157 _allocateCells(mesh, mesh_info, is_read_items);
1158 _allocateGroups(mesh, mesh_info, is_read_items);
1159 return IMeshReader::RTOk;
1160}
1161
1162/*---------------------------------------------------------------------------*/
1163/*---------------------------------------------------------------------------*/
1169readMeshFromMshFile(IMesh* mesh, const String& filename)
1170{
1171 info() << "Trying to read 'msh' file '" << filename << "'";
1172 std::ifstream ifile(filename.localstr());
1173 if (!ifile) {
1174 error() << "Unable to read file '" << filename << "'";
1175 return IMeshReader::RTError;
1176 }
1178 String mesh_format_str = ios_file.getNextLine(); // Comments do not seem to be implemented in .msh files
1179 if (IosFile::isEqualString(mesh_format_str, "$MeshFormat"))
1180 return _readMeshFromNewMshFile(mesh, ios_file);
1181 info() << "The file does not begin with '$MeshFormat' returning RTError";
1182 return IMeshReader::RTError;
1183}
1184
1185/*---------------------------------------------------------------------------*/
1186/*---------------------------------------------------------------------------*/
1187
1188/*---------------------------------------------------------------------------*/
1189/*---------------------------------------------------------------------------*/
1190
1191extern "C++" Ref<IMshMeshReader>
1192createMshParallelMeshReader(ITraceMng* tm);
1193
1194namespace
1195{
1196
1199{
1200 bool use_new_reader = true;
1201 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_USE_PARALLEL_MSH_READER", true))
1202 use_new_reader = (v.value()!=0);
1203 Ref<IMshMeshReader> reader;
1204 if (use_new_reader)
1205 reader = createMshParallelMeshReader(tm);
1206 else
1207 reader = createMshMeshReader(tm);
1208 return reader;
1209}
1210
1211}
1212
1213/*---------------------------------------------------------------------------*/
1214/*---------------------------------------------------------------------------*/
1215
1217: public AbstractService
1218, public IMeshReader
1219{
1220 public:
1221
1224 {
1225 }
1226
1227 public:
1228
1229 void build() override {}
1230
1231 bool allowExtension(const String& str) override { return str == "msh"; }
1232
1234 const String& file_name, const String& dir_name,
1235 bool use_internal_partition) override
1236 {
1237 ARCANE_UNUSED(dir_name);
1238 ARCANE_UNUSED(use_internal_partition);
1239 ARCANE_UNUSED(mesh_node);
1240
1242 return reader->readMeshFromMshFile(mesh, file_name);
1243 }
1244};
1245
1246/*---------------------------------------------------------------------------*/
1247/*---------------------------------------------------------------------------*/
1248
1249ARCANE_REGISTER_SERVICE(MshMeshReaderService,
1250 ServiceProperty("MshNewMeshReader", ST_SubDomain),
1251 ARCANE_SERVICE_INTERFACE(IMeshReader));
1252
1253/*---------------------------------------------------------------------------*/
1254/*---------------------------------------------------------------------------*/
1255
1257: public AbstractService
1258, public ICaseMeshReader
1259{
1260 public:
1261
1263 : public IMeshBuilder
1264 {
1265 public:
1266
1268 : m_trace_mng(tm)
1269 , m_read_info(read_info)
1270 {}
1271
1272 public:
1273
1275 {
1276 ARCANE_UNUSED(build_info);
1277 }
1279 {
1280 Ref<IMshMeshReader> reader = _internalCreateReader(m_trace_mng);
1281 String fname = m_read_info.fileName();
1282 m_trace_mng->info() << "Msh Reader (ICaseMeshReader) file_name=" << fname;
1283 IMeshReader::eReturnType ret = reader->readMeshFromMshFile(pm, fname);
1284 if (ret != IMeshReader::RTOk)
1285 ARCANE_FATAL("Can not read MSH File");
1286 }
1287
1288 private:
1289
1290 ITraceMng* m_trace_mng;
1291 CaseMeshReaderReadInfo m_read_info;
1292 };
1293
1294 public:
1295
1296 explicit MshCaseMeshReader(const ServiceBuildInfo& sbi)
1298 {}
1299
1300 public:
1301
1303 {
1304 IMeshBuilder* builder = nullptr;
1305 if (read_info.format() == "msh")
1306 builder = new Builder(traceMng(), read_info);
1307 return makeRef(builder);
1308 }
1309};
1310
1311/*---------------------------------------------------------------------------*/
1312/*---------------------------------------------------------------------------*/
1313
1314ARCANE_REGISTER_SERVICE(MshCaseMeshReader,
1315 ServiceProperty("MshCaseMeshReader", ST_SubDomain),
1316 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
1317
1318/*---------------------------------------------------------------------------*/
1319/*---------------------------------------------------------------------------*/
1320
1321} // End namespace Arcane
1322
1323/*---------------------------------------------------------------------------*/
1324/*---------------------------------------------------------------------------*/
#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.
Informations nécessaires pour la lecture d'un fichier de maillage.
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
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
virtual const MeshPartInfo & meshPartInfo() const =0
Informations sur les parties du maillage.
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.
Routines des Lecture/Ecriture d'un fichier.
Definition IosFile.h:30
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
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.
Lecteur de fichiers de maillage au format msh.
eReturnType readMeshFromMshFile(IMesh *mesh, const String &file_name) override
eReturnType _readNodesFromAsciiMshV4File(IosFile &, MeshInfo &mesh_info)
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,...)
Classe gérant un vecteur de réel de dimension 3.
Definition Real3.h:132
Structure contenant les informations pour créer un service.
Noeud d'un arbre DOM.
Definition XmlNode.h:51
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Exception lorsqu'une opération n'est pas supportée.
Vue sur une chaîne de caractères UTF-8.
Definition StringView.h:47
Chaîne de caractères unicode.
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
Definition String.cc:452
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:227
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage info() const
Flot pour un message d'information.
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 -*-
@ 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:638
Int32 Integer
Type représentant un entier.
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.