SpECTRE Documentation Coverage Report
Current view: top level - Evolution/Imex/Protocols - ImplicitSector.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 1 18 5.6 %
Date: 2025-12-05 05:03:31
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 1.14