SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/LinearSolver/Schwarz - Tags.hpp Hit Total Coverage
Commit: 9a96208c506d9ca7b3df1d25d929aecc56222b98 Lines: 11 61 18.0 %
Date: 2026-01-20 21:13:49
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 <array>
       7             : #include <cstddef>
       8             : #include <string>
       9             : 
      10             : #include "DataStructures/DataBox/Subitems.hpp"
      11             : #include "DataStructures/DataBox/Tag.hpp"
      12             : #include "DataStructures/DataVector.hpp"
      13             : #include "DataStructures/Tensor/Tensor.hpp"
      14             : #include "DataStructures/Variables.hpp"
      15             : #include "Options/Auto.hpp"
      16             : #include "Options/String.hpp"
      17             : #include "ParallelAlgorithms/LinearSolver/Schwarz/OverlapHelpers.hpp"
      18             : #include "Utilities/Gsl.hpp"
      19             : #include "Utilities/PrettyType.hpp"
      20             : #include "Utilities/Serialization/Serialize.hpp"
      21             : #include "Utilities/TMPL.hpp"
      22             : 
      23             : namespace LinearSolver::Schwarz {
      24             : 
      25             : /// Option tags related to the Schwarz solver
      26           1 : namespace OptionTags {
      27             : 
      28             : template <typename OptionsGroup>
      29           0 : struct MaxOverlap {
      30           0 :   using type = Options::Auto<size_t>;
      31           0 :   using group = OptionsGroup;
      32           0 :   static constexpr Options::String help =
      33             :       "Number of points that subdomains can extend into neighbors. "
      34             :       "'Auto' means no restriction, so the overlap covers the full neighbor.";
      35             : };
      36             : 
      37             : template <typename SolverType, typename OptionsGroup>
      38           0 : struct SubdomainSolver {
      39           0 :   using type = SolverType;
      40           0 :   using group = OptionsGroup;
      41           0 :   static constexpr Options::String help = "The linear solver on subdomains";
      42             : };
      43             : 
      44             : template <typename OptionsGroup>
      45           0 : struct SkipSubdomainSolverResets {
      46           0 :   static std::string name() { return "SkipResets"; }
      47           0 :   using type = bool;
      48           0 :   using group = OptionsGroup;
      49           0 :   static constexpr Options::String help =
      50             :       "Skip resets of the subdomain solver. This only has an effect in cases "
      51             :       "where the operator changes, e.g. between nonlinear-solver iterations. "
      52             :       "Skipping resets avoids expensive re-building of the operator, but comes "
      53             :       "at the cost of less accurate preconditioning and thus potentially more "
      54             :       "preconditioned iterations. Whether or not this helps convergence "
      55             :       "overall is highly problem-dependent.";
      56             : };
      57             : 
      58             : template <typename OptionsGroup>
      59           0 : struct ObservePerCoreReductions {
      60           0 :   using type = bool;
      61           0 :   using group = OptionsGroup;
      62           0 :   static constexpr Options::String help =
      63             :       "Output statistics per-core in a file per-node, e.g. to assess the load "
      64             :       "(im)balance of subdomain solves.";
      65             : };
      66             : 
      67             : }  // namespace OptionTags
      68             : 
      69             : /// Tags related to the Schwarz solver
      70             : namespace Tags {
      71             : 
      72             : /// Number of points a subdomain can overlap with its neighbor
      73             : template <typename OptionsGroup>
      74           1 : struct MaxOverlap : db::SimpleTag {
      75           0 :   static std::string name() {
      76             :     return "MaxOverlap(" + pretty_type::name<OptionsGroup>() + ")";
      77             :   }
      78           0 :   using type = std::optional<size_t>;
      79           0 :   static constexpr bool pass_metavariables = false;
      80           0 :   using option_tags = tmpl::list<OptionTags::MaxOverlap<OptionsGroup>>;
      81           0 :   static type create_from_options(const type& value) { return value; }
      82             : };
      83             : 
      84             : /// The serial linear solver of type `SolverType` used to solve subdomain
      85             : /// operators
      86             : template <typename SolverType, typename OptionsGroup>
      87           1 : struct SubdomainSolver : db::SimpleTag {
      88           0 :   using type = std::unique_ptr<SolverType>;
      89           0 :   static std::string name() {
      90             :     return "SubdomainSolver(" + pretty_type::name<OptionsGroup>() + ")";
      91             :   }
      92           0 :   static constexpr bool pass_metavariables = false;
      93           0 :   using option_tags = tmpl::list<
      94             :       OptionTags::SubdomainSolver<std::unique_ptr<SolverType>, OptionsGroup>>;
      95           0 :   static type create_from_options(const type& value) {
      96             :     return deserialize<type>(serialize<type>(value).data());
      97             :   }
      98             : };
      99             : 
     100             : /// Skip resets of the subdomain solver.
     101             : ///
     102             : /// \see LinearSolver::Schwarz::Actions::ResetSubdomainSolver
     103             : template <typename OptionsGroup>
     104           1 : struct SkipSubdomainSolverResets : db::SimpleTag {
     105           0 :   using type = bool;
     106           0 :   static constexpr bool pass_metavariables = false;
     107           0 :   using option_tags =
     108             :       tmpl::list<OptionTags::SkipSubdomainSolverResets<OptionsGroup>>;
     109           0 :   static bool create_from_options(const bool value) { return value; }
     110             : };
     111             : 
     112             : /// Enable per-core reduction observations
     113             : template <typename OptionsGroup>
     114           1 : struct ObservePerCoreReductions : db::SimpleTag {
     115           0 :   using type = bool;
     116           0 :   static constexpr bool pass_metavariables = false;
     117           0 :   using option_tags =
     118             :       tmpl::list<OptionTags::ObservePerCoreReductions<OptionsGroup>>;
     119           0 :   static bool create_from_options(const bool value) { return value; }
     120             : };
     121             : 
     122             : /*!
     123             :  * \brief The `Tag` on the overlap region with each neighbor, i.e. on a region
     124             :  * extruding from the central element.
     125             :  *
     126             :  * Note that data on an overlap with a neighbor is typically oriented according
     127             :  * to the neighbor's orientation, so re-orientation needs to happen whenever
     128             :  * the data cross element boundaries.
     129             :  */
     130             : template <typename Tag, size_t Dim, typename OptionsGroup>
     131           1 : struct Overlaps : db::SimpleTag {
     132           0 :   static std::string name() {
     133             :     return "Overlaps(" + db::tag_name<Tag>() + ", " +
     134             :            pretty_type::name<OptionsGroup>() + ")";
     135             :   }
     136           0 :   using tag = Tag;
     137           0 :   using type = OverlapMap<Dim, typename Tag::type>;
     138             : };
     139             : 
     140             : /// The number of points a neighbor's subdomain extends into the element
     141             : template <size_t Dim, typename OptionsGroup>
     142           1 : struct IntrudingExtents : db::SimpleTag {
     143           0 :   static std::string name() {
     144             :     return "IntrudingExtents(" + pretty_type::name<OptionsGroup>() + ")";
     145             :   }
     146           0 :   using type = std::array<size_t, Dim>;
     147             : };
     148             : 
     149             : /// The width in element-logical coordinates that a neighbor's subdomain extends
     150             : /// into the element
     151             : template <size_t Dim, typename OptionsGroup>
     152           1 : struct IntrudingOverlapWidths : db::SimpleTag {
     153           0 :   static std::string name() {
     154             :     return "IntrudingOverlapWidths(" + pretty_type::name<OptionsGroup>() + ")";
     155             :   }
     156           0 :   using type = std::array<double, Dim>;
     157             : };
     158             : 
     159             : /// Weighting field for combining data from multiple overlapping subdomains
     160             : template <typename OptionsGroup>
     161           1 : struct Weight : db::SimpleTag {
     162           0 :   static std::string name() {
     163             :     return "Weight(" + pretty_type::name<OptionsGroup>() + ")";
     164             :   }
     165           0 :   using type = Scalar<DataVector>;
     166             : };
     167             : 
     168             : /*!
     169             :  * \brief A diagnostic quantity to check that weights are conserved
     170             :  *
     171             :  * This quantity and the `Tags::Weight` on the element should sum to one on all
     172             :  * grid points. Residual values indicate that overlap data from neighboring
     173             :  * subdomains and data on the element are combined in a non-conservative way.
     174             :  */
     175             : template <typename OptionsGroup>
     176           1 : struct SummedIntrudingOverlapWeights : db::SimpleTag {
     177           0 :   static std::string name() {
     178             :     return "SummedIntrudingOverlapWeights(" +
     179             :            pretty_type::name<OptionsGroup>() + ")";
     180             :   }
     181           0 :   using type = Scalar<DataVector>;
     182             : };
     183             : 
     184             : /// Buffer for recording volume data
     185             : template <typename SubdomainDataType, typename OptionsGroup>
     186           1 : struct VolumeDataForOutput : db::SimpleTag {
     187           0 :   using type = SubdomainDataType;
     188           0 :   static std::string name() {
     189             :     return "VolumeDataForOutput(" + pretty_type::name<OptionsGroup>() + ")";
     190             :   }
     191             : };
     192             : }  // namespace Tags
     193             : }  // namespace LinearSolver::Schwarz
     194             : 
     195             : namespace db {
     196             : namespace detail {
     197             : // This implementation mirrors the interface tag subitems in `Domain/Tags.hpp`.
     198             : // Please see that implementation for details.
     199             : template <typename VariablesTag, size_t Dim, typename OptionsGroup,
     200             :           typename Tags = typename VariablesTag::type::tags_list>
     201             : struct OverlapSubitemsImpl;
     202             : 
     203             : template <typename VariablesTag, size_t Dim, typename OptionsGroup,
     204             :           typename... Tags>
     205             : struct OverlapSubitemsImpl<VariablesTag, Dim, OptionsGroup,
     206             :                            tmpl::list<Tags...>> {
     207             :   using type = tmpl::list<
     208             :       LinearSolver::Schwarz::Tags::Overlaps<Tags, Dim, OptionsGroup>...>;
     209             :   using tag =
     210             :       LinearSolver::Schwarz::Tags::Overlaps<VariablesTag, Dim, OptionsGroup>;
     211             :   using return_type = NoSuchType;
     212             :   template <typename Subtag>
     213             :   static void create_item(
     214             :       const gsl::not_null<typename tag::type*> parent_value,
     215             :       const gsl::not_null<typename Subtag::type*> sub_value) {
     216             :     sub_value->clear();
     217             :     for (auto& [overlap_id, parent_overlap_vars] : *parent_value) {
     218             :       auto& parent_overlap_field =
     219             :           get<typename Subtag::tag>(parent_overlap_vars);
     220             :       auto& sub_overlap_field = (*sub_value)[overlap_id];
     221             :       for (size_t i = 0; i < parent_overlap_field.size(); ++i) {
     222             :         sub_overlap_field[i].set_data_ref(&parent_overlap_field[i]);
     223             :       }
     224             :     }
     225             :   }
     226             :   template <typename Subtag>
     227             :   static void create_compute_item(
     228             :       const gsl::not_null<typename Subtag::type*> sub_value,
     229             :       const typename tag::type& parent_value) {
     230             :     for (const auto& [overlap_id, parent_overlap_vars] : parent_value) {
     231             :       const auto& parent_overlap_field =
     232             :           get<typename Subtag::tag>(parent_overlap_vars);
     233             :       auto& sub_overlap_field = (*sub_value)[overlap_id];
     234             :       for (size_t i = 0; i < parent_overlap_field.size(); ++i) {
     235             :         // clang-tidy: do not use const_cast
     236             :         // The DataBox will only give out a const reference to the result of a
     237             :         // compute item. Here, that is a reference to a const map to Tensors of
     238             :         // DataVectors. There is no (publicly visible) indirection there, so
     239             :         // having the map const will allow only const access to the contained
     240             :         // DataVectors, so no modification through the pointer cast here is
     241             :         // possible. See the implementation of subitems in `Domain/Tags.hpp` for
     242             :         // details.
     243             :         sub_overlap_field[i].set_data_ref(
     244             :             const_cast<DataVector*>(&parent_overlap_field[i]));  // NOLINT
     245             :       }
     246             :     }
     247             :   }
     248             : };
     249             : }  // namespace detail
     250             : 
     251             : template <typename VariablesTag, size_t Dim, typename OptionsGroup>
     252           0 : struct Subitems<
     253             :     LinearSolver::Schwarz::Tags::Overlaps<VariablesTag, Dim, OptionsGroup>,
     254             :     Requires<tt::is_a_v<Variables, typename VariablesTag::type>>>
     255             :     : detail::OverlapSubitemsImpl<VariablesTag, Dim, OptionsGroup> {};
     256             : 
     257             : }  // namespace db

Generated by: LCOV version 1.14