Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : 9 : #include "DataStructures/ApplyMatrices.hpp" 10 : #include "DataStructures/DataVector.hpp" 11 : #include "DataStructures/Index.hpp" 12 : #include "DataStructures/Matrix.hpp" 13 : #include "DataStructures/Variables.hpp" 14 : #include "Utilities/Gsl.hpp" 15 : 16 : /// \cond 17 : template <size_t Dim> 18 : class Mesh; 19 : namespace PUP { 20 : class er; 21 : } // namespace PUP 22 : /// \endcond 23 : 24 : namespace intrp { 25 : 26 : /// \ingroup NumericalAlgorithmsGroup 27 : /// \brief Interpolate data from a Mesh onto a regular grid of points. 28 : /// 29 : /// The target points must lie on a tensor-product grid that is aligned with the 30 : /// source Mesh. In any direction where the source and target points share an 31 : /// identical Mesh (i.e., where the underlying 1-dimensional meshes share the 32 : /// same extent, basis, and quadrature), the code is optimized to avoid 33 : /// performing identity interpolations. 34 : /// 35 : /// Note, however, that in each dimension of the target grid, the points can 36 : /// be freely distributed; in particular, the grid points need not be the 37 : /// collocation points corresponding to a particular basis and quadrature. Note 38 : /// also that the target grid need not overlap the source grid. In this case, 39 : /// polynomial extrapolation is performed, with order set by the order of the 40 : /// basis in the source grid. The extrapolation will be correct but may suffer 41 : /// from reduced accuracy, especially for higher-order polynomials. 42 : template <size_t Dim> 43 1 : class RegularGrid { 44 : public: 45 : /// \brief An interpolator between two regular grids. 46 : /// 47 : /// When the optional third argument is NOT passed, creates an interpolator 48 : /// between two regular meshes. 49 : /// 50 : /// The optional third argument allows the caller to override the distribution 51 : /// of grid points in any dimension(s) of the target grid. Each non-empty 52 : /// element of `override_target_mesh_with_1d_logical_coords` gives the logical 53 : /// coordinates which will override the default coordinates of `target_mesh`. 54 1 : RegularGrid(const Mesh<Dim>& source_mesh, const Mesh<Dim>& target_mesh, 55 : const std::array<DataVector, Dim>& 56 : override_target_mesh_with_1d_logical_coords = {}); 57 : 58 0 : RegularGrid(); 59 : 60 : // NOLINTNEXTLINE(google-runtime-references) 61 0 : void pup(PUP::er& p); 62 : 63 : /// @{ 64 : /// \brief Interpolate a Variables onto the target points. 65 : template <typename TagsList> 66 1 : void interpolate(gsl::not_null<Variables<TagsList>*> result, 67 : const Variables<TagsList>& vars) const; 68 : template <typename TagsList> 69 1 : Variables<TagsList> interpolate(const Variables<TagsList>& vars) const; 70 : /// @} 71 : 72 : /// @{ 73 : /// \brief Interpolate a DataVector onto the target points. 74 : /// 75 : /// \note When interpolating multiple tensors, the Variables interface is more 76 : /// efficient. However, this DataVector interface is useful for applications 77 : /// where only some components of a Tensor or Variables need to be 78 : /// interpolated. 79 1 : void interpolate(gsl::not_null<DataVector*> result, 80 : const DataVector& input) const; 81 1 : DataVector interpolate(const DataVector& input) const; 82 1 : void interpolate(gsl::not_null<ComplexDataVector*> result, 83 : const ComplexDataVector& input) const; 84 1 : ComplexDataVector interpolate(const ComplexDataVector& input) const; 85 : /// @} 86 : 87 : /// \brief Return the internally-stored matrices that interpolate from the 88 : /// source grid to the target grid. 89 : /// 90 : /// Each matrix interpolates in one logical direction, and can be empty if the 91 : /// interpolation in that direction is the identity (i.e., if the source 92 : /// and target grids have the same logical coordinates in this direction). 93 1 : const std::array<Matrix, Dim>& interpolation_matrices() const; 94 : 95 : private: 96 : template <size_t LocalDim> 97 : // NOLINTNEXTLINE(readability-redundant-declaration) 98 0 : friend bool operator==(const RegularGrid<LocalDim>& lhs, 99 : const RegularGrid<LocalDim>& rhs); 100 : 101 0 : size_t number_of_target_points_{}; 102 0 : Index<Dim> source_extents_; 103 0 : std::array<Matrix, Dim> interpolation_matrices_; 104 : }; 105 : 106 : template <size_t Dim> 107 : template <typename TagsList> 108 0 : void RegularGrid<Dim>::interpolate( 109 : const gsl::not_null<Variables<TagsList>*> result, 110 : const Variables<TagsList>& vars) const { 111 : if (result->number_of_grid_points() != number_of_target_points_) { 112 : result->initialize(number_of_target_points_); 113 : } 114 : apply_matrices(result, interpolation_matrices_, vars, source_extents_); 115 : } 116 : 117 : template <size_t Dim> 118 : template <typename TagsList> 119 : Variables<TagsList> RegularGrid<Dim>::interpolate( 120 : const Variables<TagsList>& vars) const { 121 : Variables<TagsList> result; 122 : interpolate(make_not_null(&result), vars); 123 : return result; 124 : } 125 : 126 : template <size_t Dim> 127 0 : bool operator!=(const RegularGrid<Dim>& lhs, const RegularGrid<Dim>& rhs); 128 : 129 : } // namespace intrp