Line | Branch | Exec | Source |
---|---|---|---|
1 | // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de> | ||
2 | // SPDX-License-Identifier: MIT | ||
3 | /*! | ||
4 | * \file | ||
5 | * \ingroup VTK | ||
6 | * \copydoc GridFormat::PVDWriter | ||
7 | */ | ||
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> | ||
22 | #include <gridformat/grid/writer.hpp> | ||
23 | #include <gridformat/grid.hpp> | ||
24 | |||
25 | namespace GridFormat { | ||
26 | |||
27 | #ifndef DOXYGEN | ||
28 | namespace PVDDetail { | ||
29 | |||
30 | template<typename W> | ||
31 | class WriterStorage { | ||
32 | public: | ||
33 | 148 | explicit WriterStorage(W&& w) : _w(std::move(w)) {} | |
34 | |||
35 | protected: | ||
36 | 3180 | 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 | |||
46 | /*! | ||
47 | * \ingroup VTK | ||
48 | * \brief Writer for .pvd time-series file format | ||
49 | */ | ||
50 | template<typename VTKWriter> | ||
51 | class PVDWriter : public PVDDetail::WriterStorage<VTKWriter>, | ||
52 | public TimeSeriesGridWriter<typename VTKWriter::Grid> { | ||
53 | using Storage = PVDDetail::WriterStorage<VTKWriter>; | ||
54 | using ParentType = TimeSeriesGridWriter<typename VTKWriter::Grid>; | ||
55 | |||
56 | public: | ||
57 | 148 | explicit PVDWriter(VTKWriter&& writer, std::string base_filename) | |
58 | 148 | : Storage(std::move(writer)) | |
59 | 148 | , ParentType(Storage::_writer().grid(), Storage::_writer().writer_options()) | |
60 | 148 | , _base_filename{std::move(base_filename)} | |
61 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
148 | , _pvd_filename{_base_filename + ".pvd"} |
62 |
2/4✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 76 times.
✗ Branch 9 not taken.
|
592 | , _xml{"VTKFile"} { |
63 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
296 | _xml.set_attribute("type", "Collection"); |
64 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
296 | _xml.set_attribute("version", "1.0"); |
65 |
2/4✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 76 times.
✗ Branch 5 not taken.
|
296 | _xml.add_child("Collection"); |
66 | 148 | this->_writer().clear(); | |
67 | 148 | } | |
68 | |||
69 | private: | ||
70 | 684 | std::string _write(double _time) override { | |
71 |
1/2✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
|
684 | const auto time_step_index = _xml.get_child("Collection").number_of_children(); |
72 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
684 | const auto vtk_filename = _write_time_step_file(time_step_index); |
73 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
684 | _add_dataset(_time, vtk_filename); |
74 | |||
75 |
1/2✓ Branch 2 taken 248 times.
✗ Branch 3 not taken.
|
684 | const auto& communicator = Traits::CommunicatorAccess<VTKWriter>::get(this->_writer()); |
76 |
3/4✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 124 times.
✓ Branch 4 taken 124 times.
|
684 | if (Parallel::rank(communicator) == 0) { |
77 |
1/2✓ Branch 1 taken 234 times.
✗ Branch 2 not taken.
|
447 | std::ofstream pvd_file(_pvd_filename, std::ios::out); |
78 |
2/4✓ Branch 1 taken 234 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 234 times.
✗ Branch 5 not taken.
|
447 | write_xml_with_version_header(_xml, pvd_file, Indentation{{.width = 2}}); |
79 | 447 | } | |
80 |
1/2✓ Branch 1 taken 248 times.
✗ Branch 2 not taken.
|
684 | Parallel::barrier(communicator); // make sure all process exit here after the pvd file is written |
81 | |||
82 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
1368 | return _pvd_filename; |
83 | 684 | } | |
84 | |||
85 | 684 | std::string _write_time_step_file(const std::integral auto index) { | |
86 | 684 | this->copy_fields(this->_writer()); | |
87 |
1/2✓ Branch 2 taken 358 times.
✗ Branch 3 not taken.
|
1368 | const auto filename = this->_writer().write( |
88 |
3/6✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 358 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 358 times.
✗ Branch 8 not taken.
|
1368 | _base_filename + "-" + _get_file_number_string(index) |
89 | ); | ||
90 | 684 | this->_writer().clear(); | |
91 | 684 | return filename; | |
92 | } | ||
93 | |||
94 | 684 | std::string _get_file_number_string(const std::integral auto index) const { | |
95 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
684 | std::ostringstream file_number; |
96 |
2/4✓ Branch 4 taken 358 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 358 times.
✗ Branch 8 not taken.
|
684 | file_number << std::setw(5) << std::setfill('0') << index; |
97 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
1368 | return file_number.str(); |
98 | 684 | } | |
99 | |||
100 | 358 | XMLElement& _add_dataset(const Concepts::Scalar auto _time, const std::string& filename) { | |
101 |
3/6✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
|
716 | auto& dataset = _xml.get_child("Collection").add_child("DataSet"); |
102 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
|
716 | dataset.set_attribute("timestep", _time); |
103 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
|
716 | dataset.set_attribute("group", ""); |
104 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
|
716 | dataset.set_attribute("part", "0"); |
105 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
|
716 | dataset.set_attribute("name", ""); |
106 |
4/8✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 32 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 32 times.
✗ Branch 11 not taken.
|
1074 | dataset.set_attribute("file", std::filesystem::path{filename}.filename()); |
107 | 358 | return dataset; | |
108 | } | ||
109 | |||
110 | std::string _base_filename; | ||
111 | std::filesystem::path _pvd_filename; | ||
112 | XMLElement _xml; | ||
113 | }; | ||
114 | |||
115 | template<typename VTKWriter> | ||
116 | PVDWriter(VTKWriter&&) -> PVDWriter<std::remove_cvref_t<VTKWriter>>; | ||
117 | |||
118 | namespace Traits { | ||
119 | |||
120 | template<typename VTKWriter> | ||
121 | struct WritesConnectivity<PVDWriter<VTKWriter>> : public WritesConnectivity<VTKWriter> {}; | ||
122 | |||
123 | } // namespace Traits | ||
124 | } // namespace GridFormat | ||
125 | |||
126 | #endif // GRIDFORMAT_VTK_PVD_WRITER_HPP_ | ||
127 |