version 3.8
multidomain/newtonsolver.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_MULTIDOMAIN_NEWTON_SOLVER_HH
14#define DUMUX_MULTIDOMAIN_NEWTON_SOLVER_HH
15
16#include <memory>
18
19namespace Dumux {
20namespace Detail {
21
22template<class Assembler, class Index>
24
25} // end namespace Detail
26
32template <class Assembler, class LinearSolver, class CouplingManager,
33 class Reassembler = DefaultPartialReassembler,
34 class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator> >
35class MultiDomainNewtonSolver: public NewtonSolver<Assembler, LinearSolver, Reassembler, Comm>
36{
38 using typename ParentType::Backend;
39 using typename ParentType::SolutionVector;
40
41 static constexpr bool assemblerExportsVariables = Detail::PDESolver::assemblerExportsVariables<Assembler>;
42
43 template<std::size_t i>
44 using PrimaryVariableSwitch =
45 Dune::Std::detected_or_t<int, Detail::DetectPVSwitchMultiDomain, Assembler, Dune::index_constant<i>>;
46
47 template<std::size_t i>
48 using HasPriVarsSwitch =
49 Dune::Std::is_detected<Detail::DetectPVSwitchMultiDomain, Assembler, Dune::index_constant<i>>; // std::true_type or std::false_type
50
51 template<std::size_t i>
52 using PrivarSwitchPtr = std::unique_ptr<PrimaryVariableSwitch<i>>;
53 using PriVarSwitchPtrTuple = typename Assembler::Traits::template Tuple<PrivarSwitchPtr>;
54
55public:
56 using typename ParentType::Variables;
57
61 MultiDomainNewtonSolver(std::shared_ptr<Assembler> assembler,
62 std::shared_ptr<LinearSolver> linearSolver,
63 std::shared_ptr<CouplingManager> couplingManager,
64 const Comm& comm = Dune::MPIHelper::getCommunication(),
65 const std::string& paramGroup = "")
67 , couplingManager_(couplingManager)
68 {
69 using namespace Dune::Hybrid;
70 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
71 {
72 const int priVarSwitchVerbosity = getParamFromGroup<int>(paramGroup, "PrimaryVariableSwitch.Verbosity", 1);
73 using PVSwitch = PrimaryVariableSwitch<std::decay_t<decltype(id)>::value>;
74 elementAt(priVarSwitches_, id) = std::make_unique<PVSwitch>(priVarSwitchVerbosity);
75 });
76
77 priVarsSwitchedInLastIteration_.fill(false);
78 }
79
83 void newtonBeginStep(const Variables& varsCurrentIter) override
84 {
85 ParentType::newtonBeginStep(varsCurrentIter);
86 couplingManager_->updateSolution(Backend::dofs(varsCurrentIter));
87 }
88
96 void newtonBegin(Variables& vars) override
97 {
99
100 using namespace Dune::Hybrid;
101 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
102 {
103 this->initPriVarSwitch_(vars, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
104 });
105 }
106
111 bool newtonConverged() const override
112 {
113 if (Dune::any_true(priVarsSwitchedInLastIteration_))
114 return false;
115
117 }
118
119
126 void newtonEndStep(Variables& varsCurrentIter, const SolutionVector& uLastIter) override
127 {
128 using namespace Dune::Hybrid;
129 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
130 {
131 auto& uCurrentIter = Backend::dofs(varsCurrentIter)[id];
132 if constexpr (!assemblerExportsVariables)
133 this->invokePriVarSwitch_(this->assembler().gridVariables(id),
134 uCurrentIter, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
135 else
136 this->invokePriVarSwitch_(varsCurrentIter[id], uCurrentIter, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
137 });
138
139 ParentType::newtonEndStep(varsCurrentIter, uLastIter);
140 couplingManager_->updateSolution(Backend::dofs(varsCurrentIter));
141 }
142
143protected:
147 void solutionChanged_(Variables& vars, const SolutionVector& uCurrentIter) override
148 {
149 couplingManager_->updateSolution(uCurrentIter);
150 ParentType::solutionChanged_(vars, uCurrentIter);
151 }
152
153private:
154
158 template<std::size_t i>
159 void initPriVarSwitch_(Variables&, Dune::index_constant<i> id, std::false_type) {}
160
164 template<std::size_t i>
165 void initPriVarSwitch_(Variables& vars, Dune::index_constant<i> id, std::true_type)
166 {
167 using namespace Dune::Hybrid;
168 auto& priVarSwitch = *elementAt(priVarSwitches_, id);
169 auto& sol = Backend::dofs(vars)[id];
170
171 priVarSwitch.reset(sol.size());
172 priVarsSwitchedInLastIteration_[i] = false;
173
174 const auto& problem = this->assembler().problem(id);
175 const auto& gridGeometry = this->assembler().gridGeometry(id);
176 if constexpr (!assemblerExportsVariables)
177 priVarSwitch.updateDirichletConstraints(problem, gridGeometry, this->assembler().gridVariables(id), sol);
178 else // This expects usage of MultiDomainGridVariables
179 priVarSwitch.updateDirichletConstraints(problem, gridGeometry, vars[id], sol[id]);
180 }
181
185 template<class SubVars, class SubSol, std::size_t i>
186 void invokePriVarSwitch_(SubVars&, SubSol&, Dune::index_constant<i> id, std::false_type) {}
187
191 template<class SubVars, class SubSol, std::size_t i>
192 void invokePriVarSwitch_(SubVars& subVars, SubSol& uCurrentIter, Dune::index_constant<i> id, std::true_type)
193 {
194 // update the variable switch (returns true if the pri vars at at least one dof were switched)
195 // for disabled grid variable caching
196 const auto& gridGeometry = this->assembler().gridGeometry(id);
197 const auto& problem = this->assembler().problem(id);
198
199 using namespace Dune::Hybrid;
200 auto& priVarSwitch = *elementAt(priVarSwitches_, id);
201
202 // invoke the primary variable switch
203 priVarsSwitchedInLastIteration_[i] = priVarSwitch.update(uCurrentIter, subVars, problem, gridGeometry);
204
205 if (priVarsSwitchedInLastIteration_[i])
206 {
207 for (const auto& element : elements(gridGeometry.gridView()))
208 {
209 // if the volume variables are cached globally, we need to update those where the primary variables have been switched
210 priVarSwitch.updateSwitchedVolVars(problem, element, gridGeometry, subVars, uCurrentIter);
211
212 // if the flux variables are cached globally, we need to update those where the primary variables have been switched
213 priVarSwitch.updateSwitchedFluxVarsCache(problem, element, gridGeometry, subVars, uCurrentIter);
214 }
215 }
216 }
217
219 std::shared_ptr<CouplingManager> couplingManager_;
220
222 PriVarSwitchPtrTuple priVarSwitches_;
224 std::array<bool, Assembler::Traits::numSubDomains> priVarsSwitchedInLastIteration_;
225};
226
227} // end namespace Dumux
228
229#endif
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:48
Definition: partialreassembler.hh:32
Base class for linear solvers.
Definition: solver.hh:27
Newton solver for coupled problems.
Definition: multidomain/newtonsolver.hh:36
bool newtonConverged() const override
Returns true if the error of the solution is below the tolerance.
Definition: multidomain/newtonsolver.hh:111
MultiDomainNewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, std::shared_ptr< CouplingManager > couplingManager, const Comm &comm=Dune::MPIHelper::getCommunication(), const std::string &paramGroup="")
The constructor.
Definition: multidomain/newtonsolver.hh:61
void newtonEndStep(Variables &varsCurrentIter, const SolutionVector &uLastIter) override
Indicates that one Newton iteration was finished.
Definition: multidomain/newtonsolver.hh:126
void newtonBeginStep(const Variables &varsCurrentIter) override
Indicates the beginning of a Newton iteration.
Definition: multidomain/newtonsolver.hh:83
void newtonBegin(Variables &vars) override
Called before the Newton method is applied to an non-linear system of equations.
Definition: multidomain/newtonsolver.hh:96
void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter) override
Update solution-depended quantities like grid variables after the solution has changed.
Definition: multidomain/newtonsolver.hh:147
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:181
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:807
virtual void newtonBegin(Variables &initVars)
Called before the Newton method is applied to an non-linear system of equations.
Definition: nonlinear/newtonsolver.hh:386
virtual void newtonEndStep(Variables &vars, const SolutionVector &uLastIter)
Indicates that one Newton iteration was finished.
Definition: nonlinear/newtonsolver.hh:604
virtual void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter)
Update solution-dependent quantities like grid variables after the solution has changed.
Definition: nonlinear/newtonsolver.hh:841
virtual void newtonBeginStep(const Variables &vars)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:447
typename Backend::DofVector SolutionVector
Definition: nonlinear/newtonsolver.hh:186
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:236
VariablesBackend< typename ParentType::Variables > Backend
Definition: nonlinear/newtonsolver.hh:185
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:651
const LinearSolver & linearSolver() const
Access the linear solver.
Definition: common/pdesolver.hh:133
const Assembler & assembler() const
Access the assembler.
Definition: common/pdesolver.hh:121
Detail::PDESolver::AssemblerVariables< Assembler > Variables
export the type of variables that represent a numerical solution
Definition: common/pdesolver.hh:71
typename Assembler::template GridVariables< Index::value >::VolumeVariables::PrimaryVariableSwitch DetectPVSwitchMultiDomain
Definition: multidomain/newtonsolver.hh:23
Dune::Std::detected_or_t< int, DetectPVSwitch, Variables > PrimaryVariableSwitch
Definition: primaryvariableswitchadapter.hh:27
Definition: adapt.hh:17
Reference implementation of a Newton solver.