SpECTRE Documentation Coverage Report
Current view: top level - Elliptic/Protocols - FirstOrderSystem.hpp Hit Total Coverage
Commit: 2c4f624839e832d3d5b2abc37601f7e1f9a600c9 Lines: 2 13 15.4 %
Date: 2024-05-04 01:01:37
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 <type_traits>
       8             : 
       9             : #include "DataStructures/Tensor/Tensor.hpp"
      10             : #include "Domain/BoundaryConditions/BoundaryCondition.hpp"
      11             : #include "Utilities/TMPL.hpp"
      12             : #include "Utilities/TypeTraits/IsA.hpp"
      13             : 
      14             : /// \ref protocols related to elliptic systems
      15           1 : namespace elliptic::protocols {
      16             : 
      17             : namespace FirstOrderSystem_detail {
      18             : template <size_t Dim, typename PrimalFields, typename PrimalFluxes>
      19             : struct test_fields_and_fluxes;
      20             : template <size_t Dim, typename... PrimalFields, typename... PrimalFluxes>
      21             : struct test_fields_and_fluxes<Dim, tmpl::list<PrimalFields...>,
      22             :                               tmpl::list<PrimalFluxes...>> : std::true_type {
      23             :   static_assert(sizeof...(PrimalFields) == sizeof...(PrimalFluxes),
      24             :                 "The system must have the same number of fields and fluxes.");
      25             :   static_assert(
      26             :       ((tmpl::size<typename PrimalFluxes::type::index_list>::value ==
      27             :         tmpl::size<typename PrimalFields::type::index_list>::value + 1) and
      28             :        ...) and
      29             :           (std::is_same_v<tmpl::front<typename PrimalFluxes::type::index_list>,
      30             :                           SpatialIndex<Dim, UpLo::Up, Frame::Inertial>> and
      31             :            ...),
      32             :       "Primal fluxes and primal fields must correspond to each "
      33             :       "other. In particular, each primal flux must have one "
      34             :       "index more than its corresponding primal field and an upper-spatial "
      35             :       "first index.");
      36             : };
      37             : }  // namespace FirstOrderSystem_detail
      38             : 
      39             : /*!
      40             :  * \brief A system of elliptic equations in first-order "flux" formulation
      41             :  *
      42             :  * Classes conforming to this protocol represent a set of elliptic partial
      43             :  * differential equations in first-order "flux" formulation:
      44             :  *
      45             :  * \f{equation}
      46             :  * -\partial_i F^i_\alpha + S_\alpha = f_\alpha(x)
      47             :  * \f}
      48             :  *
      49             :  * in terms of fluxes \f$F_\alpha^i\f$, sources \f$S_\alpha\f$ and fixed-sources
      50             :  * \f$f_\alpha(x)\f$ \cite Fischer2021voj.
      51             :  * It resembles closely formulations of hyperbolic
      52             :  * conservation laws but allows the fluxes \f$F_\alpha^i\f$ to be higher-rank
      53             :  * tensor fields. The fluxes and sources are functionals of the system
      54             :  * variables \f$u_\alpha(x)\f$ and their derivatives. The fixed-sources
      55             :  * \f$f_\alpha(x)\f$ are independent of the system variables. See the
      56             :  * `Poisson::FirstOrderSystem` and the `Elasticity::FirstOrderSystem` for
      57             :  * examples.
      58             :  *
      59             :  * Note that this formulation has been simplified since \cite Fischer2021voj :
      60             :  * We assume that the fluxes are linear in the fields and their derivatives and
      61             :  * removed the notion of "auxiliary variables" from the formulation altogether.
      62             :  * In the language of \cite Fischer2021voj we always just choose the partial
      63             :  * derivatives of the fields as auxiliary variables.
      64             :  *
      65             :  * Conforming classes must have these static member variables:
      66             :  *
      67             :  * - `size_t volume_dim`: The number of spatial dimensions.
      68             :  *
      69             :  * Conforming classes must have these type aliases:
      70             :  *
      71             :  * - `primal_fields`: A list of tags representing the primal fields. These are
      72             :  *   the fields we solve for, e.g. \f$u\f$ for a Poisson equation.
      73             :  *   (we may rename this to just "fields" since we removed the notion of
      74             :  *   "auxiliary fields")
      75             :  *
      76             :  * - `primal_fluxes`: A list of tags representing the primal fluxes
      77             :  *   \f$F_\alpha^i\f$. These are typically some linear combination of the
      78             :  *   derivatives of the system fields with raised indices, e.g. \f$v^i = g^{ij}
      79             :  *   \partial_j u\f$ for a curved-space Poisson equation on a background metric
      80             :  *   \f$g_{ij}\f$. They must have an upper-spatial first index, because their
      81             :  *   divergence defines the elliptic equation.
      82             :  *
      83             :  * - `background_fields`: A list of tags representing the variable-independent
      84             :  *   background fields in the equations. Examples are a background metric,
      85             :  *   associated fixed geometry quantities such as Christoffel symbols or the
      86             :  *   Ricci scalar, or any other fixed field that determines the problem to be
      87             :  *   solved such as matter sources in the Einstein constraint equations.
      88             :  *
      89             :  * - `inv_metric_tag`: The tag that defines the background geometry, i.e. the
      90             :  *   the geometry that the elliptic equations are formulated on. This is the
      91             :  *   metric responsible for normalizing one-forms, such as face normals.
      92             :  *
      93             :  * - `fluxes_computer`: A class that defines the fluxes \f$F_\alpha^i\f$. Must
      94             :  *   have an `argument_tags` type alias and an `apply` function that takes these
      95             :  *   arguments in this order:
      96             :  *
      97             :  *   1. The `primal_fluxes` as not-null pointer
      98             :  *   2. The `argument_tags`
      99             :  *   3. If `is_discontinuous` is `true` (see below):
     100             :  *      const ElementId<Dim>& element_id
     101             :  *   4. The `primal_fields`
     102             :  *   5. The partial derivatives of the `primal_fields`
     103             :  *
     104             :  *   The function can assume the output buffers are already correctly sized,
     105             :  *   but no guarantee is made on the values that the buffers hold at input.
     106             :  *
     107             :  *   The `fluxes_computer` must also have an `apply` function overload that is
     108             :  *   evaluated on faces of DG elements. It computes the same fluxes
     109             :  *   \f$F_\alpha^i\f$, but with the field derivatives replaced by the the face
     110             :  *   normal times the fields, and with the non-principal (non-derivative) terms
     111             :  *   set to zero. Having this separate function is an optimization to take
     112             :  *   advantage of the face normal remaining constant throughout the solve, so it
     113             :  *   can be "baked in" to the flux. The function takes these arguments in this
     114             :  *   order:
     115             :  *
     116             :  *   1. The `primal_fluxes` as not-null pointer
     117             :  *   2. The `argument_tags`
     118             :  *   3. If `is_discontinuous` is `true` (see below):
     119             :  *      const ElementId<Dim>& element_id
     120             :  *   4. The `const tnsr::i<DataVector, Dim>& face_normal` ($n_i$)
     121             :  *   5. The `const tnsr::I<DataVector, Dim>& face_normal_vector` ($n^i$)
     122             :  *   6. The `primal_fields`
     123             :  *
     124             :  *   The `fluxes_computer` class must also have the following additional
     125             :  *   type aliases and static member variables:
     126             :  *
     127             :  *   - `volume_tags`: the subset of `argument_tags` that will be retrieved
     128             :  *     directly from the DataBox, instead of retrieving it from the face of an
     129             :  *     element, when fluxes are applied on a face.
     130             :  *   - `const_global_cache_tags`: the subset of `argument_tags` that can be
     131             :  *     retrieved from _any_ element's DataBox, because they are stored in the
     132             :  *     global cache.
     133             :  *   - `bool is_trivial`: a boolean indicating whether the fluxes are simply
     134             :  *     the spatial metric, as is the case for the Poisson equation. Some
     135             :  *     computations can be skipped in this case.
     136             :  *   - `bool is_discontinuous`: a boolean indicating whether the fluxes are
     137             :  *     potentially discontinuous across element boundaries. This is `true` for
     138             :  *     systems where the equations on both sides of the boundary are different,
     139             :  *     e.g. elasticity with different materials on either side of the boundary.
     140             :  *     An additional `element_id` argument is passed to the `apply` functions in
     141             :  *     this case, which identifies on which side of an element boundary the
     142             :  *     fluxes are being evaluated.
     143             :  *
     144             :  * - `sources_computer`: A class that defines the sources \f$S_\alpha\f$. Must
     145             :  *   have an `argument_tags` type alias and an `apply` function that adds the
     146             :  *   sources to the equations. It takes these arguments in this order:
     147             :  *
     148             :  *   1. The types of the `primal_fields` as not-null pointer. These are the
     149             :  *      primal equations.
     150             :  *   2. The `argument_tags`
     151             :  *   3. The `primal_fields`
     152             :  *   4. The `primal_fluxes`
     153             :  *
     154             :  *   The function is expected to _add_ the sources \f$S_\alpha\f$ to the
     155             :  *   output buffers.
     156             :  *   The `sources_computer` may also be `void`, in which case \f$S_\alpha=0\f$.
     157             :  *
     158             :  * - `boundary_conditions_base`: A base class representing the supported
     159             :  *   boundary conditions. Boundary conditions can be factory-created from this
     160             :  *   base class. Currently this should be a specialization of
     161             :  *   `elliptic::BoundaryConditions::BoundaryCondition`.
     162             :  */
     163           1 : struct FirstOrderSystem {
     164             :   template <typename ConformingType>
     165           0 :   struct test {
     166           0 :     static constexpr size_t volume_dim = ConformingType::volume_dim;
     167             : 
     168           0 :     using primal_fields = typename ConformingType::primal_fields;
     169           0 :     using primal_fluxes = typename ConformingType::primal_fluxes;
     170             :     static_assert(FirstOrderSystem_detail::test_fields_and_fluxes<
     171             :                   volume_dim, primal_fields, primal_fluxes>::value);
     172             : 
     173           0 :     using background_fields = typename ConformingType::background_fields;
     174             :     static_assert(tt::is_a_v<tmpl::list, background_fields>);
     175           0 :     using inv_metric_tag = typename ConformingType::inv_metric_tag;
     176             :     static_assert(std::is_same_v<inv_metric_tag, void> or
     177             :                   tmpl::list_contains_v<background_fields, inv_metric_tag>);
     178             : 
     179           0 :     using fluxes_computer = typename ConformingType::fluxes_computer;
     180           0 :     using sources_computer = typename ConformingType::sources_computer;
     181           0 :     using fluxes_argument_tags = typename fluxes_computer::argument_tags;
     182             :     static_assert(tt::is_a_v<tmpl::list, fluxes_argument_tags>);
     183             : 
     184           0 :     using boundary_conditions_base =
     185             :         typename ConformingType::boundary_conditions_base;
     186             :     static_assert(
     187             :         std::is_base_of_v<domain::BoundaryConditions::BoundaryCondition,
     188             :                           boundary_conditions_base>);
     189             :   };
     190             : };
     191             : 
     192             : }  // namespace elliptic::protocols

Generated by: LCOV version 1.14