Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
VtuMeshWriter.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* VtuMeshWriter.cc (C) 2000-2026 */
9/* */
10/* Lecture/Ecriture d'un fichier au format VtuMeshWriter. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15#include "arcane/utils/Iostream.h"
16#include "arcane/utils/StdHeader.h"
17#include "arcane/utils/HashTableMap.h"
18#include "arcane/utils/ValueConvert.h"
19#include "arcane/utils/ScopedPtr.h"
20#include "arcane/utils/ITraceMng.h"
21#include "arcane/utils/String.h"
22#include "arcane/utils/IOException.h"
23#include "arcane/utils/Collection.h"
24#include "arcane/utils/Enumerator.h"
25#include "arcane/utils/NotImplementedException.h"
26#include "arcane/utils/Real3.h"
27#include "arcane/utils/PlatformUtils.h"
28
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/AbstractService.h"
49
50#include <vtkXMLUnstructuredGridReader.h>
51#include <vtkIdTypeArray.h>
52#include <vtkXMLUnstructuredGridWriter.h>
53#include <vtkUnstructuredGrid.h>
54#include <vtkCell.h>
55#include <vtkObject.h>
56#include <vtkDataObject.h>
57#include <vtkDataSet.h>
58#include <vtkCellData.h>
59#include <vtkPointData.h>
60#include <vtkDataArray.h>
61#include <vtkLongArray.h>
62#include <vtkIntArray.h>
63#include <vtkFieldData.h>
64
65#include <map>
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70namespace Arcane
71{
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
78class VtuMeshWriter
79: public AbstractService
80, public IMeshWriter
81{
82 public:
83
84 VtuMeshWriter(const ServiceBuildInfo& sbi)
85 : AbstractService(sbi)
86 {}
87
88 virtual void build() {}
89 virtual bool writeMeshToFile(IMesh* mesh, const String& file_name);
90
91 protected:
92
93 void _writeFieldGroupsFromData(vtkFieldData* field_data, ItemGroup groups);
94};
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
99ARCANE_REGISTER_SERVICE(VtuMeshWriter,
100 ServiceProperty("VtuNewMeshWriter", ST_SubDomain),
101 ARCANE_SERVICE_INTERFACE(IMeshWriter));
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106/*****************************************************************\
107 * _writeFieldGroupsFromData
108 uniqueId().asInteger
109 localId
110\*****************************************************************/
111void VtuMeshWriter::
112_writeFieldGroupsFromData(vtkFieldData* fieldData, ItemGroup group)
113{
114 vtkLongArray* a = vtkLongArray::New();
115 a->SetName(group.name().localstr());
116
117 a->InsertNextValue(group.itemKind());
118
119 ENUMERATE_ITEM (iitem, group) {
120 a->InsertNextValue(iitem->uniqueId().asInt32());
121 }
122
123 a->SetNumberOfTuples(a->GetNumberOfTuples());
124 fieldData->AddArray(a);
125 a->Delete();
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
141writeMeshToFile(IMesh* mesh, const String& file_name)
142{
143
144 Integer mesh_nb_node = mesh->nbNode();
145 Integer mesh_nb_cell = mesh->nbCell();
146 std::map<Int64, Integer> uid_to_idx_map; // Tableau des IDs uniques des nœuds
147 info() << "[VtuMeshWriter::writeMeshToFile] mesh_nb_node=" << mesh_nb_node << " mesh_nb_cell=" << mesh_nb_cell
148 << " all=" << mesh->allNodes().size() << ", own=" << mesh->ownNodes().size();
149
150 /*************************\
151 * Initialisation côté VTK *
152 \*************************/
153 vtkPoints* points = vtkPoints::New();
154 points->SetDataTypeToDouble();
155 vtkUnstructuredGrid* grid = vtkUnstructuredGrid::New();
156 grid->Allocate(mesh_nb_cell, mesh_nb_cell);
157
158 /*************************\
159 * Initialisation côté ARC *
160 \*************************/
161 VariableItemReal3& nodes_coords = PRIMARYMESH_CAST(mesh)->nodesCoordinates();
162
163 /*************************\
164 * Sauvegarde des IDs uniques des mailles *
165 \*************************/
166 info() << "[writeMeshToFile] Création du tableau des IDs uniques des MAILLES";
167 vtkCellData* vtk_cell_data = grid->GetCellData(); // Données associées aux Mailles
168 vtkLongArray* vtk_cell_uids = vtkLongArray::New();
169 vtk_cell_uids->SetName("CellsUniqueIDs");
170 ENUMERATE_CELL (iCell, mesh->allCells()) {
171 Cell cell = *iCell;
172 vtk_cell_uids->InsertNextValue(cell.uniqueId().asInt32());
173 }
174 vtk_cell_data->AddArray(vtk_cell_uids); // Ajout de notre tableau d'IDs uniques des Mailles
175 vtk_cell_uids->Delete();
176
177 /*************************\
178 * Sauvegarde des IDs uniques des nœuds *
179 \*************************/
180 info() << "[writeMeshToFile] Création du tableau des IDs uniques des NŒUDS";
181 vtkPointData* vtk_point_data = grid->GetPointData(); // Données associées aux Points
182 vtkLongArray* vtk_point_uids = vtkLongArray::New();
183 vtk_point_uids->SetName("NodesUniqueIDs");
184 vtkIntArray* vtk_point_owners = vtkIntArray::New();
185 vtk_point_owners->SetName("NodesOwner");
186 Integer index = 0;
187 ENUMERATE_NODE (inode, mesh->allNodes()) {
188 Node node = *inode;
189 Int64 uid = node.uniqueId();
190 Real3 coord = nodes_coords[inode];
191 points->InsertNextPoint(Convert::toDouble(coord.x),
192 Convert::toDouble(coord.y),
193 Convert::toDouble(coord.z));
194 uid_to_idx_map.insert(std::make_pair(uid, index));
195 vtk_point_uids->InsertNextValue(uid);
196 vtk_point_owners->InsertNextValue(node.owner());
197 ++index;
198 }
199 vtk_point_data->AddArray(vtk_point_uids);
200 vtk_point_uids->Delete();
201
202 vtk_point_data->AddArray(vtk_point_owners);
203 vtk_point_owners->Delete();
204
205 /*****************************\
206 * Maintenant, définir les points dans le maillage *
207 \*****************************/
208 info() << "[writeMeshToFile] Maintenant, définir les points dans le maillage";
209 grid->SetPoints(points);
210
211 /**********************************************\
212 * Balayage des nœuds des mailles pour créer la connectivité *
213 \**********************************************/
214 info() << "[writeMeshToFile] Maintenant, balayer les nœuds des mailles pour créer la connectivité";
215 vtkIdList* vtk_point_ids = vtkIdList::New();
216 ENUMERATE_CELL (iCell, mesh->allCells()) {
217 Cell cell = *iCell;
218 int nb_node = cell.nbNode();
219 vtk_point_ids->Allocate(nb_node);
220
221 for (Integer j = 0; j < nb_node; ++j) {
222 Int64 node_uid = cell.node(j).uniqueId();
223 auto x = uid_to_idx_map.find(node_uid);
224 if (x == uid_to_idx_map.end())
225 ARCANE_FATAL("InternalError: no index for uid '{0}'", node_uid);
226 vtk_point_ids->InsertNextId(x->second);
227 }
228
229 int vtk_item = IT_NullType;
230 switch (cell.type()) {
231 // Mailles linéaires
232 case (IT_Tetraedron4):
233 vtk_item = VTK_TETRA;
234 break;
235 case (IT_Hexaedron8):
236 vtk_item = VTK_HEXAHEDRON;
237 break;
238 case (IT_Pyramid5):
239 vtk_item = VTK_PYRAMID;
240 break;
241
242 // Générateur de maillage simple-1&2
243 case (IT_Octaedron12):
244 vtk_item = VTK_HEXAGONAL_PRISM;
245 break;
246 case (IT_Heptaedron10):
247 vtk_item = VTK_PENTAGONAL_PRISM;
248 break;
249
250 // Prisme
251 case (IT_Pentaedron6):
252 vtk_item = VTK_WEDGE;
253 break;
254
255 // À implémenter
256 case (IT_HemiHexa7):
257 info() << "VTK_POLY_VERTEX";
258 vtk_item = VTK_POLY_VERTEX;
259 break;
260 case (IT_HemiHexa6):
261 info() << "VTK_POLY_VERTEX";
262 vtk_item = VTK_POLY_VERTEX;
263 break;
264 case (IT_HemiHexa5):
265 info() << "VTK_POLY_VERTEX";
266 vtk_item = VTK_POLY_VERTEX;
267 break;
268 case (IT_AntiWedgeLeft6):
269 info() << "VTK_POLY_VERTEX";
270 vtk_item = VTK_POLY_VERTEX;
271 break;
272 case (IT_AntiWedgeRight6):
273 info() << "VTK_POLY_VERTEX";
274 vtk_item = VTK_POLY_VERTEX;
275 break;
276 case (IT_DiTetra5):
277 info() << "VTK_POLY_VERTEX";
278 vtk_item = VTK_POLY_VERTEX;
279 break;
280 /* Autres non encore implémentés */
281 default:
282 info() << "[writeMeshToFile] Type de maille non pris en charge (" << cell.type() << ")";
283 throw NotSupportedException(A_FUNCINFO);
284 }
285 grid->InsertNextCell(vtk_item, vtk_point_ids);
286 vtk_point_ids->Reset();
287 }
288 vtk_point_ids->Delete();
289
290 /***********************\
291 * Récupération des autres groupes *
292 \***********************/
293 info() << "[writeMeshToFile] ## Maintenant Récupération des Groupes ##";
294 vtkFieldData* vtkFieldDataGroups = grid->GetFieldData();
295
296 for (ItemGroupCollection::Enumerator igroup(mesh->groups()); ++igroup;) {
297 if (igroup->isAllItems())
298 continue;
299 info() << "[writeMeshToFile] Trouvé un groupe de type " << igroup->itemKind() << " " << igroup->name();
300 _writeFieldGroupsFromData(vtkFieldDataGroups, *igroup);
301 }
302
303 /************************\
304 * Préparation pour la sortie *
305 \************************/
306 vtkXMLUnstructuredGridWriter* vtk_grid_writer = vtkXMLUnstructuredGridWriter::New();
307 vtk_grid_writer->SetInputData(grid);
308 String fileNameDotVtu(file_name);
309 if (!file_name.endsWith(".vtu"))
310 fileNameDotVtu = file_name + ".vtu";
311 vtk_grid_writer->SetFileName(fileNameDotVtu.localstr());
312 info() << "[writeMeshToFile] SetFileName " << fileNameDotVtu;
313 String isAscii = platform::getEnvironmentVariable("ARCANE_VTU_DATA_MODE_TO_ASCII");
314 if (!isAscii.null())
315 vtk_grid_writer->SetDataModeToAscii();
316 else
317 vtk_grid_writer->SetDataModeToBinary();
318 vtk_grid_writer->Write();
319
320 /**********************\
321 * Et un petit nettoyage *
322 \**********************/
323 points->Delete();
324 grid->Delete();
325 vtk_grid_writer->Delete();
326 info() << "[writeMeshToFile] Terminé";
327 return false;
328}
329
330/*---------------------------------------------------------------------------*/
331/*---------------------------------------------------------------------------*/
332
333} // namespace Arcane
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
Maille d'un maillage.
Definition Item.h:1214
Interface d'un service d'écriture d'un maillage.
Definition IMeshWriter.h:37
Groupe d'entités de maillage.
Definition ItemGroup.h:49
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
Int16 type() const
Type de l'entité
Definition Item.h:241
Noeud d'un maillage.
Definition Item.h:582
Exception lorsqu'une opération n'est pas supportée.
Classe gérant un vecteur réel de 3 dimensions.
Structure contenant les informations pour créer un service.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:305
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
bool endsWith(const String &s) const
Indique si la chaîne se termine par les caractères de s.
Definition String.cc:1084
TraceMessage info() const
Flot pour un message d'information.
virtual bool writeMeshToFile(IMesh *mesh, const String &file_name)
Écrit un maillage. Les données sont stockées selon ARCANE_VTU_DATA_MODE_TO_[ASCII|BINARY],...
virtual void build()
Construction de niveau build du service.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
ItemVariableScalarRefT< Real3 > VariableItemReal3
Grandeur de type coordonn?es 3D.
double toDouble(Real r)
Convertit un Real en double.
String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
-- 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.
Real y
deuxième composante du triplet
Real z
troisième composante du triplet
Real x
première composante du triplet