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"
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"
55#include "arcane/std/internal/IosFile.h"
56#include "arcane/std/internal/IosGmsh.h"
123 Int32 entity_tag = -1;
140 bool isNull()
const {
return dimension == (-1); }
141 Int32 dimension = -1;
152 : m_physical_names(4)
154 void add(Int32 dimension, Int32 tag,
String name)
160 for (
auto& x : m_physical_names[dimension])
200 : node_coords_map(5000,
true)
207 for (
auto& x : entities_with_nodes_list[dimension - 1])
215 for (
auto& x : entities_nodes_list)
223 Integer nb_elements = 0;
224 Integer nb_cell_node = 0;
247 Integer m_version = 0;
260 Integer _switchMshType(Integer, Integer&);
268extern "C++" Ref<IMshMeshReader>
269createMshMeshReader(ITraceMng* tm)
271 return makeRef<IMshMeshReader>(
new MshMeshReader(tm));
278_switchMshType(Integer mshElemType, Integer& nNodes)
280 switch (mshElemType) {
286 info() <<
"Could not decode IT_NullType with nNodes=" << nNodes;
287 throw IOException(
"_switchMshType",
"Could not decode IT_NullType with nNodes");
304 return IT_Tetraedron4;
307 return IT_Hexaedron8;
310 return IT_Pentaedron6;
316 return IT_Heptaedron10;
319 return IT_Octaedron12;
335 ARCANE_THROW(NotSupportedException,
"Unknown GMSH element type '{0}'", mshElemType);
344_readNodesFromAsciiMshV2File(IosFile& ios_file, Array<Real3>& node_coords)
347 info() <<
"[_readNodesFromAsciiMshV2File] Looking for number-of-nodes";
348 Integer nb_node = ios_file.getInteger();
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) {
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));
361 ios_file.getNextLine();
390 Integer nb_entity =
ios_file.getInteger();
397 info() <<
"[Nodes] nb_entity=" << nb_entity
422 for (Integer i = 0; i <
nb_node2; ++i) {
427 for (Integer i = 0; i <
nb_node2; ++i) {
443Integer MshMeshReader::
468 info() <<
"We hit the case the number of nodes is encoded (number_of_nodes=" <<
number_of_nodes <<
")";
470 Integer cell_type = _switchMshType(elm_type, number_of_nodes);
473 if (number_of_nodes < 3) {
474 for (Integer j = 0; j < number_of_nodes; ++j)
475 ios_file.getInteger();
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;
484 for (Integer j = 0; j < number_of_nodes; ++j) {
486 Integer id = ios_file.getInteger();
488 it_starts_at_zero =
true;
489 mesh_info.cells_connectivity.add(
id);
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;
497 ios_file.getNextLine();
552 Integer entity_tag =
ios_file.getInteger();
556 Integer item_nb_node = 0;
557 Integer item_type = _switchMshType(
entity_type, item_nb_node);
559 info(4) <<
"[Elements] index=" << block.index <<
" entity_dim=" <<
entity_dim
560 <<
" entity_tag=" << entity_tag
562 <<
" item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
565 block.item_type = item_type;
566 block.item_nb_node = item_nb_node;
568 block.entity_tag = entity_tag;
585 for (Integer
j = 0;
j < item_nb_node; ++
j)
586 block.connectivity.add(
ios_file.getInt64());
608 info(4) <<
"Keeping block index=" << block.index;
610 Integer item_type = block.item_type;
611 Integer item_nb_node = block.item_nb_node;
613 for (Integer i = 0; i < block.nb_entity; ++i) {
615 mesh_info.cells_nb_node.add(item_nb_node);
617 auto v = block.connectivity.subView(i * item_nb_node, item_nb_node);
618 mesh_info.cells_connectivity.addRange(v);
637 ARCANE_UNUSED(node_coords);
645_allocateCells(IMesh* mesh, MeshInfo& mesh_info,
bool is_read_items)
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;
653 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
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);
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;
673 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
674 info() <<
"## Allocating ##";
677 pmesh->allocateCells(nb_elements, cells_infos,
false);
679 pmesh->allocateCells(0, UniqueArray<Int64>(0),
false);
681 info() <<
"## Ending ##";
682 pmesh->endAllocate();
683 info() <<
"## Done ##";
688 bool has_map = mesh_info.node_coords.empty();
692 nodes_coord_var[node] = mesh_info.node_coords_map.lookupValue(node.uniqueId().asInt64());
694 nodes_coord_var.synchronize();
698 nodes_coord_var[node] = mesh_info.node_coords.item(node->uniqueId().asInt32());
708_allocateGroups(IMesh* mesh, MeshInfo& mesh_info,
bool is_read_items)
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;
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";
722 MeshPhysicalName physical_name;
724 if (block_dim == 0) {
725 MeshV4EntitiesNodes* entity = mesh_info.findNodeEntities(block_entity_tag);
727 info(5) <<
"[Groups] Skipping block index=" << block_index
728 <<
" because entity tag is invalid";
731 Int32 entity_physical_tag = entity->physical_tag;
732 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
735 MeshV4EntitiesWithNodes* entity = mesh_info.findEntities(block_dim, block_entity_tag);
737 info(5) <<
"[Groups] Skipping block index=" << block_index
738 <<
" because entity tag is invalid";
741 Int32 entity_physical_tag = entity->physical_tag;
742 physical_name = mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
744 if (physical_name.isNull()) {
745 info(5) <<
"[Groups] Skipping block index=" << block_index
746 <<
" because entity physical tag is invalid";
749 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
750 <<
" name='" << physical_name.name <<
"'";
751 if (block_dim == mesh_dim) {
753 _addCellGroup(mesh, block, physical_name.name);
755 mesh->cellFamily()->findGroup(physical_name.name,
true);
757 else if (block_dim == face_dim) {
759 _addFaceGroup(mesh, block, physical_name.name);
761 mesh->faceFamily()->findGroup(physical_name.name,
true);
765 _addNodeGroup(mesh, block, physical_name.name);
767 mesh->nodeFamily()->findGroup(physical_name.name,
true);
776_addFaceGroup(IMesh* mesh, MeshV4ElementsBlock& block,
const String& group_name)
778 const Int32 nb_entity = block.nb_entity;
782 FaceGroup face_group = mesh->faceFamily()->findGroup(group_name,
true);
784 UniqueArray<Int32> faces_id(nb_entity);
786 const Int32 item_nb_node = block.item_nb_node;
787 const Int32 face_nb_node = nb_entity * item_nb_node;
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;
794 UniqueArray<Int64> orig_nodes_id(item_nb_node);
795 UniqueArray<Integer> face_nodes_index(item_nb_node);
797 IItemFamily* node_family = mesh->nodeFamily();
798 NodeInfoListView mesh_nodes(node_family);
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];
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;
813 node_family->itemsUniqueIdToLocalId(faces_first_node_local_id, faces_first_node_unique_id);
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);
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",
831 faces_id[i_face] = face.localId();
833 faces_nodes_unique_id_index += n;
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);
844_addCellGroup(IMesh* mesh, MeshV4ElementsBlock& block,
const String& group_name)
846 const Int32 nb_entity = block.nb_entity;
850 IItemFamily* cell_family = mesh->cellFamily();
851 CellGroup cell_group = cell_family->findGroup(group_name,
true);
853 UniqueArray<Int32> cells_id(nb_entity);
855 cell_family->itemsUniqueIdToLocalId(cells_id, block.uids);
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);
866_addNodeGroup(IMesh* mesh, MeshV4ElementsBlock& block,
const String& group_name)
868 const Int32 nb_entity = block.nb_entity;
872 IItemFamily* node_family = mesh->nodeFamily();
873 NodeGroup node_group = node_family->findGroup(group_name,
true);
875 UniqueArray<Int32> nodes_id(nb_entity);
877 node_family->itemsUniqueIdToLocalId(nodes_id, block.uids);
879 info(4) <<
"Adding " << nodes_id.size() <<
" nodes from block index=" << block.index
880 <<
" to group '" << node_group.name() <<
"'";
883 info(4) <<
"Nodes UIDS=" << block.uids;
884 info(4) <<
"Nodes LIDS=" << nodes_id;
886 node_group.addItems(nodes_id);
891 info(4) <<
"Node id=" << ItemPrinter(*inode) <<
" coord=" << coords[inode];
906_readPhysicalNames(IosFile& ios_file, MeshInfo& mesh_info)
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);
921 if (s.startsWith(quote_mark))
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 <<
"'";
928 StringView s = ios_file.getNextLine();
929 if (s !=
"$EndPhysicalNames")
930 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
987 Int32 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;
1007 Int32 physical_tag = -1;
1009 physical_tag =
ios_file.getInteger();
1015 info(4) <<
"[Entities] dim=" <<
dim <<
" tag=" << tag
1018 <<
" phys_tag=" << physical_tag;
1023 if (s !=
"$EndEntities")
1024 ARCANE_FATAL(
"found '{0}' and expected '$EndEntities'", s);
1063 const char* func_name =
"MshMeshReader::_readMeshFromNewMshFile()";
1064 info() <<
"[_readMeshFromNewMshFile] New native mesh file format detected";
1066#define MSH_BINARY_TYPE 1
1071 else if (version == 4.1)
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;
1089 if (!
ios_file.lookForString(
"$EndMeshFormat"))
1114 if (m_version == 2) {
1118 else if (m_version == 4) {
1128 if (!
ios_file.lookForString(
"$EndNodes"))
1134 if (!
ios_file.lookForString(
"$Elements"))
1139 else if (m_version == 4)
1143 if (!
ios_file.lookForString(
"$EndElements"))
1144 throw IOException(func_name,
"$EndElements not found");
1171 info() <<
"Trying to read 'msh' file '" << filename <<
"'";
1174 error() <<
"Unable to read file '" << filename <<
"'";
1181 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
1205 reader = createMshParallelMeshReader(
tm);
1207 reader = createMshMeshReader(
tm);
1242 return reader->readMeshFromMshFile(mesh,
file_name);
1282 m_trace_mng->
info() <<
"Msh Reader (ICaseMeshReader) file_name=" <<
fname;
1307 return makeRef(builder);
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
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.
eReturnType
Types des codes de retour d'une lecture ou écriture.
@ RTError
Erreur lors de l'opération.
@ RTOk
Opération effectuée avec succès.
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.
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.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
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.
Structure contenant les informations pour créer un service.
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.
Chaîne de caractères unicode.
static String collapseWhiteSpace(const String &rhs)
Effectue une normalisation des caractères espaces.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Classe d'accès aux traces.
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.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
ItemGroupT< Face > FaceGroup
Groupe de faces.
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
#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.
Int32 Integer
Type représentant un entier.
Infos du bloc '$PhysicalNames'.
Infos sur un nom physique.
Infos d'un bloc pour $Elements pour la version 4.
Int32 nb_entity
Nombre d'entités du bloc.
Int32 dimension
Dimension de l'entité
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 0D.
Infos pour les entités 1D, 2D et 3D.