SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Systems/ScalarWave/BoundaryConditions - ConstraintPreservingSphericalRadiation.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 4.5 % 22 1
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <memory>
       7              : #include <optional>
       8              : #include <pup.h>
       9              : #include <string>
      10              : #include <type_traits>
      11              : 
      12              : #include "DataStructures/DataBox/Prefixes.hpp"
      13              : #include "DataStructures/DataVector.hpp"
      14              : #include "DataStructures/Tensor/Tensor.hpp"
      15              : #include "DataStructures/Variables.hpp"
      16              : #include "Evolution/BoundaryConditions/Type.hpp"
      17              : #include "Evolution/Systems/ScalarWave/BoundaryConditions/BoundaryCondition.hpp"
      18              : #include "Evolution/Systems/ScalarWave/Tags.hpp"
      19              : #include "NumericalAlgorithms/LinearOperators/PartialDerivatives.hpp"
      20              : #include "Options/Options.hpp"
      21              : #include "Options/String.hpp"
      22              : #include "PointwiseFunctions/AnalyticData/Tags.hpp"
      23              : #include "PointwiseFunctions/AnalyticSolutions/AnalyticSolution.hpp"
      24              : #include "Utilities/Gsl.hpp"
      25              : #include "Utilities/Serialization/CharmPupable.hpp"
      26              : #include "Utilities/TMPL.hpp"
      27              : 
      28              : /// \cond
      29              : namespace domain::Tags {
      30              : template <size_t Dim, typename Frame>
      31              : struct Coordinates;
      32              : }  // namespace domain::Tags
      33              : /// \endcond
      34              : 
      35              : namespace ScalarWave::BoundaryConditions {
      36              : namespace detail {
      37              : /// The type of spherical radiation boundary condition to impose
      38              : enum class ConstraintPreservingSphericalRadiationType {
      39              :   /// Impose \f$(\partial_t + \partial_r)\Psi=0\f$
      40              :   Sommerfeld,
      41              :   /// Impose \f$(\partial_t + \partial_r + r^{-1})\Psi=0\f$
      42              :   FirstOrderBaylissTurkel,
      43              :   /// Imposes a second-order Bayliss-Turkel boundary condition
      44              :   SecondOrderBaylissTurkel
      45              : };
      46              : 
      47              : ConstraintPreservingSphericalRadiationType
      48              : convert_constraint_preserving_spherical_radiation_type_from_yaml(
      49              :     const Options::Option& options);
      50              : }  // namespace detail
      51              : 
      52              : /*!
      53              :  * \brief Constraint-preserving spherical radiation boundary condition that
      54              :  * seeks to avoid ingoing constraint violations and radiation.
      55              :  *
      56              :  * The constraint-preserving part of the boundary condition imposes the
      57              :  * following condition on the time derivatives of the characteristic fields:
      58              :  *
      59              :  * \f{align*}{
      60              :  *   d_tw^\Psi&\to d_tw^{\Psi}+\lambda_{\Psi}n^i\mathcal{C}_i, \\
      61              :  *   d_tw^0_i&\to d_tw^{0}_i+\lambda_{0}n^jP^k_i\mathcal{C}_{ik},
      62              :  * \f}
      63              :  *
      64              :  * where
      65              :  *
      66              :  * \f{align*}{
      67              :  * P^k{}_i=\delta^k_i-n^kn_i
      68              :  * \f}
      69              :  *
      70              :  * projects a tensor onto the spatial surface to which \f$n_i\f$ is normal, and
      71              :  * \f$d_t w\f$ is the evolved to characteristic field transformation applied to
      72              :  * the time derivatives of the evolved fields. That is,
      73              :  *
      74              :  * \f{align*}{
      75              :  * d_t w^\Psi&=\partial_t \Psi, \\
      76              :  * d_t w_i^0&=(\delta^k_i-n^k n_i)\partial_t \Phi_k, \\
      77              :  * d_t w^{\pm}&=\partial_t\Pi\pm n^k\partial_t\Phi_k - \gamma_2\partial_t\Psi.
      78              :  * \f}
      79              :  *
      80              :  * The constraints are defined as:
      81              :  *
      82              :  * \f{align*}{
      83              :  *  \mathcal{C}_i&=\partial_i\Psi - \Phi_i=0, \\
      84              :  *  \mathcal{C}_{ij}&=\partial_{[i}\Phi_{j]}=0
      85              :  * \f}
      86              :  *
      87              :  * Radiation boundary conditions impose a condition on \f$\Pi\f$ or its time
      88              :  * derivative. We denote the boundary condition value of the time derivative of
      89              :  * \f$\Pi\f$ by \f$\partial_t\Pi^{\mathrm{BC}}\f$. With this, we can impose
      90              :  * boundary conditions on the time derivatives of the evolved variables as
      91              :  * follows:
      92              :  *
      93              :  * \f{align*}{
      94              :  * \partial_{t} \Psi&\to\partial_{t}\Psi +
      95              :  *                    \lambda_\Psi n^i \mathcal{C}_i, \\
      96              :  * \partial_{t}\Pi&\to\partial_{t}\Pi-\left(\partial_t\Pi
      97              :  *                  - \partial_t\Pi^{\mathrm{BC}}\right)
      98              :  *                  +\gamma_2\lambda_\Psi n^i \mathcal{C}_i
      99              :  *                  =\partial_t\Pi^{\mathrm{BC}}
     100              :  *                  +\gamma_2\lambda_\Psi n^i \mathcal{C}_i, \\
     101              :  * \partial_{t}\Phi_i&\to\partial_{t}\Phi_i+ 2 \lambda_0n^j \mathcal{C}_{ji}.
     102              :  * \f}
     103              :  *
     104              :  * Below we assume the normal vector \f$n^i\f$ is the radial unit normal vector.
     105              :  * That is, we assume the outer boundary is spherical. A Sommerfeld
     106              :  * \cite Sommerfeld1949 radiation condition is given by
     107              :  *
     108              :  * \f{align*}{
     109              :  *  \partial_t\Psi=n^i\Phi_i
     110              :  * \f}
     111              :  *
     112              :  * Or, assuming that \f$\partial_tn^i=0\f$ (or is very small),
     113              :  *
     114              :  * \f{align*}{
     115              :  *  \partial_t\Pi^{\mathrm{BC}}=n^i\partial_t\Phi_i
     116              :  * \f}
     117              :  *
     118              :  * The Bayliss-Turkel \cite BaylissTurkel boundary conditions are given by:
     119              :  *
     120              :  * \f{align*}{
     121              :  *  \prod_{l=1}^m\left(\partial_t + \partial_r + \frac{2l-1}{r}\right)\Psi=0
     122              :  * \f}
     123              :  *
     124              :  * The first-order form is
     125              :  *
     126              :  * \f{align*}{
     127              :  *  \partial_t\Pi^{\mathrm{BC}}=n^i\partial_t\Phi_i + \frac{1}{r}\partial_t\Psi,
     128              :  * \f}
     129              :  *
     130              :  * assuming \f$\partial_t n^i=0\f$ and \f$\partial_t r=0\f$.
     131              :  *
     132              :  * The second-order boundary condition is given by,
     133              :  *
     134              :  * \f{align*}{
     135              :  *  \partial_t\Pi^{\mathrm{BC}}
     136              :  *   &=\left(\partial_t\partial_r + \partial_r\partial_t +
     137              :  *     \partial_r^2+\frac{4}{r}\partial_t
     138              :  *     +\frac{4}{r}\partial_r + \frac{2}{r^2}\right)\Psi \notag \\
     139              :  *     &=n^i(\partial_t\Phi_i-\partial_i\Pi) + n^i n^j\partial_i\Phi_j -
     140              :  *     \frac{4}{r}\Pi+\frac{4}{r}n^i\Phi_i + \frac{2}{r^2}\Psi \notag \\
     141              :  *     &=n^i(\gamma_2(\partial_i\Psi - \Phi_i)-2\partial_i\Pi)
     142              :  *     + n^i n^j\partial_i\Phi_j -
     143              :  *     \frac{4}{r}\Pi+\frac{4}{r}n^i\Phi_i + \frac{2}{r^2}\Psi,
     144              :  * \f}
     145              :  *
     146              :  * where \f$\partial_t\f$ is the derivative with respect to the inertial frame
     147              :  * time, and we are assuming \f$\partial_t n^i=0\f$ and \f$\partial_t r=0\f$.
     148              :  *
     149              :  * The moving mesh can be accounted for by using
     150              :  *
     151              :  * \f{align*}{
     152              :  * \partial_t r = \frac{1}{r}x^i\delta_{ij}\partial_t x^j
     153              :  * \f}
     154              :  *
     155              :  * \note It is not clear if \f$\partial_t\Phi_i\f$ should be replaced by
     156              :  * \f$-\partial_i\Pi\f$, which is the evolution equation but without the
     157              :  * constraint.
     158              :  *
     159              :  * \note On a moving mesh the characteristic speeds change according to
     160              :  * \f$\lambda\to\lambda-v^i_gn_i\f$ where \f$v^i_g\f$ is the mesh velocity.
     161              :  *
     162              :  * \note For the scalar wave system \f$\lambda_0 = \lambda_\psi\f$
     163              :  *
     164              :  * \warning The boundary conditions are implemented assuming the outer boundary
     165              :  * is spherical. It might be possible to generalize the condition to
     166              :  * non-spherical boundaries by using \f$x^i/r\f$ instead of \f$n^i\f$, but this
     167              :  * hasn't been tested.
     168              :  *
     169              :  * \warning The received time derivatives are in the logical frame, not the
     170              :  * inertial frame and would need to first be corrected by subtracting the mesh
     171              :  * velocity. Similarly, the time derivative correction is in the logical frame.
     172              :  * We instead substitute the evolution equations directly in since the scalar
     173              :  * wave system is quite simple.
     174              :  */
     175              : template <size_t Dim>
     176            1 : class ConstraintPreservingSphericalRadiation final
     177              :     : public BoundaryCondition<Dim> {
     178              :  public:
     179            0 :   struct TypeOptionTag {
     180            0 :     using type = detail::ConstraintPreservingSphericalRadiationType;
     181            0 :     static std::string name() { return "Type"; }
     182            0 :     static constexpr Options::String help{
     183              :         "Whether to impose Sommerfeld, first-order Bayliss-Turkel, or "
     184              :         "second-order Bayliss-Turkel spherical radiation boundary conditions."};
     185              :   };
     186              : 
     187            0 :   using options = tmpl::list<TypeOptionTag>;
     188            0 :   static constexpr Options::String help{
     189              :       "Constraint-preserving spherical radiation boundary conditions setting "
     190              :       "the time derivatives of Psi, Phi, and Pi to avoid incoming constraint "
     191              :       "violations, and imposing radiation boundary conditions."};
     192              : 
     193            0 :   ConstraintPreservingSphericalRadiation(
     194              :       detail::ConstraintPreservingSphericalRadiationType type);
     195              : 
     196            0 :   ConstraintPreservingSphericalRadiation() = default;
     197              :   /// \cond
     198              :   ConstraintPreservingSphericalRadiation(
     199              :       ConstraintPreservingSphericalRadiation&&) = default;
     200              :   ConstraintPreservingSphericalRadiation& operator=(
     201              :       ConstraintPreservingSphericalRadiation&&) = default;
     202              :   ConstraintPreservingSphericalRadiation(
     203              :       const ConstraintPreservingSphericalRadiation&) = default;
     204              :   ConstraintPreservingSphericalRadiation& operator=(
     205              :       const ConstraintPreservingSphericalRadiation&) = default;
     206              :   /// \endcond
     207            0 :   ~ConstraintPreservingSphericalRadiation() override = default;
     208              : 
     209            0 :   explicit ConstraintPreservingSphericalRadiation(CkMigrateMessage* msg);
     210              : 
     211            0 :   WRAPPED_PUPable_decl_base_template(
     212              :       domain::BoundaryConditions::BoundaryCondition,
     213              :       ConstraintPreservingSphericalRadiation);
     214              : 
     215            0 :   auto get_clone() const -> std::unique_ptr<
     216              :       domain::BoundaryConditions::BoundaryCondition> override;
     217              : 
     218            0 :   static constexpr evolution::BoundaryConditions::Type bc_type =
     219              :       evolution::BoundaryConditions::Type::TimeDerivative;
     220              : 
     221            0 :   void pup(PUP::er& p) override;
     222              : 
     223            0 :   using dg_interior_evolved_variables_tags =
     224              :       tmpl::list<ScalarWave::Tags::Psi, ScalarWave::Tags::Pi,
     225              :                  ScalarWave::Tags::Phi<Dim>>;
     226            0 :   using dg_interior_temporary_tags =
     227              :       tmpl::list<domain::Tags::Coordinates<Dim, Frame::Inertial>,
     228              :                  Tags::ConstraintGamma2>;
     229              :   // using dg_interior_dt_vars_tags = tmpl::list<>;
     230            0 :   using dg_interior_deriv_vars_tags = tmpl::list<
     231              :       ::Tags::deriv<ScalarWave::Tags::Psi, tmpl::size_t<Dim>, Frame::Inertial>,
     232              :       ::Tags::deriv<ScalarWave::Tags::Pi, tmpl::size_t<Dim>, Frame::Inertial>,
     233              :       ::Tags::deriv<ScalarWave::Tags::Phi<Dim>, tmpl::size_t<Dim>,
     234              :                     Frame::Inertial>>;
     235            0 :   using dg_gridless_tags = tmpl::list<>;
     236              : 
     237            0 :   std::optional<std::string> dg_time_derivative(
     238              :       gsl::not_null<Scalar<DataVector>*> dt_psi_correction,
     239              :       gsl::not_null<Scalar<DataVector>*> dt_pi_correction,
     240              :       gsl::not_null<tnsr::i<DataVector, Dim, Frame::Inertial>*>
     241              :           dt_phi_correction,
     242              : 
     243              :       const std::optional<tnsr::I<DataVector, Dim, Frame::Inertial>>&
     244              :           face_mesh_velocity,
     245              :       const tnsr::i<DataVector, Dim, Frame::Inertial>& normal_covector,
     246              : 
     247              :       const Scalar<DataVector>& psi, const Scalar<DataVector>& pi,
     248              :       const tnsr::i<DataVector, Dim, Frame::Inertial>& phi,
     249              : 
     250              :       const tnsr::I<DataVector, Dim, Frame::Inertial>& coords,
     251              :       const Scalar<DataVector>& gamma2,
     252              : 
     253              :       const tnsr::i<DataVector, Dim, Frame::Inertial>& d_psi,
     254              :       const tnsr::i<DataVector, Dim, Frame::Inertial>& d_pi,
     255              :       const tnsr::ij<DataVector, Dim, Frame::Inertial>& d_phi) const;
     256              : 
     257              :  private:
     258            0 :   detail::ConstraintPreservingSphericalRadiationType type_{
     259              :       detail::ConstraintPreservingSphericalRadiationType::Sommerfeld};
     260              : };
     261              : }  // namespace ScalarWave::BoundaryConditions
     262              : 
     263              : template <>
     264              : struct Options::create_from_yaml<
     265              :     ScalarWave::BoundaryConditions::detail::
     266              :         ConstraintPreservingSphericalRadiationType> {
     267              :   template <typename Metavariables>
     268              :   static typename ScalarWave::BoundaryConditions::detail::
     269              :       ConstraintPreservingSphericalRadiationType
     270              :       create(const Options::Option& options) {
     271              :     return ScalarWave::BoundaryConditions::detail::
     272              :         convert_constraint_preserving_spherical_radiation_type_from_yaml(
     273              :             options);
     274              :   }
     275              : };
        

Generated by: LCOV version 2.0-1