14#include "arcane/utils/TraceAccessor.h"
15#include "arcane/utils/Array.h"
16#include "arcane/utils/IOException.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/Ref.h"
19#include "arcane/utils/NotSupportedException.h"
20#include "arcane/utils/Real3.h"
21#include "arcane/utils/OStringStream.h"
22#include "arcane/utils/FixedArray.h"
23#include "arcane/utils/PlatformUtils.h"
24#include "arcane/utils/CheckedConvert.h"
26#include "arcane/core/IMeshReader.h"
27#include "arcane/core/IPrimaryMesh.h"
28#include "arcane/core/IItemFamily.h"
29#include "arcane/core/ItemGroup.h"
30#include "arcane/core/VariableTypes.h"
31#include "arcane/core/IParallelMng.h"
35#include "arcane/std/internal/IosFile.h"
36#include "arcane/std/internal/IosGmsh.h"
99 Int64 entity_tag = -1;
115 bool isNull()
const {
return dimension == (-1); }
116 Int32 dimension = -1;
126 void add(Int32 dimension, Int64 tag,
String name)
132 for (
auto& x : m_physical_names[dimension])
175 for (
auto& x : entities_with_nodes_list[dimension - 1])
182 for (
auto& x : entities_nodes_list)
201 Real3 m_node_min_bounding_box;
202 Real3 m_node_max_bounding_box;
219 IMesh* m_mesh =
nullptr;
221 Int32 m_master_io_rank = A_NULL_RANK;
222 bool m_is_parallel =
false;
224 MeshInfo m_mesh_info;
235 void _readMeshFromFile();
237 void _allocateCells();
238 void _allocateGroups();
245 Int32 _switchMshType(Int64, Int32&)
const;
246 void _readPhysicalNames();
250 Int32 _getIntegerAndBroadcast();
256 void _goToNextLine();
270 inline std::pair<Int64, Int64>
293 s = f->getNextLine();
296 info() <<
"BroadcastNextLine: " << s;
297 m_parallel_mng->broadcastString(s, m_master_io_rank);
299 info() <<
"GetNextLine: " << s;
306Int32 MshParallelMeshReader::
307_getIntegerAndBroadcast()
312 v[0] = f->getInteger();
314 m_parallel_mng->broadcast(v.view(), m_master_io_rank);
322void MshParallelMeshReader::
323_getInt64ArrayAndBroadcast(ArrayView<Int64> values)
325 IosFile* f = m_ios_file.get();
327 for (
Int64& v : values)
330 m_parallel_mng->broadcast(values, m_master_io_rank);
336Real3 MshParallelMeshReader::
339 IosFile* f = m_ios_file.get();
340 Real x = f->getReal();
341 Real y = f->getReal();
342 Real z = f->getReal();
349void MshParallelMeshReader::
352 if (m_ios_file.get())
353 m_ios_file->getNextLine();
359Int32 MshParallelMeshReader::
360_switchMshType(
Int64 mshElemType,
Int32& nNodes)
const
362 switch (mshElemType) {
368 info() <<
"Could not decode IT_NullType with nNodes=" << nNodes;
369 throw IOException(
"_switchMshType",
"Could not decode IT_NullType with nNodes");
386 return IT_Tetraedron4;
389 return IT_Hexaedron8;
392 return IT_Pentaedron6;
398 return IT_Heptaedron10;
401 return IT_Octaedron12;
417 ARCANE_THROW(NotSupportedException,
"Unknown GMSH element type '{0}'", mshElemType);
430 Real min_value = -max_value;
438 m_mesh_info.m_node_min_bounding_box =
min_box;
439 m_mesh_info.m_node_max_bounding_box =
max_box;
461 for (Int64 i = 0; i <
nb_node; ++i) {
463 part = std::clamp(part, 0,
m_nb_part - 1);
469 for (Int64 i = 0; i <
nb_node; ++i) {
509 _getInt64ArrayAndBroadcast(
nodes_info.view());
521 info() <<
"[Nodes] nb_entity=" << nb_entity
526 <<
" nb_rank=" << m_parallel_mng->
commSize();
538void MshParallelMeshReader::
586 for (Integer i = 0; i < nb_to_read; ++i) {
588 nodes_uids[i] = ios_file->getInt64();
591 if (dest_rank != m_master_io_rank) {
592 pm->send(nodes_uids, dest_rank);
595 else if (my_rank == dest_rank) {
596 pm->
recv(nodes_uids, m_master_io_rank);
600 if (my_rank == dest_rank) {
609 info() <<
"Reading COORDS part i=" << i_part <<
" dest_rank=" << dest_rank <<
" nb_to_read=" << nb_to_read;
610 if (my_rank == dest_rank || my_rank == m_master_io_rank) {
611 nodes_coordinates.resize(nb_to_read);
617 for (Integer i = 0; i < nb_to_read; ++i) {
618 nodes_coordinates[i] = _getReal3();
621 if (dest_rank != m_master_io_rank) {
622 pm->send(nodes_coordinates, dest_rank);
625 else if (my_rank == dest_rank) {
626 pm->
recv(nodes_coordinates, m_master_io_rank);
630 if (my_rank == dest_rank) {
661 info() <<
"Reading block part i_part=" <<
i_part
672 for (Int64 i = 0; i <
nb_uid; ++i) {
675 for (Int32
j = 0;
j < item_nb_node; ++
j)
676 connectivities[(i * item_nb_node) +
j] =
ios_file->getInt64();
684 pm->
recv(uids, m_master_io_rank);
685 pm->
recv(connectivities, m_master_io_rank);
763 _getInt64ArrayAndBroadcast(
block_info.view());
770 Integer item_nb_node = 0;
771 Integer item_type = _switchMshType(
entity_type, item_nb_node);
773 info() <<
"[Elements] index=" << block.index <<
" entity_dim=" <<
entity_dim
774 <<
" entity_tag=" << entity_tag
776 <<
" item_type=" << item_type <<
" item_nb_node=" << item_nb_node;
779 block.item_type = item_type;
780 block.item_nb_node = item_nb_node;
782 block.entity_tag = entity_tag;
818 _computeOwnCells(block);
839 pm->broadcast(view, dest_rank);
849 template <
typename DataType>
inline ArrayView<DataType>
850 _broadcastArray(IParallelMng* pm, UniqueArray<DataType>& values,
851 UniqueArray<DataType>& work_values,
Int32 dest_rank)
856 if (dest_rank == my_rank)
857 size = values.size();
858 pm->broadcast(ArrayView<Int64>(1, &size), dest_rank);
859 return _broadcastArrayWithSize(pm, values, work_values, dest_rank, size);
864void MshParallelMeshReader::
865_computeOwnCells(MeshV4ElementsBlock& block)
869 IParallelMng* pm = m_parallel_mng;
872 const Int32 item_type = block.item_type;
873 const Int32 item_nb_node = block.item_nb_node;
875 UniqueArray<Int64> connectivities;
876 UniqueArray<Int64> uids;
877 UniqueArray<Int32> nodes_rank;
880 for (
Int32 i_part = 0; i_part < nb_part; ++i_part) {
883 ArrayView<Int64> connectivities_view = _broadcastArray(pm, block.connectivities, connectivities, dest_rank);
884 ArrayView<Int64> uids_view = _broadcastArray(pm, block.uids, uids, dest_rank);
886 Int32 nb_item = uids_view.size();
887 nodes_rank.resize(nb_item);
893 for (
Int32 i = 0; i < nb_item; ++i) {
894 Int64 first_node_uid = connectivities_view[i * item_nb_node];
899 Int32 rank = x->second;
900 nodes_rank[i] = rank;
902 pm->
reduce(Parallel::ReduceMax, nodes_rank);
903 for (
Int32 i = 0; i < nb_item; ++i) {
904 const Int32 rank = nodes_rank[i];
910 m_mesh_info.cells_type.
add(item_type);
911 m_mesh_info.cells_nb_node.
add(item_nb_node);
912 m_mesh_info.cells_uid.
add(uids_view[i]);
913 auto v = connectivities_view.subView(i * item_nb_node, item_nb_node);
914 m_mesh_info.cells_connectivity.
addRange(v);
958 for (Int32 i = 0; i <
nb_item; ++i) {
969void MshParallelMeshReader::
974 IMesh* mesh = m_mesh;
975 Integer nb_elements = m_mesh_info.cells_type.
size();
976 info() <<
"nb_of_elements=cells_type.size()=" << nb_elements;
977 Integer nb_cell_node = m_mesh_info.cells_connectivity.
size();
978 info() <<
"nb_cell_node=cells_connectivity.size()=" << nb_cell_node;
981 info() <<
"Building cells, nb_cell=" << nb_elements <<
" nb_cell_node=" << nb_cell_node;
989 for (Integer i = 0; i < nb_elements; ++i) {
991 Integer
cell_type = m_mesh_info.cells_type[i];
992 Int64 cell_uid = m_mesh_info.cells_uid[i];
1002 info() <<
"## Allocating ##";
1003 pmesh->allocateCells(nb_elements, cells_infos,
false);
1004 info() <<
"## Ending ##";
1005 pmesh->endAllocate();
1006 info() <<
"## Done ##";
1015void MshParallelMeshReader::
1018 IMesh* mesh = m_mesh;
1019 Int32 mesh_dim = mesh->dimension();
1020 Int32 face_dim = mesh_dim - 1;
1021 UniqueArray<MeshV4EntitiesWithNodes> entity_list;
1022 UniqueArray<MeshPhysicalName> physical_name_list;
1023 for (MeshV4ElementsBlock& block : m_mesh_info.blocks) {
1024 entity_list.clear();
1025 physical_name_list.clear();
1026 Int32 block_index = block.index;
1027 Int32 block_dim = block.dimension;
1030 Int64 block_entity_tag = block.entity_tag;
1031 if (block_entity_tag < 0) {
1032 info(5) <<
"[Groups] Skipping block index=" << block_index <<
" because it has no entity";
1035 if (block_dim == 0) {
1036 const MeshV4EntitiesNodes* entity = m_mesh_info.findNodeEntities(block_entity_tag);
1038 info(5) <<
"[Groups] Skipping block index=" << block_index
1039 <<
" because entity tag is invalid";
1042 Int64 entity_physical_tag = entity->physical_tag;
1043 MeshPhysicalName physical_name = m_mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
1044 physical_name_list.add(physical_name);
1047 m_mesh_info.findEntities(block_dim, block_entity_tag, entity_list);
1048 for (
const MeshV4EntitiesWithNodes& x : entity_list) {
1049 Int64 entity_physical_tag = x.physical_tag;
1050 MeshPhysicalName physical_name = m_mesh_info.physical_name_list.find(block_dim, entity_physical_tag);
1051 physical_name_list.add(physical_name);
1054 for (
const MeshPhysicalName& physical_name : physical_name_list) {
1055 if (physical_name.isNull()) {
1056 info(5) <<
"[Groups] Skipping block index=" << block_index
1057 <<
" because entity physical tag is invalid";
1060 info(4) <<
"[Groups] Block index=" << block_index <<
" dim=" << block_dim
1061 <<
" name='" << physical_name.name <<
"'";
1062 if (block_dim == mesh_dim) {
1065 else if (block_dim == face_dim) {
1096void MshParallelMeshReader::
1100 IMesh* mesh = m_mesh;
1101 const Int32 nb_entity = connectivities.size() / item_nb_node;
1125 for (Integer z = 0; z < item_nb_node; ++z)
1129 for (Integer z = 0; z < item_nb_node; ++z)
1137 faces_nodes_unique_id_index = 0;
1138 for (Integer i_face = 0; i_face < nb_entity; ++i_face) {
1139 const Integer n = item_nb_node;
1140 Int32 face_first_node_lid = faces_first_node_local_id[i_face];
1141 if (face_first_node_lid != NULL_ITEM_LOCAL_ID) {
1142 Int64ConstArrayView face_nodes_id(item_nb_node, &faces_nodes_unique_id[faces_nodes_unique_id_index]);
1143 Node current_node(mesh_nodes[faces_first_node_local_id[i_face]]);
1144 Face face = MeshUtils::getFaceFromNodesUnique(current_node, face_nodes_id);
1149 if (!m_is_parallel) {
1151 ostr() <<
"(Nodes:";
1152 for (Integer z = 0; z < n; ++z)
1153 ostr() <<
' ' << face_nodes_id[z];
1154 ostr() <<
" - " << current_node.localId() <<
")";
1155 ARCANE_FATAL(
"INTERNAL: MeshMeshReader face index={0} with nodes '{1}' is not in node/face connectivity",
1156 i_face, ostr.str());
1160 faces_id.add(face.localId());
1163 faces_nodes_unique_id_index += n;
1165 info(4) <<
"Adding " << faces_id.size() <<
" faces from block index=" << block_index
1166 <<
" to group '" << face_group.
name() <<
"'";
1190void MshParallelMeshReader::
1194 const Int32 nb_entity = uids.size();
1206 if (m_is_parallel) {
1212 info() <<
"Adding " << items_lid.size() <<
" items from block index=" << block_index
1213 <<
" to group '" << group_name <<
"' for family=" << family->
name();
1227void MshParallelMeshReader::
1230 String quote_mark =
"\"";
1231 Int32 nb_name = _getIntegerAndBroadcast();
1232 info() <<
"nb_physical_name=" << nb_name;
1236 for (
Int32 i = 0; i < nb_name; ++i) {
1237 Int32 dim = _getIntegerAndBroadcast();
1238 Int32 tag = _getIntegerAndBroadcast();
1240 if (dim < 0 || dim > 3)
1241 ARCANE_FATAL(
"Invalid value for physical name dimension dim={0}", dim);
1245 if (s.startsWith(quote_mark))
1247 if (s.endsWith(quote_mark))
1248 s = s.substring(0, s.length() - 1);
1249 m_mesh_info.physical_name_list.add(dim, tag, s);
1250 info(4) <<
"[PhysicalName] index=" << i <<
" dim=" << dim <<
" tag=" << tag <<
" name='" << s <<
"'";
1254 if (s !=
"$EndPhysicalNames")
1255 ARCANE_FATAL(
"found '{0}' and expected '$EndPhysicalNames'", s);
1312 ARCANE_FATAL(
"NotImplemented numPhysicalTag>1 (n={0}, index={1} xyz={2})",
1315 Int32 physical_tag = -1;
1317 physical_tag =
ios_file->getInteger();
1318 info(4) <<
"[Entities] point tag=" << tag <<
" pos=" <<
xyz <<
" phys_tag=" << physical_tag;
1323 m_parallel_mng->broadcast(
tag_info.view(), m_master_io_rank);
1330 _readOneEntity(
i_dim);
1333 if (s !=
"$EndEntities")
1334 ARCANE_FATAL(
"found '{0}' and expected '$EndEntities'", s);
1340void MshParallelMeshReader::
1364 Int32 physical_tag =
ios_file->getInteger();
1366 info(4) <<
"[Entities] z=" << z <<
" physical_tag=" << physical_tag;
1369 Int32 num_bounding_group = ios_file->getInteger();
1370 for (
Int32 k = 0; k < num_bounding_group; ++k) {
1371 [[maybe_unused]]
Int32 group_tag = ios_file->getInteger();
1373 info(4) <<
"[Entities] dim=" << entity_dim <<
" tag=" << tag
1374 <<
" min_pos=" << min_pos <<
" max_pos=" << max_pos
1375 <<
" nb_phys_tag=" << nb_physical_tag;
1378 m_parallel_mng->broadcast(dim_and_tag_info.view(), m_master_io_rank);
1382 Int64 tag = dim_and_tag_info[1];
1383 Int64 nb_physical_tag = dim_and_tag_info[2];
1384 for (
Int32 z = 0; z < nb_physical_tag; ++z) {
1385 Int64 physical_tag = dim_and_tag_info[3 + z];
1386 info(4) <<
"[Entities] adding info dim=" << entity_dim <<
" tag=" << tag
1387 <<
" physical_tag=" << physical_tag;
1388 m_mesh_info.entities_with_nodes_list[dim - 1].add(MeshV4EntitiesWithNodes(dim, tag, physical_tag));
1399void MshParallelMeshReader::
1402 IosFile* ios_file = m_ios_file.get();
1403 IMesh* mesh = m_mesh;
1404 info() <<
"Reading 'msh' file in parallel";
1405 const int MSH_BINARY_TYPE = 1;
1408 Real version = ios_file->getReal();
1410 ARCANE_THROW(IOException,
"Wrong msh file version '{0}'. Only version '4.1' is supported in parallel", version);
1411 Integer file_type = ios_file->getInteger();
1412 if (file_type == MSH_BINARY_TYPE)
1413 ARCANE_THROW(IOException,
"Binary mode is not supported!");
1415 Integer data_size = ios_file->getInteger();
1416 ARCANE_UNUSED(data_size);
1418 ios_file->getNextLine();
1421 if (!ios_file->lookForString(
"$EndMeshFormat"))
1431 if (next_line ==
"$PhysicalNames") {
1432 _readPhysicalNames();
1438 if (next_line ==
"$Entities") {
1443 if (next_line !=
"$Nodes")
1444 ARCANE_THROW(IOException,
"Unexpected string '{0}'. Valid values are '$Nodes'", next_line);
1450 if (ios_file && !ios_file->lookForString(
"$EndNodes"))
1454 if (ios_file && !ios_file->lookForString(
"$Elements"))
1460 if (ios_file && !ios_file->lookForString(
"$EndElements"))
1463 info() <<
"Computed mesh dimension = " << mesh_dimension;
1465 IPrimaryMesh* pmesh = mesh->toPrimaryMesh();
1466 pmesh->setDimension(mesh_dimension);
1480 info() <<
"Trying to read in parallel 'msh' file '" << filename;
1483 m_parallel_mng = pm;
1484 const Int32 nb_rank = pm->
commSize();
1501 bool is_readable = platform::isFileReadable(filename);
1505 error() <<
"Unable to read file '" << filename <<
"'";
1512 std::ifstream
ifile;
1521 _readMeshFromFile();
1525 info() <<
"The file does not begin with '$MeshFormat' returning RTError";
#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.
Informations sur le type flottant.
Interface d'une famille d'entités.
virtual ItemGroup findGroup(const String &name) const =0
Recherche un groupe.
virtual String name() const =0
Nom de la famille.
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converti un tableau de numéros uniques en numéros locaux.
virtual IItemFamily * nodeFamily()=0
Retourne la famille des noeuds.
virtual IItemFamily * faceFamily()=0
Retourne la famille des faces.
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 VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
virtual IPrimaryMesh * toPrimaryMesh()=0
Retourne l'instance sous la forme d'un IPrimaryMesh.
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Routines des Lecture/Ecriture d'un fichier.
Groupe d'entités de maillage.
const String & name() const
Nom du groupe.
void addItems(Int32ConstArrayView items_local_id, bool check_if_present=true)
Ajoute des entités.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Informations sur le maillage créé
std::unordered_map< Int64, Int32 > nodes_rank_map
Tableau associatif (uniqueId(),rang) auquel le noeud appartiendra.
UniqueArray< Int64 > nodes_unique_id
UniqueId() des noeuds de ma partie.
UniqueArray< Real3 > nodes_coordinates
Coordonnées des noeuds de ma partie.
Lecteur de fichiers de maillage au format msh.
void _addFaceGroup(MeshV4ElementsBlock &block, const String &group_name)
Ajoute des faces au groupe group_name.
Integer _readElementsFromFileAscii()
Lecture des éléments (mailles,faces,...)
UniqueArray< Int32 > m_parts_rank
Liste des rangs qui participent à la conservation des données.
void _readEntities()
Lecture des entités.
Int32 m_nb_part
Nombre de partitions pour la lecture des noeuds et blocs.
void _readOneElementBlock(MeshV4ElementsBlock &block)
Lit un bloc d'entité de type 'Element'.
void _readNodesFromFileAscii()
Lecture des noeuds du maillage.
void _setNodesCoordinates()
Positionne les coordonnées des noeuds.
eReturnType readMeshFromMshFile(IMesh *mesh, const String &file_name) override
Lit le maillage contenu dans le fichier filename et le construit dans mesh.
void _addCellOrNodeGroup(MeshV4ElementsBlock &block, const String &group_name, IItemFamily *family)
Ajoute des faces au groupe group_name.
void _computeNodesPartition()
String _getNextLineAndBroadcast()
Lis la valeur de la prochaine ligne et la broadcast aux autres rangs.
Vue sur les informations des noeuds.
Classe gérant un vecteur de réel de dimension 3.
Integer size() const
Nombre d'éléments du vecteur.
Int64 largeSize() const
Nombre d'éléments du vecteur (en 64 bits)
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.
Interface du gestionnaire de traces.
Exception lorsqu'une opération n'est pas supportée.
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.
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.
ARCCORE_HOST_DEVICE Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Int32 toInt32(Int64 v)
Converti un Int64 en un Int32.
constexpr ARCCORE_HOST_DEVICE bool isNearlyEqual(const _Type &a, const _Type &b)
Teste si deux valeurs sont à un peu près égales. Pour les types entiers, cette fonction est équivalen...
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
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 index
Index du bloc dans la liste.
Integer item_type
Type Arcane de l'entité
Int32 dimension
Dimension de l'entité
Int32 item_nb_node
Nombre de noeuds de l'entité.
Int64 nb_entity
Nombre d'entités du bloc.
UniqueArray< Int64 > connectivities
< Liste des uniqueId() du bloc
Infos pour les entités 0D.
Infos pour les entités 1D, 2D et 3D.