SliceVariables.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <ostream>
8 
10 #include "DataStructures/SliceIterator.hpp"
12 #include "ErrorHandling/Assert.hpp"
13 #include "Utilities/Gsl.hpp"
14 #include "Utilities/TMPL.hpp"
15 
16 // @{
17 /*!
18  * \ingroup DataStructuresGroup
19  * \brief Slices the data within `vars` to a codimension 1 slice. The
20  * slice has a constant logical coordinate in direction `sliced_dim`,
21  * slicing the volume at `fixed_index` in that dimension. For
22  * example, to get the lower boundary of `sliced_dim`, pass `0` for
23  * `fixed_index`; to get the upper boundary, pass
24  * `extents[sliced_dim] - 1`.
25  *
26  * \see add_slice_to_data
27  *
28  * Returns Variables class sliced to a hypersurface.
29  */
30 template <std::size_t VolumeDim, typename TagsList>
31 void data_on_slice(const gsl::not_null<Variables<TagsList>*> interface_vars,
32  const Variables<TagsList>& vars,
33  const Index<VolumeDim>& element_extents,
34  const size_t sliced_dim, const size_t fixed_index) noexcept {
35  const size_t interface_grid_points =
36  element_extents.slice_away(sliced_dim).product();
37  const size_t volume_grid_points = vars.number_of_grid_points();
38  constexpr const size_t number_of_independent_components =
39  Variables<TagsList>::number_of_independent_components;
40 
41  if (interface_vars->number_of_grid_points() != interface_grid_points) {
42  *interface_vars = Variables<TagsList>(interface_grid_points);
43  }
44  using value_type = typename Variables<TagsList>::value_type;
45  const value_type* vars_data = vars.data();
46  value_type* interface_vars_data = interface_vars->data();
47  for (SliceIterator si(element_extents, sliced_dim, fixed_index); si; ++si) {
48  for (size_t i = 0; i < number_of_independent_components; ++i) {
49  // clang-tidy: do not use pointer arithmetic
50  interface_vars_data[si.slice_offset() + // NOLINT
51  i * interface_grid_points] = // NOLINT
52  vars_data[si.volume_offset() + i * volume_grid_points]; // NOLINT
53  }
54  }
55 }
56 
57 template <std::size_t VolumeDim, typename TagsList>
58 Variables<TagsList> data_on_slice(const Variables<TagsList>& vars,
59  const Index<VolumeDim>& element_extents,
60  const size_t sliced_dim,
61  const size_t fixed_index) noexcept {
62  Variables<TagsList> interface_vars(
63  element_extents.slice_away(sliced_dim).product());
64  data_on_slice(make_not_null(&interface_vars), vars, element_extents,
65  sliced_dim, fixed_index);
66  return interface_vars;
67 }
68 // @}
69 
70 /*!
71  * \ingroup DataStructuresGroup
72  * \brief Adds data on a codimension 1 slice to a volume quantity. The
73  * slice has a constant logical coordinate in direction `sliced_dim`,
74  * slicing the volume at `fixed_index` in that dimension. For
75  * example, to add to the lower boundary of `sliced_dim`, pass `0` for
76  * `fixed_index`; to add to the upper boundary, pass
77  * `extents[sliced_dim] - 1`.
78  *
79  * \see data_on_slice
80  */
81 template <std::size_t VolumeDim, typename TagsList>
82 void add_slice_to_data(const gsl::not_null<Variables<TagsList>*> volume_vars,
83  const Variables<TagsList>& vars_on_slice,
84  const Index<VolumeDim>& extents, const size_t sliced_dim,
85  const size_t fixed_index) noexcept {
86  constexpr const size_t number_of_independent_components =
87  Variables<TagsList>::number_of_independent_components;
88  const size_t volume_grid_points = extents.product();
89  const size_t slice_grid_points = extents.slice_away(sliced_dim).product();
90  ASSERT(volume_vars->number_of_grid_points() == volume_grid_points,
91  "volume_vars has wrong number of grid points. Expected "
92  << volume_grid_points << ", got "
93  << volume_vars->number_of_grid_points());
94  ASSERT(vars_on_slice.number_of_grid_points() == slice_grid_points,
95  "vars_on_slice has wrong number of grid points. Expected "
96  << slice_grid_points << ", got "
97  << vars_on_slice.number_of_grid_points());
98  using value_type = typename Variables<TagsList>::value_type;
99  value_type* const volume_data = volume_vars->data();
100  const value_type* const slice_data = vars_on_slice.data();
101  for (SliceIterator si(extents, sliced_dim, fixed_index); si; ++si) {
102  for (size_t i = 0; i < number_of_independent_components; ++i) {
103  // clang-tidy: do not use pointer arithmetic
104  volume_data[si.volume_offset() + i * volume_grid_points] += // NOLINT
105  slice_data[si.slice_offset() + i * slice_grid_points]; // NOLINT
106  }
107  }
108 }
Index< VolumeDim >
cstddef
Assert.hpp
SliceIterator
Iterate over a (dim-1)-dimensional slice.
Definition: SliceIterator.hpp:24
Index.hpp
data_on_slice
void data_on_slice(const gsl::not_null< Variables< TagsList > * > interface_vars, const Variables< TagsList > &vars, const Index< VolumeDim > &element_extents, const size_t sliced_dim, const size_t fixed_index) noexcept
Slices the data within vars to a codimension 1 slice. The slice has a constant logical coordinate in ...
Definition: SliceVariables.hpp:31
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:51
Variables.hpp
Gsl.hpp
make_not_null
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,...
Definition: Gsl.hpp:879
ostream
add_slice_to_data
void add_slice_to_data(const gsl::not_null< Variables< TagsList > * > volume_vars, const Variables< TagsList > &vars_on_slice, const Index< VolumeDim > &extents, const size_t sliced_dim, const size_t fixed_index) noexcept
Adds data on a codimension 1 slice to a volume quantity. The slice has a constant logical coordinate ...
Definition: SliceVariables.hpp:82
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:182