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>
66template<
class Assembler>
68 = Dune::Std::is_detected_v<AssemblerGridVariablesType, Assembler>;
71template<
class Assembler,
bool exportsGr
idVars = assemblerExportsGr
idVariables<Assembler>>
76template<
class Assembler>
78{
using Type =
struct EmptyGridVariables {}; };
81template<
class Assembler>
88 template<
class Assembler>
90 ->
decltype(a.assembleJacobianAndResidual(std::declval<const typename Assembler::ResidualType&>(),
96template <
class LinearSolver,
class Res
idual>
97using NormDetector =
decltype(std::declval<LinearSolver>().norm(std::declval<Residual>()));
99template<
class LinearSolver,
class Res
idual>
101{
return Dune::Std::is_detected<NormDetector, LinearSolver, Residual>::value; }
109template<
class V,
class Scalar,
class Reduce,
class Transform>
111-> std::enable_if_t<hasDynamicIndexAccess<V>(), Scalar>
113 return std::inner_product(v1.begin(), v1.end(), v2.begin(), init, std::forward<Reduce>(r), std::forward<Transform>(t));
116template<
class V,
class Scalar,
class Reduce,
class Transform>
117auto hybridInnerProduct(
const V& v1,
const V& v2, Scalar init, Reduce&& r, Transform&& t)
118-> std::enable_if_t<hasStaticIndexAccess<V>() && !hasDynamicIndexAccess<V>(), Scalar>
120 using namespace Dune::Hybrid;
121 forEach(std::make_index_sequence<V::N()>{}, [&](
auto i){
122 init = r(init,
hybridInnerProduct(v1[Dune::index_constant<i>{}], v2[Dune::index_constant<i>{}], init, std::forward<Reduce>(r), std::forward<Transform>(t)));
130template<
class Scalar,
class V>
132-> std::enable_if_t<Dune::IsNumber<V>::value, Scalar>
134 using std::abs;
using std::max;
135 return abs(v1 - v2)/max<Scalar>(1.0, abs(v1 + v2)*0.5);
140template<
class Scalar,
class V>
142-> std::enable_if_t<!Dune::IsNumber<V>::value, Scalar>
145 [](
const auto& a,
const auto& b){
using std::max;
return max(a, b); },
146 [](
const auto& a,
const auto& b){
return maxRelativeShift<Scalar>(a, b); }
150template<
class To,
class From>
153 if constexpr (std::is_assignable<To&, From>::value)
156 else if constexpr (hasStaticIndexAccess<To>() && hasStaticIndexAccess<To>() && !hasDynamicIndexAccess<From>() && !hasDynamicIndexAccess<From>())
158 using namespace Dune::Hybrid;
159 forEach(std::make_index_sequence<To::N()>{}, [&](
auto i){
160 assign(to[Dune::index_constant<i>{}], from[Dune::index_constant<i>{}]);
164 else if constexpr (hasDynamicIndexAccess<To>() && hasDynamicIndexAccess<From>())
165 for (
decltype(to.size()) i = 0; i < to.size(); ++i)
168 else if constexpr (hasDynamicIndexAccess<To>() && Dune::IsNumber<From>::value)
170 assert(to.size() == 1);
174 else if constexpr (Dune::IsNumber<To>::value && hasDynamicIndexAccess<From>())
176 assert(from.size() == 1);
181 DUNE_THROW(Dune::Exception,
"Values are not assignable to each other!");
184template<
class T, std::enable_if_t<Dune::IsNumber<std::decay_t<T>>::value,
int> = 0>
187template<
class T, std::enable_if_t<!Dune::IsNumber<std::decay_t<T>>::value,
int> = 0>
188constexpr std::size_t
blockSize() {
return std::decay_t<T>::size(); }
190template<
class S,
bool isScalar = false>
192{
using type = std::decay_t<decltype(std::declval<S>()[0])>; };
197template<
class SolutionVector>
214 class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator> >
224 using Scalar =
typename Assembler::Scalar;
225 using JacobianMatrix =
typename Assembler::JacobianMatrix;
231 static constexpr bool assemblerExportsVariables = Detail::exportsVariables<Assembler>;
232 using PriVarSwitchVariables
233 = std::conditional_t<assemblerExportsVariables,
262 this->
linearSolver().setResidualReduction(getParamFromGroup<Scalar>(
paramGroup,
"LinearSolver.ResidualReduction", 1e-6));
265 if (enablePartialReassembly_)
266 partialReassembler_ = std::make_unique<Reassembler>(this->
assembler());
281 { shiftTolerance_ = tolerance; }
290 { residualTolerance_ = tolerance; }
299 { reductionTolerance_ = tolerance; }
341 if constexpr (!assemblerExportsVariables)
343 if (this->
assembler().isStationaryProblem())
344 DUNE_THROW(Dune::InvalidStateException,
"Using time step control with stationary problem makes no sense!");
348 for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
351 const bool converged = solve_(vars);
356 else if (!converged && i < maxTimeStepDivisions_)
358 if constexpr (assemblerExportsVariables)
359 DUNE_THROW(Dune::NotImplemented,
"Time step reset for new assembly methods");
363 Backend::update(vars, this->
assembler().prevSol());
364 this->
assembler().resetTimeStep(Backend::dofs(vars));
369 std::cout << Fmt::format(
"Newton solver did not converge with dt = {} seconds. ", dt)
370 << Fmt::format(
"Retrying with time step of dt = {} seconds.\n", dt*retryTimeStepReductionFactor_);
381 Fmt::format(
"Newton solver didn't converge after {} time-step divisions; dt = {}.\n",
395 const bool converged = solve_(vars);
398 Fmt::format(
"Newton solver didn't converge after {} iterations.\n",
numSteps_));
411 if constexpr (hasPriVarsSwitch<PriVarSwitchVariables>)
413 if constexpr (assemblerExportsVariables)
414 priVarSwitchAdapter_->initialize(Backend::dofs(initVars), initVars);
416 priVarSwitchAdapter_->initialize(initVars, this->
assembler().gridVariables());
419 const auto& initSol = Backend::dofs(initVars);
422 if (convergenceWriter_)
424 this->
assembler().assembleResidual(initVars);
427 auto delta = Backend::zeros(Backend::size(initSol));
428 convergenceWriter_->write(initSol, delta, this->
assembler().residual());
431 if (enablePartialReassembly_)
433 partialReassembler_->resetColors();
434 resizeDistanceFromLastLinearization_(initSol, distanceFromLastLinearization_);
455 if (enableShiftCriterion_)
487 assembleLinearSystem_(this->
assembler(), vars);
489 if (enablePartialReassembly_)
507 bool converged =
false;
513 if constexpr (Detail::hasNorm<LinearSolver, SolutionVector>())
518 Scalar norm2 = b.two_norm2();
519 if (comm_.size() > 1)
520 norm2 = comm_.sum(norm2);
529 converged = solveLinearSystem_(deltaU);
531 catch (
const Dune::Exception &e)
534 std::cout <<
"Newton: Caught exception from the linear solver: \"" << e.what() <<
"\"\n";
540 int convergedRemote = converged;
541 if (comm_.size() > 1)
542 convergedRemote = comm_.min(converged);
547 ++numLinearSolverBreakdowns_;
549 else if (!convergedRemote)
551 DUNE_THROW(
NumericalProblem,
"Linear solver did not converge on a remote process");
552 ++numLinearSolverBreakdowns_;
577 if (enableShiftCriterion_ || enablePartialReassembly_)
578 newtonUpdateShift_(uLastIter, deltaU);
580 if (enablePartialReassembly_) {
600 auto reassemblyThreshold = max(reassemblyMinThreshold_,
601 min(reassemblyMaxThreshold_,
602 shift_*reassemblyShiftWeight_));
604 updateDistanceFromLastLinearization_(uLastIter, deltaU);
605 partialReassembler_->computeColors(this->
assembler(),
606 distanceFromLastLinearization_,
607 reassemblyThreshold);
610 for (
unsigned int i = 0; i < distanceFromLastLinearization_.size(); i++)
612 distanceFromLastLinearization_[i] = 0;
616 lineSearchUpdate_(vars, uLastIter, deltaU);
619 choppedUpdate_(vars, uLastIter, deltaU);
623 auto uCurrentIter = uLastIter;
624 uCurrentIter -= deltaU;
627 if (enableResidualCriterion_)
641 if constexpr (hasPriVarsSwitch<PriVarSwitchVariables>)
643 if constexpr (assemblerExportsVariables)
644 priVarSwitchAdapter_->invoke(Backend::dofs(vars), vars);
646 priVarSwitchAdapter_->invoke(vars, this->
assembler().gridVariables());
653 if (enableDynamicOutput_)
656 const auto width = Fmt::formatted_size(
"{}",
maxSteps_);
657 std::cout << Fmt::format(
"Newton iteration {:{}} done",
numSteps_, width);
659 if (enableShiftCriterion_)
660 std::cout << Fmt::format(
", maximum relative shift = {:.4e}",
shift_);
661 if (enableResidualCriterion_ && enableAbsoluteResidualCriterion_)
662 std::cout << Fmt::format(
", residual = {:.4e}",
residualNorm_);
663 else if (enableResidualCriterion_)
664 std::cout << Fmt::format(
", residual reduction = {:.4e}",
reduction_);
689 if (priVarSwitchAdapter_->switched())
692 if (enableShiftCriterion_ && !enableResidualCriterion_)
694 return shift_ <= shiftTolerance_;
696 else if (!enableShiftCriterion_ && enableResidualCriterion_)
698 if(enableAbsoluteResidualCriterion_)
703 else if (satisfyResidualAndShiftCriterion_)
705 if(enableAbsoluteResidualCriterion_)
706 return shift_ <= shiftTolerance_
709 return shift_ <= shiftTolerance_
712 else if(enableShiftCriterion_ && enableResidualCriterion_)
714 if(enableAbsoluteResidualCriterion_)
715 return shift_ <= shiftTolerance_
718 return shift_ <= shiftTolerance_
723 return shift_ <= shiftTolerance_
746 void report(std::ostream& sout = std::cout)
const
749 <<
"Newton statistics\n"
750 <<
"----------------------------------------------\n"
751 <<
"-- Total Newton iterations: " << totalWastedIter_ + totalSucceededIter_ <<
'\n'
752 <<
"-- Total wasted Newton iterations: " << totalWastedIter_ <<
'\n'
753 <<
"-- Total succeeded Newton iterations: " << totalSucceededIter_ <<
'\n'
754 <<
"-- Average iterations per solve: " << std::setprecision(3) << double(totalSucceededIter_) / double(numConverged_) <<
'\n'
755 <<
"-- Number of linear solver breakdowns: " << numLinearSolverBreakdowns_ <<
'\n'
764 totalWastedIter_ = 0;
765 totalSucceededIter_ = 0;
767 numLinearSolverBreakdowns_ = 0;
775 sout <<
"\nNewton solver configured with the following options and parameters:\n";
777 if (useLineSearch_) sout <<
" -- Newton.UseLineSearch = true\n";
778 if (useChop_) sout <<
" -- Newton.EnableChop = true\n";
779 if (enablePartialReassembly_) sout <<
" -- Newton.EnablePartialReassembly = true\n";
780 if (enableAbsoluteResidualCriterion_) sout <<
" -- Newton.EnableAbsoluteResidualCriterion = true\n";
781 if (enableShiftCriterion_) sout <<
" -- Newton.EnableShiftCriterion = true (relative shift convergence criterion)\n";
782 if (enableResidualCriterion_) sout <<
" -- Newton.EnableResidualCriterion = true\n";
783 if (satisfyResidualAndShiftCriterion_) sout <<
" -- Newton.SatisfyResidualAndShiftCriterion = true\n";
785 if (enableShiftCriterion_) sout <<
" -- Newton.MaxRelativeShift = " << shiftTolerance_ <<
'\n';
786 if (enableAbsoluteResidualCriterion_) sout <<
" -- Newton.MaxAbsoluteResidual = " << residualTolerance_ <<
'\n';
787 if (enableResidualCriterion_) sout <<
" -- Newton.ResidualReduction = " << reductionTolerance_ <<
'\n';
788 sout <<
" -- Newton.MinSteps = " <<
minSteps_ <<
'\n';
789 sout <<
" -- Newton.MaxSteps = " <<
maxSteps_ <<
'\n';
790 sout <<
" -- Newton.TargetSteps = " <<
targetSteps_ <<
'\n';
791 if (enablePartialReassembly_)
793 sout <<
" -- Newton.ReassemblyMinThreshold = " << reassemblyMinThreshold_ <<
'\n';
794 sout <<
" -- Newton.ReassemblyMaxThreshold = " << reassemblyMaxThreshold_ <<
'\n';
795 sout <<
" -- Newton.ReassemblyShiftWeight = " << reassemblyShiftWeight_ <<
'\n';
797 sout <<
" -- Newton.RetryTimeStepReductionFactor = " << retryTimeStepReductionFactor_ <<
'\n';
798 sout <<
" -- Newton.MaxTimeStepDivisions = " << maxTimeStepDivisions_ <<
'\n';
819 return oldTimeStep/(1.0 + percent);
823 return oldTimeStep*(1.0 + percent/1.2);
830 { verbosity_ = val; }
836 {
return verbosity_ ; }
842 {
return paramGroup_; }
848 { convergenceWriter_ = convWriter; }
854 { convergenceWriter_ =
nullptr; }
860 {
return retryTimeStepReductionFactor_; }
866 { retryTimeStepReductionFactor_ = factor; }
877 Backend::update(vars, uCurrentIter);
879 if constexpr (!assemblerExportsVariables)
880 this->
assembler().updateGridVariables(Backend::dofs(vars));
887 if constexpr (Detail::hasNorm<LinearSolver, SolutionVector>())
889 if constexpr (!assemblerExportsVariables)
890 this->
assembler().assembleResidual(Backend::dofs(vars));
892 this->
assembler().assembleResidual(vars);
897 if constexpr (!assemblerExportsVariables)
908 {
return enableResidualCriterion_; }
947 auto uLastIter = Backend::dofs(vars);
948 auto deltaU = Backend::dofs(vars);
951 Dune::Timer assembleTimer(
false);
952 Dune::Timer solveTimer(
false);
953 Dune::Timer updateTimer(
false);
957 bool converged =
false;
966 uLastIter = Backend::dofs(vars);
968 if (verbosity_ >= 1 && enableDynamicOutput_)
969 std::cout <<
"Assemble: r(x^k) = dS/dt + div F - q; M = grad r"
977 assembleTimer.start();
979 assembleTimer.stop();
988 const char clearRemainingLine[] = { 0x1b,
'[',
'K', 0 };
990 if (verbosity_ >= 1 && enableDynamicOutput_)
991 std::cout <<
"\rSolve: M deltax^k = r"
992 << clearRemainingLine << std::flush;
1006 if (verbosity_ >= 1 && enableDynamicOutput_)
1007 std::cout <<
"\rUpdate: x^(k+1) = x^k - deltax^k"
1008 << clearRemainingLine << std::flush;
1010 updateTimer.start();
1020 if (convergenceWriter_)
1022 this->
assembler().assembleResidual(vars);
1023 convergenceWriter_->write(Backend::dofs(vars), deltaU, this->
assembler().residual());
1047 if (verbosity_ >= 1) {
1048 const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
1049 std::cout << Fmt::format(
"Assemble/solve/update time: {:.2g}({:.2f}%)/{:.2g}({:.2f}%)/{:.2g}({:.2f}%)\n",
1050 assembleTimer.elapsed(), 100*assembleTimer.elapsed()/elapsedTot,
1051 solveTimer.elapsed(), 100*solveTimer.elapsed()/elapsedTot,
1052 updateTimer.elapsed(), 100*updateTimer.elapsed()/elapsedTot);
1059 if (verbosity_ >= 1)
1060 std::cout <<
"Newton: Caught exception: \"" << e.what() <<
"\"\n";
1074 this->
assembler().assembleJacobianAndResidual(vars, partialReassembler_.get());
1079 auto assembleLinearSystem_(
const A& assembler,
const Variables& vars)
1080 ->
typename std::enable_if_t<!
decltype(
isValid(Detail::supportsPartialReassembly())(assembler))::value,
void>
1082 this->assembler().assembleJacobianAndResidual(vars);
1092 virtual void newtonUpdateShift_(
const SolutionVector &uLastIter,
1093 const SolutionVector &deltaU)
1095 auto uNew = uLastIter;
1097 shift_ = Detail::maxRelativeShift<Scalar>(uLastIter, uNew);
1099 if (comm_.size() > 1)
1100 shift_ = comm_.max(shift_);
1103 virtual void lineSearchUpdate_(Variables &vars,
1104 const SolutionVector &uLastIter,
1105 const SolutionVector &deltaU)
1107 Scalar lambda = 1.0;
1108 auto uCurrentIter = uLastIter;
1112 Backend::axpy(-lambda, deltaU, uCurrentIter);
1113 solutionChanged_(vars, uCurrentIter);
1115 computeResidualReduction_(vars);
1117 if (reduction_ < lastReduction_ || lambda <= lineSearchMinRelaxationFactor_)
1119 endIterMsgStream_ << Fmt::format(
", residual reduction {:.4e}->{:.4e}@lambda={:.4f}", lastReduction_, reduction_, lambda);
1125 uCurrentIter = uLastIter;
1130 virtual void choppedUpdate_(Variables& vars,
1131 const SolutionVector& uLastIter,
1132 const SolutionVector& deltaU)
1134 DUNE_THROW(Dune::NotImplemented,
1135 "Chopped Newton update strategy not implemented.");
1138 virtual bool solveLinearSystem_(SolutionVector& deltaU)
1140 return solveLinearSystemImpl_(this->linearSolver(),
1141 this->assembler().jacobian(),
1143 this->assembler().residual());
1155 template<
class V = SolutionVector>
1156 typename std::enable_if_t<!isMultiTypeBlockVector<V>(),
bool>
1157 solveLinearSystemImpl_(LinearSolver& ls,
1168 using OriginalBlockType = Detail::BlockType<SolutionVector>;
1169 constexpr auto blockSize = Detail::blockSize<OriginalBlockType>();
1171 using BlockType = Dune::FieldVector<Scalar, blockSize>;
1172 Dune::BlockVector<BlockType> xTmp; xTmp.resize(Backend::size(b));
1173 Dune::BlockVector<BlockType> bTmp(xTmp);
1176 const int converged = ls.solve(A, xTmp, bTmp);
1192 template<
class LS = LinearSolver,
class V = SolutionVector>
1193 typename std::enable_if_t<linearSolverAcceptsMultiTypeMatrix<LS>() &&
1194 isMultiTypeBlockVector<V>(),
bool>
1195 solveLinearSystemImpl_(LinearSolver& ls,
1200 assert(this->checkSizesOfSubMatrices(A) &&
"Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1201 return ls.solve(A, x, b);
1214 template<
class LS = LinearSolver,
class V = SolutionVector>
1215 typename std::enable_if_t<!linearSolverAcceptsMultiTypeMatrix<LS>() &&
1216 isMultiTypeBlockVector<V>(),
bool>
1217 solveLinearSystemImpl_(LinearSolver& ls,
1222 assert(this->checkSizesOfSubMatrices(A) &&
"Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1228 const std::size_t numRows = M.N();
1229 assert(numRows == M.M());
1233 assert(bTmp.size() == numRows);
1236 using VectorBlock =
typename Dune::FieldVector<Scalar, 1>;
1237 using BlockVector =
typename Dune::BlockVector<VectorBlock>;
1238 BlockVector y(numRows);
1241 const bool converged = ls.solve(M, y, bTmp);
1251 void initParams_(
const std::string& group =
"")
1253 useLineSearch_ = getParamFromGroup<bool>(group,
"Newton.UseLineSearch",
false);
1254 lineSearchMinRelaxationFactor_ = getParamFromGroup<Scalar>(group,
"Newton.LineSearchMinRelaxationFactor", 0.125);
1255 useChop_ = getParamFromGroup<bool>(group,
"Newton.EnableChop",
false);
1256 if(useLineSearch_ && useChop_)
1257 DUNE_THROW(Dune::InvalidStateException,
"Use either linesearch OR chop!");
1259 enableAbsoluteResidualCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableAbsoluteResidualCriterion",
false);
1260 enableShiftCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableShiftCriterion",
true);
1261 enableResidualCriterion_ = getParamFromGroup<bool>(group,
"Newton.EnableResidualCriterion",
false) || enableAbsoluteResidualCriterion_;
1262 satisfyResidualAndShiftCriterion_ = getParamFromGroup<bool>(group,
"Newton.SatisfyResidualAndShiftCriterion",
false);
1263 enableDynamicOutput_ = getParamFromGroup<bool>(group,
"Newton.EnableDynamicOutput",
true);
1265 if (!enableShiftCriterion_ && !enableResidualCriterion_)
1267 DUNE_THROW(Dune::NotImplemented,
1268 "at least one of NewtonEnableShiftCriterion or "
1269 <<
"NewtonEnableResidualCriterion has to be set to true");
1272 setMaxRelativeShift(getParamFromGroup<Scalar>(group,
"Newton.MaxRelativeShift", 1e-8));
1273 setMaxAbsoluteResidual(getParamFromGroup<Scalar>(group,
"Newton.MaxAbsoluteResidual", 1e-5));
1274 setResidualReduction(getParamFromGroup<Scalar>(group,
"Newton.ResidualReduction", 1e-5));
1275 setTargetSteps(getParamFromGroup<int>(group,
"Newton.TargetSteps", 10));
1276 setMinSteps(getParamFromGroup<int>(group,
"Newton.MinSteps", 2));
1277 setMaxSteps(getParamFromGroup<int>(group,
"Newton.MaxSteps", 18));
1279 enablePartialReassembly_ = getParamFromGroup<bool>(group,
"Newton.EnablePartialReassembly",
false);
1280 reassemblyMinThreshold_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyMinThreshold", 1e-1*shiftTolerance_);
1281 reassemblyMaxThreshold_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyMaxThreshold", 1e2*shiftTolerance_);
1282 reassemblyShiftWeight_ = getParamFromGroup<Scalar>(group,
"Newton.ReassemblyShiftWeight", 1e-3);
1284 maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group,
"Newton.MaxTimeStepDivisions", 10);
1285 retryTimeStepReductionFactor_ = getParamFromGroup<Scalar>(group,
"Newton.RetryTimeStepReductionFactor", 0.5);
1287 verbosity_ = comm_.rank() == 0 ? getParamFromGroup<int>(group,
"Newton.Verbosity", 2) : 0;
1291 if (verbosity_ >= 2)
1296 void updateDistanceFromLastLinearization_(
const Sol& u,
const Sol& uDelta)
1298 if constexpr (Dune::IsNumber<Sol>::value)
1300 auto nextPriVars = u;
1301 nextPriVars -= uDelta;
1304 auto shift = Detail::maxRelativeShift<Scalar>(u, nextPriVars);
1305 distanceFromLastLinearization_[0] += shift;
1309 for (std::size_t i = 0; i < u.size(); ++i)
1311 const auto& currentPriVars(u[i]);
1312 auto nextPriVars(currentPriVars);
1313 nextPriVars -= uDelta[i];
1316 auto shift = Detail::maxRelativeShift<Scalar>(currentPriVars, nextPriVars);
1317 distanceFromLastLinearization_[i] += shift;
1322 template<
class ...Args>
1326 DUNE_THROW(Dune::NotImplemented,
"Reassembly for MultiTypeBlockVector");
1330 void resizeDistanceFromLastLinearization_(
const Sol& u, std::vector<Scalar>& dist)
1332 dist.assign(Backend::size(u), 0.0);
1335 template<
class ...Args>
1337 std::vector<Scalar>& dist)
1339 DUNE_THROW(Dune::NotImplemented,
"Reassembly for MultiTypeBlockVector");
1343 Communication comm_;
1348 Scalar shiftTolerance_;
1349 Scalar reductionTolerance_;
1350 Scalar residualTolerance_;
1353 std::size_t maxTimeStepDivisions_;
1354 Scalar retryTimeStepReductionFactor_;
1357 bool useLineSearch_;
1358 Scalar lineSearchMinRelaxationFactor_;
1360 bool enableAbsoluteResidualCriterion_;
1361 bool enableShiftCriterion_;
1362 bool enableResidualCriterion_;
1363 bool satisfyResidualAndShiftCriterion_;
1364 bool enableDynamicOutput_;
1367 std::string paramGroup_;
1370 bool enablePartialReassembly_;
1371 std::unique_ptr<Reassembler> partialReassembler_;
1372 std::vector<Scalar> distanceFromLastLinearization_;
1373 Scalar reassemblyMinThreshold_;
1374 Scalar reassemblyMaxThreshold_;
1375 Scalar reassemblyShiftWeight_;
1378 std::size_t totalWastedIter_ = 0;
1379 std::size_t totalSucceededIter_ = 0;
1380 std::size_t numConverged_ = 0;
1381 std::size_t numLinearSolverBreakdowns_ = 0;
1384 std::unique_ptr<PrimaryVariableSwitchAdapter> priVarSwitchAdapter_;
1387 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.
Backends for operations on different solution vector types or more generic variable classes to be use...
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 class that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix.
An adapter for the Newton to manage models with primary variable switch.
@ 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
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
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:110
typename Assembler::GridVariables AssemblerGridVariablesType
Definition: nonlinear/newtonsolver.hh:65
decltype(std::declval< LinearSolver >().norm(std::declval< Residual >())) NormDetector
Definition: nonlinear/newtonsolver.hh:97
decltype(std::declval< C >()[0]) dynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:104
void assign(To &to, const From &from)
Definition: nonlinear/newtonsolver.hh:151
static constexpr auto hasDynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:106
static constexpr auto hasStaticIndexAccess
Definition: nonlinear/newtonsolver.hh:107
static constexpr bool hasNorm()
Definition: nonlinear/newtonsolver.hh:100
constexpr std::size_t blockSize()
Definition: nonlinear/newtonsolver.hh:185
decltype(std::declval< C >()[Dune::Indices::_0]) staticIndexAccess
Definition: nonlinear/newtonsolver.hh:105
typename BlockTypeHelper< SolutionVector, Dune::IsNumber< SolutionVector >::value >::type BlockType
Definition: nonlinear/newtonsolver.hh:198
constexpr bool assemblerExportsGridVariables
Definition: nonlinear/newtonsolver.hh:68
auto maxRelativeShift(const V &v1, const V &v2) -> std::enable_if_t< Dune::IsNumber< V >::value, Scalar >
Definition: nonlinear/newtonsolver.hh:131
typename PriVarSwitchVariablesType< Assembler, assemblerExportsGridVariables< Assembler > >::Type PriVarSwitchVariables
Definition: nonlinear/newtonsolver.hh:83
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:432
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:39
A high-level interface for a PDESolver.
Definition: common/pdesolver.hh:72
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
Manages the handling of time dependent problems.
Definition: common/timeloop.hh:68
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 .
Definition: variablesbackend.hh:43
Definition: variablesbackend.hh:159
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)
Copies 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
Base class for linear solvers.
Definition: solver.hh:37
Definition: nonlinear/newtonconvergencewriter.hh:39
Definition: nonlinear/newtonsolver.hh:72
typename Assembler::GridVariables Type
Definition: nonlinear/newtonsolver.hh:72
EmptyGridVariables {} Type
Definition: nonlinear/newtonsolver.hh:78
helper struct detecting if an assembler supports partial reassembly
Definition: nonlinear/newtonsolver.hh:87
auto operator()(Assembler &&a) -> decltype(a.assembleJacobianAndResidual(std::declval< const typename Assembler::ResidualType & >(), std::declval< const PartialReassembler< Assembler > * >()))
Definition: nonlinear/newtonsolver.hh:89
Definition: nonlinear/newtonsolver.hh:192
std::decay_t< decltype(std::declval< S >()[0])> type
Definition: nonlinear/newtonsolver.hh:192
S type
Definition: nonlinear/newtonsolver.hh:195
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:216
Comm Communication
Definition: nonlinear/newtonsolver.hh:240
virtual void newtonFail(Variables &u)
Called if the Newton method broke down. This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:735
int maxSteps_
maximum number of iterations we do before giving up
Definition: nonlinear/newtonsolver.hh:915
void setMaxSteps(int maxSteps)
Set the number of iterations after which the Newton method gives up.
Definition: nonlinear/newtonsolver.hh:329
void newtonUpdate(Variables &vars, const SolutionVector &uLastIter, const SolutionVector &deltaU)
Update the current solution with a delta vector.
Definition: nonlinear/newtonsolver.hh:573
void setResidualReduction(Scalar tolerance)
Set the maximum acceptable residual norm reduction.
Definition: nonlinear/newtonsolver.hh:298
void reportParams(std::ostream &sout=std::cout) const
Report the options and parameters this Newton is configured with.
Definition: nonlinear/newtonsolver.hh:773
int targetSteps_
optimal number of iterations we want to achieve
Definition: nonlinear/newtonsolver.hh:911
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:841
void setRetryTimeStepReductionFactor(const Scalar factor)
Set the factor for reducing the time step after a Newton iteration has failed.
Definition: nonlinear/newtonsolver.hh:865
Scalar reduction_
Definition: nonlinear/newtonsolver.hh:920
Scalar retryTimeStepReductionFactor() const
Return the factor for reducing the time step after a Newton iteration has failed.
Definition: nonlinear/newtonsolver.hh:859
int numSteps_
actual number of steps done so far
Definition: nonlinear/newtonsolver.hh:917
int verbosity() const
Return the verbosity level.
Definition: nonlinear/newtonsolver.hh:835
void setMinSteps(int minSteps)
Set the number of minimum iterations for the Newton method.
Definition: nonlinear/newtonsolver.hh:320
int minSteps_
minimum number of iterations we do
Definition: nonlinear/newtonsolver.hh:913
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 assembleLinearSystem(const Variables &vars)
Assemble the linear system of equations .
Definition: nonlinear/newtonsolver.hh:485
bool enableResidualCriterion() const
Definition: nonlinear/newtonsolver.hh:907
virtual bool newtonProceed(const Variables &varsCurrentIter, bool converged)
Returns true if another iteration should be done.
Definition: nonlinear/newtonsolver.hh:444
void solve(Variables &vars, 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:339
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
void report(std::ostream &sout=std::cout) const
output statistics / report
Definition: nonlinear/newtonsolver.hh:746
void solve(Variables &vars) override
Run the Newton method to solve a non-linear system. The solver is responsible for all the strategic d...
Definition: nonlinear/newtonsolver.hh:393
virtual void newtonSucceed()
Called if the Newton method ended successfully This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:741
void attachConvergenceWriter(std::shared_ptr< ConvergenceWriter > convWriter)
Attach a convergence writer to write out intermediate results after each iteration.
Definition: nonlinear/newtonsolver.hh:847
Scalar initialResidual_
Definition: nonlinear/newtonsolver.hh:923
Scalar lastReduction_
Definition: nonlinear/newtonsolver.hh:922
virtual void newtonBeginStep(const Variables &vars)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:467
std::ostringstream endIterMsgStream_
message stream to be displayed at the end of iterations
Definition: nonlinear/newtonsolver.hh:930
void setVerbosity(int val)
Specifies the verbosity level.
Definition: nonlinear/newtonsolver.hh:829
typename Backend::DofVector SolutionVector
Definition: nonlinear/newtonsolver.hh:221
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:270
void resetReport()
reset the statistics
Definition: nonlinear/newtonsolver.hh:762
NewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCommunication(), const std::string ¶mGroup="")
The Constructor.
Definition: nonlinear/newtonsolver.hh:245
void setMaxAbsoluteResidual(Scalar tolerance)
Set the maximum acceptable absolute residual for declaring convergence.
Definition: nonlinear/newtonsolver.hh:289
virtual void newtonEnd()
Called if the Newton method ended (not known yet if we failed or succeeded)
Definition: nonlinear/newtonsolver.hh:679
void setTargetSteps(int targetSteps)
Set the number of iterations at which the Newton method should aim at.
Definition: nonlinear/newtonsolver.hh:311
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:685
Scalar suggestTimeStepSize(Scalar oldTimeStep) const
Suggest a new time-step size based on the old time-step size.
Definition: nonlinear/newtonsolver.hh:810
void solveLinearSystem(SolutionVector &deltaU)
Solve the linear system of equations .
Definition: nonlinear/newtonsolver.hh:504
void detachConvergenceWriter()
Detach the convergence writer to stop the output.
Definition: nonlinear/newtonsolver.hh:853
void setMaxRelativeShift(Scalar tolerance)
Set the maximum acceptable difference of any primary variable between two iterations for declaring co...
Definition: nonlinear/newtonsolver.hh:280
Scalar shift_
Definition: nonlinear/newtonsolver.hh:926
void computeResidualReduction_(const Variables &vars)
Definition: nonlinear/newtonsolver.hh:883
Scalar residualNorm_
Definition: nonlinear/newtonsolver.hh:921
Scalar lastShift_
Definition: nonlinear/newtonsolver.hh:927
An adapter for the Newton to manage models with primary variable switch.
Definition: primaryvariableswitchadapter.hh:59
Defines a high-level interface for a PDESolver.
Manages the handling of time dependent problems.
This class provides the infrastructure to write the convergence behaviour of the newton method into a...