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