GridFormat 0.4.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
pvd_writer.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2// SPDX-License-Identifier: MIT
8#ifndef GRIDFORMAT_VTK_PVD_WRITER_HPP_
9#define GRIDFORMAT_VTK_PVD_WRITER_HPP_
10
11#include <iomanip>
12#include <sstream>
13#include <fstream>
14#include <utility>
15#include <string>
16#include <ranges>
17#include <type_traits>
18#include <filesystem>
19
20#include <gridformat/parallel/communication.hpp>
21#include <gridformat/xml/element.hpp>
23#include <gridformat/grid.hpp>
24
25namespace GridFormat {
26
27#ifndef DOXYGEN
28namespace PVDDetail {
29
30 template<typename W>
31 class WriterStorage {
32 public:
33 explicit WriterStorage(W&& w) : _w(std::move(w)) {}
34
35 protected:
36 W& _writer() { return _w; }
37 const W& _writer() const { return _w; }
38
39 private:
40 W _w;
41 };
42
43} // namespace PVDDetail
44#endif // DOXYGEN
45
50template<typename VTKWriter>
51class PVDWriter : public PVDDetail::WriterStorage<VTKWriter>,
52 public TimeSeriesGridWriter<typename VTKWriter::Grid> {
53 using Storage = PVDDetail::WriterStorage<VTKWriter>;
55
56 public:
57 explicit PVDWriter(VTKWriter&& writer, std::string base_filename)
58 : Storage(std::move(writer))
59 , ParentType(Storage::_writer().grid(), Storage::_writer().writer_options())
60 , _base_filename{std::move(base_filename)}
61 , _pvd_filename{_base_filename + ".pvd"}
62 , _xml{"VTKFile"} {
63 _xml.set_attribute("type", "Collection");
64 _xml.set_attribute("version", "1.0");
65 _xml.add_child("Collection");
66 this->_writer().clear();
67 }
68
69 private:
70 std::string _write(double _time) override {
71 const auto time_step_index = _xml.get_child("Collection").number_of_children();
72 const auto vtk_filename = _write_time_step_file(time_step_index);
73 _add_dataset(_time, vtk_filename);
74
75 const auto& communicator = Traits::CommunicatorAccess<VTKWriter>::get(this->_writer());
76 if (Parallel::rank(communicator) == 0) {
77 std::ofstream pvd_file(_pvd_filename, std::ios::out);
78 write_xml_with_version_header(_xml, pvd_file, Indentation{{.width = 2}});
79 }
80 Parallel::barrier(communicator); // make sure all process exit here after the pvd file is written
81
82 return _pvd_filename;
83 }
84
85 std::string _write_time_step_file(const std::integral auto index) {
86 this->copy_fields(this->_writer());
87 const auto filename = this->_writer().write(
88 _base_filename + "-" + _get_file_number_string(index)
89 );
90 this->_writer().clear();
91 return filename;
92 }
93
94 std::string _get_file_number_string(const std::integral auto index) const {
95 std::ostringstream file_number;
96 file_number << std::setw(5) << std::setfill('0') << index;
97 return file_number.str();
98 }
99
100 XMLElement& _add_dataset(const Concepts::Scalar auto _time, const std::string& filename) {
101 auto& dataset = _xml.get_child("Collection").add_child("DataSet");
102 dataset.set_attribute("timestep", _time);
103 dataset.set_attribute("group", "");
104 dataset.set_attribute("part", "0");
105 dataset.set_attribute("name", "");
106 dataset.set_attribute("file", std::filesystem::path{filename}.filename());
107 return dataset;
108 }
109
110 std::string _base_filename;
111 std::filesystem::path _pvd_filename;
112 XMLElement _xml;
113};
114
115template<typename VTKWriter>
117
118namespace Traits {
119
120template<typename VTKWriter>
121struct WritesConnectivity<PVDWriter<VTKWriter>> : public WritesConnectivity<VTKWriter> {};
122
123} // namespace Traits
124} // namespace GridFormat
125
126#endif // GRIDFORMAT_VTK_PVD_WRITER_HPP_
Writer for .pvd time-series file format.
Definition: pvd_writer.hpp:52
Abstract base class for time series file writers.
Definition: writer.hpp:344
Base classes for grid data writers.
Can be specialized by parallel writers to expose their underlying communicator.
Definition: writer.hpp:40
Can be specialized by writers in case the file format does not contain connectivity information.
Definition: writer.hpp:36