Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <ostream> 8 : 9 : #include "DataStructures/Index.hpp" 10 : #include "DataStructures/SliceIterator.hpp" 11 : #include "DataStructures/Variables.hpp" 12 : #include "Utilities/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 1 : 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) { 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 1 : 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) { 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... VolumeTags, typename... SliceTags> 82 1 : void add_slice_to_data( 83 : const gsl::not_null<Variables<tmpl::list<VolumeTags...>>*> volume_vars, 84 : const Variables<tmpl::list<SliceTags...>>& vars_on_slice, 85 : const Index<VolumeDim>& extents, const size_t sliced_dim, 86 : const size_t fixed_index) { 87 : static_assert((std::is_same_v<db::remove_all_prefixes<VolumeTags>, 88 : db::remove_all_prefixes<SliceTags>> and 89 : ...)); 90 : static_assert( 91 : (std::is_same_v<typename VolumeTags::type, typename SliceTags::type> and 92 : ...), 93 : "Tensor types do not match."); 94 : constexpr const size_t number_of_independent_components = 95 : Variables<tmpl::list<VolumeTags...>>::number_of_independent_components; 96 : const size_t volume_grid_points = extents.product(); 97 : const size_t slice_grid_points = extents.slice_away(sliced_dim).product(); 98 : ASSERT(volume_vars->number_of_grid_points() == volume_grid_points, 99 : "volume_vars has wrong number of grid points. Expected " 100 : << volume_grid_points << ", got " 101 : << volume_vars->number_of_grid_points()); 102 : ASSERT(vars_on_slice.number_of_grid_points() == slice_grid_points, 103 : "vars_on_slice has wrong number of grid points. Expected " 104 : << slice_grid_points << ", got " 105 : << vars_on_slice.number_of_grid_points()); 106 : using value_type = typename Variables<tmpl::list<VolumeTags...>>::value_type; 107 : value_type* const volume_data = volume_vars->data(); 108 : const value_type* const slice_data = vars_on_slice.data(); 109 : for (SliceIterator si(extents, sliced_dim, fixed_index); si; ++si) { 110 : for (size_t i = 0; i < number_of_independent_components; ++i) { 111 : // clang-tidy: do not use pointer arithmetic 112 : volume_data[si.volume_offset() + i * volume_grid_points] += // NOLINT 113 : slice_data[si.slice_offset() + i * slice_grid_points]; // NOLINT 114 : } 115 : } 116 : }