GridFormat 0.2.1
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
vtr_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_VTR_WRITER_HPP_
9#define GRIDFORMAT_VTK_VTR_WRITER_HPP_
10
11#include <array>
12#include <ranges>
13#include <ostream>
14#include <utility>
15#include <string>
16#include <optional>
17#include <iterator>
18
20#include <gridformat/common/field_storage.hpp>
21#include <gridformat/common/lvalue_reference.hpp>
22
23#include <gridformat/grid/grid.hpp>
24#include <gridformat/grid/type_traits.hpp>
27
28namespace GridFormat {
29
34template<Concepts::RectilinearGrid Grid>
35class VTRWriter : public VTK::XMLWriterBase<Grid, VTRWriter<Grid>> {
37 using CType = CoordinateType<Grid>;
38 static constexpr std::size_t dim = dimension<Grid>;
39 static constexpr std::size_t space_dim = 3;
40 static_assert(dim <= 3);
41
42 public:
43 struct Domain {
44 std::array<std::size_t, dim> whole_extent;
45 };
46
47 using Offset = std::array<std::size_t, dim>;
48
49 explicit VTRWriter(LValueReferenceOf<const Grid> grid,
50 VTK::XMLOptions xml_opts = {})
51 : ParentType(grid.get(), ".vtr", true, std::move(xml_opts))
52 {}
53
54 VTRWriter as_piece_for(Domain domain) const {
55 auto result = this->with(this->_xml_opts);
56 result._domain = std::move(domain);
57 result._offset = _offset;
58 return result;
59 }
60
61 VTRWriter with_offset(Offset offset) const {
62 auto result = this->with(this->_xml_opts);
63 result._offset = std::move(offset);
64 result._domain = _domain;
65 return result;
66 }
67
68 private:
69 VTRWriter _with(VTK::XMLOptions xml_opts) const override {
70 return VTRWriter{this->grid(), std::move(xml_opts)};
71 }
72
73 void _write(std::ostream& s) const override {
74 auto context = this->_get_write_context("RectilinearGrid");
75 _set_attributes(context);
76
77 FieldStorage vtk_point_fields;
78 FieldStorage vtk_cell_fields;
79 std::ranges::for_each(this->_point_field_names(), [&] (const std::string& name) {
80 vtk_cell_fields.set(name, VTK::make_vtk_field(this->_get_point_field_ptr(name)));
81 this->_set_data_array(context, "Piece/PointData", name, vtk_cell_fields.get(name));
82 });
83 std::ranges::for_each(this->_cell_field_names(), [&] (const std::string& name) {
84 vtk_cell_fields.set(name, VTK::make_vtk_field(this->_get_cell_field_ptr(name)));
85 this->_set_data_array(context, "Piece/CellData", name, vtk_cell_fields.get(name));
86 });
87
88 const auto coord_fields = _make_ordinate_fields();
89 for (unsigned dir = 0; dir < space_dim; ++dir)
90 this->_set_data_array(context, "Piece/Coordinates", "X_" + std::to_string(dir), *coord_fields[dir]);
91 this->_write_xml(std::move(context), s);
92 }
93
94 void _set_attributes(typename ParentType::WriteContext& context) const {
95 _set_domain_attributes(context);
96 _set_extent_attributes(context);
97 }
98
99 void _set_domain_attributes(typename ParentType::WriteContext& context) const {
100 using VTK::CommonDetail::extents_string;
101 if (_domain)
102 this->_set_attribute(context, "", "WholeExtent", extents_string(_domain->whole_extent));
103 else
104 this->_set_attribute(context, "", "WholeExtent", extents_string(this->grid()));
105 }
106
107 void _set_extent_attributes(typename ParentType::WriteContext& context) const {
108 using VTK::CommonDetail::extents_string;
109 if (int i = 0; _offset) {
110 auto begin = (*_offset);
111 auto end = GridFormat::extents(this->grid());
112 std::ranges::for_each(end, [&] (std::integral auto& ex) { ex += begin[i++]; });
113 this->_set_attribute(context, "Piece", "Extent", extents_string(begin, end));
114 } else {
115 this->_set_attribute(context, "Piece", "Extent", extents_string(this->grid()));
116 }
117 }
118
119 std::array<FieldPtr, space_dim> _make_ordinate_fields() const {
120 std::array<FieldPtr, space_dim> result;
121 std::visit([&] <typename T> (const Precision<T>& prec) {
122 for (unsigned dir = 0; dir < space_dim; ++dir) {
123 if (dir < dim)
124 result[dir] = make_field_ptr(RangeField{ordinates(this->grid(), dir), prec});
125 else
126 result[dir] = make_field_ptr(RangeField{std::vector<double>{}, prec});
127 }
128 }, this->_xml_settings.coordinate_precision);
129 return result;
130 }
131
132 std::optional<Domain> _domain;
133 std::optional<Offset> _offset;
134};
135
136template<typename G>
137VTRWriter(G&&, VTK::XMLOptions = {}) -> VTRWriter<std::remove_cvref_t<G>>;
138
139namespace Traits {
140
141template<typename... Args>
142struct WritesConnectivity<VTRWriter<Args...>> : public std::false_type {};
143
144} // namespace Traits
145} // namespace GridFormat
146
147#endif // GRIDFORMAT_VTK_VTR_WRITER_HPP_
Base class for VTK-XML Writer implementations.
Definition: xml.hpp:190
Writer for .vtr file format.
Definition: vtr_writer.hpp:35
FieldPtr make_field_ptr(F &&f)
Factory function for field pointers.
Definition: field.hpp:192
Can be specialized by writers in case the file format does not contain connectivity information.
Definition: writer.hpp:36
Options for VTK-XML files for setting the desired encoding, data format and compression.
Definition: xml.hpp:99
Definition: vtr_writer.hpp:43
Common functionality for VTK writers.
Helper classes and functions for VTK XML-type file format writers & readers.