24#ifndef DUMUX_NEWTON_SOLVER_HH
25#define DUMUX_NEWTON_SOLVER_HH
34#include <dune/common/timer.hh>
35#include <dune/common/exceptions.hh>
36#include <dune/common/parallel/mpicommunication.hh>
37#include <dune/common/parallel/mpihelper.hh>
38#include <dune/common/std/type_traits.hh>
39#include <dune/common/indices.hh>
40#include <dune/common/hybridutilities.hh>
42#include <dune/istl/bvector.hh>
43#include <dune/istl/multitypeblockvector.hh>
64 template<
class Assembler>
66 ->
decltype(a.assembleJacobianAndResidual(std::declval<const typename Assembler::ResidualType&>(),
72template<
class Assembler>
73using DetectPVSwitch =
typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch;
75template<
class Assembler>
76using GetPVSwitch = Dune::Std::detected_or<int, DetectPVSwitch, Assembler>;
79template <
class LinearSolver,
class Res
idual>
80using NormDetector =
decltype(std::declval<LinearSolver>().norm(std::declval<Residual>()));
82template<
class LinearSolver,
class Res
idual>
84{
return Dune::Std::is_detected<NormDetector, LinearSolver, Residual>::value; }
90template<
class C>
static constexpr auto hasStaticIndexAccess = Dune::Std::is_detected<staticIndexAccess, C>{};
92template<
class V,
class Scalar,
class Reduce,
class Transform>
94-> std::enable_if_t<hasDynamicIndexAccess<V>(), Scalar>
96 return std::inner_product(v1.begin(), v1.end(), v2.begin(), init, std::forward<Reduce>(r), std::forward<Transform>(t));
99template<
class V,
class Scalar,
class Reduce,
class Transform>
100auto hybridInnerProduct(
const V& v1,
const V& v2, Scalar init, Reduce&& r, Transform&& t)
101-> std::enable_if_t<hasStaticIndexAccess<V>() && !hasDynamicIndexAccess<V>(), Scalar>
103 using namespace Dune::Hybrid;
104 forEach(std::make_index_sequence<V::N()>{}, [&](
auto i){
105 init = r(init,
hybridInnerProduct(v1[Dune::index_constant<i>{}], v2[Dune::index_constant<i>{}], init, std::forward<Reduce>(r), std::forward<Transform>(t)));
113template<
class Scalar,
class V>
115-> std::enable_if_t<Dune::IsNumber<V>::value, Scalar>
117 using std::abs;
using std::max;
118 return abs(v1 - v2)/max<Scalar>(1.0, abs(v1 + v2)*0.5);
123template<
class Scalar,
class V>
125-> std::enable_if_t<!Dune::IsNumber<V>::value, Scalar>
128 [](
const auto& a,
const auto& b){
using std::max;
return max(a, b); },
129 [](
const auto& a,
const auto& b){
return maxRelativeShift<Scalar>(a, b); }
133template<
class To,
class From>
136 if constexpr (std::is_assignable<To&, From>::value)
139 else if constexpr (hasStaticIndexAccess<To>() && hasStaticIndexAccess<To>() && !hasDynamicIndexAccess<From>() && !hasDynamicIndexAccess<From>())
141 using namespace Dune::Hybrid;
142 forEach(std::make_index_sequence<To::N()>{}, [&](
auto i){
143 assign(to[Dune::index_constant<i>{}], from[Dune::index_constant<i>{}]);
147 else if constexpr (hasDynamicIndexAccess<From>() && hasDynamicIndexAccess<From>())
148 for (
decltype(to.size()) i = 0; i < to.size(); ++i)
152 DUNE_THROW(Dune::Exception,
"Values are not assignable to each other!");
155template<
class T, std::enable_if_t<Dune::IsNumber<std::decay_t<T>>::value,
int> = 0>
158template<
class T, std::enable_if_t<!Dune::IsNumber<std::decay_t<T>>::value,
int> = 0>
159constexpr std::size_t
blockSize() {
return std::decay_t<T>::size(); }
173template <
class Assembler,
class LinearSolver,
174 class Reassembler = PartialReassembler<Assembler>,
175 class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
179 using Scalar =
typename Assembler::Scalar;
180 using JacobianMatrix =
typename Assembler::JacobianMatrix;
181 using SolutionVector =
typename Assembler::ResidualType;
187 static constexpr bool hasPriVarsSwitch() {
return HasPriVarsSwitch::value; };
215 if (enablePartialReassembly_)
216 partialReassembler_ = std::make_unique<Reassembler>(this->
assembler());
218 if (hasPriVarsSwitch())
220 const int priVarSwitchVerbosity = getParamFromGroup<int>(
paramGroup,
"PrimaryVariableSwitch.Verbosity", 1);
221 priVarSwitch_ = std::make_unique<PrimaryVariableSwitch>(priVarSwitchVerbosity);
237 { shiftTolerance_ = tolerance; }
246 { residualTolerance_ = tolerance; }
255 { reductionTolerance_ = tolerance; }
294 if (this->
assembler().isStationaryProblem())
295 DUNE_THROW(Dune::InvalidStateException,
"Using time step control with stationary problem makes no sense!");
298 for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
301 const bool converged = solve_(uCurrentIter);
306 else if (!converged && i < maxTimeStepDivisions_)
309 uCurrentIter = this->
assembler().prevSol();
312 this->
assembler().resetTimeStep(uCurrentIter);
317 std::cout << Fmt::format(
"Newton solver did not converge with dt = {} seconds. ", dt)
318 << Fmt::format(
"Retrying with time step of dt = {} seconds.\n", dt*retryTimeStepReductionFactor_);
328 Fmt::format(
"Newton solver didn't converge after {} time-step divisions; dt = {}.\n",
338 void solve(SolutionVector& uCurrentIter)
override
340 const bool converged = solve_(uCurrentIter);
343 Fmt::format(
"Newton solver didn't converge after {} iterations.\n",
numSteps_));
358 if (convergenceWriter_)
361 SolutionVector delta(u);
363 convergenceWriter_->write(u, delta, this->
assembler().residual());
366 if (enablePartialReassembly_)
368 partialReassembler_->resetColors();
369 resizeDistanceFromLastLinearization_(u, distanceFromLastLinearization_);
379 virtual bool newtonProceed(
const SolutionVector &uCurrentIter,
bool converged)
390 if (enableShiftCriterion_)
422 assembleLinearSystem_(this->
assembler(), uCurrentIter);
424 if (enablePartialReassembly_)
447 if constexpr (Detail::hasNorm<LinearSolver, SolutionVector>())
452 Scalar norm2 = b.two_norm2();
453 if (comm_.size() > 1)
454 norm2 = comm_.sum(norm2);
463 bool converged = solveLinearSystem_(deltaU);
466 int convergedRemote = converged;
467 if (comm_.size() > 1)
468 convergedRemote = comm_.min(converged);
472 ++numLinearSolverBreakdowns_;
474 else if (!convergedRemote) {
475 DUNE_THROW(
NumericalProblem,
"Linear solver did not converge on a remote process");
476 ++numLinearSolverBreakdowns_;
479 catch (
const Dune::Exception &e) {
482 if (comm_.size() > 1)
483 converged = comm_.min(converged);
509 const SolutionVector &uLastIter,
510 const SolutionVector &deltaU)
512 if (enableShiftCriterion_ || enablePartialReassembly_)
513 newtonUpdateShift_(uLastIter, deltaU);
515 if (enablePartialReassembly_) {
535 auto reassemblyThreshold = max(reassemblyMinThreshold_,
536 min(reassemblyMaxThreshold_,
537 shift_*reassemblyShiftWeight_));
539 updateDistanceFromLastLinearization_(uLastIter, deltaU);
540 partialReassembler_->computeColors(this->
assembler(),
541 distanceFromLastLinearization_,
542 reassemblyThreshold);
545 for (
unsigned int i = 0; i < distanceFromLastLinearization_.size(); i++)
547 distanceFromLastLinearization_[i] = 0;
551 lineSearchUpdate_(uCurrentIter, uLastIter, deltaU);
554 choppedUpdate_(uCurrentIter, uLastIter, deltaU);
558 uCurrentIter = uLastIter;
559 uCurrentIter -= deltaU;
562 if (enableResidualCriterion_)
574 const SolutionVector &uLastIter)
582 if (enableDynamicOutput_)
585 const auto width = Fmt::formatted_size(
"{}",
maxSteps_);
586 std::cout << Fmt::format(
"Newton iteration {:{}} done",
numSteps_, width);
588 if (enableShiftCriterion_)
589 std::cout << Fmt::format(
", maximum relative shift = {:.4e}",
shift_);
590 if (enableResidualCriterion_ && enableAbsoluteResidualCriterion_)
591 std::cout << Fmt::format(
", residual = {:.4e}",
residualNorm_);
592 else if (enableResidualCriterion_)
593 std::cout << Fmt::format(
", residual reduction = {:.4e}",
reduction_);
618 if (priVarsSwitchedInLastIteration_)
621 if (enableShiftCriterion_ && !enableResidualCriterion_)
623 return shift_ <= shiftTolerance_;
625 else if (!enableShiftCriterion_ && enableResidualCriterion_)
627 if(enableAbsoluteResidualCriterion_)
632 else if (satisfyResidualAndShiftCriterion_)
634 if(enableAbsoluteResidualCriterion_)
635 return shift_ <= shiftTolerance_
638 return shift_ <= shiftTolerance_
641 else if(enableShiftCriterion_ && enableResidualCriterion_)
643 if(enableAbsoluteResidualCriterion_)
644 return shift_ <= shiftTolerance_
647 return shift_ <= shiftTolerance_
652 return shift_ <= shiftTolerance_
675 void report(std::ostream& sout = std::cout)
const
678 <<
"Newton statistics\n"
679 <<
"----------------------------------------------\n"
680 <<
"-- Total Newton iterations: " << totalWastedIter_ + totalSucceededIter_ <<
'\n'
681 <<
"-- Total wasted Newton iterations: " << totalWastedIter_ <<
'\n'
682 <<
"-- Total succeeded Newton iterations: " << totalSucceededIter_ <<
'\n'
683 <<
"-- Average iterations per solve: " << std::setprecision(3) << double(totalSucceededIter_) / double(numConverged_) <<
'\n'
684 <<
"-- Number of linear solver breakdowns: " << numLinearSolverBreakdowns_ <<
'\n'
693 totalWastedIter_ = 0;
694 totalSucceededIter_ = 0;
696 numLinearSolverBreakdowns_ = 0;
704 sout <<
"\nNewton solver configured with the following options and parameters:\n";
706 if (useLineSearch_) sout <<
" -- Newton.UseLineSearch = true\n";
707 if (useChop_) sout <<
" -- Newton.EnableChop = true\n";
708 if (enablePartialReassembly_) sout <<
" -- Newton.EnablePartialReassembly = true\n";
709 if (enableAbsoluteResidualCriterion_) sout <<
" -- Newton.EnableAbsoluteResidualCriterion = true\n";
710 if (enableShiftCriterion_) sout <<
" -- Newton.EnableShiftCriterion = true (relative shift convergence criterion)\n";
711 if (enableResidualCriterion_) sout <<
" -- Newton.EnableResidualCriterion = true\n";
712 if (satisfyResidualAndShiftCriterion_) sout <<
" -- Newton.SatisfyResidualAndShiftCriterion = true\n";
714 if (enableShiftCriterion_) sout <<
" -- Newton.MaxRelativeShift = " << shiftTolerance_ <<
'\n';
715 if (enableAbsoluteResidualCriterion_) sout <<
" -- Newton.MaxAbsoluteResidual = " << residualTolerance_ <<
'\n';
716 if (enableResidualCriterion_) sout <<
" -- Newton.ResidualReduction = " << reductionTolerance_ <<
'\n';
717 sout <<
" -- Newton.MinSteps = " <<
minSteps_ <<
'\n';
718 sout <<
" -- Newton.MaxSteps = " <<
maxSteps_ <<
'\n';
719 sout <<
" -- Newton.TargetSteps = " <<
targetSteps_ <<
'\n';
720 if (enablePartialReassembly_)
722 sout <<
" -- Newton.ReassemblyMinThreshold = " << reassemblyMinThreshold_ <<
'\n';
723 sout <<
" -- Newton.ReassemblyMaxThreshold = " << reassemblyMaxThreshold_ <<
'\n';
724 sout <<
" -- Newton.ReassemblyShiftWeight = " << reassemblyShiftWeight_ <<
'\n';
726 sout <<
" -- Newton.RetryTimeStepReductionFactor = " << retryTimeStepReductionFactor_ <<
'\n';
727 sout <<
" -- Newton.MaxTimeStepDivisions = " << maxTimeStepDivisions_ <<
'\n';
748 return oldTimeStep/(1.0 + percent);
752 return oldTimeStep*(1.0 + percent/1.2);
759 { verbosity_ = val; }
765 {
return verbosity_ ; }
771 {
return paramGroup_; }
777 { convergenceWriter_ = convWriter; }
783 { convergenceWriter_ =
nullptr; }
792 this->
assembler().updateGridVariables(uCurrentIter);
797 if constexpr (Detail::hasNorm<LinearSolver, SolutionVector>())
799 this->
assembler().assembleResidual(uCurrentIter);
810 {
return enableResidualCriterion_; }
822 priVarSwitch_->reset(sol.size());
823 priVarsSwitchedInLastIteration_ =
false;
825 const auto& problem = this->
assembler().problem();
826 const auto& gridGeometry = this->
assembler().gridGeometry();
827 auto& gridVariables = this->
assembler().gridVariables();
828 priVarSwitch_->updateDirichletConstraints(problem, gridGeometry, gridVariables, sol);
843 const auto& gridGeometry = this->
assembler().gridGeometry();
844 const auto& problem = this->
assembler().problem();
845 auto& gridVariables = this->
assembler().gridVariables();
848 priVarsSwitchedInLastIteration_ = priVarSwitch_->update(uCurrentIter, gridVariables,
849 problem, gridGeometry);
851 if (priVarsSwitchedInLastIteration_)
853 for (
const auto& element : elements(gridGeometry.gridView()))
856 priVarSwitch_->updateSwitchedVolVars(problem, element, gridGeometry, gridVariables, uCurrentIter);
859 priVarSwitch_->updateSwitchedFluxVarsCache(problem, element, gridGeometry, gridVariables, uCurrentIter);
893 bool solve_(SolutionVector& uCurrentIter)
901 SolutionVector uLastIter(uCurrentIter);
902 SolutionVector deltaU(uCurrentIter);
905 Dune::Timer assembleTimer(
false);
906 Dune::Timer solveTimer(
false);
907 Dune::Timer updateTimer(
false);
911 bool converged =
false;
920 uLastIter = uCurrentIter;
922 if (verbosity_ >= 1 && enableDynamicOutput_)
923 std::cout <<
"Assemble: r(x^k) = dS/dt + div F - q; M = grad r"
931 assembleTimer.start();
933 assembleTimer.stop();
942 const char clearRemainingLine[] = { 0x1b,
'[',
'K', 0 };
944 if (verbosity_ >= 1 && enableDynamicOutput_)
945 std::cout <<
"\rSolve: M deltax^k = r"
946 << clearRemainingLine << std::flush;
960 if (verbosity_ >= 1 && enableDynamicOutput_)
961 std::cout <<
"\rUpdate: x^(k+1) = x^k - deltax^k"
962 << clearRemainingLine << std::flush;
974 if (convergenceWriter_)
976 this->
assembler().assembleResidual(uCurrentIter);
977 convergenceWriter_->write(uCurrentIter, deltaU, this->
assembler().residual());
1001 if (verbosity_ >= 1) {
1002 const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
1003 std::cout << Fmt::format(
"Assemble/solve/update time: {:.2g}({:.2f}%)/{:.2g}({:.2f}%)/{:.2g}({:.2f}%)\n",
1004 assembleTimer.elapsed(), 100*assembleTimer.elapsed()/elapsedTot,
1005 solveTimer.elapsed(), 100*solveTimer.elapsed()/elapsedTot,
1006 updateTimer.elapsed(), 100*updateTimer.elapsed()/elapsedTot);
1013 if (verbosity_ >= 1)
1014 std::cout <<
"Newton: Caught exception: \"" << e.what() <<
"\"\n";
1024 auto assembleLinearSystem_(
const A&
assembler,
const SolutionVector& uCurrentIter)
1027 this->
assembler().assembleJacobianAndResidual(uCurrentIter, partialReassembler_.get());
1032 auto assembleLinearSystem_(
const A& assembler,
const SolutionVector& uCurrentIter)
1033 ->
typename std::enable_if_t<!
decltype(
isValid(Detail::supportsPartialReassembly())(assembler))::value,
void>
1035 this->assembler().assembleJacobianAndResidual(uCurrentIter);
1045 virtual void newtonUpdateShift_(
const SolutionVector &uLastIter,
1046 const SolutionVector &deltaU)
1048 auto uNew = uLastIter;
1050 shift_ = Detail::maxRelativeShift<Scalar>(uLastIter, uNew);
1052 if (comm_.size() > 1)
1053 shift_ = comm_.max(shift_);
1056 virtual void lineSearchUpdate_(SolutionVector &uCurrentIter,
1057 const SolutionVector &uLastIter,
1058 const SolutionVector &deltaU)
1060 Scalar lambda = 1.0;
1064 uCurrentIter = deltaU;
1065 uCurrentIter *= -lambda;
1066 uCurrentIter += uLastIter;
1067 solutionChanged_(uCurrentIter);
1069 computeResidualReduction_(uCurrentIter);
1071 if (reduction_ < lastReduction_ || lambda <= 0.125) {
1072 endIterMsgStream_ << Fmt::format(
", residual reduction {:.4e}->{:.4e}@lambda={:.4f}", lastReduction_, reduction_, lambda);
1082 virtual void choppedUpdate_(SolutionVector &uCurrentIter,
1083 const SolutionVector &uLastIter,
1084 const SolutionVector &deltaU)
1086 DUNE_THROW(Dune::NotImplemented,
1087 "Chopped Newton update strategy not implemented.");
1090 virtual bool solveLinearSystem_(SolutionVector& deltaU)
1092 return solveLinearSystemImpl_(this->linearSolver(),
1093 this->assembler().jacobian(),
1095 this->assembler().residual());
1107 template<
class V = SolutionVector>
1108 typename std::enable_if_t<!isMultiTypeBlockVector<V>(),
bool>
1109 solveLinearSystemImpl_(LinearSolver& ls,
1120 constexpr auto blockSize = Detail::blockSize<decltype(b[0])>();
1121 using BlockType = Dune::FieldVector<Scalar, blockSize>;
1122 Dune::BlockVector<BlockType> xTmp; xTmp.resize(b.size());
1123 Dune::BlockVector<BlockType> bTmp(xTmp);
1126 const int converged = ls.solve(A, xTmp, bTmp);
1142 template<
class LS = LinearSolver,
class V = SolutionVector>
1143 typename std::enable_if_t<linearSolverAcceptsMultiTypeMatrix<LS>() &&
1144 isMultiTypeBlockVector<V>(),
bool>
1145 solveLinearSystemImpl_(LinearSolver& ls,
1150 assert(this->checkSizesOfSubMatrices(A) &&
"Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1151 return ls.solve(A, x, b);
1164 template<
class LS = LinearSolver,
class V = SolutionVector>
1165 typename std::enable_if_t<!linearSolverAcceptsMultiTypeMatrix<LS>() &&
1166 isMultiTypeBlockVector<V>(),
bool>
1167 solveLinearSystemImpl_(LinearSolver& ls,
1172 assert(this->checkSizesOfSubMatrices(A) &&
"Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1178 const std::size_t numRows = M.N();
1179 assert(numRows == M.M());
1183 assert(bTmp.size() == numRows);
1186 using VectorBlock =
typename Dune::FieldVector<Scalar, 1>;
1187 using BlockVector =
typename Dune::BlockVector<VectorBlock>;
1188 BlockVector y(numRows);
1191 const bool converged = ls.solve(M, y, bTmp);
1201 void initParams_(
const std::string& group =
"")
1203 useLineSearch_ = getParamFromGroup<bool>(group,
"Newton.UseLineSearch");
1204 useChop_ = getParamFromGroup<bool>(group,
"Newton.EnableChop");
1205 if(useLineSearch_ && useChop_)
1206 DUNE_THROW(Dune::InvalidStateException,
"Use either linesearch OR chop!");
1208 enableAbsoluteResidualCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableAbsoluteResidualCriterion");
1209 enableShiftCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableShiftCriterion");
1210 enableResidualCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableResidualCriterion") || enableAbsoluteResidualCriterion_;
1211 satisfyResidualAndShiftCriterion_ = getParamFromGroup<bool>(group,
"Newton.SatisfyResidualAndShiftCriterion");
1212 enableDynamicOutput_ = getParamFromGroup<bool>(group,
"Newton.EnableDynamicOutput",
true);
1214 if (!enableShiftCriterion_ && !enableResidualCriterion_)
1216 DUNE_THROW(Dune::NotImplemented,
1217 "at least one of NewtonEnableShiftCriterion or "
1218 <<
"NewtonEnableResidualCriterion has to be set to true");
1221 setMaxRelativeShift(getParamFromGroup<Scalar>(group,
"Newton.MaxRelativeShift"));
1222 setMaxAbsoluteResidual(getParamFromGroup<Scalar>(group,
"Newton.MaxAbsoluteResidual"));
1223 setResidualReduction(getParamFromGroup<Scalar>(group,
"Newton.ResidualReduction"));
1224 setTargetSteps(getParamFromGroup<int>(group,
"Newton.TargetSteps"));
1225 setMinSteps(getParamFromGroup<int>(group,
"Newton.MinSteps"));
1226 setMaxSteps(getParamFromGroup<int>(group,
"Newton.MaxSteps"));
1228 enablePartialReassembly_ = getParamFromGroup<bool>(group,
"Newton.EnablePartialReassembly");
1229 reassemblyMinThreshold_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyMinThreshold", 1e-1*shiftTolerance_);
1230 reassemblyMaxThreshold_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyMaxThreshold", 1e2*shiftTolerance_);
1231 reassemblyShiftWeight_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyShiftWeight", 1e-3);
1233 maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group,
"Newton.MaxTimeStepDivisions", 10);
1234 retryTimeStepReductionFactor_ = getParamFromGroup<Scalar>(group,
"Newton.RetryTimeStepReductionFactor", 0.5);
1236 verbosity_ = comm_.rank() == 0 ? getParamFromGroup<int>(group,
"Newton.Verbosity", 2) : 0;
1240 if (verbosity_ >= 2)
1245 void updateDistanceFromLastLinearization_(
const Sol& u,
const Sol& uDelta)
1247 for (
size_t i = 0; i < u.size(); ++i) {
1248 const auto& currentPriVars(u[i]);
1249 auto nextPriVars(currentPriVars);
1250 nextPriVars -= uDelta[i];
1253 auto shift = Detail::maxRelativeShift<Scalar>(currentPriVars, nextPriVars);
1254 distanceFromLastLinearization_[i] += shift;
1258 template<
class ...Args>
1259 void updateDistanceFromLastLinearization_(
const Dune::MultiTypeBlockVector<Args...>& uLastIter,
1260 const Dune::MultiTypeBlockVector<Args...>& deltaU)
1262 DUNE_THROW(Dune::NotImplemented,
"Reassembly for MultiTypeBlockVector");
1266 void resizeDistanceFromLastLinearization_(
const Sol& u, std::vector<Scalar>& dist)
1268 dist.assign(u.size(), 0.0);
1271 template<
class ...Args>
1272 void resizeDistanceFromLastLinearization_(
const Dune::MultiTypeBlockVector<Args...>& u,
1273 std::vector<Scalar>& dist)
1275 DUNE_THROW(Dune::NotImplemented,
"Reassembly for MultiTypeBlockVector");
1279 Communication comm_;
1284 Scalar shiftTolerance_;
1285 Scalar reductionTolerance_;
1286 Scalar residualTolerance_;
1289 std::size_t maxTimeStepDivisions_;
1290 Scalar retryTimeStepReductionFactor_;
1293 bool useLineSearch_;
1295 bool enableAbsoluteResidualCriterion_;
1296 bool enableShiftCriterion_;
1297 bool enableResidualCriterion_;
1298 bool satisfyResidualAndShiftCriterion_;
1299 bool enableDynamicOutput_;
1302 std::string paramGroup_;
1305 bool enablePartialReassembly_;
1306 std::unique_ptr<Reassembler> partialReassembler_;
1307 std::vector<Scalar> distanceFromLastLinearization_;
1308 Scalar reassemblyMinThreshold_;
1309 Scalar reassemblyMaxThreshold_;
1310 Scalar reassemblyShiftWeight_;
1313 std::size_t totalWastedIter_ = 0;
1314 std::size_t totalSucceededIter_ = 0;
1315 std::size_t numConverged_ = 0;
1316 std::size_t numLinearSolverBreakdowns_ = 0;
1319 std::unique_ptr<PrimaryVariableSwitch> priVarSwitch_;
1321 bool priVarsSwitchedInLastIteration_ =
false;
1324 std::shared_ptr<ConvergenceWriter> convergenceWriter_ =
nullptr;
Detects which entries in the Jacobian have to be recomputed.
Type traits to be used with vector types.
A helper function for class member function introspection.
Some exceptions thrown in DuMux
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Formatting based on the fmt-library which implements std::format of C++20.
Trait checking if linear solvers accept Dune::MultiTypeBlockMatrix or we need to convert the matrix.
A helper classe that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix.
This class provides the infrastructure to write the convergence behaviour of the newton method into a...
@ red
distance from last linearization is above the tolerance
constexpr auto isValid(const Expression &t)
A function that creates a test functor to do class member introspection at compile time.
Definition: isvalid.hh:93
auto hybridInnerProduct(const V &v1, const V &v2, Scalar init, Reduce &&r, Transform &&t) -> std::enable_if_t< hasDynamicIndexAccess< V >(), Scalar >
Definition: nonlinear/newtonsolver.hh:93
decltype(std::declval< LinearSolver >().norm(std::declval< Residual >())) NormDetector
Definition: nonlinear/newtonsolver.hh:80
decltype(std::declval< C >()[0]) dynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:87
void assign(To &to, const From &from)
Definition: nonlinear/newtonsolver.hh:134
static constexpr auto hasDynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:89
static constexpr auto hasStaticIndexAccess
Definition: nonlinear/newtonsolver.hh:90
Dune::Std::detected_or< int, DetectPVSwitch, Assembler > GetPVSwitch
Definition: nonlinear/newtonsolver.hh:76
static constexpr bool hasNorm()
Definition: nonlinear/newtonsolver.hh:83
constexpr std::size_t blockSize()
Definition: nonlinear/newtonsolver.hh:156
decltype(std::declval< C >()[Dune::Indices::_0]) staticIndexAccess
Definition: nonlinear/newtonsolver.hh:88
typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch DetectPVSwitch
helper aliases to extract a primary variable switch from the VolumeVariables (if defined,...
Definition: nonlinear/newtonsolver.hh:73
auto maxRelativeShift(const V &v1, const V &v2) -> std::enable_if_t< Dune::IsNumber< V >::value, Scalar >
Definition: nonlinear/newtonsolver.hh:114
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:425
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:39
A high-level interface for a PDESolver.
Definition: common/pdesolver.hh:55
const Assembler & assembler() const
Access the assembler.
Definition: common/pdesolver.hh:92
const LinearSolver & linearSolver() const
Access the linear solver.
Definition: common/pdesolver.hh:104
Manages the handling of time dependent problems.
Definition: common/timeloop.hh:69
virtual void setTimeStepSize(Scalar dt)=0
Set the current time step size to a given value.
virtual Scalar timeStepSize() const =0
Returns the suggested time step length .
static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A)
Converts the matrix to a type the IterativeSolverBackend can handle.
Definition: matrixconverter.hh:58
static void retrieveValues(MultiTypeBlockVector &x, const BlockVector &y)
Copys the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector.
Definition: matrixconverter.hh:241
static auto multiTypeToBlockVector(const MultiTypeBlockVector &b)
Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector.
Definition: matrixconverter.hh:215
void setResidualReduction(double r)
set the linear solver residual reduction
Definition: solver.hh:103
Definition: newtonconvergencewriter.hh:39
helper struct detecting if an assembler supports partial reassembly
Definition: nonlinear/newtonsolver.hh:63
auto operator()(Assembler &&a) -> decltype(a.assembleJacobianAndResidual(std::declval< const typename Assembler::ResidualType & >(), std::declval< const PartialReassembler< Assembler > * >()))
Definition: nonlinear/newtonsolver.hh:65
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:177
virtual void solutionChanged_(const SolutionVector &uCurrentIter)
Update solution-depended quantities like grid variables after the solution has changed.
Definition: nonlinear/newtonsolver.hh:790
void solve(SolutionVector &uCurrentIter) override
Run the Newton method to solve a non-linear system. The solver is responsible for all the strategic d...
Definition: nonlinear/newtonsolver.hh:338
Comm Communication
Definition: nonlinear/newtonsolver.hh:191
int maxSteps_
maximum number of iterations we do before giving up
Definition: nonlinear/newtonsolver.hh:869
void setMaxSteps(int maxSteps)
Set the number of iterations after which the Newton method gives up.
Definition: nonlinear/newtonsolver.hh:285
void setResidualReduction(Scalar tolerance)
Set the maximum acceptable residual norm reduction.
Definition: nonlinear/newtonsolver.hh:254
void invokePriVarSwitch_(SolutionVector &, std::false_type)
Switch primary variables if necessary, noop if there is no priVarSwitch.
Definition: nonlinear/newtonsolver.hh:834
void newtonUpdate(SolutionVector &uCurrentIter, const SolutionVector &uLastIter, const SolutionVector &deltaU)
Update the current solution with a delta vector.
Definition: nonlinear/newtonsolver.hh:508
void reportParams(std::ostream &sout=std::cout) const
Report the options and parameters this Newton is configured with.
Definition: nonlinear/newtonsolver.hh:702
void initPriVarSwitch_(SolutionVector &, std::false_type)
Initialize the privar switch, noop if there is no priVarSwitch.
Definition: nonlinear/newtonsolver.hh:815
int targetSteps_
optimal number of iterations we want to achieve
Definition: nonlinear/newtonsolver.hh:865
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:770
Scalar reduction_
Definition: nonlinear/newtonsolver.hh:874
int numSteps_
actual number of steps done so far
Definition: nonlinear/newtonsolver.hh:871
int verbosity() const
Return the verbosity level.
Definition: nonlinear/newtonsolver.hh:764
void setMinSteps(int minSteps)
Set the number of minimum iterations for the Newton method.
Definition: nonlinear/newtonsolver.hh:276
int minSteps_
minimum number of iterations we do
Definition: nonlinear/newtonsolver.hh:867
bool enableResidualCriterion() const
Definition: nonlinear/newtonsolver.hh:809
void report(std::ostream &sout=std::cout) const
output statistics / report
Definition: nonlinear/newtonsolver.hh:675
virtual void newtonBeginStep(const SolutionVector &u)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:402
virtual void newtonEndStep(SolutionVector &uCurrentIter, const SolutionVector &uLastIter)
Indicates that one Newton iteration was finished.
Definition: nonlinear/newtonsolver.hh:573
void initPriVarSwitch_(SolutionVector &sol, std::true_type)
Initialize the privar switch.
Definition: nonlinear/newtonsolver.hh:820
NewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCollectiveCommunication(), const std::string ¶mGroup="")
The Constructor.
Definition: nonlinear/newtonsolver.hh:196
virtual void newtonSucceed()
Called if the Newton method ended successfully This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:670
void attachConvergenceWriter(std::shared_ptr< ConvergenceWriter > convWriter)
Attach a convergence writer to write out intermediate results after each iteration.
Definition: nonlinear/newtonsolver.hh:776
Scalar initialResidual_
Definition: nonlinear/newtonsolver.hh:877
Scalar lastReduction_
Definition: nonlinear/newtonsolver.hh:876
std::ostringstream endIterMsgStream_
message stream to be displayed at the end of iterations
Definition: nonlinear/newtonsolver.hh:884
void setVerbosity(int val)
Specifies the verbosity level.
Definition: nonlinear/newtonsolver.hh:758
void invokePriVarSwitch_(SolutionVector &uCurrentIter, std::true_type)
Switch primary variables if necessary.
Definition: nonlinear/newtonsolver.hh:839
virtual void assembleLinearSystem(const SolutionVector &uCurrentIter)
Assemble the linear system of equations .
Definition: nonlinear/newtonsolver.hh:420
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:226
void resetReport()
reset the statistics
Definition: nonlinear/newtonsolver.hh:691
virtual void newtonFail(SolutionVector &u)
Called if the Newton method broke down. This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:664
void setMaxAbsoluteResidual(Scalar tolerance)
Set the maximum acceptable absolute residual for declaring convergence.
Definition: nonlinear/newtonsolver.hh:245
virtual void newtonEnd()
Called if the Newton method ended (not known yet if we failed or succeeded)
Definition: nonlinear/newtonsolver.hh:608
void solve(SolutionVector &uCurrentIter, TimeLoop &timeLoop) override
Run the Newton method to solve a non-linear system. Does time step control when the Newton fails to c...
Definition: nonlinear/newtonsolver.hh:292
void setTargetSteps(int targetSteps)
Set the number of iterations at which the Newton method should aim at.
Definition: nonlinear/newtonsolver.hh:267
virtual void newtonBegin(SolutionVector &u)
Called before the Newton method is applied to an non-linear system of equations.
Definition: nonlinear/newtonsolver.hh:352
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:614
Scalar suggestTimeStepSize(Scalar oldTimeStep) const
Suggest a new time-step size based on the old time-step size.
Definition: nonlinear/newtonsolver.hh:739
void solveLinearSystem(SolutionVector &deltaU)
Solve the linear system of equations .
Definition: nonlinear/newtonsolver.hh:439
void computeResidualReduction_(const SolutionVector &uCurrentIter)
Definition: nonlinear/newtonsolver.hh:795
void detachConvergenceWriter()
Detach the convergence writer to stop the output.
Definition: nonlinear/newtonsolver.hh:782
void setMaxRelativeShift(Scalar tolerance)
Set the maximum acceptable difference of any primary variable between two iterations for declaring co...
Definition: nonlinear/newtonsolver.hh:236
Scalar shift_
Definition: nonlinear/newtonsolver.hh:880
virtual bool newtonProceed(const SolutionVector &uCurrentIter, bool converged)
Returns true if another iteration should be done.
Definition: nonlinear/newtonsolver.hh:379
Scalar residualNorm_
Definition: nonlinear/newtonsolver.hh:875
Scalar lastShift_
Definition: nonlinear/newtonsolver.hh:881
Defines a high-level interface for a PDESolver.
Manages the handling of time dependent problems.