Skip to content

Commit a6e10d1

Browse files
Update subcell projection to work with ZernikeB1 bases
ZernikeB1 bases, used with Cartoon, require the parity of the component to be known as the interpolation requires this to be sufficiently accurate. When the projection is of a DataVector, it must either be a single component with the parity passed as an argument, or the underlying tmpl::list to types that make up the DataVector must be passed as a template. The GrMhd systems are updated to correctly call the projection, while all other systems are simply updated to work with the new interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5cee5da commit a6e10d1

32 files changed

Lines changed: 1262 additions & 227 deletions

src/Evolution/DgSubcell/Actions/ReconstructionCommunication.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "Evolution/DgSubcell/CombineVolumeGhostData.hpp"
3535
#include "Evolution/DgSubcell/GhostData.hpp"
3636
#include "Evolution/DgSubcell/NeighborRdmpAndVolumeData.hpp"
37+
#include "Evolution/DgSubcell/NeighborRdmpAndVolumeData.tpp"
3738
#include "Evolution/DgSubcell/Projection.hpp"
3839
#include "Evolution/DgSubcell/RdmpTci.hpp"
3940
#include "Evolution/DgSubcell/RdmpTciData.hpp"
@@ -803,7 +804,9 @@ struct ReceiveDataForReconstruction {
803804
*boundary_data.ghost_cell_data, number_of_rdmp_vars,
804805
directional_element_id,
805806
mesh_for_ghost_data->at(directional_element_id), element,
806-
subcell_mesh, ghost_zone_size, neighbor_dg_to_fd_interpolants);
807+
subcell_mesh, ghost_zone_size, neighbor_dg_to_fd_interpolants,
808+
tmpl::list<typename Metavariables::SubcellOptions::
809+
GhostVariables::ghost_variables_tag_list>{});
807810
ASSERT(neighbor_tci_decisions->contains(directional_element_id),
808811
"The NeighorTciDecisions should contain the neighbor ("
809812
<< directional_element_id.direction() << ", "

src/Evolution/DgSubcell/Actions/TciAndRollback.hpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "Evolution/DgSubcell/ActiveGrid.hpp"
2828
#include "Evolution/DgSubcell/GhostData.hpp"
2929
#include "Evolution/DgSubcell/NeighborRdmpAndVolumeData.hpp"
30+
#include "Evolution/DgSubcell/NeighborRdmpAndVolumeData.tpp"
3031
#include "Evolution/DgSubcell/Projection.hpp"
3132
#include "Evolution/DgSubcell/RdmpTci.hpp"
3233
#include "Evolution/DgSubcell/RdmpTciData.hpp"
@@ -247,12 +248,14 @@ struct TciAndRollback {
247248
for (const auto& [directional_element_id, mesh_for_ghost_data] :
248249
meshes_for_ghost_data) {
249250
evolution::dg::subcell::insert_or_update_neighbor_volume_data<
250-
false>(ghost_data_ptr,
251-
ghost_data_ptr->at(directional_element_id)
252-
.neighbor_ghost_data_for_reconstruction(),
253-
0, directional_element_id, mesh_for_ghost_data, element,
254-
subcell_mesh, ghost_zone_size,
255-
neighbor_dg_to_fd_interpolants);
251+
false>(
252+
ghost_data_ptr,
253+
ghost_data_ptr->at(directional_element_id)
254+
.neighbor_ghost_data_for_reconstruction(),
255+
0, directional_element_id, mesh_for_ghost_data, element,
256+
subcell_mesh, ghost_zone_size, neighbor_dg_to_fd_interpolants,
257+
tmpl::list<typename Metavariables::SubcellOptions::
258+
GhostVariables::ghost_variables_tag_list>{});
256259
}
257260

258261
// Note: We do _not_ project the boundary history here because

src/Evolution/DgSubcell/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ spectre_target_headers(
2727
Matrices.hpp
2828
Mesh.hpp
2929
NeighborRdmpAndVolumeData.hpp
30+
NeighborRdmpAndVolumeData.tpp
3031
NeighborReconstructedFaceSolution.hpp
3132
NeighborReconstructedFaceSolution.tpp
3233
NeighborTciDecision.hpp
@@ -59,7 +60,6 @@ spectre_target_sources(
5960
InitialTciData.cpp
6061
Matrices.cpp
6162
Mesh.cpp
62-
NeighborRdmpAndVolumeData.cpp
6363
NeighborTciDecision.cpp
6464
PerssonTci.cpp
6565
Projection.cpp

src/Evolution/DgSubcell/CellCenteredFlux.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "Evolution/DgSubcell/Tags/Mesh.hpp"
1919
#include "Evolution/DgSubcell/Tags/SubcellOptions.hpp"
2020
#include "NumericalAlgorithms/Spectral/Mesh.hpp"
21+
#include "NumericalAlgorithms/Spectral/Parity.hpp"
2122
#include "Utilities/Gsl.hpp"
2223
#include "Utilities/TMPL.hpp"
2324

@@ -74,7 +75,8 @@ struct CellCenteredFlux {
7475
const DataVector& cell_centered_mesh_velocity =
7576
evolution::dg::subcell::fd::project(
7677
dg_mesh_velocity.value().get(i), dg_mesh,
77-
subcell_mesh.extents());
78+
subcell_mesh.extents(),
79+
i == 0 ? Spectral::Parity::Odd : Spectral::Parity::Even);
7880

7981
tmpl::for_each<flux_variables>(
8082
[&cell_centered_flux_vars, &cell_centered_mesh_velocity,

src/Evolution/DgSubcell/CorrectPackagedData.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ void correct_package_data(
122122
projected_data = DataVector{
123123
Variables<DgPackageFieldTags>::number_of_independent_components *
124124
subcell_face_mesh.number_of_grid_points()};
125-
evolution::dg::subcell::fd::detail::project_impl(
125+
evolution::dg::subcell::fd::detail::project_impl_with_tag_list<
126+
DgPackageFieldTags>(
126127
gsl::make_span(projected_data.data(), projected_data.size()),
127128
gsl::make_span(
128129
slice_data,

src/Evolution/DgSubcell/Matrices.cpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "NumericalAlgorithms/Spectral/MaximumNumberOfPoints.hpp"
2020
#include "NumericalAlgorithms/Spectral/Mesh.hpp"
2121
#include "NumericalAlgorithms/Spectral/MinimumNumberOfPoints.hpp"
22+
#include "NumericalAlgorithms/Spectral/Parity.hpp"
2223
#include "NumericalAlgorithms/Spectral/Quadrature.hpp"
2324
#include "NumericalAlgorithms/Spectral/QuadratureWeights.hpp"
2425
#include "Utilities/Algorithm.hpp"
@@ -31,12 +32,15 @@
3132
#include "Utilities/StaticCache.hpp"
3233

3334
namespace evolution::dg::subcell::fd {
34-
const Matrix& projection_matrix(
35-
const Mesh<1>& dg_mesh, const size_t subcell_extents,
36-
const Spectral::Quadrature& subcell_quadrature) {
35+
const Matrix& projection_matrix(const Mesh<1>& dg_mesh,
36+
const size_t subcell_extents,
37+
const Spectral::Quadrature& subcell_quadrature,
38+
const Spectral::Parity parity) {
3739
ASSERT(dg_mesh.basis(0) == Spectral::Basis::Legendre or
38-
dg_mesh.basis(0) == Spectral::Basis::Cartoon,
39-
"FD Subcell projection only supports Legendre or Cartoon bases right "
40+
dg_mesh.basis(0) == Spectral::Basis::Cartoon or
41+
dg_mesh.basis(0) == Spectral::Basis::ZernikeB1,
42+
"FD Subcell projection only supports Legendre, Cartoon, or ZernikeB1 "
43+
"bases right "
4044
"now but got basis "
4145
<< dg_mesh.basis(0));
4246
ASSERT(subcell_quadrature == Spectral::Quadrature::FaceCentered or
@@ -46,7 +50,39 @@ const Matrix& projection_matrix(
4650
"subcell_quadrature option in projection_matrix should be "
4751
"FaceCentered, CellCentered, or a Cartoon quadrature, but got "
4852
<< subcell_quadrature);
49-
static const auto cache = make_static_cache<
53+
ASSERT(dg_mesh.basis(0) != Spectral::Basis::ZernikeB1 or
54+
parity != Spectral::Parity::Uninitialized,
55+
"Parity must be set when using ZernikeB1");
56+
57+
const static auto zernike_b1_cache = make_static_cache<
58+
CacheRange<
59+
Spectral::minimum_number_of_points<
60+
Spectral::Basis::ZernikeB1,
61+
Spectral::Quadrature::GaussRadauUpper>,
62+
Spectral::maximum_number_of_points<Spectral::Basis::ZernikeB1> + 1>,
63+
CacheRange<Spectral::minimum_number_of_points<
64+
Spectral::Basis::FiniteDifference,
65+
Spectral::Quadrature::CellCentered>,
66+
Spectral::maximum_number_of_points<
67+
Spectral::Basis::FiniteDifference> +
68+
1>,
69+
CacheEnumeration<Spectral::Quadrature, Spectral::Quadrature::CellCentered,
70+
Spectral::Quadrature::FaceCentered>,
71+
CacheEnumeration<Spectral::Parity, Spectral::Parity::Even,
72+
Spectral::Parity::Odd>>(
73+
[](const size_t local_num_dg_points, const size_t local_num_fd_points,
74+
const Spectral::Quadrature local_subcell_quadrature,
75+
const Spectral::Parity local_parity) {
76+
return Spectral::interpolation_matrix<
77+
Spectral::Basis::ZernikeB1, Spectral::Quadrature::GaussRadauUpper>(
78+
local_num_dg_points,
79+
Spectral::collocation_points(
80+
Mesh<1>{local_num_fd_points, Spectral::Basis::FiniteDifference,
81+
local_subcell_quadrature}),
82+
local_parity);
83+
});
84+
85+
const static auto legendre_cache = make_static_cache<
5086
CacheRange<
5187
Spectral::minimum_number_of_points<
5288
Spectral::Basis::Legendre, Spectral::Quadrature::GaussLobatto>,
@@ -74,9 +110,13 @@ const Matrix& projection_matrix(
74110
if (dg_mesh.basis(0) == Spectral::Basis::Cartoon) {
75111
static const Matrix cartoon_matrix{1, 1, 1.0};
76112
return cartoon_matrix;
113+
} else if (dg_mesh.basis(0) == Spectral::Basis::ZernikeB1) {
114+
return zernike_b1_cache(dg_mesh.extents(0), subcell_extents,
115+
subcell_quadrature, parity);
116+
} else {
117+
return legendre_cache(dg_mesh.extents(0), subcell_extents,
118+
dg_mesh.quadrature(0), subcell_quadrature);
77119
}
78-
return cache(dg_mesh.extents(0), subcell_extents, dg_mesh.quadrature(0),
79-
subcell_quadrature);
80120
}
81121

82122
namespace {

src/Evolution/DgSubcell/Matrices.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ template <size_t Dim>
1414
class Mesh;
1515
enum class Side : uint8_t;
1616
namespace Spectral {
17+
enum class Parity : uint8_t;
1718
enum class Quadrature : uint8_t;
1819
} // namespace Spectral
1920
/// \endcond
@@ -23,9 +24,12 @@ namespace evolution::dg::subcell::fd {
2324
* \ingroup DgSubcellGroup
2425
* \brief Computes the projection matrix in 1 dimension going from a DG
2526
* mesh to a conservative finite difference subcell mesh.
27+
*
28+
* The parity parameter is required for ZernikeB1 bases.
2629
*/
2730
const Matrix& projection_matrix(const Mesh<1>& dg_mesh, size_t subcell_extents,
28-
const Spectral::Quadrature& subcell_quadrature);
31+
const Spectral::Quadrature& subcell_quadrature,
32+
Spectral::Parity parity);
2933

3034
/*!
3135
* \ingroup DgSubcellGroup
@@ -95,4 +99,4 @@ const Matrix& reconstruction_matrix(const Mesh<Dim>& dg_mesh,
9599
*/
96100
const Matrix& projection_matrix(const Mesh<1>& dg_mesh, size_t subcell_extents,
97101
size_t ghost_zone_size, Side side);
98-
} // namespace evolution::dg::subcellfd
102+
} // namespace evolution::dg::subcell::fd

src/Evolution/DgSubcell/NeighborRdmpAndVolumeData.hpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "Evolution/DgSubcell/RdmpTciData.hpp"
1616
#include "NumericalAlgorithms/Interpolation/IrregularInterpolant.hpp"
1717
#include "Utilities/Gsl.hpp"
18+
#include "Utilities/TMPL.hpp"
1819

1920
/// \cond
2021
template <size_t Dim>
@@ -31,25 +32,34 @@ namespace evolution::dg::subcell {
3132
*
3233
* This is intended to be used during a rollback from DG to make sure neighbor
3334
* data is projected to the FD grid.
35+
*
36+
* The `tmpl::list<VolumeFields>` meta parameter encodes the tag list of the
37+
* packed ghost DataVector so that per-component parity information can be
38+
* deduced for ZernikeB1 meshes.
3439
*/
35-
template <bool InsertIntoMap, size_t Dim>
40+
template <bool InsertIntoMap, size_t Dim, typename VolumeFields>
3641
void insert_or_update_neighbor_volume_data(
3742
gsl::not_null<DirectionalIdMap<Dim, GhostData>*> ghost_data_ptr,
3843
const DataVector& neighbor_subcell_data,
39-
const size_t number_of_rdmp_vars_in_buffer,
44+
size_t number_of_rdmp_vars_in_buffer,
4045
const DirectionalId<Dim>& directional_element_id,
4146
const Mesh<Dim>& neighbor_mesh, const Element<Dim>& element,
4247
const Mesh<Dim>& subcell_mesh, size_t number_of_ghost_zones,
4348
const DirectionalIdMap<Dim, std::optional<intrp::Irregular<Dim>>>&
44-
Neighbor_dg_to_fd_interpolants);
49+
neighbor_dg_to_fd_interpolants,
50+
tmpl::list<VolumeFields> /*meta*/);
4551

4652
/*!
4753
* \brief Check whether the neighbor sent is DG volume or FD ghost data, and
4854
* orient project DG volume data if necessary.
4955
*
5056
* This is intended to be used by the `ReceiveDataForReconstruction` action.
57+
*
58+
* The `tmpl::list<VolumeFields>` meta parameter encodes the tag list of the
59+
* packed ghost DataVector so that per-component parity information can be
60+
* deduced for ZernikeB1 meshes.
5161
*/
52-
template <size_t Dim>
62+
template <size_t Dim, typename VolumeFields>
5363
void insert_neighbor_rdmp_and_volume_data(
5464
gsl::not_null<RdmpTciData*> rdmp_tci_data_ptr,
5565
gsl::not_null<DirectionalIdMap<Dim, GhostData>*> ghost_data_ptr,
@@ -59,5 +69,6 @@ void insert_neighbor_rdmp_and_volume_data(
5969
const Mesh<Dim>& neighbor_mesh, const Element<Dim>& element,
6070
const Mesh<Dim>& subcell_mesh, size_t number_of_ghost_zones,
6171
const DirectionalIdMap<Dim, std::optional<intrp::Irregular<Dim>>>&
62-
neighbor_dg_to_fd_interpolants);
72+
neighbor_dg_to_fd_interpolants,
73+
tmpl::list<VolumeFields> /*meta*/);
6374
} // namespace evolution::dg::subcell

0 commit comments

Comments
 (0)