SpECTRE Documentation Coverage Report
Current view: top level - NumericalAlgorithms/Interpolation - InterpolateOnSphericalShell.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 50.0 % 2 1
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <algorithm>
       7              : #include <array>
       8              : #include <cmath>
       9              : #include <cstddef>
      10              : 
      11              : #include "DataStructures/ApplyMatrices.hpp"
      12              : #include "DataStructures/DataVector.hpp"
      13              : #include "DataStructures/Matrix.hpp"
      14              : #include "DataStructures/Tensor/Tensor.hpp"
      15              : #include "DataStructures/Variables.hpp"
      16              : #include "NumericalAlgorithms/Interpolation/IrregularInterpolant.hpp"
      17              : #include "NumericalAlgorithms/Spectral/Basis.hpp"
      18              : #include "NumericalAlgorithms/Spectral/InterpolationMatrix.hpp"
      19              : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
      20              : #include "Utilities/ErrorHandling/Assert.hpp"
      21              : #include "Utilities/Gsl.hpp"
      22              : 
      23              : namespace intrp {
      24              : namespace InterpolateOnSphericalShell_detail {
      25              : // Target points whose radial logical coordinates differ by at most this much
      26              : // from the first point of a group are interpolated together. This absorbs the
      27              : // roundoff in the logical coordinates of points at the same radius.
      28              : constexpr double radial_coordinate_tolerance = 1.0e-12;
      29              : }  // namespace InterpolateOnSphericalShell_detail
      30              : 
      31              : /*!
      32              :  * \brief Interpolates `vars` on a spherical-harmonic shell `mesh` to the
      33              :  * `target_points`, first in the radial dimension and then in the angular
      34              :  * dimensions.
      35              :  *
      36              :  * Consecutive target points whose radial logical coordinates agree with that of
      37              :  * the first point of the group to within a tolerance share the
      38              :  * radial interpolation, which leaves an interpolation on the sphere with
      39              :  * `intrp::Irregular<2>`. This is much cheaper than `intrp::Irregular<3>` when
      40              :  * the target points lie on a few spheres of constant radial logical coordinate.
      41              :  */
      42              : template <typename TagsList>
      43            1 : Variables<TagsList> interpolate_on_spherical_shell(
      44              :     const Variables<TagsList>& vars, const Mesh<3>& mesh,
      45              :     const tnsr::I<DataVector, 3, Frame::ElementLogical>& target_points) {
      46              :   ASSERT((mesh.basis(0) == Spectral::Basis::Legendre or
      47              :           mesh.basis(0) == Spectral::Basis::Chebyshev) and
      48              :              mesh.basis(1) == Spectral::Basis::SphericalHarmonic and
      49              :              mesh.basis(2) == Spectral::Basis::SphericalHarmonic,
      50              :          "Expected a spherical-harmonic shell, but the mesh is " << mesh);
      51              :   ASSERT(vars.number_of_grid_points() == mesh.number_of_grid_points(),
      52              :          "The mesh has " << mesh.number_of_grid_points()
      53              :                          << " grid points but the variables have "
      54              :                          << vars.number_of_grid_points() << ".");
      55              :   const size_t number_of_target_points = get<0>(target_points).size();
      56              :   Variables<TagsList> result(number_of_target_points);
      57              :   const Mesh<1> radial_mesh = mesh.slice_through(0);
      58              :   const Mesh<2> angular_mesh = mesh.slice_away(0);
      59              :   size_t begin = 0;
      60              :   while (begin < number_of_target_points) {
      61              :     const double radial_coord = get<0>(target_points)[begin];
      62              :     size_t end = begin + 1;
      63              :     while (
      64              :         end < number_of_target_points and
      65              :         std::abs(get<0>(target_points)[end] - radial_coord) <=
      66              :             InterpolateOnSphericalShell_detail::radial_coordinate_tolerance) {
      67              :       ++end;
      68              :     }
      69              :     const size_t group_size = end - begin;
      70              :     // Interpolate radially to the sphere of the group
      71              :     const Variables<TagsList> vars_on_sphere = apply_matrices(
      72              :         std::array<Matrix, 3>{{Spectral::interpolation_matrix(
      73              :                                    radial_mesh, DataVector{1, radial_coord}),
      74              :                                Matrix{}, Matrix{}}},
      75              :         vars, mesh.extents());
      76              :     // Then on the sphere to the angular coordinates of the group
      77              :     const tnsr::I<DataVector, 2, Frame::ElementLogical> angular_points{};
      78              :     for (size_t d = 0; d < 2; ++d) {
      79              :       make_const_view(make_not_null(&angular_points.get(d)),
      80              :                       target_points.get(d + 1), begin, group_size);
      81              :     }
      82              :     const Variables<TagsList> result_on_sphere =
      83              :         intrp::Irregular<2>(angular_mesh, angular_points)
      84              :             .interpolate(vars_on_sphere);
      85              :     for (size_t component = 0;
      86              :          component < result.number_of_independent_components; ++component) {
      87              :       std::copy_n(result_on_sphere.data() + component * group_size, group_size,
      88              :                   result.data() + component * number_of_target_points + begin);
      89              :     }
      90              :     begin = end;
      91              :   }
      92              :   return result;
      93              : }
      94              : }  // namespace intrp
        

Generated by: LCOV version 2.0-1