Arcane  v3.15.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
VtkHdfV2PostProcessor.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* VtkHdfV2PostProcessor.cc (C) 2000-2025 */
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/StringBuilder.h"
18#include "arcane/utils/IOException.h"
19#include "arcane/utils/FixedArray.h"
20#include "arcane/utils/MemoryView.h"
21
22#include "arcane/core/PostProcessorWriterBase.h"
23#include "arcane/core/Directory.h"
24#include "arcane/core/FactoryService.h"
25#include "arcane/core/IDataWriter.h"
26#include "arcane/core/IData.h"
27#include "arcane/core/IItemFamily.h"
28#include "arcane/core/VariableCollection.h"
29#include "arcane/core/IParallelMng.h"
30#include "arcane/core/IMesh.h"
31#include "arcane/core/internal/VtkCellTypes.h"
32
33#include "arcane/core/materials/IMeshMaterialMng.h"
34#include "arcane/core/materials/IMeshEnvironment.h"
35
36#include "arcane/hdf5/Hdf5Utils.h"
37#include "arcane/hdf5/VtkHdfV2PostProcessor_axl.h"
38
39#include <map>
40
41// Ce format est décrit sur la page web suivante :
42//
43// https://kitware.github.io/vtk-examples/site/VTKFileFormats/#hdf-file-formats
44//
45// Le format 2.0 avec le support intégré de l'évolution temporelle n'est
46// disponible que dans la branche master de VTK à partir d'avril 2023.
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51// TODO: Ajouter test de vérifcation des valeurs sauvegardées
52
53// TODO: Regarder la sauvegarde des uniqueId() (via vtkOriginalCellIds)
54
55// TODO: Regarder comment éviter de sauver le maillage à chaque itération s'il
56// ne change pas.
57
58// TODO: Regarder la compression
59
60// TODO: gérer les variables 2D
61
62// TODO: hors HDF5, faire un mécanisme qui regroupe plusieurs parties
63// du maillage en une seule. Cela permettra de réduire le nombre de mailles
64// fantômes et d'utiliser MPI/IO en mode hybride.
65
66/*---------------------------------------------------------------------------*/
67/*---------------------------------------------------------------------------*/
68
69namespace Arcane
70{
71using namespace Hdf5Utils;
72using namespace Materials;
73
74namespace
75{
76 template <typename T> Span<const T>
77 asConstSpan(const T* v)
78 {
79 return Span<const T>(v, 1);
80 }
81} // namespace
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
87: public TraceAccessor
88, public IDataWriter
89{
90 public:
91
99 {
100 public:
101
103 : group(group_)
104 , name(name_)
105 {}
106
107 public:
108
109 HGroup& group;
110 String name;
111 };
112
125 {
126 DatasetInfo() = default;
127 explicit DatasetInfo(const String& name)
128 : m_name(name)
129 {}
130 DatasetInfo(HGroup& _group, const String& name)
131 : m_group(&_group)
132 , m_name(name)
133 {}
134 bool isNull() const { return m_name.null(); }
135
136 HGroup* group() const { return m_group; }
137 const String& name() const { return m_name; }
139 Int64 offset() const { return m_offset; }
140 void setOffset(Int64 v) { m_offset = v; }
141 friend bool operator<(const DatasetInfo& s1, const DatasetInfo& s2)
142 {
143 return (s1.m_name < s2.m_name);
144 }
145
146 private:
147
148 HGroup* m_group = nullptr;
149 String m_name;
150 Int64 m_offset = -1;
151 };
152
155 {
156 public:
157
158 void setTotalSize(Int64 v) { m_total_size = v; }
159 void setSize(Int64 v) { m_size = v; }
160 void setOffset(Int64 v) { m_offset = v; }
161
162 Int64 totalSize() const { return m_total_size; }
163 Int64 size() const { return m_size; }
164 Int64 offset() const { return m_offset; }
165
166 private:
167
174 };
175
178 {
179 public:
180
181 explicit ItemGroupCollectiveInfo(const ItemGroup& g)
182 : m_item_group(g)
183 {}
184
185 public:
186
187 void setWritePartInfo(const WritePartInfo& part_info) { m_write_part_info = part_info; }
188 const WritePartInfo& writePartInfo() const { return m_write_part_info; }
189
190 public:
191
196 };
197
201 struct DataInfo
202 {
203 public:
204
206 : dataset(dname)
207 , m_dataset_info(dataset_info)
208 {
209 }
212 : dataset(dname)
213 , m_dataset_info(dataset_info)
214 , m_group_info(group_info)
215 {
216 }
217
218 public:
219
220 DatasetInfo datasetInfo() const { return m_dataset_info; }
221
222 public:
223
224 DatasetGroupAndName dataset;
225 DatasetInfo m_dataset_info;
226 ItemGroupCollectiveInfo* m_group_info = nullptr;
227 };
228
229 public:
230
232
233 public:
234
235 void beginWrite(const VariableCollection& vars) override;
236 void endWrite() override;
237 void setMetaData(const String& meta_data) override;
238 void write(IVariable* var, IData* data) override;
239
240 public:
241
242 void setTimes(RealConstArrayView times) { m_times = times; }
243 void setDirectoryName(const String& dir_name) { m_directory_name = dir_name; }
244 void setMaxWriteSize(Int64 v) { m_max_write_size = v; }
245
246 private:
247
249 IMesh* m_mesh = nullptr;
250
253
256
259
262
265
268
269 HGroup m_top_group;
270 HGroup m_cell_data_group;
271 HGroup m_node_data_group;
272
273 HGroup m_steps_group;
274 HGroup m_point_data_offsets_group;
275 HGroup m_cell_data_offsets_group;
276 HGroup m_field_data_offsets_group;
277
278 bool m_is_parallel = false;
279 bool m_is_master_io = false;
280 bool m_is_collective_io = false;
281 bool m_is_first_call = false;
282 bool m_is_writer = false;
283
284 DatasetInfo m_cell_offset_info;
285 DatasetInfo m_point_offset_info;
286 DatasetInfo m_connectivity_offset_info;
287 DatasetInfo m_offset_for_cell_offset_info;
288 DatasetInfo m_part_offset_info;
289 DatasetInfo m_time_offset_info;
290 std::map<DatasetInfo, Int64> m_offset_info_list;
291
292 StandardTypes m_standard_types{ false };
293
294 ItemGroupCollectiveInfo m_all_cells_info;
295 ItemGroupCollectiveInfo m_all_nodes_info;
297
305
306 private:
307
308 void _addInt64ArrayAttribute(Hid& hid, const char* name, Span<const Int64> values);
309 void _addStringAttribute(Hid& hid, const char* name, const String& value);
310
311 template <typename DataType> void
312 _writeDataSet1D(const DataInfo& data_info, Span<const DataType> values);
313 template <typename DataType> void
314 _writeDataSet1DUsingCollectiveIO(const DataInfo& data_info, Span<const DataType> values);
315 template <typename DataType> void
316 _writeDataSet1DCollective(const DataInfo& data_info, Span<const DataType> values);
317 template <typename DataType> void
318 _writeDataSet2D(const DataInfo& data_info, Span2<const DataType> values);
319 template <typename DataType> void
320 _writeDataSet2DUsingCollectiveIO(const DataInfo& data_info, Span2<const DataType> values);
321 template <typename DataType> void
322 _writeDataSet2DCollective(const DataInfo& data_info, Span2<const DataType> values);
323 template <typename DataType> void
324 _writeBasicTypeDataset(const DataInfo& data_info, IData* data);
325 void _writeReal3Dataset(const DataInfo& data_info, IData* data);
326 void _writeReal2Dataset(const DataInfo& data_info, IData* data);
327
328 String _getFileName()
329 {
331 sb += ".hdf";
332 return sb.toString();
333 }
334 template <typename DataType> void
335 _writeDataSetGeneric(const DataInfo& data_info, Int32 nb_dim,
336 Int64 dim1_size, Int64 dim2_size, const DataType* values_data,
337 bool is_collective);
338 void _writeDataSetGeneric(const DataInfo& data_info, Int32 nb_dim,
339 Int64 dim1_size, Int64 dim2_size, ConstMemoryView values_data,
341 void _addInt64Attribute(Hid& hid, const char* name, Int64 value);
342 Int64 _readInt64Attribute(Hid& hid, const char* name);
343 void _openOrCreateGroups();
344 void _closeGroups();
345 void _readAndSetOffset(DatasetInfo& offset_info, Int32 wanted_step);
346 void _initializeOffsets();
347 void _initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info);
349 void _writeConstituentsGroups();
350};
351
352/*---------------------------------------------------------------------------*/
353/*---------------------------------------------------------------------------*/
354
355VtkHdfV2DataWriter::
356VtkHdfV2DataWriter(IMesh* mesh, const ItemGroupCollection& groups, bool is_collective_io)
357: TraceAccessor(mesh->traceMng())
358, m_mesh(mesh)
359, m_groups(groups)
360, m_is_collective_io(is_collective_io)
361, m_all_cells_info(mesh->allCells())
362, m_all_nodes_info(mesh->allNodes())
363{
364}
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369void VtkHdfV2DataWriter::
370beginWrite(const VariableCollection& vars)
371{
372 ARCANE_UNUSED(vars);
373
374 // Récupère le gestionnaire de matériaux s'il existe
376
377 IParallelMng* pm = m_mesh->parallelMng();
378 const Int32 nb_rank = pm->commSize();
379 m_is_parallel = nb_rank > 1;
380 m_is_master_io = pm->isMasterIO();
381
382 Int32 time_index = m_times.size();
383 const bool is_first_call = (time_index < 2);
384 m_is_first_call = is_first_call;
385 if (is_first_call)
386 info() << "WARNING: L'implémentation au format 'VtkHdfV2' est expérimentale";
387
388 String filename = _getFileName();
389
390 Directory dir(m_directory_name);
391
392 m_full_filename = dir.file(filename);
393 info(4) << "VtkHdfV2DataWriter::beginWrite() file=" << m_full_filename;
394
395 HInit();
396
397 // Il est possible d'utiliser le mode collectif de HDF5 via MPI-IO dans les cas suivants :
398 // * Hdf5 a été compilé avec MPI,
399 // * on est en mode MPI pure (ni mode mémoire partagé, ni mode hybride).
400 m_is_collective_io = m_is_collective_io && (pm->isParallel() && HInit::hasParallelHdf5());
402 m_is_collective_io = false;
403
404 if (is_first_call) {
405 info() << "VtkHdfV2DataWriter: using collective MPI/IO ?=" << m_is_collective_io;
406 info() << "VtkHdfV2DataWriter: max_write_size (kB) =" << m_max_write_size;
407 info() << "VtkHdfV2DataWriter: has_material?=" << (m_material_mng != nullptr);
408 }
409
410 // Vrai si on doit participer aux écritures
411 // Si on utilise MPI/IO avec HDF5, il faut tout de même que tous
412 // les rangs fassent toutes les opérations d'écriture pour garantir
413 // la cohérence des méta-données.
414 m_is_writer = m_is_master_io || m_is_collective_io;
415
416 // Indique qu'on utilise MPI/IO si demandé
417 HProperty plist_id;
418 if (m_is_collective_io)
419 plist_id.createFilePropertyMPIIO(pm);
420
421 if (is_first_call && m_is_master_io)
422 dir.createDirectory();
423
424 if (m_is_collective_io)
425 pm->barrier();
426
427 if (m_is_writer) {
428 m_standard_types.initialize();
429
430 if (is_first_call)
431 m_file_id.openTruncate(m_full_filename, plist_id.id());
432 else
433 m_file_id.openAppend(m_full_filename, plist_id.id());
434
435 _openOrCreateGroups();
436
437 if (is_first_call) {
438 std::array<Int64, 2> version = { 2, 0 };
439 _addInt64ArrayAttribute(m_top_group, "Version", version);
440 _addStringAttribute(m_top_group, "Type", "UnstructuredGrid");
441 }
442 }
443
444 // Initialise les informations collectives sur les groupes de mailles et noeuds
445 _initializeItemGroupCollectiveInfos(m_all_cells_info);
446 _initializeItemGroupCollectiveInfos(m_all_nodes_info);
447
448 CellGroup all_cells = m_mesh->allCells();
449 NodeGroup all_nodes = m_mesh->allNodes();
450
451 const Int32 nb_cell = all_cells.size();
452 const Int32 nb_node = all_nodes.size();
453
454 Int32 total_nb_connected_node = 0;
455 ENUMERATE_ (Cell, icell, all_cells) {
456 Cell cell = *icell;
457 total_nb_connected_node += cell.nodeIds().size();
458 }
459
460 // Pour les offsets, la taille du tableau est égal
461 // au nombre de mailles plus 1.
462 UniqueArray<Int64> cells_connectivity(total_nb_connected_node);
463 UniqueArray<Int64> cells_offset(nb_cell + 1);
464 UniqueArray<unsigned char> cells_ghost_type(nb_cell);
465 UniqueArray<unsigned char> cells_type(nb_cell);
466 UniqueArray<Int64> cells_uid(nb_cell);
467 cells_offset[0] = 0;
468 {
469 Int32 connected_node_index = 0;
470 ENUMERATE_CELL (icell, all_cells) {
471 Int32 index = icell.index();
472 Cell cell = *icell;
473
474 cells_uid[index] = cell.uniqueId();
475
476 Byte ghost_type = 0;
477 bool is_ghost = !cell.isOwn();
478 if (is_ghost)
479 ghost_type = VtkUtils::CellGhostTypes::DUPLICATECELL;
480 cells_ghost_type[index] = ghost_type;
481
482 unsigned char vtk_type = VtkUtils::arcaneToVtkCellType(cell.type());
483 cells_type[index] = vtk_type;
484 for (NodeLocalId node : cell.nodeIds()) {
485 cells_connectivity[connected_node_index] = node;
486 ++connected_node_index;
487 }
488 cells_offset[index + 1] = connected_node_index;
489 }
490 }
491
492 _initializeOffsets();
493
494 // TODO: faire un offset pour cet objet (ou regarder comment le calculer automatiquement
495 _writeDataSet1DCollective<Int64>({ { m_top_group, "Offsets" }, m_offset_for_cell_offset_info }, cells_offset);
496
497 _writeDataSet1DCollective<Int64>({ { m_top_group, "Connectivity" }, m_connectivity_offset_info },
498 cells_connectivity);
499 _writeDataSet1DCollective<unsigned char>({ { m_top_group, "Types" }, m_cell_offset_info }, cells_type);
500
501 {
502 Int64 nb_cell_int64 = nb_cell;
503 _writeDataSet1DCollective<Int64>({ { m_top_group, "NumberOfCells" }, m_part_offset_info },
504 asConstSpan(&nb_cell_int64));
505 Int64 nb_node_int64 = nb_node;
506 _writeDataSet1DCollective<Int64>({ { m_top_group, "NumberOfPoints" }, m_part_offset_info },
507 asConstSpan(&nb_node_int64));
508 Int64 number_of_connectivity_ids = cells_connectivity.size();
509 _writeDataSet1DCollective<Int64>({ { m_top_group, "NumberOfConnectivityIds" }, m_part_offset_info },
510 asConstSpan(&number_of_connectivity_ids));
511 }
512
513 // Sauve les uniqueIds, les types et les coordonnées des noeuds.
514 {
515 UniqueArray<Int64> nodes_uid(nb_node);
516 UniqueArray<unsigned char> nodes_ghost_type(nb_node);
517 VariableNodeReal3& nodes_coordinates(m_mesh->nodesCoordinates());
518 UniqueArray2<Real> points;
519 points.resize(nb_node, 3);
520 ENUMERATE_ (Node, inode, all_nodes) {
521 Int32 index = inode.index();
522 Node node = *inode;
523
524 nodes_uid[index] = node.uniqueId();
525
526 Byte ghost_type = 0;
527 bool is_ghost = !node.isOwn();
528 if (is_ghost)
529 ghost_type = VtkUtils::PointGhostTypes::DUPLICATEPOINT;
530 nodes_ghost_type[index] = ghost_type;
531
532 Real3 pos = nodes_coordinates[inode];
533 points[index][0] = pos.x;
534 points[index][1] = pos.y;
535 points[index][2] = pos.z;
536 }
537
538 // Sauve l'uniqueId de chaque nœud dans le dataset "GlobalNodeId".
539 _writeDataSet1DCollective<Int64>({ { m_node_data_group, "GlobalNodeId" }, m_cell_offset_info }, nodes_uid);
540
541 // Sauve les informations sur le type de nœud (réel ou fantôme).
542 _writeDataSet1DCollective<unsigned char>({ { m_node_data_group, "vtkGhostType" }, m_cell_offset_info }, nodes_ghost_type);
543
544 // Sauve les coordonnées des noeuds.
545 _writeDataSet2DCollective<Real>({ { m_top_group, "Points" }, m_point_offset_info }, points);
546 }
547
548 // Sauve les informations sur le type de maille (réel ou fantôme)
549 _writeDataSet1DCollective<unsigned char>({ { m_cell_data_group, "vtkGhostType" }, m_cell_offset_info }, cells_ghost_type);
550
551 // Sauve l'uniqueId de chaque maille dans le dataset "GlobalCellId".
552 // L'utilisation du dataset "vtkOriginalCellIds" ne fonctionne pas dans Paraview.
553 _writeDataSet1DCollective<Int64>({ { m_cell_data_group, "GlobalCellId" }, m_cell_offset_info }, cells_uid);
554
555 if (m_is_writer) {
556 // Liste des temps.
557 Real current_time = m_times[time_index - 1];
558 _writeDataSet1D<Real>({ { m_steps_group, "Values" }, m_time_offset_info }, asConstSpan(&current_time));
559
560 // Offset de la partie.
561 Int64 part_offset = (time_index - 1) * pm->commSize();
562 _writeDataSet1D<Int64>({ { m_steps_group, "PartOffsets" }, m_time_offset_info }, asConstSpan(&part_offset));
563
564 // Nombre de temps
565 _addInt64Attribute(m_steps_group, "NSteps", time_index);
566 }
567
568 _writeConstituentsGroups();
569}
570
571/*---------------------------------------------------------------------------*/
572/*---------------------------------------------------------------------------*/
573
574void VtkHdfV2DataWriter::
575_writeConstituentsGroups()
576{
577 if (!m_material_mng)
578 return;
579
580 // Remplit les informations des groupes liés aux constituents
581 // NOTE : Pour l'instant, on ne traite que les milieux.
582 for (IMeshEnvironment* env : m_material_mng->environments()) {
583 CellGroup cells = env->cells();
584 Ref<ItemGroupCollectiveInfo> group_info_ref = createRef<ItemGroupCollectiveInfo>(cells);
585 m_materials_groups.add(group_info_ref);
586 ItemGroupCollectiveInfo& group_info = *group_info_ref.get();
587 _initializeItemGroupCollectiveInfos(group_info);
588 ConstArrayView<Int32> groups_ids = cells.view().localIds();
589 DatasetGroupAndName dataset_group_name(m_top_group, String("Constituent_") + cells.name());
590 if (m_is_first_call)
591 info() << "Writing infos for group '" << cells.name() << "'";
592 _writeDataSet1DCollective<Int32>({ dataset_group_name, m_cell_offset_info }, groups_ids);
593 }
594}
595
596/*---------------------------------------------------------------------------*/
597/*---------------------------------------------------------------------------*/
603{
604 // TODO: regarder pour utiliser un scan.
606 Int32 nb_rank = pm->commSize();
607 Int32 my_rank = pm->commRank();
608
611 Int64 dim1_size = local_size;
612 pm->allGather(ConstArrayView<Int64>(1, &dim1_size), all_sizes);
613
614 Int64 total_size = 0;
615 for (Integer i = 0; i < nb_rank; ++i)
616 total_size += all_sizes[i];
617
618 Int64 my_index = 0;
619 for (Integer i = 0; i < my_rank; ++i)
620 my_index += all_sizes[i];
621
623 part_info.setTotalSize(total_size);
624 part_info.setSize(local_size);
625 part_info.setOffset(my_index);
626 return part_info;
627}
628
629/*---------------------------------------------------------------------------*/
630/*---------------------------------------------------------------------------*/
631
632void VtkHdfV2DataWriter::
633_initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info)
634{
635 Int64 dim1_size = group_info.m_item_group.size();
636 group_info.setWritePartInfo(_computeWritePartInfo(dim1_size));
637}
638
639namespace
640{
641 std::pair<Int64, Int64> _getInterval(Int64 index, Int64 nb_interval, Int64 total_size)
642 {
643 Int64 n = total_size;
644 Int64 isize = n / nb_interval;
645 Int64 ibegin = index * isize;
646 // Pour le dernier interval, prend les elements restants
647 if ((index + 1) == nb_interval)
648 isize = n - ibegin;
649 return { ibegin, isize };
650 }
651} // namespace
652
653/*---------------------------------------------------------------------------*/
654/*---------------------------------------------------------------------------*/
661void VtkHdfV2DataWriter::
662_writeDataSetGeneric(const DataInfo& data_info, Int32 nb_dim,
663 Int64 dim1_size, Int64 dim2_size,
664 ConstMemoryView values_data,
665 const hid_t hdf_type, bool is_collective)
666{
667 if (nb_dim == 1)
668 dim2_size = 1;
669
670 HGroup& group = data_info.dataset.group;
671 const String& name = data_info.dataset.name;
672
673 // Si positif ou nul, indique l'offset d'écriture.
674 // Sinon, on écrit à la fin du dataset actuel.
675 Int64 wanted_offset = data_info.datasetInfo().offset();
676
677 static constexpr int MAX_DIM = 2;
678 HDataset dataset;
679
680 // En cas d'opération collective, local_dims et global_dims sont
681 // différents sur la première dimension. La deuxième dimension est toujours
682 // identique pour local_dims et global_dims et ne doit pas être modifiée durant
683 // tout le calcul.
684
685 // Dimensions du dataset que le rang courant va écrire.
687 local_dims[0] = dim1_size;
688 local_dims[1] = dim2_size;
689
690 // Dimensions cumulées de tous les rangs pour l'écriture.
692
693 // Dimensions maximales du DataSet
694 // Pour la deuxième dimension, on suppose qu'elle est constante au cours du temps.
697 max_dims[1] = dim2_size;
698
699 herr_t herror = 0;
701
702 Int64 my_index = 0;
703 Int64 global_dim1_size = dim1_size;
705
706 if (is_collective) {
709 if (data_info.m_group_info) {
710 // Si la donnée est associée à un groupe, alors les informations
711 // sur l'offset ont déjà été calculées
712 part_info = data_info.m_group_info->writePartInfo();
713 }
714 else {
715 part_info = _computeWritePartInfo(dim1_size);
716 }
717 global_dim1_size = part_info.totalSize();
718 my_index = part_info.offset();
719 }
720
722 if (is_collective)
723 write_plist_id.createDatasetTransfertCollectiveMPIIO();
724
727
728 if (m_is_first_call) {
729 // TODO: regarder comment mieux calculer le chunk
732 global_dims[1] = dim2_size;
733 // Il est important que tout le monde ait la même taille de chunk.
735 if (chunk_size < 1024)
736 chunk_size = 1024;
737 const Int64 max_chunk_size = 1024 * 1024 * 10;
740 chunk_dims[1] = dim2_size;
741 info() << "CHUNK nb_dim=" << nb_dim
742 << " global_dim1_size=" << global_dim1_size
743 << " chunk0=" << chunk_dims[0]
744 << " chunk1=" << chunk_dims[1]
745 << " name=" << name;
746 file_space.createSimple(nb_dim, global_dims.data(), max_dims.data());
749 H5Pset_chunk(plist_id.id(), nb_dim, chunk_dims.data());
750 dataset.create(group, name.localstr(), hdf_type, file_space, HProperty{}, plist_id, HProperty{});
751
752 if (is_collective) {
754 hyperslab_offsets[1] = 0;
755 }
756 }
757 else {
758 // Agrandit la première dimension du dataset.
759 // On va ajouter 'global_dim1_size' à cette dimension.
760 dataset.open(group, name.localstr());
761 file_space = dataset.getSpace();
762 int nb_dimension = file_space.nbDimension();
763 if (nb_dimension != nb_dim)
764 ARCANE_THROW(IOException, "Bad dimension '{0}' for dataset '{1}' (should be 1)",
765 nb_dimension, name);
766 // TODO: Vérifier que la deuxième dimension est la même que celle sauvée.
768 file_space.getDimensions(original_dims.data(), nullptr);
770 // Si on a un offset positif issu de DatasetInfo alors on le prend.
771 // Cela signifie qu'on a fait un retour arrière.
772 if (wanted_offset >= 0) {
774 info() << "Forcing offset to " << wanted_offset;
775 }
777 global_dims[1] = dim2_size;
779 // Agrandit le dataset.
780 // ATTENTION cela invalide file_space. Il faut donc le relire juste après.
781 if ((herror = dataset.setExtent(global_dims.data())) < 0)
782 ARCANE_THROW(IOException, "Can not extent dataset '{0}' (err={1})", name, herror);
783 file_space = dataset.getSpace();
784
786 hyperslab_offsets[1] = 0;
787 info(4) << "APPEND nb_dim=" << nb_dim
788 << " dim0=" << global_dims[0]
789 << " count0=" << local_dims[0]
790 << " offsets0=" << hyperslab_offsets[0] << " name=" << name;
791 }
792
793 Int64 nb_write_byte = global_dim1_size * dim2_size * values_data.datatypeSize();
794
795 // Effectue l'écriture en plusieurs parties si demandé.
796 // Cela n'est possible que pour l'écriture collective.
797 Int64 nb_interval = 1;
798 if (is_collective && m_max_write_size > 0) {
800 }
801 info(4) << "WRITE global_size=" << nb_write_byte << " max_size=" << m_max_write_size << " nb_interval=" << nb_interval;
802
803 for (Int64 i = 0; i < nb_interval; ++i) {
804 auto [index, nb_element] = _getInterval(i, nb_interval, dim1_size);
805 // Sélectionne la partie de la donnée à écrire
807 dims[0] = nb_element;
808 dims[1] = dim2_size;
810 offsets[0] = hyperslab_offsets[0] + index;
811 offsets[1] = 0;
812 if ((herror = H5Sselect_hyperslab(file_space.id(), H5S_SELECT_SET, offsets.data(), nullptr, dims.data(), nullptr)) < 0)
813 ARCANE_THROW(IOException, "Can not select hyperslab '{0}' (err={1})", name, herror);
814
816 memory_space.createSimple(nb_dim, dims.data());
817 Int64 data_offset = index * values_data.datatypeSize() * dim2_size;
818 // Effectue l'écriture
819 if ((herror = dataset.write(hdf_type, values_data.data() + data_offset, memory_space, file_space, write_plist_id)) < 0)
820 ARCANE_THROW(IOException, "Can not write dataset '{0}' (err={1})", name, herror);
821
822 if (dataset.isBad())
823 ARCANE_THROW(IOException, "Can not write dataset '{0}'", name);
824 }
825
826 if (!data_info.datasetInfo().isNull())
827 m_offset_info_list.insert(std::make_pair(data_info.datasetInfo(), write_offset));
828}
829
830/*---------------------------------------------------------------------------*/
831/*---------------------------------------------------------------------------*/
832
833template <typename DataType> void VtkHdfV2DataWriter::
834_writeDataSetGeneric(const DataInfo& data_info, Int32 nb_dim,
835 Int64 dim1_size, Int64 dim2_size, const DataType* values_data,
836 bool is_collective)
837{
838 const hid_t hdf_type = m_standard_types.nativeType(DataType{});
839 ConstMemoryView mem_view = makeConstMemoryView(values_data, sizeof(DataType), dim1_size * dim2_size);
840 _writeDataSetGeneric(data_info, nb_dim, dim1_size, dim2_size, mem_view, hdf_type, is_collective);
841}
842
843/*---------------------------------------------------------------------------*/
844/*---------------------------------------------------------------------------*/
845
846template <typename DataType> void VtkHdfV2DataWriter::
847_writeDataSet1D(const DataInfo& data_info, Span<const DataType> values)
848{
849 _writeDataSetGeneric(data_info, 1, values.size(), 1, values.data(), false);
850}
851
852/*---------------------------------------------------------------------------*/
853/*---------------------------------------------------------------------------*/
854
855template <typename DataType> void VtkHdfV2DataWriter::
856_writeDataSet1DUsingCollectiveIO(const DataInfo& data_info, Span<const DataType> values)
857{
858 _writeDataSetGeneric(data_info, 1, values.size(), 1, values.data(), true);
859}
860
861/*---------------------------------------------------------------------------*/
862/*---------------------------------------------------------------------------*/
863
864template <typename DataType> void VtkHdfV2DataWriter::
865_writeDataSet1DCollective(const DataInfo& data_info, Span<const DataType> values)
866{
867 if (!m_is_parallel)
868 return _writeDataSet1D(data_info, values);
869 if (m_is_collective_io)
870 return _writeDataSet1DUsingCollectiveIO(data_info, values);
871 UniqueArray<DataType> all_values;
872 IParallelMng* pm = m_mesh->parallelMng();
873 pm->gatherVariable(values.smallView(), all_values, pm->masterIORank());
874 if (m_is_master_io)
875 _writeDataSet1D<DataType>(data_info, all_values);
876}
877
878/*---------------------------------------------------------------------------*/
879/*---------------------------------------------------------------------------*/
880
881template <typename DataType> void VtkHdfV2DataWriter::
882_writeDataSet2D(const DataInfo& data_info, Span2<const DataType> values)
883{
884 _writeDataSetGeneric(data_info, 2, values.dim1Size(), values.dim2Size(), values.data(), false);
885}
886
887/*---------------------------------------------------------------------------*/
888/*---------------------------------------------------------------------------*/
889
890template <typename DataType> void VtkHdfV2DataWriter::
891_writeDataSet2DUsingCollectiveIO(const DataInfo& data_info, Span2<const DataType> values)
892{
893 _writeDataSetGeneric(data_info, 2, values.dim1Size(), values.dim2Size(), values.data(), true);
894}
895
896/*---------------------------------------------------------------------------*/
897/*---------------------------------------------------------------------------*/
898
899template <typename DataType> void VtkHdfV2DataWriter::
900_writeDataSet2DCollective(const DataInfo& data_info, Span2<const DataType> values)
901{
902 if (!m_is_parallel)
903 return _writeDataSet2D(data_info, values);
904 if (m_is_collective_io)
905 return _writeDataSet2DUsingCollectiveIO(data_info, values);
906
907 Int64 dim2_size = values.dim2Size();
908 UniqueArray<DataType> all_values;
909 IParallelMng* pm = m_mesh->parallelMng();
910 Span<const DataType> values_1d(values.data(), values.totalNbElement());
911 pm->gatherVariable(values_1d.smallView(), all_values, pm->masterIORank());
912 if (m_is_master_io) {
913 Int64 dim1_size = all_values.size();
914 if (dim2_size != 0)
915 dim1_size = dim1_size / dim2_size;
916 Span2<const DataType> span2(all_values.data(), dim1_size, dim2_size);
917 return _writeDataSet2D<DataType>(data_info, span2);
918 }
919}
920
921/*---------------------------------------------------------------------------*/
922/*---------------------------------------------------------------------------*/
923
924void VtkHdfV2DataWriter::
925_addInt64ArrayAttribute(Hid& hid, const char* name, Span<const Int64> values)
926{
927 hsize_t len = values.size();
928 hid_t aid = H5Screate_simple(1, &len, nullptr);
929 hid_t attr = H5Acreate2(hid.id(), name, H5T_NATIVE_INT64, aid, H5P_DEFAULT, H5P_DEFAULT);
930 if (attr < 0)
931 ARCANE_FATAL("Can not create attribute '{0}'", name);
932 int ret = H5Awrite(attr, H5T_NATIVE_INT64, values.data());
933 if (ret < 0)
934 ARCANE_FATAL("Can not write attribute '{0}'", name);
935 H5Aclose(attr);
936 H5Sclose(aid);
937}
938
939/*---------------------------------------------------------------------------*/
940/*---------------------------------------------------------------------------*/
941
942void VtkHdfV2DataWriter::
943_addInt64Attribute(Hid& hid, const char* name, Int64 value)
944{
945 HSpace aid(H5Screate(H5S_SCALAR));
946 HAttribute attr;
947 if (m_is_first_call)
948 attr.create(hid, name, H5T_NATIVE_INT64, aid);
949 else
950 attr.open(hid, name);
951 if (attr.isBad())
952 ARCANE_FATAL("Can not create attribute '{0}'", name);
953 herr_t ret = attr.write(H5T_NATIVE_INT64, &value);
954 if (ret < 0)
955 ARCANE_FATAL("Can not write attribute '{0}'", name);
956}
957
958/*---------------------------------------------------------------------------*/
959/*---------------------------------------------------------------------------*/
960
961Int64 VtkHdfV2DataWriter::
962_readInt64Attribute(Hid& hid, const char* name)
963{
964 HAttribute attr;
965 attr.open(hid, name);
966 if (attr.isBad())
967 ARCANE_FATAL("Can not open attribute '{0}'", name);
968 Int64 value;
969 herr_t ret = attr.read(H5T_NATIVE_INT64, &value);
970 if (ret < 0)
971 ARCANE_FATAL("Can not read attribute '{0}'", name);
972 return value;
973}
974
975/*---------------------------------------------------------------------------*/
976/*---------------------------------------------------------------------------*/
977
978void VtkHdfV2DataWriter::
979_addStringAttribute(Hid& hid, const char* name, const String& value)
980{
981 hid_t aid = H5Screate(H5S_SCALAR);
982 hid_t attr_type = H5Tcopy(H5T_C_S1);
983 H5Tset_size(attr_type, value.length());
984 hid_t attr = H5Acreate2(hid.id(), name, attr_type, aid, H5P_DEFAULT, H5P_DEFAULT);
985 if (attr < 0)
986 ARCANE_FATAL("Can not create attribute {0}", name);
987 int ret = H5Awrite(attr, attr_type, value.localstr());
988 ret = H5Tclose(attr_type);
989 if (ret < 0)
990 ARCANE_FATAL("Can not write attribute '{0}'", name);
991 H5Aclose(attr);
992 H5Sclose(aid);
993}
994
995/*---------------------------------------------------------------------------*/
996/*---------------------------------------------------------------------------*/
997
998void VtkHdfV2DataWriter::
999endWrite()
1000{
1001 // Sauvegarde les offsets enregistrés
1002
1003 if (m_is_writer) {
1004 for (const auto& i : m_offset_info_list) {
1005 Int64 offset = i.second;
1006 const DatasetInfo& offset_info = i.first;
1007 HGroup* hdf_group = offset_info.group();
1008 //info() << "OFFSET_INFO name=" << offset_info.name() << " offset=" << offset;
1009 if (hdf_group)
1010 _writeDataSet1D<Int64>({ { *hdf_group, offset_info.name() }, m_time_offset_info }, asConstSpan(&offset));
1011 }
1012 }
1013 _closeGroups();
1014 m_file_id.close();
1015}
1016
1017/*---------------------------------------------------------------------------*/
1018/*---------------------------------------------------------------------------*/
1019
1020void VtkHdfV2DataWriter::
1021_openOrCreateGroups()
1022{
1023 // Tout groupe ouvert ici doit être fermé dans closeGroups().
1024 m_top_group.openOrCreate(m_file_id, "VTKHDF");
1025 m_cell_data_group.openOrCreate(m_top_group, "CellData");
1026 m_node_data_group.openOrCreate(m_top_group, "PointData");
1027 m_steps_group.openOrCreate(m_top_group, "Steps");
1028 m_point_data_offsets_group.openOrCreate(m_steps_group, "PointDataOffsets");
1029 m_cell_data_offsets_group.openOrCreate(m_steps_group, "CellDataOffsets");
1030 m_field_data_offsets_group.openOrCreate(m_steps_group, "FieldDataOffsets");
1031}
1032
1033/*---------------------------------------------------------------------------*/
1034/*---------------------------------------------------------------------------*/
1035
1036void VtkHdfV2DataWriter::
1037_closeGroups()
1038{
1039 m_cell_data_group.close();
1040 m_node_data_group.close();
1041 m_point_data_offsets_group.close();
1042 m_cell_data_offsets_group.close();
1043 m_field_data_offsets_group.close();
1044 m_steps_group.close();
1045 m_top_group.close();
1046}
1047
1048/*---------------------------------------------------------------------------*/
1049/*---------------------------------------------------------------------------*/
1050
1053{
1054 ARCANE_UNUSED(meta_data);
1055}
1056
1057/*---------------------------------------------------------------------------*/
1058/*---------------------------------------------------------------------------*/
1059
1061write(IVariable* var, IData* data)
1062{
1063 info(4) << "Write VtkHdfV2 var=" << var->name();
1064
1065 eItemKind item_kind = var->itemKind();
1066
1067 if (var->dimension() != 1)
1068 ARCANE_FATAL("Only export of scalar item variable is implemented (name={0})", var->name());
1069 if (var->isPartial())
1070 ARCANE_FATAL("Export of partial variable is not implemented");
1071
1072 HGroup* group = nullptr;
1075 switch (item_kind) {
1076 case IK_Cell:
1077 group = &m_cell_data_group;
1078 offset_info = m_cell_offset_info;
1079 group_info = &m_all_cells_info;
1080 break;
1081 case IK_Node:
1082 group = &m_node_data_group;
1083 offset_info = m_point_offset_info;
1084 group_info = &m_all_nodes_info;
1085 break;
1086 default:
1087 ARCANE_FATAL("Only export of 'Cell' or 'Node' variable is implemented (name={0})", var->name());
1088 }
1089
1090 ARCANE_CHECK_POINTER(group);
1091
1093 eDataType data_type = var->dataType();
1094 switch (data_type) {
1095 case DT_Real:
1097 break;
1098 case DT_Int64:
1100 break;
1101 case DT_Int32:
1103 break;
1104 case DT_Real3:
1105 _writeReal3Dataset(data_info, data);
1106 break;
1107 case DT_Real2:
1108 _writeReal2Dataset(data_info, data);
1109 break;
1110 default:
1111 warning() << String::format("Export for datatype '{0}' is not supported (var_name={1})", data_type, var->name());
1112 }
1113}
1114
1115/*---------------------------------------------------------------------------*/
1116/*---------------------------------------------------------------------------*/
1117
1118template <typename DataType> void VtkHdfV2DataWriter::
1119_writeBasicTypeDataset(const DataInfo& data_info, IData* data)
1120{
1121 auto* true_data = dynamic_cast<IArrayDataT<DataType>*>(data);
1123 _writeDataSet1DCollective(data_info, Span<const DataType>(true_data->view()));
1124}
1125
1126/*---------------------------------------------------------------------------*/
1127/*---------------------------------------------------------------------------*/
1128
1129void VtkHdfV2DataWriter::
1130_writeReal3Dataset(const DataInfo& data_info, IData* data)
1131{
1132 auto* true_data = dynamic_cast<IArrayDataT<Real3>*>(data);
1133 ARCANE_CHECK_POINTER(true_data);
1134 SmallSpan<const Real3> values(true_data->view());
1135 Int32 nb_value = values.size();
1136 // TODO: optimiser cela sans passer par un tableau temporaire
1137 UniqueArray2<Real> scalar_values;
1138 scalar_values.resize(nb_value, 3);
1139 for (Int32 i = 0; i < nb_value; ++i) {
1140 Real3 v = values[i];
1141 scalar_values[i][0] = v.x;
1142 scalar_values[i][1] = v.y;
1143 scalar_values[i][2] = v.z;
1144 }
1145 _writeDataSet2DCollective<Real>(data_info, scalar_values);
1146}
1147
1148/*---------------------------------------------------------------------------*/
1149/*---------------------------------------------------------------------------*/
1150
1151void VtkHdfV2DataWriter::
1152_writeReal2Dataset(const DataInfo& data_info, IData* data)
1153{
1154 // Converti en un tableau de 3 composantes dont la dernière vaudra 0.
1155 auto* true_data = dynamic_cast<IArrayDataT<Real2>*>(data);
1156 ARCANE_CHECK_POINTER(true_data);
1157 SmallSpan<const Real2> values(true_data->view());
1158 Int32 nb_value = values.size();
1159 UniqueArray2<Real> scalar_values;
1160 scalar_values.resize(nb_value, 3);
1161 for (Int32 i = 0; i < nb_value; ++i) {
1162 Real2 v = values[i];
1163 scalar_values[i][0] = v.x;
1164 scalar_values[i][1] = v.y;
1165 scalar_values[i][2] = 0.0;
1166 }
1167 _writeDataSet2DCollective<Real>(data_info, scalar_values);
1168}
1169
1170/*---------------------------------------------------------------------------*/
1171/*---------------------------------------------------------------------------*/
1172
1173void VtkHdfV2DataWriter::
1174_readAndSetOffset(DatasetInfo& offset_info, Int32 wanted_step)
1175{
1176 HGroup* hgroup = offset_info.group();
1177 ARCANE_CHECK_POINTER(hgroup);
1178 StandardArrayT<Int64> a(hgroup->id(), offset_info.name());
1179 UniqueArray<Int64> values;
1180 a.directRead(m_standard_types, values);
1181 Int64 offset_value = values[wanted_step];
1182 offset_info.setOffset(offset_value);
1183 info() << "VALUES name=" << offset_info.name() << " values=" << values
1184 << " wanted_step=" << wanted_step << " v=" << offset_value;
1185}
1186
1187/*---------------------------------------------------------------------------*/
1188/*---------------------------------------------------------------------------*/
1189
1190void VtkHdfV2DataWriter::
1191_initializeOffsets()
1192{
1193 // Il y a 5 valeurs d'offset utilisées :
1194 //
1195 // - offset sur le nombre de mailles (CellOffsets). Cet offset a pour nombre d'éléments
1196 // le nombre de temps sauvés et est augmenté à chaque sortie du nombre de mailles. Cet offset
1197 // est aussi utilisé pour les variables aux mailles
1198 // - offset sur le nombre de noeuds (PointOffsets). Il est équivalent à 'CellOffsets' mais
1199 // pour les noeuds.
1200 // - offset pour "NumberOfCells", "NumberOfPoints" et "NumberOfConnectivityIds". Pour chacun
1201 // de ces champs il y a NbPart valeurs par temps, avec 'NbPart' le nombre de parties (donc
1202 // le nombre de sous-domaines si on ne fait pas de regroupement). Il y a ainsi au total
1203 // NbPart * NbTimeStep dans ce champ d'offset.
1204 // - offset pour le champ "Connectivity" qui s'appelle "ConnectivityIdOffsets".
1205 // Cet offset a pour nombre d'éléments le nombre de temps sauvés.
1206 // - offset pour le champ "Offsets". "Offset" contient pour chaque maille l'offset dans
1207 // "Connectivity" de la connectivité des noeuds de la maille. Cet offset n'est pas sauvés,
1208 // mais comme ce champ à un nombre de valeurs égal au nombre de mailles plus un il est possible
1209 // de le déduire de "CellOffsets" (il vaut "CellOffsets" plus l'index du temps courant).
1210
1211 m_cell_offset_info = DatasetInfo(m_steps_group, "CellOffsets");
1212 m_point_offset_info = DatasetInfo(m_steps_group, "PointOffsets");
1213 m_connectivity_offset_info = DatasetInfo(m_steps_group, "ConnectivityIdOffsets");
1214 // Ces trois offsets ne sont pas sauvegardés dans le format VTK
1215 m_offset_for_cell_offset_info = DatasetInfo("_OffsetForCellOffsetInfo");
1216 m_part_offset_info = DatasetInfo("_PartOffsetInfo");
1217 m_time_offset_info = DatasetInfo("_TimeOffsetInfo");
1218
1219 // Regarde si on n'a pas fait de retour-arrière.
1220 // C'est le cas si le nombre de temps sauvés est supérieur au nombre
1221 // de valeurs de \a m_times.
1222 if (m_is_writer && !m_is_first_call) {
1223 IParallelMng* pm = m_mesh->parallelMng();
1224 const Int32 nb_rank = pm->commSize();
1225 Int64 nb_current_step = _readInt64Attribute(m_steps_group, "NSteps");
1226 Int32 time_index = m_times.size();
1227 info(4) << "NB_STEP=" << nb_current_step << " time_index=" << time_index
1228 << " current_time=" << m_times.back();
1229 const bool debug_times = false;
1230 if (debug_times) {
1231 StandardArrayT<Real> a1(m_steps_group.id(), "Values");
1232 UniqueArray<Real> times;
1233 a1.directRead(m_standard_types, times);
1234 info() << "TIMES=" << times;
1235 }
1236 if ((nb_current_step + 1) != time_index) {
1237 info() << "[VtkHdf] go_backward detected";
1238 Int32 wanted_step = time_index - 1;
1239 // Signifie qu'on a fait un retour arrière.
1240 // Dans ce cas, il faut relire les offsets
1241 _readAndSetOffset(m_cell_offset_info, wanted_step);
1242 _readAndSetOffset(m_point_offset_info, wanted_step);
1243 _readAndSetOffset(m_connectivity_offset_info, wanted_step);
1244 m_part_offset_info.setOffset(wanted_step * nb_rank);
1245 m_time_offset_info.setOffset(wanted_step);
1246 m_offset_for_cell_offset_info.setOffset(m_cell_offset_info.offset() + wanted_step * nb_rank);
1247 }
1248 }
1249}
1250
1251/*---------------------------------------------------------------------------*/
1252/*---------------------------------------------------------------------------*/
1253
1254/*---------------------------------------------------------------------------*/
1255/*---------------------------------------------------------------------------*/
1261{
1262 public:
1263
1266 {
1267 }
1268
1269 IDataWriter* dataWriter() override { return m_writer.get(); }
1270 void notifyBeginWrite() override
1271 {
1272 bool use_collective_io = true;
1274 if (options()) {
1275 use_collective_io = options()->useCollectiveWrite();
1276 max_write_size = options()->maxWriteSize();
1277 }
1278 auto w = std::make_unique<VtkHdfV2DataWriter>(mesh(), groups(), use_collective_io);
1279 w->setMaxWriteSize(max_write_size);
1280 w->setTimes(times());
1282 w->setDirectoryName(dir.file("vtkhdfv2"));
1283 m_writer = std::move(w);
1284 }
1285 void notifyEndWrite() override
1286 {
1287 m_writer = nullptr;
1288 }
1289 void close() override {}
1290
1291 private:
1292
1293 std::unique_ptr<IDataWriter> m_writer;
1294};
1295
1296/*---------------------------------------------------------------------------*/
1297/*---------------------------------------------------------------------------*/
1298
1299ARCANE_REGISTER_SERVICE_VTKHDFV2POSTPROCESSOR(VtkHdfV2PostProcessor,
1300 VtkHdfV2PostProcessor);
1301
1302/*---------------------------------------------------------------------------*/
1303/*---------------------------------------------------------------------------*/
1304
1305} // namespace Arcane
1306
1307/*---------------------------------------------------------------------------*/
1308/*---------------------------------------------------------------------------*/
#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_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_CELL(name, group)
Enumérateur générique d'un groupe de mailles.
Generation de la classe de base du Service.
CaseOptionsVtkHdfV2PostProcessor * options() const
Options du jeu de données du service.
Classe gérant un répertoire.
Definition Directory.h:33
Encapsule un hid_t pour un dataset.
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 pour une propriété (H5P*).
Encapsule un hid_t pour un dataspace.
Encapsule un hid_t.
Définition des types standards Arcane pour hdf5.
void initialize()
Initialise les types.
Definition Hdf5Utils.cc:702
Interface d'écriture des données d'une variable.
Definition IDataWriter.h:49
Interface d'une donnée.
Definition IData.h:33
virtual String name() const =0
Nom du maillage.
virtual NodeGroup allNodes()=0
Groupe de tous les noeuds.
virtual CellGroup allCells()=0
Groupe de toutes les mailles.
virtual VariableNodeReal3 & nodesCoordinates()=0
Coordonnées des noeuds.
virtual IParallelMng * parallelMng()=0
Gestionnaire de parallèlisme.
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Definition IOException.h:32
Interface du gestionnaire de parallélisme pour un sous-domaine.
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:56
Groupe d'entités de maillage.
Definition ItemGroup.h:49
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Interface du gestionnaire des matériaux et des milieux d'un maillage.
static IMeshMaterialMng * getReference(const MeshHandleOrMesh &mesh_handle, bool create=true)
Récupère ou créé la référence associée à mesh.
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.
void write(IVariable *var, IData *data) override
Ecrit les données data de la variable var.
IMeshMaterialMng * m_material_mng
Gestionnaire de matériaux associé (peut-être nul)
Int64 m_max_write_size
Taille maximale (en kilo-octet) pour une écriture.
String m_directory_name
Répertoire de sortie.
WritePartInfo _computeWritePartInfo(Int64 local_size)
Calcule l'offset de notre partie et le nombre total d'éléments.
IMesh * m_mesh
Maillage associé
HFile m_file_id
Identifiant HDF du fichier.
ItemGroupCollection m_groups
Liste des groupes à sauver.
UniqueArray< Real > m_times
Liste des temps.
void setMetaData(const String &meta_data) override
Positionne les infos des méta-données.
String m_full_filename
Nom du fichier HDF courant.
Post-traitement au format VtkHdf V2.
IDataWriter * dataWriter() override
Retourne l'écrivain associé à ce post-processeur.
void close() override
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
void notifyBeginWrite() override
Notifie qu'une sortie va être effectuée avec les paramètres courants.
void notifyEndWrite() override
Notifie qu'une sortie vient d'être effectuée.
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.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
TraceMessage warning() const
Flot pour un message d'avertissement.
TraceMessage info() const
Flot pour un message d'information.
ARCCORE_HOST_DEVICE Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:336
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.
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
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43
Ensemble des classes assurant la gestion des matériaux et des milieux.
Conserve les infos sur les données à sauver et l'offset associé.
Classe pour conserver un couple (hdf_group,nom_du_dataset).
Classe pour conserver les information d'un offset.
Int64 offset() const
Valeur de l'offset. (-1) si on écrit à la fin du tableau.
Informations collectives sur un ItemGroup;.
WritePartInfo m_write_part_info
Informations sur l'écriture.
Informations sur l'offset de la partie à écrire associée à un rang.
Int64 m_size
Nombre d'éléments de mon rang.
Int64 m_total_size
Nombre d'éléments sur tous les rangs.