Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <boost/range/combine.hpp>
7 : #include <boost/tuple/tuple.hpp>
8 : #include <cstddef>
9 : #include <optional>
10 :
11 : #include "DataStructures/Index.hpp"
12 : #include "DataStructures/SliceIterator.hpp"
13 : #include "DataStructures/Tensor/Tensor.hpp"
14 : #include "Utilities/Gsl.hpp"
15 : #include "Utilities/TMPL.hpp"
16 : #include "Utilities/TypeTraits.hpp"
17 :
18 : /// @{
19 : /*!
20 : * \ingroup DataStructuresGroup
21 : * \brief Slices the data within `volume_tensor` to a codimension 1 slice. The
22 : * slice has a constant logical coordinate in direction `sliced_dim`,
23 : * slicing the volume at `fixed_index` in that dimension. For
24 : * example, to get the lower boundary of `sliced_dim`, pass `0` for
25 : * `fixed_index`; to get the upper boundary, pass
26 : * `extents[sliced_dim] - 1`.
27 : *
28 : * \see add_slice_to_data
29 : *
30 : * Returns Tensor class sliced to a hypersurface.
31 : */
32 : template <std::size_t VolumeDim, typename VectorType, typename... Structure>
33 1 : void data_on_slice(
34 : const gsl::not_null<Tensor<VectorType, Structure...>*> interface_tensor,
35 : const Tensor<VectorType, Structure...>& volume_tensor,
36 : const Index<VolumeDim>& element_extents, const size_t sliced_dim,
37 : const size_t fixed_index) {
38 : const size_t interface_grid_points =
39 : element_extents.slice_away(sliced_dim).product();
40 : if (interface_tensor->begin()->size() != interface_grid_points) {
41 : *interface_tensor = Tensor<VectorType, Structure...>(interface_grid_points);
42 : }
43 :
44 : for (SliceIterator si(element_extents, sliced_dim, fixed_index); si; ++si) {
45 : for (decltype(auto) interface_and_volume_tensor_components :
46 : boost::combine(*interface_tensor, volume_tensor)) {
47 : boost::get<0>(interface_and_volume_tensor_components)[si.slice_offset()] =
48 : boost::get<1>(
49 : interface_and_volume_tensor_components)[si.volume_offset()];
50 : }
51 : }
52 : }
53 :
54 : template <std::size_t VolumeDim, typename VectorType, typename... Structure>
55 1 : Tensor<VectorType, Structure...> data_on_slice(
56 : const Tensor<VectorType, Structure...>& volume_tensor,
57 : const Index<VolumeDim>& element_extents, const size_t sliced_dim,
58 : const size_t fixed_index) {
59 : Tensor<VectorType, Structure...> interface_tensor(
60 : element_extents.slice_away(sliced_dim).product());
61 : data_on_slice(make_not_null(&interface_tensor), volume_tensor,
62 : element_extents, sliced_dim, fixed_index);
63 : return interface_tensor;
64 : }
65 :
66 : template <std::size_t VolumeDim, typename VectorType, typename... Structure>
67 1 : void data_on_slice(
68 : const gsl::not_null<std::optional<Tensor<VectorType, Structure...>>*>
69 : interface_tensor,
70 : const std::optional<Tensor<VectorType, Structure...>>& volume_tensor,
71 : const Index<VolumeDim>& element_extents, const size_t sliced_dim,
72 : const size_t fixed_index) {
73 : if (volume_tensor.has_value()) {
74 : if (not(*interface_tensor)) {
75 : *interface_tensor = Tensor<VectorType, Structure...>{
76 : element_extents.slice_away(sliced_dim).product()};
77 : }
78 : data_on_slice(make_not_null(&**interface_tensor), *volume_tensor,
79 : element_extents, sliced_dim, fixed_index);
80 : } else {
81 : *interface_tensor = std::nullopt;
82 : }
83 : }
84 :
85 : template <std::size_t VolumeDim, typename VectorType, typename... Structure>
86 1 : std::optional<Tensor<VectorType, Structure...>> data_on_slice(
87 : const std::optional<Tensor<VectorType, Structure...>>& volume_tensor,
88 : const Index<VolumeDim>& element_extents, const size_t sliced_dim,
89 : const size_t fixed_index) {
90 : if (volume_tensor.has_value()) {
91 : Tensor<VectorType, Structure...> interface_tensor(
92 : element_extents.slice_away(sliced_dim).product());
93 : data_on_slice(make_not_null(&interface_tensor), *volume_tensor,
94 : element_extents, sliced_dim, fixed_index);
95 : return interface_tensor;
96 : }
97 : return std::nullopt;
98 : }
99 : /// @}
|