SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/GrMhd/GhValenciaDivClean/BoundaryConditions - ProductOfConditions.hpp Hit Total Coverage
Commit: e93d8312de4f331d36b5aa00ea83a894e26dfcb7 Lines: 1 35 2.9 %
Date: 2021-09-24 22:40:29
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 <cstddef>
       7             : #include <memory>
       8             : #include <optional>
       9             : #include <pup.h>
      10             : #include <string>
      11             : #include <utility>
      12             : 
      13             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      14             : #include "DataStructures/DataVector.hpp"
      15             : #include "DataStructures/Tensor/Tensor.hpp"
      16             : #include "Evolution/BoundaryConditions/Type.hpp"
      17             : #include "Evolution/DiscontinuousGalerkin/Actions/ComputeTimeDerivativeHelpers.hpp"
      18             : #include "Evolution/Systems/GeneralizedHarmonic/BoundaryConditions/Factory.hpp"
      19             : #include "Evolution/Systems/GeneralizedHarmonic/System.hpp"
      20             : #include "Evolution/Systems/GrMhd/GhValenciaDivClean/BoundaryConditions/BoundaryCondition.hpp"
      21             : #include "Evolution/Systems/GrMhd/GhValenciaDivClean/Tags.hpp"
      22             : #include "Evolution/Systems/GrMhd/ValenciaDivClean/BoundaryConditions/Factory.hpp"
      23             : #include "Evolution/Systems/GrMhd/ValenciaDivClean/System.hpp"
      24             : #include "NumericalAlgorithms/DiscontinuousGalerkin/Formulation.hpp"
      25             : #include "Options/Options.hpp"
      26             : #include "Parallel/CharmPupable.hpp"
      27             : #include "PointwiseFunctions/GeneralRelativity/Lapse.hpp"
      28             : #include "PointwiseFunctions/GeneralRelativity/Shift.hpp"
      29             : #include "PointwiseFunctions/GeneralRelativity/SpatialMetric.hpp"
      30             : #include "Utilities/Gsl.hpp"
      31             : #include "Utilities/TMPL.hpp"
      32             : #include "Utilities/TaggedTuple.hpp"
      33             : 
      34             : namespace grmhd::GhValenciaDivClean::BoundaryConditions {
      35             : namespace detail {
      36             : template <evolution::BoundaryConditions::Type GhBcType,
      37             :           evolution::BoundaryConditions::Type ValenciaBcType>
      38             : struct UnionOfBcTypes {
      39             :   static constexpr evolution::BoundaryConditions::Type bc_type =
      40             :       evolution::BoundaryConditions::Type::GhostAndTimeDerivative;
      41             : };
      42             : 
      43             : template <>
      44             : struct UnionOfBcTypes<evolution::BoundaryConditions::Type::Ghost,
      45             :                       evolution::BoundaryConditions::Type::Ghost> {
      46             :   static constexpr evolution::BoundaryConditions::Type bc_type =
      47             :       evolution::BoundaryConditions::Type::Ghost;
      48             : };
      49             : 
      50             : template <>
      51             : struct UnionOfBcTypes<evolution::BoundaryConditions::Type::TimeDerivative,
      52             :                       evolution::BoundaryConditions::Type::TimeDerivative> {
      53             :   static constexpr evolution::BoundaryConditions::Type bc_type =
      54             :       evolution::BoundaryConditions::Type::TimeDerivative;
      55             : };
      56             : 
      57             : template <evolution::BoundaryConditions::Type GhBcType>
      58             : struct UnionOfBcTypes<GhBcType, evolution::BoundaryConditions::Type::Outflow> {
      59             :   static_assert(GhBcType == evolution::BoundaryConditions::Type::Outflow,
      60             :                 "If either boundary condition in `ProductOfConditions` has "
      61             :                 "`Type::Outflow`, both must have `Type::Outflow`");
      62             : };
      63             : 
      64             : template <evolution::BoundaryConditions::Type ValenciaBcType>
      65             : struct UnionOfBcTypes<evolution::BoundaryConditions::Type::Outflow,
      66             :                       ValenciaBcType> {
      67             :   static_assert(ValenciaBcType == evolution::BoundaryConditions::Type::Outflow,
      68             :                 "If either boundary condition in `ProductOfConditions` has "
      69             :                 "`Type::Outflow`, both must have `Type::Outflow`");
      70             : };
      71             : 
      72             : template <>
      73             : struct UnionOfBcTypes<evolution::BoundaryConditions::Type::Outflow,
      74             :                       evolution::BoundaryConditions::Type::Outflow> {
      75             :   static constexpr evolution::BoundaryConditions::Type bc_type =
      76             :       evolution::BoundaryConditions::Type::Outflow;
      77             : };
      78             : 
      79             : struct ValenciaDoNothingGhostCondition {
      80             :   using dg_interior_evolved_variables_tags =
      81             :       typename grmhd::ValenciaDivClean::System::variables_tag::tags_list;
      82             : 
      83             :   using dg_interior_temporary_tags = tmpl::push_back<
      84             :       db::wrap_tags_in<::Tags::Flux,
      85             :                        typename grmhd::ValenciaDivClean::System::flux_variables,
      86             :                        tmpl::size_t<3_st>, Frame::Inertial>,
      87             :       gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>>;
      88             : 
      89             :   std::optional<std::string> dg_ghost(
      90             :       const gsl::not_null<Scalar<DataVector>*> tilde_d,
      91             :       const gsl::not_null<Scalar<DataVector>*> tilde_tau,
      92             :       const gsl::not_null<tnsr::i<DataVector, 3, Frame::Inertial>*> tilde_s,
      93             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> tilde_b,
      94             :       const gsl::not_null<Scalar<DataVector>*> tilde_phi,
      95             : 
      96             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
      97             :           tilde_d_flux,
      98             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
      99             :           tilde_tau_flux,
     100             :       const gsl::not_null<tnsr::Ij<DataVector, 3, Frame::Inertial>*>
     101             :           tilde_s_flux,
     102             :       const gsl::not_null<tnsr::IJ<DataVector, 3, Frame::Inertial>*>
     103             :           tilde_b_flux,
     104             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*>
     105             :           tilde_phi_flux,
     106             : 
     107             :       const gsl::not_null<Scalar<DataVector>*> lapse,
     108             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
     109             :       const gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
     110             :           inv_spatial_metric,
     111             : 
     112             :       const std::optional<
     113             :           tnsr::I<DataVector, 3, Frame::Inertial>>& /*face_mesh_velocity*/,
     114             :       const tnsr::i<DataVector, 3, Frame::Inertial>& /*normal_covector*/,
     115             :       const tnsr::I<DataVector, 3, Frame::Inertial>& /*normal_vector*/,
     116             : 
     117             :       const Scalar<DataVector>& interior_tilde_d,
     118             :       const Scalar<DataVector>& interior_tilde_tau,
     119             :       const tnsr::i<DataVector, 3, Frame::Inertial>& interior_tilde_s,
     120             :       const tnsr::I<DataVector, 3, Frame::Inertial>& interior_tilde_b,
     121             :       const Scalar<DataVector>& interior_tilde_phi,
     122             : 
     123             :       const tnsr::I<DataVector, 3, Frame::Inertial>& interior_tilde_d_flux,
     124             :       const tnsr::I<DataVector, 3, Frame::Inertial>& interior_tilde_tau_flux,
     125             :       const tnsr::Ij<DataVector, 3, Frame::Inertial>& interior_tilde_s_flux,
     126             :       const tnsr::IJ<DataVector, 3, Frame::Inertial>& interior_tilde_b_flux,
     127             :       const tnsr::I<DataVector, 3, Frame::Inertial>& interior_tilde_phi_flux,
     128             : 
     129             :       const tnsr::aa<DataVector, 3, Frame::Inertial>&
     130             :           interior_spacetime_metric) noexcept {
     131             :     *tilde_d = interior_tilde_d;
     132             :     *tilde_tau = interior_tilde_tau;
     133             :     *tilde_s = interior_tilde_s;
     134             :     *tilde_b = interior_tilde_b;
     135             :     *tilde_phi = interior_tilde_phi;
     136             : 
     137             :     *tilde_d_flux = interior_tilde_d_flux;
     138             :     *tilde_tau_flux = interior_tilde_tau_flux;
     139             :     *tilde_s_flux = interior_tilde_s_flux;
     140             :     *tilde_b_flux = interior_tilde_b_flux;
     141             :     *tilde_phi_flux = interior_tilde_phi_flux;
     142             : 
     143             :     const auto spatial_metric = gr::spatial_metric(interior_spacetime_metric);
     144             :     *inv_spatial_metric = determinant_and_inverse(spatial_metric).second;
     145             :     gr::shift(shift, interior_spacetime_metric, *inv_spatial_metric);
     146             :     gr::lapse(lapse, *shift, interior_spacetime_metric);
     147             :     return {};
     148             :   }
     149             : };
     150             : 
     151             : struct GhDoNothingGhostCondition {
     152             :   using dg_interior_evolved_variables_tags =
     153             :       typename GeneralizedHarmonic::System<3_st>::variables_tag::tags_list;
     154             : 
     155             :   using dg_interior_temporary_tags = tmpl::list<
     156             :       ::GeneralizedHarmonic::ConstraintDamping::Tags::ConstraintGamma1,
     157             :       ::GeneralizedHarmonic::ConstraintDamping::Tags::ConstraintGamma2>;
     158             : 
     159             :   std::optional<std::string> dg_ghost(
     160             :       const gsl::not_null<tnsr::aa<DataVector, 3, Frame::Inertial>*>
     161             :           spacetime_metric,
     162             :       const gsl::not_null<tnsr::aa<DataVector, 3, Frame::Inertial>*> pi,
     163             :       const gsl::not_null<tnsr::iaa<DataVector, 3, Frame::Inertial>*> phi,
     164             :       const gsl::not_null<Scalar<DataVector>*> gamma1,
     165             :       const gsl::not_null<Scalar<DataVector>*> gamma2,
     166             :       const gsl::not_null<Scalar<DataVector>*> lapse,
     167             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
     168             :       const gsl::not_null<tnsr::II<DataVector, 3, Frame::Inertial>*>
     169             :           inv_spatial_metric,
     170             :       const std::optional<
     171             :           tnsr::I<DataVector, 3, Frame::Inertial>>& /*face_mesh_velocity*/,
     172             :       const tnsr::i<DataVector, 3, Frame::Inertial>& /*normal_covector*/,
     173             :       const tnsr::I<DataVector, 3, Frame::Inertial>& /*normal_vector*/,
     174             :       const tnsr::aa<DataVector, 3, Frame::Inertial>& interior_spacetime_metric,
     175             :       const tnsr::aa<DataVector, 3, Frame::Inertial>& interior_pi,
     176             :       const tnsr::iaa<DataVector, 3, Frame::Inertial>& interior_phi,
     177             :       const Scalar<DataVector>& interior_gamma1,
     178             :       const Scalar<DataVector>& interior_gamma2) noexcept {
     179             :     *gamma1 = interior_gamma1;
     180             :     *gamma2 = interior_gamma2;
     181             :     *spacetime_metric = interior_spacetime_metric;
     182             :     *pi = interior_pi;
     183             :     *phi = interior_phi;
     184             : 
     185             :     const auto spatial_metric = gr::spatial_metric(interior_spacetime_metric);
     186             :     *inv_spatial_metric = determinant_and_inverse(spatial_metric).second;
     187             :     gr::shift(shift, interior_spacetime_metric, *inv_spatial_metric);
     188             :     gr::lapse(lapse, *shift, interior_spacetime_metric);
     189             :     return {};
     190             :   }
     191             : };
     192             : 
     193             : // Implementation for expanding the combination of packs for full compatibility
     194             : // with all possible combination of tag lists that can be used for constructing
     195             : // `BoundaryCondition` structs.
     196             : template <
     197             :     typename DerivedGhCondition, typename DerivedValenciaCondition,
     198             :     typename GhEvolvedTagList, typename ValenciaEvolvedTagList,
     199             :     typename GhFluxTagList, typename ValenicaFluxTagList,
     200             :     typename GhInteriorEvolvedTagList, typename ValenciaInteriorEvolvedTagList,
     201             :     typename DeduplicatedInteriorEvolvedTagList,
     202             :     typename GhInteriorPrimitiveTagList, typename ValenciaInteriorPrimitiveTgs,
     203             :     typename GhInteriorTempTagList, typename ValenciaInteriorTempTagList,
     204             :     typename DeduplicatedTempTagList, typename GhInteriorDtTagList,
     205             :     typename ValenciaInteriorDtTagList, typename GhInteriorDerivTagList,
     206             :     typename ValenciaInteriorDerivTagList, typename GhGridlessTagList,
     207             :     typename ValenciaGridlessTagList, typename DeduplicatedGridlessTagList>
     208             : struct ProductOfConditionsImpl;
     209             : 
     210             : template <
     211             :     typename DerivedGhCondition, typename DerivedValenciaCondition,
     212             :     typename... GhEvolvedTags, typename... ValenciaEvolvedTags,
     213             :     typename... GhFluxTags, typename... ValenciaFluxTags,
     214             :     typename... GhInteriorEvolvedTags, typename... ValenciaInteriorEvolvedTags,
     215             :     typename... DeduplicatedInteriorEvolvedTags,
     216             :     typename... GhInteriorPrimitiveTags,
     217             :     typename... ValenciaInteriorPrimitiveTags, typename... GhInteriorTempTags,
     218             :     typename... ValenciaInteriorTempTags, typename... DeduplicatedTempTags,
     219             :     typename... GhInteriorDtTags, typename... ValenciaInteriorDtTags,
     220             :     typename... GhInteriorDerivTags, typename... ValenciaInteriorDerivTags,
     221             :     typename... GhGridlessTags, typename... ValenciaGridlessTags,
     222             :     typename... DeduplicatedGridlessTags>
     223             : struct ProductOfConditionsImpl<
     224             :     DerivedGhCondition, DerivedValenciaCondition, tmpl::list<GhEvolvedTags...>,
     225             :     tmpl::list<ValenciaEvolvedTags...>, tmpl::list<GhFluxTags...>,
     226             :     tmpl::list<ValenciaFluxTags...>, tmpl::list<GhInteriorEvolvedTags...>,
     227             :     tmpl::list<ValenciaInteriorEvolvedTags...>,
     228             :     tmpl::list<DeduplicatedInteriorEvolvedTags...>,
     229             :     tmpl::list<GhInteriorPrimitiveTags...>,
     230             :     tmpl::list<ValenciaInteriorPrimitiveTags...>,
     231             :     tmpl::list<GhInteriorTempTags...>, tmpl::list<ValenciaInteriorTempTags...>,
     232             :     tmpl::list<DeduplicatedTempTags...>, tmpl::list<GhInteriorDtTags...>,
     233             :     tmpl::list<ValenciaInteriorDtTags...>, tmpl::list<GhInteriorDerivTags...>,
     234             :     tmpl::list<ValenciaInteriorDerivTags...>, tmpl::list<GhGridlessTags...>,
     235             :     tmpl::list<ValenciaGridlessTags...>,
     236             :     tmpl::list<DeduplicatedGridlessTags...>> {
     237             :   // In the current setup, we aren't given type information about the possible
     238             :   // arguments to `BoundaryCorrection`s directly, so we just need to support all
     239             :   // possibilities of (GH BoundaryCorrection)x(Valencia BoundaryCorrection) with
     240             :   // explicit overloads of `dg_ghost`.
     241             :   // This can be solved with (more) template logic instead if in the future
     242             :   // `BoundaryCondition`s can supply stronger type constraints
     243             : 
     244             :   template <typename... GridlessVariables>
     245             :   static std::optional<std::string> dg_ghost(
     246             :       const DerivedGhCondition& gh_condition,
     247             :       const DerivedValenciaCondition& valencia_condition,
     248             : 
     249             :       const gsl::not_null<typename GhEvolvedTags::type*>... gh_variables,
     250             :       const gsl::not_null<
     251             :           typename ValenciaEvolvedTags::type*>... valencia_variables,
     252             : 
     253             :       const gsl::not_null<typename GhFluxTags::type*>... gh_fluxes,
     254             :       const gsl::not_null<typename ValenciaFluxTags::type*>... valencia_fluxes,
     255             : 
     256             :       const gsl::not_null<Scalar<DataVector>*> gamma1,
     257             :       const gsl::not_null<Scalar<DataVector>*> gamma2,
     258             :       const gsl::not_null<Scalar<DataVector>*> lapse,
     259             :       const gsl::not_null<tnsr::I<DataVector, 3, Frame::Inertial>*> shift,
     260             :       const gsl::not_null<tnsr::II<DataVector, 3_st, Frame::Inertial>*>
     261             :           inv_spatial_metric,
     262             :       const std::optional<tnsr::I<DataVector, 3_st, Frame::Inertial>>&
     263             :           face_mesh_velocity,
     264             :       const tnsr::i<DataVector, 3_st, Frame::Inertial>& normal_covector,
     265             :       const tnsr::I<DataVector, 3_st, Frame::Inertial>& normal_vector,
     266             : 
     267             :       const typename DeduplicatedInteriorEvolvedTags::
     268             :           type&... int_evolved_variables,
     269             : 
     270             :       const typename GhInteriorPrimitiveTags::type&... gh_int_prim_variables,
     271             :       const typename ValenciaInteriorPrimitiveTags::
     272             :           type&... valencia_int_prim_variables,
     273             : 
     274             :       const typename DeduplicatedTempTags::type&... temp_variables,
     275             : 
     276             :       const typename GhInteriorDtTags::type&... gh_int_dt_variables,
     277             :       const typename ValenciaInteriorDtTags::type&... valencia_int_dt_variables,
     278             : 
     279             :       const typename GhInteriorDerivTags::type&... gh_int_deriv_variables,
     280             :       const typename ValenciaInteriorDerivTags::
     281             :           type&... valencia_int_deriv_variables,
     282             : 
     283             :       const GridlessVariables&... gridless_variables) noexcept {
     284             :     using gridless_tags_and_types =
     285             :         tmpl::map<tmpl::pair<DeduplicatedGridlessTags, GridlessVariables>...>;
     286             : 
     287             :     tuples::TaggedTuple<
     288             :         Tags::detail::TemporaryReference<
     289             :             DeduplicatedGridlessTags,
     290             :             tmpl::at<gridless_tags_and_types, DeduplicatedGridlessTags>>...,
     291             :         Tags::detail::TemporaryReference<DeduplicatedTempTags>...,
     292             :         Tags::detail::TemporaryReference<DeduplicatedInteriorEvolvedTags>...>
     293             :         shuffle_refs{gridless_variables..., temp_variables...,
     294             :                      int_evolved_variables...};
     295             : 
     296             :     std::optional<std::string> gh_string{};
     297             :     if constexpr (DerivedGhCondition::bc_type ==
     298             :                       evolution::BoundaryConditions::Type::Ghost or
     299             :                   DerivedGhCondition::bc_type ==
     300             :                       evolution::BoundaryConditions::Type::
     301             :                           GhostAndTimeDerivative) {
     302             :       gh_string = gh_condition.dg_ghost(
     303             :           gh_variables..., gh_fluxes..., gamma1, gamma2, lapse, shift,
     304             :           inv_spatial_metric, face_mesh_velocity, normal_covector,
     305             :           normal_vector,
     306             :           tuples::get<Tags::detail::TemporaryReference<GhInteriorEvolvedTags>>(
     307             :               shuffle_refs)...,
     308             :           gh_int_prim_variables...,
     309             :           tuples::get<Tags::detail::TemporaryReference<GhInteriorTempTags>>(
     310             :               shuffle_refs)...,
     311             :           gh_int_dt_variables..., gh_int_deriv_variables...,
     312             :           tuples::get<Tags::detail::TemporaryReference<
     313             :               GhGridlessTags,
     314             :               tmpl::at<gridless_tags_and_types, GhGridlessTags>>>(
     315             :               shuffle_refs)...);
     316             :     } else {
     317             :       GhDoNothingGhostCondition{}.dg_ghost(
     318             :           gh_variables..., gh_fluxes..., gamma1, gamma2, lapse, shift,
     319             :           inv_spatial_metric, face_mesh_velocity, normal_covector,
     320             :           normal_vector,
     321             :           tuples::get<Tags::detail::TemporaryReference<GhEvolvedTags>>(
     322             :               shuffle_refs)...,
     323             :           tuples::get<Tags::detail::TemporaryReference<
     324             :               ::GeneralizedHarmonic::ConstraintDamping::Tags::
     325             :                   ConstraintGamma1>>(shuffle_refs),
     326             :           tuples::get<Tags::detail::TemporaryReference<
     327             :               ::GeneralizedHarmonic::ConstraintDamping::Tags::
     328             :                   ConstraintGamma2>>(shuffle_refs));
     329             :     }
     330             :     std::optional<std::string> valencia_string{};
     331             :     if constexpr (DerivedValenciaCondition::bc_type ==
     332             :                       evolution::BoundaryConditions::Type::Ghost or
     333             :                   DerivedValenciaCondition::bc_type ==
     334             :                       evolution::BoundaryConditions::Type::
     335             :                           GhostAndTimeDerivative) {
     336             :       valencia_string = valencia_condition.dg_ghost(
     337             :           valencia_variables..., valencia_fluxes..., lapse, shift,
     338             :           inv_spatial_metric, face_mesh_velocity, normal_covector,
     339             :           normal_vector,
     340             :           tuples::get<
     341             :               Tags::detail::TemporaryReference<ValenciaInteriorEvolvedTags>>(
     342             :               shuffle_refs)...,
     343             :           valencia_int_prim_variables...,
     344             :           tuples::get<
     345             :               Tags::detail::TemporaryReference<ValenciaInteriorTempTags>>(
     346             :               shuffle_refs)...,
     347             :           valencia_int_dt_variables..., valencia_int_deriv_variables...,
     348             :           tuples::get<Tags::detail::TemporaryReference<
     349             :               ValenciaGridlessTags,
     350             :               tmpl::at<gridless_tags_and_types, ValenciaGridlessTags>>>(
     351             :               shuffle_refs)...);
     352             :     } else {
     353             :       ValenciaDoNothingGhostCondition{}.dg_ghost(
     354             :           valencia_variables..., valencia_fluxes..., gamma1, gamma2, lapse,
     355             :           shift, inv_spatial_metric, face_mesh_velocity, normal_covector,
     356             :           normal_vector,
     357             :           tuples::get<Tags::detail::TemporaryReference<ValenciaEvolvedTags>>(
     358             :               shuffle_refs)...,
     359             :           tuples::get<Tags::detail::TemporaryReference<ValenciaFluxTags>>(
     360             :               shuffle_refs)...,
     361             :           tuples::get<Tags::detail::TemporaryReference<
     362             :               gr::Tags::SpacetimeMetric<3, Frame::Inertial, DataVector>>>(
     363             :               shuffle_refs));
     364             :     }
     365             :     if (not gh_string.has_value()) {
     366             :       return valencia_string;
     367             :     }
     368             :     if (not valencia_string.has_value()) {
     369             :       return gh_string;
     370             :     }
     371             :     return gh_string.value() + ";" + valencia_string.value();
     372             :   }
     373             : 
     374             :   template <typename... GridlessVariables>
     375             :   static std::optional<std::string> dg_outflow(
     376             :       const DerivedGhCondition& gh_condition,
     377             :       const DerivedValenciaCondition& valencia_condition,
     378             : 
     379             :       const std::optional<tnsr::I<DataVector, 3_st, Frame::Inertial>>&
     380             :           face_mesh_velocity,
     381             :       const tnsr::i<DataVector, 3_st, Frame::Inertial>& normal_covector,
     382             :       const tnsr::I<DataVector, 3_st, Frame::Inertial>& normal_vector,
     383             : 
     384             :       const typename DeduplicatedInteriorEvolvedTags::
     385             :           type&... int_evolved_variables,
     386             : 
     387             :       const typename GhInteriorPrimitiveTags::type&... gh_int_prim_variables,
     388             :       const typename ValenciaInteriorPrimitiveTags::
     389             :           type&... valencia_int_prim_variables,
     390             : 
     391             :       const typename DeduplicatedTempTags::type&... temp_variables,
     392             : 
     393             :       const typename GhInteriorDtTags::type&... gh_int_dt_variables,
     394             :       const typename ValenciaInteriorDtTags::type&... valencia_int_dt_variables,
     395             : 
     396             :       const typename GhInteriorDerivTags::type&... gh_int_deriv_variables,
     397             :       const typename ValenciaInteriorDerivTags::
     398             :           type&... valencia_int_deriv_variables,
     399             : 
     400             :       const GridlessVariables&... gridless_variables) noexcept {
     401             :     using gridless_tags_and_types =
     402             :         tmpl::map<tmpl::pair<DeduplicatedGridlessTags, GridlessVariables>...>;
     403             : 
     404             :     tuples::TaggedTuple<
     405             :         Tags::detail::TemporaryReference<
     406             :             DeduplicatedGridlessTags,
     407             :             tmpl::at<gridless_tags_and_types, DeduplicatedGridlessTags>>...,
     408             :         Tags::detail::TemporaryReference<DeduplicatedTempTags>...,
     409             :         Tags::detail::TemporaryReference<DeduplicatedInteriorEvolvedTags>...>
     410             :         shuffle_refs{gridless_variables..., temp_variables...,
     411             :                      int_evolved_variables...};
     412             :     // outflow condition is only valid if both boundary conditions are outflow,
     413             :     // so we directly apply both. A static_assert elsewhere is triggered if only
     414             :     // one boundary condition is outflow.
     415             :     auto gh_string = gh_condition.dg_outflow(
     416             :         face_mesh_velocity, normal_covector, normal_vector,
     417             :         tuples::get<Tags::detail::TemporaryReference<GhInteriorEvolvedTags>>(
     418             :             shuffle_refs)...,
     419             :         gh_int_prim_variables...,
     420             :         tuples::get<Tags::detail::TemporaryReference<GhInteriorTempTags>>(
     421             :             shuffle_refs)...,
     422             :         gh_int_dt_variables..., gh_int_deriv_variables...,
     423             :         tuples::get<Tags::detail::TemporaryReference<
     424             :             GhGridlessTags, tmpl::at<gridless_tags_and_types, GhGridlessTags>>>(
     425             :             shuffle_refs)...);
     426             :     auto valencia_string = valencia_condition.dg_outflow(
     427             :         face_mesh_velocity, normal_covector, normal_vector,
     428             :         tuples::get<
     429             :             Tags::detail::TemporaryReference<ValenciaInteriorEvolvedTags>>(
     430             :             shuffle_refs)...,
     431             :         valencia_int_prim_variables...,
     432             :         tuples::get<Tags::detail::TemporaryReference<ValenciaInteriorTempTags>>(
     433             :             shuffle_refs)...,
     434             :         valencia_int_dt_variables..., valencia_int_deriv_variables...,
     435             :         tuples::get<Tags::detail::TemporaryReference<
     436             :             ValenciaGridlessTags,
     437             :             tmpl::at<gridless_tags_and_types, ValenciaGridlessTags>>>(
     438             :             shuffle_refs)...);
     439             :     if (not gh_string.has_value()) {
     440             :       return valencia_string;
     441             :     }
     442             :     if (not valencia_string.has_value()) {
     443             :       return gh_string;
     444             :     }
     445             :     return gh_string.value() + ";" + valencia_string.value();
     446             :   }
     447             : 
     448             :   template <typename... GridlessVariables>
     449             :   static std::optional<std::string> dg_time_derivative(
     450             :       const DerivedGhCondition& gh_condition,
     451             :       const DerivedValenciaCondition& valencia_condition,
     452             : 
     453             :       const gsl::not_null<typename GhEvolvedTags::type*>... gh_dt_variables,
     454             :       const gsl::not_null<
     455             :           typename ValenciaEvolvedTags::type*>... valencia_dt_variables,
     456             : 
     457             :       const std::optional<tnsr::I<DataVector, 3_st, Frame::Inertial>>&
     458             :           face_mesh_velocity,
     459             :       const tnsr::i<DataVector, 3_st, Frame::Inertial>& normal_covector,
     460             :       const tnsr::I<DataVector, 3_st, Frame::Inertial>& normal_vector,
     461             : 
     462             :       const typename DeduplicatedInteriorEvolvedTags::
     463             :           type&... int_evolved_variables,
     464             : 
     465             :       const typename GhInteriorPrimitiveTags::type&... gh_int_prim_variables,
     466             :       const typename ValenciaInteriorPrimitiveTags::
     467             :           type&... valencia_int_prim_variables,
     468             : 
     469             :       const typename DeduplicatedTempTags::type&... temp_variables,
     470             : 
     471             :       const typename GhInteriorDtTags::type&... gh_int_dt_variables,
     472             :       const typename ValenciaInteriorDtTags::type&... valencia_int_dt_variables,
     473             : 
     474             :       const typename GhInteriorDerivTags::type&... gh_int_deriv_variables,
     475             :       const typename ValenciaInteriorDerivTags::
     476             :           type&... valencia_int_deriv_variables,
     477             : 
     478             :       const GridlessVariables&... gridless_variables) noexcept {
     479             :     using gridless_tags_and_types =
     480             :         tmpl::map<tmpl::pair<DeduplicatedGridlessTags, GridlessVariables>...>;
     481             : 
     482             :     tuples::TaggedTuple<
     483             :         Tags::detail::TemporaryReference<
     484             :             DeduplicatedGridlessTags,
     485             :             tmpl::at<gridless_tags_and_types, DeduplicatedGridlessTags>>...,
     486             :         Tags::detail::TemporaryReference<DeduplicatedTempTags>...,
     487             :         Tags::detail::TemporaryReference<DeduplicatedInteriorEvolvedTags>...>
     488             :         shuffle_refs{gridless_variables..., temp_variables...,
     489             :                      int_evolved_variables...};
     490             : 
     491             :     std::optional<std::string> gh_string{};
     492             :     if constexpr (DerivedGhCondition::bc_type ==
     493             :                       evolution::BoundaryConditions::Type::TimeDerivative or
     494             :                   DerivedGhCondition::bc_type ==
     495             :                       evolution::BoundaryConditions::Type::
     496             :                           GhostAndTimeDerivative) {
     497             :       gh_string = gh_condition.dg_time_derivative(
     498             :           gh_dt_variables..., face_mesh_velocity, normal_covector,
     499             :           normal_vector,
     500             :           tuples::get<Tags::detail::TemporaryReference<GhInteriorEvolvedTags>>(
     501             :               shuffle_refs)...,
     502             :           gh_int_prim_variables...,
     503             :           tuples::get<Tags::detail::TemporaryReference<GhInteriorTempTags>>(
     504             :               shuffle_refs)...,
     505             :           gh_int_dt_variables..., gh_int_deriv_variables...,
     506             :           tuples::get<Tags::detail::TemporaryReference<
     507             :               GhGridlessTags,
     508             :               tmpl::at<gridless_tags_and_types, GhGridlessTags>>>(
     509             :               shuffle_refs)...);
     510             :     }
     511             :     std::optional<std::string> valencia_string{};
     512             :     if constexpr (DerivedValenciaCondition::bc_type ==
     513             :                       evolution::BoundaryConditions::Type::TimeDerivative or
     514             :                   DerivedValenciaCondition::bc_type ==
     515             :                       evolution::BoundaryConditions::Type::
     516             :                           GhostAndTimeDerivative) {
     517             :       valencia_string = valencia_condition.dg_time_derivative(
     518             :           valencia_dt_variables..., face_mesh_velocity, normal_covector,
     519             :           normal_vector,
     520             :           tuples::get<
     521             :               Tags::detail::TemporaryReference<ValenciaInteriorEvolvedTags>>(
     522             :               shuffle_refs)...,
     523             :           valencia_int_prim_variables...,
     524             :           tuples::get<
     525             :               Tags::detail::TemporaryReference<ValenciaInteriorTempTags>>(
     526             :               shuffle_refs)...,
     527             :           valencia_int_dt_variables..., valencia_int_deriv_variables...,
     528             :           tuples::get<Tags::detail::TemporaryReference<
     529             :               ValenciaGridlessTags,
     530             :               tmpl::at<gridless_tags_and_types, ValenciaGridlessTags>>>(
     531             :               shuffle_refs)...);
     532             :     }
     533             :     if (not gh_string.has_value()) {
     534             :       return valencia_string;
     535             :     }
     536             :     if (not valencia_string.has_value()) {
     537             :       return gh_string;
     538             :     }
     539             :     return gh_string.value() + ";" + valencia_string.value();
     540             :   }
     541             : };
     542             : }  // namespace detail
     543             : 
     544             : /*!
     545             :  * \brief Apply a boundary condition to the combined Generalized Harmonic (GH)
     546             :  * and Valencia GRMHD system using the boundary conditions defined separately
     547             :  * for the GH and Valencia systems.
     548             :  *
     549             :  * \details The implementation of this boundary condition applies the
     550             :  * `DerivedGhCondition` followed by the `DerivedValenciaCondition`.
     551             :  * It is anticipated that the systems are sufficiently independent that the
     552             :  * order of application is inconsequential. Arbitrary combinations of differing
     553             :  * `bc_type`s for the two systems are supported, with the only restriction that
     554             :  * if either is an outflow condition, both must be.
     555             :  */
     556             : template <typename DerivedGhCondition, typename DerivedValenciaCondition>
     557           1 : class ProductOfConditions final : public BoundaryCondition {
     558             :  public:
     559           0 :   static constexpr evolution::BoundaryConditions::Type bc_type =
     560             :       detail::UnionOfBcTypes<DerivedGhCondition::bc_type,
     561             :                              DerivedValenciaCondition::bc_type>::bc_type;
     562             : 
     563           0 :   using dg_interior_evolved_variables_tags =
     564             :       tmpl::remove_duplicates<tmpl::append<
     565             :           typename DerivedGhCondition::dg_interior_evolved_variables_tags,
     566             :           typename DerivedValenciaCondition::dg_interior_evolved_variables_tags,
     567             :           tmpl::conditional_t<
     568             :               DerivedGhCondition::bc_type ==
     569             :                       evolution::BoundaryConditions::Type::TimeDerivative and
     570             :                   bc_type == evolution::BoundaryConditions::Type::
     571             :                                  GhostAndTimeDerivative,
     572             :               typename detail::GhDoNothingGhostCondition::
     573             :                   dg_interior_evolved_variables_tags,
     574             :               tmpl::list<>>,
     575             :           tmpl::conditional_t<
     576             :               DerivedValenciaCondition::bc_type ==
     577             :                       evolution::BoundaryConditions::Type::TimeDerivative and
     578             :                   bc_type == evolution::BoundaryConditions::Type::
     579             :                                  GhostAndTimeDerivative,
     580             :               typename detail::ValenciaDoNothingGhostCondition::
     581             :                   dg_interior_evolved_variables_tags,
     582             :               tmpl::list<>>>>;
     583           0 :   using dg_interior_primitive_variables_tags = tmpl::append<
     584             :       tmpl::list<>,
     585             :       typename DerivedValenciaCondition::dg_interior_primitive_variables_tags>;
     586           0 :   using dg_interior_temporary_tags = tmpl::remove_duplicates<tmpl::append<
     587             :       typename DerivedGhCondition::dg_interior_temporary_tags,
     588             :       typename DerivedValenciaCondition::dg_interior_temporary_tags,
     589             :       tmpl::conditional_t<
     590             :           DerivedGhCondition::bc_type ==
     591             :                   evolution::BoundaryConditions::Type::TimeDerivative and
     592             :               bc_type ==
     593             :                   evolution::BoundaryConditions::Type::GhostAndTimeDerivative,
     594             :           typename detail::GhDoNothingGhostCondition::
     595             :               dg_interior_temporary_tags,
     596             :           tmpl::list<>>,
     597             :       tmpl::conditional_t<
     598             :           DerivedValenciaCondition::bc_type ==
     599             :                   evolution::BoundaryConditions::Type::TimeDerivative and
     600             :               bc_type ==
     601             :                   evolution::BoundaryConditions::Type::GhostAndTimeDerivative,
     602             :           typename detail::ValenciaDoNothingGhostCondition::
     603             :               dg_interior_temporary_tags,
     604             :           tmpl::list<>>>>;
     605           0 :   using dg_gridless_tags = tmpl::remove_duplicates<
     606             :       tmpl::append<typename DerivedGhCondition::dg_gridless_tags,
     607             :                    typename DerivedValenciaCondition::dg_gridless_tags>>;
     608           0 :   using dg_interior_dt_vars_tags = tmpl::append<
     609             :       evolution::dg::Actions::detail::get_dt_vars_from_boundary_condition<
     610             :           DerivedGhCondition>,
     611             :       evolution::dg::Actions::detail::get_dt_vars_from_boundary_condition<
     612             :           DerivedValenciaCondition>>;
     613           0 :   using dg_interior_deriv_vars_tags = tmpl::append<
     614             :       evolution::dg::Actions::detail::get_deriv_vars_from_boundary_condition<
     615             :           DerivedGhCondition>,
     616             :       evolution::dg::Actions::detail::get_deriv_vars_from_boundary_condition<
     617             :           DerivedValenciaCondition>>;
     618             : 
     619           0 :   using product_of_conditions_impl = detail::ProductOfConditionsImpl<
     620             :       DerivedGhCondition, DerivedValenciaCondition,
     621             :       typename GeneralizedHarmonic::System<3_st>::variables_tag::tags_list,
     622             :       typename grmhd::ValenciaDivClean::System::variables_tag::tags_list,
     623             :       db::wrap_tags_in<
     624             :           ::Tags::Flux,
     625             :           typename GeneralizedHarmonic::System<3_st>::flux_variables,
     626             :           tmpl::size_t<3_st>, Frame::Inertial>,
     627             :       db::wrap_tags_in<::Tags::Flux,
     628             :                        typename grmhd::ValenciaDivClean::System::flux_variables,
     629             :                        tmpl::size_t<3_st>, Frame::Inertial>,
     630             :       typename DerivedGhCondition::dg_interior_evolved_variables_tags,
     631             :       typename DerivedValenciaCondition::dg_interior_evolved_variables_tags,
     632             :       dg_interior_evolved_variables_tags, tmpl::list<>,
     633             :       typename DerivedValenciaCondition::dg_interior_primitive_variables_tags,
     634             :       typename DerivedGhCondition::dg_interior_temporary_tags,
     635             :       typename DerivedValenciaCondition::dg_interior_temporary_tags,
     636             :       dg_interior_temporary_tags,
     637             :       evolution::dg::Actions::detail::get_dt_vars_from_boundary_condition<
     638             :           DerivedGhCondition>,
     639             :       evolution::dg::Actions::detail::get_dt_vars_from_boundary_condition<
     640             :           DerivedValenciaCondition>,
     641             :       evolution::dg::Actions::detail::get_deriv_vars_from_boundary_condition<
     642             :           DerivedGhCondition>,
     643             :       evolution::dg::Actions::detail::get_deriv_vars_from_boundary_condition<
     644             :           DerivedValenciaCondition>,
     645             :       typename DerivedGhCondition::dg_gridless_tags,
     646             :       typename DerivedValenciaCondition::dg_gridless_tags, dg_gridless_tags>;
     647             : 
     648           0 :   static std::string name() noexcept {
     649             :     return "Product" + Options::name<DerivedGhCondition>() + "And" +
     650             :            Options::name<DerivedValenciaCondition>();
     651             :   }
     652             : 
     653           0 :   struct GhCondition {
     654           0 :     using type = DerivedGhCondition;
     655           0 :     static std::string name() noexcept {
     656             :       return "GeneralizedHarmonic" + Options::name<DerivedGhCondition>();
     657             :     }
     658           0 :     static constexpr Options::String help{
     659             :         "The Generalized Harmonic part of the product boundary condition"};
     660             :   };
     661           0 :   struct ValenciaCondition {
     662           0 :     using type = DerivedValenciaCondition;
     663           0 :     static std::string name() noexcept {
     664             :       return "Valencia" + Options::name<DerivedValenciaCondition>();
     665             :     }
     666           0 :     static constexpr Options::String help{
     667             :         "The Valencia part of the product boundary condition"};
     668             :   };
     669             : 
     670           0 :   using options = tmpl::list<GhCondition, ValenciaCondition>;
     671             : 
     672           0 :   static constexpr Options::String help = {
     673             :       "Direct product of a GH and ValenciaDivClean GRMHD boundary conditions. "
     674             :       "See the documentation for the two individual boundary conditions for "
     675             :       "further details."};
     676             : 
     677           0 :   ProductOfConditions() = default;
     678           0 :   ProductOfConditions(DerivedGhCondition gh_condition,
     679             :                       DerivedValenciaCondition valencia_condition) noexcept
     680             :       : derived_gh_condition_{gh_condition},
     681             :         derived_valencia_condition_{valencia_condition} {}
     682           0 :   ProductOfConditions(const ProductOfConditions&) = default;
     683           0 :   ProductOfConditions& operator=(const ProductOfConditions&) = default;
     684           0 :   ProductOfConditions(ProductOfConditions&&) = default;
     685           0 :   ProductOfConditions& operator=(ProductOfConditions&&) = default;
     686           0 :   ~ProductOfConditions() override = default;
     687             : 
     688             :   /// \cond
     689             :   explicit ProductOfConditions(CkMigrateMessage* msg) noexcept
     690             :       : BoundaryCondition(msg) {}
     691             :   using PUP::able::register_constructor;
     692             :   WRAPPED_PUPable_decl_base_template(
     693             :       domain::BoundaryConditions::BoundaryCondition, ProductOfConditions);
     694             :   /// \endcond
     695             : 
     696           0 :   void pup(PUP::er& p) noexcept override;
     697             : 
     698           0 :   auto get_clone() const noexcept -> std::unique_ptr<
     699             :       domain::BoundaryConditions::BoundaryCondition> override;
     700             : 
     701             :   template <typename... Args>
     702           0 :   std::optional<std::string> dg_ghost(Args&&... args) const noexcept {
     703             :     return product_of_conditions_impl::dg_ghost(derived_gh_condition_,
     704             :                                                 derived_valencia_condition_,
     705             :                                                 std::forward<Args>(args)...);
     706             :   }
     707             : 
     708             :   template <typename... Args>
     709           0 :   std::optional<std::string> dg_outflow(Args&&... args) const noexcept {
     710             :     return product_of_conditions_impl::dg_outflow(derived_gh_condition_,
     711             :                                                   derived_valencia_condition_,
     712             :                                                   std::forward<Args>(args)...);
     713             :   }
     714             : 
     715             :   template <typename... Args>
     716           0 :   std::optional<std::string> dg_time_derivative(Args&&... args) const noexcept {
     717             :     return product_of_conditions_impl::dg_time_derivative(
     718             :         derived_gh_condition_, derived_valencia_condition_,
     719             :         std::forward<Args>(args)...);
     720             :   }
     721             : 
     722             :  private:
     723           0 :   DerivedGhCondition derived_gh_condition_;
     724           0 :   DerivedValenciaCondition derived_valencia_condition_;
     725             : };
     726             : 
     727             : template <typename DerivedGhCondition, typename DerivedValenciaCondition>
     728             : void ProductOfConditions<DerivedGhCondition, DerivedValenciaCondition>::pup(
     729             :     PUP::er& p) noexcept {
     730             :   p | derived_gh_condition_;
     731             :   p | derived_valencia_condition_;
     732             :   BoundaryCondition::pup(p);
     733             : }
     734             : 
     735             : template <typename DerivedGhCondition, typename DerivedValenciaCondition>
     736             : auto ProductOfConditions<DerivedGhCondition,
     737             :                          DerivedValenciaCondition>::get_clone() const noexcept
     738             :     -> std::unique_ptr<domain::BoundaryConditions::BoundaryCondition> {
     739             :   return std::make_unique<ProductOfConditions>(*this);
     740             : }
     741             : 
     742             : /// \cond
     743             : template <typename DerivedGhCondition, typename DerivedValenciaCondition>
     744             : PUP::able::PUP_ID ProductOfConditions<DerivedGhCondition,
     745             :                                       DerivedValenciaCondition>::my_PUP_ID =
     746             :     0;  // NOLINT
     747             : /// \endcond
     748             : }  // namespace grmhd::GhValenciaDivClean::BoundaryConditions

Generated by: LCOV version 1.14