Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include "DataStructures/Tensor/TypeAliases.hpp" 7 : #include "DataStructures/Variables.hpp" 8 : #include "Evolution/Systems/ScalarWave/Tags.hpp" 9 : #include "NumericalAlgorithms/TensorYlm/ApplyFilter.hpp" 10 : #include "NumericalAlgorithms/TensorYlm/Filter.hpp" 11 : #include "NumericalAlgorithms/TensorYlm/TensorYlm.hpp" 12 : #include "Utilities/Gsl.hpp" 13 : 14 : /// \cond 15 : class DataVector; 16 : namespace ylm { 17 : class Spherepack; 18 : } // namespace ylm 19 : /// \endcond 20 : 21 : namespace ylm::TensorYlm { 22 : 23 : /// Defines tags and functions used internally in filtering, but 24 : /// tested independently in the unit tests. 25 : namespace filter_detail { 26 : 27 : /// Variables list for the ScalarWave evolved fields, parameterized by \p Frame. 28 : template <typename Frame> 29 : using sw_vars_list = tmpl::list<::ScalarWave::Tags::Psi, ::ScalarWave::Tags::Pi, 30 : ::ScalarWave::Tags::Phi<3, Frame>>; 31 : 32 : /*! 33 : * \brief Transforms spatial tensors into a different frame, ignoring hessians. 34 : * 35 : * This is done for filtering, where having the correct (i.e. with hessians) 36 : * transformation doesn't matter; all that matters is that the tensor 37 : * indices correspond to the coordinates (or in other words, no dual frame). 38 : * 39 : * Assumes that all the variables have lower indices. 40 : * 41 : * Takes special care to re-use memory. The Variables arguments must 42 : * already be allocated to their correct sizes; no memory allocation 43 : * is done. 44 : * 45 : * \tparam SrcFrame Source frame. 46 : * \tparam DestFrame Destination frame. 47 : * \param dest A Variables for the destination spatial variables. 48 : * \param src A Variables containing the source spatial variables. 49 : * \param jac The jacobian dx^src/dx^dest 50 : */ 51 : template <typename SrcFrame, typename DestFrame> 52 : void transform_spatial_tensors_to_different_frame_without_hessians( 53 : gsl::not_null<Variables<sw_vars_list<DestFrame>>*> dest, 54 : const Variables<sw_vars_list<SrcFrame>>& src, 55 : const InverseJacobian<DataVector, 3, SrcFrame, DestFrame>& jac); 56 : 57 : } // namespace filter_detail 58 : 59 : /*! 60 : * \brief Applies TensorYlm filter in place to Scalar Wave variables. 61 : * 62 : * When radial_extents is 1, sw_vars and temp_storage are assumed to 63 : * be defined on a spherical slice, with number of grid points 64 : * corresponding to a spherical-harmonic grid of ell_max, and the 65 : * filter happens only on that slice. 66 : * 67 : * When radial_extents is > 1, sw_vars and temp_storage are assumed to 68 : * be defined on a spherical shell of topology I1 x S2. The filter 69 : * happens in the entire volume, internally iterating over each 70 : * spherical slice at a time. 71 : * 72 : * For performance reasons, apply_tensor_ylm_filter does not allocate 73 : * or deallocate memory, but it does take a temp_storage buffer. The 74 : * size of temp_storage should at least 75 : * radial_extents*spectral_size*num_components, where num_components 76 : * is the total number of independent components in the SW variable 77 : * list (i.e. 5), and spectral_size is the size of the S2 Spherepack 78 : * spectral coefficient array for ell_max, as obtained from the member 79 : * function ylm::Spherepack::spectral_size(). Note that for S2 on 80 : * Spherepack, the number of collocation points is different than the 81 : * number of spectral coefficients, and both are different than the 82 : * size of the Spherepack storage array. 83 : * 84 : * \param sw_vars ScalarWave variables in the inertial frame 85 : * (`sw_vars_list<Frame::Inertial>`). Internally, \f$\Phi_i\f$ is 86 : * frame-transformed to the grid frame before filtering and transformed back 87 : * afterward; `sw_vars` is updated in-place and remains in the inertial frame 88 : * on exit. 89 : * \param temp_storage Temporary storage for scalar wave variables, 90 : * allocated outside apply_tensor_ylm_filter. See above for size requirements. 91 : * \param jac_inertial_to_grid Jacobian taking V_x from inertial to grid. 92 : * \param jac_grid_to_inertial Jacobian taking V_x from grid to inertial. 93 : * \param filter_matrices The bundle of filter matrices computed by 94 : * fill_filter. Only the `scalar` and `i` members are used here. 95 : * \param ell_max The maximum ylm ell. 96 : * \param radial_extents The number of radial grid points, can be 1 for slices. 97 : */ 98 : template <> 99 1 : void apply_tensor_ylm_filter( 100 : gsl::not_null<Variables<filter_detail::sw_vars_list<Frame::Inertial>>*> 101 : sw_vars, 102 : gsl::not_null<Variables<filter_detail::sw_vars_list<Frame::Inertial>>*> 103 : temp_storage, 104 : const InverseJacobian<DataVector, 3, Frame::Inertial, Frame::Grid>& 105 : jac_inertial_to_grid, 106 : const InverseJacobian<DataVector, 3, Frame::Grid, Frame::Inertial>& 107 : jac_grid_to_inertial, 108 : const FilterMatrixHolder& filter_matrices, size_t ell_max, 109 : size_t radial_extents); 110 : 111 : } // namespace ylm::TensorYlm