| 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 <utility> | ||
| 14 | #include <string> | ||
| 15 | #include <ranges> | ||
| 16 | #include <type_traits> | ||
| 17 | #include <filesystem> | ||
| 18 | |||
| 19 | #include <gridformat/common/output_file.hpp> | ||
| 20 | #include <gridformat/parallel/communication.hpp> | ||
| 21 | #include <gridformat/parallel/helpers.hpp> | ||
| 22 | #include <gridformat/xml/element.hpp> | ||
| 23 | #include <gridformat/grid/writer.hpp> | ||
| 24 | #include <gridformat/grid.hpp> | ||
| 25 | |||
| 26 | namespace GridFormat { | ||
| 27 | |||
| 28 | #ifndef DOXYGEN | ||
| 29 | namespace PVDDetail { | ||
| 30 | |||
| 31 | template<typename W> | ||
| 32 | class WriterStorage { | ||
| 33 | public: | ||
| 34 | 151 | explicit WriterStorage(W&& w) : _w(std::move(w)) {} | |
| 35 | |||
| 36 | protected: | ||
| 37 | 3201 | W& _writer() { return _w; } | |
| 38 | const W& _writer() const { return _w; } | ||
| 39 | |||
| 40 | private: | ||
| 41 | W _w; | ||
| 42 | }; | ||
| 43 | |||
| 44 | } // namespace PVDDetail | ||
| 45 | #endif // DOXYGEN | ||
| 46 | |||
| 47 | /*! | ||
| 48 | * \ingroup VTK | ||
| 49 | * \brief Writer for .pvd time-series file format | ||
| 50 | */ | ||
| 51 | template<typename VTKWriter> | ||
| 52 | class PVDWriter : public PVDDetail::WriterStorage<VTKWriter>, | ||
| 53 | public TimeSeriesGridWriter<typename VTKWriter::Grid> { | ||
| 54 | using Storage = PVDDetail::WriterStorage<VTKWriter>; | ||
| 55 | using ParentType = TimeSeriesGridWriter<typename VTKWriter::Grid>; | ||
| 56 | |||
| 57 | public: | ||
| 58 | 151 | explicit PVDWriter(VTKWriter&& writer, std::string base_filename) | |
| 59 | 151 | : Storage(std::move(writer)) | |
| 60 | 151 | , ParentType(Storage::_writer().grid(), Storage::_writer().writer_options()) | |
| 61 | 151 | , _base_filename{std::move(base_filename)} | |
| 62 |
2/4✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
|
151 | , _pvd_filename{_base_filename + ".pvd"} |
| 63 |
2/4✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 79 times.
✗ Branch 9 not taken.
|
604 | , _xml{"VTKFile"} { |
| 64 |
2/4✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
|
302 | _xml.set_attribute("type", "Collection"); |
| 65 |
2/4✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
|
302 | _xml.set_attribute("version", "1.0"); |
| 66 |
2/4✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 79 times.
✗ Branch 5 not taken.
|
302 | _xml.add_child("Collection"); |
| 67 | 151 | this->_writer().clear(); | |
| 68 | 151 | } | |
| 69 | |||
| 70 | private: | ||
| 71 | 687 | std::string _write(double _time) override { | |
| 72 |
1/2✓ Branch 2 taken 361 times.
✗ Branch 3 not taken.
|
687 | const auto time_step_index = _xml.get_child("Collection").number_of_children(); |
| 73 |
1/2✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
|
687 | const auto vtk_filename = _write_time_step_file(time_step_index); |
| 74 |
1/2✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
|
687 | _add_dataset(_time, vtk_filename); |
| 75 | |||
| 76 |
1/2✓ Branch 2 taken 250 times.
✗ Branch 3 not taken.
|
687 | const auto& communicator = Traits::CommunicatorAccess<VTKWriter>::get(this->_writer()); |
| 77 | // the collective invocation also makes sure all processes exit here after the pvd file is written | ||
| 78 |
2/2✓ Branch 1 taken 358 times.
✓ Branch 2 taken 3 times.
|
1046 | Parallel::invoke_collectively(communicator, [&] () { |
| 79 |
12/12✓ Branch 1 taken 70 times.
✓ Branch 2 taken 38 times.
✓ Branch 4 taken 41 times.
✓ Branch 5 taken 23 times.
✓ Branch 7 taken 26 times.
✓ Branch 8 taken 13 times.
✓ Branch 10 taken 26 times.
✓ Branch 11 taken 13 times.
✓ Branch 13 taken 23 times.
✓ Branch 14 taken 13 times.
✓ Branch 16 taken 50 times.
✓ Branch 17 taken 25 times.
|
361 | if (Parallel::rank(communicator) == 0) { |
| 80 |
13/24✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✓ Branch 5 taken 2 times.
✓ Branch 9 taken 41 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 41 times.
✗ Branch 13 not taken.
✓ Branch 17 taken 26 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 26 times.
✗ Branch 21 not taken.
✓ Branch 25 taken 26 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 26 times.
✗ Branch 29 not taken.
✓ Branch 33 taken 23 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 23 times.
✗ Branch 37 not taken.
✓ Branch 41 taken 50 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 50 times.
✗ Branch 45 not taken.
|
664 | write_to(_pvd_filename, [&] (std::ostream& s) { |
| 81 |
12/24✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 41 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 41 times.
✗ Branch 13 not taken.
✓ Branch 17 taken 26 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 26 times.
✗ Branch 21 not taken.
✓ Branch 25 taken 26 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 26 times.
✗ Branch 29 not taken.
✓ Branch 33 taken 23 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 23 times.
✗ Branch 37 not taken.
✓ Branch 41 taken 50 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 50 times.
✗ Branch 45 not taken.
|
234 | write_xml_with_version_header(_xml, s, Indentation{{.width = 2}}); |
| 82 | }); | ||
| 83 | } | ||
| 84 |
3/6✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 361 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 361 times.
✗ Branch 8 not taken.
|
1383 | }, "Writing '" + _pvd_filename.string() + "'"); |
| 85 | |||
| 86 |
1/2✓ Branch 1 taken 358 times.
✗ Branch 2 not taken.
|
1368 | return _pvd_filename; |
| 87 | 687 | } | |
| 88 | |||
| 89 | 687 | std::string _write_time_step_file(const std::integral auto index) { | |
| 90 | 687 | this->copy_fields(this->_writer()); | |
| 91 |
1/2✓ Branch 2 taken 361 times.
✗ Branch 3 not taken.
|
1374 | const auto filename = this->_writer().write( |
| 92 |
3/6✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 361 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 361 times.
✗ Branch 8 not taken.
|
1374 | _base_filename + "-" + _get_file_number_string(index) |
| 93 | ); | ||
| 94 | 687 | this->_writer().clear(); | |
| 95 | 687 | return filename; | |
| 96 | } | ||
| 97 | |||
| 98 | 687 | std::string _get_file_number_string(const std::integral auto index) const { | |
| 99 |
1/2✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
|
687 | std::ostringstream file_number; |
| 100 |
2/4✓ Branch 4 taken 361 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 361 times.
✗ Branch 8 not taken.
|
687 | file_number << std::setw(5) << std::setfill('0') << index; |
| 101 |
1/2✓ Branch 1 taken 361 times.
✗ Branch 2 not taken.
|
1374 | return file_number.str(); |
| 102 | 687 | } | |
| 103 | |||
| 104 | 361 | XMLElement& _add_dataset(const Concepts::Scalar auto _time, const std::string& filename) { | |
| 105 |
3/6✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 35 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 35 times.
✗ Branch 9 not taken.
|
722 | auto& dataset = _xml.get_child("Collection").add_child("DataSet"); |
| 106 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
722 | dataset.set_attribute("timestep", _time); |
| 107 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
722 | dataset.set_attribute("group", ""); |
| 108 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
722 | dataset.set_attribute("part", "0"); |
| 109 |
2/4✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
722 | dataset.set_attribute("name", ""); |
| 110 |
4/8✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 35 times.
✗ Branch 11 not taken.
|
1083 | dataset.set_attribute("file", std::filesystem::path{filename}.filename()); |
| 111 | 361 | return dataset; | |
| 112 | } | ||
| 113 | |||
| 114 | std::string _base_filename; | ||
| 115 | std::filesystem::path _pvd_filename; | ||
| 116 | XMLElement _xml; | ||
| 117 | }; | ||
| 118 | |||
| 119 | template<typename VTKWriter> | ||
| 120 | PVDWriter(VTKWriter&&) -> PVDWriter<std::remove_cvref_t<VTKWriter>>; | ||
| 121 | |||
| 122 | namespace Traits { | ||
| 123 | |||
| 124 | template<typename VTKWriter> | ||
| 125 | struct WritesConnectivity<PVDWriter<VTKWriter>> : public WritesConnectivity<VTKWriter> {}; | ||
| 126 | |||
| 127 | } // namespace Traits | ||
| 128 | } // namespace GridFormat | ||
| 129 | |||
| 130 | #endif // GRIDFORMAT_VTK_PVD_WRITER_HPP_ | ||
| 131 |