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