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: The 'VtkHdfV2' implementation is experimental";
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);
528 UniqueArray<Int64> faces_connectivity;
529 UniqueArray<Int64> faces_offset;
530 UniqueArray<Int64> polyhedron_to_faces;
531 UniqueArray<Int64> polyhedron_offset(nb_cell + 1);
533 polyhedron_offset[0] = 0;
543 Int32 connected_node_index = 0;
545 Int32 index = icell.index();
548 cells_uid[index] = cell.uniqueId();
551 bool is_ghost = !cell.isOwn();
553 ghost_type = VtkUtils::CellGhostTypes::DUPLICATECELL;
554 cells_ghost_type[index] = ghost_type;
556 const bool is_polyhedron = cell.typeInfo()->isPolyhedron() || (mesh_is_polyhedral && cell.nbFace() > 0);
557 unsigned char vtk_type = VtkUtils::VTK_POLYHEDRON;
559 vtk_type = VtkUtils::arcaneToVtkCellType(cell.type());
560 cells_type[index] = vtk_type;
561 for (NodeLocalId node : cell.nodeIds()) {
562 cells_connectivity[connected_node_index] = node;
563 ++connected_node_index;
565 cells_offset[index + 1] = connected_node_index;
568 for (Face face : cell.faces()) {
574 Int32 face_nb_node = face.nbNode();
575 bool is_back_cell = (face.backCellId().localId() == cell.localId());
577 for (NodeLocalId node : face.nodeIds())
578 faces_connectivity.add(node);
582 for (
Int32 i = face_nb_node - 1; i >= 0; --i)
583 faces_connectivity.add(node_ids[i]);
585 faces_offset.add(faces_connectivity.size());
586 polyhedron_to_faces.add(nb_face);
590 polyhedron_offset[index + 1] = polyhedron_to_faces.size();
600 Int32 local_has_polyhedron = (nb_face > 0) ? 1 : 0;
602 Int32 global_has_polyhedron_datasets = 0;
603 if (!m_is_first_call) {
604 Int32 local_has_polyhedron_datasets = 0;
606 HDataset polyhedron_dataset;
607 polyhedron_dataset.openIfExists(m_top_group,
"FaceConnectivity");
608 local_has_polyhedron_datasets = (polyhedron_dataset.id() > 0) ? 1 : 0;
612 if (global_has_polyhedron != 0 && global_has_polyhedron_datasets == 0 && !m_is_first_call)
613 ARCANE_FATAL(
"The mesh contains polyhedron cells but the associated datasets "
614 "do not exist in the file '{0}'. Polyhedron cells must be present "
615 "from the first output",
620 _initializeOffsets();
624 GatherGroupInfo* ggi = ggi_ref.get();
627 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"Offsets", m_offset_for_cell_offset_info),
634 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"PolyhedronOffsets", m_offset_for_polyhedron_offset_info),
635 ggi, polyhedron_offset);
637 ggi->setNeedRecompute();
639 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"Connectivity", m_connectivity_offset_info),
640 ggi, cells_connectivity);
641 ggi->setNeedRecompute();
645 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"FaceConnectivity", m_face_connectivity_offset_info),
646 ggi, faces_connectivity);
647 ggi->setNeedRecompute();
651 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"PolyhedronToFaces", m_polyhedron_to_face_offset_info),
652 ggi, polyhedron_to_faces);
653 ggi->setNeedRecompute();
657 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"FaceOffsets", m_offset_for_face_offset_info),
659 ggi->setNeedRecompute();
662 _writeDataSet1DCollective<unsigned char>(
DataInfo(m_top_group,
"Types", m_cell_offset_info),
663 &m_all_cells_gather_group_info, cells_type);
666 Int64 nb_cell_int64 = nb_cell;
667 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfCells", m_part_offset_info),
668 ggi, asConstSpan(&nb_cell_int64));
670 Int64 nb_node_int64 = nb_node;
671 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfPoints", m_part_offset_info),
672 ggi, asConstSpan(&nb_node_int64));
674 Int64 number_of_connectivity_ids = cells_connectivity.size();
675 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfConnectivityIds", m_part_offset_info),
676 ggi, asConstSpan(&number_of_connectivity_ids));
679 Int64 nb_face_int64 = nb_face;
680 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfFaces", m_part_offset_info),
681 ggi, asConstSpan(&nb_face_int64));
683 Int64 number_of_face_connectivity_ids = faces_connectivity.size();
684 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfFaceConnectivityIds", m_part_offset_info),
685 ggi, asConstSpan(&number_of_face_connectivity_ids));
687 Int64 number_of_polyhedron_to_face_ids = polyhedron_to_faces.size();
688 _writeDataSet1DCollective<Int64>(
DataInfo(m_top_group,
"NumberOfPolyhedronToFaceIds", m_part_offset_info),
689 ggi, asConstSpan(&number_of_polyhedron_to_face_ids));
692 ggi->setNeedRecompute();
696 UniqueArray<Int64> nodes_uid(nb_node);
697 UniqueArray<unsigned char> nodes_ghost_type(nb_node);
699 UniqueArray2<Real> points;
700 points.resize(nb_node, 3);
702 Int32 index = inode.index();
705 nodes_uid[index] = node.uniqueId();
708 bool is_ghost = !node.isOwn();
710 ghost_type = VtkUtils::PointGhostTypes::DUPLICATEPOINT;
711 nodes_ghost_type[index] = ghost_type;
713 Real3 pos = nodes_coordinates[inode];
714 points[index][0] = pos.x;
715 points[index][1] = pos.y;
716 points[index][2] = pos.z;
721 &m_all_nodes_gather_group_info, nodes_uid);
725 &m_all_nodes_gather_group_info, nodes_ghost_type);
730 ggi->setNeedRecompute();
735 &m_all_cells_gather_group_info, cells_ghost_type);
740 &m_all_cells_gather_group_info, cells_uid);
747 ggi, asConstSpan(¤t_time));
750 Int64 comm_size = pm->commSize();
751 Int64 part_offset = (time_index - 1) * comm_size;
753 ggi, asConstSpan(&part_offset));
761 auto face_offsets_write_offset = m_offset_info_list.find(m_offset_for_face_offset_info);
762 if (face_offsets_write_offset == m_offset_info_list.end())
763 ARCANE_FATAL(
"The dataset 'FaceOffsets' has not been written");
764 Int64 nb_offset_value = (time_index - 1) * comm_size;
765 Int64 face_offsets_offset = face_offsets_write_offset->second - nb_offset_value;
766 _writeDataSet1D<Int64>({ { m_steps_group,
"FaceOffsetsOffsets" }, m_time_offset_info }, ggi,
767 asConstSpan(&face_offsets_offset));
771 _addInt64Attribute(m_steps_group,
"NSteps", time_index);
775 _writeConstituentsGroups();
781void VtkHdfV2DataWriter::
782_writeConstituentsGroups()
793 m_materials_groups.add(group_info_ref);
796 m_gather_info_materials_groups.add(gather_info_ref);
799 GatherGroupInfo& gather_info = *gather_info_ref.get();
800 _initializeItemGroupCollectiveInfos(group_info, gather_info);
802 ConstArrayView<Int32> groups_ids = cells.view().localIds();
803 DatasetGroupAndName dataset_group_name(m_top_group, String(
"Constituent_") + cells.name());
805 info() <<
"Writing infos for group '" << cells.name() <<
"'";
806 _writeDataSet1DCollective<Int32>({ dataset_group_name, m_cell_offset_info, group_info_ref.get() }, gather_info_ref.get(), groups_ids);
825 Int64 dim1_size = local_size;
828 Int64 total_size = 0;
829 for (
Integer i = 0; i < nb_rank; ++i)
830 total_size += all_sizes[i];
833 for (
Integer i = 0; i < my_rank; ++i)
834 my_index += all_sizes[i];
837 part_info.setTotalSize(total_size);
838 part_info.setSize(local_size);
839 part_info.setOffset(my_index);
846void VtkHdfV2DataWriter::
847_initializeItemGroupCollectiveInfos(ItemGroupCollectiveInfo& group_info,
GatherGroupInfo& gather_info)
849 Int32 dim1_size = group_info.m_item_group.size();
851 gather_info.setCollectiveIO(m_is_collective_io);
861 std::pair<Int64, Int64> _getInterval(Int64 index, Int64 nb_interval, Int64 total_size)
863 Int64 n = total_size;
864 Int64 isize = n / nb_interval;
865 Int64 ibegin = index * isize;
867 if ((index + 1) == nb_interval)
869 return { ibegin, isize };
881void VtkHdfV2DataWriter::
885 const hid_t hdf_type,
bool is_collective)
891 HGroup& group = data_info.dataset.group;
892 const String& name = data_info.dataset.name;
896 Int64 wanted_offset = data_info.datasetInfo().
offset();
898 static constexpr int MAX_DIM = 2;
908 local_dims[0] = dim1_size;
909 local_dims[1] = dim2_size;
917 max_dims[0] = H5S_UNLIMITED;
918 max_dims[1] = dim2_size;
921 Int64 write_offset = 0;
924 Int64 global_dim1_size = dim1_size;
925 Int32 nb_participating_rank = 1;
930 if (data_info.m_group_info) {
933 part_info = data_info.m_group_info->writePartInfo();
938 global_dim1_size = part_info.totalSize();
939 my_index = part_info.offset();
958 if (m_is_first_call) {
961 global_dims[0] = global_dim1_size;
962 global_dims[1] = dim2_size;
964 Int64 chunk_size = global_dim1_size / nb_participating_rank;
965 if (chunk_size < 1024)
967 const Int64 max_chunk_size = 1024 * 1024 * 10;
968 chunk_size =
math::min(chunk_size, max_chunk_size);
969 chunk_dims[0] = chunk_size;
970 chunk_dims[1] = dim2_size;
971 info() <<
"CHUNK nb_dim=" << nb_dim
972 <<
" global_dim1_size=" << global_dim1_size
973 <<
" chunk0=" << chunk_dims[0]
974 <<
" chunk1=" << chunk_dims[1]
976 file_space.createSimple(nb_dim, global_dims.data(), max_dims.data());
978 plist_id.create(H5P_DATASET_CREATE);
979 H5Pset_chunk(plist_id.id(), nb_dim, chunk_dims.data());
980 dataset.create(group, name.localstr(), hdf_type, file_space,
HProperty{}, plist_id,
HProperty{});
983 hyperslab_offsets[0] = my_index;
984 hyperslab_offsets[1] = 0;
990 dataset.open(group, name.
localstr());
991 file_space = dataset.getSpace();
992 int nb_dimension = file_space.nbDimension();
993 if (nb_dimension != nb_dim)
998 file_space.getDimensions(original_dims.data(),
nullptr);
999 hsize_t offset0 = original_dims[0];
1002 if (wanted_offset >= 0) {
1003 offset0 = wanted_offset;
1004 info() <<
"Forcing offset to " << wanted_offset;
1006 global_dims[0] = offset0 + global_dim1_size;
1007 global_dims[1] = dim2_size;
1008 write_offset = offset0;
1011 if ((herror = dataset.setExtent(global_dims.data())) < 0)
1013 file_space = dataset.getSpace();
1015 hyperslab_offsets[0] = offset0 + my_index;
1016 hyperslab_offsets[1] = 0;
1017 info(4) <<
"APPEND nb_dim=" << nb_dim
1018 <<
" dim0=" << global_dims[0]
1019 <<
" count0=" << local_dims[0]
1020 <<
" offsets0=" << hyperslab_offsets[0] <<
" name=" << name;
1023 Int64 nb_write_byte = global_dim1_size * dim2_size * values_data.
datatypeSize();
1027 Int64 nb_interval = 1;
1031 info(4) <<
"WRITE global_size=" << nb_write_byte <<
" max_size=" <<
m_max_write_size <<
" nb_interval=" << nb_interval;
1033 for (
Int64 i = 0; i < nb_interval; ++i) {
1034 auto [index, nb_element] = _getInterval(i, nb_interval, dim1_size);
1037 dims[0] = nb_element;
1038 dims[1] = dim2_size;
1040 offsets[0] = hyperslab_offsets[0] + index;
1042 if ((herror = H5Sselect_hyperslab(file_space.id(), H5S_SELECT_SET, offsets.data(),
nullptr, dims.data(),
nullptr)) < 0)
1046 memory_space.createSimple(nb_dim, dims.data());
1049 if ((herror = dataset.write(hdf_type, values_data.
data() + data_offset, memory_space, file_space, write_plist_id)) < 0)
1052 if (dataset.isBad())
1056 if (!data_info.datasetInfo().isNull())
1057 m_offset_info_list.insert(std::make_pair(data_info.datasetInfo(), write_offset));
1063template <
typename DataType>
void VtkHdfV2DataWriter::
1065 Int64 dim1_size,
Int64 dim2_size,
const DataType* values_data,
1068 const hid_t hdf_type = m_standard_types.nativeType(DataType{});
1069 ConstMemoryView mem_view =
makeConstMemoryView(values_data,
sizeof(DataType), dim1_size * dim2_size);
1070 _writeDataSetGeneric(data_info, gather_info, nb_dim, dim1_size, dim2_size, mem_view, hdf_type, is_collective);
1076template <
typename DataType>
void VtkHdfV2DataWriter::
1079 _writeDataSetGeneric(data_info, gather_info, 1, values.size(), 1, values.data(),
false);
1085template <
typename DataType>
void VtkHdfV2DataWriter::
1088 _writeDataSetGeneric(data_info, gather_info, 1, values.size(), 1, values.data(),
true);
1094template <
typename DataType>
void VtkHdfV2DataWriter::
1101 gather_info->computeSizeT(values);
1102 gg.setGatherGroupInfo(gather_info);
1104 if (gg.isNeedGather()) {
1105 UniqueArray<DataType> all_values;
1106 gg.gatherToMasterIOT(values, all_values);
1108 if (m_is_collective_io)
1109 _writeDataSet1DUsingCollectiveIO(data_info, gather_info, all_values.constSpan());
1111 _writeDataSet1D(data_info, gather_info, all_values.constSpan());
1114 if (m_is_collective_io)
1115 _writeDataSet1DUsingCollectiveIO(data_info, gather_info, values);
1117 _writeDataSet1D(data_info, gather_info, values);
1124template <
typename DataType>
void VtkHdfV2DataWriter::
1127 _writeDataSetGeneric(data_info, gather_info, 2, values.dim1Size(), values.dim2Size(), values.data(),
false);
1133template <
typename DataType>
void VtkHdfV2DataWriter::
1136 _writeDataSetGeneric(data_info, gather_info, 2, values.dim1Size(), values.dim2Size(), values.data(),
true);
1142template <
typename DataType>
void VtkHdfV2DataWriter::
1149 gather_info->computeSizeT(values);
1150 gg.setGatherGroupInfo(gather_info);
1152 if (gg.isNeedGather()) {
1153 UniqueArray2<DataType> all_values;
1154 gg.gatherToMasterIOT(values, all_values);
1156 if (m_is_collective_io)
1157 _writeDataSet2DUsingCollectiveIO(data_info, gather_info, all_values.constSpan());
1159 _writeDataSet2D(data_info, gather_info, all_values.constSpan());
1162 if (m_is_collective_io)
1163 _writeDataSet2DUsingCollectiveIO(data_info, gather_info, values);
1165 _writeDataSet2D(data_info, gather_info, values);
1172void VtkHdfV2DataWriter::
1175 hsize_t
len = values.size();
1176 hid_t aid = H5Screate_simple(1, &len,
nullptr);
1177 hid_t attr = H5Acreate2(hid.id(), name, H5T_NATIVE_INT64, aid, H5P_DEFAULT, H5P_DEFAULT);
1180 int ret = H5Awrite(attr, H5T_NATIVE_INT64, values.data());
1190void VtkHdfV2DataWriter::
1191_addInt64Attribute(
Hid& hid,
const char* name,
Int64 value)
1193 HSpace aid(H5Screate(H5S_SCALAR));
1195 if (m_is_first_call)
1196 attr.create(hid, name, H5T_NATIVE_INT64, aid);
1198 attr.open(hid, name);
1201 herr_t ret = attr.write(H5T_NATIVE_INT64, &value);
1209Int64 VtkHdfV2DataWriter::
1210_readInt64Attribute(
Hid& hid,
const char* name)
1213 attr.open(hid, name);
1217 herr_t ret = attr.read(H5T_NATIVE_INT64, &value);
1226void VtkHdfV2DataWriter::
1227_addStringAttribute(
Hid& hid,
const char* name,
const String& value)
1229 hid_t aid = H5Screate(H5S_SCALAR);
1230 hid_t attr_type = H5Tcopy(H5T_C_S1);
1231 H5Tset_size(attr_type, value.length());
1232 hid_t attr = H5Acreate2(hid.id(), name, attr_type, aid, H5P_DEFAULT, H5P_DEFAULT);
1235 int ret = H5Awrite(attr, attr_type, value.localstr());
1236 ret = H5Tclose(attr_type);
1246void VtkHdfV2DataWriter::
1252 for (
const auto& i : m_offset_info_list) {
1253 Int64 offset = i.second;
1255 HGroup* hdf_group = offset_info.group();
1259 _writeDataSet1D<Int64>({ { *hdf_group, offset_info.name() }, m_time_offset_info }, ggi.get(), asConstSpan(&offset));
1270void VtkHdfV2DataWriter::
1271_openOrCreateGroups()
1274 m_top_group.openOrCreate(
m_file_id,
"VTKHDF");
1275 m_cell_data_group.openOrCreate(m_top_group,
"CellData");
1276 m_node_data_group.openOrCreate(m_top_group,
"PointData");
1277 m_steps_group.openOrCreate(m_top_group,
"Steps");
1278 m_point_data_offsets_group.openOrCreate(m_steps_group,
"PointDataOffsets");
1279 m_cell_data_offsets_group.openOrCreate(m_steps_group,
"CellDataOffsets");
1280 m_field_data_offsets_group.openOrCreate(m_steps_group,
"FieldDataOffsets");
1286void VtkHdfV2DataWriter::
1289 m_cell_data_group.close();
1290 m_node_data_group.close();
1291 m_point_data_offsets_group.close();
1292 m_cell_data_offsets_group.close();
1293 m_field_data_offsets_group.close();
1294 m_steps_group.close();
1295 m_top_group.close();
1304 ARCANE_UNUSED(meta_data);
1313 info(4) <<
"Write VtkHdfV2 var=" << var->
name();
1318 ARCANE_FATAL(
"Only export of scalar item variable is implemented (name={0})", var->
name());
1320 ARCANE_FATAL(
"Export of partial variable is not implemented");
1326 switch (item_kind) {
1328 group = &m_cell_data_group;
1329 offset_info = m_cell_offset_info;
1330 group_info = &m_all_cells_info;
1331 gather_info = &m_all_cells_gather_group_info;
1334 group = &m_node_data_group;
1335 offset_info = m_point_offset_info;
1336 group_info = &m_all_nodes_info;
1337 gather_info = &m_all_nodes_gather_group_info;
1340 ARCANE_FATAL(
"Only export of 'Cell' or 'Node' variable is implemented (name={0})", var->
name());
1347 switch (data_type) {
1349 _writeBasicTypeDataset<Real>(data_info, gather_info, data);
1352 _writeBasicTypeDataset<Int64>(data_info, gather_info, data);
1355 _writeBasicTypeDataset<Int32>(data_info, gather_info, data);
1358 _writeReal3Dataset(data_info, gather_info, data);
1361 _writeReal2Dataset(data_info, gather_info, data);
1364 warning() << String::format(
"Export for datatype '{0}' is not supported (var_name={1})", data_type, var->
name());
1371template <
typename DataType>
void VtkHdfV2DataWriter::
1382void VtkHdfV2DataWriter::
1383_writeReal3Dataset(
const DataInfo& data_info, GatherGroupInfo* gather_info, IData* data)
1385 auto* true_data =
dynamic_cast<IArrayDataT<Real3>*
>(data);
1387 SmallSpan<const Real3> values(true_data->view());
1388 Int32 nb_value = values.size();
1390 UniqueArray2<Real> scalar_values;
1391 scalar_values.resize(nb_value, 3);
1392 for (Int32 i = 0; i < nb_value; ++i) {
1393 Real3 v = values[i];
1394 scalar_values[i][0] = v.x;
1395 scalar_values[i][1] = v.y;
1396 scalar_values[i][2] = v.z;
1398 _writeDataSet2DCollective<Real>(data_info, gather_info, scalar_values);
1404void VtkHdfV2DataWriter::
1408 auto* true_data =
dynamic_cast<IArrayDataT<Real2>*
>(data);
1410 SmallSpan<const Real2> values(true_data->view());
1411 Int32 nb_value = values.size();
1412 UniqueArray2<Real> scalar_values;
1413 scalar_values.resize(nb_value, 3);
1414 for (
Int32 i = 0; i < nb_value; ++i) {
1415 Real2 v = values[i];
1416 scalar_values[i][0] = v.x;
1417 scalar_values[i][1] = v.y;
1418 scalar_values[i][2] = 0.0;
1420 _writeDataSet2DCollective<Real>(data_info, gather_info, scalar_values);
1426void VtkHdfV2DataWriter::
1427_readAndSetOffset(DatasetInfo& offset_info,
Int32 wanted_step)
1429 HGroup* hgroup = offset_info.group();
1431 StandardArrayT<Int64> a(hgroup->id(), offset_info.name());
1432 UniqueArray<Int64> values;
1433 a.directRead(m_standard_types, values);
1434 Int64 offset_value = values[wanted_step];
1435 offset_info.setOffset(offset_value);
1436 info() <<
"VALUES name=" << offset_info.name() <<
" values=" << values
1437 <<
" wanted_step=" << wanted_step <<
" v=" << offset_value;
1443void VtkHdfV2DataWriter::
1477 m_cell_offset_info =
DatasetInfo(m_steps_group,
"CellOffsets");
1478 m_point_offset_info =
DatasetInfo(m_steps_group,
"PointOffsets");
1479 m_connectivity_offset_info =
DatasetInfo(m_steps_group,
"ConnectivityIdOffsets");
1480 m_face_connectivity_offset_info =
DatasetInfo(m_steps_group,
"FaceConnectivityOffsets");
1481 m_polyhedron_to_face_offset_info =
DatasetInfo(m_steps_group,
"PolyhedronToFaceIdOffsets");
1482 m_face_offsets_offset_info =
DatasetInfo(m_steps_group,
"FaceOffsetsOffsets");
1484 m_offset_for_cell_offset_info =
DatasetInfo(
"_OffsetForCellOffsetInfo");
1485 m_offset_for_face_offset_info =
DatasetInfo(
"_OffsetForFaceOffsetInfo");
1486 m_offset_for_polyhedron_offset_info =
DatasetInfo(
"_OffsetForPolyhedronOffsetInfo");
1487 m_part_offset_info =
DatasetInfo(
"_PartOffsetInfo");
1488 m_time_offset_info =
DatasetInfo(
"_TimeOffsetInfo");
1493 if (m_is_writer && !m_is_first_call) {
1494 IParallelMng* pm =
m_mesh->parallelMng();
1495 const Int32 nb_rank = pm->commSize();
1496 Int64 nb_current_step = _readInt64Attribute(m_steps_group,
"NSteps");
1498 info(4) <<
"NB_STEP=" << nb_current_step <<
" time_index=" << time_index
1499 <<
" current_time=" <<
m_times.back();
1500 const bool debug_times =
false;
1502 StandardArrayT<Real> a1(m_steps_group.id(),
"Values");
1503 UniqueArray<Real> times;
1504 a1.directRead(m_standard_types, times);
1505 info() <<
"TIMES=" << times;
1507 if ((nb_current_step + 1) != time_index) {
1508 info() <<
"[VtkHdf] go_backward detected";
1509 Int32 wanted_step = time_index - 1;
1512 _readAndSetOffset(m_cell_offset_info, wanted_step);
1513 _readAndSetOffset(m_point_offset_info, wanted_step);
1514 _readAndSetOffset(m_connectivity_offset_info, wanted_step);
1516 _readAndSetOffset(m_face_connectivity_offset_info, wanted_step);
1517 _readAndSetOffset(m_polyhedron_to_face_offset_info, wanted_step);
1518 _readAndSetOffset(m_face_offsets_offset_info, wanted_step);
1521 m_offset_for_face_offset_info.setOffset(m_face_offsets_offset_info.offset() + wanted_step * nb_rank);
1524 m_offset_for_polyhedron_offset_info.setOffset(m_offset_for_cell_offset_info.offset());
1526 m_part_offset_info.setOffset(wanted_step * nb_rank);
1527 m_time_offset_info.setOffset(wanted_step);
1528 m_offset_for_cell_offset_info.setOffset(m_cell_offset_info.offset() + wanted_step * nb_rank);
1541class VtkHdfV2PostProcessor
1554 bool use_collective_io =
true;
1555 Int64 max_write_size = 0;
1557 use_collective_io =
options()->useCollectiveWrite();
1558 max_write_size =
options()->maxWriteSize();
1560 auto w = std::make_unique<VtkHdfV2DataWriter>(
mesh(),
groups(), use_collective_io);
1561 w->setMaxWriteSize(max_write_size);
1562 w->setTimes(
times());
1564 w->setDirectoryName(dir.
file(
"vtkhdfv2"));
1565 m_writer = std::move(w);
1575 std::unique_ptr<IDataWriter> m_writer;
1581ARCANE_REGISTER_SERVICE_VTKHDFV2POSTPROCESSOR(VtkHdfV2PostProcessor,
1582 VtkHdfV2PostProcessor);
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
CaseOptionsVtkHdfV2PostProcessor * options() const
Options du jeu de données du service.
ArcaneVtkHdfV2PostProcessorObject(const Arcane::ServiceBuildInfo &sbi)
Constructeur.
Modifiable view of an array of type T.
Constant view of an array of type T.
Constant view on a contiguous memory region containing fixed-size elements.
constexpr Int32 datatypeSize() const
Size of the associated data type (1 by default).
constexpr const std::byte * data() const
Pointer to the memory region.
Class managing a directory.
String file(const String &file_name) const override
Returns the full path of the file file_name in the directory.
Class allowing the calculation and storage of grouping information.
void computeSize(Int32 nb_elem_in) override
Method allowing the calculation of grouping information.
Int32 nbWriterGlobal() override
Method allowing knowledge of the number of writing subdomains.
Int32 nbElemOutput() override
Method allowing knowledge of the number of elements that our subdomain must process after reception.
Encapsulates a hid_t for a dataset.
Encapsulates a hid_t for a file.
Encapsulates a hid_t for a group.
static void useMutex(bool is_active, IParallelMng *pm)
Function allowing activation or deactivation of locks on each HDF5 call.
static constexpr bool hasParallelHdf5()
True HDF5 is compiled with MPI support.
Encapsulates a hid_t for a property (H5P*).
void createDatasetTransfertCollectiveMPIIO()
Creates a dataset property for MPIIO.
void createDatasetTransfertIndependentMPIIO()
Creates a dataset property for MPIIO.
Encapsulates a hid_t for a dataspace.
Definition of standard Arcane types for hdf5.
Interface of a 1D array data item of type T.
Interface for writing variable data.
Interface of a data item.
Exception when an input/output error is detected.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
virtual eDataType dataType() const =0
Data type managed by the variable (Real, Integer, ...).
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual bool isPartial() const =0
Indicates if the variable is partial.
virtual Integer dimension() const =0
Dimension of the variable.
virtual String name() const =0
Variable name.
Interface for the material and environment manager of a mesh.
static IMeshMaterialMng * getReference(const MeshHandleOrMesh &mesh_handle, bool create=true)
Retrieves or creates the reference associated with mesh.
ItemGroupCollection groups() override
List of groups to save.
ConstArrayView< Real > times() override
List of saved times.
const String & baseDirectoryName() override
Name of the output directory for files.
Structure containing the information to create a service.
View for a 2D array whose size is an 'Int64'.
View of an array of elements of type T.
Unicode character string constructor.
Unicode character string.
const char * localstr() const
Returns the conversion of the instance into UTF-8 encoding.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage info() const
Flow for an information message.
TraceMessage warning() const
Flow for a warning message.
1D data vector with value semantics (STL style).
void write(IVariable *var, IData *data) override
Writes the data data of the variable var.
IMeshMaterialMng * m_material_mng
Associated material manager (may be null).
Int64 m_max_write_size
Maximum size (in kilobytes) for a write operation.
String m_directory_name
Output directory.
WritePartInfo _computeWritePartInfo(Int64 local_size)
Computes the offset of our part and the total number of elements.
bool m_write_polyhedron_datasets
True if the datasets related to the polyhedron cells must be written for the current time step.
IMesh * m_mesh
Associated mesh.
HFile m_file_id
HDF file identifier.
ItemGroupCollection m_groups
List of groups to save.
UniqueArray< Real > m_times
List of times.
void setMetaData(const String &meta_data) override
Sets the metadata information.
String m_full_filename
Current HDF filename.
IDataWriter * dataWriter() override
Returns the writer associated with this post-processor.
void close() override
Closes the writer. After closing, it can no longer be used.
void notifyBeginWrite() override
Notifies that an output is going to be performed with the current parameters.
void notifyEndWrite() override
Notifies that an output has just been performed.
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
ItemLocalIdListViewT< Node > NodeLocalIdView
View over the localId() of a list of nodes.
ItemGroupT< Cell > CellGroup
Group of cells.
ItemGroupT< Node > NodeGroup
Group of nodes.
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Coordinate type quantity at node.
Integer len(const char *s)
Returns the length of the string s.
Utility functions for Hdf5.
Always enables tracing in Arcane parts concerning materials.
@ ReduceMax
Maximum of values.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Ref< TrueType > createRef(Args &&... args)
Creates an instance of type TrueType with arguments Args and returns a reference to it.
Collection< ItemGroup > ItemGroupCollection
Collection of mesh item groups.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
@ Polyhedral
Polyhedral mesh.
bool operator<(const Item &item1, const Item &item2)
Compare two entities.
ConstMemoryView makeConstMemoryView(const void *ptr, Int32 datatype_size, Int64 nb_element)
Creates a read-only memory view.
eItemKind
Mesh entity type.
@ IK_Node
Node mesh entity.
@ IK_Cell
Cell mesh entity.
double Real
Type representing a real number.
unsigned char Byte
Type of a byte.
@ DT_Int32
32-bit integer data type
@ DT_Real3
Vector 3 data type.
@ DT_Int64
64-bit integer data type
@ DT_Real2
Vector 2 data type.
@ Cell
The mesh is AMR by cell.
std::int32_t Int32
Signed integer type of 32 bits.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Stores info about the data to be saved and the associated offset.
Class to store a pair (hdf_group, dataset_name).
Class to store offset information.
Int64 offset() const
Offset value. (-1) if writing to the end of the array.
Collective information for an ItemGroup;.
WritePartInfo m_write_part_info
Writing information.
ItemGroup m_item_group
Associated group.
Offset information for the part to write associated with a rank.
Int64 m_offset
Offset of my rank.
Int64 m_size
Number of elements on my rank.
Int64 m_total_size
Number of elements across all ranks.