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 <vector> 8 : 9 : #include "Utilities/ErrorHandling/Assert.hpp" 10 : #include "Utilities/Gsl.hpp" 11 : #include "Utilities/TMPL.hpp" 12 : 13 : /// \cond 14 : template <size_t VolumeDim> 15 : class Mesh; 16 : template <size_t VolumeDim> 17 : class OrientationMap; 18 : template <size_t> 19 : class Index; 20 : template <typename TagsList> 21 : class Variables; 22 : /// \endcond 23 : 24 : /// \ingroup ComputationalDomainGroup 25 : /// \brief Orient a sliced Mesh to the logical frame of a neighbor element with 26 : /// the given orientation. 27 : template <size_t VolumeDim> 28 1 : Mesh<VolumeDim - 1> orient_mesh_on_slice( 29 : const Mesh<VolumeDim - 1>& mesh_on_slice, size_t sliced_dim, 30 : const OrientationMap<VolumeDim>& orientation_of_neighbor); 31 : 32 : /// @{ 33 : /// \ingroup ComputationalDomainGroup 34 : /// \brief Orient a `DataVector`, `ComplexDataVector`, `std::vector<double>`, or 35 : /// `std::vector<std::complex<double>>` to the data-storage order of a neighbor 36 : /// element with the given orientation. 37 : /// 38 : /// The vector may represent more than one tensor component over the grid 39 : /// represented by `extents`. 40 : /// 41 : /// \warning The result is *not* resized and assumes to be of the correct size 42 : /// (`variables.size()`). 43 : /// 44 : /// In most cases the `Variables` version of `orient_variables` should be 45 : /// called. However, in some cases the tags and thus the type of the data being 46 : /// sent is determined at runtime. In these cases the `std::vector` version of 47 : /// `orient_variables` is useful. A concrete example of this is when hybridizing 48 : /// DG with finite difference methods, where sometimes the data sent is both the 49 : /// variables for reconstruction and the fluxes for either the DG or finite 50 : /// difference scheme, while at other points only one of these three is sent. 51 : template <typename VectorType, size_t VolumeDim> 52 1 : void orient_variables(gsl::not_null<VectorType*> result, 53 : const VectorType& variables, 54 : const Index<VolumeDim>& extents, 55 : const OrientationMap<VolumeDim>& orientation_of_neighbor); 56 : 57 : template <typename VectorType, size_t VolumeDim> 58 1 : VectorType orient_variables( 59 : const VectorType& variables, const Index<VolumeDim>& extents, 60 : const OrientationMap<VolumeDim>& orientation_of_neighbor); 61 : 62 : template <typename VectorType, size_t VolumeDim> 63 1 : void orient_variables_on_slice( 64 : gsl::not_null<VectorType*> result, const VectorType& variables_on_slice, 65 : const Index<VolumeDim - 1>& slice_extents, size_t sliced_dim, 66 : const OrientationMap<VolumeDim>& orientation_of_neighbor); 67 : 68 : template <typename VectorType, size_t VolumeDim> 69 1 : VectorType orient_variables_on_slice( 70 : const VectorType& variables_on_slice, 71 : const Index<VolumeDim - 1>& slice_extents, size_t sliced_dim, 72 : const OrientationMap<VolumeDim>& orientation_of_neighbor); 73 : /// @} 74 : 75 : /// @{ 76 : /// \ingroup ComputationalDomainGroup 77 : /// Orient variables to the data-storage order of a neighbor element with 78 : /// the given orientation. 79 : template <size_t VolumeDim, typename TagsList> 80 1 : Variables<TagsList> orient_variables( 81 : const Variables<TagsList>& variables, const Index<VolumeDim>& extents, 82 : const OrientationMap<VolumeDim>& orientation_of_neighbor) { 83 : // Skip work (aside from a copy) if neighbor is aligned 84 : if (orientation_of_neighbor.is_aligned()) { 85 : return variables; 86 : } 87 : 88 : const size_t number_of_grid_points = extents.product(); 89 : ASSERT(variables.number_of_grid_points() == number_of_grid_points, 90 : "Inconsistent `variables` and `extents`:\n" 91 : " variables.number_of_grid_points() = " 92 : << variables.number_of_grid_points() 93 : << "\n" 94 : " extents.product() = " 95 : << extents.product()); 96 : Variables<TagsList> oriented_variables(number_of_grid_points); 97 : using VectorType = typename Variables<TagsList>::vector_type; 98 : using ValueType = typename Variables<TagsList>::value_type; 99 : VectorType result(oriented_variables.data(), oriented_variables.size()); 100 : orient_variables( 101 : make_not_null(&result), 102 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) 103 : VectorType(const_cast<ValueType*>(variables.data()), variables.size()), 104 : extents, orientation_of_neighbor); 105 : return oriented_variables; 106 : } 107 : 108 : template <size_t VolumeDim, typename TagsList> 109 1 : Variables<TagsList> orient_variables_on_slice( 110 : const Variables<TagsList>& variables_on_slice, 111 : const Index<VolumeDim - 1>& slice_extents, const size_t sliced_dim, 112 : const OrientationMap<VolumeDim>& orientation_of_neighbor) { 113 : // Skip work (aside from a copy) if neighbor slice is aligned 114 : if (orientation_of_neighbor.is_aligned()) { 115 : return variables_on_slice; 116 : } 117 : 118 : const size_t number_of_grid_points = slice_extents.product(); 119 : ASSERT(variables_on_slice.number_of_grid_points() == number_of_grid_points, 120 : "Inconsistent `variables_on_slice` and `slice_extents`:\n" 121 : " variables_on_slice.number_of_grid_points() = " 122 : << variables_on_slice.number_of_grid_points() 123 : << "\n" 124 : " slice_extents.product() = " 125 : << slice_extents.product()); 126 : 127 : Variables<TagsList> oriented_variables(number_of_grid_points); 128 : using VectorType = typename Variables<TagsList>::vector_type; 129 : using ValueType = typename Variables<TagsList>::value_type; 130 : VectorType result(oriented_variables.data(), oriented_variables.size()); 131 : orient_variables_on_slice( 132 : make_not_null(&result), 133 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) 134 : VectorType(const_cast<ValueType*>(variables_on_slice.data()), 135 : variables_on_slice.size()), 136 : slice_extents, sliced_dim, orientation_of_neighbor); 137 : return oriented_variables; 138 : } 139 : /// @}