Algorithm.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
7 
8 #include <algorithm>
9 #include <cstddef>
10 #include <string>
11 #include <tuple>
12 #include <vector>
13 
18 #include "Helpers/ParallelAlgorithms/LinearSolver/LinearSolverAlgorithmTestHelpers.hpp"
19 #include "IO/Observer/Helpers.hpp"
20 #include "IO/Observer/ObserverComponent.hpp"
21 #include "NumericalAlgorithms/Convergence/HasConverged.hpp"
22 #include "NumericalAlgorithms/Convergence/Tags.hpp"
23 #include "Options/Options.hpp"
24 #include "Parallel/Actions/Goto.hpp"
25 #include "Parallel/Actions/SetupDataBox.hpp"
28 #include "Parallel/GlobalCache.hpp"
29 #include "Parallel/InitializationFunctions.hpp"
30 #include "Parallel/Invoke.hpp"
31 #include "Parallel/Main.hpp"
32 #include "ParallelAlgorithms/Initialization/MutateAssign.hpp"
37 #include "Utilities/FileSystem.hpp"
38 #include "Utilities/Gsl.hpp"
39 #include "Utilities/Requires.hpp"
40 #include "Utilities/TMPL.hpp"
41 
42 namespace TestHelpers::NonlinearSolver {
43 
45  static constexpr Options::String help = "The source b in the equation Ax=b.";
46  using type = DenseVector<double>;
47  static constexpr bool pass_metavariables = false;
48  using option_tags = tmpl::list<Source>;
49  static type create_from_options(const type& option) { return option; }
50 };
52  static constexpr Options::String help = "The initial guess for the vector x.";
53  using type = DenseVector<double>;
54  static constexpr bool pass_metavariables = false;
55  using option_tags = tmpl::list<InitialGuess>;
56  static type create_from_options(const type& option) { return option; }
57 };
59  static constexpr Options::String help = "The solution x in the equation Ax=b";
60  using type = DenseVector<double>;
61  static constexpr bool pass_metavariables = false;
62  using option_tags = tmpl::list<ExpectedResult>;
63  static type create_from_options(const type& option) { return option; }
64 };
65 
66 // The vector `x` we want to solve for
68  using type = DenseVector<double>;
69  static std::string name() noexcept { return "VectorTag"; }
70 };
71 
72 using fields_tag = VectorTag;
74 
75 // Checks for the correct solution after the algorithm has terminated.
76 template <typename OptionsGroup>
77 struct TestResult {
78  using const_global_cache_tags = tmpl::list<ExpectedResult>;
79 
80  template <typename DbTagsList, typename... InboxTags, typename Metavariables,
81  typename ActionList, typename ParallelComponent>
82  static std::tuple<db::DataBox<DbTagsList>&&, bool> apply(
83  db::DataBox<DbTagsList>& box,
84  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
86  const int /*array_index*/, const ActionList /*meta*/,
87  const ParallelComponent* const /*meta*/) noexcept {
88  const auto& has_converged =
89  get<Convergence::Tags::HasConverged<OptionsGroup>>(box);
90  SPECTRE_PARALLEL_REQUIRE(has_converged);
91  SPECTRE_PARALLEL_REQUIRE(has_converged.reason() ==
93  const auto& result = get<VectorTag>(box);
94  const auto& expected_result = get<ExpectedResult>(cache);
95  for (size_t i = 0; i < expected_result.size(); i++) {
96  SPECTRE_PARALLEL_REQUIRE(result[i] == approx(expected_result[i]));
97  }
98  return {std::move(box), true};
99  }
100 };
101 
103  using const_global_cache_tags = tmpl::list<Source, InitialGuess>;
104  using simple_tags = tmpl::list<fields_tag, nonlinear_source_tag>;
105 
106  template <typename DbTagsList, typename... InboxTags, typename Metavariables,
107  typename ActionList, typename ParallelComponent>
108  static auto apply(db::DataBox<DbTagsList>& box,
109  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
111  const int /*array_index*/, const ActionList /*meta*/,
112  const ParallelComponent* const /*meta*/) noexcept {
113  const auto& b = get<Source>(cache);
114  const auto& x0 = get<InitialGuess>(cache);
115 
116  ::Initialization::mutate_assign<simple_tags>(make_not_null(&box), x0, b);
117  return std::make_tuple(std::move(box));
118  }
119 };
120 
121 template <typename Metavariables>
122 struct ElementArray {
124  using array_index = int;
125  using metavariables = Metavariables;
126 
127  using nonlinear_solver = typename Metavariables::nonlinear_solver;
128  using linear_solver = typename Metavariables::linear_solver;
129 
130  using phase_dependent_action_list = tmpl::list<
132  typename Metavariables::Phase, Metavariables::Phase::Initialization,
134  typename nonlinear_solver::initialize_element,
135  typename linear_solver::initialize_element,
138  typename Metavariables::Phase,
139  Metavariables::Phase::RegisterWithObserver,
140  tmpl::list<typename nonlinear_solver::register_element,
141  typename linear_solver::register_element,
144  typename Metavariables::Phase, Metavariables::Phase::Solve,
145  tmpl::list<
146  typename Metavariables::template apply_nonlinear_operator<
147  typename nonlinear_solver::fields_tag>,
148  typename nonlinear_solver::template solve<
149  typename Metavariables::template apply_nonlinear_operator<
150  typename nonlinear_solver::operand_tag>,
151  typename linear_solver::template solve<
152  typename Metavariables::
153  template apply_linearized_operator<
154  typename linear_solver::operand_tag,
155  typename nonlinear_solver::fields_tag>>>,
158  typename Metavariables::Phase, Metavariables::Phase::TestResult,
159  tmpl::list<TestResult<typename nonlinear_solver::options_group>>>>;
160 
161  using array_allocation_tags = tmpl::list<>;
162  using initialization_tags = Parallel::get_initialization_tags<
164  array_allocation_tags>;
165 
166  static void allocate_array(
167  Parallel::CProxy_GlobalCache<Metavariables>& global_cache,
168  const tuples::tagged_tuple_from_typelist<initialization_tags>&
169  initialization_items) noexcept {
170  auto& local_component = Parallel::get_parallel_component<ElementArray>(
171  *(global_cache.ckLocalBranch()));
172  local_component[0].insert(global_cache, initialization_items, 0);
173  local_component.doneInserting();
174  }
175 
176  static void execute_next_phase(
177  const typename Metavariables::Phase next_phase,
178  Parallel::CProxy_GlobalCache<Metavariables>& global_cache) noexcept {
179  auto& local_component = Parallel::get_parallel_component<ElementArray>(
180  *(global_cache.ckLocalBranch()));
181  local_component.start_phase(next_phase);
182  }
183 };
184 
185 template <typename Metavariables>
186 using OutputCleaner =
188 
189 enum class Phase {
190  Initialization,
191  RegisterWithObserver,
192  Solve,
193  TestResult,
194  CleanOutput,
195  Exit
196 };
197 
198 template <typename Metavariables, typename... Tags>
199 static Phase determine_next_phase(
200  const gsl::not_null<
201  tuples::TaggedTuple<Tags...>*> /*phase_change_decision_data*/,
202  const Phase& current_phase,
203  const Parallel::CProxy_GlobalCache<
204  Metavariables>& /*cache_proxy*/) noexcept {
205  switch (current_phase) {
206  case Phase::Initialization:
207  return Phase::RegisterWithObserver;
208  case Phase::RegisterWithObserver:
209  return Phase::Solve;
210  case Phase::Solve:
211  return Phase::TestResult;
212  case Phase::TestResult:
213  return Phase::CleanOutput;
214  default:
215  return Phase::Exit;
216  }
217 }
218 
219 template <typename Metavariables>
220 using component_list = tmpl::flatten<tmpl::list<
221  typename Metavariables::nonlinear_solver::component_list,
222  typename Metavariables::linear_solver::component_list,
223  ElementArray<Metavariables>, observers::Observer<Metavariables>,
224  observers::ObserverWriter<Metavariables>, OutputCleaner<Metavariables>>>;
225 
226 template <typename Metavariables>
227 using observed_reduction_data_tags = observers::collect_reduction_data_tags<
228  tmpl::list<typename Metavariables::linear_solver,
229  typename Metavariables::nonlinear_solver>>;
230 
231 } // namespace TestHelpers::NonlinearSolver
FloatingPointExceptions.hpp
TestHelpers::NonlinearSolver::TestResult
Definition: Algorithm.hpp:77
Actions::SetupDataBox
Add into the DataBox default constructed items for the collection of tags requested by any of the act...
Definition: SetupDataBox.hpp:102
std::string
DataBoxTag.hpp
Main.hpp
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
Tags.hpp
GlobalCache.hpp
Options.hpp
vector
Error.hpp
TestingFramework.hpp
DenseVector.hpp
DenseMatrix.hpp
tuple
Parallel::Actions::TerminatePhase
Terminate the algorithm to proceed to the next phase.
Definition: TerminatePhase.hpp:26
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
SPECTRE_PARALLEL_REQUIRE
#define SPECTRE_PARALLEL_REQUIRE(expr)
A similar to Catch's REQUIRE statement, but can be used in tests that spawn several chares with possi...
Definition: TestingFramework.hpp:48
DenseVector< double >
algorithm
Tags.hpp
FileSystem.hpp
Parallel::get_initialization_tags
tmpl::remove_duplicates< tmpl::flatten< tmpl::list< AllocationTagsList, tmpl::transform< InitializationActionsList, detail::get_initialization_tags_from_action< tmpl::_1 > >> >> get_initialization_tags
Given a list of initialization actions, and possibly a list of tags needed for allocation of an array...
Definition: ParallelComponentHelpers.hpp:254
Parallel::get_initialization_actions_list
tmpl::flatten< tmpl::transform< PhaseDepActionList, detail::get_initialization_actions_list< tmpl::_1 > >> get_initialization_actions_list
Given the phase dependent action list, return the list of actions in the Initialization phase (or an ...
Definition: ParallelComponentHelpers.hpp:218
Tags::FixedSource
Prefix indicating a source term that is independent of dynamic variables.
Definition: Prefixes.hpp:75
Parallel::PhaseActions
List of all the actions to be executed in the specified phase.
Definition: PhaseDependentActionList.hpp:16
observers::ObserverWriter
The nodegroup parallel component that is responsible for writing data to disk.
Definition: ObserverComponent.hpp:51
DataBox.hpp
cstddef
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
observers::Observer
The group parallel component that is responsible for reducing data to be observed.
Definition: ObserverComponent.hpp:29
LinearSolverAlgorithmTestHelpers::OutputCleaner
Definition: LinearSolverAlgorithmTestHelpers.hpp:351
AlgorithmArray.hpp
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:380
Parallel::Algorithms::Array
A struct that stores the charm++ types relevant for a particular array component.
Definition: AlgorithmArrayDeclarations.hpp:29
TestHelpers::NonlinearSolver::ExpectedResult
Definition: Algorithm.hpp:58
TestHelpers::NonlinearSolver::VectorTag
Definition: Algorithm.hpp:67
Gsl.hpp
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
Requires.hpp
AlgorithmSingleton.hpp
TestHelpers::NonlinearSolver::InitialGuess
Definition: Algorithm.hpp:51
TestHelpers::NonlinearSolver::Source
Definition: Algorithm.hpp:44
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
TestHelpers::NonlinearSolver::InitializeElement
Definition: Algorithm.hpp:102
Convergence::Reason::AbsoluteResidual
@ AbsoluteResidual
Residual converged below absolute tolerance.
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecThirdOrderPiecewisePolynomial.hpp:13
TestHelpers::NonlinearSolver::ElementArray
Definition: Algorithm.hpp:122
string