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

Generated by: LCOV version 1.14