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 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< 81 : LinearSolver::Schwarz::Tags::SubdomainSolverBase<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