ElementActions.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <map>
8 #include <string>
9 #include <tuple>
10 #include <unordered_map>
11 #include <utility>
12 #include <vector>
13 
15 #include "DataStructures/DataBox/PrefixHelpers.hpp"
16 #include "DataStructures/DataBox/Tag.hpp"
17 #include "DataStructures/Index.hpp"
19 #include "Domain/Structure/DirectionMap.hpp"
22 #include "Domain/Structure/OrientationMapHelpers.hpp"
23 #include "Domain/Tags.hpp"
24 #include "Domain/Tags/Faces.hpp"
25 #include "IO/Logging/Tags.hpp"
26 #include "IO/Logging/Verbosity.hpp"
27 #include "IO/Observer/Actions/RegisterWithObservers.hpp"
28 #include "IO/Observer/ArrayComponentId.hpp"
29 #include "IO/Observer/GetSectionObservationKey.hpp"
30 #include "IO/Observer/ObservationId.hpp"
31 #include "IO/Observer/Protocols/ReductionDataFormatter.hpp"
32 #include "IO/Observer/ReductionActions.hpp"
33 #include "IO/Observer/Tags.hpp"
34 #include "IO/Observer/TypeOfObservation.hpp"
35 #include "NumericalAlgorithms/Convergence/Tags.hpp"
36 #include "NumericalAlgorithms/DiscontinuousGalerkin/HasReceivedFromAllMortars.hpp"
37 #include "NumericalAlgorithms/LinearSolver/ExplicitInverse.hpp"
38 #include "NumericalAlgorithms/LinearSolver/Gmres.hpp"
41 #include "Options/Options.hpp"
42 #include "Parallel/AlgorithmMetafunctions.hpp"
43 #include "Parallel/GlobalCache.hpp"
44 #include "Parallel/InboxInserters.hpp"
45 #include "Parallel/Invoke.hpp"
46 #include "Parallel/ParallelComponentHelpers.hpp"
47 #include "Parallel/Printf.hpp"
48 #include "Parallel/Reduction.hpp"
49 #include "ParallelAlgorithms/Initialization/MergeIntoDataBox.hpp"
50 #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
51 #include "ParallelAlgorithms/LinearSolver/AsynchronousSolvers/ElementActions.hpp"
53 #include "ParallelAlgorithms/LinearSolver/Schwarz/ElementCenteredSubdomainData.hpp"
54 #include "ParallelAlgorithms/LinearSolver/Schwarz/OverlapHelpers.hpp"
55 #include "ParallelAlgorithms/LinearSolver/Schwarz/Tags.hpp"
56 #include "ParallelAlgorithms/LinearSolver/Schwarz/Weighting.hpp"
58 #include "Utilities/Gsl.hpp"
59 #include "Utilities/PrettyType.hpp"
60 #include "Utilities/ProtocolHelpers.hpp"
61 #include "Utilities/TMPL.hpp"
62 #include "Utilities/TaggedTuple.hpp"
63 
64 namespace LinearSolver::Schwarz::detail {
65 
66 using reduction_data = Parallel::ReductionData<
67  // Iteration
69  // Number of subdomains (= number of elements)
71  // Average number of subdomain solver iterations
74  // Minimum number of subdomain solver iterations
76  // Maximum number of subdomain solver iterations
78 
79 template <typename OptionsGroup>
80 struct SubdomainStatsFormatter
81  : tt::ConformsTo<observers::protocols::ReductionDataFormatter> {
82  using reduction_data = Schwarz::detail::reduction_data;
83  SubdomainStatsFormatter() noexcept = default;
84  SubdomainStatsFormatter(std::string local_section_observation_key) noexcept
85  : section_observation_key(std::move(local_section_observation_key)) {}
86  std::string operator()(const size_t iteration_id, const size_t num_subdomains,
87  const size_t avg_subdomain_its,
88  const size_t min_subdomain_its,
89  const size_t max_subdomain_its) const noexcept {
90  return Options::name<OptionsGroup>() + section_observation_key + "(" +
91  get_output(iteration_id) + ") completed all " +
92  get_output(num_subdomains) +
93  " subdomain solves. Average of number of iterations: " +
94  get_output(avg_subdomain_its) + " (min " +
95  get_output(min_subdomain_its) + ", max " +
96  get_output(max_subdomain_its) + ").";
97  }
98  // NOLINTNEXTLINE(google-runtime-references)
99  void pup(PUP::er& p) noexcept { p | section_observation_key; }
100  std::string section_observation_key{};
101 };
102 
103 template <typename OptionsGroup, typename ArraySectionIdTag>
104 struct RegisterObservers {
105  template <typename ParallelComponent, typename DbTagsList,
106  typename ArrayIndex>
108  register_info(const db::DataBox<DbTagsList>& box,
109  const ArrayIndex& /*array_index*/) noexcept {
110  // Get the observation key, or "Unused" if the element does not belong
111  // to a section with this tag. In the latter case, no observations will
112  // ever be contributed.
113  const std::optional<std::string>& section_observation_key =
114  observers::get_section_observation_key<ArraySectionIdTag>(box);
115  ASSERT(section_observation_key != "Unused",
116  "The identifier 'Unused' is reserved to indicate that no "
117  "observations with this key will be contributed. Use a different "
118  "key, or change the identifier 'Unused' to something else.");
119  return {
121  observers::ObservationKey{pretty_type::get_name<OptionsGroup>() +
122  section_observation_key.value_or("Unused") +
123  "SubdomainSolves"}};
124  }
125 };
126 
127 template <typename FieldsTag, typename OptionsGroup, typename SourceTag,
128  typename ArraySectionIdTag>
129 using RegisterElement = observers::Actions::RegisterWithObservers<
130  RegisterObservers<OptionsGroup, ArraySectionIdTag>>;
131 
132 template <typename OptionsGroup, typename ParallelComponent,
133  typename Metavariables, typename ArrayIndex>
134 void contribute_to_subdomain_stats_observation(
135  const size_t iteration_id, const size_t subdomain_solve_num_iterations,
136  Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index,
137  const std::string& section_observation_key) noexcept {
138  auto& local_observer =
139  *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
140  cache)
141  .ckLocalBranch();
142  auto formatter =
144  ::Verbosity::Verbose)
145  ? std::make_optional(
146  SubdomainStatsFormatter<OptionsGroup>{section_observation_key})
147  : std::nullopt;
148  Parallel::simple_action<observers::Actions::ContributeReductionData>(
149  local_observer,
150  observers::ObservationId(iteration_id,
151  pretty_type::get_name<OptionsGroup>() +
152  section_observation_key + "SubdomainSolves"),
155  Parallel::ArrayIndex<ArrayIndex>(array_index)},
156  std::string{"/" + Options::name<OptionsGroup>() +
157  section_observation_key + "SubdomainSolves"},
158  std::vector<std::string>{"Iteration", "NumSubdomains", "AvgNumIterations",
159  "MinNumIterations", "MaxNumIterations"},
160  reduction_data{iteration_id, 1, subdomain_solve_num_iterations,
161  subdomain_solve_num_iterations,
162  subdomain_solve_num_iterations},
163  std::move(formatter));
164 }
165 
166 template <typename SubdomainDataType, typename OptionsGroup>
167 struct SubdomainDataBufferTag : db::SimpleTag {
168  static std::string name() noexcept {
169  return "SubdomainData(" + Options::name<OptionsGroup>() + ")";
170  }
171  using type = SubdomainDataType;
172 };
173 
174 // Allow factory-creating any of these serial linear solvers for use as
175 // subdomain solver
176 template <typename FieldsTag, typename SubdomainOperator,
177  typename SubdomainData = ElementCenteredSubdomainData<
178  SubdomainOperator::volume_dim,
180  FieldsTag>::tags_list>>
181 using subdomain_solver = LinearSolver::Serial::LinearSolver<
182  tmpl::list<::LinearSolver::Serial::Registrars::Gmres<SubdomainData>,
184 
185 template <typename FieldsTag, typename OptionsGroup, typename SubdomainOperator>
186 struct InitializeElement {
187  private:
188  using fields_tag = FieldsTag;
189  using residual_tag =
191  static constexpr size_t Dim = SubdomainOperator::volume_dim;
192  using SubdomainData =
193  ElementCenteredSubdomainData<Dim, typename residual_tag::tags_list>;
194  using subdomain_solver_tag = Tags::SubdomainSolver<
196  OptionsGroup>;
197 
198  public:
199  using initialization_tags =
200  tmpl::list<domain::Tags::InitialExtents<Dim>, subdomain_solver_tag>;
201  using initialization_tags_to_keep = tmpl::list<subdomain_solver_tag>;
202  using const_global_cache_tags = tmpl::list<Tags::MaxOverlap<OptionsGroup>>;
203 
204  using simple_tags =
205  tmpl::list<Tags::IntrudingExtents<Dim, OptionsGroup>,
206  Tags::Weight<OptionsGroup>,
208  SubdomainDataBufferTag<SubdomainData, OptionsGroup>>;
209  using compute_tags = tmpl::list<>;
210  template <typename DbTagsList, typename... InboxTags, typename Metavariables,
211  typename ActionList, typename ParallelComponent>
212  static auto apply(db::DataBox<DbTagsList>& box,
213  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
214  const Parallel::GlobalCache<Metavariables>& /*cache*/,
215  const ElementId<Dim>& /*element_id*/,
216  const ActionList /*meta*/,
217  const ParallelComponent* const /*meta*/) noexcept {
218  const auto& element = db::get<domain::Tags::Element<Dim>>(box);
219  const auto& mesh = db::get<domain::Tags::Mesh<Dim>>(box);
220  const size_t num_points = mesh.number_of_grid_points();
221  const auto& logical_coords =
222  db::get<domain::Tags::Coordinates<Dim, Frame::Logical>>(box);
223  const size_t max_overlap = db::get<Tags::MaxOverlap<OptionsGroup>>(box);
224 
225  // Intruding overlaps
226  std::array<size_t, Dim> intruding_extents{};
227  std::array<double, Dim> intruding_overlap_widths{};
228  for (size_t d = 0; d < Dim; ++d) {
229  gsl::at(intruding_extents, d) =
230  LinearSolver::Schwarz::overlap_extent(mesh.extents(d), max_overlap);
231  const auto& collocation_points =
232  Spectral::collocation_points(mesh.slice_through(d));
233  gsl::at(intruding_overlap_widths, d) =
234  LinearSolver::Schwarz::overlap_width(gsl::at(intruding_extents, d),
236  }
237 
238  // Element weight
239  Scalar<DataVector> element_weight{num_points, 1.};
240  // For max_overlap > 0 all overlaps will have non-zero extents on an LGL
241  // mesh (because it has at least 2 points per dimension), so we don't need
242  // to check their extents are non-zero individually
243  if (LIKELY(max_overlap > 0)) {
245  make_not_null(&element_weight), logical_coords,
246  intruding_overlap_widths, element.external_boundaries());
247  }
248 
249  // Intruding overlap weights
250  DirectionMap<Dim, Scalar<DataVector>> intruding_overlap_weights{};
251  for (const auto& direction : element.internal_boundaries()) {
252  const size_t dim = direction.dimension();
253  if (gsl::at(intruding_extents, dim) > 0) {
254  const auto intruding_logical_coords =
256  logical_coords, mesh.extents(), gsl::at(intruding_extents, dim),
257  direction);
258  intruding_overlap_weights[direction] =
260  intruding_logical_coords, direction, intruding_overlap_widths,
261  element.neighbors().at(direction).size(),
262  element.external_boundaries());
263  }
264  }
265 
266  Initialization::mutate_assign<simple_tags>(
267  make_not_null(&box), std::move(intruding_extents),
268  std::move(element_weight), std::move(intruding_overlap_weights),
269  SubdomainData{num_points});
270  return std::make_tuple(std::move(box));
271  }
272 };
273 
274 // Restrict the residual to neighboring subdomains that overlap with this
275 // element and send the data to those elements
276 template <typename FieldsTag, typename OptionsGroup, typename SubdomainOperator>
278  tmpl::list<db::add_tag_prefix<LinearSolver::Tags::Residual, FieldsTag>>,
279  OptionsGroup, true>;
280 
281 template <size_t Dim, typename OptionsGroup, typename OverlapSolution>
282 struct OverlapSolutionInboxTag
284  OverlapSolutionInboxTag<Dim, OptionsGroup, OverlapSolution>> {
285  using temporal_id = size_t;
287 };
288 
289 // Wait for the residual data on regions of this element's subdomain that
290 // overlap with other elements. Once the residual data is available on all
291 // overlaps, solve the restricted problem for this element-centered subdomain.
292 // Apply the weighted solution on this element directly and send the solution on
293 // overlap regions to the neighbors that they overlap with.
294 template <typename FieldsTag, typename OptionsGroup, typename SubdomainOperator,
295  typename ArraySectionIdTag>
296 struct SolveSubdomain {
297  private:
298  using fields_tag = FieldsTag;
299  using residual_tag =
301  static constexpr size_t Dim = SubdomainOperator::volume_dim;
302  using overlap_residuals_inbox_tag =
303  Actions::detail::OverlapFieldsTag<Dim, tmpl::list<residual_tag>,
304  OptionsGroup>;
305  using SubdomainData =
306  ElementCenteredSubdomainData<Dim, typename residual_tag::tags_list>;
307  using OverlapData = typename SubdomainData::OverlapData;
308  using overlap_solution_inbox_tag =
309  OverlapSolutionInboxTag<Dim, OptionsGroup, OverlapData>;
310 
311  public:
312  using const_global_cache_tags =
313  tmpl::list<Tags::MaxOverlap<OptionsGroup>,
315  using inbox_tags = tmpl::list<overlap_residuals_inbox_tag>;
316 
317  template <typename DbTagsList, typename... InboxTags, typename Metavariables,
318  typename ActionList, typename ParallelComponent>
320  apply(db::DataBox<DbTagsList>& box,
323  const ElementId<Dim>& element_id, const ActionList /*meta*/,
324  const ParallelComponent* const /*meta*/) noexcept {
325  const size_t iteration_id =
326  get<Convergence::Tags::IterationId<OptionsGroup>>(box);
327  const auto& element = db::get<domain::Tags::Element<Dim>>(box);
328  const size_t max_overlap = db::get<Tags::MaxOverlap<OptionsGroup>>(box);
329 
330  // Wait for communicated overlap data
331  const bool has_overlap_data =
332  max_overlap > 0 and element.number_of_neighbors() > 0;
333  if (LIKELY(has_overlap_data) and
334  not dg::has_received_from_all_mortars<overlap_residuals_inbox_tag>(
335  iteration_id, element, inboxes)) {
336  return {std::move(box), Parallel::AlgorithmExecution::Retry};
337  }
338 
339  // Do some logging
341  ::Verbosity::Debug)) {
342  Parallel::printf("%s %s(%zu): Solve subdomain\n", element_id,
343  Options::name<OptionsGroup>(), iteration_id);
344  }
345 
346  // Assemble the subdomain data from the data on the element and the
347  // communicated overlap data
348  db::mutate<SubdomainDataBufferTag<SubdomainData, OptionsGroup>>(
349  make_not_null(&box),
350  [&inboxes, &iteration_id, &has_overlap_data](
351  const gsl::not_null<SubdomainData*> subdomain_data,
352  const auto& residual) noexcept {
353  subdomain_data->element_data = residual;
354  // Nothing was communicated if the overlaps are empty
355  if (LIKELY(has_overlap_data)) {
356  subdomain_data->overlap_data =
357  std::move(tuples::get<overlap_residuals_inbox_tag>(inboxes)
358  .extract(iteration_id)
359  .mapped());
360  }
361  },
362  db::get<residual_tag>(box));
363  const auto& subdomain_residual =
364  db::get<SubdomainDataBufferTag<SubdomainData, OptionsGroup>>(box);
365 
366  // Allocate workspace memory for repeatedly applying the subdomain operator
367  SubdomainOperator subdomain_operator{};
368 
369  // Construct the subdomain operator
370  const auto apply_subdomain_operator =
371  [&box, &subdomain_operator](const gsl::not_null<SubdomainData*> result,
372  const SubdomainData& operand) noexcept {
373  // The subdomain operator can retrieve any information on the subdomain
374  // geometry that is available through the DataBox. The user is responsible
375  // for communicating this information across neighbors if necessary.
376  subdomain_operator(result, operand, box);
377  };
378 
379  // Solve the subdomain problem
380  const auto& subdomain_solver =
381  get<Tags::SubdomainSolverBase<OptionsGroup>>(box);
382  auto subdomain_solve_initial_guess_in_solution_out =
383  make_with_value<SubdomainData>(subdomain_residual, 0.);
384  const auto subdomain_solve_has_converged = subdomain_solver.solve(
385  make_not_null(&subdomain_solve_initial_guess_in_solution_out),
386  apply_subdomain_operator, subdomain_residual);
387  // Re-naming the solution buffer for the code below
388  auto& subdomain_solution = subdomain_solve_initial_guess_in_solution_out;
389 
390  // Do some logging and observing
392  ::Verbosity::Quiet)) {
393  if (not subdomain_solve_has_converged or
394  subdomain_solve_has_converged.reason() ==
397  "%s %s(%zu): WARNING: Subdomain solver did not converge in %zu "
398  "iterations: %e -> %e\n",
399  element_id, Options::name<OptionsGroup>(), iteration_id,
400  subdomain_solve_has_converged.num_iterations(),
401  subdomain_solve_has_converged.initial_residual_magnitude(),
402  subdomain_solve_has_converged.residual_magnitude());
404  ::Verbosity::Debug)) {
406  "%s %s(%zu): Subdomain solver converged in %zu iterations (%s): %e "
407  "-> %e\n",
408  element_id, Options::name<OptionsGroup>(), iteration_id,
409  subdomain_solve_has_converged.num_iterations(),
410  subdomain_solve_has_converged.reason(),
411  subdomain_solve_has_converged.initial_residual_magnitude(),
412  subdomain_solve_has_converged.residual_magnitude());
413  }
414  }
415  const std::optional<std::string> section_observation_key =
416  observers::get_section_observation_key<ArraySectionIdTag>(box);
417  if (section_observation_key.has_value()) {
418  contribute_to_subdomain_stats_observation<OptionsGroup,
419  ParallelComponent>(
420  iteration_id + 1, subdomain_solve_has_converged.num_iterations(),
421  cache, element_id, *section_observation_key);
422  }
423 
424  // Apply weighting
425  if (LIKELY(max_overlap > 0)) {
426  subdomain_solution.element_data *=
427  get(db::get<Tags::Weight<OptionsGroup>>(box));
428  }
429 
430  // Apply solution to central element
431  db::mutate<fields_tag>(make_not_null(&box),
432  [&subdomain_solution](const auto fields) noexcept {
433  *fields += subdomain_solution.element_data;
434  });
435 
436  // Send overlap solutions back to the neighbors that they are on
437  if (LIKELY(max_overlap > 0)) {
438  auto& receiver_proxy =
439  Parallel::get_parallel_component<ParallelComponent>(cache);
440  for (auto& [overlap_id, overlap_solution] :
441  subdomain_solution.overlap_data) {
442  const auto& direction = overlap_id.first;
443  const auto& neighbor_id = overlap_id.second;
444  const auto& orientation =
445  element.neighbors().at(direction).orientation();
446  const auto direction_from_neighbor = orientation(direction.opposite());
447  Parallel::receive_data<overlap_solution_inbox_tag>(
448  receiver_proxy[neighbor_id], iteration_id,
449  std::make_pair(
450  OverlapId<Dim>{direction_from_neighbor, element.id()},
451  std::move(overlap_solution)));
452  }
453  }
454  return {std::move(box), Parallel::AlgorithmExecution::Continue};
455  }
456 };
457 
458 // Wait for the subdomain solutions on regions within this element that overlap
459 // with neighboring element-centered subdomains. Combine the solutions as a
460 // weighted sum.
461 template <typename FieldsTag, typename OptionsGroup, typename SubdomainOperator>
462 struct ReceiveOverlapSolution {
463  private:
464  using fields_tag = FieldsTag;
465  using residual_tag =
467  static constexpr size_t Dim = SubdomainOperator::volume_dim;
468  using SubdomainData =
469  ElementCenteredSubdomainData<Dim, typename residual_tag::tags_list>;
470  using OverlapSolution = typename SubdomainData::OverlapData;
471  using overlap_solution_inbox_tag =
472  OverlapSolutionInboxTag<Dim, OptionsGroup, OverlapSolution>;
473 
474  public:
475  using const_global_cache_tags = tmpl::list<Tags::MaxOverlap<OptionsGroup>>;
476  using inbox_tags = tmpl::list<overlap_solution_inbox_tag>;
477 
478  template <typename DbTagsList, typename... InboxTags, typename Metavariables,
479  typename ActionList, typename ParallelComponent>
481  apply(db::DataBox<DbTagsList>& box,
483  const Parallel::GlobalCache<Metavariables>& /*cache*/,
484  const ElementId<Dim>& element_id, const ActionList /*meta*/,
485  const ParallelComponent* const /*meta*/) noexcept {
486  const size_t iteration_id =
487  get<Convergence::Tags::IterationId<OptionsGroup>>(box);
488  const auto& element = db::get<domain::Tags::Element<Dim>>(box);
489 
490  // Nothing to do if overlap is empty
491  if (UNLIKELY(db::get<Tags::MaxOverlap<OptionsGroup>>(box) == 0 or
492  element.number_of_neighbors() == 0)) {
493  return {std::move(box), Parallel::AlgorithmExecution::Continue};
494  }
495 
496  if (not dg::has_received_from_all_mortars<overlap_solution_inbox_tag>(
497  iteration_id, element, inboxes)) {
498  return {std::move(box), Parallel::AlgorithmExecution::Retry};
499  }
500 
501  // Do some logging
503  ::Verbosity::Debug)) {
504  Parallel::printf("%s %s(%zu): Receive overlap solution\n", element_id,
505  Options::name<OptionsGroup>(), iteration_id);
506  }
507 
508  // Add solutions on overlaps to this element's solution in a weighted sum
509  const auto received_overlap_solutions =
510  std::move(tuples::get<overlap_solution_inbox_tag>(inboxes)
511  .extract(iteration_id)
512  .mapped());
513  db::mutate<fields_tag>(
514  make_not_null(&box),
515  [&received_overlap_solutions](
516  const auto fields, const Index<Dim>& full_extents,
517  const std::array<size_t, Dim>& all_intruding_extents,
518  const DirectionMap<Dim, Scalar<DataVector>>&
519  all_intruding_overlap_weights) noexcept {
520  for (const auto& [overlap_id, overlap_solution] :
521  received_overlap_solutions) {
522  const auto& direction = overlap_id.first;
523  const auto& intruding_extents =
524  gsl::at(all_intruding_extents, direction.dimension());
525  const auto& overlap_weight =
526  all_intruding_overlap_weights.at(direction);
528  fields, overlap_solution * get(overlap_weight), full_extents,
529  intruding_extents, direction);
530  }
531  },
532  db::get<domain::Tags::Mesh<Dim>>(box).extents(),
533  db::get<Tags::IntrudingExtents<Dim, OptionsGroup>>(box),
534  db::get<domain::Tags::Faces<Dim, Tags::Weight<OptionsGroup>>>(box));
535  return {std::move(box), Parallel::AlgorithmExecution::Continue};
536  }
537 };
538 
539 } // namespace LinearSolver::Schwarz::detail
LinearSolver::Schwarz::intruding_weight
DataVector intruding_weight(const DataVector &logical_coords, double width, const Side &side) noexcept
Weights for the intruding solution of a neighboring element-centered subdomain, increasing from 0 to ...
LinearSolver::Serial::LinearSolver
Base class for serial linear solvers that supports factory-creation.
Definition: LinearSolver.hpp:37
gsl::at
constexpr T & at(std::array< T, N > &arr, Size index)
Retrieve a entry from a container, with checks in Debug mode that the index being retrieved is valid.
Definition: Gsl.hpp:125
observers::ObservationId
A unique identifier for an observation representing the type of observation and the instance (e....
Definition: ObservationId.hpp:71
std::apply
T apply(T... args)
funcl::Divides
Functional for computing / of two objects.
Definition: Functional.hpp:235
std::string
utility
Parallel::AlgorithmExecution::Retry
@ Retry
Temporarily stop executing iterable actions, but try the same action again after receiving data from ...
LinearSolver::Schwarz::overlap_extent
size_t overlap_extent(size_t volume_extent, size_t max_overlap) noexcept
The number of points that an overlap extends into the volume_extent
UNLIKELY
#define UNLIKELY(x)
Definition: Gsl.hpp:73
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
Parallel::ReductionDatum
The data to be reduced, and invokables to be called whenever two reduction messages are combined and ...
Definition: Reduction.hpp:65
LinearSolver::Schwarz::element_weight
void element_weight(gsl::not_null< Scalar< DataVector > * > element_weight, const tnsr::I< DataVector, Dim, Frame::Logical > &logical_coords, const std::array< double, Dim > &overlap_widths, const std::unordered_set< Direction< Dim >> &external_boundaries) noexcept
Weights for data on the central element of an element-centered subdomain.
std::pair
GlobalCache.hpp
std::index_sequence
Options.hpp
CommunicateOverlapFields.hpp
Tags.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
db::add_tag_prefix
typename detail::add_tag_prefix_impl< Prefix, Tag, Args... >::type add_tag_prefix
Definition: PrefixHelpers.hpp:51
observers::ObservationKey
Used as a key in maps to keep track of how many elements have registered.
Definition: ObservationId.hpp:28
tuple
db::get
const auto & get(const DataBox< TagList > &box) noexcept
Retrieve the item with tag Tag from the DataBox.
Definition: DataBox.hpp:791
Index
Definition: Index.hpp:31
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
evolution::dg::subcell::fd::mesh
Mesh< Dim > mesh(const Mesh< Dim > &dg_mesh) noexcept
Computes the cell-centered finite-difference mesh from the DG mesh, using grid points per dimension,...
Spectral.hpp
Tags.hpp
domain::Tags::Faces
The Tag on element faces.
Definition: Faces.hpp:25
LinearSolver::Schwarz::Actions::SendOverlapFields
Send data on regions that overlap with other subdomains to their corresponding elements.
Definition: CommunicateOverlapFields.hpp:72
get_output
std::string get_output(const T &t) noexcept
Get the streamed output of t as a std::string
Definition: GetOutput.hpp:14
Registration::Registrar
A template for defining a registrar.
Definition: Registration.hpp:42
ElementId< Dim >
Spectral::collocation_points
const DataVector & collocation_points(size_t num_points) noexcept
Collocation points.
ElementId.hpp
std::add_pointer_t
LinearSolver::Schwarz::add_overlap_data
void add_overlap_data(const gsl::not_null< Variables< VolumeTagsList > * > volume_data, const Variables< OverlapTagsList > &overlap_data, const Index< Dim > &volume_extents, const size_t overlap_extent, const Direction< Dim > &direction) noexcept
Add the overlap_data to the volume_data
Definition: OverlapHelpers.hpp:226
Printf.hpp
LinearSolver::Schwarz::overlap_width
double overlap_width(size_t overlap_extent, const DataVector &collocation_points) noexcept
Width of an overlap extending overlap_extent points into the collocation_points from either side.
Parallel::AlgorithmExecution::Continue
@ Continue
Leave the algorithm termination flag in its current state.
DataBox.hpp
cstddef
logging::Tags::Verbosity
Tag for putting Verbosity in a DataBox.
Definition: Tags.hpp:33
LinearSolver::Schwarz::data_on_overlap
void data_on_overlap(const gsl::not_null< Tensor< DataType, TensorStructure... > * > restricted_tensor, const Tensor< DataType, TensorStructure... > &tensor, const Index< Dim > &volume_extents, const size_t overlap_extent, const Direction< Dim > &direction) noexcept
The part of the tensor data that lies within the overlap region.
Definition: OverlapHelpers.hpp:139
std::array< size_t, Dim >
Index.hpp
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
map
Parallel::AlgorithmExecution
AlgorithmExecution
The possible options for altering the current execution of the algorithm, used in the return type of ...
Definition: AlgorithmMetafunctions.hpp:31
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:49
Element.hpp
DirectionMap
Definition: DirectionMap.hpp:15
ActionTesting::cache
Parallel::GlobalCache< Metavariables > & cache(MockRuntimeSystem< Metavariables > &runner, const ArrayIndex &array_index) noexcept
Returns the GlobalCache of Component with index array_index.
Definition: MockRuntimeSystemFreeFunctions.hpp:382
Scalar
Tensor< T, Symmetry<>, index_list<> > Scalar
Definition: TypeAliases.hpp:21
PhaseControl::reduction_data
Parallel::ReductionData< Parallel::ReductionDatum< tuples::tagged_tuple_from_typelist< TagsAndCombinesPresent >, TaggedTupleCombine > > reduction_data
A Parallel::ReductionData with a single Parallel::ReductionDatum for a given tagged tuple type determ...
Definition: PhaseControlReductionHelpers.hpp:83
Gsl.hpp
LinearSolver::Tags::Residual
The residual .
Definition: Tags.hpp:66
observers::TypeOfObservation::Reduction
@ Reduction
The sender will only perform reduction observations.
LIKELY
#define LIKELY(x)
Definition: Gsl.hpp:67
std::optional
observers::ArrayComponentId
An ID type that identifies both the parallel component and the index in the parallel component.
Definition: ArrayComponentId.hpp:27
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:28
Direction.hpp
std::unique_ptr
unordered_map
tt::ConformsTo
Indicate a class conforms to the Protocol.
Definition: ProtocolHelpers.hpp:22
Convergence::Reason::MaxIterations
@ MaxIterations
Reached the maximum number of iterations. Can be interpreted as an error condition.
TMPL.hpp
Mesh.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecPiecewisePolynomial.hpp:13
Parallel::InboxInserters::Map
Inserter for inserting data that is received as the value_type (with non-const key_type) of a map dat...
Definition: InboxInserters.hpp:36
observers::Actions::RegisterWithObservers
Register an observation ID with the observers.
Definition: RegisterWithObservers.hpp:47
string