ElementActions.hpp
1 // 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 
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"
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"
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
47 
48 using reduction_data = Parallel::ReductionData<
49  // Iteration
51  // Residual
53 
54 template <typename FieldsTag, typename OptionsGroup, typename ParallelComponent,
55  typename DbTagsList, typename Metavariables, typename ArrayIndex>
56 void contribute_to_residual_observation(
57  const db::DataBox<DbTagsList>& box,
59  const ArrayIndex& array_index) noexcept {
60  using residual_tag =
62  using residual_magnitude_square_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>()),
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>(
85  static_cast<int>(::Verbosity::Verbose))) {
86  if (iteration_id == 0) {
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>
104  private:
105  using fields_tag = FieldsTag;
106  using operator_applied_to_fields_tag =
108  using source_tag = SourceTag;
109  using residual_tag =
113 
114  public:
115  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  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(
132  operator_applied_to_fields_tag>,
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
143  typename operator_applied_to_fields_tag::type{}));
144  }
145 };
146 
147 template <typename OptionsGroup>
149  template <typename ParallelComponent, typename DbTagsList,
150  typename ArrayIndex>
152  register_info(const db::DataBox<DbTagsList>& /*box*/,
153  const ArrayIndex& /*array_index*/) noexcept {
155  observers::ObservationKey{pretty_type::get_name<OptionsGroup>()}};
156  }
157 };
158 
159 template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
160 using RegisterElement =
162 
163 template <typename FieldsTag, typename OptionsGroup, typename SourceTag>
164 struct PrepareSolve {
165  private:
166  using fields_tag = FieldsTag;
167  using residual_tag =
171 
172  public:
173  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>
181  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
183  const ArrayIndex& array_index, const ActionList /*meta*/,
184  const ParallelComponent* const /*meta*/) noexcept {
185  db::mutate<LinearSolver::Tags::IterationId<OptionsGroup>,
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 struct CompleteStep {
205  private:
206  using fields_tag = FieldsTag;
207  using residual_tag =
211 
212  public:
213  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>
223  const ArrayIndex& array_index, const ActionList /*meta*/,
224  const ParallelComponent* const /*meta*/) noexcept {
225  // Update and observe element-local residual magnitude
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
observers::ObservationId
A unique identifier for an observation representing the type of observation and the instance (e....
Definition: ObservationId.hpp:71
LinearSolver::Tags::MagnitudeSquare
The magnitude square w.r.t. the LinearSolver::inner_product
Definition: Tags.hpp:136
std::string
utility
UNLIKELY
#define UNLIKELY(x)
Definition: Gsl.hpp:73
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:639
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:16
Parallel::ReductionDatum
The data to be reduced, and invokables to be called whenever two reduction messages are combined and ...
Definition: Reduction.hpp:63
InnerProduct.hpp
std::pair
GlobalCache.hpp
vector
PrettyType.hpp
Parallel::printf
void printf(const std::string &format, Args &&... args)
Print an atomic message to stdout with C printf usage.
Definition: Printf.hpp:103
LinearSolver::Tags::IterationId
Holds an IterationId that identifies a step in the linear solver algorithm.
Definition: Tags.hpp:84
db::add_tag_prefix
typename detail::add_tag_prefix_impl< Prefix, Tag, Args... >::type add_tag_prefix
Definition: PrefixHelpers.hpp:52
observers::ObservationKey
Used as a key in maps to keep track of how many elements have registered.
Definition: ObservationId.hpp:28
db::AddComputeTags
tmpl::flatten< tmpl::list< Tags... > > AddComputeTags
List of Compute Item Tags to add to the DataBox.
Definition: DataBox.hpp:1153
tuple
LinearSolver::async_solvers::RegisterObservers
Definition: ElementActions.hpp:148
LinearSolver::async_solvers::InitializeElement
Definition: ElementActions.hpp:103
Tags.hpp
db::mutate
void mutate(const gsl::not_null< DataBox< TagList > * > box, Invokable &&invokable, Args &&... args) noexcept
Allows changing the state of one or more non-computed elements in the DataBox.
Definition: DataBox.hpp:1003
get_output
std::string get_output(const T &t) noexcept
Get the streamed output of t as a std::string
Definition: GetOutput.hpp:14
funcl::Sqrt
Functional for computing sqrt on an object.
Definition: Functional.hpp:273
db::apply
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args) noexcept
Apply the invokable f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1424
std::add_pointer_t
Printf.hpp
LinearSolver::inner_product
double inner_product(const Lhs &lhs, const Rhs &rhs) noexcept
The local part of the Euclidean inner product on the vector space w.r.t. which the addition and scala...
Definition: InnerProduct.hpp:71
DataBox.hpp
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
db::AddSimpleTags
tmpl::flatten< tmpl::list< Tags... > > AddSimpleTags
List of Tags to add to the DataBox.
Definition: DataBox.hpp:1132
LinearSolver::Tags::Verbosity
Definition: Tags.hpp:377
limits
Gsl.hpp
LinearSolver::async_solvers
Functionality shared between parallel linear solvers that have no global synchronization points.
Definition: ElementActions.hpp:46
Requires.hpp
observers::TypeOfObservation::Reduction
@ Reduction
The sender will only perform reduction observations.
Initialization::merge_into_databox
auto merge_into_databox(db::DataBox< DbTagsList > &&box, Args &&... args) noexcept
Add tags that are not yet in the DataBox.
Definition: MergeIntoDataBox.hpp:133
observers::ArrayComponentId
An ID type that identifies both the parallel component and the index in the parallel component.
Definition: ArrayComponentId.hpp:27
LinearSolver::Tags::HasConvergedByIterationsCompute
Employs the LinearSolver::Tags::Iterations to determine the linear solver has converged once it has c...
Definition: Tags.hpp:274
LinearSolver::async_solvers::PrepareSolve
Definition: ElementActions.hpp:164
LinearSolver::Tags::ResidualCompute
Compute the residual from the SourceTag and the db::add_tag_prefix<LinearSolver::Tags::OperatorAppl...
Definition: Tags.hpp:110
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
Parallel::ArrayIndex
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:27
db::DataBox
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
std::numeric_limits
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: Gsl.hpp:183
observers::Actions::RegisterWithObservers
Register an observation ID with the observers.
Definition: RegisterWithObservers.hpp:39
LinearSolver::async_solvers::CompleteStep
Definition: ElementActions.hpp:204
string