diff --git a/docs/References.bib b/docs/References.bib index 644cc10e6fd6..02b048d421ff 100644 --- a/docs/References.bib +++ b/docs/References.bib @@ -2198,6 +2198,21 @@ @article{Shibata2003 url = "https://link.aps.org/doi/10.1103/PhysRevD.68.104020" } +@article{Shiokawa2011ih, + author = "Shiokawa, Hotaka and Dolence, Joshua C. and Gammie, Charles F. + and Noble, Scott C.", + title = "{Global GRMHD Simulations of Black Hole Accretion Flows: + a Convergence Study}", + eprint = "1111.0396", + archivePrefix = "arXiv", + primaryClass = "astro-ph.HE", + doi = "10.1088/0004-637X/744/2/187", + journal = "Astrophys. J.", + volume = "744", + pages = "187", + year = "2012" +} + @article{Shu1988439, title = "Efficient implementation of essentially non-oscillatory shock-capturing schemes", diff --git a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/CMakeLists.txt b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/CMakeLists.txt index 3ae01b6ef84d..1f5e5506c620 100644 --- a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/CMakeLists.txt +++ b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/CMakeLists.txt @@ -8,6 +8,7 @@ spectre_target_sources( DemandOutgoingCharSpeeds.cpp DirichletAnalytic.cpp HydroFreeOutflow.cpp + Reflective.cpp ) spectre_target_headers( @@ -19,4 +20,5 @@ spectre_target_headers( DirichletAnalytic.hpp Factory.hpp HydroFreeOutflow.hpp + Reflective.hpp ) diff --git a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Factory.hpp b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Factory.hpp index 5b7db2701acc..48561e5f7ad7 100644 --- a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Factory.hpp +++ b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Factory.hpp @@ -8,10 +8,12 @@ #include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/DemandOutgoingCharSpeeds.hpp" #include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/DirichletAnalytic.hpp" #include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/HydroFreeOutflow.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp" namespace grmhd::ValenciaDivClean::BoundaryConditions { /// Typelist of standard BoundaryConditions using standard_boundary_conditions = tmpl::list<DemandOutgoingCharSpeeds, DirichletAnalytic, HydroFreeOutflow, + Reflective, domain::BoundaryConditions::Periodic<BoundaryCondition>>; } // namespace grmhd::ValenciaDivClean::BoundaryConditions diff --git a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.cpp b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.cpp new file mode 100644 index 000000000000..c9cdfc546a6d --- /dev/null +++ b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.cpp @@ -0,0 +1,553 @@ +// Distributed under the MIT License. +// See LICENSE.txt for details. + +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp" + +#include <cstddef> +#include <memory> +#include <optional> +#include <pup.h> + +#include "DataStructures/DataVector.hpp" +#include "DataStructures/Index.hpp" +#include "DataStructures/SliceVariables.hpp" +#include "DataStructures/Tags/TempTensor.hpp" +#include "DataStructures/Tensor/EagerMath/DeterminantAndInverse.hpp" +#include "DataStructures/Tensor/EagerMath/DotProduct.hpp" +#include "DataStructures/Tensor/EagerMath/RaiseOrLowerIndex.hpp" +#include "DataStructures/Tensor/Expressions/Evaluate.hpp" +#include "DataStructures/Tensor/Expressions/TensorExpression.hpp" +#include "DataStructures/Tensor/Tensor.hpp" +#include "DataStructures/Variables.hpp" +#include "Domain/Structure/Direction.hpp" +#include "Evolution/DgSubcell/SliceTensor.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/ConservativeFromPrimitive.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/FiniteDifference/Reconstructor.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/Fluxes.hpp" +#include "NumericalAlgorithms/Spectral/Mesh.hpp" +#include "PointwiseFunctions/Hydro/LorentzFactor.hpp" +#include "PointwiseFunctions/Hydro/Tags.hpp" +#include "Utilities/Gsl.hpp" + +namespace grmhd::ValenciaDivClean::BoundaryConditions { + +Reflective::Reflective(bool reflect_both) : reflect_both_(reflect_both) {} + +Reflective::Reflective(CkMigrateMessage* const msg) : BoundaryCondition(msg) {} + +std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> +Reflective::get_clone() const { + return std::make_unique<Reflective>(*this); +} + +void Reflective::pup(PUP::er& p) { + BoundaryCondition::pup(p); + p | reflect_both_; +} + +// NOLINTNEXTLINE +PUP::able::PUP_ID Reflective::my_PUP_ID = 0; + +std::optional<std::string> Reflective::dg_ghost( + const gsl::not_null<Scalar<DataVector>*> tilde_d, + const gsl::not_null<Scalar<DataVector>*> tilde_ye, + const gsl::not_null<Scalar<DataVector>*> tilde_tau, + const gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*> tilde_s, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_b, + const gsl::not_null<Scalar<DataVector>*> tilde_phi, + + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_d_flux, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_ye_flux, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + tilde_tau_flux, + const gsl::not_null<tnsr::Ij<DataVector, 3, Frame::Inertial>*> tilde_s_flux, + const gsl::not_null<tnsr::IJ<DataVector, 3, Frame::Inertial>*> tilde_b_flux, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + tilde_phi_flux, + + const gsl::not_null<Scalar<DataVector>*> lapse, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift, + const gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*> + inv_spatial_metric, + + const std::optional<tnsr::I<DataVector, 3, Frame::Inertial>>& + /*face_mesh_velocity*/, + const tnsr::i<DataVector, 3, Frame::Inertial>& + outward_directed_normal_covector, + const tnsr::I<DataVector, 3, Frame::Inertial>& + outward_directed_normal_vector, + + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_specific_internal_energy, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + const Scalar<DataVector>& interior_lorentz_factor, + const Scalar<DataVector>& interior_pressure, + + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + const Scalar<DataVector>& interior_lapse, + const tnsr::II<DataVector, 3, Frame::Inertial>& interior_inv_spatial_metric) + const { + const size_t number_of_grid_points = get(interior_rest_mass_density).size(); + + // temp buffer to store + // * n_i v^i + // * v_{ghost}^i + // * n_i B^i + // * B_{ghost}^i + // * divergence cleaning field on ghost zone + // * spatial metric + // * sqrt determinant of spatial metric + Variables<tmpl::list< + ::Tags::TempScalar<0>, hydro::Tags::SpatialVelocity<DataVector, 3>, + ::Tags::TempScalar<1>, hydro::Tags::MagneticField<DataVector, 3>, + ::Tags::TempScalar<2>, gr::Tags::SpatialMetric<DataVector, 3>, + gr::Tags::SqrtDetSpatialMetric<DataVector>>> + temp_buffer{number_of_grid_points}; + auto& normal_dot_interior_spatial_velocity = + get<::Tags::TempScalar<0>>(temp_buffer); + auto& exterior_spatial_velocity = + get<hydro::Tags::SpatialVelocity<DataVector, 3>>(temp_buffer); + auto& normal_dot_interior_magnetic_field = + get<::Tags::TempScalar<1>>(temp_buffer); + auto& exterior_magnetic_field = + get<hydro::Tags::MagneticField<DataVector, 3>>(temp_buffer); + auto& exterior_divergence_cleaning_field = + get<::Tags::TempScalar<2>>(temp_buffer); + auto& interior_spatial_metric = + get<gr::Tags::SpatialMetric<DataVector, 3>>(temp_buffer); + auto& interior_sqrt_det_spatial_metric = + get<gr::Tags::SqrtDetSpatialMetric<DataVector>>(temp_buffer); + + get(*lapse) = get(interior_lapse); + for (size_t i = 0; i < 3; ++i) { + (*shift).get(i) = interior_shift.get(i); + for (size_t j = 0; j < 3; ++j) { + (*inv_spatial_metric).get(i, j) = interior_inv_spatial_metric.get(i, j); + } + } + + // spatial metric and sqrt determinant of spatial metric can be retrived from + // Databox but only as gridless_tags with whole volume data (unlike all the + // other arguments which are face tensors). Rather than doing expensive tensor + // slicing operations on those, we just compute those two quantities from + // inverse spatial metric as below. + determinant_and_inverse(make_not_null(&interior_sqrt_det_spatial_metric), + make_not_null(&interior_spatial_metric), + interior_inv_spatial_metric); + get(interior_sqrt_det_spatial_metric) = + 1.0 / sqrt(get(interior_sqrt_det_spatial_metric)); + + // copy-paste interior spatial velocity to exterior spatial velocity, but + // kill ingoing normal component to zero + dot_product(make_not_null(&normal_dot_interior_spatial_velocity), + outward_directed_normal_covector, interior_spatial_velocity); + dot_product(make_not_null(&normal_dot_interior_magnetic_field), + outward_directed_normal_covector, interior_magnetic_field); + + // reflect both outward and inward normal components of + // spatial velocity and magnetic field. + if (reflect_both_) { + for (size_t i = 0; i < number_of_grid_points; ++i) { + if (get(normal_dot_interior_spatial_velocity)[i] > 0.0) { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_spatial_velocity.get(spatial_index)[i] = + interior_spatial_velocity.get(spatial_index)[i] - + 2.0 * get(normal_dot_interior_spatial_velocity)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } else { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_spatial_velocity.get(spatial_index)[i] = + interior_spatial_velocity.get(spatial_index)[i] + + 2.0 * get(normal_dot_interior_spatial_velocity)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } + if (get(normal_dot_interior_magnetic_field)[i] > 0.0) { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_magnetic_field.get(spatial_index)[i] = + interior_magnetic_field.get(spatial_index)[i] - + 2.0 * get(normal_dot_interior_magnetic_field)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } else { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_magnetic_field.get(spatial_index)[i] = + interior_magnetic_field.get(spatial_index)[i] + + 2.0 * get(normal_dot_interior_magnetic_field)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } + } + } + + // reflect only the outward normal component of + // spatial velocity and magnetic field. + else { + for (size_t i = 0; i < number_of_grid_points; ++i) { + if (get(normal_dot_interior_spatial_velocity)[i] > 0.0) { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_spatial_velocity.get(spatial_index)[i] = + interior_spatial_velocity.get(spatial_index)[i] - + 2.0 * get(normal_dot_interior_spatial_velocity)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } else { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_spatial_velocity.get(spatial_index)[i] = + interior_spatial_velocity.get(spatial_index)[i]; + } + } + if (get(normal_dot_interior_magnetic_field)[i] > 0.0) { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_magnetic_field.get(spatial_index)[i] = + interior_magnetic_field.get(spatial_index)[i] - + 2.0 * get(normal_dot_interior_magnetic_field)[i] * + outward_directed_normal_vector.get(spatial_index)[i]; + } + } else { + for (size_t spatial_index = 0; spatial_index < 3; ++spatial_index) { + exterior_magnetic_field.get(spatial_index)[i] = + interior_magnetic_field.get(spatial_index)[i]; + } + } + } + } + get(exterior_divergence_cleaning_field) = 0.0; + + ConservativeFromPrimitive::apply( + tilde_d, tilde_ye, tilde_tau, tilde_s, tilde_b, tilde_phi, + interior_rest_mass_density, interior_electron_fraction, + interior_specific_internal_energy, interior_pressure, + exterior_spatial_velocity, interior_lorentz_factor, + exterior_magnetic_field, interior_sqrt_det_spatial_metric, + interior_spatial_metric, exterior_divergence_cleaning_field); + + ComputeFluxes::apply(tilde_d_flux, tilde_ye_flux, tilde_tau_flux, + tilde_s_flux, tilde_b_flux, tilde_phi_flux, *tilde_d, + *tilde_ye, *tilde_tau, *tilde_s, *tilde_b, *tilde_phi, + *lapse, *shift, interior_sqrt_det_spatial_metric, + interior_spatial_metric, *inv_spatial_metric, + interior_pressure, exterior_spatial_velocity, + interior_lorentz_factor, exterior_magnetic_field); + + return {}; +} + +void Reflective::fd_ghost( + const gsl::not_null<Scalar<DataVector>*> rest_mass_density, + const gsl::not_null<Scalar<DataVector>*> electron_fraction, + const gsl::not_null<Scalar<DataVector>*> temperature, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + lorentz_factor_times_spatial_velocity, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + magnetic_field, + const gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field, + + const gsl::not_null<std::optional<Variables<db::wrap_tags_in< + Flux, typename grmhd::ValenciaDivClean::System::flux_variables>>>*> + cell_centered_ghost_fluxes, + + const Direction<3>& direction, + + // fd_interior_temporary_tags + const Mesh<3>& subcell_mesh, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + const Scalar<DataVector>& interior_lapse, + const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric, + + // fd_interior_primitive_variables_tags + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_temperature, + const Scalar<DataVector>& interior_pressure, + const Scalar<DataVector>& interior_specific_internal_energy, + const Scalar<DataVector>& interior_lorentz_factor, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + + // fd_gridless_tags + const fd::Reconstructor& reconstructor) const { + Variables<tmpl::push_back<typename System::variables_tag::tags_list, + SpatialVelocity, LorentzFactor, Pressure, + SpecificInternalEnergy, SqrtDetSpatialMetric, + SpatialMetric, InvSpatialMetric, Lapse, Shift>> + temp_vars{get(*rest_mass_density).size()}; + fd_ghost_impl(rest_mass_density, electron_fraction, temperature, + make_not_null(&get<Pressure>(temp_vars)), + make_not_null(&get<SpecificInternalEnergy>(temp_vars)), + lorentz_factor_times_spatial_velocity, + make_not_null(&get<SpatialVelocity>(temp_vars)), + make_not_null(&get<LorentzFactor>(temp_vars)), magnetic_field, + divergence_cleaning_field, + make_not_null(&get<SpatialMetric>(temp_vars)), + make_not_null(&get<InvSpatialMetric>(temp_vars)), + make_not_null(&get<SqrtDetSpatialMetric>(temp_vars)), + make_not_null(&get<Lapse>(temp_vars)), + make_not_null(&get<Shift>(temp_vars)), + + direction, + + // fd_interior_temporary_tags + subcell_mesh, + + // fd_interior_primitive_variables_tags + interior_rest_mass_density, interior_electron_fraction, + interior_temperature, interior_pressure, + interior_specific_internal_energy, interior_lorentz_factor, + interior_spatial_velocity, interior_magnetic_field, + interior_spatial_metric, interior_lapse, interior_shift, + + reconstructor.ghost_zone_size(), + + cell_centered_ghost_fluxes->has_value()); + if (cell_centered_ghost_fluxes->has_value()) { + ConservativeFromPrimitive::apply( + make_not_null(&get<Tags::TildeD>(temp_vars)), + make_not_null(&get<Tags::TildeYe>(temp_vars)), + make_not_null(&get<Tags::TildeTau>(temp_vars)), + make_not_null(&get<Tags::TildeS<>>(temp_vars)), + make_not_null(&get<Tags::TildeB<>>(temp_vars)), + make_not_null(&get<Tags::TildePhi>(temp_vars)), + + // Note: Only the spatial velocity changes. + *rest_mass_density, *electron_fraction, + get<SpecificInternalEnergy>(temp_vars), get<Pressure>(temp_vars), + get<SpatialVelocity>(temp_vars), get<LorentzFactor>(temp_vars), + *magnetic_field, + + get<SqrtDetSpatialMetric>(temp_vars), get<SpatialMetric>(temp_vars), + *divergence_cleaning_field); + + ComputeFluxes::apply( + make_not_null( + &get<Flux<Tags::TildeD>>(cell_centered_ghost_fluxes->value())), + make_not_null( + &get<Flux<Tags::TildeYe>>(cell_centered_ghost_fluxes->value())), + make_not_null( + &get<Flux<Tags::TildeTau>>(cell_centered_ghost_fluxes->value())), + make_not_null( + &get<Flux<Tags::TildeS<>>>(cell_centered_ghost_fluxes->value())), + make_not_null( + &get<Flux<Tags::TildeB<>>>(cell_centered_ghost_fluxes->value())), + make_not_null( + &get<Flux<Tags::TildePhi>>(cell_centered_ghost_fluxes->value())), + + get<Tags::TildeD>(temp_vars), get<Tags::TildeYe>(temp_vars), + get<Tags::TildeTau>(temp_vars), get<Tags::TildeS<>>(temp_vars), + get<Tags::TildeB<>>(temp_vars), get<Tags::TildePhi>(temp_vars), + + get<Lapse>(temp_vars), get<Shift>(temp_vars), + get<SqrtDetSpatialMetric>(temp_vars), get<SpatialMetric>(temp_vars), + get<InvSpatialMetric>(temp_vars), get<Pressure>(temp_vars), + get<SpatialVelocity>(temp_vars), get<LorentzFactor>(temp_vars), + *magnetic_field); + } +} + +void Reflective::fd_ghost_impl( + const gsl::not_null<Scalar<DataVector>*> rest_mass_density, + const gsl::not_null<Scalar<DataVector>*> electron_fraction, + const gsl::not_null<Scalar<DataVector>*> temperature, + const gsl::not_null<Scalar<DataVector>*> pressure, + const gsl::not_null<Scalar<DataVector>*> specific_internal_energy, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + lorentz_factor_times_spatial_velocity, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + spatial_velocity, + const gsl::not_null<Scalar<DataVector>*> lorentz_factor, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + magnetic_field, + const gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field, + const gsl::not_null<tnsr::ii<DataVector, 3, Frame::Inertial>*> + spatial_metric, + const gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*> + inv_spatial_metric, + const gsl::not_null<Scalar<DataVector>*> sqrt_det_spatial_metric, + const gsl::not_null<Scalar<DataVector>*> lapse, + const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift, + + const Direction<3>& direction, + + // fd_interior_temporary_tags + const Mesh<3>& subcell_mesh, + + // fd_interior_primitive_variables_tags + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_temperature, + const Scalar<DataVector>& interior_pressure, + const Scalar<DataVector>& interior_specific_internal_energy, + const Scalar<DataVector>& interior_lorentz_factor, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric, + const Scalar<DataVector>& interior_lapse, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + + const size_t ghost_zone_size, const bool need_tags_for_fluxes) const { + const size_t dim_direction{direction.dimension()}; + + const auto subcell_extents{subcell_mesh.extents()}; + const size_t num_face_pts{ + subcell_extents.slice_away(dim_direction).product()}; + + using prim_tags_without_cleaning_field = + tmpl::list<RestMassDensity, ElectronFraction, Temperature, + LorentzFactorTimesSpatialVelocity, MagneticField>; + + // Create a single large DV to reduce the number of Variables allocations + using fluxes_tags = + tmpl::list<Pressure, SpecificInternalEnergy, SpatialMetric, Lapse, Shift>; + const size_t buffer_size_for_fluxes = + need_tags_for_fluxes + ? Variables<fluxes_tags>::number_of_independent_components + : 0; + const size_t buffer_size_per_grid_pts = Variables< + prim_tags_without_cleaning_field>::number_of_independent_components; + DataVector buffer_for_vars{ + num_face_pts * ((1 + ghost_zone_size) * + (buffer_size_per_grid_pts + buffer_size_for_fluxes)), + 0.0}; + + // Assign two Variables object to the buffer + Variables<prim_tags_without_cleaning_field> outermost_prim_vars{ + buffer_for_vars.data(), num_face_pts * buffer_size_per_grid_pts}; + Variables<prim_tags_without_cleaning_field> ghost_prim_vars{ + outermost_prim_vars.data() + outermost_prim_vars.size(), + num_face_pts * buffer_size_per_grid_pts * ghost_zone_size}; + + // Slice values on the outermost grid points and store them to + // `outermost_prim_vars` + auto get_boundary_val = [&direction, &subcell_extents](auto volume_tensor) { + return evolution::dg::subcell::slice_tensor_for_subcell( + volume_tensor, subcell_extents, 1, direction, {}); + }; + + get<RestMassDensity>(outermost_prim_vars) = + get_boundary_val(interior_rest_mass_density); + get<ElectronFraction>(outermost_prim_vars) = + get_boundary_val(interior_electron_fraction); + get<Temperature>(outermost_prim_vars) = + get_boundary_val(interior_temperature); + + { + const auto normal_spatial_velocity_at_boundary = + get_boundary_val(interior_spatial_velocity).get(dim_direction); + // reflect both the outgoing and ingoing normal components of + // spatial velocity and the magnetic field. + if (reflect_both_) { + for (size_t i = 0; i < 3; ++i) { + if (i == dim_direction) { + get<LorentzFactorTimesSpatialVelocity>(outermost_prim_vars).get(i) = + -get(get_boundary_val(interior_lorentz_factor)) * + get_boundary_val(interior_spatial_velocity).get(i); + get<MagneticField>(outermost_prim_vars).get(i) = + -1.0 * get_boundary_val(interior_magnetic_field).get(i); + } else { + get<LorentzFactorTimesSpatialVelocity>(outermost_prim_vars).get(i) = + get(get_boundary_val(interior_lorentz_factor)) * + get_boundary_val(interior_spatial_velocity).get(i); + get<MagneticField>(outermost_prim_vars).get(i) = + get_boundary_val(interior_magnetic_field).get(i); + } + } + } + // reflect only the outgoing normal component of spatial + // velocity and the magnetic field. + else { + for (size_t i = 0; i < 3; ++i) { + if (i == dim_direction) { + if (direction.sign() > 0.0) { + get<LorentzFactorTimesSpatialVelocity>(outermost_prim_vars).get(i) = + get(get_boundary_val(interior_lorentz_factor)) * + min(normal_spatial_velocity_at_boundary, + -normal_spatial_velocity_at_boundary); + get<MagneticField>(outermost_prim_vars).get(i) = + min(get_boundary_val(interior_magnetic_field).get(i), + -1.0 * get_boundary_val(interior_magnetic_field).get(i)); + } else { + get<LorentzFactorTimesSpatialVelocity>(outermost_prim_vars).get(i) = + get(get_boundary_val(interior_lorentz_factor)) * + max(normal_spatial_velocity_at_boundary, + -normal_spatial_velocity_at_boundary); + get<MagneticField>(outermost_prim_vars).get(i) = + max(get_boundary_val(interior_magnetic_field).get(i), + -1.0 * get_boundary_val(interior_magnetic_field).get(i)); + } + } else { + get<LorentzFactorTimesSpatialVelocity>(outermost_prim_vars).get(i) = + get(get_boundary_val(interior_lorentz_factor)) * + get_boundary_val(interior_spatial_velocity).get(i); + get<MagneticField>(outermost_prim_vars).get(i) = + get_boundary_val(interior_magnetic_field).get(i); + } + } + } + } + + // Now copy `outermost_prim_vars` into each slices of `ghost_prim_vars`. + Index<3> ghost_data_extents = subcell_extents; + ghost_data_extents[dim_direction] = ghost_zone_size; + + for (size_t i_ghost = 0; i_ghost < ghost_zone_size; ++i_ghost) { + add_slice_to_data(make_not_null(&ghost_prim_vars), outermost_prim_vars, + ghost_data_extents, dim_direction, i_ghost); + } + + *rest_mass_density = get<RestMassDensity>(ghost_prim_vars); + *electron_fraction = get<ElectronFraction>(ghost_prim_vars); + *temperature = get<Temperature>(ghost_prim_vars); + *lorentz_factor_times_spatial_velocity = + get<LorentzFactorTimesSpatialVelocity>(ghost_prim_vars); + *magnetic_field = get<MagneticField>(ghost_prim_vars); + + // divergence cleaning scalar field is just set to zero in the ghost zone. + get(*divergence_cleaning_field) = 0.0; + + if (need_tags_for_fluxes) { + Variables<fluxes_tags> outermost_fluxes_vars{ + std::next(ghost_prim_vars.data(), + static_cast<std::ptrdiff_t>(ghost_prim_vars.size())), + num_face_pts * buffer_size_for_fluxes}; + Variables<fluxes_tags> ghost_fluxes_vars{ + std::next(outermost_fluxes_vars.data(), + static_cast<std::ptrdiff_t>(outermost_fluxes_vars.size())), + num_face_pts * buffer_size_for_fluxes * ghost_zone_size}; + + get<Pressure>(outermost_fluxes_vars) = get_boundary_val(interior_pressure); + get<SpecificInternalEnergy>(outermost_fluxes_vars) = + get_boundary_val(interior_specific_internal_energy); + get<SpatialMetric>(outermost_fluxes_vars) = + get_boundary_val(interior_spatial_metric); + get<Lapse>(outermost_fluxes_vars) = get_boundary_val(interior_lapse); + get<Shift>(outermost_fluxes_vars) = get_boundary_val(interior_shift); + + for (size_t i_ghost = 0; i_ghost < ghost_zone_size; ++i_ghost) { + add_slice_to_data(make_not_null(&ghost_fluxes_vars), + outermost_fluxes_vars, ghost_data_extents, + dim_direction, i_ghost); + } + // Need pressure for high-order finite difference + *pressure = get<Pressure>(ghost_fluxes_vars); + *specific_internal_energy = get<SpecificInternalEnergy>(ghost_fluxes_vars); + *spatial_metric = get<SpatialMetric>(ghost_fluxes_vars); + *lapse = get<Lapse>(ghost_fluxes_vars); + *shift = get<Shift>(ghost_fluxes_vars); + + determinant_and_inverse(sqrt_det_spatial_metric, inv_spatial_metric, + *spatial_metric); + get(*sqrt_det_spatial_metric) = sqrt(get(*sqrt_det_spatial_metric)); + tenex::evaluate( + lorentz_factor, + sqrt(1.0 + (*spatial_metric)(ti::i, ti::j) * + (*lorentz_factor_times_spatial_velocity)(ti::I) * + (*lorentz_factor_times_spatial_velocity)(ti::J))); + tenex::evaluate<ti::I>( + spatial_velocity, + (*lorentz_factor_times_spatial_velocity)(ti::I) / (*lorentz_factor)()); + } +} +} // namespace grmhd::ValenciaDivClean::BoundaryConditions diff --git a/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp new file mode 100644 index 000000000000..341eeb5298ed --- /dev/null +++ b/src/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp @@ -0,0 +1,271 @@ +// Distributed under the MIT License. +// See LICENSE.txt for details. + +#pragma once + +#include <memory> +#include <optional> +#include <pup.h> +#include <string> + +#include "DataStructures/DataBox/PrefixHelpers.hpp" +#include "DataStructures/DataBox/Prefixes.hpp" +#include "DataStructures/Tensor/TypeAliases.hpp" +#include "Domain/BoundaryConditions/BoundaryCondition.hpp" +#include "Evolution/BoundaryConditions/Type.hpp" +#include "Evolution/DgSubcell/Tags/Mesh.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/BoundaryCondition.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/FiniteDifference/Tag.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/System.hpp" +#include "Options/String.hpp" +#include "PointwiseFunctions/GeneralRelativity/Tags.hpp" +#include "PointwiseFunctions/Hydro/Tags.hpp" +#include "PointwiseFunctions/Hydro/Temperature.hpp" +#include "Utilities/TMPL.hpp" + +/// \cond +class DataVector; +template <size_t VolumeDim> +class Direction; +namespace gsl { +template <typename T> +class not_null; +} // namespace gsl +/// \endcond + +namespace grmhd::ValenciaDivClean::BoundaryConditions { +/*! + * \brief Apply "soft" reflective boundary condition as described in + * \cite Shiokawa2011ih. + * + * All primitive variables at the boundary are copied into ghost zone except : + * + * - If \f$n_iv^i \leq 0\f$ where \f$v^i\f$ is spatial velocity and \f$n_i\f$ + * is outward directed normal covector, copy the values of \f$v^i\f$ at the + * boundary to ghost zone. If \f$n_iv^i>0\f$, spatial velocity in the ghost zone + * is modified such that the sign of normal component is inverted at the + * interface i.e. \f$v_\text{ghost}^i = v^i - 2*(n_jv^j)n^i\f$. + * + * - If \f$n_iB^i \leq 0\f$ where \f$B^i\f$ is magnetic field and \f$n_i\f$ + * is outward directed normal covector, copy the values of \f$B^i\f$ at the + * boundary to ghost zone. If \f$n_iB^i>0\f$, magnetic field in the ghost zone + * is modified such that the sign of normal component is inverted at the + * interface i.e. \f$B_\text{ghost}^i = B^i - 2*(n_jB^j)n^i\f$. + * + * - If reflect_both is true, then spatial velocity and magnetic field are + * are inverted regardless of whether the normal component is pointing outward + * or inward. + * + * - However, regardless of whether the normal component of the spatial + * velocity $n_iv^i$ is pointing outward or inward, the lorentz factor \f$W\f$ + * is copied into ghost zone without any modification. + * + * - Divergence cleaning scalar field \f$\Phi\f$ is set to zero in ghost zone. + * + */ +class Reflective final : public BoundaryCondition { + private: + bool reflect_both_{false}; + + using RestMassDensity = hydro::Tags::RestMassDensity<DataVector>; + using ElectronFraction = hydro::Tags::ElectronFraction<DataVector>; + using Temperature = hydro::Tags::Temperature<DataVector>; + using Pressure = hydro::Tags::Pressure<DataVector>; + using LorentzFactorTimesSpatialVelocity = + hydro::Tags::LorentzFactorTimesSpatialVelocity<DataVector, 3>; + using MagneticField = hydro::Tags::MagneticField<DataVector, 3>; + using DivergenceCleaningField = + hydro::Tags::DivergenceCleaningField<DataVector>; + using SpecificInternalEnergy = + hydro::Tags::SpecificInternalEnergy<DataVector>; + using SpatialVelocity = hydro::Tags::SpatialVelocity<DataVector, 3>; + using LorentzFactor = hydro::Tags::LorentzFactor<DataVector>; + using SqrtDetSpatialMetric = gr::Tags::SqrtDetSpatialMetric<DataVector>; + using SpatialMetric = gr::Tags::SpatialMetric<DataVector, 3>; + using InvSpatialMetric = gr::Tags::InverseSpatialMetric<DataVector, 3>; + using Lapse = gr::Tags::Lapse<DataVector>; + using Shift = gr::Tags::Shift<DataVector, 3>; + + using prim_tags_for_reconstruction = + tmpl::list<RestMassDensity, ElectronFraction, Temperature, + LorentzFactorTimesSpatialVelocity, MagneticField, + DivergenceCleaningField>; + + template <typename T> + using Flux = ::Tags::Flux<T, tmpl::size_t<3>, Frame::Inertial>; + + public: + struct ReflectBoth { + using type = bool; + static constexpr Options::String help = { + "Reflect both outgoing and incoming normal component of " + "spatial velocity and magnetic field."}; + }; + using options = tmpl::list<ReflectBoth>; + static constexpr Options::String help{ + "Reflective boundary conditions, inverting the sign " + "of outgoing normal component of spatial velocity " + "and magnetic field."}; + + Reflective() = default; + Reflective(Reflective&&) = default; + Reflective& operator=(Reflective&&) = default; + Reflective(const Reflective&) = default; + Reflective& operator=(const Reflective&) = default; + ~Reflective() override = default; + + explicit Reflective(bool reflect_both); + + explicit Reflective(CkMigrateMessage* msg); + + WRAPPED_PUPable_decl_base_template( + domain::BoundaryConditions::BoundaryCondition, Reflective); + + auto get_clone() const -> std::unique_ptr< + domain::BoundaryConditions::BoundaryCondition> override; + + static constexpr evolution::BoundaryConditions::Type bc_type = + evolution::BoundaryConditions::Type::Ghost; + + void pup(PUP::er& p) override; + + using dg_interior_evolved_variables_tags = tmpl::list<>; + using dg_interior_primitive_variables_tags = + tmpl::list<hydro::Tags::RestMassDensity<DataVector>, + hydro::Tags::ElectronFraction<DataVector>, + hydro::Tags::SpecificInternalEnergy<DataVector>, + hydro::Tags::SpatialVelocity<DataVector, 3>, + hydro::Tags::MagneticField<DataVector, 3>, + hydro::Tags::LorentzFactor<DataVector>, + hydro::Tags::Pressure<DataVector>>; + using dg_interior_temporary_tags = tmpl::list<Shift, Lapse, InvSpatialMetric>; + using dg_gridless_tags = tmpl::list<>; + + std::optional<std::string> dg_ghost( + gsl::not_null<Scalar<DataVector>*> tilde_d, + gsl::not_null<Scalar<DataVector>*> tilde_ye, + gsl::not_null<Scalar<DataVector>*> tilde_tau, + gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*> tilde_s, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_b, + gsl::not_null<Scalar<DataVector>*> tilde_phi, + + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_d_flux, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_ye_flux, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_tau_flux, + gsl::not_null<tnsr::Ij<DataVector, 3, Frame::Inertial>*> tilde_s_flux, + gsl::not_null<tnsr::IJ<DataVector, 3, Frame::Inertial>*> tilde_b_flux, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_phi_flux, + + gsl::not_null<Scalar<DataVector>*> lapse, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift, + gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*> + inv_spatial_metric, + + const std::optional<tnsr::I<DataVector, 3, Frame::Inertial>>& + /*face_mesh_velocity*/, + const tnsr::i<DataVector, 3, Frame::Inertial>& + outward_directed_normal_covector, + const tnsr::I<DataVector, 3, Frame::Inertial>& + outward_directed_normal_vector, + + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_specific_internal_energy, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + const Scalar<DataVector>& interior_lorentz_factor, + const Scalar<DataVector>& interior_pressure, + + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + const Scalar<DataVector>& interior_lapse, + const tnsr::II<DataVector, 3, Frame::Inertial>& + interior_inv_spatial_metric) const; + + using fd_interior_evolved_variables_tags = tmpl::list<>; + using fd_interior_temporary_tags = + tmpl::list<evolution::dg::subcell::Tags::Mesh<3>, Shift, Lapse, + SpatialMetric>; + using fd_interior_primitive_variables_tags = + tmpl::list<RestMassDensity, ElectronFraction, Temperature, + hydro::Tags::Pressure<DataVector>, + hydro::Tags::SpecificInternalEnergy<DataVector>, + hydro::Tags::LorentzFactor<DataVector>, + hydro::Tags::SpatialVelocity<DataVector, 3>, MagneticField>; + + using fd_gridless_tags = tmpl::list<fd::Tags::Reconstructor>; + + void fd_ghost( + gsl::not_null<Scalar<DataVector>*> rest_mass_density, + gsl::not_null<Scalar<DataVector>*> electron_fraction, + gsl::not_null<Scalar<DataVector>*> temperature, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + lorentz_factor_times_spatial_velocity, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field, + gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field, + + gsl::not_null<std::optional<Variables<db::wrap_tags_in< + Flux, typename grmhd::ValenciaDivClean::System::flux_variables>>>*> + cell_centered_ghost_fluxes, + + const Direction<3>& direction, + + // interior temporary tags + const Mesh<3>& subcell_mesh, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + const Scalar<DataVector>& interior_lapse, + const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric, + + // interior prim vars tags + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_temperature, + const Scalar<DataVector>& interior_pressure, + const Scalar<DataVector>& interior_specific_internal_energy, + const Scalar<DataVector>& interior_lorentz_factor, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + + // gridless tags + const fd::Reconstructor& reconstructor) const; + + // have an impl to make sharing code with GH+GRMHD easy + void fd_ghost_impl( + gsl::not_null<Scalar<DataVector>*> rest_mass_density, + gsl::not_null<Scalar<DataVector>*> electron_fraction, + gsl::not_null<Scalar<DataVector>*> temperature, + gsl::not_null<Scalar<DataVector>*> pressure, + gsl::not_null<Scalar<DataVector>*> specific_internal_energy, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> + lorentz_factor_times_spatial_velocity, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> spatial_velocity, + gsl::not_null<Scalar<DataVector>*> lorentz_factor, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> magnetic_field, + gsl::not_null<Scalar<DataVector>*> divergence_cleaning_field, + gsl::not_null<tnsr::ii<DataVector, 3, Frame::Inertial>*> spatial_metric, + gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*> + inv_spatial_metric, + gsl::not_null<Scalar<DataVector>*> sqrt_det_spatial_metric, + gsl::not_null<Scalar<DataVector>*> lapse, + gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift, + + const Direction<3>& direction, + + // fd_interior_temporary_tags + const Mesh<3>& subcell_mesh, + + // fd_interior_primitive_variables_tags + const Scalar<DataVector>& interior_rest_mass_density, + const Scalar<DataVector>& interior_electron_fraction, + const Scalar<DataVector>& interior_temperature, + const Scalar<DataVector>& interior_pressure, + const Scalar<DataVector>& interior_specific_internal_energy, + const Scalar<DataVector>& interior_lorentz_factor, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_spatial_velocity, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_magnetic_field, + const tnsr::ii<DataVector, 3, Frame::Inertial>& interior_spatial_metric, + const Scalar<DataVector>& interior_lapse, + const tnsr::I<DataVector, 3, Frame::Inertial>& interior_shift, + + size_t ghost_zone_size, bool need_tags_for_fluxes) const; + }; +} // namespace grmhd::ValenciaDivClean::BoundaryConditions diff --git a/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.py b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.py new file mode 100644 index 000000000000..494da7f2580d --- /dev/null +++ b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.py @@ -0,0 +1,934 @@ +# Distributed under the MIT License. +# See LICENSE.txt for details. + +import Evolution.Systems.GrMhd.ValenciaDivClean.Fluxes as fluxes +import Evolution.Systems.GrMhd.ValenciaDivClean.TestFunctions as cons +import numpy as np + + +def _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, +): + dot_interior_spatial_velocity = np.dot( + outward_directed_normal_covector, interior_spatial_velocity + ) + + if reflect_both: + return np.where( + dot_interior_spatial_velocity > 0.0, + interior_spatial_velocity + - 2 + * outward_directed_normal_vector + * dot_interior_spatial_velocity, + interior_spatial_velocity + + 2 + * outward_directed_normal_vector + * dot_interior_spatial_velocity, + ) + + else: + return np.where( + dot_interior_spatial_velocity > 0.0, + interior_spatial_velocity + - 2 + * outward_directed_normal_vector + * dot_interior_spatial_velocity, + interior_spatial_velocity, + ) + + +def _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, +): + dot_interior_magnetic_field = np.dot( + outward_directed_normal_covector, interior_magnetic_field + ) + if reflect_both: + return np.where( + dot_interior_magnetic_field > 0.0, + interior_magnetic_field + - 2 * outward_directed_normal_vector * dot_interior_magnetic_field, + interior_magnetic_field + + 2 * outward_directed_normal_vector * dot_interior_magnetic_field, + ) + else: + return np.where( + dot_interior_magnetic_field > 0.0, + interior_magnetic_field + - 2 * outward_directed_normal_vector * dot_interior_magnetic_field, + interior_magnetic_field, + ) + + +def _spatial_metric(inv_spatial_metric): + return np.linalg.inv(inv_spatial_metric) + + +def error( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + return None + + +def tilde_d( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_d( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def tilde_ye( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_ye( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def tilde_tau( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_tau( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def tilde_s( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_s( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def tilde_b( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_b( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def tilde_phi( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + return cons.tilde_phi( + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + sqrt_det_spatial_metric, + spatial_metric, + 0.0, + ) + + +def _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + return { + "tilde_d": tilde_d( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + "tilde_ye": tilde_ye( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + "tilde_tau": tilde_tau( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + "tilde_s": tilde_s( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + "tilde_b": tilde_b( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + "tilde_phi": tilde_phi( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ), + } + + +def flux_tilde_d( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_d_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def flux_tilde_ye( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_ye_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def flux_tilde_tau( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_tau_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def flux_tilde_s( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_s_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def flux_tilde_b( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_b_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def flux_tilde_phi( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + exterior_spatial_velocity = _exterior_spatial_velocity( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_spatial_velocity, + reflect_both, + ) + exterior_magnetic_field = _exterior_magnetic_field( + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_magnetic_field, + reflect_both, + ) + spatial_metric = _spatial_metric(inv_spatial_metric) + sqrt_det_spatial_metric = np.sqrt(np.linalg.det(spatial_metric)) + + cons_vars = _return_cons_vars( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, + ) + + return fluxes.tilde_phi_flux( + cons_vars["tilde_d"], + cons_vars["tilde_ye"], + cons_vars["tilde_tau"], + cons_vars["tilde_s"], + cons_vars["tilde_b"], + cons_vars["tilde_phi"], + lapse, + shift, + sqrt_det_spatial_metric, + spatial_metric, + inv_spatial_metric, + interior_pressure, + exterior_spatial_velocity, + interior_lorentz_factor, + exterior_magnetic_field, + ) + + +def lapse( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + return lapse + + +def shift( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + return shift + + +def inv_spatial_metric( + face_mesh_velocity, + outward_directed_normal_covector, + outward_directed_normal_vector, + interior_rest_mass_density, + interior_electron_fraction, + interior_specific_internal_energy, + interior_spatial_velocity, + interior_magnetic_field, + interior_lorentz_factor, + interior_pressure, + shift, + lapse, + inv_spatial_metric, + reflect_both, +): + return inv_spatial_metric diff --git a/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Test_Reflective.cpp b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Test_Reflective.cpp new file mode 100644 index 000000000000..44efaa0ac264 --- /dev/null +++ b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Test_Reflective.cpp @@ -0,0 +1,118 @@ +// Distributed under the MIT License. +// See LICENSE.txt for details. + +#include "Framework/TestingFramework.hpp" + +#include <array> + +#include "DataStructures/DataBox/DataBox.hpp" +#include "DataStructures/DataVector.hpp" +#include "DataStructures/Index.hpp" +#include "DataStructures/Tensor/EagerMath/Determinant.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/BoundaryCondition.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Reflective.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryCorrections/Rusanov.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/System.hpp" +#include "Evolution/Systems/GrMhd/ValenciaDivClean/Tags.hpp" +#include "Framework/SetupLocalPythonEnvironment.hpp" +#include "Framework/TestHelpers.hpp" +#include "Helpers/DataStructures/MakeWithRandomValues.hpp" +#include "Helpers/Evolution/DiscontinuousGalerkin/BoundaryConditions.hpp" +#include "Helpers/PointwiseFunctions/GeneralRelativity/TestHelpers.hpp" +#include "Utilities/Gsl.hpp" +#include "Utilities/TMPL.hpp" +#include "Utilities/TaggedTuple.hpp" + +namespace helpers = ::TestHelpers::evolution::dg; +namespace { +void test_stuffs(const bool reflect_both) { + MAKE_GENERATOR(gen); + + const auto face_mesh_index = Index<2>{2}; + const DataVector used_for_size{face_mesh_index.product()}; + std::uniform_real_distribution<> dist(0.5, 1.0); + + const auto spatial_metric = + ::TestHelpers::gr::random_spatial_metric<3, DataVector, Frame::Inertial>( + make_not_null(&gen), used_for_size); + const auto sqrt_det_spatial_metric = determinant(spatial_metric); + + struct ReflectBoth : db::SimpleTag { + using type = bool; + }; + + const auto box_with_gridless_tags = + db::create<db::AddSimpleTags<gr::Tags::SpatialMetric<DataVector, 3>, + gr::Tags::SqrtDetSpatialMetric<DataVector>, + ReflectBoth>>( + spatial_metric, sqrt_det_spatial_metric, reflect_both); + + // for factory string + const std::string reflect_both_str = (reflect_both) ? "true" : "false"; + + helpers::test_boundary_condition_with_python< + grmhd::ValenciaDivClean::BoundaryConditions::Reflective, + grmhd::ValenciaDivClean::BoundaryConditions::BoundaryCondition, + grmhd::ValenciaDivClean::System, + tmpl::list<grmhd::ValenciaDivClean::BoundaryCorrections::Rusanov>, + tmpl::list<>, tmpl::list<ReflectBoth>>( + make_not_null(&gen), + "Evolution.Systems.GrMhd.ValenciaDivClean.BoundaryConditions." + "Reflective", + tuples::TaggedTuple< + helpers::Tags::PythonFunctionForErrorMessage<>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildeD>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildeYe>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildeTau>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildeS<Frame::Inertial>>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildeB<Frame::Inertial>>, + helpers::Tags::PythonFunctionName< + grmhd::ValenciaDivClean::Tags::TildePhi>, + + helpers::Tags::PythonFunctionName< + ::Tags::Flux<grmhd::ValenciaDivClean::Tags::TildeD, + tmpl::size_t<3>, Frame::Inertial>>, + helpers::Tags::PythonFunctionName< + ::Tags::Flux<grmhd::ValenciaDivClean::Tags::TildeYe, + tmpl::size_t<3>, Frame::Inertial>>, + helpers::Tags::PythonFunctionName< + ::Tags::Flux<grmhd::ValenciaDivClean::Tags::TildeTau, + tmpl::size_t<3>, Frame::Inertial>>, + helpers::Tags::PythonFunctionName<::Tags::Flux< + grmhd::ValenciaDivClean::Tags::TildeS<Frame::Inertial>, + tmpl::size_t<3>, Frame::Inertial>>, + helpers::Tags::PythonFunctionName<::Tags::Flux< + grmhd::ValenciaDivClean::Tags::TildeB<Frame::Inertial>, + tmpl::size_t<3>, Frame::Inertial>>, + helpers::Tags::PythonFunctionName< + ::Tags::Flux<grmhd::ValenciaDivClean::Tags::TildePhi, + tmpl::size_t<3>, Frame::Inertial>>, + + helpers::Tags::PythonFunctionName<gr::Tags::Lapse<DataVector>>, + helpers::Tags::PythonFunctionName<gr::Tags::Shift<DataVector, 3>>, + helpers::Tags::PythonFunctionName< + gr::Tags::InverseSpatialMetric<DataVector, 3>>>{ + "error", "tilde_d", "tilde_ye", "tilde_tau", "tilde_s", "tilde_b", + "tilde_phi", "flux_tilde_d", "flux_tilde_ye", "flux_tilde_tau", + "flux_tilde_s", "flux_tilde_b", "flux_tilde_phi", "lapse", "shift", + "inv_spatial_metric"}, + "Reflective:\n" + " ReflectBoth: " + + reflect_both_str + "\n", + face_mesh_index, box_with_gridless_tags, tuples::TaggedTuple<>{}, + 1.0e-10); +} +} // namespace + +SPECTRE_TEST_CASE("Unit.GrMhd.BoundaryConditions.Reflective", "[Unit][GrMhd]") { + pypp::SetupLocalPythonEnvironment local_python_env{""}; + // Test for two cases of Reflective.reflect_both + + test_stuffs(true); + test_stuffs(false); +} diff --git a/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/CMakeLists.txt b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/CMakeLists.txt index f9dfb390f259..3f1bd89f0d5d 100644 --- a/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/CMakeLists.txt +++ b/tests/Unit/Evolution/Systems/GrMhd/ValenciaDivClean/CMakeLists.txt @@ -9,6 +9,7 @@ set(LIBRARY_SOURCES BoundaryConditions/Test_DemandOutgoingCharSpeeds.cpp BoundaryConditions/Test_HydroFreeOutflow.cpp BoundaryConditions/Test_Periodic.cpp + BoundaryConditions/Test_Reflective.cpp BoundaryCorrections/Test_Hll.cpp BoundaryCorrections/Test_Rusanov.cpp FiniteDifference/Test_BoundaryConditionGhostData.cpp