Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <optional>
8 : #include <tuple>
9 :
10 : #include "DataStructures/DataBox/DataBox.hpp"
11 : #include "Domain/Structure/ElementId.hpp"
12 : #include "IO/Logging/Tags.hpp"
13 : #include "IO/Logging/Verbosity.hpp"
14 : #include "Parallel/AlgorithmExecution.hpp"
15 : #include "Parallel/Printf/Printf.hpp"
16 : #include "ParallelAlgorithms/LinearSolver/Schwarz/Tags.hpp"
17 : #include "Utilities/Gsl.hpp"
18 : #include "Utilities/PrettyType.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : namespace Parallel {
23 : template <typename Metavariables>
24 : struct GlobalCache;
25 : } // namespace Parallel
26 : namespace tuples {
27 : template <typename...>
28 : struct TaggedTuple;
29 : } // namespace tuples
30 : /// \endcond
31 :
32 : namespace LinearSolver::Schwarz::Actions {
33 :
34 : /*!
35 : * \brief Reset the subdomain solver, clearing its caches related to the linear
36 : * operator it has solved so far.
37 : *
38 : * Invoke this action when the linear operator has changed. For example, an
39 : * operator representing the linearization of a nonlinear operator changes
40 : * whenever the point around which it is being linearized gets updated, i.e. in
41 : * every iteration of a nonlinear solve. Note that the operator does _not_
42 : * change between iterations of a linear solve, so make sure you place this
43 : * action _outside_ the looping action list for the linear solve.
44 : *
45 : * \par Skipping the reset:
46 : * Depending on the subdomain solver in use, the reset may incur significant
47 : * re-initialization cost the next time the subdomain solver is invoked. See the
48 : * `LinearSolver::Serial::ExplicitInverse` solver for an example of a subdomain
49 : * solver with high initialization cost. For this reason the reset can be
50 : * skipped with the option
51 : * `LinearSolver::Schwarz::Tags::SkipSubdomainSolverResets`. Skipping resets
52 : * means that caches built up for the linear operator are never cleared, so
53 : * expensive re-initializations are avoided but the subdomain solves may be
54 : * increasingly inaccurate or slow down as the linear operator changes over
55 : * nonlinear solver iterations. Whether or not skipping resets helps with the
56 : * overall convergence of the solve is highly problem-dependent. A possible
57 : * optimization would be to decide at runtime whether or not to reset the
58 : * subdomain solver.
59 : */
60 : template <typename SubdomainSolverType, typename OptionsGroup>
61 1 : struct ResetSubdomainSolver {
62 0 : using const_global_cache_tags = tmpl::list<
63 : LinearSolver::Schwarz::Tags::SkipSubdomainSolverResets<OptionsGroup>,
64 : logging::Tags::Verbosity<OptionsGroup>>;
65 : template <typename DbTagsList, typename... InboxTags, typename Metavariables,
66 : size_t Dim, typename ActionList, typename ParallelComponent>
67 0 : static Parallel::iterable_action_return_t apply(
68 : db::DataBox<DbTagsList>& box,
69 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
70 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
71 : const ElementId<Dim>& element_id, const ActionList /*meta*/,
72 : const ParallelComponent* const /*meta*/) {
73 : if (not get<LinearSolver::Schwarz::Tags::SkipSubdomainSolverResets<
74 : OptionsGroup>>(box)) {
75 : if (UNLIKELY(get<logging::Tags::Verbosity<OptionsGroup>>(box) >=
76 : ::Verbosity::Debug)) {
77 : Parallel::printf("%s %s: Reset subdomain solver\n", element_id,
78 : pretty_type::name<OptionsGroup>());
79 : }
80 : db::mutate<LinearSolver::Schwarz::Tags::SubdomainSolver<
81 : SubdomainSolverType, OptionsGroup>>(
82 : [](const auto subdomain_solver) {
83 : // Dereference the gsl::not_null pointer, and then the
84 : // std::unique_ptr for the subdomain solver's abstract superclass.
85 : // This needs adjustment if the subdomain solver is stored in the
86 : // DataBox directly as a derived class and thus there's no
87 : // std::unique_ptr. Note that std::unique_ptr also has a `reset`
88 : // function, which must not be confused with the serial linear
89 : // solver's `reset` function here.
90 : (*subdomain_solver)->reset();
91 : },
92 : make_not_null(&box));
93 : }
94 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
95 : }
96 : };
97 :
98 : } // namespace LinearSolver::Schwarz::Actions
|