Tatooine
vertex_property.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_RECTILINEAR_GRID_VERTEX_PROPERTY_PROPERTY_H
2#define TATOOINE_DETAIL_RECTILINEAR_GRID_VERTEX_PROPERTY_PROPERTY_H
3//==============================================================================
4#include <tatooine/concepts.h>
11#include <tatooine/write_png.h>
12//==============================================================================
14//==============================================================================
15template <typename GridVertexProperty,
16 template <typename> typename InterpolationKernel, std::size_t N,
17 template <typename> typename... CollectedInterpolationKernels>
20 GridVertexProperty, InterpolationKernel, N - 1,
21 CollectedInterpolationKernels..., InterpolationKernel>::type;
22};
23//----------------------------------------------------------------------------
24template <typename GridVertexProperty,
25 template <typename> typename InterpolationKernel,
26 template <typename> typename... CollectedInterpolationKernels>
28 GridVertexProperty, InterpolationKernel, 0,
29 CollectedInterpolationKernels...> {
30 using type = vertex_property_sampler<GridVertexProperty,
31 CollectedInterpolationKernels...>;
32};
33//----------------------------------------------------------------------------
34template <typename GridVertexProperty,
35 template <typename> typename InterpolationKernel>
38 GridVertexProperty, InterpolationKernel,
39 GridVertexProperty::num_dimensions()>::type;
40//==============================================================================
41template <typename Grid, typename ValueType, bool HasNonConstReference>
43//==============================================================================
44template <typename Grid>
46 //============================================================================
48 using real_type = typename Grid::real_type;
49 using vertex_handle = typename Grid::vertex_handle;
50 //============================================================================
51 static constexpr auto num_dimensions() -> std::size_t { return Grid::num_dimensions(); }
52 //============================================================================
53 private:
54 Grid const* m_grid;
55 //============================================================================
56 public:
57 vertex_property(Grid const& g) : m_grid{&g} {}
58 vertex_property(vertex_property const& other) = default;
59 vertex_property(vertex_property&& other) noexcept = default;
60 //----------------------------------------------------------------------------
61 virtual ~vertex_property() = default;
62 //----------------------------------------------------------------------------
64 virtual auto type() const -> std::type_info const& = 0;
65 virtual auto container_type() const -> std::type_info const& = 0;
66 //----------------------------------------------------------------------------
67 virtual auto clone() const -> std::unique_ptr<this_type> = 0;
68 //----------------------------------------------------------------------------
69 virtual auto resize(std::array<std::size_t, num_dimensions()> const& size)
70 -> void = 0;
71 //----------------------------------------------------------------------------
72 auto resize(integral auto const... size)
73 -> decltype(auto) requires(sizeof...(size) == num_dimensions()) {
74 return resize(std::array{static_cast<std::size_t>(size)...});
75 }
76 //----------------------------------------------------------------------------
77 auto grid() -> auto& { return *m_grid; }
78 auto grid() const -> auto const& { return *m_grid; }
79 auto set_grid(Grid const& g) { m_grid = &g; }
80 //----------------------------------------------------------------------------
81 template <typename T, bool HasNonConstReference = false>
82 auto cast_to_typed() -> auto& {
83 return *static_cast<
85 }
86 //----------------------------------------------------------------------------
87 template <typename T, bool HasNonConstReference = false>
88 auto cast_to_typed() const -> auto const& {
89 return *static_cast<
91 this);
92 }
93};
94//==============================================================================
95template <typename Grid, typename ValueType, bool HasNonConstReference>
97 //============================================================================
98 // typedefs
99 //============================================================================
100 using this_type =
103 using value_type = ValueType;
104 using const_reference = ValueType const&;
105 using reference =
106 std::conditional_t<HasNonConstReference, ValueType&, const_reference>;
107 using grid_type = Grid;
108 using real_type = typename Grid::real_type;
112 using inverse_distance_weighting_sampler_type = detail::rectilinear_grid::
113 inverse_distance_weighting_vertex_property_sampler<Grid, this_type>;
114
115 //============================================================================
116 // ctors
117 //============================================================================
118 explicit typed_vertex_property_interface(Grid const& g) : parent_type{g} {}
120 default;
122 default;
123 //----------------------------------------------------------------------------
125 //============================================================================
126 // methods
127 //============================================================================
128 auto type() const -> std::type_info const& override {
129 return typeid(value_type);
130 }
131 //----------------------------------------------------------------------------
132 private:
133 template <template <typename> typename InterpolationKernel>
136 this_type,
137 InterpolationKernel>{*this};
138 }
139 //----------------------------------------------------------------------------
140 public:
141 template <template <typename> typename... InterpolationKernels>
142 requires (sizeof...(InterpolationKernels) == num_dimensions()) ||
143 (sizeof...(InterpolationKernels) == 1)
144 auto sampler() const {
145 if constexpr (sizeof...(InterpolationKernels) == 1) {
146 return repeated_interpolation_kernel_sampler<InterpolationKernels...>();
147 } else {
148 using sampler_t =
149 vertex_property_sampler<this_type, InterpolationKernels...>;
150 return sampler_t{*this};
151 }
152 }
153 //----------------------------------------------------------------------------
154 auto linear_sampler() const -> decltype(auto) {
155 return sampler<interpolation::linear>();
156 }
157 //----------------------------------------------------------------------------
158 auto cubic_sampler() const -> decltype(auto) {
159 return sampler<interpolation::cubic>();
160 }
161 //----------------------------------------------------------------------------
163 return inverse_distance_weighting_sampler_type{this->grid(), *this, radius};
164 }
165 //----------------------------------------------------------------------------
166 // data access
167 //----------------------------------------------------------------------------
168 constexpr auto operator[](vertex_handle const& h) const -> decltype(auto) {
169 return at(h);
170 }
171 //----------------------------------------------------------------------------
172 constexpr auto operator[](vertex_handle const& h) -> decltype(auto) {
173 return at(h);
174 }
175 //----------------------------------------------------------------------------
176 constexpr auto operator()(
177 std::array<std::size_t, num_dimensions()> const& indices) const
178 -> decltype(auto) {
179 return at(indices);
180 }
181 //----------------------------------------------------------------------------
182 constexpr auto operator()(
183 std::array<std::size_t, num_dimensions()> const& indices)
184 -> decltype(auto) {
185 return at(indices);
186 }
187 //----------------------------------------------------------------------------
188 constexpr auto operator()(integral auto const... indices) const
189 -> decltype(auto) requires(sizeof...(indices) == num_dimensions()) {
190 return at(std::array{static_cast<std::size_t>(indices)...});
191 }
192 //----------------------------------------------------------------------------
193 constexpr auto operator()(integral auto const... indices)
194 -> decltype(auto) requires(sizeof...(indices) == num_dimensions()) {
195 return at(std::array{static_cast<std::size_t>(indices)...});
196 }
197 //----------------------------------------------------------------------------
198 constexpr auto at(vertex_handle const& h) const -> decltype(auto) {
199 return at(h, std::make_index_sequence<num_dimensions()>{});
200 }
201 //----------------------------------------------------------------------------
202 constexpr auto at(vertex_handle const& h) -> decltype(auto) {
203 return at(h, std::make_index_sequence<num_dimensions()>{});
204 }
205 //----------------------------------------------------------------------------
206 private:
207 template <std::size_t... Is>
208 constexpr auto at(vertex_handle const& h,
209 std::index_sequence<Is...> /*seq*/) const
210 -> decltype(auto) {
211 return at(h.index(Is)...);
212 }
213 //----------------------------------------------------------------------------
214 template <std::size_t... Is>
215 constexpr auto at(vertex_handle const& h, std::index_sequence<Is...> /*seq*/)
216 -> decltype(auto) {
217 return at(h.index(Is)...);
218 }
219 //----------------------------------------------------------------------------
220 public:
221 auto at(integral auto const... indices) const
222 -> decltype(auto) requires(sizeof...(indices) == num_dimensions()) {
223 return at(std::array{static_cast<std::size_t>(indices)...});
224 }
225 //----------------------------------------------------------------------------
226 auto at(integral auto const... indices)
227 -> decltype(auto) requires(sizeof...(indices) == num_dimensions()) {
228 return at(std::array{static_cast<std::size_t>(indices)...});
229 }
230 //----------------------------------------------------------------------------
231 virtual auto at(std::array<std::size_t, num_dimensions()> const& indices)
232 const -> const_reference = 0;
233 //----------------------------------------------------------------------------
234 virtual auto at(std::array<std::size_t, num_dimensions()> const& indices)
235 -> reference = 0;
236 //----------------------------------------------------------------------------
237 virtual auto plain_at(std::size_t) const -> const_reference = 0;
238 //----------------------------------------------------------------------------
239 virtual auto plain_at(std::size_t) -> reference = 0;
240 //----------------------------------------------------------------------------
241#if TATOOINE_PNG_AVAILABLE
242 template <invocable<ValueType> T>
243 auto write_png(filesystem::path const& path, T&& f, auto&& color_scale,
245 tatooine::value_type<ValueType> const max = 1) const
246 -> void requires(num_dimensions() == 2) &&
247 (static_vec<ValueType>)&&(arithmetic<invoke_result<T, ValueType>>) {
248 png::image<png::rgb_pixel> image{
249 static_cast<png::uint_32>(this->grid().size(0)),
250 static_cast<png::uint_32>(this->grid().size(1))};
251 for (unsigned int y = 0; y < image.get_height(); ++y) {
252 for (png::uint_32 x = 0; x < image.get_width(); ++x) {
253 auto d = f(at(x, y));
254 if (std::isnan(d)) {
255 d = 0;
256 } else {
257 d = std::max<tatooine::value_type<ValueType>>(
258 min, std::min<tatooine::value_type<ValueType>>(max, d));
259 d -= min;
260 d /= max - min;
261 }
262 auto const col = color_scale(d);
263 image[image.get_height() - 1 - y][x].red = col.x() * 255;
264 image[image.get_height() - 1 - y][x].green = col.y() * 255;
265 image[image.get_height() - 1 - y][x].blue = col.z() * 255;
266 }
267 }
268 image.write(path.string());
269 }
270 //----------------------------------------------------------------------------
271 auto write_png(filesystem::path const& path,
273 tatooine::value_type<ValueType> const max = 1) const
274 -> void requires(num_dimensions() == 2) &&
275 ((static_vec<ValueType>) || (arithmetic<ValueType>)) {
276 png::image<png::rgb_pixel> image{
277 static_cast<png::uint_32>(this->grid().size(0)),
278 static_cast<png::uint_32>(this->grid().size(1))};
279 for (unsigned int y = 0; y < image.get_height(); ++y) {
280 for (png::uint_32 x = 0; x < image.get_width(); ++x) {
281 auto d = at(x, y);
282 if constexpr (is_floating_point<ValueType>) {
283 if (std::isnan(d)) {
284 d = 0;
285 } else {
286 d = std::max<ValueType>(min, std::min<ValueType>(max, d));
287 d -= min;
288 d /= max - min;
289 }
290 image[image.get_height() - 1 - y][x].red =
291 image[image.get_height() - 1 - y][x].green =
292 image[image.get_height() - 1 - y][x].blue = d * 255;
293 } else if constexpr (static_vec<ValueType>) {
294 if (std::isnan(d(0))) {
295 for (auto& c : d) {
296 c = 0;
297 }
298 } else {
299 for (auto& c : d) {
300 c = std::max<typename ValueType::value_type>(
301 min, std::min<typename ValueType::value_type>(max, c));
302 c -= min;
303 c /= max - min;
304 }
305 }
306 image[image.get_height() - 1 - y][x].red = d(0) * 255;
307 image[image.get_height() - 1 - y][x].green = d(1) * 255;
308 image[image.get_height() - 1 - y][x].blue = d(2) * 255;
309 }
310 }
311 }
312 image.write(path.string());
313 }
314 //----------------------------------------------------------------------------
315 auto write_png(filesystem::path const& path, auto&& color_scale,
316 ValueType const min = 0, ValueType const max = 1) const
317 -> void requires(num_dimensions() == 2) &&
318 (is_floating_point<ValueType>) {
319 png::image<png::rgb_pixel> image{
320 static_cast<png::uint_32>(this->grid().size(0)),
321 static_cast<png::uint_32>(this->grid().size(1))};
322 for (unsigned int y = 0; y < image.get_height(); ++y) {
323 for (png::uint_32 x = 0; x < image.get_width(); ++x) {
324 auto d = at(x, y);
325 if (std::isnan(d)) {
326 d = 0;
327 } else {
328 d = std::max<ValueType>(min, std::min<ValueType>(max, d));
329 d -= min;
330 d /= max - min;
331 }
332 auto const col = color_scale(d) * 255;
333 image[image.get_height() - 1 - y][x].red = col(0);
334 image[image.get_height() - 1 - y][x].green = col(1);
335 image[image.get_height() - 1 - y][x].blue = col(2);
336 }
337 }
338 image.write(path.string());
339 }
340#endif
341};
342//==============================================================================
343#if TATOOINE_PNG_AVAILABLE
344template <typename Grid, typename ValueType, bool HasNonConstReference>
346 Grid, ValueType, HasNonConstReference> const& prop,
347 filesystem::path const& path) -> void {
348 prop.write_png(path);
349}
350//------------------------------------------------------------------------------
351template <typename Grid, typename ValueType, bool HasNonConstReference>
352auto write_png(filesystem::path const& path,
354 Grid, ValueType, HasNonConstReference> const& prop) -> void {
355 prop.write_png(path);
356}
357#endif
358//==============================================================================
359template <typename Grid, typename ValueType, typename Container>
362 Grid, ValueType,
363 std::is_convertible_v<
364 decltype(std::declval<Container&>().at(
365 std::declval<
366 std::array<std::size_t, Grid::num_dimensions()>>())),
367 ValueType&>>,
368 Container {
369 static_assert(std::is_same_v<ValueType, typename Container::value_type>);
370 //============================================================================
371 // typedefs
372 //============================================================================
374 static constexpr bool has_non_const_reference = std::is_convertible_v<
375 decltype(std::declval<Container&>().at(
376 std::declval<std::array<std::size_t, Grid::num_dimensions()>>())),
377 ValueType&>;
384 using grid_type = Grid;
385 using real_type = typename Grid::real_type;
387 //============================================================================
388 // ctors
389 //============================================================================
390 template <typename... Args>
391 explicit typed_vertex_property(Grid const& g, Args&&... args)
392 : prop_parent_type{g}, cont_parent_type{std::forward<Args>(args)...} {}
395 //----------------------------------------------------------------------------
396 virtual ~typed_vertex_property() = default;
397 //============================================================================
398 // methods
399 //============================================================================
400 auto clone() const -> std::unique_ptr<vertex_property<Grid>> override {
401 return std::unique_ptr<this_type>(new this_type{*this});
402 }
403 //----------------------------------------------------------------------------
404 auto container_type() const -> std::type_info const& override {
405 return typeid(Container);
406 }
407 //----------------------------------------------------------------------------
408 constexpr auto operator()(integral auto const... indices) const
409 -> decltype(auto) requires(sizeof...(indices) == Grid::num_dimensions()) {
410 return Container::at(indices...);
411 }
412 //----------------------------------------------------------------------------
413 constexpr auto operator()(integral auto const... indices)
414 -> decltype(auto) requires(sizeof...(indices) == Grid::num_dimensions()) {
415 return Container::at(indices...);
416 }
417 //----------------------------------------------------------------------------
418 auto at(integral auto const... indices) const
419 -> decltype(auto) requires(sizeof...(indices) == Grid::num_dimensions()) {
420 return Container::at(indices...);
421 }
422 //----------------------------------------------------------------------------
423 auto at(integral auto const... indices)
424 -> decltype(auto) requires(sizeof...(indices) == Grid::num_dimensions()) {
425 return Container::at(indices...);
426 }
427 //----------------------------------------------------------------------------
428 template <std::size_t... Is>
429 auto at(std::array<std::size_t, num_dimensions()> const& size,
430 std::index_sequence<Is...> /*seq*/) const -> const_reference {
431 return Container::at(size[Is]...);
432 }
433 //----------------------------------------------------------------------------
434 auto at(std::array<std::size_t, num_dimensions()> const& size) const
435 -> const_reference override {
436 return at(size, std::make_index_sequence<num_dimensions()>{});
437 }
438 //----------------------------------------------------------------------------
439 template <std::size_t... Is>
440 auto at(std::array<std::size_t, num_dimensions()> const& size,
441 std::index_sequence<Is...> /*seq*/) -> reference {
442 return Container::at(size[Is]...);
443 }
444 //----------------------------------------------------------------------------
445 auto at(std::array<std::size_t, num_dimensions()> const& size)
446 -> reference override {
447 return at(size, std::make_index_sequence<num_dimensions()>{});
448 }
449 //----------------------------------------------------------------------------
450 auto plain_at(std::size_t const i) const -> const_reference override {
451 return Container::operator[](i);
452 }
453 //----------------------------------------------------------------------------
454 auto plain_at(std::size_t const i) -> reference override {
455 return Container::operator[](i);
456 }
457 //----------------------------------------------------------------------------
458 auto resize(std::array<std::size_t, num_dimensions()> const& size)
459 -> void override {
460 Container::resize(size);
461 }
462};
463//==============================================================================
464template <std::size_t DiffOrder, typename Grid, typename ValueType>
466// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
467template <std::size_t DiffOrder, typename Grid, typename ValueType>
469 typename vertex_property_differentiated_type_impl<DiffOrder, Grid,
470 ValueType>::type;
471// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
472template <floating_point T, typename Grid>
474 using type = vec<T, Grid::num_dimensions()>;
475};
476// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
477template <floating_point T, typename Grid>
479 using type = mat<T, Grid::num_dimensions(), Grid::num_dimensions()>;
480};
481// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
482template <floating_point T, typename Grid>
484 using type = tensor<T, Grid::num_dimensions(), Grid::num_dimensions(),
485 Grid::num_dimensions()>;
486};
487// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
488template <typename Grid, floating_point T, std::size_t N>
490 using type = mat<T, N, Grid::num_dimensions()>;
491};
492// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
493template <typename Grid, floating_point T, std::size_t N>
495 using type = mat<T, N, Grid::num_dimensions()>;
496};
497// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
498template <typename Grid, floating_point T, std::size_t N>
500 using type = tensor<T, N, Grid::num_dimensions(), Grid::num_dimensions()>;
501};
502// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
503template <typename Grid, floating_point T, std::size_t N>
505 using type = tensor<T, N, Grid::num_dimensions(), Grid::num_dimensions()>;
506};
507// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
508template <typename Grid, floating_point T, std::size_t M, std::size_t N>
510 using type = tensor<T, M, N, Grid::num_dimensions()>;
511};
512// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
513template <typename Grid, floating_point T, std::size_t... Dims>
515 using type = tensor<T, Dims..., Grid::num_dimensions()>;
516};
517//==============================================================================
518template <std::size_t DiffOrder, typename Grid, typename PropValueType,
519 bool PropHasNonConstReference, typename Impl>
521 using this_type =
522 differentiated_vertex_property_interface<DiffOrder, Grid, PropValueType,
523 PropHasNonConstReference, Impl>;
524 using prop_type = typed_vertex_property_interface<Grid, PropValueType,
525 PropHasNonConstReference>;
529 using grid_type = Grid;
530 using real_type = typename Grid::real_type;
531 //----------------------------------------------------------------------------
532 static constexpr auto num_dimensions() -> std::size_t { return Grid::num_dimensions(); }
533 //----------------------------------------------------------------------------
534 private:
535 //----------------------------------------------------------------------------
537 std::array<std::array<std::vector<real_type>, num_dimensions()>, DiffOrder>
539 std::size_t m_stencil_size;
541 //----------------------------------------------------------------------------
542 template <std::size_t... Is>
544 std::size_t stencil_size,
545 std::index_sequence<Is...> /*seq*/)
546 : m_prop{prop},
549 (generate_coefficients<Is>(), ...);
550 }
551 //----------------------------------------------------------------------------
552 public:
554 std::size_t stencil_size)
556 prop, stencil_size, std::make_index_sequence<num_dimensions()>{}} {}
557
558 private:
559 //----------------------------------------------------------------------------
561 template <std::size_t i_dim>
563 auto local_positions = std::vector<real_type>(m_stencil_size, 0);
564 auto const& dim = grid().template dimension<i_dim>();
565
566 // local positions relative to current position on dimension. relative
567 // position of current point will be 0.
568 for (std::size_t i_x = 0; i_x < dim.size(); ++i_x) {
569 auto i_left = this->first_stencil_index(i_x, i_dim);
570 for (std::size_t i_local = 0; i_local < m_stencil_size; ++i_local) {
571 local_positions[i_local] = dim[i_left + i_local] - dim[i_x];
572 }
573 for (std::size_t i_order = 0; i_order < differentiation_order();
574 ++i_order) {
575 auto& stencils = m_diff_coeffs_per_order_per_dimension[i_order][i_dim];
576 for (auto const c :
577 finite_differences_coefficients(i_order + 1, local_positions)) {
578 stencils.push_back(c);
579 }
580 }
581 }
582 }
583
584 public:
585 //----------------------------------------------------------------------------
586 auto property() const -> auto const& { return m_prop; }
587 //----------------------------------------------------------------------------
588 auto grid() const -> auto const& { return property().grid(); }
589 //----------------------------------------------------------------------------
590 auto stencil_size() const { return m_stencil_size; }
591 //----------------------------------------------------------------------------
592 auto half_stencil_size() const { return m_half_stencil_size; }
593 //----------------------------------------------------------------------------
594 static constexpr auto differentiation_order() { return DiffOrder; }
595 //----------------------------------------------------------------------------
596 auto differentiation_coefficients(std::size_t const diff_order,
597 std::size_t const dimension) const
598 -> auto const& {
599 return m_diff_coeffs_per_order_per_dimension[diff_order - 1][dimension];
600 }
601 //----------------------------------------------------------------------------
602 // data access
603 //----------------------------------------------------------------------------
604 constexpr auto operator()(integral auto const... indices) const -> value_type
605 requires(sizeof...(indices) == Grid::num_dimensions()) {
606 return at(indices...);
607 }
608 //----------------------------------------------------------------------------
609 auto at(integral auto const... indices) const -> value_type
610 requires(sizeof...(indices) == Grid::num_dimensions()) {
611 return this->as_derived().at(indices...);
612 }
613 //----------------------------------------------------------------------------
616 auto first_stencil_index(std::size_t const i_x,
617 std::size_t const i_dim) const {
618 return static_cast<std::size_t>(std::min<long>(
619 (this->grid().size(i_dim) - 1) - (stencil_size() - 1),
620 std::max<long>(0, static_cast<long>(i_x) - half_stencil_size())));
621 }
622};
623//==============================================================================
624template <std::size_t DiffOrder, typename Grid, typename PropValueType, bool H>
626//==============================================================================
629template <typename Grid, floating_point PropValueType, bool H>
630struct diffentiated_vertex_property<1, Grid, PropValueType, H>
632 1, Grid, PropValueType, H,
633 diffentiated_vertex_property<1, Grid, PropValueType, H>> {
636 differentiated_vertex_property_interface<1, Grid, PropValueType, H,
637 this_type>;
638 using parent_type::differentiation_coefficients;
639 using parent_type::half_stencil_size;
640 using parent_type::num_dimensions;
641 using parent_type::property;
642 using parent_type::stencil_size;
643 using typename parent_type::prop_type;
644 using typename parent_type::value_type;
645 //----------------------------------------------------------------------------
647 std::size_t stencil_size)
648 : parent_type{prop, stencil_size} {}
649 //----------------------------------------------------------------------------
650 auto at(integral auto const... var_indices) const -> value_type {
651 auto derivative = value_type{};
652
653 auto const indices = std::array{static_cast<std::size_t>(var_indices)...};
654
655 for (std::size_t i_dim = 0; i_dim < num_dimensions(); ++i_dim) {
656 auto const i_x = indices[i_dim];
657 auto running_indices = indices;
658 running_indices[i_dim] = this->first_stencil_index(i_x, i_dim);
659
660 auto stencil_it = next(begin(differentiation_coefficients(1, i_dim)),
661 i_x * stencil_size());
662
663 for (std::size_t i = 0; i < stencil_size();
664 ++i, ++running_indices[i_dim], ++stencil_it) {
665 derivative(i_dim) += *stencil_it * property().at(running_indices);
666 }
667 }
668 return derivative;
669 }
670};
671//==============================================================================
674template <typename Grid, floating_point PropValueType, bool H>
675struct diffentiated_vertex_property<2, Grid, PropValueType, H>
677 2, Grid, PropValueType, H,
678 diffentiated_vertex_property<2, Grid, PropValueType, H>> {
681 differentiated_vertex_property_interface<2, Grid, PropValueType, H,
682 this_type>;
683 using parent_type::differentiation_coefficients;
684 using parent_type::half_stencil_size;
685 using parent_type::num_dimensions;
686 using parent_type::property;
687 using parent_type::stencil_size;
688 using typename parent_type::prop_type;
689 using typename parent_type::value_type;
690 //----------------------------------------------------------------------------
692 std::size_t stencil_size)
693 : parent_type{prop, stencil_size} {}
694 //----------------------------------------------------------------------------
695 auto at(integral auto const... var_indices) const -> value_type {
696 auto derivative = value_type::zeros();
697 auto const indices = std::array{static_cast<std::size_t>(var_indices)...};
698 auto origin_indices = indices;
699 // compute start indices of data that is necessary to compute derivative
700 for (std::size_t i = 0; i < num_dimensions(); ++i) {
701 origin_indices[i] = this->first_stencil_index(indices[i], i);
702 }
703 auto data =
704 dynamic_multidim_array<PropValueType>{stencil_size(), stencil_size()};
705 auto diff_coeffs2d =
706 dynamic_multidim_array<PropValueType>{stencil_size(), stencil_size()};
707 // copy actual data
709 [&, this](auto const ix, auto const iy) {
710 data(ix, iy) =
711 property().at(origin_indices[0] + ix, origin_indices[1] + iy);
712 },
713 stencil_size(), stencil_size());
714
715 // compute second order derivatives by calculating outer products of first
716 // order derivative coefficients
717
718 // for each element of the lower triangular matrix of the hessian matrix...
719 for (std::size_t i_dim0 = 0; i_dim0 < num_dimensions(); ++i_dim0) {
720 for (std::size_t i_dim1 = 0; i_dim1 <= i_dim0; ++i_dim1) {
721 if (i_dim0 == i_dim1) {
722 auto const i_dim = i_dim0;
723 auto running_indices = indices;
724 running_indices[i_dim] =
725 this->first_stencil_index(indices[i_dim], i_dim);
726 auto stencil_it = next(begin(differentiation_coefficients(2, i_dim)),
727 indices[i_dim] * stencil_size());
728 for (std::size_t i = 0; i < stencil_size();
729 ++running_indices[i_dim], ++stencil_it, ++i) {
730 derivative(i_dim, i_dim) +=
731 *stencil_it * property().at(running_indices);
732 }
733 running_indices[i_dim] = half_stencil_size();
734
735 } else {
736 auto const& diff_coeffs1d_x = differentiation_coefficients(1, i_dim0);
737 auto const& diff_coeffs1d_y = differentiation_coefficients(1, i_dim1);
738 // ... compute second order differentiation coefficients ...
739 for (std::size_t i_stencil1 = 0; i_stencil1 < stencil_size();
740 ++i_stencil1) {
741 for (std::size_t i_stencil0 = 0; i_stencil0 < stencil_size();
742 ++i_stencil0) {
743 auto const stencil_ix =
744 indices[i_dim0] * stencil_size() + i_stencil0;
745 auto const stencil_iy =
746 indices[i_dim1] * stencil_size() + i_stencil1;
747 diff_coeffs2d(i_stencil0, i_stencil1) =
748 diff_coeffs1d_x[stencil_ix] * diff_coeffs1d_y[stencil_iy];
749 }
750 }
751 // ... and compute derivative
752 for (std::size_t i_stencil1 = 0; i_stencil1 < stencil_size();
753 ++i_stencil1) {
754 for (std::size_t i_stencil0 = 0; i_stencil0 < stencil_size();
755 ++i_stencil0) {
756 derivative(i_dim0, i_dim1) +=
757 diff_coeffs2d(i_stencil0, i_stencil1) *
758 data(i_stencil0, i_stencil1);
759 }
760 }
761 if (i_dim0 != i_dim1) {
762 derivative(i_dim1, i_dim0) = derivative(i_dim0, i_dim1);
763 }
764 }
765 }
766 }
767
768 // mixed derivatives
769 return derivative;
770 }
771};
772//==============================================================================
775template <typename Grid, floating_point VecReal, std::size_t VecN, bool H>
776struct diffentiated_vertex_property<1, Grid, vec<VecReal, VecN>, H>
778 1, Grid, vec<VecReal, VecN>, H,
779 diffentiated_vertex_property<1, Grid, vec<VecReal, VecN>, H>> {
780 using this_type =
784 this_type>;
785 using parent_type::differentiation_coefficients;
786 using parent_type::half_stencil_size;
787 using parent_type::num_dimensions;
788 using parent_type::property;
789 using parent_type::stencil_size;
790 using typename parent_type::prop_type;
791 using typename parent_type::value_type;
792 //----------------------------------------------------------------------------
794 std::size_t stencil_size)
795 : parent_type{prop, stencil_size} {}
796 //----------------------------------------------------------------------------
797 auto at(integral auto const... var_indices) const -> value_type {
798 auto d = value_type{};
799 auto const indices = std::array{static_cast<std::size_t>(var_indices)...};
800 auto running_indices = indices;
801 for (std::size_t i_dim = 0; i_dim < num_dimensions(); ++i_dim) {
802 auto const i_x = indices[i_dim];
803 auto const coeffs_begin = next(
804 begin(differentiation_coefficients(1, i_dim)), i_x * stencil_size());
805 auto const coeffs_end = next(coeffs_begin, stencil_size());
806 running_indices[i_dim] = this->first_stencil_index(i_x, i_dim);
807 for (auto coeffs_it = coeffs_begin; coeffs_it != coeffs_end;
808 ++coeffs_it, ++running_indices[i_dim]) {
809 d.template slice<value_type::rank() - 1>(i_dim) +=
810 property()(running_indices) * *coeffs_it;
811 }
812 running_indices[i_dim] = indices[i_dim];
813 }
814 return d;
815 }
816};
817//==============================================================================
818static auto constexpr default_diff_stencil_size = 5;
819//------------------------------------------------------------------------------
820template <std::size_t DiffOrder = 1, typename Grid, typename ValueType,
821 bool HasNonConstReference>
823 HasNonConstReference> const& prop,
824 std::size_t const stencil_size = default_diff_stencil_size) {
825 return diffentiated_vertex_property<DiffOrder, Grid, ValueType,
826 HasNonConstReference>{prop, stencil_size};
827}
828//==============================================================================
829template <std::size_t DiffOrder = 1, std::size_t CurDiffOrder, typename Grid,
830 typename ValueType, bool HasNonConstReference>
831auto diff(diffentiated_vertex_property<CurDiffOrder, Grid, ValueType,
832 HasNonConstReference> const& d,
833 std::size_t const stencil_size) {
834 return diffentiated_vertex_property<DiffOrder + CurDiffOrder, Grid, ValueType,
835 HasNonConstReference>{d.property(),
836 stencil_size};
837}
838//==============================================================================
839template <std::size_t DiffOrder = 1, std::size_t CurDiffOrder, typename Grid,
840 typename ValueType, bool HasNonConstReference>
841auto diff(diffentiated_vertex_property<CurDiffOrder, Grid, ValueType,
842 HasNonConstReference> const& d) {
843 return diff<DiffOrder>(d, d.stencil_size());
844}
845//==============================================================================
846} // namespace tatooine::detail::rectilinear_grid
847//==============================================================================
848#endif
Definition: dynamic_multidim_array.h:18
Definition: grid_edge.h:16
Definition: concepts.h:33
Definition: concepts.h:30
Definition: concepts.h:21
Definition: tensor_concepts.h:23
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
Definition: cell_container.h:15
static auto constexpr default_diff_stencil_size
Definition: vertex_property.h:818
typename vertex_property_differentiated_type_impl< DiffOrder, Grid, ValueType >::type vertex_property_differentiated_type
Definition: vertex_property.h:470
auto size(cell_container< Dimensions... > const &c)
Definition: cell_container.h:175
auto write_png(typed_vertex_property_interface< Grid, ValueType, HasNonConstReference > const &prop, filesystem::path const &path) -> void
Definition: vertex_property.h:345
typename repeated_interpolation_kernel_for_vertex_property_impl< GridVertexProperty, InterpolationKernel, GridVertexProperty::num_dimensions()>::type repeated_interpolation_kernel_for_vertex_property
Definition: vertex_property.h:39
auto begin(Range &&range)
Definition: iterator_facade.h:318
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
std::invoke_result_t< F, Args... > invoke_result
Definition: concepts.h:127
static constexpr auto is_floating_point
Definition: type_traits.h:76
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
auto next(Iter iter)
Definition: iterator_facade.h:325
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
constexpr auto diff(polynomial< Real, Degree > const &f)
Definition: polynomial.h:179
static constexpr forward_tag forward
Definition: tags.h:9
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
Definition: crtp.h:7
auto at(integral auto const ... var_indices) const -> value_type
Definition: vertex_property.h:650
diffentiated_vertex_property(prop_type const &prop, std::size_t stencil_size)
Definition: vertex_property.h:646
vertex_property_differentiated_type< DiffOrder, Grid, PropValueType > value_type
Definition: vertex_property.h:528
diffentiated_vertex_property(prop_type const &prop, std::size_t stencil_size)
Definition: vertex_property.h:793
auto at(integral auto const ... var_indices) const -> value_type
Definition: vertex_property.h:797
vertex_property_differentiated_type< DiffOrder, Grid, PropValueType > value_type
Definition: vertex_property.h:528
diffentiated_vertex_property(prop_type const &prop, std::size_t stencil_size)
Definition: vertex_property.h:691
vertex_property_differentiated_type< DiffOrder, Grid, PropValueType > value_type
Definition: vertex_property.h:528
auto at(integral auto const ... var_indices) const -> value_type
Definition: vertex_property.h:695
differentiated_vertex_property_interface(prop_type const &prop, std::size_t stencil_size, std::index_sequence< Is... >)
Definition: vertex_property.h:543
typename Grid::real_type real_type
Definition: vertex_property.h:530
std::array< std::array< std::vector< real_type >, num_dimensions()>, DiffOrder > m_diff_coeffs_per_order_per_dimension
Definition: vertex_property.h:538
auto generate_coefficients()
Generates diffentiation coefficients for dimension i_dim.
Definition: vertex_property.h:562
auto grid() const -> auto const &
Definition: vertex_property.h:588
auto differentiation_coefficients(std::size_t const diff_order, std::size_t const dimension) const -> auto const &
Definition: vertex_property.h:596
auto property() const -> auto const &
Definition: vertex_property.h:586
static constexpr auto num_dimensions() -> std::size_t
Definition: vertex_property.h:532
constexpr auto operator()(integral auto const ... indices) const -> value_type requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:604
static constexpr auto differentiation_order()
Definition: vertex_property.h:594
prop_type const & m_prop
Definition: vertex_property.h:536
vertex_property_differentiated_type< DiffOrder, Grid, PropValueType > value_type
Definition: vertex_property.h:528
differentiated_vertex_property_interface(prop_type const &prop, std::size_t stencil_size)
Definition: vertex_property.h:553
auto at(integral auto const ... indices) const -> value_type requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:609
auto first_stencil_index(std::size_t const i_x, std::size_t const i_dim) const
Definition: vertex_property.h:616
Definition: inverse_distance_weighting_vertex_property_sampler.h:14
typename repeated_interpolation_kernel_for_vertex_property_impl< GridVertexProperty, InterpolationKernel, N - 1, CollectedInterpolationKernels..., InterpolationKernel >::type type
Definition: vertex_property.h:21
constexpr auto at(vertex_handle const &h, std::index_sequence< Is... >) const -> decltype(auto)
Definition: vertex_property.h:208
auto at(integral auto const ... indices) const -> decltype(auto) requires(sizeof...(indices)==num_dimensions())
Definition: vertex_property.h:221
constexpr auto at(vertex_handle const &h, std::index_sequence< Is... >) -> decltype(auto)
Definition: vertex_property.h:215
constexpr auto operator[](vertex_handle const &h) -> decltype(auto)
Definition: vertex_property.h:172
auto linear_sampler() const -> decltype(auto)
Definition: vertex_property.h:154
auto at(integral auto const ... indices) -> decltype(auto) requires(sizeof...(indices)==num_dimensions())
Definition: vertex_property.h:226
auto write_png(filesystem::path const &path, auto &&color_scale, ValueType const min=0, ValueType const max=1) const -> void requires(num_dimensions()==2) &&(is_floating_point< ValueType >)
Definition: vertex_property.h:315
virtual auto at(std::array< std::size_t, num_dimensions()> const &indices) -> reference=0
ValueType const & const_reference
Definition: vertex_property.h:104
auto cubic_sampler() const -> decltype(auto)
Definition: vertex_property.h:158
constexpr auto at(vertex_handle const &h) -> decltype(auto)
Definition: vertex_property.h:202
typed_vertex_property_interface(Grid const &g)
Definition: vertex_property.h:118
constexpr auto operator()(integral auto const ... indices) const -> decltype(auto) requires(sizeof...(indices)==num_dimensions())
Definition: vertex_property.h:188
virtual auto at(std::array< std::size_t, num_dimensions()> const &indices) const -> const_reference=0
constexpr auto operator()(std::array< std::size_t, num_dimensions()> const &indices) -> decltype(auto)
Definition: vertex_property.h:182
typename Grid::real_type real_type
Definition: vertex_property.h:108
auto inverse_distance_weighting_sampler(real_type const radius) const
Definition: vertex_property.h:162
typed_vertex_property_interface(typed_vertex_property_interface const &)=default
constexpr auto at(vertex_handle const &h) const -> decltype(auto)
Definition: vertex_property.h:198
static constexpr auto num_dimensions() -> std::size_t
Definition: vertex_property.h:51
auto grid() -> auto &
Definition: vertex_property.h:77
typed_vertex_property_interface(typed_vertex_property_interface &&) noexcept=default
constexpr auto operator()(std::array< std::size_t, num_dimensions()> const &indices) const -> decltype(auto)
Definition: vertex_property.h:176
typed_vertex_property_interface< Grid, ValueType, HasNonConstReference > this_type
Definition: vertex_property.h:101
virtual auto plain_at(std::size_t) const -> const_reference=0
constexpr auto operator()(integral auto const ... indices) -> decltype(auto) requires(sizeof...(indices)==num_dimensions())
Definition: vertex_property.h:193
auto sampler() const
Definition: vertex_property.h:144
std::conditional_t< HasNonConstReference, ValueType &, const_reference > reference
Definition: vertex_property.h:106
auto repeated_interpolation_kernel_sampler() const
Definition: vertex_property.h:134
ValueType value_type
Definition: vertex_property.h:103
auto write_png(filesystem::path const &path, tatooine::value_type< ValueType > min=0, tatooine::value_type< ValueType > const max=1) const -> void requires(num_dimensions()==2) &&((static_vec< ValueType >)||(arithmetic< ValueType >))
Definition: vertex_property.h:271
typename Grid::vertex_handle vertex_handle
Definition: vertex_property.h:49
constexpr auto operator[](vertex_handle const &h) const -> decltype(auto)
Definition: vertex_property.h:168
auto write_png(filesystem::path const &path, T &&f, auto &&color_scale, tatooine::value_type< ValueType > const min=0, tatooine::value_type< ValueType > const max=1) const -> void requires(num_dimensions()==2) &&(static_vec< ValueType >)&&(arithmetic< invoke_result< T, ValueType > >)
Definition: vertex_property.h:243
auto type() const -> std::type_info const &override
for identifying type.
Definition: vertex_property.h:128
auto plain_at(std::size_t const i) -> reference override
Definition: vertex_property.h:454
typename prop_parent_type::const_reference const_reference
Definition: vertex_property.h:383
static constexpr bool has_non_const_reference
Definition: vertex_property.h:374
auto at(std::array< std::size_t, num_dimensions()> const &size) const -> const_reference override
Definition: vertex_property.h:434
typename prop_parent_type::value_type value_type
Definition: vertex_property.h:381
auto at(integral auto const ... indices) -> decltype(auto) requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:423
constexpr auto operator()(integral auto const ... indices) const -> decltype(auto) requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:408
auto at(integral auto const ... indices) const -> decltype(auto) requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:418
auto at(std::array< std::size_t, num_dimensions()> const &size, std::index_sequence< Is... >) -> reference
Definition: vertex_property.h:440
typename prop_parent_type::reference reference
Definition: vertex_property.h:382
typed_vertex_property(Grid const &g, Args &&... args)
Definition: vertex_property.h:391
constexpr auto operator()(integral auto const ... indices) -> decltype(auto) requires(sizeof...(indices)==Grid::num_dimensions())
Definition: vertex_property.h:413
auto at(std::array< std::size_t, num_dimensions()> const &size) -> reference override
Definition: vertex_property.h:445
typename Grid::real_type real_type
Definition: vertex_property.h:385
auto container_type() const -> std::type_info const &override
Definition: vertex_property.h:404
static constexpr auto num_dimensions() -> std::size_t
Definition: vertex_property.h:51
Grid grid_type
Definition: vertex_property.h:384
auto at(std::array< std::size_t, num_dimensions()> const &size, std::index_sequence< Is... >) const -> const_reference
Definition: vertex_property.h:429
typed_vertex_property(typed_vertex_property const &)=default
auto plain_at(std::size_t const i) const -> const_reference override
Definition: vertex_property.h:450
auto resize(std::array< std::size_t, num_dimensions()> const &size) -> void override
Definition: vertex_property.h:458
typed_vertex_property(typed_vertex_property &&) noexcept=default
auto clone() const -> std::unique_ptr< vertex_property< Grid > > override
Definition: vertex_property.h:400
Definition: vertex_property_sampler.h:271
Grid const * m_grid
Definition: vertex_property.h:54
virtual auto resize(std::array< std::size_t, num_dimensions()> const &size) -> void=0
typename Grid::real_type real_type
Definition: vertex_property.h:48
auto grid() const -> auto const &
Definition: vertex_property.h:78
auto cast_to_typed() const -> auto const &
Definition: vertex_property.h:88
vertex_property(Grid const &g)
Definition: vertex_property.h:57
vertex_property(vertex_property const &other)=default
virtual auto type() const -> std::type_info const &=0
for identifying type.
static constexpr auto num_dimensions() -> std::size_t
Definition: vertex_property.h:51
auto grid() -> auto &
Definition: vertex_property.h:77
auto set_grid(Grid const &g)
Definition: vertex_property.h:79
virtual auto container_type() const -> std::type_info const &=0
auto cast_to_typed() -> auto &
Definition: vertex_property.h:82
virtual auto clone() const -> std::unique_ptr< this_type >=0
vertex_property(vertex_property &&other) noexcept=default
typename Grid::vertex_handle vertex_handle
Definition: vertex_property.h:49
Definition: mat.h:14
Definition: tensor.h:17
Definition: vec.h:12