Slice.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <boost/optional.hpp>
7 #include <boost/range/combine.hpp>
8 #include <boost/tuple/tuple.hpp>
9 #include <cstddef>
10 
11 #include "DataStructures/Index.hpp"
12 #include "DataStructures/SliceIterator.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>
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) noexcept {
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 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) noexcept {
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>
68  const gsl::not_null<boost::optional<Tensor<VectorType, Structure...>>*>
69  interface_tensor,
70  const boost::optional<Tensor<VectorType, Structure...>>& volume_tensor,
71  const Index<VolumeDim>& element_extents, const size_t sliced_dim,
72  const size_t fixed_index) noexcept {
73  if (volume_tensor) {
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 = boost::none;
82  }
83 }
84 
85 template <std::size_t VolumeDim, typename VectorType, typename... Structure>
86 boost::optional<Tensor<VectorType, Structure...>> data_on_slice(
87  const boost::optional<Tensor<VectorType, Structure...>>& volume_tensor,
88  const Index<VolumeDim>& element_extents, const size_t sliced_dim,
89  const size_t fixed_index) noexcept {
90  if (volume_tensor) {
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 boost::none;
98 }
99 // @}
Defines class template Index.
Defines classes for Tensor.
Wraps the template metaprogramming library used (brigand)
Defines functions and classes from the GSL.
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:879
void data_on_slice(const gsl::not_null< Tensor< VectorType, Structure... > *> interface_tensor, const Tensor< VectorType, Structure... > &volume_tensor, const Index< VolumeDim > &element_extents, const size_t sliced_dim, const size_t fixed_index) noexcept
Slices the data within volume_tensor to a codimension 1 slice. The slice has a constant logical coord...
Definition: Slice.hpp:33
Require a pointer to not be a nullptr
Definition: Gsl.hpp:182
Iterate over a (dim-1)-dimensional slice.
Definition: SliceIterator.hpp:24