3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
25#ifndef DUMUX_MULTIDOMAIN_NEWTON_SOLVER_HH
26#define DUMUX_MULTIDOMAIN_NEWTON_SOLVER_HH
27
28#include <memory>
30
31namespace Dumux {
32namespace Detail {
33
34template<class Assembler, class Index>
36
37template<class Assembler, std::size_t i>
38using GetPVSwitchMultiDomain = Dune::Std::detected_or<int, DetectPVSwitchMultiDomain, Assembler, Dune::index_constant<i>>;
39
40} // end namespace Detail
41
47template <class Assembler, class LinearSolver, class CouplingManager,
48 class Reassembler = DefaultPartialReassembler,
49 class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
50class MultiDomainNewtonSolver: public NewtonSolver<Assembler, LinearSolver, Reassembler, Comm>
51{
53 using typename ParentType::Backend;
54 using typename ParentType::SolutionVector;
55
56 static constexpr bool assemblerExportsVariables = Detail::exportsVariables<Assembler>;
57
58 template<std::size_t i>
59 using PrimaryVariableSwitch = typename Detail::GetPVSwitchMultiDomain<Assembler, i>::type;
60
61 template<std::size_t i>
62 using HasPriVarsSwitch = typename Detail::GetPVSwitchMultiDomain<Assembler, i>::value_t; // std::true_type or std::false_type
63
64 template<std::size_t i>
65 using PrivarSwitchPtr = std::unique_ptr<PrimaryVariableSwitch<i>>;
66 using PriVarSwitchPtrTuple = typename Assembler::Traits::template Tuple<PrivarSwitchPtr>;
67
68public:
69 using typename ParentType::Variables;
70
74 MultiDomainNewtonSolver(std::shared_ptr<Assembler> assembler,
75 std::shared_ptr<LinearSolver> linearSolver,
76 std::shared_ptr<CouplingManager> couplingManager,
77 const Comm& comm = Dune::MPIHelper::getCollectiveCommunication(),
78 const std::string& paramGroup = "")
80 , couplingManager_(couplingManager)
81 {
82 using namespace Dune::Hybrid;
83 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
84 {
85 const int priVarSwitchVerbosity = getParamFromGroup<int>(paramGroup, "PrimaryVariableSwitch.Verbosity", 1);
86 using PVSwitch = PrimaryVariableSwitch<std::decay_t<decltype(id)>::value>;
87 elementAt(priVarSwitches_, id) = std::make_unique<PVSwitch>(priVarSwitchVerbosity);
88 });
89
90 priVarsSwitchedInLastIteration_.fill(false);
91 }
92
96 void newtonBeginStep(const Variables& varsCurrentIter) override
97 {
98 ParentType::newtonBeginStep(varsCurrentIter);
99 couplingManager_->updateSolution(Backend::dofs(varsCurrentIter));
100 }
101
109 void newtonBegin(Variables& vars) override
110 {
112
113 using namespace Dune::Hybrid;
114 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
115 {
116 this->initPriVarSwitch_(vars, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
117 });
118 }
119
124 bool newtonConverged() const override
125 {
126 if (Dune::any_true(priVarsSwitchedInLastIteration_))
127 return false;
128
130 }
131
132
139 void newtonEndStep(Variables& varsCurrentIter, const SolutionVector& uLastIter) override
140 {
141 using namespace Dune::Hybrid;
142 forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id)
143 {
144 auto& uCurrentIter = Backend::dofs(varsCurrentIter)[id];
145 if constexpr (!assemblerExportsVariables)
146 this->invokePriVarSwitch_(this->assembler().gridVariables(id),
147 uCurrentIter, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
148 else
149 this->invokePriVarSwitch_(varsCurrentIter[id], uCurrentIter, id, HasPriVarsSwitch<std::decay_t<decltype(id)>::value>{});
150 });
151
152 ParentType::newtonEndStep(varsCurrentIter, uLastIter);
153 couplingManager_->updateSolution(Backend::dofs(varsCurrentIter));
154 }
155
156protected:
160 void solutionChanged_(Variables& vars, const SolutionVector& uCurrentIter) override
161 {
162 couplingManager_->updateSolution(uCurrentIter);
163 ParentType::solutionChanged_(vars, uCurrentIter);
164 }
165
166private:
167
171 template<std::size_t i>
172 void initPriVarSwitch_(Variables&, Dune::index_constant<i> id, std::false_type) {}
173
177 template<std::size_t i>
178 void initPriVarSwitch_(Variables& vars, Dune::index_constant<i> id, std::true_type)
179 {
180 using namespace Dune::Hybrid;
181 auto& priVarSwitch = *elementAt(priVarSwitches_, id);
182 auto& sol = Backend::dofs(vars)[id];
183
184 priVarSwitch.reset(sol.size());
185 priVarsSwitchedInLastIteration_[i] = false;
186
187 const auto& problem = this->assembler().problem(id);
188 const auto& gridGeometry = this->assembler().gridGeometry(id);
189 if constexpr (!assemblerExportsVariables)
190 priVarSwitch.updateDirichletConstraints(problem, gridGeometry, this->assembler().gridVariables(id), sol);
191 else // This expects usage of MultiDomainGridVariables
192 priVarSwitch.updateDirichletConstraints(problem, gridGeometry, vars[id], sol[id]);
193 }
194
198 template<class SubVars, class SubSol, std::size_t i>
199 void invokePriVarSwitch_(SubVars&, SubSol&, Dune::index_constant<i> id, std::false_type) {}
200
204 template<class SubVars, class SubSol, std::size_t i>
205 void invokePriVarSwitch_(SubVars& subVars, SubSol& uCurrentIter, Dune::index_constant<i> id, std::true_type)
206 {
207 // update the variable switch (returns true if the pri vars at at least one dof were switched)
208 // for disabled grid variable caching
209 const auto& gridGeometry = this->assembler().gridGeometry(id);
210 const auto& problem = this->assembler().problem(id);
211
212 using namespace Dune::Hybrid;
213 auto& priVarSwitch = *elementAt(priVarSwitches_, id);
214
215 // invoke the primary variable switch
216 priVarsSwitchedInLastIteration_[i] = priVarSwitch.update(uCurrentIter, subVars, problem, gridGeometry);
217
218 if (priVarsSwitchedInLastIteration_[i])
219 {
220 for (const auto& element : elements(gridGeometry.gridView()))
221 {
222 // if the volume variables are cached globally, we need to update those where the primary variables have been switched
223 priVarSwitch.updateSwitchedVolVars(problem, element, gridGeometry, subVars, uCurrentIter);
224
225 // if the flux variables are cached globally, we need to update those where the primary variables have been switched
226 priVarSwitch.updateSwitchedFluxVarsCache(problem, element, gridGeometry, subVars, uCurrentIter);
227 }
228 }
229 }
230
232 std::shared_ptr<CouplingManager> couplingManager_;
233
235 PriVarSwitchPtrTuple priVarSwitches_;
237 std::array<bool, Assembler::Traits::numSubDomains> priVarsSwitchedInLastIteration_;
238};
239
240} // end namespace Dumux
241
242#endif
Definition: adapt.hh:29
typename GetPVSwitch< Variables >::type PrimaryVariableSwitch
Definition: primaryvariableswitchadapter.hh:42
typename Assembler::template GridVariables< Index::value >::VolumeVariables::PrimaryVariableSwitch DetectPVSwitchMultiDomain
Definition: multidomain/newtonsolver.hh:35
Dune::Std::detected_or< int, DetectPVSwitchMultiDomain, Assembler, Dune::index_constant< i > > GetPVSwitchMultiDomain
Definition: multidomain/newtonsolver.hh:38
Definition: partialreassembler.hh:43
Detail::AssemblerVariables< Assembler > Variables
export the type of variables that represent a numerical solution
Definition: common/pdesolver.hh:82
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
Base class for linear solvers.
Definition: solver.hh:37
Definition: multidomain/couplingmanager.hh:46
Newton sover for coupled problems.
Definition: multidomain/newtonsolver.hh:51
bool newtonConverged() const override
Returns true if the error of the solution is below the tolerance.
Definition: multidomain/newtonsolver.hh:124
void newtonEndStep(Variables &varsCurrentIter, const SolutionVector &uLastIter) override
Indicates that one Newton iteration was finished.
Definition: multidomain/newtonsolver.hh:139
void newtonBeginStep(const Variables &varsCurrentIter) override
Indicates the beginning of a Newton iteration.
Definition: multidomain/newtonsolver.hh:96
void newtonBegin(Variables &vars) override
Called before the Newton method is applied to an non-linear system of equations.
Definition: multidomain/newtonsolver.hh:109
void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter) override
Update solution-depended quantities like grid variables after the solution has changed.
Definition: multidomain/newtonsolver.hh:160
MultiDomainNewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, std::shared_ptr< CouplingManager > couplingManager, const Comm &comm=Dune::MPIHelper::getCollectiveCommunication(), const std::string &paramGroup="")
The constructor.
Definition: multidomain/newtonsolver.hh:74
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:216
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:841
virtual void newtonBegin(Variables &initVars)
Called before the Newton method is applied to an non-linear system of equations.
Definition: nonlinear/newtonsolver.hh:407
virtual void newtonEndStep(Variables &vars, const SolutionVector &uLastIter)
Indicates that one Newton iteration was finished.
Definition: nonlinear/newtonsolver.hh:638
virtual void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter)
Update solution-dependent quantities like grid variables after the solution has changed.
Definition: nonlinear/newtonsolver.hh:875
virtual void newtonBeginStep(const Variables &vars)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:467
typename Backend::DofVector SolutionVector
Definition: nonlinear/newtonsolver.hh:221
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:270
VariablesBackend< typename ParentType::Variables > Backend
Definition: nonlinear/newtonsolver.hh:220
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:685
Reference implementation of a Newton solver.