SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/LinearSolver/AsynchronousSolvers - ElementActions.hpp Hit Total Coverage
Commit: b1342d46f40e2d46bbd11d0cef68fd973031a24b Lines: 1 27 3.7 %
Date: 2020-09-24 20:24: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 <limits>
       7             : #include <string>
       8             : #include <tuple>
       9             : #include <utility>
      10             : #include <vector>
      11             : 
      12             : #include "DataStructures/DataBox/DataBox.hpp"
      13             : #include "DataStructures/DataBox/PrefixHelpers.hpp"
      14             : #include "IO/Observer/Actions/RegisterWithObservers.hpp"
      15             : #include "IO/Observer/ArrayComponentId.hpp"
      16             : #include "IO/Observer/Helpers.hpp"
      17             : #include "IO/Observer/ObservationId.hpp"
      18             : #include "IO/Observer/ObserverComponent.hpp"
      19             : #include "IO/Observer/ReductionActions.hpp"
      20             : #include "IO/Observer/TypeOfObservation.hpp"
      21             : #include "Informer/Verbosity.hpp"
      22             : #include "NumericalAlgorithms/Convergence/HasConverged.hpp"
      23             : #include "NumericalAlgorithms/LinearSolver/Gmres.hpp"
      24             : #include "NumericalAlgorithms/LinearSolver/InnerProduct.hpp"
      25             : #include "Parallel/GlobalCache.hpp"
      26             : #include "Parallel/Invoke.hpp"
      27             : #include "Parallel/Printf.hpp"
      28             : #include "Parallel/Reduction.hpp"
      29             : #include "ParallelAlgorithms/Initialization/MergeIntoDataBox.hpp"
      30             : #include "ParallelAlgorithms/LinearSolver/Tags.hpp"
      31             : #include "Utilities/GetOutput.hpp"
      32             : #include "Utilities/Gsl.hpp"
      33             : #include "Utilities/PrettyType.hpp"
      34             : #include "Utilities/Requires.hpp"
      35             : #include "Utilities/TMPL.hpp"
      36             : 
      37             : /// \cond
      38             : namespace tuples {
      39             : template <typename...>
      40             : class TaggedTuple;
      41             : }  // namespace tuples
      42             : /// \endcond
      43             : 
      44             : /// Functionality shared between parallel linear solvers that have no global
      45             : /// synchronization points
      46           1 : namespace LinearSolver::async_solvers {
      47             : 
      48           0 : using reduction_data = Parallel::ReductionData<
      49             :     // Iteration
      50             :     Parallel::ReductionDatum<size_t, funcl::AssertEqual<>>,
      51             :     // Residual
      52             :     Parallel::ReductionDatum<double, funcl::Plus<>, funcl::Sqrt<>>>;
      53             : 
      54             : template <typename FieldsTag, typename OptionsGroup, typename ParallelComponent,
      55             :           typename DbTagsList, typename Metavariables, typename ArrayIndex>
      56           0 : void contribute_to_residual_observation(
      57             :     const db::DataBox<DbTagsList>& box,
      58             :     Parallel::GlobalCache<Metavariables>& cache,
      59             :     const ArrayIndex& array_index) noexcept {
      60             :   using residual_tag =
      61             :       db::add_tag_prefix<LinearSolver::Tags::Residual, FieldsTag>;
      62             :   using residual_magnitude_square_tag =
      63             :       LinearSolver::Tags::MagnitudeSquare<residual_tag>;
      64             : 
      65             :   const size_t iteration_id =
      66             :       get<LinearSolver::Tags::IterationId<OptionsGroup>>(box);
      67             :   const double residual_magnitude_square =
      68             :       get<residual_magnitude_square_tag>(box);
      69             :   auto& local_observer =
      70             :       *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
      71             :            cache)
      72             :            .ckLocalBranch();
      73             :   Parallel::simple_action<observers::Actions::ContributeReductionData>(
      74             :       local_observer,
      75             :       observers::ObservationId(iteration_id,
      76             :                                pretty_type::get_name<OptionsGroup>()),
      77             :       observers::ArrayComponentId{
      78             :           std::add_pointer_t<ParallelComponent>{nullptr},
      79             :           Parallel::ArrayIndex<ArrayIndex>(array_index)},
      80             :       std::string{"/" + Options::name<OptionsGroup>() + "Residuals"},
      81             :       std::vector<std::string>{"Iteration", "Residual"},
      82             :       reduction_data{iteration_id, residual_magnitude_square});
      83             :   if (UNLIKELY(static_cast<int>(
      84             :                    get<LinearSolver::Tags::Verbosity<OptionsGroup>>(cache)) >=
      85             :                static_cast<int>(::Verbosity::Verbose))) {
      86             :     if (iteration_id == 0) {
      87             :       Parallel::printf(
      88             :           "Linear solver '" + Options::name<OptionsGroup>() +
      89             :               "' initialized on element %s. Remaining local residual: %e\n",
      90             :           get_output(array_index), sqrt(residual_magnitude_square));
      91             :     } else {
      92             :       Parallel::printf("Linear solver '" +
      93             :                            Options::name<OptionsGroup>() +
      94             :                            "' iteration %zu done on element %s. Remaining "
      95             :                            "local residual: %e\n",
      96             :                        iteration_id, get_output(array_index),
      97             :                        sqrt(residual_magnitude_square));
      98             :     }
      99             :   }
     100             : }
     101             : 
     102             : template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
     103           0 : struct InitializeElement {
     104             :  private:
     105           0 :   using fields_tag = FieldsTag;
     106           0 :   using operator_applied_to_fields_tag =
     107             :       db::add_tag_prefix<LinearSolver::Tags::OperatorAppliedTo, fields_tag>;
     108           0 :   using source_tag = SourceTag;
     109           0 :   using residual_tag =
     110             :       db::add_tag_prefix<LinearSolver::Tags::Residual, fields_tag>;
     111           0 :   using residual_magnitude_square_tag =
     112             :       LinearSolver::Tags::MagnitudeSquare<residual_tag>;
     113             : 
     114             :  public:
     115           0 :   using const_global_cache_tags =
     116             :       tmpl::list<LinearSolver::Tags::Iterations<OptionsGroup>>;
     117             : 
     118             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     119             :             typename ArrayIndex, typename ActionList,
     120             :             typename ParallelComponent>
     121           0 :   static auto apply(db::DataBox<DbTagsList>& box,
     122             :                     const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     123             :                     const Parallel::GlobalCache<Metavariables>& /*cache*/,
     124             :                     const ArrayIndex& /*array_index*/,
     125             :                     const ActionList /*meta*/,
     126             :                     const ParallelComponent* const /*meta*/) noexcept {
     127             :     return std::make_tuple(
     128             :         ::Initialization::merge_into_databox<
     129             :             InitializeElement,
     130             :             db::AddSimpleTags<LinearSolver::Tags::IterationId<OptionsGroup>,
     131             :                               residual_magnitude_square_tag,
     132             :                               operator_applied_to_fields_tag>,
     133             :             db::AddComputeTags<
     134             :                 LinearSolver::Tags::ResidualCompute<fields_tag, source_tag>,
     135             :                 LinearSolver::Tags::HasConvergedByIterationsCompute<
     136             :                     OptionsGroup>>>(
     137             :             std::move(box),
     138             :             // The `PrepareSolve` action populates these tags with initial
     139             :             // values, except for `operator_applied_to_fields_tag` which is
     140             :             // expected to be updated in every iteration of the algorithm
     141             :             std::numeric_limits<size_t>::max(),
     142             :             std::numeric_limits<double>::signaling_NaN(),
     143             :             typename operator_applied_to_fields_tag::type{}));
     144             :   }
     145             : };
     146             : 
     147             : template <typename OptionsGroup>
     148           0 : struct RegisterObservers {
     149             :   template <typename ParallelComponent, typename DbTagsList,
     150             :             typename ArrayIndex>
     151             :   static std::pair<observers::TypeOfObservation, observers::ObservationKey>
     152           0 :   register_info(const db::DataBox<DbTagsList>& /*box*/,
     153             :                 const ArrayIndex& /*array_index*/) noexcept {
     154             :     return {observers::TypeOfObservation::Reduction,
     155             :             observers::ObservationKey{pretty_type::get_name<OptionsGroup>()}};
     156             :   }
     157             : };
     158             : 
     159             : template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
     160           0 : using RegisterElement =
     161             :     observers::Actions::RegisterWithObservers<RegisterObservers<OptionsGroup>>;
     162             : 
     163             : template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
     164           0 : struct PrepareSolve {
     165             :  private:
     166           0 :   using fields_tag = FieldsTag;
     167           0 :   using residual_tag =
     168             :       db::add_tag_prefix<LinearSolver::Tags::Residual, FieldsTag>;
     169           0 :   using residual_magnitude_square_tag =
     170             :       LinearSolver::Tags::MagnitudeSquare<residual_tag>;
     171             : 
     172             :  public:
     173           0 :   using const_global_cache_tags =
     174             :       tmpl::list<LinearSolver::Tags::Verbosity<OptionsGroup>>;
     175             : 
     176             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     177             :             typename ArrayIndex, typename ActionList,
     178             :             typename ParallelComponent>
     179           0 :   static std::tuple<db::DataBox<DbTagsList>&&> apply(
     180             :       db::DataBox<DbTagsList>& box,
     181             :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     182             :       Parallel::GlobalCache<Metavariables>& cache,
     183             :       const ArrayIndex& array_index, const ActionList /*meta*/,
     184             :       const ParallelComponent* const /*meta*/) noexcept {
     185             :     db::mutate<LinearSolver::Tags::IterationId<OptionsGroup>,
     186             :                residual_magnitude_square_tag>(
     187             :         make_not_null(&box),
     188             :         [](const gsl::not_null<size_t*> iteration_id,
     189             :            const gsl::not_null<double*> residual_magnitude_square,
     190             :            const auto& residual) noexcept {
     191             :           *iteration_id = 0;
     192             :           *residual_magnitude_square = inner_product(residual, residual);
     193             :         },
     194             :         get<residual_tag>(box));
     195             :     // Observe the initial residual even if no steps are going to be performed
     196             :     contribute_to_residual_observation<FieldsTag, OptionsGroup,
     197             :                                        ParallelComponent>(box, cache,
     198             :                                                           array_index);
     199             :     return {std::move(box)};
     200             :   }
     201             : };
     202             : 
     203             : template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
     204           0 : struct CompleteStep {
     205             :  private:
     206           0 :   using fields_tag = FieldsTag;
     207           0 :   using residual_tag =
     208             :       db::add_tag_prefix<LinearSolver::Tags::Residual, fields_tag>;
     209           0 :   using residual_magnitude_square_tag =
     210             :       LinearSolver::Tags::MagnitudeSquare<residual_tag>;
     211             : 
     212             :  public:
     213           0 :   using const_global_cache_tags =
     214             :       tmpl::list<LinearSolver::Tags::Verbosity<OptionsGroup>>;
     215             : 
     216             :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
     217             :             typename ArrayIndex, typename ActionList,
     218             :             typename ParallelComponent>
     219           0 :   static std::tuple<db::DataBox<DbTagsList>&&> apply(
     220             :       db::DataBox<DbTagsList>& box,
     221             :       tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     222             :       Parallel::GlobalCache<Metavariables>& cache,
     223             :       const ArrayIndex& array_index, const ActionList /*meta*/,
     224             :       const ParallelComponent* const /*meta*/) noexcept {
     225             :     // Update and observe element-local residual magnitude
     226             :     db::mutate<residual_magnitude_square_tag,
     227             :                LinearSolver::Tags::IterationId<OptionsGroup>>(
     228             :         make_not_null(&box),
     229             :         [](const gsl::not_null<double*> residual_magnitude_square,
     230             :            const gsl::not_null<size_t*> iteration_id,
     231             :            const auto& residual) noexcept {
     232             :           *residual_magnitude_square = inner_product(residual, residual);
     233             :           ++(*iteration_id);
     234             :         },
     235             :         get<residual_tag>(box));
     236             :     contribute_to_residual_observation<FieldsTag, OptionsGroup,
     237             :                                        ParallelComponent>(box, cache,
     238             :                                                           array_index);
     239             :     return {std::move(box)};
     240             :   }
     241             : };
     242             : 
     243             : }  // namespace LinearSolver::async_solvers

Generated by: LCOV version 1.14