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

Generated by: LCOV version 1.14