75 using Field =
typename FieldStorage::Field;
76 using FieldPtr =
typename FieldStorage::FieldPtr;
78 explicit GridWriterBase(
const Grid& grid, std::optional<WriterOptions> opts)
80 , _opts{std::move(opts)}
88 template<std::ranges::range R>
91 !std::is_array_v<std::remove_cvref_t<R>>,
92 "Built-in arrays are not supported, please use std::array (e.g. via std::to_array)"
95 !std::is_lvalue_reference_v<R>,
96 "Cannot take ranges by reference, please move or pass a view (e.g. std::views::all) "
97 "to data that outlives the writer"
99 _meta_data.set(name, RangeField{std::move(range)});
102 template<std::
size_t N>
103 void set_meta_data(
const std::string& name,
const char (&text)[N]) {
104 _meta_data.set(name, RangeField{std::to_array(text)});
107 void set_meta_data(
const std::string& name, std::string text) {
108 if (_opts && _opts.value().append_null_terminator_to_strings)
109 text.push_back(
'\0');
110 _meta_data.set(name, RangeField{std::move(text)});
113 template<Concepts::Scalar T>
115 _meta_data.set(name, ScalarField{value});
118 template<std::derived_from<Field> F>
120 static_assert(!std::is_lvalue_reference_v<F>,
"Cannot take metadata fields by reference, please move");
125 _meta_data.set(name, ptr);
128 FieldPtr remove_meta_data(
const std::string& name) {
129 return _meta_data.pop(name);
132 template<Concepts::Po
intFunction<Gr
id> F, Concepts::Scalar T = Gr
idDetail::Po
intFunctionScalarType<Gr
id, F>>
133 void set_point_field(
const std::string& name, F&& point_function,
const Precision<T>& prec = {}) {
134 static_assert(!std::is_lvalue_reference_v<F>,
"Cannot take functions by reference, please move");
135 set_point_field(name, _make_point_field(std::move(point_function), prec));
138 template<std::derived_from<Field> F>
139 void set_point_field(
const std::string& name, F&& field) {
140 static_assert(!std::is_lvalue_reference_v<F>,
"Cannot take fields by reference, please move");
144 void set_point_field(
const std::string& name, FieldPtr field_ptr) {
145 _point_fields.set(name, std::move(field_ptr));
148 FieldPtr remove_point_field(
const std::string& name) {
149 return _point_fields.pop(name);
152 template<Concepts::CellFunction<Gr
id> F, Concepts::Scalar T = Gr
idDetail::CellFunctionScalarType<Gr
id, F>>
153 void set_cell_field(
const std::string& name, F&& cell_function,
const Precision<T>& prec = {}) {
154 static_assert(!std::is_lvalue_reference_v<F>,
"Cannot take functions by reference, please move");
155 set_cell_field(name, _make_cell_field(std::move(cell_function), prec));
158 template<std::derived_from<Field> F>
159 void set_cell_field(
const std::string& name, F&& field) {
160 static_assert(!std::is_lvalue_reference_v<F>,
"Cannot take fields by reference, please move");
164 void set_cell_field(
const std::string& name, FieldPtr field_ptr) {
165 _cell_fields.set(name, field_ptr);
168 FieldPtr remove_cell_field(
const std::string& name) {
169 return _cell_fields.pop(name);
174 _point_fields.clear();
175 _cell_fields.clear();
178 void set_ignore_warnings(
bool value) {
179 _ignore_warnings = value;
182 const Grid& grid()
const {
186 const std::optional<WriterOptions>& writer_options()
const {
190 template<
typename Writer>
191 void copy_fields(Writer& w)
const {
192 if (_opts.has_value() != w.writer_options().has_value())
193 throw TypeError(
"Cannot copy fields into writers with different options");
194 if (_opts.has_value() && writer_options().value() != w.writer_options().value())
195 throw TypeError(
"Cannot copy fields into writers with different options");
197 for (
const auto& [name, field_ptr] : meta_data_fields(*
this))
198 w.set_meta_data(name, field_ptr);
199 for (
const auto& [name, field_ptr] : point_fields(*
this))
200 w.set_point_field(name, field_ptr);
201 for (
const auto& [name, field_ptr] : cell_fields(*
this))
202 w.set_cell_field(name, field_ptr);
206 friend Concepts::RangeOf<std::pair<std::string, FieldPtr>>
auto
208 return writer._point_field_names()
209 | std::views::filter([&, r=rank] (
const std::string& n) {
210 return writer._get_point_field(n).layout().dimension() - 1 == r;
212 | std::views::transform([&] (std::string n) {
213 auto field_ptr = writer._get_point_field_ptr(n);
214 return std::make_pair(std::move(n), std::move(field_ptr));
219 friend Concepts::RangeOf<std::pair<std::string, FieldPtr>>
auto
221 return writer._cell_field_names()
222 | std::views::filter([&, r=rank] (
const std::string& n) {
223 return writer._get_cell_field(n).layout().dimension() - 1 == r;
225 | std::views::transform([&] (std::string n) {
226 auto field_ptr = writer._get_cell_field_ptr(n);
227 return std::make_pair(std::move(n), std::move(field_ptr));
231 friend Concepts::RangeOf<std::pair<std::string, FieldPtr>>
auto point_fields(
const GridWriterBase& writer) {
232 return writer._point_field_names() | std::views::transform([&] (std::string n) {
233 auto field_ptr = writer._get_point_field_ptr(n);
234 return std::make_pair(std::move(n), std::move(field_ptr));
238 friend Concepts::RangeOf<std::pair<std::string, FieldPtr>>
auto cell_fields(
const GridWriterBase& writer) {
239 return writer._cell_field_names() | std::views::transform([&] (std::string n) {
240 auto field_ptr = writer._get_cell_field_ptr(n);
241 return std::make_pair(std::move(n), std::move(field_ptr));
245 friend Concepts::RangeOf<std::pair<std::string, FieldPtr>>
auto meta_data_fields(
const GridWriterBase& writer) {
246 return writer._meta_data_field_names() | std::views::transform([&] (std::string n) {
247 auto field_ptr = writer._get_meta_data_field_ptr(n);
248 return std::make_pair(std::move(n), std::move(field_ptr));
253 void _log_warning(std::string_view warning)
const {
254 if (!_ignore_warnings)
257 + (warning.ends_with(
"\n") ?
"" :
"\n")
258 +
"To deactivate this warning, call set_ignore_warnings(true);"
262 template<
typename EntityFunction, Concepts::Scalar T>
263 auto _make_point_field(EntityFunction&& f,
const Precision<T>& prec)
const {
264 if (_opts.has_value())
265 return PointField{_grid, std::move(f), _opts.value().use_structured_grid_ordering, prec};
266 return PointField{_grid, std::move(f),
false, prec};
269 template<
typename EntityFunction, Concepts::Scalar T>
270 auto _make_cell_field(EntityFunction&& f,
const Precision<T>& prec)
const {
271 if (_opts.has_value())
272 return CellField{_grid, std::move(f), _opts.value().use_structured_grid_ordering, prec};
273 return CellField{_grid, std::move(f),
false, prec};
276 std::ranges::range
auto _point_field_names()
const {
277 return _point_fields.field_names();
280 std::ranges::range
auto _cell_field_names()
const {
281 return _cell_fields.field_names();
284 const Field& _get_point_field(
const std::string& name)
const {
285 return _point_fields.get(name);
288 FieldPtr _get_point_field_ptr(
const std::string& name)
const {
289 return _point_fields.get_ptr(name);
292 const Field& _get_cell_field(
const std::string& name)
const {
293 return _cell_fields.get(name);
296 FieldPtr _get_cell_field_ptr(
const std::string& name)
const {
297 return _cell_fields.get_ptr(name);
300 std::ranges::range
auto _meta_data_field_names()
const {
301 return _meta_data.field_names();
304 const Field& _get_meta_data_field(
const std::string& name)
const {
305 return _meta_data.get(name);
308 FieldPtr _get_meta_data_field_ptr(
const std::string& name)
const {
309 return _meta_data.get_ptr(name);
314 FieldStorage _point_fields;
315 FieldStorage _cell_fields;
316 FieldStorage _meta_data;
317 std::optional<WriterOptions> _opts;
318 bool _ignore_warnings =
false;