Tatooine
rectilinear_grid.h
Go to the documentation of this file.
1#ifndef TATOOINE_RECTILINEAR_GRID_H
2#define TATOOINE_RECTILINEAR_GRID_H
3//==============================================================================
8#include <tatooine/concepts.h>
14#include <tatooine/filesystem.h>
15#include <tatooine/for_loop.h>
16#include <tatooine/nan.h>
17#if TATOOINE_HDF5_AVAILABLE
18#include <tatooine/hdf5.h>
19#endif
22#include <tatooine/linspace.h>
23#include <tatooine/netcdf.h>
24#include <tatooine/random.h>
25#include <tatooine/tags.h>
27#include <tatooine/tuple.h>
28#include <tatooine/vec.h>
29
30#include <map>
31#include <memory>
32#include <mutex>
33//==============================================================================
34namespace tatooine {
35//==============================================================================
36template <floating_point_range... Dimensions>
37 requires(sizeof...(Dimensions) > 1)
39public:
40 static constexpr bool is_uniform =
41 (is_linspace<std::decay_t<Dimensions>> && ...);
42 static constexpr auto num_dimensions() -> std::size_t {
43 return sizeof...(Dimensions);
44 }
45 using this_type = rectilinear_grid<Dimensions...>;
46 using real_type = common_type<typename Dimensions::value_type...>;
47 using vec_type = vec<real_type, num_dimensions()>;
49 using sequence_type = std::make_index_sequence<num_dimensions()>;
50
51 template <std::size_t I>
52 using dimension_type = variadic::ith_type<I, Dimensions...>;
54
58 detail::rectilinear_grid::vertex_handle<sizeof...(Dimensions)>;
61
62 // general property types
65 template <typename ValueType, bool HasNonConstReference = false>
68 this_type, ValueType, HasNonConstReference>;
69 template <typename Container>
72 this_type, typename Container::value_type, Container>;
73 template <typename F>
75 std::invoke_result_t<F, decltype(((void)std::declval<Dimensions>(),
76 std::declval<std::size_t>()))...>;
77
78 using property_ptr_type = std::unique_ptr<vertex_property_type>;
79 using property_container_type = std::map<std::string, property_ptr_type>;
80 //============================================================================
81private:
82 mutable std::mutex m_finite_difference_coefficients_mutex = {};
85
86 using finite_difference_coefficents_list_type = std::vector<real_type>;
87 // finite difference finite_difference_coefficentss per size per dimension
88 mutable std::vector<
89 std::array<finite_difference_coefficents_list_type, num_dimensions()>>
90 m_finite_difference_coefficients = {};
91 std::size_t m_chunk_size_for_lazy_properties = 2;
92 //============================================================================
93public:
95 constexpr rectilinear_grid() = default;
96 //============================================================================
98 constexpr rectilinear_grid(rectilinear_grid const &other)
99 : m_dimensions{other.m_dimensions},
100 m_finite_difference_coefficients{
101 other.m_finite_difference_coefficients} {
102 for (auto const &[name, prop] : other.m_vertex_properties) {
103 auto &emplaced_prop =
104 m_vertex_properties.emplace(name, prop->clone()).first->second;
105 emplaced_prop->set_grid(*this);
106 }
107 }
108 //============================================================================
110 constexpr rectilinear_grid(rectilinear_grid &&other) noexcept
111 : m_dimensions{std::move(other.m_dimensions)},
112 m_vertex_properties{std::move(other.m_vertex_properties)},
113 m_finite_difference_coefficients{
114 std::move(other.m_finite_difference_coefficients)} {
115 for (auto const &[name, prop] : m_vertex_properties) {
116 prop->set_grid(*this);
117 }
118 }
119 //----------------------------------------------------------------------------
121 template <floating_point_range... Dimensions_>
122 constexpr rectilinear_grid(Dimensions_ &&...dimensions)
123 requires(sizeof...(Dimensions_) == sizeof...(Dimensions))
124 : m_dimensions{std::forward<Dimensions_>(dimensions)...} {}
125 //----------------------------------------------------------------------------
126private:
127 template <typename Real, integral... Res, std::size_t... Seq>
129 axis_aligned_bounding_box<Real, num_dimensions()> const &bb,
130 std::index_sequence<Seq...> /*seq*/, Res const... res)
131 : m_dimensions{linspace<real_type>{real_type(bb.min(Seq)),
132 real_type(bb.max(Seq)),
133 static_cast<std::size_t>(res)}...} {}
134 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
135public:
136 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
139 template <typename Real, integral... Res>
140 requires(sizeof...(Res) == num_dimensions())
142 axis_aligned_bounding_box<Real, num_dimensions()> const &bb,
143 Res const... res)
144 : rectilinear_grid{bb, sequence_type{}, res...} {}
145 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149 constexpr rectilinear_grid(integral auto const... size)
151 linspace{0.0, 1.0, static_cast<std::size_t>(size)}...} {
152 assert(((size >= 0) && ...));
153 }
154 //----------------------------------------------------------------------------
156 rectilinear_grid(filesystem::path const &path) { read(path); }
157 //----------------------------------------------------------------------------
158 ~rectilinear_grid() = default;
159 //============================================================================
160private:
161 template <std::size_t... Ds>
162 constexpr auto
163 copy_without_properties(std::index_sequence<Ds...> /*seq*/) const {
164 return this_type{dimension<Ds>()...};
165 }
166
167public:
169 constexpr auto copy_without_properties() const {
170 return copy_without_properties(
171 std::make_index_sequence<num_dimensions()>{});
172 }
173 //============================================================================
174 constexpr auto operator=(rectilinear_grid const &other)
175 -> rectilinear_grid & = default;
176 constexpr auto operator=(rectilinear_grid &&other) noexcept
177 -> rectilinear_grid & {
178 m_dimensions = std::move(other.m_dimensions);
179 m_vertex_properties = std::move(other.m_vertex_properties);
180 m_finite_difference_coefficients =
181 std::move(other.m_finite_difference_coefficients);
182 for (auto const &[name, prop] : m_vertex_properties) {
183 prop->set_grid(*this);
184 }
185 for (auto const &[name, prop] : other.m_vertex_properties) {
186 prop->set_grid(other);
187 }
188 }
189 //----------------------------------------------------------------------------
192 template <std::size_t I>
193 requires(I < num_dimensions())
194 constexpr auto dimension() const -> auto const & {
195 return m_dimensions.template at<I>();
196 }
197 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
202 constexpr auto dimension(std::size_t const i) const -> auto const &
203 requires(is_same<Dimensions...>) && (num_dimensions() <= 11)
204 {
205 if (i == 0) {
206 return dimension<0>();
207 }
208 if constexpr (num_dimensions() > 1) {
209 if (i == 1) {
210 return dimension<1>();
211 }
212 }
213 if constexpr (num_dimensions() > 2) {
214 if (i == 2) {
215 return dimension<2>();
216 }
217 }
218 if constexpr (num_dimensions() > 3) {
219 if (i == 3) {
220 return dimension<3>();
221 }
222 }
223 if constexpr (num_dimensions() > 4) {
224 if (i == 4) {
225 return dimension<4>();
226 }
227 }
228 if constexpr (num_dimensions() > 5) {
229 if (i == 5) {
230 return dimension<5>();
231 }
232 }
233 if constexpr (num_dimensions() > 6) {
234 if (i == 6) {
235 return dimension<6>();
236 }
237 }
238 if constexpr (num_dimensions() > 7) {
239 if (i == 7) {
240 return dimension<7>();
241 }
242 }
243 if constexpr (num_dimensions() > 8) {
244 if (i == 8) {
245 return dimension<8>();
246 }
247 }
248 if constexpr (num_dimensions() > 9) {
249 if (i == 9) {
250 return dimension<9>();
251 }
252 }
253 if constexpr (num_dimensions() > 10) {
254 if (i == 10) {
255 return dimension<10>();
256 }
257 }
258 return dimension<0>();
259 }
260 //----------------------------------------------------------------------------
262 constexpr auto dimensions() const -> auto const & { return m_dimensions; }
263 //----------------------------------------------------------------------------
264private:
265 template <std::size_t... Seq>
266 constexpr auto min(std::index_sequence<Seq...> /*seq*/) const {
267 return vec<real_type, num_dimensions()>{
268 static_cast<real_type>(dimension<Seq>().front())...};
269 }
270 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271public:
273 constexpr auto min() const { return min(sequence_type{}); }
274 //----------------------------------------------------------------------------
275private:
276 template <std::size_t... Seq>
277 constexpr auto max(std::index_sequence<Seq...> /*seq*/) const {
278 return vec<real_type, num_dimensions()>{
279 static_cast<real_type>(dimension<Seq>().back())...};
280 }
281 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
282public:
284 constexpr auto max() const { return max(sequence_type{}); }
285 //----------------------------------------------------------------------------
287 template <std::size_t I> constexpr auto extent() const {
288 return dimension<I>().back() - dimension<I>().front();
289 }
290 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
291private:
293 template <std::size_t... Is>
294 constexpr auto extent(std::index_sequence<Is...> /*seq*/) const {
295 return vec{extent<Is>()...};
296 }
297 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
298public:
300 constexpr auto extent() const {
301 return extent(std::make_index_sequence<num_dimensions()>{});
302 }
303 //----------------------------------------------------------------------------
306 template <std::size_t DimensionIndex>
307 constexpr auto extent(std::size_t const cell_index) const {
308 auto const &dim = dimension<DimensionIndex>();
309 return dim[cell_index + 1] - dim[cell_index];
310 }
311 //----------------------------------------------------------------------------
312 template <std::size_t I> constexpr auto center() const {
313 return (dimension<I>().back() + dimension<I>().front()) / 2;
314 }
315 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
316private:
317 template <std::size_t... Is>
318 constexpr auto center(std::index_sequence<Is...> /*seq*/) const {
319 return vec{center<Is>()...};
320 }
321 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
322public:
323 constexpr auto center() const {
324 return center(std::make_index_sequence<num_dimensions()>{});
325 }
326 //----------------------------------------------------------------------------
327private:
329 template <std::size_t... Seq>
330 requires(sizeof...(Seq) == num_dimensions())
331 constexpr auto bounding_box(std::index_sequence<Seq...> /*seq*/) const {
332 return axis_aligned_bounding_box<real_type, num_dimensions()>{
333 vec<real_type, num_dimensions()>{
334 static_cast<real_type>(dimension<Seq>().front())...},
335 vec<real_type, num_dimensions()>{
336 static_cast<real_type>(dimension<Seq>().back())...}};
337 }
338 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
339public:
341 constexpr auto bounding_box() const { return bounding_box(sequence_type{}); }
342 //----------------------------------------------------------------------------
343private:
345 template <std::size_t... Seq>
346 requires(sizeof...(Seq) == num_dimensions())
347 constexpr auto size(std::index_sequence<Seq...> /*seq*/) const {
348 return std::array{size<Seq>()...};
349 }
350 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
351public:
353 constexpr auto size() const { return size(sequence_type{}); }
354 //----------------------------------------------------------------------------
357 template <std::size_t I> constexpr auto size() const {
358 return dimension<I>().size();
359 }
360 //----------------------------------------------------------------------------
364 constexpr auto size(std::size_t const i) const {
365 if (i == 0) {
366 return size<0>();
367 }
368 if constexpr (num_dimensions() > 1) {
369 if (i == 1) {
370 return size<1>();
371 }
372 }
373 if constexpr (num_dimensions() > 2) {
374 if (i == 2) {
375 return size<2>();
376 }
377 }
378 if constexpr (num_dimensions() > 3) {
379 if (i == 3) {
380 return size<3>();
381 }
382 }
383 if constexpr (num_dimensions() > 4) {
384 if (i == 4) {
385 return size<4>();
386 }
387 }
388 if constexpr (num_dimensions() > 5) {
389 if (i == 5) {
390 return size<5>();
391 }
392 }
393 if constexpr (num_dimensions() > 6) {
394 if (i == 6) {
395 return size<6>();
396 }
397 }
398 if constexpr (num_dimensions() > 7) {
399 if (i == 7) {
400 return size<7>();
401 }
402 }
403 if constexpr (num_dimensions() > 8) {
404 if (i == 8) {
405 return size<8>();
406 }
407 }
408 if constexpr (num_dimensions() > 9) {
409 if (i == 9) {
410 return size<9>();
411 }
412 }
413 if constexpr (num_dimensions() > 10) {
414 if (i == 10) {
415 return size<10>();
416 }
417 }
418 return std::numeric_limits<std::size_t>::max();
419 }
420 //----------------------------------------------------------------------------
421private:
423 for (auto &[name, prop] : vertex_properties()) {
424 prop->resize(size());
425 }
426 }
427
428public:
429 //----------------------------------------------------------------------------
431 template <std::size_t I>
432 constexpr auto set_dimension(convertible_to<dimension_type<I>> auto &&dim) {
433 m_finite_difference_coefficients.clear();
434 m_dimensions.template at<I>() = std::forward<decltype(dim)>(dim);
435 resize_vertex_properties();
436 }
437 //----------------------------------------------------------------------------
439 template <std::size_t I> constexpr auto push_back() {
440 m_finite_difference_coefficients.clear();
441 auto &dim = m_dimensions.template at<I>();
442 if constexpr (is_linspace<std::decay_t<decltype(dim)>>) {
443 dim.push_back();
444 } else {
445 dim.push_back(dimension<I>().back() + extent<I>(size<I>() - 2));
446 }
447 resize_vertex_properties();
448 }
449 //----------------------------------------------------------------------------
451 template <std::size_t I>
452 requires requires(dimension_type<I> dim) { dim.pop_back(); }
453 constexpr auto pop_back() {
454 m_finite_difference_coefficients.clear();
455 m_dimensions.template at<I>().pop_back();
456 resize_vertex_properties();
457 }
458 //----------------------------------------------------------------------------
460 template <std::size_t I>
461 requires requires(dimension_type<I> dim) { dim.pop_back(); }
462 constexpr auto pop_front() {
463 m_finite_difference_coefficients.clear();
464 m_dimensions.template at<I>().pop_front();
465 resize_vertex_properties();
466 }
467 //----------------------------------------------------------------------------
468private:
470 template <arithmetic... Comps, std::size_t... Seq>
471 requires(num_dimensions() == sizeof...(Comps))
472 constexpr auto is_inside(std::index_sequence<Seq...> /*seq*/,
473 Comps const... comps) const {
474 return ((dimension<Seq>().front() <= comps &&
475 comps <= dimension<Seq>().back()) &&
476 ...);
477 }
478 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
479public:
481 template <arithmetic... Comps>
482 requires(num_dimensions() == sizeof...(Comps))
483 constexpr auto is_inside(Comps const... comps) const {
484 return is_inside(std::make_index_sequence<num_dimensions()>{}, comps...);
485 }
486 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
487private:
489 template <std::size_t... Seq>
490 constexpr auto is_inside(pos_type const &p,
491 std::index_sequence<Seq...> /*seq*/) const {
492 return ((dimension<Seq>().front() <= p(Seq) &&
493 p(Seq) <= dimension<Seq>().back()) &&
494 ...);
495 }
496 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
497public:
499 constexpr auto is_inside(pos_type const &p) const {
500 return is_inside(p, std::make_index_sequence<num_dimensions()>{});
501 }
502 //----------------------------------------------------------------------------
503private:
505 template <std::size_t... Seq>
506 constexpr auto is_inside(std::array<real_type, num_dimensions()> const &p,
507 std::index_sequence<Seq...> /*seq*/) const {
508 return is_inside(p[Seq]...);
509 }
510 //----------------------------------------------------------------------------
511public:
513 constexpr auto
514 is_inside(std::array<real_type, num_dimensions()> const &p) const {
515 return is_inside(p, sequence_type{});
516 }
517 //----------------------------------------------------------------------------
520 template <std::size_t DimensionIndex>
521 auto cell_index(arithmetic auto x) const
522 -> std::pair<std::size_t, real_type> {
523 auto const &dim = dimension<DimensionIndex>();
524 using dim_value_type = value_type<std::decay_t<decltype(dim)>>;
525 if (std::abs(x - dim.front()) < 1e-10) {
526 x = dim.front();
527 }
528 if (std::abs(x - dim.back()) < 1e-10) {
529 x = dim.back();
530 }
531 if constexpr (is_linspace<std::decay_t<decltype(dim)>>) {
532 // calculate
533 auto pos = (x - dim.front()) / (dim.back() - dim.front()) *
534 static_cast<dim_value_type>((dim.size() - 1));
535 auto quantized_pos = static_cast<std::size_t>(std::floor(pos));
536 if (quantized_pos == dim.size() - 1) {
537 --quantized_pos;
538 }
539 auto cell_position = pos - static_cast<dim_value_type>(quantized_pos);
540 if (quantized_pos == dim.size() - 1) {
541 --quantized_pos;
542 cell_position = 1;
543 }
544 return {quantized_pos, cell_position};
545 } else {
546 // binary search
547 std::size_t left = 0;
548 std::size_t right = dim.size() - 1;
549 while (right - left > 1) {
550 auto const center = (right + left) / 2;
551 if (x < dim[center]) {
552 right = center;
553 } else {
554 left = center;
555 }
556 }
557 return {left, (x - dim[left]) / (dim[left + 1] - dim[left])};
558 }
559 }
560 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
562private:
563 template <std::size_t... DimensionIndex>
564 auto cell_index(std::index_sequence<DimensionIndex...>,
565 arithmetic auto const... xs) const
566 -> std::array<std::pair<std::size_t, double>, num_dimensions()> {
567 return std::array{cell_index<DimensionIndex>(static_cast<double>(xs))...};
568 }
569 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
570public:
571 auto cell_index(arithmetic auto const... xs) const
572 requires(sizeof...(xs) == num_dimensions())
573 {
574 return cell_index(sequence_type{}, xs...);
575 }
576 //------------------------------------------------------------------------------
577 auto cell_index(fixed_size_vec<num_dimensions()> auto &&xs) const {
578 return invoke_unpacked(
579 [this](auto const... xs) { return cell_index(xs...); },
580 unpack(std::forward<decltype(xs)>(xs)));
581 }
582 //----------------------------------------------------------------------------
583 auto finite_differences_coefficients(std::size_t const stencil_size,
584 std::size_t const dim_index,
585 std::size_t const i) const {
586 {
587 auto lock = std::lock_guard{m_finite_difference_coefficients_mutex};
588 if (stencil_size > m_finite_difference_coefficients.size()) {
589 create_finite_differences_coefficients(stencil_size);
590 }
591 }
592 auto beg =
593 begin(m_finite_difference_coefficients[stencil_size - 1][dim_index]);
594 return std::ranges::subrange{beg + stencil_size * i,
595 beg + stencil_size * (i + 1)};
596 }
597 //----------------------------------------------------------------------------
603 auto
604 create_finite_differences_coefficients(std::size_t const stencil_size) const {
605 using namespace std::ranges;
606 if (m_finite_difference_coefficients.size() < stencil_size) {
607 m_finite_difference_coefficients.resize(stencil_size);
608 }
609 auto &stencil_per_size = m_finite_difference_coefficients[stencil_size - 1];
610
611 auto const half_stencil_size = stencil_size / 2;
612 auto local_positions = std::vector<real_type>(stencil_size);
613
614 auto foreach_dim = [&, dim_idx = std::size_t{}](auto const &dim) mutable {
615 auto stencil_begin = begin(dim);
616 auto stencil_end = next(begin(dim), stencil_size);
617 assert(stencil_size <= dim.size());
618 for (auto it = begin(dim); it != end(dim); ++it) {
619 auto &stencil_per_dim = stencil_per_size[dim_idx];
620 auto distance_to_center = [&it](auto const &x) { return x - *it; };
622 1, subrange{stencil_begin, stencil_end} |
623 views::transform(distance_to_center)),
624 std::back_inserter(stencil_per_dim));
625 if (distance(stencil_begin, it) >=
626 static_cast<long>(half_stencil_size) &&
627 stencil_end != end(dim)) {
628 ++stencil_begin;
629 ++stencil_end;
630 }
631 }
632 ++dim_idx;
633 };
634 m_dimensions.iterate(foreach_dim);
635 }
636 //----------------------------------------------------------------------------
637 auto vertices() const { return vertex_container{*this}; }
638 //----------------------------------------------------------------------------
639 template <std::size_t... DIs, integral Int>
640 auto vertex_at(std::index_sequence<DIs...> /*seq*/,
641 std::array<Int, num_dimensions()> const &is) const
642 -> vec<real_type, num_dimensions()> {
643 return pos_type{static_cast<real_type>(dimension<DIs>()[is[DIs]])...};
644 }
645 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
646 template <std::size_t... DIs>
647 auto vertex_at(std::index_sequence<DIs...>, integral auto const... is) const
648 -> vec<real_type, num_dimensions()> {
649 static_assert(sizeof...(DIs) == sizeof...(is));
650 static_assert(sizeof...(is) == num_dimensions());
651 return pos_type{static_cast<real_type>(dimension<DIs>()[is])...};
652 }
653 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
654 auto vertex_at(integral auto const... is) const {
655 static_assert(sizeof...(is) == num_dimensions());
656 return vertex_at(sequence_type{}, is...);
657 }
658 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
659 template <integral Int>
660 auto vertex_at(std::array<Int, num_dimensions()> const &is) const {
661 return vertex_at(sequence_type{}, is);
662 }
663 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
664 auto vertex_at(vertex_handle const &h) const {
665 return vertex_at(sequence_type{}, h.indices());
666 }
667 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
668 auto operator[](vertex_handle const &h) const {
669 return vertex_at(sequence_type{}, h.indices());
670 }
671 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
672 constexpr auto plain_index(integral auto const... is)
673 requires(sizeof...(is) == num_dimensions())
674 {
675 auto const arr_is = std::array{is...};
676 auto const size = this->size();
677 auto pi = std::size_t{};
678 auto multiplier = 1;
679 for (std::size_t i = 0; i < sizeof...(is); ++i) {
680 pi += arr_is[i] * multiplier;
681 multiplier *= size[i];
682 }
683 return pi;
684 }
685 //----------------------------------------------------------------------------
686 auto cells() const { return cell_container{*this}; }
687 //----------------------------------------------------------------------------
688private:
689 template <std::size_t... Is>
690 auto add_dimension(floating_point_range auto &&additional_dimension,
691 std::index_sequence<Is...> /*seq*/) const {
692 return rectilinear_grid<Dimensions...,
693 std::decay_t<decltype(additional_dimension)>>{
694 dimension<Is>()...,
695 std::forward<decltype(additional_dimension)>(additional_dimension)};
696 }
697 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
698public:
699 auto add_dimension(floating_point_range auto &&additional_dimension) const {
700 return add_dimension(
701 std::forward<decltype(additional_dimension)>(additional_dimension),
702 sequence_type{});
703 }
704 //----------------------------------------------------------------------------
705 auto has_vertex_property(std::string const &name) {
706 return m_vertex_properties.find(name) != end(m_vertex_properties);
707 }
708 //----------------------------------------------------------------------------
709 auto remove_vertex_property(std::string const &name) -> void {
710 if (auto it = m_vertex_properties.find(name);
711 it != end(m_vertex_properties)) {
712 m_vertex_properties.erase(it);
713 }
714 }
715 //----------------------------------------------------------------------------
716 auto rename_vertex_property(std::string const &current_name,
717 std::string const &new_name) -> void {
718 if (auto it = m_vertex_properties.find(current_name);
719 it != end(m_vertex_properties)) {
720 auto handler = m_vertex_properties.extract(it);
721 handler.key() = new_name;
722 m_vertex_properties.insert(std::move(handler));
723 }
724 }
725 //----------------------------------------------------------------------------
726 template <typename Container, typename... Args>
727 auto create_vertex_property(std::string const &name, Args &&...args)
728 -> auto & {
729 if (!has_vertex_property(name)) {
730 auto new_prop = new typed_vertex_property_type<Container>{
731 *this, std::forward<Args>(args)...};
732 m_vertex_properties.emplace(
733 name, std::unique_ptr<vertex_property_type>{new_prop});
734 if constexpr (sizeof...(Args) == 0) {
735 new_prop->resize(size());
736 }
737 return *new_prop;
738 }
739 throw std::runtime_error{"There is already a vertex property named \"" +
740 name + "\"."};
741 }
742 //----------------------------------------------------------------------------
743 auto vertex_properties() const -> auto const & { return m_vertex_properties; }
744 auto vertex_properties() -> auto & { return m_vertex_properties; }
745 //----------------------------------------------------------------------------
746 template <typename T, typename IndexOrder = x_fastest>
747 auto insert_vertex_property(std::string const &name) -> auto & {
748 return insert_contiguous_vertex_property<T, IndexOrder>(name);
749 }
750 //----------------------------------------------------------------------------
751 template <typename IndexOrder = x_fastest>
752 auto insert_scalar_vertex_property(std::string const &name) -> auto & {
753 return insert_vertex_property<tatooine::real_number, IndexOrder>(name);
754 }
755 //----------------------------------------------------------------------------
756 template <typename IndexOrder = x_fastest>
757 auto insert_vec2_vertex_property(std::string const &name) -> auto & {
758 return insert_vertex_property<vec2, IndexOrder>(name);
759 }
760 //----------------------------------------------------------------------------
761 template <typename IndexOrder = x_fastest>
762 auto insert_vec3_vertex_property(std::string const &name) -> auto & {
763 return insert_vertex_property<vec3, IndexOrder>(name);
764 }
765 //----------------------------------------------------------------------------
766 template <typename IndexOrder = x_fastest>
767 auto insert_vec4_vertex_property(std::string const &name) -> auto & {
768 return insert_vertex_property<vec4, IndexOrder>(name);
769 }
770 //----------------------------------------------------------------------------
771 template <typename IndexOrder = x_fastest>
772 auto insert_mat2_vertex_property(std::string const &name) -> auto & {
773 return insert_vertex_property<mat2, IndexOrder>(name);
774 }
775 //----------------------------------------------------------------------------
776 template <typename IndexOrder = x_fastest>
777 auto insert_mat3_vertex_property(std::string const &name) -> auto & {
778 return insert_vertex_property<mat3, IndexOrder>(name);
779 }
780 //----------------------------------------------------------------------------
781 template <typename IndexOrder = x_fastest>
782 auto insert_mat4_vertex_property(std::string const &name) -> auto & {
783 return insert_vertex_property<mat4, IndexOrder>(name);
784 }
785 //----------------------------------------------------------------------------
787 //----------------------------------------------------------------------------
788 template <typename T, typename IndexOrder = x_fastest>
789 auto insert_contiguous_vertex_property(std::string const &name) -> auto & {
790 return create_vertex_property<dynamic_multidim_array<T, IndexOrder>>(
791 name, size());
792 }
793 //----------------------------------------------------------------------------
794 template <typename T, typename IndexOrder = x_fastest>
795 auto
796 insert_chunked_vertex_property(std::string const &name,
797 std::vector<std::size_t> const &chunk_size)
798 -> auto & {
799 return create_vertex_property<chunked_multidim_array<T, IndexOrder>>(
800 name, size(), chunk_size);
801 }
802 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
803 template <typename T, typename IndexOrder = x_fastest>
805 std::string const &name,
806 std::array<std::size_t, num_dimensions()> const &chunk_size) -> auto & {
807 return create_vertex_property<chunked_multidim_array<T, IndexOrder>>(
808 name, size(), chunk_size);
809 }
810 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
811 template <typename T, typename IndexOrder = x_fastest>
812
813 auto insert_chunked_vertex_property(std::string const &name,
814 integral auto const... chunk_size)
815 -> auto &
816 requires(sizeof...(chunk_size) == num_dimensions())
817 {
818 return create_vertex_property<chunked_multidim_array<T, IndexOrder>>(
819 name, size(),
820 std::vector<std::size_t>{static_cast<std::size_t>(chunk_size)...});
821 }
822 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
823 template <typename T, typename IndexOrder = x_fastest>
824 auto insert_chunked_vertex_property(std::string const &name) -> auto & {
825 return create_vertex_property<chunked_multidim_array<T, IndexOrder>>(
826 name, size(), make_array<num_dimensions()>(std::size_t(10)));
827 }
828 //----------------------------------------------------------------------------
830 template <typename T, bool HasNonConstReference = true>
831 auto vertex_property(std::string const &name)
833 if (auto it = m_vertex_properties.find(name);
834 it == end(m_vertex_properties)) {
835 return insert_vertex_property<T>(name);
836 } else {
837 if (typeid(T) != it->second->type()) {
838 throw std::runtime_error{"type of property \"" + name + "\"(" +
839 type_name(it->second->type()) +
840 ") does not match specified type " +
841 type_name<T>() + "."};
842 }
843 return *dynamic_cast<
845 it->second.get());
846 }
847 }
848 //----------------------------------------------------------------------------
849 template <typename T, bool HasNonConstReference = true>
850 auto vertex_property(std::string const &name) const
852 if (auto it = m_vertex_properties.find(name);
853 it == end(m_vertex_properties)) {
854 throw std::runtime_error{"property \"" + name + "\" not found"};
855 } else {
856 if (typeid(T) != it->second->type()) {
857 throw std::runtime_error{"type of property \"" + name + "\"(" +
858 type_name(it->second->type()) +
859 ") does not match specified type " +
860 type_name<T>() + "."};
861 }
862 return *dynamic_cast<typed_vertex_property_interface_type<
863 T, HasNonConstReference> const *>(it->second.get());
864 }
865 }
866 //----------------------------------------------------------------------------
867 template <bool HasNonConstReference = true>
868 auto scalar_vertex_property(std::string const &name) const -> auto const & {
869 return vertex_property<tatooine::real_number, HasNonConstReference>(name);
870 }
871 //----------------------------------------------------------------------------
872 template <bool HasNonConstReference = true>
873 auto scalar_vertex_property(std::string const &name) -> auto & {
874 return vertex_property<tatooine::real_number, HasNonConstReference>(name);
875 }
876 //----------------------------------------------------------------------------
877 template <bool HasNonConstReference = true>
878 auto vec2_vertex_property(std::string const &name) const -> auto const & {
879 return vertex_property<vec2, HasNonConstReference>(name);
880 }
881 //----------------------------------------------------------------------------
882 template <bool HasNonConstReference = true>
883 auto vec2_vertex_property(std::string const &name) -> auto & {
884 return vertex_property<vec2, HasNonConstReference>(name);
885 }
886 //----------------------------------------------------------------------------
887 template <bool HasNonConstReference = true>
888 auto vec3_vertex_property(std::string const &name) const -> auto const & {
889 return vertex_property<vec3, HasNonConstReference>(name);
890 }
891 //----------------------------------------------------------------------------
892 template <bool HasNonConstReference = true>
893 auto vec3_vertex_property(std::string const &name) -> auto & {
894 return vertex_property<vec3, HasNonConstReference>(name);
895 }
896 //----------------------------------------------------------------------------
897 template <bool HasNonConstReference = true>
898 auto vec4_vertex_property(std::string const &name) const -> auto const & {
899 return vertex_property<vec4, HasNonConstReference>(name);
900 }
901 //----------------------------------------------------------------------------
902 template <bool HasNonConstReference = true>
903 auto vec4_vertex_property(std::string const &name) -> auto & {
904 return vertex_property<vec4, HasNonConstReference>(name);
905 }
906 //----------------------------------------------------------------------------
907 template <bool HasNonConstReference = true>
908 auto mat2_vertex_property(std::string const &name) const -> auto const & {
909 return vertex_property<mat2, HasNonConstReference>(name);
910 }
911 //----------------------------------------------------------------------------
912 template <bool HasNonConstReference = true>
913 auto mat2_vertex_property(std::string const &name) -> auto & {
914 return vertex_property<mat2, HasNonConstReference>(name);
915 }
916 //----------------------------------------------------------------------------
917 template <bool HasNonConstReference = true>
918 auto mat3_vertex_property(std::string const &name) const -> auto const & {
919 return vertex_property<mat3, HasNonConstReference>(name);
920 }
921 //----------------------------------------------------------------------------
922 template <bool HasNonConstReference = true>
923 auto mat3_vertex_property(std::string const &name) -> auto & {
924 return vertex_property<mat3, HasNonConstReference>(name);
925 }
926 //----------------------------------------------------------------------------
927 template <bool HasNonConstReference = true>
928 auto mat4_vertex_property(std::string const &name) const -> auto const & {
929 return vertex_property<mat4, HasNonConstReference>(name);
930 }
931 //----------------------------------------------------------------------------
932 template <bool HasNonConstReference = true>
933 auto mat4_vertex_property(std::string const &name) -> auto & {
934 return vertex_property<mat4, HasNonConstReference>(name);
935 }
936 //----------------------------------------------------------------------------
937 template <typename T, typename GlobalIndexOrder = x_fastest,
938 typename LocalIndexOrder = GlobalIndexOrder>
939 auto insert_lazy_vertex_property(filesystem::path const &path,
940 std::string const &dataset_name)
942 auto const ext = path.extension();
943#if TATOOINE_HDF5_AVAILABLE
944 if (ext == ".h5") {
945 return insert_hdf5_lazy_vertex_property<T, GlobalIndexOrder,
946 LocalIndexOrder>(path,
947 dataset_name);
948 }
949#endif
950#ifdef TATOOINE_NETCDF_AVAILABLE
951 if (ext == ".nc") {
952 return insert_netcdf_lazy_vertex_property<T, GlobalIndexOrder,
953 LocalIndexOrder>(path,
954 dataset_name);
955 }
956#endif
957 throw std::runtime_error{
958 "[rectilinear_grid::insert_lazy_vertex_property] - unknown file "
959 "extension"};
960 }
961 //----------------------------------------------------------------------------
962#if TATOOINE_HDF5_AVAILABLE
963 template <typename IndexOrder = x_fastest, typename T>
964 auto insert_vertex_property(hdf5::dataset<T> const &dataset) -> auto & {
965 return insert_vertex_property<IndexOrder>(dataset, dataset.name());
966 }
967 //----------------------------------------------------------------------------
968 template <typename IndexOrder = x_fastest, typename T>
970 std::string const &name) -> auto & {
971 auto num_dims_dataset = dataset.num_dimensions();
972 if (num_dimensions() != num_dims_dataset) {
973 throw std::runtime_error{"Number of dimensions(" +
974 std::to_string(num_dims_dataset) +
975 ") do not match for HDF5 dataset and "
976 "rectilinear_grid(" +
977 std::to_string(num_dimensions()) + ")."};
978 }
979 auto size_dataset = dataset.size();
980 for (std::size_t i = 0; i < num_dimensions(); ++i) {
981 if (size_dataset[i] != size(i)) {
982 std::stringstream ss;
983 ss << "Resolution of rectilinear_grid and HDF5 DataSet do not match. "
984 "rectilinear_grid("
985 << size(0);
986 for (std::size_t i = 1; i < num_dimensions(); ++i) {
987 ss << ", " << size(i);
988 }
989 ss << ") and hdf5 dataset(" << size_dataset[i];
990 for (std::size_t i = 1; i < num_dimensions(); ++i) {
991 ss << ", " << size_dataset[i];
992 }
993 ss << ")";
994 throw std::runtime_error{ss.str()};
995 }
996 }
997 auto &prop = insert_vertex_property<T, IndexOrder>(name);
998 dataset.read(prop);
999 return prop;
1000 }
1001 //----------------------------------------------------------------------------
1002 template <typename T, typename GlobalIndexOrder = x_fastest,
1003 typename LocalIndexOrder = GlobalIndexOrder>
1004 auto insert_hdf5_lazy_vertex_property(filesystem::path const &path,
1005 std::string const &dataset_name)
1006 -> auto & {
1007 hdf5::file f{path};
1008 return insert_lazy_vertex_property<GlobalIndexOrder, LocalIndexOrder>(
1009 f.dataset<T>(dataset_name));
1010 }
1011 //----------------------------------------------------------------------------
1012 template <typename GlobalIndexOrder = x_fastest,
1013 typename LocalIndexOrder = GlobalIndexOrder, typename T>
1014 auto insert_lazy_vertex_property(hdf5::dataset<T> const &dataset) -> auto & {
1015 return insert_lazy_vertex_property<GlobalIndexOrder, LocalIndexOrder>(
1016 dataset, dataset.name());
1017 }
1018 //----------------------------------------------------------------------------
1019 template <typename GlobalIndexOrder = x_fastest,
1020 typename LocalIndexOrder = GlobalIndexOrder, typename T>
1022 std::string const &name) -> auto & {
1023 auto num_dims_dataset = dataset.num_dimensions();
1024 if (num_dimensions() != num_dims_dataset) {
1025 throw std::runtime_error{
1026 "Number of dimensions do not match for HDF5 dataset and "
1027 "rectilinear_grid."};
1028 }
1029 auto size_dataset = dataset.size();
1030 for (std::size_t i = 0; i < num_dimensions(); ++i) {
1031 if (size_dataset[i] != size(i)) {
1032 std::stringstream ss;
1033 ss << "Resolution of rectilinear_grid and HDF5 DataSet (\"" << name
1034 << "\")do not match. rectilinear_grid(" << size(0);
1035 for (std::size_t i = 1; i < num_dimensions(); ++i) {
1036 ss << ", " << size(i);
1037 }
1038 ss << ") and hdf5 dataset(" << size_dataset[i];
1039 for (std::size_t i = 1; i < num_dimensions(); ++i) {
1040 ss << ", " << size_dataset[i];
1041 }
1042 ss << ")";
1043 throw std::runtime_error{ss.str()};
1044 }
1045 }
1046 return create_vertex_property<
1047 lazy_reader<hdf5::dataset<T>, GlobalIndexOrder, LocalIndexOrder>>(
1048 name, dataset,
1049 std::vector<std::size_t>(num_dimensions(),
1050 m_chunk_size_for_lazy_properties));
1051 }
1052#endif
1053#ifdef TATOOINE_NETCDF_AVAILABLE
1054 //----------------------------------------------------------------------------
1055 template <typename T, typename GlobalIndexOrder = x_fastest,
1056 typename LocalIndexOrder = GlobalIndexOrder>
1057 auto insert_netcdf_lazy_vertex_property(filesystem::path const &path,
1058 std::string const &dataset_name)
1059 -> auto & {
1060 netcdf::file f{path, netCDF::NcFile::read};
1061 return insert_lazy_vertex_property<GlobalIndexOrder, LocalIndexOrder, T>(
1062 f.variable<T>(dataset_name));
1063 }
1064 //----------------------------------------------------------------------------
1065 template <typename GlobalIndexOrder = x_fastest,
1066 typename LocalIndexOrder = GlobalIndexOrder, typename T>
1068 -> auto & {
1069 return create_vertex_property<
1070 lazy_reader<netcdf::variable<T>, GlobalIndexOrder, LocalIndexOrder>>(
1071 dataset.name(), dataset,
1072 std::vector<std::size_t>(num_dimensions(),
1073 m_chunk_size_for_lazy_properties));
1074 }
1075#endif
1076 //============================================================================
1077 template <typename F>
1078 requires invocable_with_n_integrals<F, num_dimensions()> ||
1080 auto sample_to_vertex_property(F &&f, std::string const &name)
1081 -> auto & {
1082 return sample_to_vertex_property(std::forward<F>(f), name,
1084 }
1085 //----------------------------------------------------------------------------
1086 template <typename F>
1087 requires invocable_with_n_integrals<F, num_dimensions()> ||
1089 auto sample_to_vertex_property(F &&f, std::string const &name,
1090 execution_policy_tag auto tag)
1091 -> auto & {
1092 if constexpr (invocable<F, pos_type>) {
1093 return sample_to_vertex_property_pos(std::forward<F>(f), name, tag);
1094 } else {
1095 return sample_to_vertex_property_indices(
1096 std::forward<F>(f), name, tag,
1097 std::make_index_sequence<num_dimensions()>{});
1098 }
1099 }
1100 //----------------------------------------------------------------------------
1101private:
1102 template <invocable_with_n_integrals<num_dimensions()> F, std::size_t... Is>
1103 auto sample_to_vertex_property_indices(F &&f, std::string const &name,
1104 execution_policy_tag auto tag,
1105 std::index_sequence<Is...> /*seq*/)
1106 -> auto & {
1107 using T = std::invoke_result_t<F, decltype(Is)...>;
1108 auto &prop = vertex_property<T>(name);
1109 vertices().iterate_indices(
1110 [&](auto const... is) {
1111 try {
1112 prop(is...) = f(is...);
1113 } catch (std::exception &) {
1114 if constexpr (tensor_num_components<T> == 1) {
1115 prop(is...) = nan<T>();
1116 } else {
1117 prop(is...) = T::fill(nan<tatooine::value_type<T>>());
1118 }
1119 }
1120 },
1121 tag);
1122 return prop;
1123 }
1124 //----------------------------------------------------------------------------
1125 template <invocable<pos_type> F>
1126 auto sample_to_vertex_property_pos(F &&f, std::string const &name,
1127 execution_policy_tag auto tag) -> auto & {
1128 using invoke_result = std::decay_t<std::invoke_result_t<F, pos_type>>;
1129 auto &prop = vertex_property<invoke_result>(name);
1130 vertices().iterate_indices(
1131 [&](auto const... is) {
1132 try {
1133 prop(is...) = f(vertices()(is...));
1134 } catch (std::exception &) {
1135 if constexpr (tensor_num_components<invoke_result> == 1) {
1136 prop(is...) = invoke_result{nan<invoke_result>()};
1137 } else {
1138 prop(is...) = invoke_result::fill(
1140 }
1141 }
1142 },
1143 tag);
1144 return prop;
1145 }
1146 //============================================================================
1147public:
1148 auto read(filesystem::path const &path) {
1149#ifdef TATOOINE_NETCDF_AVAILABLE
1150 if constexpr (!is_uniform) {
1151 if (path.extension() == ".nc") {
1152 read_netcdf(path);
1153 return;
1154 }
1155 }
1156#endif
1157 if constexpr (num_dimensions() == 2 || num_dimensions() == 3) {
1158 if (path.extension() == ".vtk") {
1159 read_vtk(path);
1160 return;
1161 }
1162 if constexpr (is_uniform) {
1163 if (path.extension() == ".am") {
1164 read_amira(path);
1165 return;
1166 }
1167 }
1168 }
1169 throw std::runtime_error{
1170 "[rectilinear_grid::read] Unknown file extension."};
1171 }
1172 //----------------------------------------------------------------------------
1177 vtk_listener(this_type &gr_, bool &is_structured_points_, vec3 &spacing_)
1178 : gr{gr_}, is_structured_points{is_structured_points_}, spacing{
1179 spacing_} {}
1180 // header data
1181 auto on_dataset_type(vtk::dataset_type t) -> void override {
1182 if (t == vtk::dataset_type::structured_points && !is_uniform) {
1183 is_structured_points = true;
1184 }
1185 }
1186
1187 // coordinate data
1188 auto on_origin(double x, double y, double z) -> void override {
1189 gr.dimension<0>().front() = x;
1190 gr.dimension<1>().front() = y;
1191 if (num_dimensions() < 3 && z > 1) {
1192 throw std::runtime_error{
1193 "[rectilinear_grid::read_vtk] number of dimensions is < 3 but got "
1194 "third "
1195 "dimension."};
1196 }
1197 if constexpr (num_dimensions() > 3) {
1198 gr.dimension<2>().front() = z;
1199 }
1200 }
1201 auto on_spacing(double x, double y, double z) -> void override {
1202 spacing = {x, y, z};
1203 }
1204 auto on_dimensions(std::size_t x, std::size_t y, std::size_t z)
1205 -> void override {
1206 gr.dimension<0>().resize(x);
1207 gr.dimension<1>().resize(y);
1208 if (num_dimensions() < 3 && z > 1) {
1209 throw std::runtime_error{
1210 "[rectilinear_grid::read_vtk] number of dimensions is < 3 but got "
1211 "third "
1212 "dimension."};
1213 }
1214 if constexpr (num_dimensions() > 2) {
1215 gr.dimension<2>().resize(z);
1216 }
1217 }
1218 auto on_x_coordinates(std::vector<float> const & /*xs*/) -> void override {}
1219 auto on_x_coordinates(std::vector<double> const & /*xs*/) -> void override {
1220 }
1221 auto on_y_coordinates(std::vector<float> const & /*ys*/) -> void override {}
1222 auto on_y_coordinates(std::vector<double> const & /*ys*/) -> void override {
1223 }
1224 auto on_z_coordinates(std::vector<float> const & /*zs*/) -> void override {}
1225 auto on_z_coordinates(std::vector<double> const & /*zs*/) -> void override {
1226 }
1227
1228 // index data
1229 auto on_cells(std::vector<int> const &) -> void override {}
1230 auto on_cell_types(std::vector<vtk::cell_type> const &) -> void override {}
1231 auto on_vertices(std::vector<int> const &) -> void override {}
1232 auto on_lines(std::vector<int> const &) -> void override {}
1233 auto on_polygons(std::vector<int> const &) -> void override {}
1234 auto on_triangle_strips(std::vector<int> const &) -> void override {}
1235
1236 // cell- / pointdata
1237 auto on_vectors(std::string const & /*name*/,
1238 std::vector<std::array<float, 3>> const & /*vectors*/,
1239 vtk::reader_data) -> void override {}
1240 auto on_vectors(std::string const & /*name*/,
1241 std::vector<std::array<double, 3>> const & /*vectors*/,
1242 vtk::reader_data) -> void override {}
1243 auto on_normals(std::string const & /*name*/,
1244 std::vector<std::array<float, 3>> const & /*normals*/,
1245 vtk::reader_data) -> void override {}
1246 auto on_normals(std::string const & /*name*/,
1247 std::vector<std::array<double, 3>> const & /*normals*/,
1248 vtk::reader_data) -> void override {}
1250 std::string const & /*name*/,
1251 std::vector<std::array<float, 2>> const & /*texture_coordinates*/,
1252 vtk::reader_data) -> void override {}
1254 std::string const & /*name*/,
1255 std::vector<std::array<double, 2>> const & /*texture_coordinates*/,
1256 vtk::reader_data) -> void override {}
1257 auto on_tensors(std::string const & /*name*/,
1258 std::vector<std::array<float, 9>> const & /*tensors*/,
1259 vtk::reader_data) -> void override {}
1260 auto on_tensors(std::string const & /*name*/,
1261 std::vector<std::array<double, 9>> const & /*tensors*/,
1262 vtk::reader_data) -> void override {}
1263
1264 template <typename T>
1265 auto insert_prop(std::string const &prop_name, std::vector<T> const &data,
1266 std::size_t const num_components) {
1267 std::size_t i = 0;
1268 if (num_components == 1) {
1269 auto &prop = gr.insert_vertex_property<T>(prop_name);
1270 gr.vertices().iterate_indices(
1271 [&](auto const... is) { prop(is...) = data[i++]; });
1272 }
1273 if (num_components == 2) {
1274 auto &prop = gr.insert_vertex_property<vec<T, 2>>(prop_name);
1275 gr.vertices().iterate_indices([&](auto const... is) {
1276 prop(is...) = {data[i], data[i + 1]};
1277 i += num_components;
1278 });
1279 }
1280 if (num_components == 3) {
1281 auto &prop = gr.insert_vertex_property<vec<T, 3>>(prop_name);
1282 gr.vertices().iterate_indices([&](auto const... is) {
1283 prop(is...) = {data[i], data[i + 1], data[i + 2]};
1284 i += num_components;
1285 });
1286 }
1287 if (num_components == 4) {
1288 auto &prop = gr.insert_vertex_property<vec<T, 4>>(prop_name);
1289 gr.vertices().iterate_indices([&](auto const... is) {
1290 prop(is...) = {data[i], data[i + 1], data[i + 2], data[i + 3]};
1291 i += num_components;
1292 });
1293 }
1294 }
1295 auto on_scalars(std::string const &data_name,
1296 std::string const & /*lookup_table_name*/,
1297 std::size_t const num_components,
1298 std::vector<float> const &data, vtk::reader_data)
1299 -> void override {
1300 insert_prop<float>(data_name, data, num_components);
1301 }
1302 auto on_scalars(std::string const &data_name,
1303 std::string const & /*lookup_table_name*/,
1304 std::size_t const num_components,
1305 std::vector<double> const &data, vtk::reader_data)
1306 -> void override {
1307 insert_prop<double>(data_name, data, num_components);
1308 }
1309 auto on_point_data(std::size_t) -> void override {}
1310 auto on_cell_data(std::size_t) -> void override {}
1311 auto on_field_array(std::string const /*field_name*/,
1312 std::string const field_array_name,
1313 std::vector<int> const &data,
1314 std::size_t num_components, std::size_t /*num_tuples*/)
1315 -> void override {
1316 insert_prop<int>(field_array_name, data, num_components);
1317 }
1318 auto on_field_array(std::string const /*field_name*/,
1319 std::string const field_array_name,
1320 std::vector<float> const &data,
1321 std::size_t num_components, std::size_t /*num_tuples*/)
1322 -> void override {
1323 insert_prop<float>(field_array_name, data, num_components);
1324 }
1325 auto on_field_array(std::string const /*field_name*/,
1326 std::string const field_array_name,
1327 std::vector<double> const &data,
1328 std::size_t num_components, std::size_t /*num_tuples*/)
1329 -> void override {
1330 insert_prop<double>(field_array_name, data, num_components);
1331 }
1332 };
1333 //============================================================================
1334 auto read_vtk(filesystem::path const &path)
1335 requires(num_dimensions() == 2) || (num_dimensions() == 3)
1336 {
1337 bool is_structured_points = false;
1338 vec3 spacing;
1339 vtk_listener listener{*this, is_structured_points, spacing};
1340 vtk::legacy_file f{path};
1341 f.add_listener(listener);
1342 f.read();
1343
1344 if (is_structured_points) {
1345 if constexpr (is_same<std::decay_t<decltype(dimension<0>())>,
1347 dimension<0>().back() =
1348 dimension<0>().front() + (size<0>() - 1) * spacing(0);
1349 } else {
1350 std::size_t i = 0;
1351 for (auto &d : dimension<0>()) {
1352 d = dimension<0>().front() + (i++) * spacing(0);
1353 }
1354 }
1355 if constexpr (is_same<std::decay_t<decltype(dimension<1>())>,
1357 dimension<1>().back() =
1358 dimension<1>().front() + (size<1>() - 1) * spacing(1);
1359 } else {
1360 std::size_t i = 0;
1361 for (auto &d : dimension<1>()) {
1362 d = dimension<1>().front() + (i++) * spacing(1);
1363 }
1364 }
1365 if constexpr (num_dimensions() == 3) {
1366 if constexpr (is_same<std::decay_t<decltype(dimension<2>())>,
1368 dimension<2>().back() =
1369 dimension<2>().front() + (size<2>() - 1) * spacing(2);
1370 } else {
1371 std::size_t i = 0;
1372 for (auto &d : dimension<2>()) {
1373 d = dimension<2>().front() + (i++) * spacing(2);
1374 }
1375 }
1376 }
1377 }
1378 }
1379 //----------------------------------------------------------------------------
1380 auto read_amira(filesystem::path const &path)
1381 requires is_uniform && ((num_dimensions() == 2) || (num_dimensions() == 3))
1382 {
1383 auto const reader_data = amira::read<real_type>(path);
1384 auto const &[data, dims, aabb, num_components] = reader_data;
1385 if (dims[2] == 1 && num_dimensions() == 3) {
1386 throw std::runtime_error{
1387 "[rectilinear_grid::read_amira] file contains 2-dimensional data. "
1388 "Cannot read into 3-dimensional rectilinear_grid"};
1389 }
1390 if (dims[2] > 1 && num_dimensions() == 2) {
1391 throw std::runtime_error{
1392 "[rectilinear_grid::read_amira] file contains 3-dimensional data. "
1393 "Cannot read into 2-dimensional rectilinear_grid"};
1394 }
1395
1396 // set dimensions
1397 if constexpr (is_linspace<std::decay_t<decltype(dimension<0>())>>) {
1398 dimension<0>().front() = aabb.min(0);
1399 dimension<0>().back() = aabb.max(0);
1400 dimension<0>().resize(dims[0]);
1401 } else {
1402 auto const uniform_dim =
1403 linspace<double>{aabb.min(0), aabb.max(0), dims[0]};
1404 dimension<0>().resize(dims[0]);
1405 std::ranges::copy(uniform_dim, begin(dimension<0>()));
1406 }
1407 if constexpr (is_linspace<std::decay_t<decltype(dimension<1>())>>) {
1408 dimension<1>().front() = aabb.min(1);
1409 dimension<1>().back() = aabb.max(1);
1410 dimension<1>().resize(dims[1]);
1411 } else {
1412 auto const uniform_dim =
1413 linspace<double>{aabb.min(1), aabb.max(1), dims[1]};
1414 dimension<1>().resize(dims[1]);
1415 std::ranges::copy(uniform_dim, begin(dimension<1>()));
1416 }
1417 if constexpr (num_dimensions() == 3) {
1418 if constexpr (is_linspace<std::decay_t<decltype(dimension<2>())>>) {
1419 dimension<2>().front() = aabb.min(2);
1420 dimension<2>().back() = aabb.max(2);
1421 dimension<2>().resize(dims[2]);
1422 } else {
1423 auto const uniform_dim =
1424 linspace<double>{aabb.min(2), aabb.max(2), dims[2]};
1425 dimension<2>().resize(dims[2]);
1426 std::ranges::copy(uniform_dim, begin(dimension<2>()));
1427 }
1428 }
1429 // copy data
1430 auto i = std::size_t{};
1431 if (num_components == 1) {
1432 auto &prop = scalar_vertex_property(path.filename().string());
1433 vertices().iterate_indices([&](auto const... is) {
1434 auto const &data = std::get<0>(reader_data);
1435 prop(is...) = data[i++];
1436 });
1437 } else if (num_components == 2) {
1438 auto &prop = vertex_property<vec<real_type, 2>>(path.filename().string());
1439 vertices().iterate_indices([&](auto const... is) {
1440 auto const &[data, dims, aabb, num_components] = reader_data;
1441 prop(is...) = {data[i], data[i + 1]};
1442 i += num_components;
1443 });
1444 } else if (num_components == 3) {
1445 auto &prop = vertex_property<vec<real_type, 3>>(path.filename().string());
1446 vertices().iterate_indices([&](auto const... is) {
1447 auto const &[data, dims, aabb, num_components] = reader_data;
1448 prop(is...) = {data[i], data[i + 1], data[i + 2]};
1449 i += num_components;
1450 });
1451 }
1452 }
1453 //----------------------------------------------------------------------------
1454#ifdef TATOOINE_NETCDF_AVAILABLE
1455 auto read_netcdf(filesystem::path const &path)
1456 requires(!is_uniform)
1457 {
1458 read_netcdf(path, std::make_index_sequence<num_dimensions()>{});
1459 }
1460 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1461 template <typename T, std::size_t... Seq>
1462 auto insert_variables_of_type(netcdf::file &f, bool &first,
1463 std::index_sequence<Seq...> /*seq*/)
1464 requires(!is_uniform)
1465 {
1466 for (auto v : f.variables<T>()) {
1467 if (v.name() == "x" || v.name() == "y" || v.name() == "z" ||
1468 v.name() == "t" || v.name() == "X" || v.name() == "Y" ||
1469 v.name() == "Z" || v.name() == "T" || v.name() == "xdim" ||
1470 v.name() == "ydim" || v.name() == "zdim" || v.name() == "tdim" ||
1471 v.name() == "Xdim" || v.name() == "Ydim" || v.name() == "Zdim" ||
1472 v.name() == "Tdim" || v.name() == "XDim" || v.name() == "YDim" ||
1473 v.name() == "ZDim" || v.name() == "TDim") {
1474 continue;
1475 }
1476 if (v.num_dimensions() != num_dimensions() &&
1477 v.size()[0] != vertices().size()) {
1478 throw std::runtime_error{
1479 "[rectilinear_grid::read_netcdf] variable's number of dimensions "
1480 "does "
1481 "not "
1482 "match rectilinear_grid's number of dimensions:\nnumber of "
1483 "rectilinear_grid "
1484 "dimensions: " +
1485 std::to_string(num_dimensions()) + "\nnumber of data dimensions: " +
1486 std::to_string(v.num_dimensions()) +
1487 "\nvariable name: " + v.name()};
1488 }
1489 if (!first) {
1490 auto check = [this, &v](std::size_t i) {
1491 if (v.size(i) != size(i)) {
1492 throw std::runtime_error{
1493 "[rectilinear_grid::read_netcdf] variable's size(" +
1494 std::to_string(i) +
1495 ") does not "
1496 "match rectilinear_grid's size(" +
1497 std::to_string(i) + ")"};
1498 }
1499 };
1500 (check(Seq), ...);
1501 } else {
1502 ((f.variable<
1503 typename std::decay_t<decltype(dimension<Seq>())>::value_type>(
1504 v.dimension_name(Seq))
1505 .read(dimension<Seq>())),
1506 ...);
1507 first = false;
1508 }
1509 create_vertex_property<lazy_reader<netcdf::variable<T>>>(
1510 v.name(), v,
1511 std::vector<std::size_t>(num_dimensions(),
1512 m_chunk_size_for_lazy_properties));
1513 }
1514 }
1516 template <std::size_t... Seq>
1517 auto read_netcdf(filesystem::path const &path,
1518 std::index_sequence<Seq...> seq)
1519 requires(!is_uniform)
1520 {
1521 netcdf::file f{path, netCDF::NcFile::read};
1522 bool first = true;
1523 insert_variables_of_type<double>(f, first, seq);
1524 insert_variables_of_type<float>(f, first, seq);
1525 insert_variables_of_type<int>(f, first, seq);
1526 }
1527#endif
1528 //----------------------------------------------------------------------------
1529 template <typename T>
1530 void write_amira(std::string const &path,
1531 std::string const &vertex_property_name) const
1532 requires(num_dimensions() == 3)
1533 {
1534 write_amira(path, vertex_property<T>(vertex_property_name));
1535 }
1536 //----------------------------------------------------------------------------
1537 template <typename T, bool HasNonConstReference>
1538 void write_amira(
1539 std::string const &path,
1540 typed_vertex_property_interface_type<T, HasNonConstReference> const &prop)
1541 const
1542 requires is_uniform && (num_dimensions() == 3)
1543 {
1544 std::ofstream outfile{path, std::ofstream::binary};
1545 std::stringstream header;
1546
1547 header << "# AmiraMesh BINARY-LITTLE-ENDIAN 2.1\n\n";
1548 header << "define Lattice " << size<0>() << " " << size<1>() << " "
1549 << size<2>() << "\n\n";
1550 header << "Parameters {\n";
1551 header << " BoundingBox " << dimension<0>().front() << " "
1552 << dimension<0>().back() << " " << dimension<1>().front() << " "
1553 << dimension<1>().back() << " " << dimension<2>().front() << " "
1554 << dimension<2>().back() << ",\n";
1555 header << " CoordType \"uniform\"\n";
1556 header << "}\n";
1557 if constexpr (tensor_num_components < T >> 1) {
1558 header << "Lattice { " << type_name<internal_data_type_t<T>>() << "["
1559 << tensor_num_components<T> << "] Data } @1\n\n";
1560 } else {
1561 header << "Lattice { " << type_name<internal_data_type_t<T>>()
1562 << " Data } @1\n\n";
1563 }
1564 header << "# Data section follows\n@1\n";
1565 auto const header_string = header.str();
1566
1567 std::vector<T> data;
1568 data.reserve(size<0>() * size<1>() * size<2>());
1569 auto back_inserter = [&](auto const... is) { data.push_back(prop(is...)); };
1570 for_loop(back_inserter, size<0>(), size<1>(), size<2>());
1571 outfile.write(
1572 (char *)header_string.c_str(),
1573 static_cast<std::streamsize>(header_string.size() * sizeof(char)));
1574 outfile.write((char *)data.data(),
1575 static_cast<std::streamsize>(data.size() * sizeof(T)));
1576 }
1577 //----------------------------------------------------------------------------
1578
1579public:
1580 auto write(filesystem::path const &path) const {
1581 auto const ext = path.extension();
1582
1583 if constexpr (num_dimensions() == 2 || num_dimensions() == 3) {
1584 if (ext == ".vtk") {
1585 write_vtk(path);
1586 return;
1587 }
1588 }
1589 if constexpr (num_dimensions() == 2 || num_dimensions() == 3) {
1590 if (ext == ".vtr") {
1591 write_vtr(path);
1592 return;
1593 }
1594 }
1595#if TATOOINE_HDF5_AVAILABLE
1596 if constexpr (num_dimensions() == 2 || num_dimensions() == 3) {
1597 if (ext == ".h5") {
1598 write_visitvs(path);
1599 return;
1600 }
1601 }
1602#endif
1603 throw std::runtime_error{"Unsupported file extension: \"" + ext.string() +
1604 "\"."};
1605 }
1606 //----------------------------------------------------------------------------
1607 auto
1608 write_vtk(filesystem::path const &path,
1609 std::string const &description = "tatooine rectilinear_grid") const
1610 requires is_uniform && ((num_dimensions() == 2) || (num_dimensions() == 3))
1611 {
1612 auto writer =
1613 vtk::legacy_file_writer{path, vtk::dataset_type::structured_points};
1614 writer.set_title(description);
1615 writer.write_header();
1616 if constexpr (num_dimensions() == 1) {
1617 writer.write_dimensions(size<0>(), 1, 1);
1618 writer.write_origin(dimension<0>().front(), 0, 0);
1619 writer.write_spacing(dimension<0>().spacing(), 0, 0);
1620 } else if constexpr (num_dimensions() == 2) {
1621 writer.write_dimensions(size<0>(), size<1>(), 1);
1622 writer.write_origin(dimension<0>().front(), dimension<1>().front(), 0);
1623 writer.write_spacing(dimension<0>().spacing(), dimension<1>().spacing(),
1624 0);
1625 } else if constexpr (num_dimensions() == 3) {
1626 writer.write_dimensions(size<0>(), size<1>(), size<2>());
1627 writer.write_origin(dimension<0>().front(), dimension<1>().front(),
1628 dimension<2>().front());
1629 writer.write_spacing(dimension<0>().spacing(), dimension<1>().spacing(),
1630 dimension<2>().spacing());
1631 }
1632 // write vertex data
1633 writer.write_point_data(vertices().size());
1634 write_vtk_prop<int, float, double, vec2f, vec3f, vec4f, vec2d, vec3d,
1635 vec4d>(writer);
1636 }
1637 //----------------------------------------------------------------------------
1638 auto
1639 write_vtk(filesystem::path const &path,
1640 std::string const &description = "tatooine rectilinear_grid") const
1641 requires(!is_uniform) && ((num_dimensions() == 2) || (num_dimensions() == 3))
1642 {
1643 auto writer =
1644 vtk::legacy_file_writer{path, vtk::dataset_type::rectilinear_grid};
1645 writer.set_title(description);
1646 writer.write_header();
1647 if constexpr (num_dimensions() == 1) {
1648 writer.write_dimensions(size<0>(), 1, 1);
1649 writer.write_x_coordinates(
1650 std::vector<double>(begin(dimension<0>()), end(dimension<0>())));
1651 writer.write_y_coordinates(std::vector<double>{0});
1652 writer.write_z_coordinates(std::vector<double>{0});
1653 } else if constexpr (num_dimensions() == 2) {
1654 writer.write_dimensions(size<0>(), size<1>(), 1);
1655 writer.write_x_coordinates(
1656 std::vector<double>(begin(dimension<0>()), end(dimension<0>())));
1657 writer.write_y_coordinates(
1658 std::vector<double>(begin(dimension<1>()), end(dimension<1>())));
1659 writer.write_z_coordinates(std::vector<double>{0});
1660 } else if constexpr (num_dimensions() == 3) {
1661 writer.write_dimensions(size<0>(), size<1>(), size<2>());
1662 writer.write_x_coordinates(
1663 std::vector<double>(begin(dimension<0>()), end(dimension<0>())));
1664 writer.write_y_coordinates(
1665 std::vector<double>(begin(dimension<1>()), end(dimension<1>())));
1666 writer.write_z_coordinates(
1667 std::vector<double>(begin(dimension<2>()), end(dimension<2>())));
1668 }
1669 // write vertex data
1670 writer.write_point_data(vertices().size());
1671 write_vtk_prop<int, float, double, vec2f, vec3f, vec4f, vec2d, vec3d,
1672 vec4d>(writer);
1673 }
1674 //----------------------------------------------------------------------------
1675private:
1676 template <typename T, bool HasNonConstReference>
1677 auto write_vtk_prop(
1678 vtk::legacy_file_writer &writer, std::string const &name,
1679 typed_vertex_property_interface_type<T, HasNonConstReference> const &prop)
1680 const -> void {
1681 auto data = std::vector<T>{};
1682 vertices().iterate_indices(
1683 [&](auto const... is) { data.push_back(prop(is...)); });
1684 writer.write_scalars(name, data);
1685 }
1686 //----------------------------------------------------------------------------
1687 template <typename... Ts>
1688 auto write_vtk_prop(vtk::legacy_file_writer &writer) const -> void {
1689 for (auto const &key_value : this->m_vertex_properties) {
1690 invoke([&] {
1691 auto const &[name, prop] = key_value;
1692 if (prop->type() == typeid(Ts)) {
1693 write_vtk_prop(writer, name, prop->template cast_to_typed<Ts>());
1694 }
1695 }...);
1696 }
1697 }
1698
1699public:
1700 template <typename HeaderType = std::uint64_t>
1701 auto write_vtr(filesystem::path const &path) const
1702 requires(num_dimensions() == 2) || (num_dimensions() == 3)
1703 {
1704 detail::rectilinear_grid::vtr_writer<this_type, HeaderType>{*this}.write(
1705 path);
1706 }
1707
1708public:
1709 auto write_visitvs(filesystem::path const &path) const -> void {
1710 write_visitvs(path, std::make_index_sequence<num_dimensions()>{});
1711 }
1712
1713private:
1714 //----------------------------------------------------------------------------
1715#if TATOOINE_HDF5_AVAILABLE
1716private:
1717 template <typename T, bool HasNonConstReference, std::size_t... Is>
1718 void write_prop_hdf5(
1719 hdf5::file &f, std::string const &name,
1720 typed_vertex_property_interface_type<T, HasNonConstReference> const &prop,
1721 std::index_sequence<Is...> /*seq*/) const {
1722 if constexpr (is_arithmetic<T>) {
1723 auto dataset = f.create_dataset<T>(name, size<Is>()...);
1724 dataset.attribute("vsMesh") = "/rectilinear_grid";
1725 dataset.attribute("vsCentering") = "nodal";
1726 dataset.attribute("vsType") = "variable";
1727 dataset.attribute("vsIndexOrder") = "compMinorF";
1728 auto data = std::vector<T>{};
1729 data.reserve(vertices().size());
1730 vertices().iterate_indices(
1731 [&](auto const... is) { data.push_back(prop(is...)); });
1732 dataset.write(H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
1733 } else if constexpr (static_vec<T>) {
1734 using vec_type = T;
1735 auto g = f.group(name);
1736 auto gg = g.sub_group(name);
1737 std::stringstream ss;
1738 ss << "{";
1739 ss << "<" + name + "/" << name << "_0>";
1740 for (std::size_t i = 1; i < vec_type::dimension(0); ++i) {
1741 ss << ",<" + name + "/" << name << "_" << i << ">";
1742 }
1743 ss << "}";
1744 gg.attribute(name) = ss.str();
1745 gg.attribute("vsType") = "vsVars";
1746
1747 for (std::size_t i = 0; i < vec_type::dimension(0); ++i) {
1748 auto dataset = g.create_dataset<typename vec_type::value_type>(
1749 name + "_" + std::to_string(i), size<Is>()...);
1750 dataset.attribute("vsMesh") = "/rectilinear_grid";
1751 dataset.attribute("vsCentering") = "nodal";
1752 dataset.attribute("vsType") = "variable";
1753 dataset.attribute("vsIndexOrder") = "compMinorF";
1754 auto data = std::vector<typename vec_type::value_type>{};
1755 data.reserve(vertices().size());
1756 vertices().iterate_indices(
1757 [&](auto const... is) { data.push_back(prop(is...)(i)); });
1758 dataset.write(H5S_ALL, H5S_ALL, H5P_DEFAULT, data.data());
1759 }
1760 }
1761 }
1762 //----------------------------------------------------------------------------
1763 template <typename... Ts, std::size_t... Is>
1764 auto write_prop_hdf5_wrapper(hdf5::file &f, std::string const &name,
1765 vertex_property_type const &prop,
1766 std::index_sequence<Is...> seq) const -> void {
1767 invoke([&] {
1768 if (prop.type() == typeid(Ts)) {
1769 write_prop_hdf5(
1770 f, name,
1771 *dynamic_cast<
1772 typed_vertex_property_interface_type<Ts, true> const *>(&prop),
1773 seq);
1774 return;
1775 }
1776 }...);
1777 }
1778 //----------------------------------------------------------------------------
1779public:
1780 template <std::size_t... Is>
1781 auto write_visitvs(filesystem::path const &path,
1782 std::index_sequence<Is...> seq) const -> void {
1783 if (filesystem::exists(path)) {
1784 filesystem::remove(path);
1785 }
1786 auto f = hdf5::file{path};
1787 auto group = f.group("rectilinear_grid");
1788
1789 auto axis_labels_stream = std::stringstream{};
1790 axis_labels_stream << cartesian_axis_label(0);
1791 for (std::size_t i = 1; i < num_dimensions(); ++i) {
1792 axis_labels_stream << ", " << cartesian_axis_label(i);
1793 }
1794
1795 group.attribute("vsAxisLabels") = axis_labels_stream.str();
1796 group.attribute("vsKind") = "rectilinear";
1797 group.attribute("vsType") = "mesh";
1798 group.attribute("vsIndexOrder") = "compMinorF";
1799
1800 m_dimensions.iterate([&, i = std::size_t{}](auto const &dim) mutable {
1801 using dim_type = typename std::decay_t<decltype(dim)>::value_type;
1802 group.attribute("vsAxis" + std::to_string(i)) =
1803 "axis" + std::to_string(i);
1804 auto dim_as_vec = std::vector<dim_type>{};
1805 dim_as_vec.reserve(dim.size());
1806 std::ranges::copy(dim, std::back_inserter(dim_as_vec));
1807
1808 auto dim_dataset = f.create_dataset<dim_type>(
1809 "rectilinear_grid/axis" + std::to_string(i), dim.size());
1810 dim_dataset.write(dim_as_vec);
1811 ++i;
1812 });
1813
1814 for (const auto &[name, prop] : this->m_vertex_properties) {
1815 write_prop_hdf5_wrapper<std::uint16_t, std::uint32_t, std::int16_t,
1816 std::int32_t, float, double, vec2f, vec2d, vec2f,
1817 vec2d, vec4f, vec4d, vec5f, vec5d>(f, name, *prop,
1818 seq);
1819 }
1820 }
1821#endif
1822
1823private:
1824 template <std::size_t I> auto print_dim(std::ostream &out) const {
1825 auto const &dim = dimension<I>();
1826 if constexpr (is_linspace<std::decay_t<decltype(dim)>>) {
1827 out << dim;
1828 } else {
1829 out << dim.front() << ", " << dim[1] << ", ..., " << dim.back();
1830 }
1831 out << " [" << dim.size() << "]\n";
1832 }
1833 template <std::size_t... Seq>
1834 auto print(std::ostream &out, std::index_sequence<Seq...> /*seq*/) const
1835 -> auto & {
1836 (print_dim<Seq>(out), ...);
1837 return out;
1838 }
1839
1840public:
1841 auto print(std::ostream &out = std::cout) const -> auto & {
1842 return print(out, std::make_index_sequence<num_dimensions()>{});
1843 }
1844 //----------------------------------------------------------------------------
1845 auto chunk_size_for_lazy_properties() {
1846 return m_chunk_size_for_lazy_properties;
1847 }
1848 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1849 auto set_chunk_size_for_lazy_properties(std::size_t const val) -> void {
1850 m_chunk_size_for_lazy_properties = val;
1851 }
1852};
1853//==============================================================================
1854// free functions
1855//==============================================================================
1856template <typename... Dimensions>
1857auto operator<<(std::ostream &out, rectilinear_grid<Dimensions...> const &g)
1858 -> auto & {
1859 return g.print(out);
1860}
1861template <floating_point_range... Dimensions>
1863 return g.vertices();
1864}
1865//==============================================================================
1866// deduction guides
1867//==============================================================================
1868template <floating_point_range... Dimensions>
1869rectilinear_grid(Dimensions &&...)
1871// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1872template <typename Real, std::size_t N>
1874 integral auto const... res)
1876 linspace<std::conditional_t<true, Real, decltype(res)>>...>;
1877// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1878template <integral... Ints>
1880 linspace<std::conditional_t<true, double, decltype(res)>>...>;
1881//==============================================================================
1882// operators
1883//==============================================================================
1884template <floating_point_range... Dimensions,
1885 floating_point_range AdditionalDimension>
1887 AdditionalDimension &&additional_dimension) {
1889 std::forward<AdditionalDimension>(additional_dimension));
1890}
1891// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1892template <floating_point_range... Dimensions,
1893 floating_point_range AdditionalDimension>
1894auto operator+(AdditionalDimension &&additional_dimension,
1897 std::forward<AdditionalDimension>(additional_dimension));
1898}
1899//==============================================================================
1900// typedefs
1901//==============================================================================
1902template <floating_point Real, std::size_t N>
1905template <std::size_t N>
1911template <floating_point Real>
1913template <floating_point Real>
1915template <floating_point Real>
1917template <floating_point Real>
1919//------------------------------------------------------------------------------
1920template <arithmetic Real, std::size_t N>
1923template <std::size_t N>
1929//------------------------------------------------------------------------------
1930template <arithmetic Real, std::size_t... N>
1933template <std::size_t N>
1939//==============================================================================
1940} // namespace tatooine
1941//==============================================================================
1943#endif
Definition: netcdf.h:350
Definition: netcdf.h:58
Definition: rectilinear_grid.h:38
constexpr rectilinear_grid()=default
Default CTOR.
auto scalar_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:868
auto vec4_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:898
auto sample_to_vertex_property(F &&f, std::string const &name) -> auto &
Definition: rectilinear_grid.h:1080
constexpr auto copy_without_properties() const
Creates a copy of with any of the give properties.
Definition: rectilinear_grid.h:169
auto insert_hdf5_lazy_vertex_property(filesystem::path const &path, std::string const &dataset_name) -> auto &
Definition: rectilinear_grid.h:1004
auto cells() const
Definition: rectilinear_grid.h:686
auto create_vertex_property(std::string const &name, Args &&...args) -> auto &
Definition: rectilinear_grid.h:727
auto insert_lazy_vertex_property(hdf5::dataset< T > const &dataset, std::string const &name) -> auto &
Definition: rectilinear_grid.h:1021
constexpr auto dimension(std::size_t const i) const -> auto const &requires(is_same< Dimensions... >) &&(num_dimensions()<=11)
Definition: rectilinear_grid.h:202
auto insert_vec2_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:757
auto insert_netcdf_lazy_vertex_property(filesystem::path const &path, std::string const &dataset_name) -> auto &
Definition: rectilinear_grid.h:1057
constexpr auto min() const
Definition: rectilinear_grid.h:273
auto insert_mat2_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:772
constexpr rectilinear_grid(axis_aligned_bounding_box< Real, num_dimensions()> const &bb, Res const ... res)
Definition: rectilinear_grid.h:141
auto vec3_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:888
auto insert_lazy_vertex_property(netcdf::variable< T > const &dataset) -> auto &
Definition: rectilinear_grid.h:1067
static constexpr auto num_dimensions() -> std::size_t
Definition: rectilinear_grid.h:42
auto insert_contiguous_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:789
auto cell_index(arithmetic auto x) const -> std::pair< std::size_t, real_type >
Definition: rectilinear_grid.h:521
auto vertex_property(std::string const &name) const -> typed_vertex_property_interface_type< T, HasNonConstReference > const &
Definition: rectilinear_grid.h:850
constexpr auto bounding_box() const
Definition: rectilinear_grid.h:341
auto read(filesystem::path const &path)
Definition: rectilinear_grid.h:1148
constexpr auto is_inside(pos_type const &p, std::index_sequence< Seq... >) const
Checks if point p is inside of grid.
Definition: rectilinear_grid.h:490
auto mat2_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:913
auto vec2_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:883
auto insert_chunked_vertex_property(std::string const &name, std::array< std::size_t, num_dimensions()> const &chunk_size) -> auto &
Definition: rectilinear_grid.h:804
constexpr rectilinear_grid(integral auto const ... size)
Definition: rectilinear_grid.h:149
constexpr auto copy_without_properties(std::index_sequence< Ds... >) const
Definition: rectilinear_grid.h:163
auto vertices() const
Definition: rectilinear_grid.h:637
auto cell_index(arithmetic auto const ... xs) const
Definition: rectilinear_grid.h:571
constexpr auto extent(std::size_t const cell_index) const
Definition: rectilinear_grid.h:307
auto insert_lazy_vertex_property(filesystem::path const &path, std::string const &dataset_name) -> typed_vertex_property_interface_type< T, false > &
Definition: rectilinear_grid.h:939
auto sample_to_vertex_property(F &&f, std::string const &name, execution_policy_tag auto tag) -> auto &
Definition: rectilinear_grid.h:1089
auto add_dimension(floating_point_range auto &&additional_dimension, std::index_sequence< Is... >) const
Definition: rectilinear_grid.h:690
constexpr auto size(std::index_sequence< Seq... >) const
Definition: rectilinear_grid.h:347
auto insert_chunked_vertex_property(std::string const &name, std::vector< std::size_t > const &chunk_size) -> auto &
Definition: rectilinear_grid.h:796
constexpr auto pop_front()
Removes first discrete point in dimension I.
Definition: rectilinear_grid.h:462
auto mat2_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:908
auto vertex_at(std::index_sequence< DIs... >, std::array< Int, num_dimensions()> const &is) const -> vec< real_type, num_dimensions()>
Definition: rectilinear_grid.h:640
auto insert_vec4_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:767
auto vec4_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:903
auto insert_vertex_property(hdf5::dataset< T > const &dataset, std::string const &name) -> auto &
Definition: rectilinear_grid.h:969
auto insert_lazy_vertex_property(hdf5::dataset< T > const &dataset) -> auto &
Definition: rectilinear_grid.h:1014
constexpr auto size() const
Definition: rectilinear_grid.h:357
constexpr auto center(std::index_sequence< Is... >) const
Definition: rectilinear_grid.h:318
constexpr auto extent(std::index_sequence< Is... >) const
Definition: rectilinear_grid.h:294
constexpr auto dimensions() const -> auto const &
Definition: rectilinear_grid.h:262
constexpr auto pop_back()
Removes last discrete point in dimension I.
Definition: rectilinear_grid.h:453
auto scalar_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:873
constexpr auto min(std::index_sequence< Seq... >) const
Definition: rectilinear_grid.h:266
auto vertex_at(vertex_handle const &h) const
Definition: rectilinear_grid.h:664
auto has_vertex_property(std::string const &name)
Definition: rectilinear_grid.h:705
std::map< std::string, property_ptr_type > property_container_type
Definition: rectilinear_grid.h:79
constexpr auto plain_index(integral auto const ... is)
Definition: rectilinear_grid.h:672
auto insert_mat3_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:777
common_type< typename Dimensions::value_type... > real_type
Definition: rectilinear_grid.h:46
auto insert_vec3_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:762
auto finite_differences_coefficients(std::size_t const stencil_size, std::size_t const dim_index, std::size_t const i) const
Definition: rectilinear_grid.h:583
auto resize_vertex_properties()
Definition: rectilinear_grid.h:422
constexpr auto push_back()
Inserts new discrete point in dimension I with extent of last cell.
Definition: rectilinear_grid.h:439
constexpr rectilinear_grid(rectilinear_grid const &other)
Copy CTOR.
Definition: rectilinear_grid.h:98
variadic::ith_type< I, Dimensions... > dimension_type
Definition: rectilinear_grid.h:52
auto cell_index(std::index_sequence< DimensionIndex... >, arithmetic auto const ... xs) const -> std::array< std::pair< std::size_t, double >, num_dimensions()>
returns cell indices and factors for each dimension for interpolaton
Definition: rectilinear_grid.h:564
constexpr auto extent() const
Definition: rectilinear_grid.h:287
auto vertex_properties() const -> auto const &
Definition: rectilinear_grid.h:743
auto vec2_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:878
constexpr auto is_inside(std::array< real_type, num_dimensions()> const &p) const
Checks if point p is inside of grid.
Definition: rectilinear_grid.h:514
constexpr auto dimension() const -> auto const &
Definition: rectilinear_grid.h:194
auto insert_vertex_property(hdf5::dataset< T > const &dataset) -> auto &
Definition: rectilinear_grid.h:964
constexpr auto operator=(rectilinear_grid &&other) noexcept -> rectilinear_grid &
Definition: rectilinear_grid.h:176
constexpr auto extent() const
Definition: rectilinear_grid.h:300
auto rename_vertex_property(std::string const &current_name, std::string const &new_name) -> void
Definition: rectilinear_grid.h:716
constexpr auto size(std::size_t const i) const
Definition: rectilinear_grid.h:364
auto remove_vertex_property(std::string const &name) -> void
Definition: rectilinear_grid.h:709
rectilinear_grid(filesystem::path const &path)
Constructs a rectilinear grid by reading a file.
Definition: rectilinear_grid.h:156
constexpr auto max(std::index_sequence< Seq... >) const
Definition: rectilinear_grid.h:277
constexpr rectilinear_grid(axis_aligned_bounding_box< Real, num_dimensions()> const &bb, std::index_sequence< Seq... >, Res const ... res)
Definition: rectilinear_grid.h:128
auto read_vtk(filesystem::path const &path)
Definition: rectilinear_grid.h:1334
constexpr auto operator=(rectilinear_grid const &other) -> rectilinear_grid &=default
auto insert_chunked_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:824
auto mat3_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:918
std::make_index_sequence< num_dimensions()> sequence_type
Definition: rectilinear_grid.h:49
auto create_finite_differences_coefficients(std::size_t const stencil_size) const
Computes finite difference coefficients for given stencil size.
Definition: rectilinear_grid.h:604
constexpr auto max() const
Definition: rectilinear_grid.h:284
constexpr auto size() const
Definition: rectilinear_grid.h:353
auto insert_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:747
auto vec3_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:893
auto vertex_at(std::array< Int, num_dimensions()> const &is) const
Definition: rectilinear_grid.h:660
std::unique_ptr< vertex_property_type > property_ptr_type
Definition: rectilinear_grid.h:78
constexpr rectilinear_grid(Dimensions_ &&...dimensions)
Definition: rectilinear_grid.h:122
constexpr auto bounding_box(std::index_sequence< Seq... >) const
Definition: rectilinear_grid.h:331
auto mat4_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:933
auto vertex_at(integral auto const ... is) const
Definition: rectilinear_grid.h:654
auto add_dimension(floating_point_range auto &&additional_dimension) const
Definition: rectilinear_grid.h:699
auto mat4_vertex_property(std::string const &name) const -> auto const &
Definition: rectilinear_grid.h:928
constexpr auto center() const
Definition: rectilinear_grid.h:323
auto insert_mat4_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:782
constexpr auto is_inside(std::array< real_type, num_dimensions()> const &p, std::index_sequence< Seq... >) const
Checks if point p is inside of grid.
Definition: rectilinear_grid.h:506
dimensions_type m_dimensions
Definition: rectilinear_grid.h:83
auto mat3_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:923
constexpr auto set_dimension(convertible_to< dimension_type< I > > auto &&dim)
Definition: rectilinear_grid.h:432
property_container_type m_vertex_properties
Definition: rectilinear_grid.h:84
auto sample_to_vertex_property_indices(F &&f, std::string const &name, execution_policy_tag auto tag, std::index_sequence< Is... >) -> auto &
Definition: rectilinear_grid.h:1103
auto operator[](vertex_handle const &h) const
Definition: rectilinear_grid.h:668
constexpr auto center() const
Definition: rectilinear_grid.h:312
auto insert_chunked_vertex_property(std::string const &name, integral auto const ... chunk_size) -> auto &requires(sizeof...(chunk_size)==num_dimensions())
Definition: rectilinear_grid.h:813
auto insert_scalar_vertex_property(std::string const &name) -> auto &
Definition: rectilinear_grid.h:752
constexpr auto is_inside(pos_type const &p) const
Checks if point p is inside of grid.
Definition: rectilinear_grid.h:499
auto vertex_properties() -> auto &
Definition: rectilinear_grid.h:744
auto vertex_property(std::string const &name) -> typed_vertex_property_interface_type< T, HasNonConstReference > &
Definition: rectilinear_grid.h:831
auto vertex_at(std::index_sequence< DIs... >, integral auto const ... is) const -> vec< real_type, num_dimensions()>
Definition: rectilinear_grid.h:647
std::vector< real_type > finite_difference_coefficents_list_type
Definition: rectilinear_grid.h:86
auto cell_index(fixed_size_vec< num_dimensions()> auto &&xs) const
Definition: rectilinear_grid.h:577
constexpr rectilinear_grid(rectilinear_grid &&other) noexcept
Move CTOR.
Definition: rectilinear_grid.h:110
std::invoke_result_t< F, decltype(((void) std::declval< Dimensions >(), std::declval< std::size_t >()))... > invoke_result_with_indices
Definition: rectilinear_grid.h:76
auto sample_to_vertex_property_pos(F &&f, std::string const &name, execution_policy_tag auto tag) -> auto &
Definition: rectilinear_grid.h:1126
Definition: vtk_legacy.h:184
auto add_listener(legacy_file_listener &listener) -> void
Definition: concepts.h:33
Definition: concepts.h:39
Definition: tags.h:72
Definition: tensor_concepts.h:33
Definition: concepts.h:94
Definition: concepts.h:21
Definition: invocable_with_n_types.h:37
Definition: concepts.h:121
auto finite_differences_coefficients(std::size_t const derivative_order, floating_point auto const ... xs)
See What is this? for an explanation.
Definition: finite_differences_coefficients.h:13
auto read(std::ifstream &file)
Definition: read.h:104
typename detail::rectilinear_grid::creator< IndexableSpace, N >::type creator_t
Definition: creator.h:37
static constexpr sequential_t sequential
Definition: tags.h:63
constexpr auto name()
Definition: reflection.h:61
typename ith_type_impl< I, Types... >::type ith_type
Definition: ith_type.h:15
reader_data
Definition: vtk_legacy.h:42
dataset_type
Definition: vtk_legacy.h:44
Definition: algorithm.h:6
auto operator<<(std::ostream &out, linspace< Real > const &l) -> auto &
Definition: linspace.h:165
constexpr auto distance(Iter const &it0, Iter const &it1)
Definition: iterator_facade.h:372
typename common_type_impl< Ts... >::type common_type
Definition: common_type.h:23
VecF< 3 > vec3f
Definition: vec_typedefs.h:40
auto write_vtk(Lines const &lines, filesystem::path const &path, std::string const &title="tatooine lines") -> void
Definition: write.h:163
NonuniformRectilinearGrid< 3 > static_nonuniform_rectilinear_grid3
Definition: rectilinear_grid.h:1936
auto begin(Range &&range)
Definition: iterator_facade.h:318
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
auto end(Range &&range)
Definition: iterator_facade.h:322
auto write(Lines const &lines, filesystem::path const &path) -> void
Definition: write.h:218
UniformRectilinearGrid< 4 > uniform_rectilinear_grid4
Definition: rectilinear_grid.h:1909
std::invoke_result_t< F, Args... > invoke_result
Definition: concepts.h:127
VecD< 3 > vec3d
Definition: vec_typedefs.h:51
uniform_rectilinear_grid< Real, 5 > UniformRectilinearGrid5
Definition: rectilinear_grid.h:1918
auto type_name() -> std::string
returns demangled typename
Definition: demangling.h:21
auto vertices(pointset< Real, NumDimensions > const &ps)
Definition: vertex_container.h:278
uniform_rectilinear_grid< Real, 2 > UniformRectilinearGrid2
Definition: rectilinear_grid.h:1912
axis_aligned_bounding_box< Real, NumDimensions > aabb
Definition: axis_aligned_bounding_box.h:553
nonuniform_rectilinear_grid< real_number, N > NonuniformRectilinearGrid
Definition: rectilinear_grid.h:1924
uniform_rectilinear_grid< Real, 4 > UniformRectilinearGrid4
Definition: rectilinear_grid.h:1916
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
detail::rectilinear_grid::creator_t< std::vector< Real >, N > nonuniform_rectilinear_grid
Definition: rectilinear_grid.h:1922
static constexpr auto is_linspace
Definition: linspace.h:160
UniformRectilinearGrid< 2 > uniform_rectilinear_grid2
Definition: rectilinear_grid.h:1907
UniformRectilinearGrid< 3 > uniform_rectilinear_grid3
Definition: rectilinear_grid.h:1908
VecD< 2 > vec2d
Definition: vec_typedefs.h:50
VecF< 4 > vec4f
Definition: vec_typedefs.h:41
detail::rectilinear_grid::creator_t< linspace< Real >, N > uniform_rectilinear_grid
Definition: rectilinear_grid.h:1904
uniform_rectilinear_grid< real_number, N > UniformRectilinearGrid
Definition: rectilinear_grid.h:1906
static constexpr auto is_same
Definition: type_traits.h:42
NonuniformRectilinearGrid< 2 > nonuniform_rectilinear_grid2
Definition: rectilinear_grid.h:1925
VecD< 4 > vec4d
Definition: vec_typedefs.h:52
auto size(vec< ValueType, N > const &v)
Definition: vec.h:148
auto next(Iter iter)
Definition: iterator_facade.h:325
auto nan(const char *arg="")
Definition: nan.h:26
NonuniformRectilinearGrid< 3 > nonuniform_rectilinear_grid3
Definition: rectilinear_grid.h:1926
static auto constexpr cartesian_axis_label()
Definition: cartesian_axis_labels.h:27
NonuniformRectilinearGrid< 5 > static_nonuniform_rectilinear_grid5
Definition: rectilinear_grid.h:1938
VecF< 5 > vec5f
Definition: vec_typedefs.h:42
NonuniformRectilinearGrid< 5 > nonuniform_rectilinear_grid5
Definition: rectilinear_grid.h:1928
auto back(linspace< Real > const &l)
Definition: linspace.h:136
auto front(linspace< Real > const &l)
Definition: linspace.h:126
constexpr decltype(auto) invoke_unpacked(F &&f)
All arguments are bound -> just call f.
Definition: invoke_unpacked.h:15
constexpr auto for_loop(Iteration &&iteration, execution_policy::sequential_t, Ranges(&&... ranges)[2]) -> void
Use this function for creating a sequential nested loop.
Definition: for_loop.h:336
UniformRectilinearGrid< 5 > uniform_rectilinear_grid5
Definition: rectilinear_grid.h:1910
NonuniformRectilinearGrid< 4 > nonuniform_rectilinear_grid4
Definition: rectilinear_grid.h:1927
uniform_rectilinear_grid< Real, 3 > UniformRectilinearGrid3
Definition: rectilinear_grid.h:1914
NonuniformRectilinearGrid< 2 > static_nonuniform_rectilinear_grid2
Definition: rectilinear_grid.h:1935
NonuniformRectilinearGrid< 4 > static_nonuniform_rectilinear_grid4
Definition: rectilinear_grid.h:1937
VecF< 2 > vec2f
Definition: vec_typedefs.h:39
VecD< 5 > vec5d
Definition: vec_typedefs.h:53
Definition: axis_aligned_bounding_box.h:103
auto resize(std::array< std::size_t, num_dimensions()> const &size) -> void override
Definition: vertex_property.h:458
constexpr auto indices() const -> auto const &
Definition: vertex_handle.h:31
Definition: hdf5.h:363
Definition: hdf5.h:864
Definition: lazy_reader.h:14
Definition: linspace.h:26
constexpr auto back() const
Definition: linspace.h:95
Definition: rectilinear_grid.h:1173
auto on_field_array(std::string const, std::string const field_array_name, std::vector< double > const &data, std::size_t num_components, std::size_t) -> void override
Definition: rectilinear_grid.h:1325
auto on_field_array(std::string const, std::string const field_array_name, std::vector< int > const &data, std::size_t num_components, std::size_t) -> void override
Definition: rectilinear_grid.h:1311
auto on_lines(std::vector< int > const &) -> void override
Definition: rectilinear_grid.h:1232
auto on_field_array(std::string const, std::string const field_array_name, std::vector< float > const &data, std::size_t num_components, std::size_t) -> void override
Definition: rectilinear_grid.h:1318
auto on_cell_types(std::vector< vtk::cell_type > const &) -> void override
Definition: rectilinear_grid.h:1230
auto on_vectors(std::string const &, std::vector< std::array< float, 3 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1237
auto on_z_coordinates(std::vector< float > const &) -> void override
Definition: rectilinear_grid.h:1224
auto on_y_coordinates(std::vector< double > const &) -> void override
Definition: rectilinear_grid.h:1222
auto on_polygons(std::vector< int > const &) -> void override
Definition: rectilinear_grid.h:1233
auto on_cell_data(std::size_t) -> void override
Definition: rectilinear_grid.h:1310
auto insert_prop(std::string const &prop_name, std::vector< T > const &data, std::size_t const num_components)
Definition: rectilinear_grid.h:1265
auto on_origin(double x, double y, double z) -> void override
Definition: rectilinear_grid.h:1188
auto on_x_coordinates(std::vector< double > const &) -> void override
Definition: rectilinear_grid.h:1219
bool & is_structured_points
Definition: rectilinear_grid.h:1175
auto on_triangle_strips(std::vector< int > const &) -> void override
Definition: rectilinear_grid.h:1234
auto on_point_data(std::size_t) -> void override
Definition: rectilinear_grid.h:1309
vtk_listener(this_type &gr_, bool &is_structured_points_, vec3 &spacing_)
Definition: rectilinear_grid.h:1177
auto on_texture_coordinates(std::string const &, std::vector< std::array< double, 2 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1253
vec3 & spacing
Definition: rectilinear_grid.h:1176
auto on_z_coordinates(std::vector< double > const &) -> void override
Definition: rectilinear_grid.h:1225
auto on_dimensions(std::size_t x, std::size_t y, std::size_t z) -> void override
Definition: rectilinear_grid.h:1204
auto on_dataset_type(vtk::dataset_type t) -> void override
Definition: rectilinear_grid.h:1181
auto on_y_coordinates(std::vector< float > const &) -> void override
Definition: rectilinear_grid.h:1221
auto on_scalars(std::string const &data_name, std::string const &, std::size_t const num_components, std::vector< double > const &data, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1302
auto on_x_coordinates(std::vector< float > const &) -> void override
Definition: rectilinear_grid.h:1218
auto on_cells(std::vector< int > const &) -> void override
Definition: rectilinear_grid.h:1229
auto on_texture_coordinates(std::string const &, std::vector< std::array< float, 2 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1249
auto on_normals(std::string const &, std::vector< std::array< float, 3 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1243
auto on_tensors(std::string const &, std::vector< std::array< double, 9 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1260
this_type & gr
Definition: rectilinear_grid.h:1174
auto on_spacing(double x, double y, double z) -> void override
Definition: rectilinear_grid.h:1201
auto on_tensors(std::string const &, std::vector< std::array< float, 9 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1257
auto on_scalars(std::string const &data_name, std::string const &, std::size_t const num_components, std::vector< float > const &data, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1295
auto on_normals(std::string const &, std::vector< std::array< double, 3 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1246
auto on_vertices(std::vector< int > const &) -> void override
Definition: rectilinear_grid.h:1231
auto on_vectors(std::string const &, std::vector< std::array< double, 3 > > const &, vtk::reader_data) -> void override
Definition: rectilinear_grid.h:1240
Definition: invoke_unpacked.h:11
Definition: vtk_legacy.h:92
Definition: index_order.h:17