Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
VtkHdfPostProcessor.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* VtkHdfPostProcessor.cc (C) 2000-2023 */
9/* */
10/* Pos-traitement au format VTK HDF. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Collection.h"
15#include "arcane/utils/Enumerator.h"
16#include "arcane/utils/Iostream.h"
17#include "arcane/utils/ScopedPtr.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/CheckedConvert.h"
20#include "arcane/utils/JSONWriter.h"
21#include "arcane/utils/IOException.h"
22
23#include "arcane/core/PostProcessorWriterBase.h"
24#include "arcane/core/Directory.h"
25#include "arcane/core/FactoryService.h"
26#include "arcane/core/IDataWriter.h"
27#include "arcane/core/IData.h"
28#include "arcane/core/IItemFamily.h"
29#include "arcane/core/VariableCollection.h"
30#include "arcane/core/IParallelMng.h"
31#include "arcane/core/IMesh.h"
32
33#include "arcane/std/Hdf5Utils.h"
34#include "arcane/std/VtkHdfPostProcessor_axl.h"
35#include "arcane/std/internal/VtkCellTypes.h"
36
37// Ce format est décrit sur la page web suivante:
38//
39// https://kitware.github.io/vtk-examples/site/VTKFileFormats/#hdf-file-formats
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44// TODO: Regarder la sauvegarde des uniqueId() (via vtkOriginalCellIds)
45// TODO: Regarder comment éviter de sauver le maillage à chaque itération s'il
46// ne change pas. Avec la notion de lien de HDF5, il doit être possible
47// de mettre cette information ailleurs et de ne sauver le maillage
48// que s'il évolue.
49// TODO: Regarder la compression
50
51/*
52 NOTE sur l'implémentation parallèle
53
54 L'implémentation actuelle est très basique.
55 Seul le rang maitre (le rang 0 en général) effectue les sorties. Pour
56 chaque dataset, ce rang fait un gather pour récupérer les informations. Cela
57 suppose donc que tout le monde a les mêmes variables et dans le même ordre
58 (normalement c'est toujours le cas car c'est trié par la VariableMng).
59
60 Cette implémentation fonctionne donc quel que soit le mode d'échange de
61 message utilisé (full MPI, mémoire partagé ou hybride).
62
63 TODO: Découpler l'écriture de la gestion des variables pour pouvoir utiliser
64 les opérations collectives de HDF5 (si compilé avec MPI). Dans ce cas il
65 faut quand même géré manuellement le mode échange de message en mémoire
66 partagée ou hybride.
67*/
68/*---------------------------------------------------------------------------*/
69/*---------------------------------------------------------------------------*/
70
71namespace Arcane
72{
73using namespace Hdf5Utils;
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
79: public TraceAccessor
80, public IDataWriter
81{
82 public:
83
85
86 public:
87
88 void beginWrite(const VariableCollection& vars) override;
89 void endWrite() override;
90 void setMetaData(const String& meta_data) override;
91 void write(IVariable* var, IData* data) override;
92
93 public:
94
95 void setTimes(RealConstArrayView times) { m_times = times; }
96 void setDirectoryName(const String& dir_name) { m_directory_name = dir_name; }
97
98 private:
99
100 IMesh* m_mesh;
101
104
107
110
113
116
117 HGroup m_cell_data_group;
118 HGroup m_node_data_group;
119 bool m_is_parallel = false;
120 bool m_is_master_io = false;
121 bool m_is_collective_io = false;
122
123 private:
124
125 void _addInt64ArrayAttribute(Hid& hid, const char* name, Span<const Int64> values);
126 void _addStringAttribute(Hid& hid, const char* name, const String& value);
127
128 template <typename DataType> void
129 _writeDataSet1D(HGroup& group, const String& name, Span<const DataType> values);
130 template <typename DataType> void
131 _writeDataSet1DCollective(HGroup& group, const String& name, Span<const DataType> values);
132 template <typename DataType> void
133 _writeDataSet2D(HGroup& group, const String& name, Span2<const DataType> values);
134 template <typename DataType> void
135 _writeDataSet2DCollective(HGroup& group, const String& name, Span2<const DataType> values);
136 template <typename DataType> void
137 _writeBasicTypeDataset(HGroup& group, IVariable* var, IData* data);
138 void _writeReal3Dataset(HGroup& group, IVariable* var, IData* data);
139 void _writeReal2Dataset(HGroup& group, IVariable* var, IData* data);
140
141 template <typename DataType> void
142 _writeDataSet1DCollectiveWithCollectiveIO(HGroup& group, const String& name, Span<const DataType> values);
143 template <typename DataType> void
144 _writeDataSet2DCollectiveWithCollectiveIO(HGroup& group, const String& name, Span2<const DataType> values);
145
146 String _getFileNameForTimeIndex(Int32 index)
147 {
148 StringBuilder sb(m_mesh->name());
149 if (index >= 0) {
150 sb += "_";
151 sb += index;
152 }
153 sb += ".hdf";
154 return sb.toString();
155 }
156};
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161VtkHdfDataWriter::
162VtkHdfDataWriter(IMesh* mesh, ItemGroupCollection groups)
163: TraceAccessor(mesh->traceMng())
164, m_mesh(mesh)
165, m_groups(groups)
166{
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
172void VtkHdfDataWriter::
173beginWrite(const VariableCollection& vars)
174{
175 ARCANE_UNUSED(vars);
176
177 IParallelMng* pm = m_mesh->parallelMng();
178 const Int32 nb_rank = pm->commSize();
179 m_is_parallel = nb_rank > 1;
180 m_is_master_io = pm->isMasterIO();
181
182 Int32 time_index = m_times.size();
183 const bool is_first_call = (time_index < 2);
184 if (is_first_call)
185 pwarning() << "L'implémentation au format 'VtkHdf' est expérimentale";
186
187 String filename = _getFileNameForTimeIndex(time_index);
188
189 Directory dir(m_directory_name);
190
191 m_full_filename = dir.file(filename);
192 info(4) << "VtkHdfDataWriter::beginWrite() file=" << m_full_filename;
193
194 HInit();
195
196 HGroup top_group;
197
198 // TODO: protéger appels concurrents HDF5
199 // Il est possible d'utiliser le mode collectif de HDF5 via MPI-IO dans les cas suivants:
200 // - Hdf5 a été compilé avec MPI
201 // - on est en mode MPI pure (ni mode mémoire partagé, ni mode hybride)
202 m_is_collective_io = pm->isParallel() && HInit::hasParallelHdf5();
204 m_is_collective_io = false;
205 if (is_first_call)
206 info() << "VtkHdfDataWriter: using collective MPI/IO ?=" << m_is_collective_io;
207
208 HProperty plist_id;
209 if (m_is_collective_io)
210 plist_id.createFilePropertyMPIIO(pm);
211
212 if (time_index <= 1) {
213 if (m_is_master_io) {
214 dir.createDirectory();
215 }
216 }
217
218 if (m_is_collective_io)
219 pm->barrier();
220
221 if (m_is_collective_io || m_is_master_io) {
222 m_file_id.openTruncate(m_full_filename, plist_id.id());
223
224 top_group.create(m_file_id, "VTKHDF");
225
226 m_cell_data_group.create(top_group, "CellData");
227 m_node_data_group.create(top_group, "PointData");
228
229 std::array<Int64, 2> version = { 1, 0 };
230 _addInt64ArrayAttribute(top_group, "Version", version);
231 _addStringAttribute(top_group, "Type", "UnstructuredGrid");
232 }
233
234 CellGroup all_cells = m_mesh->allCells();
235 NodeGroup all_nodes = m_mesh->allNodes();
236
237 const Int32 nb_cell = all_cells.size();
238 const Int32 nb_node = all_nodes.size();
239
240 Int32 total_nb_connected_node = 0;
241 {
242 ENUMERATE_CELL (icell, all_cells) {
243 Cell cell = *icell;
244 total_nb_connected_node += cell.nodeIds().size();
245 }
246 }
247
248 // Pour les connectivités, la taille du tableau est égal
249 // au nombre de mailles plus 1.
250 UniqueArray<Int64> cells_connectivity(total_nb_connected_node);
251 UniqueArray<Int64> cells_offset(nb_cell + 1);
252 UniqueArray<unsigned char> cells_ghost_type(nb_cell);
253 UniqueArray<unsigned char> cells_type(nb_cell);
254 UniqueArray<Int64> cells_uid(nb_cell);
255 cells_offset[0] = 0;
256 {
257 Int32 connected_node_index = 0;
258 ENUMERATE_CELL (icell, all_cells) {
259 Int32 index = icell.index();
260 Cell cell = *icell;
261
262 cells_uid[index] = icell->uniqueId();
263
264 Byte ghost_type = 0;
265 bool is_ghost = !cell.isOwn();
266 if (is_ghost)
267 ghost_type = VtkUtils::CellGhostTypes::DUPLICATECELL;
268 cells_ghost_type[index] = ghost_type;
269
270 unsigned char vtk_type = VtkUtils::arcaneToVtkCellType(cell.type());
271 cells_type[index] = vtk_type;
272 for (NodeLocalId node : cell.nodeIds()) {
273 cells_connectivity[connected_node_index] = node;
274 ++connected_node_index;
275 }
276 cells_offset[index + 1] = connected_node_index;
277 }
278 }
279
280 _writeDataSet1DCollective<Int64>(top_group, "Offsets", cells_offset);
281
282 _writeDataSet1DCollective<Int64>(top_group, "Connectivity", cells_connectivity);
283 _writeDataSet1DCollective<unsigned char>(top_group, "Types", cells_type);
284
285 {
286 UniqueArray<Int64> nb_cell_by_ranks(1);
287 nb_cell_by_ranks[0] = nb_cell;
288 _writeDataSet1DCollective<Int64>(top_group, "NumberOfCells", nb_cell_by_ranks);
289
290 UniqueArray<Int64> nb_node_by_ranks(1);
291 nb_node_by_ranks[0] = nb_node;
292 _writeDataSet1DCollective<Int64>(top_group, "NumberOfPoints", nb_node_by_ranks);
293
294 UniqueArray<Int64> number_of_connectivity_ids(1);
295 number_of_connectivity_ids[0] = cells_connectivity.size();
296 _writeDataSet1DCollective<Int64>(top_group, "NumberOfConnectivityIds", number_of_connectivity_ids);
297 }
298
299 // Sauve les uniqueIds, les types et les coordonnées des noeuds.
300 {
301 UniqueArray<Int64> nodes_uid(nb_node);
302 UniqueArray<unsigned char> nodes_ghost_type(nb_node);
303 VariableNodeReal3& nodes_coordinates(m_mesh->nodesCoordinates());
304 UniqueArray2<Real> points;
305 points.resize(nb_node, 3);
306 ENUMERATE_NODE (inode, all_nodes) {
307 Int32 index = inode.index();
308 Node node = *inode;
309
310 nodes_uid[index] = inode->uniqueId();
311
312 Byte ghost_type = 0;
313 bool is_ghost = !node.isOwn();
314 if (is_ghost)
315 ghost_type = VtkUtils::PointGhostTypes::DUPLICATEPOINT;
316 nodes_ghost_type[index] = ghost_type;
317
318 Real3 pos = nodes_coordinates[inode];
319 points[index][0] = pos.x;
320 points[index][1] = pos.y;
321 points[index][2] = pos.z;
322 }
323
324 // Sauve l'uniqueId de chaque noeud dans le dataset "GlobalNodeId".
325 _writeDataSet1DCollective<Int64>(m_node_data_group, "GlobalNodeId", nodes_uid);
326
327 // Sauve les informations sur le type de noeud (réel ou fantôme).
328 _writeDataSet1DCollective<unsigned char>(m_node_data_group, "vtkGhostType", nodes_ghost_type);
329
330 // Sauve les coordonnées des noeuds.
331 _writeDataSet2DCollective<Real>(top_group, "Points", points);
332 }
333
334 // Sauve les informations sur le type de maille (réel ou fantôme)
335 _writeDataSet1DCollective<Int64>(m_cell_data_group, "GlobalCellId", cells_uid);
336
337 // Sauve l'uniqueId de chaque maille dans le dataset "GlobalCellId".
338 // L'utilisation du dataset "vtkOriginalCellIds" ne fonctionne pas dans Paraview.
339 _writeDataSet1DCollective<unsigned char>(m_cell_data_group, "vtkGhostType", cells_ghost_type);
340}
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345namespace
346{
347 template <typename DataType> class HDFTraits;
348
349 template <> class HDFTraits<Int64>
350 {
351 public:
352
353 static hid_t hdfType() { return H5T_NATIVE_INT64; }
354 };
355
356 template <> class HDFTraits<Int32>
357 {
358 public:
359
360 static hid_t hdfType() { return H5T_NATIVE_INT32; }
361 };
362
363 template <> class HDFTraits<double>
364 {
365 public:
366
367 static hid_t hdfType() { return H5T_NATIVE_DOUBLE; }
368 };
369
370 template <> class HDFTraits<unsigned char>
371 {
372 public:
373
374 static hid_t hdfType() { return H5T_NATIVE_UINT8; }
375 };
376
377} // namespace
378
379/*---------------------------------------------------------------------------*/
380/*---------------------------------------------------------------------------*/
381
382template <typename DataType> void VtkHdfDataWriter::
383_writeDataSet1DCollectiveWithCollectiveIO(HGroup& group, const String& name, Span<const DataType> values)
384{
385 IParallelMng* pm = m_mesh->parallelMng();
386 Int64 size = values.size();
387 Int32 nb_rank = pm->commSize();
388 Int32 my_rank = pm->commRank();
389 UniqueArray<Int64> all_sizes(nb_rank);
390 pm->allGather(ConstArrayView<Int64>(1, &size), all_sizes);
391
392 Int64 total_size = 0;
393 for (Integer i = 0; i < nb_rank; ++i)
394 total_size += all_sizes[i];
395 Int64 my_index = 0;
396 for (Integer i = 0; i < my_rank; ++i)
397 my_index += all_sizes[i];
398 //m_variables_offset.insert(std::make_pair(v->fullName(), VarOffset(my_index, total_size, all_sizes)));
399 //info() << " ADD OFFSET v=" << v->fullName() << " offset=" << my_index
400 // << " total_size=" << total_size;
401
402 hsize_t offset[1];
403 hsize_t count[1];
404 offset[0] = my_index;
405 count[0] = size;
406
407 hsize_t dims[1];
408 dims[0] = total_size;
409 HSpace filespace_id;
410 filespace_id.createSimple(1, dims);
411 HSpace memspace_id;
412 memspace_id.createSimple(1, count);
413
414 HDataset dataset_id;
415 const hid_t hdf_type = HDFTraits<DataType>::hdfType();
416
417 dataset_id.create(group, name.localstr(), hdf_type, filespace_id, H5P_DEFAULT);
418
419 H5Sselect_hyperslab(filespace_id.id(), H5S_SELECT_SET, offset, NULL, count, NULL);
420
421 HProperty write_plist_id;
422 write_plist_id.createDatasetTransfertCollectiveMPIIO();
423
424 herr_t herr = dataset_id.write(hdf_type, values.data(), memspace_id, filespace_id, write_plist_id);
425
426 if (herr < 0)
427 ARCANE_THROW(IOException, "Can not write dataset '{0}'", name);
428
429}
430
431/*---------------------------------------------------------------------------*/
432/*---------------------------------------------------------------------------*/
433
434template <typename DataType> void VtkHdfDataWriter::
435_writeDataSet2DCollectiveWithCollectiveIO(HGroup& group, const String& name, Span2<const DataType> values)
436{
437 IParallelMng* pm = m_mesh->parallelMng();
438 Int64 dim1_size = values.dim1Size();
439 Int64 dim2_size = values.dim2Size();
440 Int32 nb_rank = pm->commSize();
441 Int32 my_rank = pm->commRank();
442 UniqueArray<Int64> all_sizes(nb_rank);
443 pm->allGather(ConstArrayView<Int64>(1, &dim1_size), all_sizes);
444
445 Int64 total_size = 0;
446 for (Integer i = 0; i < nb_rank; ++i)
447 total_size += all_sizes[i];
448 Int64 my_index = 0;
449 for (Integer i = 0; i < my_rank; ++i)
450 my_index += all_sizes[i];
451 //m_variables_offset.insert(std::make_pair(v->fullName(), VarOffset(my_index, total_size, all_sizes)));
452 //info() << " ADD OFFSET v=" << v->fullName() << " offset=" << my_index
453 // << " total_size=" << total_size;
454
455 hsize_t offset[2];
456 hsize_t count[2];
457 offset[0] = my_index;
458 offset[1] = 0;
459 count[0] = dim1_size;
460 count[1] = dim2_size;
461
462 hsize_t dims[2];
463 dims[0] = total_size;
464 dims[1] = dim2_size;
465 HSpace filespace_id;
466 filespace_id.createSimple(2, dims);
467 HSpace memspace_id;
468 memspace_id.createSimple(2, count);
469
470 HDataset dataset_id;
471 const hid_t hdf_type = HDFTraits<DataType>::hdfType();
472
473 dataset_id.create(group, name.localstr(), hdf_type, filespace_id, H5P_DEFAULT);
474
475 H5Sselect_hyperslab(filespace_id.id(), H5S_SELECT_SET, offset, NULL, count, NULL);
476
477 HProperty write_plist_id;
478 write_plist_id.createDatasetTransfertCollectiveMPIIO();
479
480 herr_t herr = dataset_id.write(hdf_type, values.data(), memspace_id, filespace_id, write_plist_id);
481
482 if (herr < 0)
483 ARCANE_THROW(IOException, "Can not write dataset '{0}'", name);
484}
485
486/*---------------------------------------------------------------------------*/
487/*---------------------------------------------------------------------------*/
488
489template <typename DataType> void VtkHdfDataWriter::
490_writeDataSet1D(HGroup& group, const String& name, Span<const DataType> values)
491{
492 hsize_t dims[1];
493 dims[0] = values.size();
494 HSpace hspace;
495 hspace.createSimple(1, dims);
496 HDataset dataset;
497 const hid_t hdf_type = HDFTraits<DataType>::hdfType();
498 dataset.create(group, name.localstr(), hdf_type, hspace, H5P_DEFAULT);
499 dataset.write(hdf_type, values.data());
500 if (dataset.isBad())
501 ARCANE_THROW(IOException, "Can not write dataset '{0}'", name);
502}
503
504/*---------------------------------------------------------------------------*/
505/*---------------------------------------------------------------------------*/
506
507template <typename DataType> void VtkHdfDataWriter::
508_writeDataSet1DCollective(HGroup& group, const String& name, Span<const DataType> values)
509{
510 if (!m_is_parallel) {
511 _writeDataSet1D(group, name, values);
512 return;
513 }
514 if (m_is_collective_io) {
515 _writeDataSet1DCollectiveWithCollectiveIO(group, name, values);
516 return;
517 }
518 UniqueArray<DataType> all_values;
519 IParallelMng* pm = m_mesh->parallelMng();
520 pm->gatherVariable(values.smallView(), all_values, pm->masterIORank());
521 if (m_is_master_io)
522 _writeDataSet1D<DataType>(group, name, all_values);
523}
524
525/*---------------------------------------------------------------------------*/
526/*---------------------------------------------------------------------------*/
527
528template <typename DataType> void VtkHdfDataWriter::
529_writeDataSet2D(HGroup& group, const String& name, Span2<const DataType> values)
530{
531 hsize_t dims[2];
532 dims[0] = values.dim1Size();
533 dims[1] = values.dim2Size();
534 HSpace hspace;
535 hspace.createSimple(2, dims);
536 HDataset dataset;
537 const hid_t hdf_type = HDFTraits<DataType>::hdfType();
538 dataset.create(group, name.localstr(), hdf_type, hspace, H5P_DEFAULT);
539 dataset.write(hdf_type, values.data());
540 if (dataset.isBad())
541 ARCANE_THROW(IOException, "Can not write dataset '{0}'", name);
542}
543
544/*---------------------------------------------------------------------------*/
545/*---------------------------------------------------------------------------*/
546
547template <typename DataType> void VtkHdfDataWriter::
548_writeDataSet2DCollective(HGroup& group, const String& name, Span2<const DataType> values)
549{
550 Int64 dim2_size = values.dim2Size();
551
552 if (!m_is_parallel) {
553 _writeDataSet2D(group, name, values);
554 return;
555 }
556
557 if (m_is_collective_io) {
558 _writeDataSet2DCollectiveWithCollectiveIO(group, name, values);
559 return;
560 }
561
562 UniqueArray<DataType> all_values;
563 IParallelMng* pm = m_mesh->parallelMng();
564 Span<const DataType> values_1d(values.data(), values.totalNbElement());
565 pm->gatherVariable(values_1d.smallView(), all_values, pm->masterIORank());
566 if (m_is_master_io) {
567 Int64 dim1_size = all_values.size();
568 if (dim2_size != 0)
569 dim1_size = dim1_size / dim2_size;
570 Span2<const DataType> span2(all_values.data(), dim1_size, dim2_size);
571 _writeDataSet2D<DataType>(group, name, span2);
572 }
573}
574
575/*---------------------------------------------------------------------------*/
576/*---------------------------------------------------------------------------*/
577
578void VtkHdfDataWriter::
579_addInt64ArrayAttribute(Hid& hid, const char* name, Span<const Int64> values)
580{
581 hsize_t len = values.size();
582 hid_t aid = H5Screate_simple(1, &len, 0);
583 hid_t attr = H5Acreate2(hid.id(), name, H5T_NATIVE_INT64, aid, H5P_DEFAULT, H5P_DEFAULT);
584 if (attr < 0)
585 ARCANE_FATAL("Can not create attribute '{0}'", name);
586 int ret = H5Awrite(attr, H5T_NATIVE_INT64, values.data());
587 if (ret < 0)
588 ARCANE_FATAL("Can not write attribute '{0}'", name);
589 H5Aclose(attr);
590 H5Sclose(aid);
591}
592
593/*---------------------------------------------------------------------------*/
594/*---------------------------------------------------------------------------*/
595
596void VtkHdfDataWriter::
597_addStringAttribute(Hid& hid, const char* name, const String& value)
598{
599 hid_t aid = H5Screate(H5S_SCALAR);
600 hid_t attr_type = H5Tcopy(H5T_C_S1);
601 H5Tset_size(attr_type, value.length());
602 hid_t attr = H5Acreate2(hid.id(), name, attr_type, aid, H5P_DEFAULT, H5P_DEFAULT);
603 if (attr < 0)
604 ARCANE_FATAL("Can not create attribute {0}", name);
605 int ret = H5Awrite(attr, attr_type, value.localstr());
606 ret = H5Tclose(attr_type);
607 if (ret < 0)
608 ARCANE_FATAL("Can not write attribute '{0}'", name);
609 H5Aclose(attr);
610 H5Sclose(aid);
611}
612
613/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615
616void VtkHdfDataWriter::
617endWrite()
618{
619 m_cell_data_group.close();
620 m_node_data_group.close();
621 //top_group.close();
622 m_file_id.close();
623
624 // Ecrit le fichier contenant les temps (à partir de la version 5.5 de paraview)
625 // https://www.paraview.org/Wiki/ParaView_Release_Notes#JSON_based_new_meta_file_format_for_series_added
626 //
627 // Exemple:
628 // {
629 // "file-series-version" : "1.0",
630 // "files" : [
631 // { "name" : "foo1.vtk", "time" : 0 },
632 // { "name" : "foo2.vtk", "time" : 5.5 },
633 // { "name" : "foo3.vtk", "time" : 11.2 }
634 // ]
635 // }
636
637 if (!m_is_master_io)
638 return;
639
640 JSONWriter writer(JSONWriter::FormatFlags::None);
641 {
642 JSONWriter::Object o(writer);
643 writer.write("file-series-version", "1.0");
644 writer.writeKey("files");
645 writer.beginArray();
646 {
647 Integer file_index = 1;
648 for (Real v : m_times) {
649 JSONWriter::Object o(writer);
650 String filename = _getFileNameForTimeIndex(file_index);
651 writer.write("name", filename);
652 writer.write("time", v);
653 ++file_index;
654 }
655 writer.endArray();
656 }
657 }
658 Directory dir(m_directory_name);
659 String fname = dir.file(_getFileNameForTimeIndex(-1) + ".series");
660 std::ofstream ofile(fname.localstr());
661 StringView buf = writer.getBuffer();
662 ofile.write(reinterpret_cast<const char*>(buf.bytes().data()), buf.length());
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667
670{
671 ARCANE_UNUSED(meta_data);
672}
673
674/*---------------------------------------------------------------------------*/
675/*---------------------------------------------------------------------------*/
676
678write(IVariable* var, IData* data)
679{
680 info(4) << "Write VtkHdf var=" << var->name();
681
682 eItemKind item_kind = var->itemKind();
683
684 if (var->dimension() != 1)
685 ARCANE_FATAL("Only export of scalar item variable is implemented (name={0})", var->name());
686
687 HGroup* group = nullptr;
688 switch (item_kind) {
689 case IK_Cell:
690 group = &m_cell_data_group;
691 break;
692 case IK_Node:
693 group = &m_node_data_group;
694 break;
695 default:
696 ARCANE_FATAL("Only export of 'Cell' or 'Node' variable is implemented (name={0})", var->name());
697 }
699
700 eDataType data_type = var->dataType();
701 switch (data_type) {
702 case DT_Real:
703 _writeBasicTypeDataset<Real>(*group, var, data);
704 break;
705 case DT_Int64:
706 _writeBasicTypeDataset<Int64>(*group, var, data);
707 break;
708 case DT_Int32:
709 _writeBasicTypeDataset<Int32>(*group, var, data);
710 break;
711 case DT_Real3:
712 _writeReal3Dataset(*group, var, data);
713 break;
714 case DT_Real2:
715 _writeReal2Dataset(*group, var, data);
716 break;
717 default:
718 warning() << String::format("Export for datatype '{0}' is not supported (var_name={1})", data_type, var->name());
719 }
720}
721
722/*---------------------------------------------------------------------------*/
723/*---------------------------------------------------------------------------*/
724
725template <typename DataType> void VtkHdfDataWriter::
726_writeBasicTypeDataset(HGroup& group, IVariable* var, IData* data)
727{
728 auto* true_data = dynamic_cast<IArrayDataT<DataType>*>(data);
730 _writeDataSet1DCollective(group, var->name(), Span<const DataType>(true_data->view()));
731}
732
733/*---------------------------------------------------------------------------*/
734/*---------------------------------------------------------------------------*/
735
736void VtkHdfDataWriter::
737_writeReal3Dataset(HGroup& group, IVariable* var, IData* data)
738{
739 auto* true_data = dynamic_cast<IArrayDataT<Real3>*>(data);
740 ARCANE_CHECK_POINTER(true_data);
741 SmallSpan<const Real3> values(true_data->view());
742 Int32 nb_value = values.size();
743 // TODO: optimiser cela sans passer par un tableau temporaire
744 UniqueArray2<Real> scalar_values;
745 scalar_values.resize(nb_value, 3);
746 for (Int32 i = 0; i < nb_value; ++i) {
747 Real3 v = values[i];
748 scalar_values[i][0] = v.x;
749 scalar_values[i][1] = v.y;
750 scalar_values[i][2] = v.z;
751 }
752 _writeDataSet2DCollective<Real>(group, var->name(), scalar_values);
753}
754
755/*---------------------------------------------------------------------------*/
756/*---------------------------------------------------------------------------*/
757
758void VtkHdfDataWriter::
759_writeReal2Dataset(HGroup& group, IVariable* var, IData* data)
760{
761 // Converti en un tableau de 3 composantes dont la dernière vaudra 0.
762 auto* true_data = dynamic_cast<IArrayDataT<Real2>*>(data);
763 ARCANE_CHECK_POINTER(true_data);
764 SmallSpan<const Real2> values(true_data->view());
765 Int32 nb_value = values.size();
766 UniqueArray2<Real> scalar_values;
767 scalar_values.resize(nb_value, 3);
768 for (Int32 i = 0; i < nb_value; ++i) {
769 Real2 v = values[i];
770 scalar_values[i][0] = v.x;
771 scalar_values[i][1] = v.y;
772 scalar_values[i][2] = 0.0;
773 }
774 _writeDataSet2DCollective<Real>(group, var->name(), scalar_values);
775}
776
777/*---------------------------------------------------------------------------*/
778/*---------------------------------------------------------------------------*/
779
780/*---------------------------------------------------------------------------*/
781/*---------------------------------------------------------------------------*/
787{
788 public:
789
792 {
793 }
794
795 IDataWriter* dataWriter() override { return m_writer.get(); }
796 void notifyBeginWrite() override
797 {
798 auto w = std::make_unique<VtkHdfDataWriter>(mesh(), groups());
799 w->setTimes(times());
801 w->setDirectoryName(dir.file("vtkhdf"));
802 m_writer = std::move(w);
803 }
804 void notifyEndWrite() override
805 {
806 m_writer = nullptr;
807 }
808 void close() override {}
809
810 private:
811
812 std::unique_ptr<IDataWriter> m_writer;
813};
814
815/*---------------------------------------------------------------------------*/
816/*---------------------------------------------------------------------------*/
817
818ARCANE_REGISTER_SERVICE_VTKHDFPOSTPROCESSOR(VtkHdfPostProcessor,
819 VtkHdfPostProcessor);
820
821/*---------------------------------------------------------------------------*/
822/*---------------------------------------------------------------------------*/
823
824} // namespace Arcane
825
826/*---------------------------------------------------------------------------*/
827/*---------------------------------------------------------------------------*/
#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_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
#define ENUMERATE_NODE(name, group)
Enumérateur générique d'un groupe de noeuds.
Generation de la classe de base du Service.
Classe gérant un répertoire.
Definition Directory.h:33
Encapsule un hid_t pour un fichier.
Encapsule un hid_t pour un groupe.
static bool hasParallelHdf5()
Vrai HDF5 est compilé avec le support de MPI.
Definition Hdf5Utils.cc:61
Encapsule un hid_t.
Interface d'écriture des données d'une variable.
Definition IDataWriter.h:49
Interface d'une donnée.
Definition IData.h:33
virtual void gatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf, Int32 rank)=0
Effectue un regroupement sur tous les processeurs.
virtual bool isThreadImplementation() const =0
Indique si l'implémentation utilise les threads.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual bool isHybridImplementation() const =0
Indique si l'implémentation utilise le mode hybride.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Effectue un regroupement sur tous les processeurs. Il s'agit d'une opération collective....
virtual Integer masterIORank() const =0
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
virtual void barrier()=0
Effectue une barière.
Interface d'une variable.
Definition IVariable.h:54
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
virtual RealConstArrayView times()
Liste des temps sauvés.
virtual const String & baseDirectoryName()
Nom du répertoire de sortie des fichiers.
virtual ItemGroupCollection groups()
Liste des groupes à sauver.
Structure contenant les informations pour créer un service.
Collection de variables.
String m_directory_name
Répertoire de sortie.
ItemGroupCollection m_groups
Liste des groupes à sauver.
void setMetaData(const String &meta_data) override
Positionne les infos des méta-données.
UniqueArray< Real > m_times
Liste des temps.
HFile m_file_id
Identifiant HDF du fichier.
String m_full_filename
Nom du fichier HDF courant.
void write(IVariable *var, IData *data) override
Ecrit les données data de la variable var.
Post-traitement au format Ensight Hdf.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
Integer size() const
Nombre d'éléments du vecteur.
Vue constante d'un tableau de type T.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
TraceMessage pwarning() const
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage info() const
Flot pour un message d'information.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
Definition ItemTypes.h:183
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
Definition ItemTypes.h:167
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
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 -*-
Collection< ItemGroup > ItemGroupCollection
Collection de groupes d'éléments du maillage.
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
unsigned char Byte
Type d'un octet.
Definition UtilsTypes.h:142
eDataType
Type d'une donnée.
Definition DataTypes.h:39
@ DT_Int32
Donnée de type entier 32 bits.
Definition DataTypes.h:43
@ DT_Real3
Donnée de type vecteur 3.
Definition DataTypes.h:47
@ DT_Int64
Donnée de type entier 64 bits.
Definition DataTypes.h:44
@ DT_Real2
Donnée de type vecteur 2.
Definition DataTypes.h:46
@ DT_Real
Donnée de type réel.
Definition DataTypes.h:41
Int32 Integer
Type représentant un entier.