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"
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/MeshKind.h"
29#include "arcane/core/VariableCollection.h"
30#include "arcane/core/IParallelMng.h"
31#include "arcane/core/IMesh.h"
32#include "arcane/core/internal/IParallelMngInternal.h"
33#include "arcane/core/internal/VtkCellTypes.h"
34#include "arcane/core/internal/GatherGroup.h"
36#include "arcane/core/materials/IMeshMaterialMng.h"
37#include "arcane/core/materials/IMeshEnvironment.h"
39#include "arcane/hdf5/Hdf5Utils.h"
40#include "arcane/hdf5/VtkHdfV2PostProcessor_axl.h"
80 asConstSpan(
const T* v)
89class VtkHdfV2DataWriter
101 struct DatasetGroupAndName
105 DatasetGroupAndName(
HGroup& group_,
const String& name_)
129 DatasetInfo() =
default;
130 explicit DatasetInfo(
const String& name)
137 bool isNull()
const {
return m_name.null(); }
139 HGroup* group()
const {
return m_group; }
140 const String& name()
const {
return m_name; }
143 void setOffset(
Int64 v) { m_offset = v; }
144 friend bool operator<(
const DatasetInfo& s1,
const DatasetInfo& s2)
146 return (s1.m_name < s2.m_name);
151 HGroup* m_group =
nullptr;
180 struct ItemGroupCollectiveInfo
184 explicit ItemGroupCollectiveInfo(
const ItemGroup& g)
210 , m_dataset_info(dataset_info)
216 , m_dataset_info(dataset_info)
217 , m_group_info(group_info)
221 : dataset(dataset_group, dataset_name)
222 , m_dataset_info(dataset_info)
227 : dataset(dataset_group, dataset_name)
228 , m_dataset_info(dataset_info)
229 , m_group_info(group_info)
235 DatasetInfo datasetInfo()
const {
return m_dataset_info; }
251 void endWrite()
override;
289 HGroup m_point_data_offsets_group;
290 HGroup m_cell_data_offsets_group;
291 HGroup m_field_data_offsets_group;
293 bool m_is_parallel =
false;
294 bool m_is_collective_io =
false;
295 bool m_is_first_call =
false;
296 bool m_is_writer =
false;
321 std::map<DatasetInfo, Int64> m_offset_info_list;
325 ItemGroupCollectiveInfo m_all_cells_info;
326 ItemGroupCollectiveInfo m_all_nodes_info;
344 void _addStringAttribute(
Hid& hid,
const char* name,
const String& value);
346 template <
typename DataType>
void
348 template <
typename DataType>
void
350 template <
typename DataType>
void
352 template <
typename DataType>
void
354 template <
typename DataType>
void
356 template <
typename DataType>
void
358 template <
typename DataType>
void
367 return sb.toString();
369 template <
typename DataType>
void
371 Int64 dim1_size,
Int64 dim2_size,
const DataType* values_data,
373 void _writeDataSetGeneric(
const DataInfo& data_info,
GatherGroupInfo* gather_info,
Int32 nb_dim,
375 const hid_t hdf_datatype_type,
bool is_collective);
376 void _addInt64Attribute(
Hid& hid,
const char* name,
Int64 value);
377 Int64 _readInt64Attribute(
Hid& hid,
const char* name);
378 void _openOrCreateGroups();
380 void _readAndSetOffset(DatasetInfo& offset_info,
Int32 wanted_step);
381 void _initializeOffsets();
382 void _initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info,
GatherGroupInfo& gather_info);
384 void _writeConstituentsGroups();
392: TraceAccessor(mesh->traceMng())
395, m_is_collective_io(is_collective_io)
396, m_all_cells_info(mesh->allCells())
397, m_all_nodes_info(mesh->allNodes())
398, m_all_cells_gather_group_info(mesh->parallelMng(), is_collective_io)
399, m_all_nodes_gather_group_info(mesh->parallelMng(), is_collective_io)
406void VtkHdfV2DataWriter::
414 IParallelMng* pm =
m_mesh->parallelMng();
415 const Int32 nb_rank = pm->commSize();
416 m_is_parallel = nb_rank > 1;
419 const bool is_first_call = (time_index < 2);
420 m_is_first_call = is_first_call;
422 info() <<
"WARNING: L'implémentation au format 'VtkHdfV2' est expérimentale";
424 String filename = _getFileName();
438 if (pm->isThreadImplementation() && !pm->isHybridImplementation())
439 m_is_collective_io =
false;
442 info() <<
"VtkHdfV2DataWriter: using collective MPI/IO ?=" << m_is_collective_io;
447 bool is_master_io = pm->isMasterIO();
453 if (m_is_collective_io) {
454 m_writer = pm->_internalApi()->masterParallelIORank();
455 m_is_writer = (m_writer == pm->commRank());
458 m_writer = pm->masterIORank();
459 m_is_writer = is_master_io;
464 if (m_is_collective_io && m_is_writer)
465 plist_id.createFilePropertyMPIIO(pm);
468 if (is_first_call && is_master_io)
469 dir.createDirectory();
471 if (m_is_collective_io)
475 m_standard_types.initialize();
482 _openOrCreateGroups();
485 std::array<Int64, 2> version = { 2, 5 };
486 _addInt64ArrayAttribute(m_top_group,
"Version", version);
487 _addStringAttribute(m_top_group,
"Type",
"UnstructuredGrid");
492 _initializeItemGroupCollectiveInfos(m_all_cells_info, m_all_cells_gather_group_info);
493 _initializeItemGroupCollectiveInfos(m_all_nodes_info, m_all_nodes_gather_group_info);
498 const Int32 nb_cell = all_cells.size();
499 const Int32 nb_node = all_nodes.size();
501 Int64 total_nb_connected_node = 0;
504 total_nb_connected_node += cell.nodeIds().size();
509 UniqueArray<Int64> cells_connectivity(total_nb_connected_node);
510 UniqueArray<Int64> cells_offset(nb_cell + 1);
511 UniqueArray<unsigned char> cells_ghost_type(nb_cell);
512 UniqueArray<unsigned char> cells_type(nb_cell);
513 UniqueArray<Int64> cells_uid(nb_cell);
529 UniqueArray<Int64> faces_connectivity;
530 UniqueArray<Int64> faces_offset;
531 UniqueArray<Int64> polyhedron_to_faces;
532 UniqueArray<Int64> polyhedron_offset(nb_cell + 1);
534 polyhedron_offset[0] = 0;
544 Int32 connected_node_index = 0;
546 Int32 index = icell.index();
549 cells_uid[index] = cell.uniqueId();
552 bool is_ghost = !cell.isOwn();
554 ghost_type = VtkUtils::CellGhostTypes::DUPLICATECELL;
555 cells_ghost_type[index] = ghost_type;
557 const bool is_polyhedron = cell.typeInfo()->isPolyhedron() || (mesh_is_polyhedral && cell.nbFace() > 0);
558 unsigned char vtk_type = VtkUtils::VTK_POLYHEDRON;
560 vtk_type = VtkUtils::arcaneToVtkCellType(cell.type());
561 cells_type[index] = vtk_type;
562 for (NodeLocalId node : cell.nodeIds()) {
563 cells_connectivity[connected_node_index] = node;
564 ++connected_node_index;
566 cells_offset[index + 1] = connected_node_index;
569 for (Face face : cell.faces()) {
575 Int32 face_nb_node = face.nbNode();
576 bool is_back_cell = (face.backCellId().localId() == cell.localId());
578 for (NodeLocalId node : face.nodeIds())
579 faces_connectivity.add(node);
583 for (
Int32 i = face_nb_node - 1; i >= 0; --i)
584 faces_connectivity.add(node_ids[i]);
586 faces_offset.add(faces_connectivity.size());
587 polyhedron_to_faces.add(nb_face);
591 polyhedron_offset[index + 1] = polyhedron_to_faces.size();
601 Int32 local_has_polyhedron = (nb_face > 0) ? 1 : 0;
603 Int32 global_has_polyhedron_datasets = 0;
604 if (!m_is_first_call) {
605 Int32 local_has_polyhedron_datasets = 0;
607 HDataset polyhedron_dataset;
608 polyhedron_dataset.openIfExists(m_top_group,
"FaceConnectivity");
609 local_has_polyhedron_datasets = (polyhedron_dataset.id() > 0) ? 1 : 0;
613 if (global_has_polyhedron != 0 && global_has_polyhedron_datasets == 0 && !m_is_first_call)
614 ARCANE_FATAL(
"The mesh contains polyhedron cells but the associated datasets "
615 "do not exist in the file '{0}'. Polyhedron cells must be present "
616 "from the first output",
621 _initializeOffsets();
625 GatherGroupInfo* ggi = ggi_ref.get();
628 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"Offsets", m_offset_for_cell_offset_info),
635 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"PolyhedronOffsets", m_offset_for_polyhedron_offset_info),
636 ggi, polyhedron_offset);
638 ggi->setNeedRecompute();
640 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"Connectivity", m_connectivity_offset_info),
641 ggi, cells_connectivity);
642 ggi->setNeedRecompute();
646 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"FaceConnectivity", m_face_connectivity_offset_info),
647 ggi, faces_connectivity);
648 ggi->setNeedRecompute();
652 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"PolyhedronToFaces", m_polyhedron_to_face_offset_info),
653 ggi, polyhedron_to_faces);
654 ggi->setNeedRecompute();
658 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"FaceOffsets", m_offset_for_face_offset_info),
660 ggi->setNeedRecompute();
663 _writeDataSet1DCollective<unsigned char>(
DataInfo(m_top_group,
"Types", m_cell_offset_info),
664 &m_all_cells_gather_group_info, cells_type);
667 Int64 nb_cell_int64 = nb_cell;
668 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfCells", m_part_offset_info),
669 ggi, asConstSpan(&nb_cell_int64));
671 Int64 nb_node_int64 = nb_node;
672 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfPoints", m_part_offset_info),
673 ggi, asConstSpan(&nb_node_int64));
675 Int64 number_of_connectivity_ids = cells_connectivity.size();
676 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfConnectivityIds", m_part_offset_info),
677 ggi, asConstSpan(&number_of_connectivity_ids));
680 Int64 nb_face_int64 = nb_face;
681 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfFaces", m_part_offset_info),
682 ggi, asConstSpan(&nb_face_int64));
684 Int64 number_of_face_connectivity_ids = faces_connectivity.size();
685 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfFaceConnectivityIds", m_part_offset_info),
686 ggi, asConstSpan(&number_of_face_connectivity_ids));
688 Int64 number_of_polyhedron_to_face_ids = polyhedron_to_faces.size();
689 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfPolyhedronToFaceIds", m_part_offset_info),
690 ggi, asConstSpan(&number_of_polyhedron_to_face_ids));
693 ggi->setNeedRecompute();
697 UniqueArray<Int64> nodes_uid(nb_node);
698 UniqueArray<unsigned char> nodes_ghost_type(nb_node);
700 UniqueArray2<Real> points;
701 points.resize(nb_node, 3);
703 Int32 index = inode.index();
706 nodes_uid[index] = node.uniqueId();
709 bool is_ghost = !node.isOwn();
711 ghost_type = VtkUtils::PointGhostTypes::DUPLICATEPOINT;
712 nodes_ghost_type[index] = ghost_type;
714 Real3 pos = nodes_coordinates[inode];
715 points[index][0] = pos.x;
716 points[index][1] = pos.y;
717 points[index][2] = pos.z;
722 &m_all_nodes_gather_group_info, nodes_uid);
726 &m_all_nodes_gather_group_info, nodes_ghost_type);
731 ggi->setNeedRecompute();
736 &m_all_cells_gather_group_info, cells_ghost_type);
741 &m_all_cells_gather_group_info, cells_uid);
748 ggi, asConstSpan(¤t_time));
751 Int64 comm_size = pm->commSize();
752 Int64 part_offset = (time_index - 1) * comm_size;
754 ggi, asConstSpan(&part_offset));
762 auto face_offsets_write_offset = m_offset_info_list.find(m_offset_for_face_offset_info);
763 if (face_offsets_write_offset == m_offset_info_list.end())
764 ARCANE_FATAL(
"The dataset 'FaceOffsets' has not been written");
765 Int64 nb_offset_value = (time_index - 1) * comm_size;
766 Int64 face_offsets_offset = face_offsets_write_offset->second - nb_offset_value;
767 _writeDataSet1D<Int64>({ { m_steps_group,
"FaceOffsetsOffsets" }, m_time_offset_info }, ggi,
768 asConstSpan(&face_offsets_offset));
772 _addInt64Attribute(m_steps_group,
"NSteps", time_index);
776 _writeConstituentsGroups();
782void VtkHdfV2DataWriter::
783_writeConstituentsGroups()
794 m_materials_groups.add(group_info_ref);
797 m_gather_info_materials_groups.add(gather_info_ref);
800 GatherGroupInfo& gather_info = *gather_info_ref.get();
801 _initializeItemGroupCollectiveInfos(group_info, gather_info);
803 ConstArrayView<Int32> groups_ids = cells.view().localIds();
804 DatasetGroupAndName dataset_group_name(m_top_group, String(
"Constituent_") + cells.name());
806 info() <<
"Writing infos for group '" << cells.name() <<
"'";
807 _writeDataSet1DCollective<Int32>({ dataset_group_name, m_cell_offset_info, group_info_ref.get() }, gather_info_ref.get(), groups_ids);
826 Int64 dim1_size = local_size;
829 Int64 total_size = 0;
830 for (
Integer i = 0; i < nb_rank; ++i)
831 total_size += all_sizes[i];
834 for (
Integer i = 0; i < my_rank; ++i)
835 my_index += all_sizes[i];
838 part_info.setTotalSize(total_size);
839 part_info.setSize(local_size);
840 part_info.setOffset(my_index);
847void VtkHdfV2DataWriter::
848_initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info,
GatherGroupInfo& gather_info)
850 Int32 dim1_size = group_info.m_item_group.size();
852 gather_info.setCollectiveIO(m_is_collective_io);
862 std::pair<Int64, Int64> _getInterval(Int64 index, Int64 nb_interval, Int64 total_size)
864 Int64 n = total_size;
865 Int64 isize = n / nb_interval;
866 Int64 ibegin = index * isize;
868 if ((index + 1) == nb_interval)
870 return { ibegin, isize };
882void VtkHdfV2DataWriter::
886 const hid_t hdf_type,
bool is_collective)
892 HGroup& group = data_info.dataset.group;
893 const String& name = data_info.dataset.name;
897 Int64 wanted_offset = data_info.datasetInfo().
offset();
899 static constexpr int MAX_DIM = 2;
909 local_dims[0] = dim1_size;
910 local_dims[1] = dim2_size;
918 max_dims[0] = H5S_UNLIMITED;
919 max_dims[1] = dim2_size;
922 Int64 write_offset = 0;
925 Int64 global_dim1_size = dim1_size;
926 Int32 nb_participating_rank = 1;
931 if (data_info.m_group_info) {
934 part_info = data_info.m_group_info->writePartInfo();
939 global_dim1_size = part_info.totalSize();
940 my_index = part_info.offset();
959 if (m_is_first_call) {
962 global_dims[0] = global_dim1_size;
963 global_dims[1] = dim2_size;
965 Int64 chunk_size = global_dim1_size / nb_participating_rank;
966 if (chunk_size < 1024)
968 const Int64 max_chunk_size = 1024 * 1024 * 10;
969 chunk_size =
math::min(chunk_size, max_chunk_size);
970 chunk_dims[0] = chunk_size;
971 chunk_dims[1] = dim2_size;
972 info() <<
"CHUNK nb_dim=" << nb_dim
973 <<
" global_dim1_size=" << global_dim1_size
974 <<
" chunk0=" << chunk_dims[0]
975 <<
" chunk1=" << chunk_dims[1]
977 file_space.createSimple(nb_dim, global_dims.data(), max_dims.data());
979 plist_id.create(H5P_DATASET_CREATE);
980 H5Pset_chunk(plist_id.id(), nb_dim, chunk_dims.data());
981 dataset.create(group, name.localstr(), hdf_type, file_space,
HProperty{}, plist_id,
HProperty{});
984 hyperslab_offsets[0] = my_index;
985 hyperslab_offsets[1] = 0;
991 dataset.open(group, name.
localstr());
992 file_space = dataset.getSpace();
993 int nb_dimension = file_space.nbDimension();
994 if (nb_dimension != nb_dim)
999 file_space.getDimensions(original_dims.data(),
nullptr);
1000 hsize_t offset0 = original_dims[0];
1003 if (wanted_offset >= 0) {
1004 offset0 = wanted_offset;
1005 info() <<
"Forcing offset to " << wanted_offset;
1007 global_dims[0] = offset0 + global_dim1_size;
1008 global_dims[1] = dim2_size;
1009 write_offset = offset0;
1012 if ((herror = dataset.setExtent(global_dims.data())) < 0)
1014 file_space = dataset.getSpace();
1016 hyperslab_offsets[0] = offset0 + my_index;
1017 hyperslab_offsets[1] = 0;
1018 info(4) <<
"APPEND nb_dim=" << nb_dim
1019 <<
" dim0=" << global_dims[0]
1020 <<
" count0=" << local_dims[0]
1021 <<
" offsets0=" << hyperslab_offsets[0] <<
" name=" << name;
1024 Int64 nb_write_byte = global_dim1_size * dim2_size * values_data.
datatypeSize();
1028 Int64 nb_interval = 1;
1032 info(4) <<
"WRITE global_size=" << nb_write_byte <<
" max_size=" <<
m_max_write_size <<
" nb_interval=" << nb_interval;
1034 for (
Int64 i = 0; i < nb_interval; ++i) {
1035 auto [index, nb_element] = _getInterval(i, nb_interval, dim1_size);
1038 dims[0] = nb_element;
1039 dims[1] = dim2_size;
1041 offsets[0] = hyperslab_offsets[0] + index;
1043 if ((herror = H5Sselect_hyperslab(file_space.id(), H5S_SELECT_SET, offsets.data(),
nullptr, dims.data(),
nullptr)) < 0)
1047 memory_space.createSimple(nb_dim, dims.data());
1050 if ((herror = dataset.write(hdf_type, values_data.
data() + data_offset, memory_space, file_space, write_plist_id)) < 0)
1053 if (dataset.isBad())
1057 if (!data_info.datasetInfo().isNull())
1058 m_offset_info_list.insert(std::make_pair(data_info.datasetInfo(), write_offset));
1064template <
typename DataType>
void VtkHdfV2DataWriter::
1066 Int64 dim1_size,
Int64 dim2_size,
const DataType* values_data,
1069 const hid_t hdf_type = m_standard_types.nativeType(DataType{});
1070 ConstMemoryView mem_view =
makeConstMemoryView(values_data,
sizeof(DataType), dim1_size * dim2_size);
1071 _writeDataSetGeneric(data_info, gather_info, nb_dim, dim1_size, dim2_size, mem_view, hdf_type, is_collective);
1077template <
typename DataType>
void VtkHdfV2DataWriter::
1080 _writeDataSetGeneric(data_info, gather_info, 1, values.size(), 1, values.data(),
false);
1086template <
typename DataType>
void VtkHdfV2DataWriter::
1089 _writeDataSetGeneric(data_info, gather_info, 1, values.size(), 1, values.data(),
true);
1095template <
typename DataType>
void VtkHdfV2DataWriter::
1102 gather_info->computeSizeT(values);
1103 gg.setGatherGroupInfo(gather_info);
1105 if (gg.isNeedGather()) {
1106 UniqueArray<DataType> all_values;
1107 gg.gatherToMasterIOT(values, all_values);
1109 if (m_is_collective_io)
1110 _writeDataSet1DUsingCollectiveIO(data_info, gather_info, all_values.constSpan());
1112 _writeDataSet1D(data_info, gather_info, all_values.constSpan());
1115 if (m_is_collective_io)
1116 _writeDataSet1DUsingCollectiveIO(data_info, gather_info, values);
1118 _writeDataSet1D(data_info, gather_info, values);
1125template <
typename DataType>
void VtkHdfV2DataWriter::
1128 _writeDataSetGeneric(data_info, gather_info, 2, values.dim1Size(), values.dim2Size(), values.data(),
false);
1134template <
typename DataType>
void VtkHdfV2DataWriter::
1137 _writeDataSetGeneric(data_info, gather_info, 2, values.dim1Size(), values.dim2Size(), values.data(),
true);
1143template <
typename DataType>
void VtkHdfV2DataWriter::
1150 gather_info->computeSizeT(values);
1151 gg.setGatherGroupInfo(gather_info);
1153 if (gg.isNeedGather()) {
1154 UniqueArray2<DataType> all_values;
1155 gg.gatherToMasterIOT(values, all_values);
1157 if (m_is_collective_io)
1158 _writeDataSet2DUsingCollectiveIO(data_info, gather_info, all_values.constSpan());
1160 _writeDataSet2D(data_info, gather_info, all_values.constSpan());
1163 if (m_is_collective_io)
1164 _writeDataSet2DUsingCollectiveIO(data_info, gather_info, values);
1166 _writeDataSet2D(data_info, gather_info, values);
1173void VtkHdfV2DataWriter::
1176 hsize_t
len = values.size();
1177 hid_t aid = H5Screate_simple(1, &len,
nullptr);
1178 hid_t attr = H5Acreate2(hid.id(), name, H5T_NATIVE_INT64, aid, H5P_DEFAULT, H5P_DEFAULT);
1181 int ret = H5Awrite(attr, H5T_NATIVE_INT64, values.data());
1191void VtkHdfV2DataWriter::
1192_addInt64Attribute(
Hid& hid,
const char* name,
Int64 value)
1194 HSpace aid(H5Screate(H5S_SCALAR));
1196 if (m_is_first_call)
1197 attr.create(hid, name, H5T_NATIVE_INT64, aid);
1199 attr.open(hid, name);
1202 herr_t ret = attr.write(H5T_NATIVE_INT64, &value);
1210Int64 VtkHdfV2DataWriter::
1211_readInt64Attribute(
Hid& hid,
const char* name)
1214 attr.open(hid, name);
1218 herr_t ret = attr.read(H5T_NATIVE_INT64, &value);
1227void VtkHdfV2DataWriter::
1228_addStringAttribute(
Hid& hid,
const char* name,
const String& value)
1230 hid_t aid = H5Screate(H5S_SCALAR);
1231 hid_t attr_type = H5Tcopy(H5T_C_S1);
1232 H5Tset_size(attr_type, value.length());
1233 hid_t attr = H5Acreate2(hid.id(), name, attr_type, aid, H5P_DEFAULT, H5P_DEFAULT);
1236 int ret = H5Awrite(attr, attr_type, value.localstr());
1237 ret = H5Tclose(attr_type);
1247void VtkHdfV2DataWriter::
1253 for (
const auto& i : m_offset_info_list) {
1254 Int64 offset = i.second;
1256 HGroup* hdf_group = offset_info.group();
1260 _writeDataSet1D<Int64>({ { *hdf_group, offset_info.name() }, m_time_offset_info }, ggi.get(), asConstSpan(&offset));
1271void VtkHdfV2DataWriter::
1272_openOrCreateGroups()
1275 m_top_group.openOrCreate(
m_file_id,
"VTKHDF");
1276 m_cell_data_group.openOrCreate(m_top_group,
"CellData");
1277 m_node_data_group.openOrCreate(m_top_group,
"PointData");
1278 m_steps_group.openOrCreate(m_top_group,
"Steps");
1279 m_point_data_offsets_group.openOrCreate(m_steps_group,
"PointDataOffsets");
1280 m_cell_data_offsets_group.openOrCreate(m_steps_group,
"CellDataOffsets");
1281 m_field_data_offsets_group.openOrCreate(m_steps_group,
"FieldDataOffsets");
1287void VtkHdfV2DataWriter::
1290 m_cell_data_group.close();
1291 m_node_data_group.close();
1292 m_point_data_offsets_group.close();
1293 m_cell_data_offsets_group.close();
1294 m_field_data_offsets_group.close();
1295 m_steps_group.close();
1296 m_top_group.close();
1305 ARCANE_UNUSED(meta_data);
1314 info(4) <<
"Write VtkHdfV2 var=" << var->
name();
1319 ARCANE_FATAL(
"Only export of scalar item variable is implemented (name={0})", var->
name());
1321 ARCANE_FATAL(
"Export of partial variable is not implemented");
1327 switch (item_kind) {
1329 group = &m_cell_data_group;
1330 offset_info = m_cell_offset_info;
1331 group_info = &m_all_cells_info;
1332 gather_info = &m_all_cells_gather_group_info;
1335 group = &m_node_data_group;
1336 offset_info = m_point_offset_info;
1337 group_info = &m_all_nodes_info;
1338 gather_info = &m_all_nodes_gather_group_info;
1341 ARCANE_FATAL(
"Only export of 'Cell' or 'Node' variable is implemented (name={0})", var->
name());
1348 switch (data_type) {
1350 _writeBasicTypeDataset<Real>(data_info, gather_info, data);
1353 _writeBasicTypeDataset<Int64>(data_info, gather_info, data);
1356 _writeBasicTypeDataset<Int32>(data_info, gather_info, data);
1359 _writeReal3Dataset(data_info, gather_info, data);
1362 _writeReal2Dataset(data_info, gather_info, data);
1365 warning() << String::format(
"Export for datatype '{0}' is not supported (var_name={1})", data_type, var->
name());
1372template <
typename DataType>
void VtkHdfV2DataWriter::
1383void VtkHdfV2DataWriter::
1384_writeReal3Dataset(
const DataInfo& data_info, GatherGroupInfo* gather_info, IData* data)
1386 auto* true_data =
dynamic_cast<IArrayDataT<Real3>*
>(data);
1388 SmallSpan<const Real3> values(true_data->view());
1389 Int32 nb_value = values.size();
1391 UniqueArray2<Real> scalar_values;
1392 scalar_values.resize(nb_value, 3);
1393 for (Int32 i = 0; i < nb_value; ++i) {
1394 Real3 v = values[i];
1395 scalar_values[i][0] = v.x;
1396 scalar_values[i][1] = v.y;
1397 scalar_values[i][2] = v.z;
1399 _writeDataSet2DCollective<Real>(data_info, gather_info, scalar_values);
1405void VtkHdfV2DataWriter::
1409 auto* true_data =
dynamic_cast<IArrayDataT<Real2>*
>(data);
1411 SmallSpan<const Real2> values(true_data->view());
1412 Int32 nb_value = values.size();
1413 UniqueArray2<Real> scalar_values;
1414 scalar_values.resize(nb_value, 3);
1415 for (
Int32 i = 0; i < nb_value; ++i) {
1416 Real2 v = values[i];
1417 scalar_values[i][0] = v.x;
1418 scalar_values[i][1] = v.y;
1419 scalar_values[i][2] = 0.0;
1421 _writeDataSet2DCollective<Real>(data_info, gather_info, scalar_values);
1427void VtkHdfV2DataWriter::
1428_readAndSetOffset(DatasetInfo& offset_info,
Int32 wanted_step)
1430 HGroup* hgroup = offset_info.group();
1432 StandardArrayT<Int64> a(hgroup->id(), offset_info.name());
1433 UniqueArray<Int64> values;
1434 a.directRead(m_standard_types, values);
1435 Int64 offset_value = values[wanted_step];
1436 offset_info.setOffset(offset_value);
1437 info() <<
"VALUES name=" << offset_info.name() <<
" values=" << values
1438 <<
" wanted_step=" << wanted_step <<
" v=" << offset_value;
1444void VtkHdfV2DataWriter::
1480 m_cell_offset_info =
DatasetInfo(m_steps_group,
"CellOffsets");
1481 m_point_offset_info =
DatasetInfo(m_steps_group,
"PointOffsets");
1482 m_connectivity_offset_info =
DatasetInfo(m_steps_group,
"ConnectivityIdOffsets");
1483 m_face_connectivity_offset_info =
DatasetInfo(m_steps_group,
"FaceConnectivityOffsets");
1484 m_polyhedron_to_face_offset_info =
DatasetInfo(m_steps_group,
"PolyhedronToFaceIdOffsets");
1485 m_face_offsets_offset_info =
DatasetInfo(m_steps_group,
"FaceOffsetsOffsets");
1487 m_offset_for_cell_offset_info =
DatasetInfo(
"_OffsetForCellOffsetInfo");
1488 m_offset_for_face_offset_info =
DatasetInfo(
"_OffsetForFaceOffsetInfo");
1489 m_offset_for_polyhedron_offset_info =
DatasetInfo(
"_OffsetForPolyhedronOffsetInfo");
1490 m_part_offset_info =
DatasetInfo(
"_PartOffsetInfo");
1491 m_time_offset_info =
DatasetInfo(
"_TimeOffsetInfo");
1496 if (m_is_writer && !m_is_first_call) {
1497 IParallelMng* pm =
m_mesh->parallelMng();
1498 const Int32 nb_rank = pm->commSize();
1499 Int64 nb_current_step = _readInt64Attribute(m_steps_group,
"NSteps");
1501 info(4) <<
"NB_STEP=" << nb_current_step <<
" time_index=" << time_index
1502 <<
" current_time=" <<
m_times.back();
1503 const bool debug_times =
false;
1505 StandardArrayT<Real> a1(m_steps_group.id(),
"Values");
1506 UniqueArray<Real> times;
1507 a1.directRead(m_standard_types, times);
1508 info() <<
"TIMES=" << times;
1510 if ((nb_current_step + 1) != time_index) {
1511 info() <<
"[VtkHdf] go_backward detected";
1512 Int32 wanted_step = time_index - 1;
1515 _readAndSetOffset(m_cell_offset_info, wanted_step);
1516 _readAndSetOffset(m_point_offset_info, wanted_step);
1517 _readAndSetOffset(m_connectivity_offset_info, wanted_step);
1519 _readAndSetOffset(m_face_connectivity_offset_info, wanted_step);
1520 _readAndSetOffset(m_polyhedron_to_face_offset_info, wanted_step);
1521 _readAndSetOffset(m_face_offsets_offset_info, wanted_step);
1524 m_offset_for_face_offset_info.setOffset(m_face_offsets_offset_info.offset() + wanted_step * nb_rank);
1527 m_offset_for_polyhedron_offset_info.setOffset(m_offset_for_cell_offset_info.offset());
1529 m_part_offset_info.setOffset(wanted_step * nb_rank);
1530 m_time_offset_info.setOffset(wanted_step);
1531 m_offset_for_cell_offset_info.setOffset(m_cell_offset_info.offset() + wanted_step * nb_rank);
1544class VtkHdfV2PostProcessor
1557 bool use_collective_io =
true;
1558 Int64 max_write_size = 0;
1560 use_collective_io =
options()->useCollectiveWrite();
1561 max_write_size =
options()->maxWriteSize();
1563 auto w = std::make_unique<VtkHdfV2DataWriter>(
mesh(),
groups(), use_collective_io);
1564 w->setMaxWriteSize(max_write_size);
1565 w->setTimes(
times());
1567 w->setDirectoryName(dir.
file(
"vtkhdfv2"));
1568 m_writer = std::move(w);
1578 std::unique_ptr<IDataWriter> m_writer;
1584ARCANE_REGISTER_SERVICE_VTKHDFV2POSTPROCESSOR(VtkHdfV2PostProcessor,
1585 VtkHdfV2PostProcessor);
#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.
CaseOptionsVtkHdfV2PostProcessor * options() const
Options du jeu de données du service.
ArcaneVtkHdfV2PostProcessorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
Vue modifiable d'un tableau d'un type T.
Vue constante d'un tableau de type T.
Vue constante sur une zone mémoire contigue contenant des éléments de taille fixe.
constexpr Int32 datatypeSize() const
Taille du type de donnée associé (1 par défaut).
constexpr const std::byte * data() const
Pointeur sur la zone mémoire.
Classe gérant un répertoire.
String file(const String &file_name) const override
Retourne le chemin complet du fichier file_name dans le répertoire.
Tableau 1D de taille fixe.
Classe permettant de calculer et de conserver les informations de regroupements.
void computeSize(Int32 nb_elem_in) override
Méthode permettant de calculer les informations de regroupements.
Int32 nbWriterGlobal() override
Méthode pemettant de connaitre le nombre de sous-domaines écrivains.
Int32 nbElemOutput() override
Méthode permettant de connaitre le nombre d'éléments que notre sous-domaine devra traiter après récep...
Encapsule un hid_t pour un dataset.
Encapsule un hid_t pour un fichier.
Encapsule un hid_t pour un groupe.
static void useMutex(bool is_active, IParallelMng *pm)
Fonction permettant d'activer ou de désactiver les verrous à chaque appel à HDF5.
static constexpr bool hasParallelHdf5()
Vrai HDF5 est compilé avec le support de MPI.
Encapsule un hid_t pour une propriété (H5P*).
void createDatasetTransfertCollectiveMPIIO()
Créé une propriété de dataset pour MPIIO.
void createDatasetTransfertIndependentMPIIO()
Créé une propriété de dataset pour MPIIO.
Encapsule un hid_t pour un dataspace.
Définition des types standards Arcane pour hdf5.
Interface d'une donnée tableau d'un type T.
Interface d'écriture des données d'une variable.
Exception lorsqu'une erreur d'entrée/sortie est détectée.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
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....
Interface d'une variable.
virtual eDataType dataType() const =0
Type de la donnée gérée par la variable (Real, Integer, ...).
virtual eItemKind itemKind() const =0
Genre des entités du maillage sur lequel repose la variable.
virtual bool isPartial() const =0
Indique si la variable est partielle.
virtual Integer dimension() const =0
Dimension de la variable.
virtual String name() const =0
Nom de la variable.
Groupe d'entités de maillage.
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.
ItemGroupCollection groups() override
Liste des groupes à sauver.
ConstArrayView< Real > times() override
Liste des temps sauvés.
const String & baseDirectoryName() override
Nom du répertoire de sortie des fichiers.
Structure contenant les informations pour créer un service.
Vue pour un tableau 2D dont la taille est un 'Int64'.
Vue d'un tableau d'éléments de type T.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage warning() const
Flot pour un message d'avertissement.
Vecteur 1D de données avec sémantique par valeur (style STL).
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.
bool m_write_polyhedron_datasets
Vrai si les datasets liés aux mailles polyèdres doivent être écrits pour le pas de temps courant.
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.
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.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
ItemLocalIdListViewT< Node > NodeLocalIdView
Vue sur les localId() d'une liste de noeuds.
ItemGroupT< Cell > CellGroup
Groupe de mailles.
ItemGroupT< Node > NodeGroup
Groupe de noeuds.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
Integer len(const char *s)
Retourne la longueur de la chaîne s.
Fonctions utilitaires pour Hdf5.
Active toujours les traces dans les parties Arcane concernant les matériaux.
@ ReduceMax
Maximum des valeurs.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Ref< TrueType > createRef(Args &&... args)
Créé une instance de type TrueType avec les arguments Args et retourne une référence dessus.
Collection< ItemGroup > ItemGroupCollection
Collection de groupes d'éléments du maillage.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
@ Polyhedral
Maillage polyedrique.
bool operator<(const Item &item1, const Item &item2)
Compare deux entités.
ConstMemoryView makeConstMemoryView(const void *ptr, Int32 datatype_size, Int64 nb_element)
Créé une vue mémoire en lecture seule.
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
double Real
Type représentant un réel.
unsigned char Byte
Type d'un octet.
eDataType
Type d'une donnée.
@ DT_Int32
Donnée de type entier 32 bits.
@ DT_Real3
Donnée de type vecteur 3.
@ DT_Int64
Donnée de type entier 64 bits.
@ DT_Real2
Donnée de type vecteur 2.
@ DT_Real
Donnée de type réel.
@ Cell
Le maillage est AMR par maille.
std::int32_t Int32
Type entier signé sur 32 bits.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
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.
ItemGroup m_item_group
Groupe associé
Informations sur l'offset de la partie à écrire associée à un rang.
Int64 m_offset
Offset de mon rang.
Int64 m_size
Nombre d'éléments de mon rang.
Int64 m_total_size
Nombre d'éléments sur tous les rangs.