SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Imex/Protocols - ImplicitSector.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 5.6 % 18 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 <type_traits>
       7              : 
       8              : #include "ImplicitSource.hpp"
       9              : #include "ImplicitSourceJacobian.hpp"
      10              : #include "Utilities/ProtocolHelpers.hpp"
      11              : #include "Utilities/TMPL.hpp"
      12              : #include "Utilities/TypeTraits/IsA.hpp"
      13              : 
      14              : /// \cond
      15              : class DataVector;
      16              : template <typename X, typename Symm, typename IndexList>
      17              : class Tensor;
      18              : namespace Tags {
      19              : template <typename Tag>
      20              : struct Source;
      21              : }  // namespace Tags
      22              : /// \endcond
      23              : 
      24              : namespace imex::protocols {
      25              : /// Protocol for an implicit sector of an IMEX system.
      26              : ///
      27              : /// An implicit sector describes the sources for one implicit solve
      28              : /// performed during IMEX evolution.  A system may have multiple
      29              : /// implicit sectors, but they must be independent, i.e., their
      30              : /// sources must not depend on any tensors in other sectors.
      31              : ///
      32              : /// Classes implementing this protocol must define:
      33              : ///
      34              : /// * a `tensors` type alias of tags for the variables to be solved for
      35              : ///
      36              : /// * an `initial_guess` type to be passed to `db::mutate_apply`,
      37              : ///   taking additional arguments for the inhomogeneous terms \f$X\f$
      38              : ///   and implicit weight \f$w\f$ in the equation to be solved:
      39              : ///   \f$u = X + w S(u)\f$.  (See example below.)  It must return a
      40              : ///   `std::vector<GuessResult>` indicating, for each point, whether
      41              : ///   the implicit equation has been solved analytically or whether
      42              : ///   the numerical solve should continue.  An empty return is
      43              : ///   equivalent to `imex::GuessResult::InitialGuess` for every point,
      44              : ///   so numerical solves will be performed for each.  When this is
      45              : ///   called, the sector variables will have the value from the
      46              : ///   explicit part of the time step.  This mutator will not be called
      47              : ///   if the implicit weight is zero, as the solution is trivial in
      48              : ///   that case.  If using the value of the explicit step as an
      49              : ///   initial guess is acceptable, this can be the type
      50              : ///   `imex::GuessExplicitResult`.
      51              : ///
      52              : /// * a `solve_attempts` list of sources that will be attempted to be
      53              : ///   solved, in order.  The first one that succeeds at each point
      54              : ///   will be used.  Pieces of code that need "the" source for the
      55              : ///   sector will use the source from the first entry.  Each attempt
      56              : ///   must be a struct with the following types:
      57              : ///
      58              : ///   * lists used to construct a DataBox during the pointwise
      59              : ///     implicit solve:
      60              : ///
      61              : ///     * `tags_from_evolution` for tags in addition to the sector
      62              : ///        tensors to be made available from the evolution DataBox.
      63              : ///        Volume quantities will be reduced to have one grid point,
      64              : ///        with the appropriate value for the point being solved for.
      65              : ///
      66              : ///     * `simple_tags` for temporaries (e.g., primitives)
      67              : ///
      68              : ///     * `compute_tags`
      69              : ///
      70              : ///   * a `source` type to be passed to `db::mutate_apply` to compute
      71              : ///     the sources. It must conform to imex::protocols::ImplicitSource.
      72              : ///
      73              : ///   * a `jacobian` type to be passed to `db::mutate_apply` to
      74              : ///     compute the source jacobian.  It must conform to
      75              : ///     imex::protocols::ImplicitSourceJacobian. If the implicit equation can
      76              : ///     always be solved analytically for the sector, the jacobian is not
      77              : ///     required and this may be the type
      78              : ///     `imex::NoJacobianBecauseSolutionIsAnalytic`.
      79              : ///
      80              : ///   * lists `source_prep` and `jacobian_prep` that will be called
      81              : ///     before the corresponding main mutator, e.g., for computing
      82              : ///     primitives.  Mutators appearing in multiple lists, as well as
      83              : ///     the `source` and `jacobian` mutators, will be skipped if they
      84              : ///     have already been applied for the current point.  Note that
      85              : ///     the `source_prep` mutators are only used during the implicit
      86              : ///     solve, and any preparation needed before the `source` call in
      87              : ///     the main action loop to record the history is the
      88              : ///     responsibility of the user.
      89              : ///
      90              : /// All `Variables` in the DataBox, including the sources and source
      91              : /// jacobian, will be initialized to zero with a single grid point.
      92              : ///
      93              : /// \snippet DoImplicitStepSector.hpp simple_sector
      94              : ///
      95              : /// Examples of definitions of a complicated implicit source and
      96              : /// jacobian:
      97              : ///
      98              : /// \snippet Test_SolveImplicitSector.cpp source
      99              : /// \snippet Test_SolveImplicitSector.cpp Jacobian
     100            1 : struct ImplicitSector {
     101              :   template <typename ConformingType>
     102            0 :   struct test {
     103            0 :     using tensors = typename ConformingType::tensors;
     104            0 :     using initial_guess = typename ConformingType::initial_guess;
     105            0 :     using solve_attempts = typename ConformingType::solve_attempts;
     106              : 
     107              :     static_assert(tt::is_a_v<tmpl::list, tensors>);
     108              :     static_assert(tt::is_a_v<tmpl::list, solve_attempts>);
     109              :     static_assert(tmpl::size<solve_attempts>::value >= 1);
     110              : 
     111              :     static_assert(
     112              :         tmpl::all<
     113              :             tensors,
     114              :             tt::is_a<Tensor, tmpl::bind<tmpl::type_from, tmpl::_1>>>::value);
     115              : 
     116            0 :     using source_tensors =
     117              :         tmpl::transform<tensors, tmpl::bind<::Tags::Source, tmpl::_1>>;
     118              : 
     119              :     static_assert(
     120              :         tmpl::size<tmpl::list_difference<typename initial_guess::return_tags,
     121              :                                          tensors>>::value == 0,
     122              :         "initial_guess can only modify sector variables.");
     123              : 
     124              :     template <typename SolveAttempt>
     125            0 :     struct test_solve_attempt {
     126            0 :       using source = typename SolveAttempt::source;
     127            0 :       using jacobian = typename SolveAttempt::jacobian;
     128              : 
     129            0 :       using tags_from_evolution = typename SolveAttempt::tags_from_evolution;
     130            0 :       using simple_tags = typename SolveAttempt::simple_tags;
     131            0 :       using compute_tags = typename SolveAttempt::compute_tags;
     132              : 
     133            0 :       using source_prep = typename SolveAttempt::source_prep;
     134            0 :       using jacobian_prep = typename SolveAttempt::jacobian_prep;
     135              : 
     136              :       // check protocol conformity
     137              :       static_assert(
     138              :           tt::assert_conforms_to_v<source, imex::protocols::ImplicitSource>);
     139              :       static_assert(tt::assert_conforms_to_v<
     140              :                     jacobian, imex::protocols::ImplicitSourceJacobian>);
     141              : 
     142              :       static_assert(tt::is_a_v<tmpl::list, tags_from_evolution>);
     143              :       static_assert(tt::is_a_v<tmpl::list, simple_tags>);
     144              :       static_assert(tt::is_a_v<tmpl::list, compute_tags>);
     145              :       static_assert(tt::is_a_v<tmpl::list, source_prep>);
     146              :       static_assert(tt::is_a_v<tmpl::list, jacobian_prep>);
     147              : 
     148              :       static_assert(
     149              :           std::is_same_v<tmpl::list_difference<tags_from_evolution, tensors>,
     150              :                          tags_from_evolution>,
     151              :           "tags_from_evolution cannot include the sector tensors.");
     152              : 
     153              :       static_assert(
     154              :           std::is_same_v<tmpl::list_difference<source_tensors,
     155              :                                                typename source::return_tags>,
     156              :                          tmpl::list<>> and
     157              :               std::is_same_v<tmpl::list_difference<typename source::return_tags,
     158              :                                                    source_tensors>,
     159              :                              tmpl::list<>>,
     160              :           "Implicit source must provide sources for the entire sector.");
     161              : 
     162              :       template <typename T>
     163            0 :       struct is_a_tensor_of_data_vector : std::false_type {};
     164              : 
     165              :       template <typename Symm, typename IndexList>
     166            0 :       struct is_a_tensor_of_data_vector<Tensor<DataVector, Symm, IndexList>>
     167              :           : std::true_type {};
     168              : 
     169              :       static_assert(
     170              :           tmpl::none<simple_tags, is_a_tensor_of_data_vector<tmpl::bind<
     171              :                                       tmpl::type_from, tmpl::_1>>>::value,
     172              :           "Do not include tags for Tensor<DataVector> in simple_tags, because "
     173              :           "they trigger many memory allocations.  Add the tensors as part of "
     174              :           "a Variables instead.");
     175              : 
     176            0 :       using type = std::true_type;
     177              :     };
     178              : 
     179              :     static_assert(
     180              :         tmpl::all<solve_attempts, test_solve_attempt<tmpl::_1>>::value);
     181              :   };
     182              : };
     183              : }  // namespace imex::protocols
        

Generated by: LCOV version 2.0-1