Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
VtkPolyhedralMeshIOService.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/* VtkPolyhedralMeshIOService.cc (C) 2000-2026 */
9/* */
10/* Read/write fools for polyhedral mesh with vtk file format */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include <iostream>
15#include <numeric>
16#include <functional>
17#include <memory>
18#include <iterator>
19
20#include <vtkUnstructuredGrid.h>
21#include <vtkUnstructuredGridReader.h>
22#include <vtkNew.h>
23#include <vtkCellIterator.h>
24#include <vtkIdTypeArray.h>
25#include <vtkCellData.h>
26#include <vtkPointData.h>
27#include <vtkDataSetAttributes.h>
28#include <vtkArrayDispatch.h>
29#include <vtkDataArrayAccessor.h>
30#include <vtkPolyDataReader.h>
31#include <vtkPolyData.h>
32#include <vtkSmartPointer.h>
33#include <vtkCellArray.h>
34#include <vtkVersion.h>
35#if VTK_VERSION_NUMBER >= 900000000
36using vtkIdType_generic = vtkIdType const;
37#else
38using vtkIdType_generic = vtkIdType;
39#endif
40
41#include <arccore/base/Ref.h>
42#include <arccore/base/String.h>
43#include <arccore/base/FatalErrorException.h>
44#include <vtkXMLUnstructuredGridReader.h>
45#include <vtkXMLPolyDataReader.h>
46
48#include "arcane/core/AbstractService.h"
49#include "arcane/core/ICaseMeshReader.h"
51#include "arcane/core/IMeshBuilder.h"
52#include "arcane/core/MeshBuildInfo.h"
53#include "arcane/core/IPrimaryMesh.h"
55#include "arcane/core/IMeshInitialAllocator.h"
56#include "arcane/core/IVariableMng.h"
58#include "arcane/utils/ITraceMng.h"
59#include "arcane/utils/UniqueArray.h"
60#include "arcane/utils/Real3.h"
61#include "arcane/mesh/CellFamily.h"
62#include "arcane/core/MeshVariableScalarRef.h"
63#include "arcane/core/MeshVariableArrayRef.h"
64
65#include "arcane/core/ItemAllocationInfo.h"
66#include "arcane/core/VariableBuildInfo.h"
67
68#include "arcane/utils/OStringStream.h"
69
70#include "arcane/core/IXmlDocumentHolder.h"
71#include "arcane/core/XmlNode.h"
72#include "arcane/core/internal/IVariableMngInternal.h"
73#include "arcane/core/datatype/DataTypeTraits.h"
74
75#include "arcane/std/VtkPolyhedralMeshIO_axl.h"
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
80namespace Arcane
81{
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
86namespace VtkPolyhedralTools
87{
89 {
90 bool failure = false;
91 String failure_message;
92 String info_message;
93 };
94
96 {
97 bool print_mesh_info = false;
98 bool print_debug_info = false;
99 };
100} // namespace VtkPolyhedralTools
101
102/*---------------------------------------------------------------------------*/
103/*---------------------------------------------------------------------------*/
104
105class VtkPolyhedralMeshIOService
106: public TraceAccessor
107{
108 public:
109
110 explicit VtkPolyhedralMeshIOService(ITraceMng* trace_mng, VtkPolyhedralTools::PrintInfoLevel print_info_level)
111 : TraceAccessor(trace_mng)
112 , m_print_info_level(print_info_level)
113 {}
114
115 class VtkReader
116 {
117
118 public:
119
120 explicit VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level = VtkPolyhedralTools::PrintInfoLevel{});
121
122 VtkReader() = default;
123
124 static String supportedVtkExtensions() noexcept { return "vtk,vtu"; };
125
126 Int64ConstArrayView cellUids();
127 Int64ConstArrayView nodeUids();
128 Int64ConstArrayView faceUids();
129 Int64ConstArrayView edgeUids();
130
131 Integer nbNodes();
132
133 Int64ConstArrayView cellNodes();
134 Int32ConstArrayView cellNbNodes();
135
136 Int64ConstArrayView faceNodes();
137 Int32ConstArrayView faceNbNodes();
138
139 Int64ConstArrayView faceNodesInFaceMesh();
140 Int32ConstArrayView faceNbNodesInFaceMesh();
141
142 Int64ConstArrayView edgeNodes();
143 Int32ConstArrayView edgeNbNodes();
144
145 Int64ConstArrayView faceCells();
146 Int32ConstArrayView faceNbCells();
147
148 Int32ConstArrayView edgeNbCells();
149 Int64ConstArrayView edgeCells();
150
151 Int32ConstArrayView cellNbFaces();
152 Int64ConstArrayView cellFaces();
153
154 Int32ConstArrayView edgeNbFaces();
155 Int64ConstArrayView edgeFaces();
156
157 Int32ConstArrayView cellNbEdges();
158 Int64ConstArrayView cellEdges();
159
160 Int32ConstArrayView faceNbEdges();
161 Int64ConstArrayView faceEdges();
162
163 Int32ConstArrayView nodeNbCells();
164 Int64ConstArrayView nodeCells();
165
166 Int32ConstArrayView nodeNbFaces();
167 Int64ConstArrayView nodeFaces();
168
169 Int32ConstArrayView nodeNbEdges();
170 Int64ConstArrayView nodeEdges();
171
172 Real3ArrayView nodeCoords();
173
174 bool readHasFailed() const noexcept { return m_read_status.failure; }
175 VtkPolyhedralTools::ReadStatus readStatus() const noexcept { return m_read_status; }
176
177 vtkCellData* cellData();
178 vtkPointData* pointData();
179 vtkCellData* faceData();
180
181 bool isEmpty() const noexcept { return m_is_empty; }
182 bool doRead() const noexcept { return m_do_read; }
183
184 private:
185
186 bool m_is_empty = true;
187 bool m_do_read = false;
188 String m_filename;
189 VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
190 VtkPolyhedralTools::ReadStatus m_read_status;
191 vtkNew<vtkUnstructuredGridReader> m_vtk_grid_reader;
192 vtkNew<vtkXMLUnstructuredGridReader> m_vtk_xml_grid_reader;
193 vtkNew<vtkPolyDataReader> m_vtk_face_grid_reader;
194 vtkNew<vtkXMLPolyDataReader> m_vtk_xml_face_grid_reader;
195 vtkUnstructuredGrid* m_vtk_grid = nullptr;
196 vtkPolyData* m_vtk_face_grid = nullptr;
197 Int64UniqueArray m_cell_uids, m_node_uids, m_face_uids, m_edge_uids;
198 Int64UniqueArray m_face_node_uids, m_edge_node_uids, m_cell_node_uids;
199 Int64UniqueArray m_face_cell_uids, m_edge_cell_uids, m_edge_face_uids;
200 Int64UniqueArray m_cell_face_uids, m_cell_edge_uids, m_face_edge_uids;
201 Int64UniqueArray m_node_cell_uids, m_node_face_uids, m_node_edge_uids;
202 Int32UniqueArray m_face_nb_nodes, m_cell_nb_nodes, m_face_nb_cells;
203 Int32UniqueArray m_edge_nb_cells, m_edge_nb_faces, m_cell_nb_faces;
204 Int32UniqueArray m_node_nb_cells, m_node_nb_faces, m_node_nb_edges;
205 Int32UniqueArray m_cell_nb_edges, m_face_nb_edges, m_face_uid_indexes;
206 Int32UniqueArray m_cell_face_indexes, m_edge_nb_nodes;
207 Int64UniqueArray m_face_node_uids_in_face_mesh;
208 Int32UniqueArray m_face_nb_nodes_in_face_mesh;
209 using NodeUidToIndexMap = Int32UniqueArray; // use a map when no longer possible to index with node uids
210 using FaceUidToIndexMap = Int32UniqueArray; // use a map when no longer possible to index with face uids
211 using EdgeUidToIndexMap = Int32UniqueArray; // use a map when no longer possible to index with edge uids
212 NodeUidToIndexMap m_node_uid_to_index;
213 Real3UniqueArray m_node_coordinates;
214 vtkCellData* m_cell_data = nullptr;
215 vtkPointData* m_point_data = nullptr;
216 vtkCellData* m_face_data = nullptr;
217 vtkCellArray* m_poly_data = nullptr; // to store faces from face mesh file
218
219 void _printMeshInfos() const;
220
221 std::pair<bool, Int32> _findFace(const Int64UniqueArray& sorted_face_nodes, const UniqueArray<Int64UniqueArray>& node_face_uids, const NodeUidToIndexMap& node_uid_to_index, const Int32UniqueArray& face_nb_nodes, const FaceUidToIndexMap& face_uid_to_index, const UniqueArray<Int32>& face_offsets, const Int64UniqueArray& face_node_uids);
222 template <typename Connectivity2DArray>
223 static void _flattenConnectivity(Connectivity2DArray connected_item_2darray, Int32Span nb_connected_item_per_source_item, Int64UniqueArray& connected_item_array);
224 void _readPlainTextVtkGrid(const String& filename);
225 void _readXlmVtkGrid(const String& filename);
226 void _checkVtkGrid() const;
227 void _readPlainTextVtkFaceGrid(const String& faces_filename);
228 void _readXmlVtkFaceGrid(const String& faces_filename);
229 void _readfaceNodesInFaceMesh();
230 };
231
232 public:
233
234 VtkPolyhedralTools::ReadStatus read(IPrimaryMesh* mesh, const String& filename, bool is_parallel_read)
235 {
237 // warning meaning of parallel_read not obvious :
238 // if is parallel_read => master reads + broadcast, if not all ranks read a pre-distributed mesh
239 bool do_read = is_parallel_read ? mesh->parallelMng()->isMasterIO() : true;
240 using VtkReaderPtr = std::unique_ptr<VtkReader>;
241 VtkReaderPtr reader = std::make_unique<VtkReader>();
242 if (do_read)
243 reader = std::make_unique<VtkReader>(filename, m_print_info_level);
244 if (reader->readHasFailed())
245 return reader->readStatus();
246 ItemAllocationInfo item_allocation_info;
247 _fillItemAllocationInfo(item_allocation_info, *reader);
248 auto polyhedral_mesh_allocator = mesh->initialAllocator()->polyhedralMeshAllocator();
249 polyhedral_mesh_allocator->allocateItems(item_allocation_info);
250 _readVariablesAndGroups(mesh, *reader);
251 return reader->readStatus();
252 }
253
254 private:
255
256 VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
257
259 {
260 eDataType m_type = DT_Unknown;
261 bool is_array = false;
262 };
263
264 void _readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader);
265 void _createGroup(vtkDataArray* group_items, const String& group_name, IPrimaryMesh* mesh, IItemFamily* item_family, Int32ConstSpan vtkToArcaneLid) const;
266 VariableInfo _createVariable(vtkDataArray* item_values, const String& variable_name, IMesh* mesh, IItemFamily* item_family, Int32ConstSpan arcane_to_vtk_lids) const;
267
268 static void _fillItemAllocationInfo(ItemAllocationInfo& item_allocation_info, VtkReader& vtk_reader);
269 void _computeFaceVtkArcaneLidConversion(Int32Span face_vtk_to_arcane_lids, Int32Span arcane_to_vtk_lids, VtkPolyhedralMeshIOService::VtkReader& reader, IPrimaryMesh* mesh) const;
270 void _createEmptyVariablesAndGroups(IMesh* mesh, XmlNode::const_reference xml_node) const;
271 template <template <class> class VariableRootType, template <class> class ArrayVariableRootType>
272 void _createEmptyVariables(IMesh* mesh, const XmlNodeList& cell_variables_node, eItemKind item_kind) const;
273 void _createEmptyGroups(IMesh* mesh, const XmlNodeList& children, IItemFamily* item_family) const;
274};
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
278
279class VtkPolyhedralCaseMeshReader
281{
282 public:
283
284 class Builder : public IMeshBuilder
285 {
286 public:
287
288 explicit Builder(ITraceMng* tm, const CaseMeshReaderReadInfo& read_info, VtkPolyhedralTools::PrintInfoLevel print_info_level)
289 : m_trace_mng(tm)
290 , m_read_info(read_info)
291 , m_print_info_level(print_info_level)
292 {}
293
294 void fillMeshBuildInfo(MeshBuildInfo& build_info) override
295 {
296 build_info.addFactoryName("ArcanePolyhedralMeshFactory");
297 build_info.addNeedPartitioning(false);
298 MeshKind mk;
299 mk.setMeshStructure(eMeshStructure::Polyhedral);
300 build_info.addMeshKind(mk);
301 }
302
304 {
306 m_trace_mng->info() << "---Create Polyhedral mesh: " << pm->name() << "---";
307 m_trace_mng->info() << "--Read mesh file " << m_read_info.fileName();
308 VtkPolyhedralMeshIOService polyhedral_vtk_service{ m_trace_mng, m_print_info_level };
309 auto read_status = polyhedral_vtk_service.read(pm, m_read_info.fileName(), m_read_info.isParallelRead());
310 if (read_status.failure)
311 ARCANE_FATAL(read_status.failure_message);
312 m_trace_mng->info() << read_status.info_message;
313 }
314
315 private:
316
317 ITraceMng* m_trace_mng;
318 CaseMeshReaderReadInfo m_read_info;
319 VtkPolyhedralTools::PrintInfoLevel m_print_info_level;
320 };
321
324 {}
325
326 public:
327
329 {
330 IMeshBuilder* builder = nullptr;
331 if (VtkPolyhedralMeshIOService::VtkReader::supportedVtkExtensions().contains(read_info.format()))
332 builder = new Builder(traceMng(), read_info, VtkPolyhedralTools::PrintInfoLevel{ options()->getPrintMeshInfos(), options()->getPrintDebugInfos() });
333 return makeRef(builder);
334 }
335};
336
337/*---------------------------------------------------------------------------*/
338/*---------------------------------------------------------------------------*/
339
340ARCANE_REGISTER_SERVICE(VtkPolyhedralCaseMeshReader,
341 ServiceProperty("VtkPolyhedralCaseMeshReader", ST_CaseOption),
342 ARCANE_SERVICE_INTERFACE(ICaseMeshReader));
343
344/*---------------------------------------------------------------------------*/
345/*---------------------------------------------------------------------------*/
346
347void VtkPolyhedralMeshIOService::
348_fillItemAllocationInfo(ItemAllocationInfo& item_allocation_info, VtkReader& vtk_reader)
349{
350 auto nb_item_family = 4;
351 auto nb_connected_family = 3;
352 item_allocation_info.family_infos.resize(nb_item_family);
353 for (auto& family_info : item_allocation_info.family_infos) {
354 family_info.connected_family_infos.resize(nb_connected_family);
355 }
356 // Create regular item families and connectivities
357 auto& cell_family_info = item_allocation_info.family_infos[0];
358 cell_family_info.name = "Cell";
359 cell_family_info.item_kind = IK_Cell;
360 cell_family_info.item_uids = vtk_reader.cellUids();
361 auto& node_family_info = item_allocation_info.family_infos[1];
362 node_family_info.name = "Node";
363 node_family_info.item_kind = IK_Node;
364 node_family_info.item_uids = vtk_reader.nodeUids();
365 auto& face_family_info = item_allocation_info.family_infos[2];
366 face_family_info.name = "Face";
367 face_family_info.item_kind = IK_Face;
368 face_family_info.item_uids = vtk_reader.faceUids();
369 auto& edge_family_info = item_allocation_info.family_infos[3];
370 edge_family_info.name = "Edge";
371 edge_family_info.item_kind = IK_Edge;
372 edge_family_info.item_uids = vtk_reader.edgeUids();
373 // Cell to nodes connectivity
374 auto cell_connected_family_index = 0;
375 auto& cell_connected_node_family_info = cell_family_info.connected_family_infos[cell_connected_family_index++];
376 cell_connected_node_family_info.name = node_family_info.name;
377 cell_connected_node_family_info.item_kind = node_family_info.item_kind;
378 cell_connected_node_family_info.connectivity_name = "CellToNodes";
379 cell_connected_node_family_info.nb_connected_items_per_item = vtk_reader.cellNbNodes();
380 cell_connected_node_family_info.connected_items_uids = vtk_reader.cellNodes();
381 // Cell to faces connectivity
382 auto& cell_connected_face_family_info = cell_family_info.connected_family_infos[cell_connected_family_index++];
383 cell_connected_face_family_info.name = face_family_info.name;
384 cell_connected_face_family_info.item_kind = face_family_info.item_kind;
385 cell_connected_face_family_info.connectivity_name = "CellToFaces";
386 cell_connected_face_family_info.nb_connected_items_per_item = vtk_reader.cellNbFaces();
387 cell_connected_face_family_info.connected_items_uids = vtk_reader.cellFaces();
388 // Cell to edges connectivity
389 auto& cell_connected_edge_family_info = cell_family_info.connected_family_infos[cell_connected_family_index++];
390 cell_connected_edge_family_info.name = edge_family_info.name;
391 cell_connected_edge_family_info.item_kind = edge_family_info.item_kind;
392 cell_connected_edge_family_info.connectivity_name = "CellToEdges";
393 cell_connected_edge_family_info.nb_connected_items_per_item = vtk_reader.cellNbEdges();
394 cell_connected_edge_family_info.connected_items_uids = vtk_reader.cellEdges();
395 // Face to cells connectivity
396 auto face_connected_family_index = 0;
397 auto& face_connected_cell_family_info = face_family_info.connected_family_infos[face_connected_family_index++];
398 face_connected_cell_family_info.name = cell_family_info.name;
399 face_connected_cell_family_info.item_kind = cell_family_info.item_kind;
400 face_connected_cell_family_info.connectivity_name = "FaceToCells";
401 face_connected_cell_family_info.nb_connected_items_per_item = vtk_reader.faceNbCells();
402 face_connected_cell_family_info.connected_items_uids = vtk_reader.faceCells();
403 // Face to nodes connectivity
404 auto& face_connected_node_family_info = face_family_info.connected_family_infos[face_connected_family_index++];
405 face_connected_node_family_info.name = node_family_info.name;
406 face_connected_node_family_info.item_kind = node_family_info.item_kind;
407 face_connected_node_family_info.connectivity_name = "FaceToNodes";
408 face_connected_node_family_info.nb_connected_items_per_item = vtk_reader.faceNbNodes();
409 face_connected_node_family_info.connected_items_uids = vtk_reader.faceNodes();
410 // Face to edges connectivity
411 auto& face_connected_edge_family_info = face_family_info.connected_family_infos[face_connected_family_index];
412 face_connected_edge_family_info.name = edge_family_info.name;
413 face_connected_edge_family_info.item_kind = edge_family_info.item_kind;
414 face_connected_edge_family_info.connectivity_name = "FaceToEdges";
415 face_connected_edge_family_info.nb_connected_items_per_item = vtk_reader.faceNbEdges();
416 face_connected_edge_family_info.connected_items_uids = vtk_reader.faceEdges();
417 // Edge to cells connectivity
418 auto edge_connected_family_index = 0;
419 auto& edge_connected_cell_family_info = edge_family_info.connected_family_infos[edge_connected_family_index++];
420 edge_connected_cell_family_info.name = cell_family_info.name;
421 edge_connected_cell_family_info.item_kind = cell_family_info.item_kind;
422 edge_connected_cell_family_info.connectivity_name = "EdgeToCells";
423 edge_connected_cell_family_info.nb_connected_items_per_item = vtk_reader.edgeNbCells();
424 edge_connected_cell_family_info.connected_items_uids = vtk_reader.edgeCells();
425 // Edge to faces connectivity
426 auto& edge_connected_face_family_info = edge_family_info.connected_family_infos[edge_connected_family_index++];
427 edge_connected_face_family_info.name = face_family_info.name;
428 edge_connected_face_family_info.item_kind = face_family_info.item_kind;
429 edge_connected_face_family_info.connectivity_name = "EdgeToFaces";
430 edge_connected_face_family_info.nb_connected_items_per_item = vtk_reader.edgeNbFaces();
431 edge_connected_face_family_info.connected_items_uids = vtk_reader.edgeFaces();
432 // Edge to nodes connectivity
433 auto& edge_connected_node_family_info = edge_family_info.connected_family_infos[edge_connected_family_index++];
434 edge_connected_node_family_info.name = node_family_info.name;
435 edge_connected_node_family_info.item_kind = node_family_info.item_kind;
436 edge_connected_node_family_info.connectivity_name = "EdgeToNodes";
437 edge_connected_node_family_info.nb_connected_items_per_item = vtk_reader.edgeNbNodes();
438 edge_connected_node_family_info.connected_items_uids = vtk_reader.edgeNodes();
439 // Node to cells connectivity
440 auto node_connected_family_index = 0;
441 auto& node_connected_cell_family_info = node_family_info.connected_family_infos[node_connected_family_index++];
442 node_connected_cell_family_info.name = cell_family_info.name;
443 node_connected_cell_family_info.item_kind = cell_family_info.item_kind;
444 node_connected_cell_family_info.connectivity_name = "NodeToCells";
445 node_connected_cell_family_info.nb_connected_items_per_item = vtk_reader.nodeNbCells();
446 node_connected_cell_family_info.connected_items_uids = vtk_reader.nodeCells();
447 // Node to faces connectivity
448 auto& node_connected_face_family_info = node_family_info.connected_family_infos[node_connected_family_index++];
449 node_connected_face_family_info.name = face_family_info.name;
450 node_connected_face_family_info.item_kind = face_family_info.item_kind;
451 node_connected_face_family_info.connectivity_name = "NodeToFaces";
452 node_connected_face_family_info.nb_connected_items_per_item = vtk_reader.nodeNbFaces();
453 node_connected_face_family_info.connected_items_uids = vtk_reader.nodeFaces();
454 // Node to edges connectivity
455 auto& node_connected_edge_family_info = node_family_info.connected_family_infos[node_connected_family_index++];
456 node_connected_edge_family_info.name = edge_family_info.name;
457 node_connected_edge_family_info.item_kind = edge_family_info.item_kind;
458 node_connected_edge_family_info.connectivity_name = "NodeToEdges";
459 node_connected_edge_family_info.nb_connected_items_per_item = vtk_reader.nodeNbEdges();
460 node_connected_edge_family_info.connected_items_uids = vtk_reader.nodeEdges();
461 // Node coordinates
462 node_family_info.item_coordinates_variable_name = "NodeCoord";
463 node_family_info.item_coordinates = vtk_reader.nodeCoords();
464}
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
468
469void VtkPolyhedralMeshIOService::
470_readVariablesAndGroups(IPrimaryMesh* mesh, VtkReader& reader)
471{
472 // Register variable and group info in an xml for non reader ranks
473 OStringStream created_infos_str;
474 created_infos_str() << "<?xml version='1.0' ?>\n";
475 created_infos_str() << "<infos>";
476 // Cell data
477 if (auto* cell_data = reader.cellData(); cell_data) {
478 // Read cell groups and variables
479 Int32SharedArray vtk_to_arcane_lids(mesh->cellFamily()->nbItem());
480 std::iota(vtk_to_arcane_lids.begin(), vtk_to_arcane_lids.end(), 0);
481 Int32SharedArray arcane_to_vtk_lids{ vtk_to_arcane_lids };
482 for (auto array_index = 0; array_index < cell_data->GetNumberOfArrays(); ++array_index) {
483 auto* cell_array = cell_data->GetArray(array_index);
484 if (!cell_array)
485 continue;
486 if (String name = cell_array->GetName(); name.substring(0, 6) == "GROUP_") {
487 _createGroup(cell_array, name.substring(6), mesh, mesh->cellFamily(), vtk_to_arcane_lids.constSpan());
488 created_infos_str() << "<cell-group name='" << name.substring(6) << "'/>";
489 }
490 else {
491 auto var_info = _createVariable(cell_array, name, mesh, mesh->cellFamily(), arcane_to_vtk_lids);
492 created_infos_str() << "<cell-variable name='" << name << "' "
493 << " data-type='" << dataTypeName(var_info.m_type) << "' "
494 << " is_array='" << std::boolalpha << var_info.is_array << "'/>";
495 }
496 if (m_print_info_level.print_debug_info) {
497 debug(Trace::High) << "Reading property " << cell_array->GetName();
498 for (auto tuple_index = 0; tuple_index < cell_array->GetNumberOfTuples(); ++tuple_index) {
499 for (auto component_index = 0; component_index < cell_array->GetNumberOfComponents(); ++component_index) {
500 debug(Trace::High) << cell_array->GetName() << "[" << tuple_index << "][" << component_index << "] = " << cell_array->GetComponent(tuple_index, component_index);
501 }
502 }
503 }
504 }
505 }
506 // Node data
507 if (auto* point_data = reader.pointData(); point_data) {
508 // Read node groups and variables
509 Int32SharedArray vtk_to_arcane_lids(mesh->nodeFamily()->nbItem());
510 std::iota(vtk_to_arcane_lids.begin(), vtk_to_arcane_lids.end(), 0);
511 Int32SharedArray arcane_to_vtk_lids{ vtk_to_arcane_lids };
512 for (auto array_index = 0; array_index < point_data->GetNumberOfArrays(); ++array_index) {
513 auto* point_array = point_data->GetArray(array_index);
514 if (String name = point_array->GetName(); name.substring(0, 6) == "GROUP_") {
515 _createGroup(point_array, name.substring(6), mesh, mesh->nodeFamily(), vtk_to_arcane_lids.constSpan());
516 created_infos_str() << "<node-group name='" << name.substring(6) << "'/>";
517 }
518 else {
519 auto var_info = _createVariable(point_array, name, mesh, mesh->nodeFamily(), arcane_to_vtk_lids);
520 created_infos_str() << "<node-variable name='" << name << "' "
521 << " data-type='" << dataTypeName(var_info.m_type) << "' "
522 << " is_array='" << std::boolalpha << var_info.is_array << "'/>";
523 }
524 if (m_print_info_level.print_debug_info) {
525 debug(Trace::High) << "Reading property " << point_array->GetName();
526 for (auto tuple_index = 0; tuple_index < point_array->GetNumberOfTuples(); ++tuple_index) {
527 for (auto component_index = 0; component_index < point_array->GetNumberOfComponents(); ++component_index) {
528 debug(Trace::High) << point_array->GetName() << "[" << tuple_index << "][" << component_index << "] = " << point_array->GetComponent(tuple_index, component_index);
529 }
530 }
531 }
532 }
533 }
534 // Face data
535 if (auto* face_data = reader.faceData(); face_data) {
536 // Read face groups and variables
537 Int32UniqueArray vtk_to_Arcane_lids(mesh->faceFamily()->nbItem());
538 Int32UniqueArray arcane_to_vtk_lids(mesh->faceFamily()->nbItem());
539 _computeFaceVtkArcaneLidConversion(vtk_to_Arcane_lids, arcane_to_vtk_lids, reader, mesh);
540 for (auto array_index = 0; array_index < face_data->GetNumberOfArrays(); ++array_index) {
541 auto* face_array = face_data->GetArray(array_index);
542 if (String name = face_array->GetName(); name.substring(0, 6) == "GROUP_") {
543 _createGroup(face_array, name.substring(6), mesh, mesh->faceFamily(), vtk_to_Arcane_lids);
544 created_infos_str() << "<face-group name='" << name.substring(6) << "'/>";
545 }
546 else {
547 auto var_info = _createVariable(face_array, name, mesh, mesh->faceFamily(), arcane_to_vtk_lids);
548 created_infos_str() << "<face-variable name='" << name << "' "
549 << " data-type='" << dataTypeName(var_info.m_type) << "' "
550 << " is_array='" << std::boolalpha << var_info.is_array << "'/>";
551 }
552 if (m_print_info_level.print_debug_info) {
553 debug(Trace::High) << "Reading property " << face_array->GetName();
554 for (auto tuple_index = 0; tuple_index < face_array->GetNumberOfTuples(); ++tuple_index) {
555 for (auto component_index = 0; component_index < face_array->GetNumberOfComponents(); ++component_index) {
556 debug(Trace::High) << face_array->GetName() << "[" << tuple_index << "][" << component_index << "] = " << face_array->GetComponent(tuple_index, component_index);
557 }
558 }
559 }
560 }
561 }
562 created_infos_str() << "</infos>";
563 // Create empty group and variables in non reader subdomain
564 ByteUniqueArray bytes;
565 auto* pm = mesh->parallelMng();
566 if (!reader.isEmpty() && pm->isMasterIO()) {
567 String str = created_infos_str.str();
568 ByteConstArrayView bv = str.utf8();
569 Integer len = bv.size();
570 bytes.resize(len + 1);
571 bytes.copy(bv);
572 }
573 pm->broadcastMemoryBuffer(bytes, pm->masterIORank());
574 if (reader.isEmpty()) {
575 std::unique_ptr<IXmlDocumentHolder> doc(IXmlDocumentHolder::loadFromBuffer(bytes, "InternalBuffer", traceMng()));
576 XmlNode doc_node = doc->documentNode();
577 _createEmptyVariablesAndGroups(mesh, doc_node);
578 }
579}
580
581/*---------------------------------------------------------------------------*/
582/*---------------------------------------------------------------------------*/
583
584void VtkPolyhedralMeshIOService::
585_createGroup(vtkDataArray* group_items, const String& group_name, IPrimaryMesh* mesh, IItemFamily* item_family, Int32ConstSpan vtkToArcaneLid) const
586{
587 ARCANE_CHECK_POINTER(group_items);
589 ARCANE_CHECK_POINTER(item_family);
590 if (group_items->GetNumberOfComponents() != 1)
591 fatal() << String::format("Cannot create item group {0}. Group information in data property must be a scalar", group_name);
592 debug() << "Create group " << group_name;
593 Int32UniqueArray arcane_lids;
594 arcane_lids.reserve((int)group_items->GetNumberOfValues());
595 using GroupDispatcher = vtkArrayDispatch::DispatchByValueType<vtkArrayDispatch::Integrals>;
596 auto group_creator = [&arcane_lids, &vtkToArcaneLid](auto* array) {
597 vtkIdType numTuples = array->GetNumberOfTuples();
598 vtkDataArrayAccessor<std::remove_pointer_t<decltype(array)>> array_accessor{ array };
599 auto local_id = 0;
600 for (vtkIdType tupleIdx = 0; tupleIdx < numTuples; ++tupleIdx) {
601 auto value = array_accessor.Get(tupleIdx, 0);
602 if (value)
603 arcane_lids.push_back(vtkToArcaneLid[local_id]);
604 ++local_id;
605 }
606 };
607 if (!GroupDispatcher::Execute(group_items, group_creator))
608 ARCANE_FATAL("Cannot create item group {0}. Group information in data property must be an integral type", group_name);
609 debug() << " local ids for item group " << group_name << " " << arcane_lids; // to remove
610 item_family->createGroup(group_name, arcane_lids);
611}
612
613/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615
616template <typename vtkType>
618{
619 using type = vtkType;
620};
621
622template <>
623struct ToArcaneType<float>
624{
625 using type = Real;
626};
627
628template <>
629struct ToArcaneType<long long>
630{
631 using type = Int64;
632};
633
634template <>
635struct ToArcaneType<long> {
636 using type = Int32;
637};
638
639
640
641template <typename T> using to_arcane_type_t = typename ToArcaneType<T>::type;
642/*---------------------------------------------------------------------------*/
643
644VtkPolyhedralMeshIOService::VariableInfo VtkPolyhedralMeshIOService::
645_createVariable(vtkDataArray* item_values, const String& variable_name, IMesh* mesh, IItemFamily* item_family, Int32ConstSpan arcane_to_vtk_lids) const
646{
647 ARCANE_CHECK_POINTER(item_values);
649 ARCANE_CHECK_POINTER(item_family);
650 if (item_values->GetNumberOfTuples() != item_family->nbItem())
651 ARCANE_FATAL("Cannot create variable {0}, {1} values are given for {2} items in {3} family",
652 variable_name, item_values->GetNumberOfTuples(), item_family->nbItem(), item_family->name());
653 debug() << "Create mesh variable " << variable_name;
654 VariableInfo var_info;
655 auto variable_creator = [mesh, variable_name, item_family, arcane_to_vtk_lids, this, &var_info](auto* values) {
656 VariableBuildInfo vbi{ mesh, variable_name };
657 using ValueType = typename std::remove_pointer_t<decltype(values)>::ValueType;
658 auto* var = new ItemVariableScalarRefT<to_arcane_type_t<ValueType>>{ vbi, item_family->itemKind() };
660 vtkDataArrayAccessor<std::remove_pointer_t<decltype(values)>> values_accessor{ values };
661 ENUMERATE_ITEM (item, item_family->allItems()) {
662 (*var)[item] = (to_arcane_type_t<ValueType>)values_accessor.Get(arcane_to_vtk_lids[item.localId()], 0);
663 }
664 var_info.m_type = DataTypeTraitsT<to_arcane_type_t<ValueType>>::type();
665 var_info.is_array = false;
666 };
667 auto array_variable_creator = [mesh, variable_name, item_family, arcane_to_vtk_lids, this, &var_info](auto* values) {
668 VariableBuildInfo vbi{ mesh, variable_name };
669 using ValueType = typename std::remove_pointer_t<decltype(values)>::ValueType;
670 auto* var = new ItemVariableArrayRefT<to_arcane_type_t<ValueType>>{ vbi, item_family->itemKind() };
672 vtkDataArrayAccessor<std::remove_pointer_t<decltype(values)>> values_accessor{ values };
673 var->resize(values->GetNumberOfComponents());
674 ENUMERATE_ITEM (item, item_family->allItems()) {
675 auto index = 0;
676 for (auto& var_value : (*var)[item]) {
677 var_value = (to_arcane_type_t<ValueType>)values_accessor.Get(arcane_to_vtk_lids[item.localId()], index++);
678 }
679 }
680 var_info.m_type = DataTypeTraitsT<to_arcane_type_t<ValueType>>::type();
681 var_info.is_array = true;
682 };
683 // Restrict to int and real values
684 using ValueTypes = vtkTypeList_Create_6(double, float, int, long, long long, short);
685 using ArrayDispatcher = vtkArrayDispatch::DispatchByValueType<ValueTypes>;
686 // Create ScalarVariable
687 bool is_variable_created = false;
688 if (item_values->GetNumberOfComponents() == 1) {
689 is_variable_created = ArrayDispatcher::Execute(item_values, variable_creator);
690 }
691 // Create ArrayVariable
692 else { // ArrayVariable
693 is_variable_created = ArrayDispatcher::Execute(item_values, array_variable_creator);
694 }
695 if (!is_variable_created)
696 ARCANE_FATAL("Cannot create variable {0}, it's data type is not supported. Only real and integral types are supported", variable_name);
697 return var_info;
698}
699
700/*---------------------------------------------------------------------------*/
701/*---------------------------------------------------------------------------*/
702
703void VtkPolyhedralMeshIOService::
704_computeFaceVtkArcaneLidConversion(Int32Span face_vtk_to_arcane_lids, Int32Span arcane_to_vtk_lids, VtkPolyhedralMeshIOService::VtkReader& reader, IPrimaryMesh* mesh) const
705{
706 auto face_nodes_unique_ids = reader.faceNodesInFaceMesh();
707 auto face_nb_nodes = reader.faceNbNodesInFaceMesh();
708 auto current_face_index = 0;
709 auto current_face_index_in_face_nodes = 0;
710 Int32UniqueArray face_nodes_local_ids(face_nodes_unique_ids.size());
711 mesh->nodeFamily()->itemsUniqueIdToLocalId(face_nodes_local_ids, face_nodes_unique_ids);
712 for (auto current_face_nb_node : face_nb_nodes) {
713 auto current_face_nodes = face_nodes_local_ids.subConstView(current_face_index_in_face_nodes, current_face_nb_node);
714 current_face_index_in_face_nodes += current_face_nb_node;
715 Node face_first_node{ mesh->nodeFamily()->view()[current_face_nodes[0]] };
716 face_vtk_to_arcane_lids[current_face_index] = MeshUtils::getFaceFromNodesLocalId(face_first_node, current_face_nodes).localId();
717 ++current_face_index;
718 }
719 auto vtk_lid = 0;
720 for (auto arcane_lid : face_vtk_to_arcane_lids) {
721 arcane_to_vtk_lids[arcane_lid] = vtk_lid;
722 ++vtk_lid;
723 }
724}
725
726/*---------------------------------------------------------------------------*/
727/*---------------------------------------------------------------------------*/
728
729template <template <class> class VariableRootType>
730VariableRef* _createVar(IMesh* mesh, const String& var_name, const String& var_data_type_name, eItemKind var_kind)
731{
732 bool has_error = false;
733 eDataType var_data_type = dataTypeFromName(var_data_type_name.localstr(), has_error);
734 if (has_error) {
735 ARCANE_FATAL("Invalid data type name {0} for Variable creation in VtkPolyhedralMeshIOService");
736 }
737 switch (var_data_type) {
738 case DT_Int32:
739 return new VariableRootType<Int32>{ VariableBuildInfo{ mesh, var_name }, var_kind };
740 break;
741 case DT_Int64:
742 return new VariableRootType<Int64>{ VariableBuildInfo{ mesh, var_name }, var_kind };
743 break;
744 case DT_Real:
745 return new VariableRootType<Real>{ VariableBuildInfo{ mesh, var_name }, var_kind };
746 break;
747 default:
748 ARCANE_FATAL("Handle only DT_Int32, DT_Int64, DT_Real in VtkPolyhedralMeshIOService");
749 }
750}
751
752/*---------------------------------------------------------------------------*/
753/*---------------------------------------------------------------------------*/
754
755template <template <class> class VariableRootType, template <class> class ArrayVariableRootType>
756void VtkPolyhedralMeshIOService::
757_createEmptyVariables(IMesh* mesh, const XmlNodeList& item_variables_node, eItemKind item_kind) const
758{
759 ARCANE_CHECK_PTR(mesh);
760 {
761 for (XmlNode xnode : item_variables_node) {
762 String name = xnode.attrValue("name");
763 debug() << "Create mesh variable: " << name;
764 String data_type_name = xnode.attrValue("data-type");
765 bool is_array = xnode.attrValue("is_array") == "true";
766 VariableRef* var = nullptr;
767 if (is_array) {
768 var = _createVar<ArrayVariableRootType>(mesh, name, data_type_name, item_kind);
769 }
770 else {
771 var = _createVar<VariableRootType>(mesh, name, data_type_name, item_kind);
772 }
773 mesh->variableMng()->_internalApi()->addAutoDestroyVariable(var);
774 }
775 }
776}
777
778/*---------------------------------------------------------------------------*/
779/*---------------------------------------------------------------------------*/
780
781void VtkPolyhedralMeshIOService::
782_createEmptyGroups([[maybe_unused]] IMesh* mesh, const XmlNodeList& groups_node,
783 IItemFamily* item_family) const
784{
785 for (XmlNode xnode : groups_node) {
786 String name = xnode.attrValue("name");
787 info() << "Building group: " << name;
788 item_family->createGroup(name);
789 }
790}
791
792/*---------------------------------------------------------------------------*/
793/*---------------------------------------------------------------------------*/
794
795void VtkPolyhedralMeshIOService::
796_createEmptyVariablesAndGroups(IMesh* mesh, XmlNode::const_reference variable_and_group_info) const
797{
798 ARCANE_CHECK_PTR(mesh);
799 auto document_node = variable_and_group_info.documentElement();
800 _createEmptyVariables<ItemVariableScalarRefT, ItemVariableArrayRefT>(mesh, document_node.children("cell-variable"), IK_Cell);
801 _createEmptyVariables<ItemVariableScalarRefT, ItemVariableArrayRefT>(mesh, document_node.children("node-variable"), IK_Node);
802 _createEmptyVariables<ItemVariableScalarRefT, ItemVariableArrayRefT>(mesh, document_node.children("face-variable"), IK_Face);
803
804 _createEmptyGroups(mesh, document_node.children("cell-group"), mesh->itemFamily(IK_Cell));
805 _createEmptyGroups(mesh, document_node.children("node-group"), mesh->itemFamily(IK_Node));
806 _createEmptyGroups(mesh, document_node.children("face-group"), mesh->itemFamily(IK_Face));
807}
808
809/*---------------------------------------------------------------------------*/
810/*---------------------------------------------------------------------------*/
811
812VtkPolyhedralMeshIOService::VtkReader::
813VtkReader(const String& filename, VtkPolyhedralTools::PrintInfoLevel print_info_level)
814: m_filename{ filename }
815, m_print_info_level{ print_info_level }
816{
817 m_is_empty = false;
818 m_do_read = true;
819 if (filename.empty()) {
820 m_read_status.failure = true;
821 m_read_status.failure_message = "filename for polyhedral vtk mesh is empty.";
822 return;
823 }
824 if (filename.endsWith("vtk"))
825 _readPlainTextVtkGrid(filename);
826 else if (filename.endsWith("vtu"))
827 _readXlmVtkGrid(filename);
828 else {
829 m_read_status.failure = true;
830 m_read_status.failure_message = String::format("Unsupported vtk extension for file {0}. Supported vtk extension for Polyhedral meshes are {1}",
831 filename, VtkReader::supportedVtkExtensions());
832 }
833 // Check vtk grid exists and not empty
834 if (!m_vtk_grid) {
835 m_read_status.failure = true;
836 m_read_status.failure_message = String::format("Cannot read vtk polyhedral file {0}. Vtk grid was not created.", filename);
837 return;
838 }
839 if (m_vtk_grid->GetNumberOfCells() == 0) {
840 m_read_status.failure = true;
841 m_read_status.failure_message = String::format("Cannot read vtk polyhedral file {0}. No cells were found.", filename);
842 return;
843 }
844 if (!m_vtk_grid->GetFaces()) {
845 m_read_status.failure = true;
846 m_read_status.failure_message = String::format("The given mesh vtk file {0} is not a polyhedral mesh, cannot read it", filename);
847 return;
848 }
849
850 m_cell_data = m_vtk_grid->GetCellData();
851 m_point_data = m_vtk_grid->GetPointData();
852
853 // Read face info (for variables and groups) if present
854 String faces_filename = m_filename + "faces.vtk";
855 std::ifstream ifile(faces_filename.localstr());
856 if (ifile) {
857 _readPlainTextVtkFaceGrid(faces_filename);
858 }
859 else {
860 faces_filename = m_filename + "faces.vtp";
861 ifile = std::ifstream{ faces_filename.localstr() };
862 if (ifile) {
863 _readXmlVtkFaceGrid(faces_filename);
864 }
865 }
866
867 StringUniqueArray faces_filename_and_extension;
868 faces_filename.split(faces_filename_and_extension, '.');
869
870 if (!ifile) {
871 m_read_status.info_message = String::format("Information no face mesh given {0}{1} (.vtk or .vtp) to define face variables or groups on faces.",
872 faces_filename_and_extension[0],
873 faces_filename_and_extension[1]);
874 }
875 else {
876 if (m_vtk_face_grid) { // Check face vtk grid exists and not empty
877 if (m_vtk_face_grid->GetNumberOfCells() == 0) {
878 m_read_status.failure = true;
879 m_read_status.failure_message = m_read_status.failure_message + String::format(" Error in reading face information for groups in mesh file {0} ", faces_filename);
880 }
881 else {
882 m_face_data = m_vtk_face_grid->GetCellData();
883 m_poly_data = m_vtk_face_grid->GetPolys();
884 }
885 }
886 else {
887 m_read_status.failure = true;
888 m_read_status.failure_message = m_read_status.failure_message + String::format("Face data could not be built from file {0}{1} (.vtk or .vtu).", faces_filename_and_extension[0], faces_filename_and_extension[1]);
889 }
890 }
891
892 if (m_print_info_level.print_mesh_info)
893 _printMeshInfos();
894}
895
896/*---------------------------------------------------------------------------*/
897/*---------------------------------------------------------------------------*/
898
899Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
900cellUids()
901{
902 if (!doRead())
903 return m_cell_uids;
904 if (m_cell_uids.empty()) {
905 _checkVtkGrid();
906 m_cell_uids.reserve(m_vtk_grid->GetNumberOfCells());
907 m_cell_nb_nodes.reserve(m_vtk_grid->GetNumberOfCells());
908 m_cell_node_uids.reserve(10 * m_vtk_grid->GetNumberOfCells()); // take a mean of 10 nodes per cell
909 auto* cell_iter = m_vtk_grid->NewCellIterator();
910 cell_iter->InitTraversal();
911 while (!cell_iter->IsDoneWithTraversal()) {
912 m_cell_uids.push_back(cell_iter->GetCellId());
913 m_cell_nb_nodes.push_back(Integer(cell_iter->GetNumberOfPoints()));
914 ArrayView<vtkIdType> cell_nodes{ Integer(cell_iter->GetNumberOfPoints()), cell_iter->GetPointIds()->GetPointer(0) };
915 std::for_each(cell_nodes.begin(), cell_nodes.end(), [this](auto uid) { this->m_cell_node_uids.push_back(uid); });
916 cell_iter->GoToNextCell();
917 }
918 }
919 return m_cell_uids;
920}
921
922/*---------------------------------------------------------------------------*/
923/*---------------------------------------------------------------------------*/
924
925Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
926nodeUids()
927{
928 if (!doRead())
929 return m_node_uids;
930 if (m_node_uids.empty()) {
931 _checkVtkGrid();
932 auto nb_nodes = m_vtk_grid->GetNumberOfPoints();
933 m_node_uids.resize(nb_nodes);
934 m_node_nb_cells.resize(nb_nodes);
935 m_node_cell_uids.reserve(8 * nb_nodes);
936 m_node_uid_to_index.resize(nb_nodes);
937 for (int node_index = 0; node_index < nb_nodes; ++node_index) {
938 Int64 node_uid = node_index;
939 m_node_uids[node_index] = node_uid;
940 auto cell_nodes = vtkIdList::New();
941 m_vtk_grid->GetPointCells(node_index, cell_nodes);
942 Int64Span cell_nodes_view((Int64*)cell_nodes->GetPointer(0), cell_nodes->GetNumberOfIds());
943 m_node_cell_uids.addRange(cell_nodes_view);
944 m_node_nb_cells[node_index] = (Int32)cell_nodes->GetNumberOfIds();
945 // uid and index might differ in the future (ex parallel read).
946 // This structure is created to be used in faceUids. Should be a map if node_uid is no longer the node index
947 m_node_uid_to_index[node_uid] = node_index;
948 }
949 }
950 return m_node_uids;
951}
952
953/*---------------------------------------------------------------------------*/
954/*---------------------------------------------------------------------------*/
955
956Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
957faceUids()
958{
959 // Needs nodeUids to be called first (no work done if already called)
960 nodeUids();
961
962 if (!doRead())
963 return m_face_uids;
964 if (!m_face_uids.empty())
965 return m_face_uids;
966 _checkVtkGrid();
967 auto* cell_iter = m_vtk_grid->NewCellIterator();
968 cell_iter->InitTraversal();
969 vtkIdType nb_face_estimation = 0;
970 while (!cell_iter->IsDoneWithTraversal()) {
971 vtkIdType cell_nb_faces = 0;
972 vtkIdType_generic* points{ nullptr };
973 m_vtk_grid->GetFaceStream(cell_iter->GetCellId(), cell_nb_faces, points);
974 nb_face_estimation += cell_nb_faces;
975 cell_iter->GoToNextCell();
976 }
977 m_face_uids.reserve(nb_face_estimation);
978 auto const* faces = m_vtk_grid->GetFaces();
979 // This array contains the face info per cells (cf. vtk file)
980 // first_cell_nb_faces first_cell_first_face_nb_nodes first_cell_first_face_node_1 ... first_cell_first_face_node_n first_cell_second_face_nb_nodes etc
981
982 if (!faces) {
983 ARCANE_FATAL("Mesh {0} is not polyhedral: faces are not defined", m_filename);
984 }
985 Int64 face_uid = 0;
986 auto face_info_size = faces->GetNumberOfValues();
987 m_face_node_uids.reserve(face_info_size);
988 m_face_nb_nodes.reserve(nb_face_estimation);
989 m_face_cell_uids.reserve(2 * nb_face_estimation);
990 m_face_nb_cells.reserve(nb_face_estimation);
991 m_cell_face_uids.reserve(8 * m_cell_uids.size()); // take a mean of 8 faces per cell
992 m_cell_nb_faces.resize(m_cell_uids.size(), 0);
993 m_cell_face_indexes.resize(m_cell_uids.size(), -1);
994 m_face_uid_indexes.resize(2 * nb_face_estimation, -1);
995 Int64UniqueArray current_face_nodes, sorted_current_face_nodes;
996 current_face_nodes.reserve(10);
997 sorted_current_face_nodes.reserve(10);
998 UniqueArray<UniqueArray<Int64>> node_faces(m_node_uids.size());
999 UniqueArray<Int32> face_offsets;
1000 face_offsets.reserve(nb_face_estimation);
1001 face_offsets.push_back(0);
1002 FaceUidToIndexMap face_uid_to_index;
1003 face_uid_to_index.reserve(nb_face_estimation);
1004 auto cell_index = 0;
1005 auto cell_face_index = 0;
1006 auto global_face_index = 0;
1007 auto face_uid_index = 0;
1008 for (int face_info_index = 0; face_info_index < face_info_size; cell_index++) { // face data are given by cell
1009 auto current_cell_nb_faces = Int32(faces->GetValue(face_info_index++));
1010 m_cell_face_indexes[m_cell_uids[cell_index]] = cell_face_index;
1011 for (auto face_index = 0; face_index < current_cell_nb_faces; ++face_index, ++global_face_index) {
1012 auto current_face_nb_nodes = Int32(faces->GetValue(face_info_index++));
1013 m_cell_nb_faces[m_cell_uids[cell_index]] += 1;
1014 for (int node_index = 0; node_index < current_face_nb_nodes; ++node_index) {
1015 current_face_nodes.push_back(faces->GetValue(face_info_index++));
1016 }
1017 sorted_current_face_nodes.resize(current_face_nodes.size());
1018 auto is_front_cell = mesh_utils::reorderNodesOfFace(current_face_nodes, sorted_current_face_nodes);
1019 auto [is_face_found, existing_face_index] = _findFace(sorted_current_face_nodes, node_faces,
1020 m_node_uid_to_index, m_face_nb_nodes,
1021 face_uid_to_index, face_offsets, m_face_node_uids);
1022 if (!is_face_found) {
1023 for (auto node_uid : current_face_nodes) {
1024 node_faces[m_node_uid_to_index[node_uid]].push_back(face_uid);
1025 }
1026 m_cell_face_uids.push_back(face_uid);
1027 m_face_uids.push_back(face_uid); // todo parallel
1028 m_face_nb_nodes.push_back(current_face_nb_nodes);
1029 m_face_node_uids.addRange(sorted_current_face_nodes);
1030 m_face_nb_cells.push_back(1);
1031 m_face_uid_indexes[global_face_index] = face_uid_index;
1032 face_uid_to_index.push_back(face_uid_index);
1033 auto previous_offset = face_offsets.back();
1034 face_offsets.push_back(previous_offset + sorted_current_face_nodes.size());
1035 ++face_uid;
1036 ++face_uid_index;
1037 if (is_front_cell) {
1038 m_face_cell_uids.push_back(NULL_ITEM_UNIQUE_ID);
1039 m_face_cell_uids.push_back(m_cell_uids[cell_index]);
1040 }
1041 else {
1042 m_face_cell_uids.push_back(m_cell_uids[cell_index]);
1043 m_face_cell_uids.push_back(NULL_ITEM_UNIQUE_ID);
1044 }
1045 }
1046 else {
1047 m_cell_face_uids.push_back(m_face_uids[existing_face_index]);
1048 m_face_nb_cells[existing_face_index] += 1;
1049 m_face_uid_indexes[global_face_index] = existing_face_index;
1050 // add cell to face cell connectivity
1051 if (is_front_cell) {
1052 if (m_face_cell_uids[2 * existing_face_index + 1] != NULL_ITEM_UNIQUE_ID) {
1053 ARCANE_FATAL("Problem in face orientation, face uid {0}, nodes {1}, same orientation in cell {2} and {3}. Change mesh file.",
1054 m_face_uids[existing_face_index],
1055 current_face_nodes,
1056 m_face_cell_uids[2 * existing_face_index + 1],
1057 m_cell_uids[cell_index]);
1058 }
1059 m_face_cell_uids[2 * existing_face_index + 1] = m_cell_uids[cell_index];
1060 }
1061 else {
1062 if (m_face_cell_uids[2 * existing_face_index] != NULL_ITEM_UNIQUE_ID) {
1063 ARCANE_FATAL("Problem in face orientation, face uid {0}, nodes {1}, same orientation in cell {2} and {3}. Change mesh file.",
1064 m_face_uids[existing_face_index],
1065 current_face_nodes,
1066 m_face_cell_uids[2 * existing_face_index],
1067 m_cell_uids[cell_index]);
1068 }
1069 m_face_cell_uids[2 * existing_face_index] = m_cell_uids[cell_index];
1070 }
1071 }
1072 current_face_nodes.clear();
1073 sorted_current_face_nodes.clear();
1074 }
1075 cell_face_index += m_cell_nb_faces[m_cell_uids[cell_index]];
1076 }
1077 // fill node_face_uids and node_nb_faces from node_faces (array form [nb_nodes][nb_connected_faces])
1078 m_node_nb_faces.resize(m_node_uids.size(), 0);
1079 _flattenConnectivity(node_faces.constSpan(), m_node_nb_faces, m_node_face_uids);
1080
1081 if (m_print_info_level.print_debug_info) {
1082 std::cout << "================FACE NODES ==============" << std::endl;
1083 std::copy(m_face_node_uids.begin(), m_face_node_uids.end(), std::ostream_iterator<Int64>(std::cout, " "));
1084 std::cout << std::endl;
1085 std::copy(m_face_nb_nodes.begin(), m_face_nb_nodes.end(), std::ostream_iterator<Int64>(std::cout, " "));
1086 std::cout << std::endl;
1087 std::copy(m_cell_face_indexes.begin(), m_cell_face_indexes.end(), std::ostream_iterator<Int64>(std::cout, " "));
1088 std::cout << std::endl;
1089 }
1090
1091 return m_face_uids;
1092}
1093
1094/*---------------------------------------------------------------------------*/
1095/*---------------------------------------------------------------------------*/
1096
1097Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1098edgeUids()
1099{
1100 if (!doRead())
1101 return m_edge_uids;
1102 if (!m_edge_uids.empty())
1103 return m_edge_uids;
1104
1105 nodeUids(); // Needed to be called first. No work done if already called
1106
1107 _checkVtkGrid();
1108 m_edge_uids.reserve(2 * m_vtk_grid->GetNumberOfPoints());
1109 auto const* faces = m_vtk_grid->GetFaces();
1110 // This array contains the face info per cells (cf. vtk file)
1111 // first_cell_nb_faces first_cell_first_face_nb_nodes first_cell_first_face_node_1 ... first_cell_first_face_node_n first_cell_second_face_nb_nodes etc
1112
1113 if (!faces) {
1114 ARCANE_FATAL("Mesh {0} is not polyhedral: faces are not defined", m_filename);
1115 }
1116 Int64 edge_uid = 0;
1117 auto nb_edge_estimation = 2 * m_edge_uids.capacity();
1118 m_edge_node_uids.reserve(nb_edge_estimation);
1119 auto face_info_size = faces->GetNumberOfValues();
1120 auto cell_index = 0;
1121 auto global_face_index = 0;
1122 auto new_edge_index = 0;
1123 UniqueArray<std::set<Int64>> edge_cells;
1124 UniqueArray<Int64UniqueArray> edge_faces;
1125 edge_cells.reserve(m_edge_uids.capacity());
1126 edge_faces.reserve(m_edge_uids.capacity());
1127 m_cell_nb_edges.resize(m_cell_uids.size(), 0);
1128 m_cell_edge_uids.reserve(20 * m_cell_uids.size()); // choose a value of 20 edge per cell
1129 UniqueArray<std::set<Int64>> face_edges;
1130 face_edges.resize(m_face_uids.size());
1131 UniqueArray<std::set<Int64>> cell_edges;
1132 cell_edges.resize(m_cell_uids.size());
1133 UniqueArray<Int64UniqueArray> node_edges;
1134 node_edges.resize(m_node_uids.size());
1135 EdgeUidToIndexMap edge_uid_to_index;
1136 edge_uid_to_index.reserve(nb_edge_estimation);
1137 Int32UniqueArray edge_offsets;
1138 edge_offsets.reserve(nb_edge_estimation);
1139 edge_offsets.push_back(0);
1140 m_edge_nb_nodes.reserve(nb_edge_estimation);
1141 for (int face_info_index = 0; face_info_index < face_info_size; ++cell_index) {
1142 auto current_cell_nb_faces = Int32(faces->GetValue(face_info_index++));
1143 for (auto face_index = 0; face_index < current_cell_nb_faces; ++face_index, ++global_face_index) {
1144 auto current_face_nb_nodes = Int32(faces->GetValue(face_info_index++));
1145 auto first_face_node_uid = Int32(faces->GetValue(face_info_index));
1146 UniqueArray<Int64> current_edge(2), sorted_edge(2);
1147 for (int node_index = 0; node_index < current_face_nb_nodes - 1; ++node_index) {
1148 current_edge = UniqueArray<Int64>{ faces->GetValue(face_info_index++), faces->GetValue(face_info_index) };
1149 mesh_utils::reorderNodesOfFace(current_edge, sorted_edge); // works for edges
1150 auto [is_edge_found, existing_edge_index] = _findFace(sorted_edge, node_edges,
1151 m_node_uid_to_index,
1152 m_edge_nb_nodes,
1153 edge_uid_to_index, edge_offsets, m_edge_node_uids); // works for edges
1154 if (!is_edge_found) {
1155 m_cell_nb_edges[cell_index] += 1;
1156 face_edges[m_face_uid_indexes[global_face_index]].insert(edge_uid);
1157 cell_edges[cell_index].insert(edge_uid);
1158 for (auto node : current_edge) {
1159 node_edges[node].push_back(edge_uid);
1160 }
1161 edge_cells.push_back(std::set{ m_cell_uids[cell_index] });
1162 edge_faces.push_back(Int64UniqueArray{ m_cell_face_uids[m_cell_face_indexes[cell_index] + face_index] });
1163 m_edge_uids.push_back(edge_uid++); // todo parallel
1164 m_edge_node_uids.addRange(sorted_edge);
1165 edge_uid_to_index.push_back(new_edge_index);
1166 auto current_offset = edge_offsets.back();
1167 edge_offsets.push_back(current_offset + 2);
1168 m_edge_nb_nodes.push_back(2);
1169 ++new_edge_index;
1170 }
1171 else {
1172 edge_cells[existing_edge_index].insert(m_cell_uids[cell_index]);
1173 edge_faces[existing_edge_index].push_back(m_cell_face_uids[m_cell_face_indexes[cell_index] + face_index]);
1174 face_edges[m_face_uid_indexes[global_face_index]].insert(m_edge_uids[existing_edge_index]);
1175 cell_edges[cell_index].insert(m_edge_uids[existing_edge_index]);
1176 }
1177 }
1178 current_edge = UniqueArray<Int64>{ faces->GetValue(face_info_index++), first_face_node_uid };
1179 mesh_utils::reorderNodesOfFace(current_edge, sorted_edge); // works for edges
1180 auto [is_edge_found, existing_edge_index] = _findFace(sorted_edge, node_edges,
1181 m_node_uid_to_index,
1182 m_edge_nb_nodes,
1183 edge_uid_to_index, edge_offsets, m_edge_node_uids); // works for edges
1184 if (!is_edge_found) {
1185 m_cell_nb_edges[cell_index] += 1;
1186 edge_cells.push_back(std::set{ m_cell_uids[cell_index] });
1187 edge_faces.push_back(Int64UniqueArray{ m_cell_face_uids[m_cell_face_indexes[cell_index] + face_index] });
1188 face_edges[m_face_uid_indexes[global_face_index]].insert(edge_uid);
1189 cell_edges[cell_index].insert(edge_uid);
1190 for (auto node : current_edge) {
1191 node_edges[node].push_back(edge_uid);
1192 }
1193 m_edge_uids.push_back(edge_uid++); // todo parallel
1194 m_edge_node_uids.addRange(sorted_edge);
1195 edge_uid_to_index.push_back(new_edge_index);
1196 auto current_offset = edge_offsets.back();
1197 edge_offsets.push_back(current_offset + 2);
1198 m_edge_nb_nodes.push_back(2);
1199 ++new_edge_index;
1200 }
1201 else {
1202 edge_cells[existing_edge_index].insert(m_cell_uids[cell_index]);
1203 edge_faces[existing_edge_index].push_back(m_cell_face_uids[m_cell_face_indexes[cell_index] + face_index]);
1204 face_edges[m_face_uid_indexes[global_face_index]].insert(m_edge_uids[existing_edge_index]);
1205 cell_edges[cell_index].insert(m_edge_uids[existing_edge_index]);
1206 }
1207 }
1208 }
1209 // fill edge_cell_uids and edge_nb_cells from edge_cells (array form [nb_edges][nb_connected_cells])
1210 m_edge_nb_cells.resize(m_edge_uids.size(), 0);
1211 _flattenConnectivity(edge_cells.constSpan(), m_edge_nb_cells, m_edge_cell_uids);
1212
1213 // fill edge faces uids
1214 m_edge_nb_faces.resize(m_edge_uids.size(), 0);
1215 _flattenConnectivity(edge_faces.constSpan(), m_edge_nb_faces, m_edge_face_uids);
1216
1217 // fill face edge uids
1218 m_face_nb_edges.resize(m_face_uids.size(), 0);
1219 _flattenConnectivity(face_edges.constSpan(), m_face_nb_edges, m_face_edge_uids);
1220
1221 // fill cell edge uids
1222 m_cell_nb_edges.resize(m_cell_uids.size(), 0);
1223 _flattenConnectivity(cell_edges, m_cell_nb_edges, m_cell_edge_uids);
1224
1225 // fill node edge uids
1226 m_node_nb_edges.resize(m_node_uids.size(), 0);
1227 _flattenConnectivity(node_edges, m_node_nb_edges, m_node_edge_uids);
1228
1229 if (m_print_info_level.print_debug_info) {
1230 std::cout << "================EDGE NODES ==============" << std::endl;
1231 std::copy(m_edge_node_uids.begin(), m_edge_node_uids.end(), std::ostream_iterator<Int64>(std::cout, " "));
1232 std::cout << std::endl;
1233 std::cout << "================FACE EDGES ==============" << std::endl;
1234 std::copy(m_face_nb_edges.begin(), m_face_nb_edges.end(), std::ostream_iterator<Int32>(std::cout, " "));
1235 std::cout << std::endl;
1236 std::copy(m_face_edge_uids.begin(), m_face_edge_uids.end(), std::ostream_iterator<Int64>(std::cout, " "));
1237 std::cout << std::endl;
1238 std::cout << "================CELL EDGES ==============" << std::endl;
1239 std::copy(m_cell_nb_edges.begin(), m_cell_nb_edges.end(), std::ostream_iterator<Int32>(std::cout, " "));
1240 std::cout << std::endl;
1241 std::copy(m_cell_edge_uids.begin(), m_cell_edge_uids.end(), std::ostream_iterator<Int64>(std::cout, " "));
1242 std::cout << std::endl;
1243 }
1244 return m_edge_uids;
1245}
1246
1247/*---------------------------------------------------------------------------*/
1248/*---------------------------------------------------------------------------*/
1249
1250std::pair<bool, Int32> VtkPolyhedralMeshIOService::VtkReader::
1251_findFace(const Int64UniqueArray& sorted_face_nodes,
1252 const UniqueArray<Int64UniqueArray>& node_face_uids,
1253 const NodeUidToIndexMap& node_uid_to_index,
1254 const Int32UniqueArray& face_nb_nodes,
1255 const FaceUidToIndexMap& face_uid_to_index,
1256 const UniqueArray<Int32>& face_offsets,
1257 const Int64UniqueArray& face_node_uids)
1258{
1259 auto first_node_uid = sorted_face_nodes[0];
1260 auto first_node_index = node_uid_to_index[first_node_uid];
1261 // If the face already exists it has already been registered in node_face connectivity
1262 for (auto face_uid : node_face_uids[first_node_index]) {
1263 auto face_index = face_uid_to_index[face_uid];
1264 auto face_offset = face_offsets[face_index];
1265 auto face_nb_node = face_nb_nodes[face_index];
1266 if (face_nb_node == sorted_face_nodes.size()) {
1267 bool is_same_face = true;
1268 for (auto index = 0; index < face_nb_node; ++index) {
1269 if (sorted_face_nodes[index] != face_node_uids[face_offset + index]) {
1270 is_same_face = false;
1271 }
1272 }
1273 if (is_same_face)
1274 return { true, face_index };
1275 }
1276 }
1277 return { false, -1 };
1278}
1279
1280/*---------------------------------------------------------------------------*/
1281/*---------------------------------------------------------------------------*/
1282
1283Integer VtkPolyhedralMeshIOService::VtkReader::
1284nbNodes()
1285{
1286 if (m_node_uids.empty())
1287 nodeUids();
1288 return m_node_uids.size();
1289}
1290
1291/*---------------------------------------------------------------------------*/
1292/*---------------------------------------------------------------------------*/
1293
1294Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1295cellNodes()
1296{
1297 if (m_cell_node_uids.empty())
1298 cellUids();
1299 return m_cell_node_uids;
1300}
1301
1302/*---------------------------------------------------------------------------*/
1303/*---------------------------------------------------------------------------*/
1304
1305Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1306cellNbNodes()
1307{
1308 if (m_cell_nb_nodes.empty())
1309 cellUids();
1310 return m_cell_nb_nodes;
1311}
1312
1313/*---------------------------------------------------------------------------*/
1314/*---------------------------------------------------------------------------*/
1315
1316Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1317faceNodes()
1318{
1319 if (m_face_node_uids.empty())
1320 faceUids();
1321 return m_face_node_uids;
1322}
1323
1324/*---------------------------------------------------------------------------*/
1325/*---------------------------------------------------------------------------*/
1326
1327Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1328faceNbNodes()
1329{
1330 if (m_face_nb_nodes.empty())
1331 faceUids();
1332 return m_face_nb_nodes;
1333}
1334
1335/*---------------------------------------------------------------------------*/
1336/*---------------------------------------------------------------------------*/
1337
1338Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1339faceNodesInFaceMesh()
1340{
1341 if (m_face_node_uids_in_face_mesh.empty())
1342 _readfaceNodesInFaceMesh();
1343 return m_face_node_uids_in_face_mesh;
1344}
1345
1346/*---------------------------------------------------------------------------*/
1347/*---------------------------------------------------------------------------*/
1348
1349Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1350faceNbNodesInFaceMesh()
1351{
1352 if (m_face_nb_nodes_in_face_mesh.empty())
1353 _readfaceNodesInFaceMesh();
1354 return m_face_nb_nodes_in_face_mesh;
1355}
1356
1357/*---------------------------------------------------------------------------*/
1358/*---------------------------------------------------------------------------*/
1359
1360Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1361edgeNbNodes()
1362{
1363 if (m_edge_node_uids.empty())
1364 edgeUids();
1365 return m_edge_nb_nodes;
1366}
1367
1368/*---------------------------------------------------------------------------*/
1369/*---------------------------------------------------------------------------*/
1370
1371Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1372edgeNodes()
1373{
1374 if (m_edge_node_uids.empty())
1375 edgeUids();
1376 return m_edge_node_uids;
1377}
1378
1379/*---------------------------------------------------------------------------*/
1380/*---------------------------------------------------------------------------*/
1381
1382Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1383faceCells()
1384{
1385 if (m_face_cell_uids.empty())
1386 faceUids();
1387 // debug
1388 if (m_print_info_level.print_debug_info) {
1389 std::cout << "=================FACE CELLS================="
1390 << "\n";
1391 std::copy(m_face_cell_uids.begin(), m_face_cell_uids.end(), std::ostream_iterator<Int64>(std::cout, " "));
1392 std::cout << "\n";
1393 std::cout << "=================END FACE CELLS================="
1394 << "\n";
1395 }
1396 return m_face_cell_uids;
1397}
1398
1399/*---------------------------------------------------------------------------*/
1400/*---------------------------------------------------------------------------*/
1401
1402Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1403faceNbCells()
1404{
1405 if (m_face_nb_cells.empty())
1406 faceUids();
1407 return m_face_nb_cells;
1408}
1409
1410/*---------------------------------------------------------------------------*/
1411/*---------------------------------------------------------------------------*/
1412
1413Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1414edgeNbCells()
1415{
1416 if (m_edge_nb_cells.empty())
1417 edgeUids();
1418 return m_edge_nb_cells;
1419}
1420
1421/*---------------------------------------------------------------------------*/
1422/*---------------------------------------------------------------------------*/
1423
1424Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1425edgeCells()
1426{
1427 if (m_edge_cell_uids.empty())
1428 edgeUids();
1429 return m_edge_cell_uids;
1430}
1431
1432/*---------------------------------------------------------------------------*/
1433/*---------------------------------------------------------------------------*/
1434
1435Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1436cellNbFaces()
1437{
1438 if (m_cell_nb_faces.empty())
1439 faceUids();
1440 return m_cell_nb_faces;
1441}
1442
1443/*---------------------------------------------------------------------------*/
1444/*---------------------------------------------------------------------------*/
1445
1446Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1447cellFaces()
1448{
1449 if (m_cell_face_uids.empty())
1450 faceUids();
1451 return m_cell_face_uids;
1452}
1453
1454/*---------------------------------------------------------------------------*/
1455/*---------------------------------------------------------------------------*/
1456
1457Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1458edgeNbFaces()
1459{
1460 if (m_edge_nb_faces.empty())
1461 edgeUids();
1462 return m_edge_nb_faces;
1463}
1464
1465/*---------------------------------------------------------------------------*/
1466/*---------------------------------------------------------------------------*/
1467
1468Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1469edgeFaces()
1470{
1471 if (m_edge_face_uids.empty())
1472 edgeUids();
1473 return m_edge_face_uids;
1474}
1475
1476/*---------------------------------------------------------------------------*/
1477/*---------------------------------------------------------------------------*/
1478
1479Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1480cellNbEdges()
1481{
1482 if (m_cell_nb_edges.empty())
1483 edgeUids();
1484 return m_cell_nb_edges;
1485}
1486
1487/*---------------------------------------------------------------------------*/
1488/*---------------------------------------------------------------------------*/
1489
1490Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1491cellEdges()
1492{
1493 if (m_cell_edge_uids.empty())
1494 edgeUids();
1495 return m_cell_edge_uids;
1496}
1497
1498/*---------------------------------------------------------------------------*/
1499/*---------------------------------------------------------------------------*/
1500
1501Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1502faceNbEdges()
1503{
1504 if (m_face_nb_edges.empty())
1505 edgeUids();
1506 return m_face_nb_edges;
1507}
1508
1509/*---------------------------------------------------------------------------*/
1510/*---------------------------------------------------------------------------*/
1511
1512Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1513faceEdges()
1514{
1515 if (m_face_edge_uids.empty())
1516 edgeUids();
1517 return m_face_edge_uids;
1518}
1519
1520/*---------------------------------------------------------------------------*/
1521/*---------------------------------------------------------------------------*/
1522
1523template <typename Connectivity2DArray>
1524void VtkPolyhedralMeshIOService::VtkReader::
1525_flattenConnectivity(Connectivity2DArray connected_item_2darray,
1526 Int32Span nb_connected_item_per_source_item,
1527 Int64UniqueArray& connected_item_array)
1528{
1529 // fill nb_connected_item_per_source_items
1530 std::transform(connected_item_2darray.begin(), connected_item_2darray.end(), nb_connected_item_per_source_item.begin(), [](auto const& connected_items) {
1531 return connected_items.size();
1532 });
1533 // fill connected_item_array
1534 connected_item_array.reserve(std::accumulate(nb_connected_item_per_source_item.begin(), nb_connected_item_per_source_item.end(), 0));
1535 std::for_each(connected_item_2darray.begin(), connected_item_2darray.end(), [&connected_item_array](auto const& connected_items) {
1536 for (auto const& connected_item : connected_items) {
1537 connected_item_array.push_back(connected_item);
1538 }
1539 });
1540}
1541
1542/*---------------------------------------------------------------------------*/
1543/*---------------------------------------------------------------------------*/
1544
1545Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1546nodeNbCells()
1547{
1548 if (m_node_nb_cells.empty())
1549 nodeUids();
1550 return m_node_nb_cells;
1551}
1552
1553/*---------------------------------------------------------------------------*/
1554/*---------------------------------------------------------------------------*/
1555
1556Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1557nodeCells()
1558{
1559 if (m_node_cell_uids.empty())
1560 nodeUids();
1561 return m_node_cell_uids;
1562}
1563
1564/*---------------------------------------------------------------------------*/
1565/*---------------------------------------------------------------------------*/
1566
1567Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1568nodeNbFaces()
1569{
1570 if (m_node_nb_faces.empty())
1571 faceUids();
1572 return m_node_nb_faces;
1573}
1574
1575/*---------------------------------------------------------------------------*/
1576/*---------------------------------------------------------------------------*/
1577
1578Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1579nodeFaces()
1580{
1581 if (m_node_face_uids.empty())
1582 faceUids();
1583 return m_node_face_uids;
1584}
1585
1586/*---------------------------------------------------------------------------*/
1587/*---------------------------------------------------------------------------*/
1588
1589Int32ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1590nodeNbEdges()
1591{
1592 if (m_node_nb_edges.empty())
1593 edgeUids();
1594 return m_node_nb_edges;
1595}
1596
1597/*---------------------------------------------------------------------------*/
1598/*---------------------------------------------------------------------------*/
1599
1600Int64ConstArrayView VtkPolyhedralMeshIOService::VtkReader::
1601nodeEdges()
1602{
1603 if (m_node_edge_uids.empty())
1604 edgeUids();
1605 return m_node_edge_uids;
1606}
1607
1608/*---------------------------------------------------------------------------*/
1609/*---------------------------------------------------------------------------*/
1610
1611Real3ArrayView VtkPolyhedralMeshIOService::VtkReader::
1612nodeCoords()
1613{
1614 if (!doRead())
1615 return m_node_coordinates;
1616 if (m_node_coordinates.empty()) {
1617 _checkVtkGrid();
1618 auto point_coords = m_vtk_grid->GetPoints()->GetData();
1619 if (m_print_info_level.print_debug_info) {
1620 std::cout << "======= Point COORDS ====" << std::endl;
1621 std::ostringstream oss;
1622 point_coords->PrintSelf(oss, vtkIndent{ 2 });
1623 std::cout << oss.str() << std::endl;
1624 }
1625 auto nb_nodes = m_vtk_grid->GetNumberOfPoints();
1626 for (int i = 0; i < nb_nodes; ++i) {
1627 if (m_print_info_level.print_debug_info) {
1628 std::cout << "==========current point coordinates : ( ";
1629 std::cout << *(point_coords->GetTuple(i)) << " , ";
1630 std::cout << *(point_coords->GetTuple(i) + 1) << " , ";
1631 std::cout << *(point_coords->GetTuple(i) + 2) << " ) ===" << std::endl;
1632 }
1633 m_node_coordinates.add({ *(point_coords->GetTuple(i)),
1634 *(point_coords->GetTuple(i) + 1),
1635 *(point_coords->GetTuple(i) + 2) });
1636 }
1637 }
1638 return m_node_coordinates;
1639}
1640
1641/*---------------------------------------------------------------------------*/
1642/*---------------------------------------------------------------------------*/
1643
1644vtkCellData* VtkPolyhedralMeshIOService::VtkReader::
1645cellData()
1646{
1647 return m_cell_data;
1648}
1649
1650/*---------------------------------------------------------------------------*/
1651/*---------------------------------------------------------------------------*/
1652
1653vtkPointData* VtkPolyhedralMeshIOService::VtkReader::
1654pointData()
1655{
1656 return m_point_data;
1657}
1658
1659/*---------------------------------------------------------------------------*/
1660/*---------------------------------------------------------------------------*/
1661
1662void VtkPolyhedralMeshIOService::VtkReader::
1663_printMeshInfos() const
1664{
1665 _checkVtkGrid();
1666 std::cout << "-- VTK GRID READ "
1667 << " NB CELLS " << m_vtk_grid->GetNumberOfCells() << std::endl;
1668 // Parse cells
1669 auto* cell_iter = m_vtk_grid->vtkDataSet::NewCellIterator();
1670 cell_iter->InitTraversal();
1671 vtkIdType_generic* cell_faces{ nullptr };
1672 vtkIdType nb_faces = 0;
1673 while (!cell_iter->IsDoneWithTraversal()) {
1674 std::cout << "---- visiting cell id " << cell_iter->GetCellId() << std::endl;
1675 std::cout << "---- cell number of faces " << cell_iter->GetNumberOfFaces() << std::endl;
1676 std::cout << "---- cell number of points " << cell_iter->GetNumberOfPoints() << std::endl;
1677 m_vtk_grid->GetFaceStream(cell_iter->GetCellId(), nb_faces, cell_faces);
1678 for (auto iface = 0; iface < nb_faces; ++iface) {
1679 auto face_nb_nodes = *cell_faces++;
1680 std::cout << "---- has face with " << face_nb_nodes << " nodes. Node ids : ";
1681 for (int inode = 0; inode < face_nb_nodes; ++inode) {
1682 std::cout << *cell_faces++ << " ";
1683 }
1684 std::cout << std::endl;
1685 }
1686 cell_iter->GoToNextCell();
1687 }
1688}
1689
1690/*---------------------------------------------------------------------------*/
1691/*---------------------------------------------------------------------------*/
1692
1693vtkCellData* VtkPolyhedralMeshIOService::VtkReader::faceData()
1694{
1695 return m_face_data;
1696}
1697/*---------------------------------------------------------------------------*/
1698/*---------------------------------------------------------------------------*/
1699
1700/*---------------------------------------------------------------------------*/
1701/*---------------------------------------------------------------------------*/
1702
1703void VtkPolyhedralMeshIOService::VtkReader::
1704_readPlainTextVtkGrid(const String& filename)
1705{
1706 m_vtk_grid_reader->SetFileName(filename.localstr());
1707 m_vtk_grid_reader->ReadAllScalarsOn();
1708 m_vtk_grid_reader->Update();
1709 m_vtk_grid = m_vtk_grid_reader->GetOutput();
1710}
1711
1712/*---------------------------------------------------------------------------*/
1713/*---------------------------------------------------------------------------*/
1714
1715void VtkPolyhedralMeshIOService::VtkReader::
1716_readXlmVtkGrid(const String& filename)
1717{
1718 m_vtk_xml_grid_reader->SetFileName(filename.localstr());
1719 m_vtk_xml_grid_reader->Update();
1720 m_vtk_grid = m_vtk_xml_grid_reader->GetOutput();
1721}
1722
1723/*---------------------------------------------------------------------------*/
1724/*---------------------------------------------------------------------------*/
1725
1726void VtkPolyhedralMeshIOService::VtkReader::
1727_readPlainTextVtkFaceGrid(const String& faces_filename)
1728{
1729 m_vtk_face_grid_reader->SetFileName(faces_filename.localstr());
1730 m_vtk_face_grid_reader->ReadAllScalarsOn();
1731 m_vtk_face_grid_reader->Update();
1732 m_vtk_face_grid = m_vtk_face_grid_reader->GetOutput();
1733}
1734
1735/*---------------------------------------------------------------------------*/
1736/*---------------------------------------------------------------------------*/
1737
1738void VtkPolyhedralMeshIOService::VtkReader::
1739_readXmlVtkFaceGrid(const String& faces_filename)
1740{
1741 m_vtk_xml_face_grid_reader->SetFileName(faces_filename.localstr());
1742 m_vtk_xml_face_grid_reader->Update();
1743 m_vtk_face_grid = m_vtk_xml_face_grid_reader->GetOutput();
1744}
1745
1746/*---------------------------------------------------------------------------*/
1747/*---------------------------------------------------------------------------*/
1748
1749void VtkPolyhedralMeshIOService::VtkReader::
1750_readfaceNodesInFaceMesh()
1751{
1752 m_face_nb_nodes_in_face_mesh.resize(m_poly_data->GetNumberOfCells());
1753 m_face_node_uids_in_face_mesh.reserve(m_poly_data->GetNumberOfCells() * m_poly_data->GetMaxCellSize());
1754 m_poly_data->InitTraversal();
1755 vtkIdType face_nb_nodes;
1756 vtkIdType_generic* face_nodes;
1757
1758 auto face_nb_node_index = 0;
1759 Int64UniqueArray current_face_node_uids;
1760 Int64UniqueArray reordered_current_face_node_uids;
1761 current_face_node_uids.reserve(m_poly_data->GetMaxCellSize());
1762 reordered_current_face_node_uids.reserve(m_poly_data->GetMaxCellSize());
1763 Int64UniqueArray reordered_face_node_uids(m_poly_data->GetMaxCellSize());
1764 while (m_poly_data->GetNextCell(face_nb_nodes, face_nodes)) {
1765 m_face_nb_nodes_in_face_mesh[face_nb_node_index] = face_nb_nodes;
1766 ConstArrayView<vtkIdType> face_nodes_view(face_nb_nodes, face_nodes);
1767 current_face_node_uids.resize(face_nb_nodes);
1768 reordered_current_face_node_uids.resize(face_nb_nodes);
1769 std::copy(face_nodes_view.begin(), face_nodes_view.end(), current_face_node_uids.begin());
1770 MeshUtils::reorderNodesOfFace(current_face_node_uids, reordered_current_face_node_uids);
1771 std::copy(reordered_current_face_node_uids.begin(), reordered_current_face_node_uids.end(), std::back_inserter(m_face_node_uids_in_face_mesh));
1772 ++face_nb_node_index;
1773 }
1774}
1775/*---------------------------------------------------------------------------*/
1776/*---------------------------------------------------------------------------*/
1777
1778void VtkPolyhedralMeshIOService::VtkReader::
1779_checkVtkGrid() const
1780{
1781 if (!m_vtk_grid)
1782 ARCANE_FATAL("Polyhedral vtk grid not loaded. Cannot continue.");
1783}
1784
1785/*---------------------------------------------------------------------------*/
1786/*---------------------------------------------------------------------------*/
1787
1788} // End namespace Arcane
1789
1790/*---------------------------------------------------------------------------*/
1791/*---------------------------------------------------------------------------*/
Arcane configuration file.
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Declarations of Arcane's general types.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Utility functions for the mesh.
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Management of references to a C++ class.
Generation de la classe de base du Service.
CaseOptionsVtkPolyhedralMeshIO * options() const
Options du jeu de données du service.
ArcaneVtkPolyhedralMeshIOObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
Necessary information for reading a mesh file.
Interface of an entity family.
Definition IItemFamily.h:83
virtual String name() const =0
Family name.
virtual Integer nbItem() const =0
Number of entities.
virtual String name() const =0
Mesh name.
Interface of a mesh creation/reading service.
virtual IVariableMng * variableMng() const =0
Associated variable manager.
virtual void addAutoDestroyVariable(VariableRef *var)=0
Adds the variable to the list of variables that are kept until the end of execution.
virtual IVariableMngInternal * _internalApi()=0
Internal Arcane API.
static IXmlDocumentHolder * loadFromBuffer(Span< const Byte > buffer, const String &name, ITraceMng *tm)
Loads an XML document.
Definition DomUtils.cc:425
Parameters necessary for building a mesh.
MeshBuildInfo & addNeedPartitioning(bool v)
Indicates whether the generator needs to call a partitioner.
MeshBuildInfo & addMeshKind(const MeshKind &v)
Sets the mesh characteristics.
MeshBuildInfo & addFactoryName(const String &factory_name)
Sets the factory name to create this mesh.
Characteristics of a mesh.
Definition MeshKind.h:113
Reference to an instance.
Structure containing the information to create a service.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
Information characterizing a variable.
Reference to a variable.
Definition VariableRef.h:56
void fillMeshBuildInfo(MeshBuildInfo &build_info) override
Fills build_info with the necessary information to create the mesh.
void allocateMeshItems(IPrimaryMesh *pm) override
Allocates the mesh entities managed by this service.
Ref< IMeshBuilder > createBuilder(const CaseMeshReaderReadInfo &read_info) const override
Returns a builder to create and read the mesh whose information is specified in read_info.
List of nodes of a DOM tree.
Definition XmlNodeList.h:36
const value_type & const_reference
Type constant reference of an element in the array.
Definition XmlNode.h:67
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
Integer len(const char *s)
Returns the length of the string s.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Span< Int64 > Int64Span
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:514
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
std::int64_t Int64
Signed integer type of 64 bits.
ArrayView< Real3 > Real3ArrayView
C equivalent of a 1D array of Real3.
Definition UtilsTypes.h:461
Int32 Integer
Type representing an integer.
UniqueArray< Real3 > Real3UniqueArray
Dynamic 1D array of rank 3 vectors.
Definition UtilsTypes.h:357
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
@ Polyhedral
Polyhedral mesh.
Definition MeshKind.h:38
@ ST_CaseOption
The service is used at the dataset level.
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
UniqueArray< Byte > ByteUniqueArray
Dynamic 1D array of characters.
Definition UtilsTypes.h:329
SharedArray< Int32 > Int32SharedArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:375
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
eItemKind
Mesh entity type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
@ IK_Face
Face mesh entity.
@ IK_Edge
Edge mesh entity.
double Real
Type representing a real number.
ConstArrayView< Byte > ByteConstArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:470
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
UniqueArray< String > StringUniqueArray
Dynamic 1D array of strings.
Definition UtilsTypes.h:353
Span< Int32 > Int32Span
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:516
eDataType
Data type.
Definition DataTypes.h:41
@ DT_Int32
32-bit integer data type
Definition DataTypes.h:45
@ DT_Int64
64-bit integer data type
Definition DataTypes.h:46
@ DT_Unknown
Unknown or uninitialized data type.
Definition DataTypes.h:58
@ DT_Real
Real data type.
Definition DataTypes.h:43
Span< const Int32 > Int32ConstSpan
Read-only view of a 1D array of 32-bit integers.
Definition UtilsTypes.h:548
ARCANE_DATATYPE_EXPORT eDataType dataTypeFromName(const char *name, bool &has_error)
Finds the type associated with name.
Definition DataTypes.cc:94
const char * dataTypeName(eDataType type)
Data type name.
Definition DataTypes.cc:72
std::int32_t Int32
Signed integer type of 32 bits.