Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
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-2025 */
9/* */
10/* Reading/Writing a VtuMeshWriter format file. */
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());
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; // Unique nodes-IDs array
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 * VTK-side initialization *
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 * ARC-side initialization *
160 \*************************/
161 VariableItemReal3& nodes_coords = PRIMARYMESH_CAST(mesh)->nodesCoordinates();
162
163 /*************************\
164 * Saving Cells Unique IDs *
165 \*************************/
166 info() << "[writeMeshToFile] Creating array of CELLS Unique IDs";
167 vtkCellData* vtk_cell_data = grid->GetCellData(); // Data associated to Cells
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());
173 }
174 vtk_cell_data->AddArray(vtk_cell_uids); // Now add our Cells' UniqueIDs array
175 vtk_cell_uids->Delete();
176
177 /*************************\
178 * Saving Nodes Unique IDs *
179 \*************************/
180 info() << "[writeMeshToFile] Creating array of NODES Unique IDs";
181 vtkPointData* vtk_point_data = grid->GetPointData(); // Data associated to 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 * Now setting point into grid *
207 \*****************************/
208 info() << "[writeMeshToFile] Now setting point into grid";
209 grid->SetPoints(points);
210
211 /**********************************************\
212 * Scanning cells' nodes to create connectivity *
213 \**********************************************/
214 info() << "[writeMeshToFile] Now scanning cells' nodes to create connectivity";
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 // Linear cells
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 // Mesh Generator 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 // To be implemented
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 /* Others not yet implemented */
281 default:
282 info() << "[writeMeshToFile] Cell type not supported (" << 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 * Fetching Other Groups *
292 \***********************/
293 info() << "[writeMeshToFile] ## Now Fetching Groups ##";
294 vtkFieldData* vtkFieldDataGroups = grid->GetFieldData();
295
296 for (ItemGroupCollection::Enumerator igroup(mesh->groups()); ++igroup;) {
297 if (igroup->isAllItems())
298 continue;
299 info() << "[writeMeshToFile] Found a " << igroup->itemKind() << "-group " << igroup->name();
300 _writeFieldGroupsFromData(vtkFieldDataGroups, *igroup);
301 }
302
303 /************************\
304 * Now prepare for output *
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 * And cleanup a little *
322 \**********************/
323 points->Delete();
324 grid->Delete();
325 vtk_grid_writer->Delete();
326 info() << "[writeMeshToFile] Done";
327 return false;
328}
329
330/*---------------------------------------------------------------------------*/
331/*---------------------------------------------------------------------------*/
332
333} // namespace Arcane
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
#define ENUMERATE_NODE(name, group)
Generic enumerator for a node group.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Cell of a mesh.
Definition Item.h:1300
Interface of a mesh writing service.
Definition IMeshWriter.h:38
Mesh entity group.
Definition ItemGroup.h:51
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
Int32 owner() const
Owner subdomain number of the entity.
Definition Item.h:252
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
Int16 type() const
Entity type.
Definition Item.h:255
Node of a mesh.
Definition Item.h:598
Class managing a 3-dimensional real vector.
Definition Real3.h:132
Structure containing the information to create a service.
bool null() const
Returns true if the string is null.
Definition String.cc:306
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
Definition String.cc:229
bool endsWith(const String &s) const
Indicates if the string ends with the characters of s.
Definition String.cc:1095
TraceMessage info() const
Flow for an information message.
virtual bool writeMeshToFile(IMesh *mesh, const String &file_name)
Writes a mesh. The data is stored according to ARCANE_VTU_DATA_MODE_TO_[ASCII|BINARY],...
virtual void build()
Build-level construction of the service.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
ItemVariableScalarRefT< Real3 > VariableItemReal3
3D coordinate type quantity
double toDouble(Real r)
Converts a Real to double.
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
@ ST_SubDomain
The service is used at the subdomain level.
Real y
second component of the triplet
Definition Real3.h:36
Real z
third component of the triplet
Definition Real3.h:37
Real x
first component of the triplet
Definition Real3.h:35