SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/LinearSolver/Schwarz - Schwarz.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 7.7 % 13 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 "IO/Observer/Helpers.hpp"
       7              : #include "ParallelAlgorithms/LinearSolver/AsynchronousSolvers/ElementActions.hpp"
       8              : #include "ParallelAlgorithms/LinearSolver/Schwarz/ElementActions.hpp"
       9              : #include "ParallelAlgorithms/LinearSolver/Schwarz/ObserveVolumeData.hpp"
      10              : #include "Utilities/ProtocolHelpers.hpp"
      11              : #include "Utilities/TMPL.hpp"
      12              : 
      13              : /// Items related to the %Schwarz linear solver
      14              : ///
      15              : /// \see `LinearSolver::Schwarz::Schwarz`
      16              : namespace LinearSolver::Schwarz {
      17              : 
      18              : /*!
      19              :  * \ingroup LinearSolverGroup
      20              :  * \brief An additive Schwarz subdomain solver for linear systems of equations
      21              :  * \f$Ax=b\f$.
      22              :  *
      23              :  * This Schwarz-type linear solver works by solving many sub-problems in
      24              :  * parallel and combining their solutions as a weighted sum to converge towards
      25              :  * the global solution. Each sub-problem is the restriction of the global
      26              :  * problem to an element-centered subdomain, which consists of a central element
      27              :  * and an overlap region with its neighbors. The decomposition into independent
      28              :  * sub-problems makes this linear solver very parallelizable, avoiding global
      29              :  * synchronization points altogether. It is commonly used as a preconditioner to
      30              :  * Krylov-type solvers such as `LinearSolver::gmres::Gmres` or
      31              :  * `LinearSolver::cg::ConjugateGradient`, or as the "smoother" for a Multigrid
      32              :  * solver (which may in turn precondition a Krylov-type solver).
      33              :  *
      34              :  * This linear solver relies on an implementation of the global linear operator
      35              :  * \f$A(x)\f$ and its restriction to a subdomain \f$A_{ss}(x)\f$. Each step of
      36              :  * the algorithm expects that \f$A(x)\f$ is computed and stored in the DataBox
      37              :  * as `db::add_tag_prefix<LinearSolver::Tags::OperatorAppliedTo, operand_tag>`.
      38              :  * To perform a solve, add the `solve` action list to an array parallel
      39              :  * component. Pass the actions that compute \f$A(x)\f$, as well as any further
      40              :  * actions you wish to run in each step of the algorithm, as the first template
      41              :  * parameter to `solve`. If you add the `solve` action list multiple times, use
      42              :  * the second template parameter to label each solve with a different type.
      43              :  * Pass the subdomain operator as the `SubdomainOperator` template parameter to
      44              :  * this class (not to the `solve` action list template). See the paragraph below
      45              :  * for information on implementing a subdomain operator.
      46              :  *
      47              :  * \par Subdomain geometry:
      48              :  * The image below gives an overview of the structure of an element-centered
      49              :  * subdomain:
      50              :  *
      51              :  * \image html subdomain_structure.svg "Fig. 1: An element-centered subdomain" width=600px
      52              :  *
      53              :  * Fig. 1 shows part of a 2-dimensional computational domain. The domain is
      54              :  * composed of elements (light gray) that each carry a Legendre-Gauss-Lobatto
      55              :  * mesh of grid points (black dots). The diagonally shaded region to the left
      56              :  * illustrates an external domain boundary. The lines between neighboring
      57              :  * element faces illustrate mortar meshes, which are relevant when implementing
      58              :  * a subdomain operator in a DG context but play no role in the Schwarz
      59              :  * algorithm. The dashed line gives an example of an element-centered subdomain
      60              :  * with a maximum of 2 grid points of overlap into neighboring elements. For
      61              :  * details on how the number of overlap points is chosen see
      62              :  * `LinearSolver::Schwarz::overlap_extent`. Note that the subdomain does not
      63              :  * extend into corner- or edge-neighbors, which is different to both
      64              :  * \cite Stiller2016a and \cite Vincent2019qpd. The reason we don't include
      65              :  * such diagonal couplings is that in a DG context information only propagates
      66              :  * across faces, as noted in \cite Stiller2016a. By eliminating the corner-
      67              :  * and edge-neighbors we significantly reduce the complexity of the subdomain
      68              :  * geometry and potentially also the communication costs. However, the
      69              :  * advantages and disadvantages of this choice have yet to be carefully
      70              :  * evaluated.
      71              :  *
      72              :  * \par Subdomain operator:
      73              :  * The Schwarz subdomain solver relies on a restriction of the global linear
      74              :  * problem \f$Ax=b\f$ to the subdomains. The subdomain operator
      75              :  * \f$A_{ss}=R_s A R_s^T\f$, where \f$R_s\f$ is the restriction operator,
      76              :  * essentially assumes that its operand is zero everywhere but within the
      77              :  * subdomain (see Section 3.1 in \cite Stiller2016a). Therefore it can be
      78              :  * evaluated entirely on an element-centered subdomain with no need to
      79              :  * communicate with neighbors within each subdomain-operator application, as
      80              :  * opposed to the global linear operator that typically requires
      81              :  * nearest-neighbor communications. See
      82              :  * `LinearSolver::Schwarz::SubdomainOperator` for details on how to
      83              :  * implement a subdomain operator for your problem.
      84              :  *
      85              :  * \par Algorithm overview:
      86              :  * In each iteration, the Schwarz algorithm computes the residual \f$r=b-Ax\f$,
      87              :  * restricts it to all subdomains as \f$r_s=R_s r\f$ and communicates data on
      88              :  * overlap regions with neighboring elements. Once an element has received all
      89              :  * data on its subdomain it solves the sub-problem \f$A_{ss}\delta x_s=r_s\f$
      90              :  * for the correction \f$\delta x_s\f$, where \f$\delta x_s\f$ and \f$r_s\f$
      91              :  * have data only on the points of the subdomain and \f$A_{ss}\f$ is the
      92              :  * subdomain operator. Since all elements perform such a subdomain-solve, we end
      93              :  * up with a subdomain solution \f$\delta x_s\f$ on every subdomain, and the
      94              :  * solutions overlap. Therefore, the algorithm communicates subdomain solutions
      95              :  * on overlap regions with neighboring elements and adds them to the solution
      96              :  * field \f$x\f$ as a weighted sum.
      97              :  *
      98              :  * \par Applying the global linear operator:
      99              :  * In order to compute the residual \f$r=b-Ax\f$ that will be restricted to the
     100              :  * subdomains to serve as source for the subdomain solves, we must apply the
     101              :  * global linear operator \f$A\f$ to the solution field \f$x\f$ once per Schwarz
     102              :  * iteration. The global linear operator typically introduces nearest-neighbor
     103              :  * couplings between elements but no global synchronization point (as opposed to
     104              :  * Krylov-type solvers such as `LinearSolver::gmres::Gmres` that require global
     105              :  * inner products in each iteration). The algorithm assumes that the action list
     106              :  * passed to `solve` applies the global linear operator, as described above.
     107              :  *
     108              :  * \par Subdomain solves:
     109              :  * Each subdomain solve is local to an element, since the data on the subdomain
     110              :  * has been made available through communication with the neighboring elements.
     111              :  * We can now use any means to solve the subdomain problem that's appropriate
     112              :  * for the subdomain operator \f$A_{ss}\f$. For example, if the subdomain
     113              :  * operator was available as an explicit matrix we could invert it directly.
     114              :  * Since it is typically a matrix-free operator a common approach to solve the
     115              :  * subdomain problem is by means of an iterative Krylov-type method, such as
     116              :  * GMRES or Conjugate Gradient, ideally with an appropriate preconditioner (yes,
     117              :  * this would be preconditioned Krylov-methods solving the subdomains of the
     118              :  * Schwarz solver, which might in turn precondition a global Krylov-solver -
     119              :  * it's preconditioners all the way down). Currently, the linear solvers listed
     120              :  * in `LinearSolver::Serial` are available to solve subdomains. They include
     121              :  * Krylov-type methods that support nested preconditioning with any other linear
     122              :  * solver. Additional problem-specific subdomain preconditioners can be added
     123              :  * with the `SubdomainPreconditioners` template parameter. Note that the choice
     124              :  * of subdomain solver (and, by extension, the choice of subdomain
     125              :  * preconditioner) affects only the _performance_ of the Schwarz solver, not its
     126              :  * convergence or parallelization properties (assuming the subdomain solutions
     127              :  * it produces are sufficiently precise).
     128              :  *
     129              :  * \par Weighting:
     130              :  * Once the subdomain solutions \f$\delta x_s\f$ have been found they must be
     131              :  * combined where they have multiple values, i.e. on overlap regions of the
     132              :  * subdomains. We use an additive approach where we combine the subdomain
     133              :  * solutions as a weighted sum, which has the advantage over "multiplicative"
     134              :  * Schwarz methods that the subdomains decouple and can be solved in parallel.
     135              :  * See `LinearSolver::Schwarz::element_weight` and Section 3.1 of
     136              :  * \cite Stiller2016a for details. Note that we must account for the missing
     137              :  * corner- and edge-neighbors when constructing the weights. See
     138              :  * `LinearSolver::Schwarz::intruding_weight` for a discussion.
     139              :  *
     140              :  * \par Array sections
     141              :  * This linear solver requires no synchronization between elements, so it runs
     142              :  * on all elements in the array parallel component. Partitioning of the elements
     143              :  * in sections is only relevant for observing residual norms. Pass the section
     144              :  * ID tag for the `ArraySectionIdTag` template parameter if residual norms
     145              :  * should be computed over a section. Pass `void` (default) to compute residual
     146              :  * norms over all elements in the array.
     147              :  *
     148              :  * \par Possible improvements:
     149              :  * - Specify the number of overlap points as a fraction of the element width
     150              :  * instead of a fixed number. This was shown in \cite Stiller2016b to achieve
     151              :  * scale-independent convergence at the cost of increasing subdomain sizes.
     152              :  */
     153              : template <typename FieldsTag, typename OptionsGroup, typename SubdomainOperator,
     154              :           typename SubdomainPreconditioners = tmpl::list<>,
     155              :           typename SourceTag =
     156              :               db::add_tag_prefix<::Tags::FixedSource, FieldsTag>,
     157              :           typename ArraySectionIdTag = void>
     158            1 : struct Schwarz {
     159            0 :   using operand_tag = FieldsTag;
     160            0 :   using fields_tag = FieldsTag;
     161            0 :   using source_tag = SourceTag;
     162            0 :   using options_group = OptionsGroup;
     163              : 
     164            0 :   using component_list = tmpl::list<>;
     165            0 :   using observed_reduction_data_tags = observers::make_reduction_data_tags<
     166              :       tmpl::list<async_solvers::reduction_data, detail::reduction_data>>;
     167            0 :   using subdomain_solver =
     168              :       detail::subdomain_solver<FieldsTag, SubdomainOperator,
     169              :                                SubdomainPreconditioners>;
     170              : 
     171            0 :   using initialize_element = tmpl::list<
     172              :       async_solvers::InitializeElement<FieldsTag, OptionsGroup, SourceTag>,
     173              :       detail::InitializeElement<FieldsTag, OptionsGroup, SubdomainOperator,
     174              :                                 SubdomainPreconditioners>>;
     175              : 
     176            0 :   using amr_projectors = initialize_element;
     177              : 
     178            0 :   using register_element = tmpl::list<
     179              :       async_solvers::RegisterElement<FieldsTag, OptionsGroup, SourceTag,
     180              :                                      ArraySectionIdTag>,
     181              :       detail::RegisterElement<FieldsTag, OptionsGroup, SourceTag,
     182              :                               ArraySectionIdTag>,
     183              :       observers::Actions::RegisterWithObservers<
     184              :           detail::RegisterWithVolumeObserver<OptionsGroup, ArraySectionIdTag>>>;
     185              : 
     186              :   template <typename ApplyOperatorActions, typename Label = OptionsGroup>
     187            0 :   using solve = tmpl::list<
     188              :       async_solvers::PrepareSolve<FieldsTag, OptionsGroup, SourceTag, Label,
     189              :                                   ArraySectionIdTag>,
     190              :       detail::SendOverlapData<FieldsTag, OptionsGroup, SubdomainOperator>,
     191              :       detail::SolveSubdomain<FieldsTag, OptionsGroup, SubdomainOperator,
     192              :                              SubdomainPreconditioners, ArraySectionIdTag>,
     193              :       detail::ReceiveOverlapSolution<FieldsTag, OptionsGroup,
     194              :                                      SubdomainOperator>,
     195              :       detail::ObserveVolumeData<FieldsTag, OptionsGroup, SubdomainOperator,
     196              :                                 ArraySectionIdTag>,
     197              :       ApplyOperatorActions,
     198              :       async_solvers::CompleteStep<FieldsTag, OptionsGroup, SourceTag, Label,
     199              :                                   ArraySectionIdTag>>;
     200              : };
     201              : 
     202              : }  // namespace LinearSolver::Schwarz
        

Generated by: LCOV version 2.0-1