version 3.7
nonlinear/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//
12#ifndef DUMUX_NEWTON_SOLVER_HH
13#define DUMUX_NEWTON_SOLVER_HH
14
15#include <cmath>
16#include <memory>
17#include <iostream>
18#include <type_traits>
19#include <algorithm>
20#include <numeric>
21
22#include <dune/common/timer.hh>
23#include <dune/common/exceptions.hh>
24#include <dune/common/parallel/mpicommunication.hh>
25#include <dune/common/parallel/mpihelper.hh>
26#include <dune/common/std/type_traits.hh>
27#include <dune/common/indices.hh>
28#include <dune/common/hybridutilities.hh>
29
30#include <dune/istl/bvector.hh>
31#include <dune/istl/multitypeblockvector.hh>
32
40
41#include <dumux/io/format.hh>
42
43// remove after deprecated code is removed (after 3.7)
44#define DUMUX_SUPPRESS_LINEAR_SOLVER_ACCEPTS_MULTITYPEMATRIX_WARNING
46#undef DUMUX_SUPPRESS_LINEAR_SOLVER_ACCEPTS_MULTITYPEMATRIX_WARNING
47
50
53
55
56// Helper boolean that states if the assembler exports grid variables
57template<class Assembler> using AssemblerGridVariablesType = typename Assembler::GridVariables;
58template<class Assembler>
59inline constexpr bool assemblerExportsGridVariables
60 = Dune::Std::is_detected_v<AssemblerGridVariablesType, Assembler>;
61
62// helper struct to define the variables on which the privarswitch should operate
63template<class Assembler, bool exportsGridVars = assemblerExportsGridVariables<Assembler>>
64struct PriVarSwitchVariablesType { using Type = typename Assembler::GridVariables; };
65
66// if assembler does not export them, use an empty class. These situations either mean
67// that there is no privarswitch, or, it is handled by a derived implementation.
68template<class Assembler>
69struct PriVarSwitchVariablesType<Assembler, false>
70{ using Type = struct EmptyGridVariables {}; };
71
72// Helper alias to deduce the variables types used in the privarswitch adapter
73template<class Assembler>
76
79{
80 template<class Assembler>
81 auto operator()(Assembler&& a)
82 -> decltype(a.assembleJacobianAndResidual(std::declval<const typename Assembler::SolutionVector&>(),
83 std::declval<const PartialReassembler<Assembler>*>()))
84 {}
85};
86
87// helper struct and function detecting if the linear solver features a norm() function
88template <class LinearSolver, class Residual>
89using NormDetector = decltype(std::declval<LinearSolver>().norm(std::declval<Residual>()));
90
91template<class LinearSolver, class Residual>
92static constexpr bool hasNorm()
93{ return Dune::Std::is_detected<NormDetector, LinearSolver, Residual>::value; }
94
95// helpers to implement max relative shift
96template<class C> using dynamicIndexAccess = decltype(std::declval<C>()[0]);
97template<class C> using staticIndexAccess = decltype(std::declval<C>()[Dune::Indices::_0]);
98template<class C> static constexpr auto hasDynamicIndexAccess = Dune::Std::is_detected<dynamicIndexAccess, C>{};
99template<class C> static constexpr auto hasStaticIndexAccess = Dune::Std::is_detected<staticIndexAccess, C>{};
100
101template<class V, class Scalar, class Reduce, class Transform>
102auto hybridInnerProduct(const V& v1, const V& v2, Scalar init, Reduce&& r, Transform&& t)
103-> std::enable_if_t<hasDynamicIndexAccess<V>(), Scalar>
104{
105 return std::inner_product(v1.begin(), v1.end(), v2.begin(), init, std::forward<Reduce>(r), std::forward<Transform>(t));
106}
107
108template<class V, class Scalar, class Reduce, class Transform>
109auto hybridInnerProduct(const V& v1, const V& v2, Scalar init, Reduce&& r, Transform&& t)
110-> std::enable_if_t<hasStaticIndexAccess<V>() && !hasDynamicIndexAccess<V>(), Scalar>
111{
112 using namespace Dune::Hybrid;
113 forEach(std::make_index_sequence<V::N()>{}, [&](auto i){
114 init = r(init, hybridInnerProduct(v1[Dune::index_constant<i>{}], v2[Dune::index_constant<i>{}], init, std::forward<Reduce>(r), std::forward<Transform>(t)));
115 });
116 return init;
117}
118
119// Maximum relative shift at a degree of freedom.
120// For (primary variables) values below 1.0 we use
121// an absolute shift.
122template<class Scalar, class V>
123auto maxRelativeShift(const V& v1, const V& v2)
124-> std::enable_if_t<Dune::IsNumber<V>::value, Scalar>
125{
126 using std::abs; using std::max;
127 return abs(v1 - v2)/max<Scalar>(1.0, abs(v1 + v2)*0.5);
128}
129
130// Maximum relative shift for generic vector types.
131// Recursively calls maxRelativeShift until Dune::IsNumber is true.
132template<class Scalar, class V>
133auto maxRelativeShift(const V& v1, const V& v2)
134-> std::enable_if_t<!Dune::IsNumber<V>::value, Scalar>
135{
136 return hybridInnerProduct(v1, v2, Scalar(0.0),
137 [](const auto& a, const auto& b){ using std::max; return max(a, b); },
138 [](const auto& a, const auto& b){ return maxRelativeShift<Scalar>(a, b); }
139 );
140}
141
142template<class To, class From>
143void assign(To& to, const From& from)
144{
145 if constexpr (hasStaticIndexAccess<To>() && hasStaticIndexAccess<To>() && !hasDynamicIndexAccess<From>() && !hasDynamicIndexAccess<From>())
146 {
147 using namespace Dune::Hybrid;
148 forEach(std::make_index_sequence<To::N()>{}, [&](auto i){
149 assign(to[Dune::index_constant<i>{}], from[Dune::index_constant<i>{}]);
150 });
151 }
152
153 else if constexpr (std::is_assignable<To&, From>::value)
154 to = from;
155
156 else if constexpr (hasDynamicIndexAccess<To>() && hasDynamicIndexAccess<From>())
157 for (decltype(to.size()) i = 0; i < to.size(); ++i)
158 assign(to[i], from[i]);
159
160 else if constexpr (hasDynamicIndexAccess<To>() && Dune::IsNumber<From>::value)
161 {
162 assert(to.size() == 1);
163 assign(to[0], from);
164 }
165
166 else if constexpr (Dune::IsNumber<To>::value && hasDynamicIndexAccess<From>())
167 {
168 assert(from.size() == 1);
169 assign(to, from[0]);
170 }
171
172 else
173 DUNE_THROW(Dune::Exception, "Values are not assignable to each other!");
174}
175
176template<class Residual, class LinearSolver, class Assembler>
177typename Assembler::Scalar residualNorm(Residual& residual, const LinearSolver& linearSolver, const Assembler& assembler)
178{
179 if constexpr (Detail::Newton::hasNorm<LinearSolver, Residual>())
180 return linearSolver.norm(residual);
181 else // fallback to deprecated interface
182 return assembler.normOfResidual(residual);
183}
184
185} // end namespace Dumux::Detail::Newton
186
187namespace Dumux {
188
199template <class Assembler, class LinearSolver,
200 class Reassembler = PartialReassembler<Assembler>,
201 class Comm = Dune::Communication<Dune::MPIHelper::MPICommunicator> >
202class NewtonSolver : public PDESolver<Assembler, LinearSolver>
203{
205
206protected:
208 using SolutionVector = typename Backend::DofVector;
209 using ResidualVector = typename Assembler::ResidualType;
211private:
212 using Scalar = typename Assembler::Scalar;
213 using JacobianMatrix = typename Assembler::JacobianMatrix;
216
217 // enable models with primary variable switch
218 // TODO: Always use ParentType::Variables once we require assemblers to export variables
219 static constexpr bool assemblerExportsVariables = Detail::PDESolver::assemblerExportsVariables<Assembler>;
220 using PriVarSwitchVariables
221 = std::conditional_t<assemblerExportsVariables,
222 typename ParentType::Variables,
225
226public:
227 using typename ParentType::Variables;
228 using Communication = Comm;
229
233 NewtonSolver(std::shared_ptr<Assembler> assembler,
234 std::shared_ptr<LinearSolver> linearSolver,
235 const Communication& comm = Dune::MPIHelper::getCommunication(),
236 const std::string& paramGroup = "")
238 , endIterMsgStream_(std::ostringstream::out)
239 , comm_(comm)
240 , paramGroup_(paramGroup)
241 , priVarSwitchAdapter_(std::make_unique<PrimaryVariableSwitchAdapter>(paramGroup))
242 {
243 initParams_(paramGroup);
244
245 // set the linear system (matrix & residual) in the assembler
246 this->assembler().setLinearSystem();
247
248 // set a different default for the linear solver residual reduction
249 // within the Newton the linear solver doesn't need to solve too exact
250 this->linearSolver().setResidualReduction(getParamFromGroup<Scalar>(paramGroup, "LinearSolver.ResidualReduction", 1e-6));
251
252 // initialize the partial reassembler
253 if (enablePartialReassembly_)
254 partialReassembler_ = std::make_unique<Reassembler>(this->assembler());
255 }
256
258 const Communication& comm() const
259 { return comm_; }
260
268 void setMaxRelativeShift(Scalar tolerance)
269 { shiftTolerance_ = tolerance; }
270
277 void setMaxAbsoluteResidual(Scalar tolerance)
278 { residualTolerance_ = tolerance; }
279
286 void setResidualReduction(Scalar tolerance)
287 { reductionTolerance_ = tolerance; }
288
299 void setTargetSteps(int targetSteps)
300 { targetSteps_ = targetSteps; }
301
308 void setMinSteps(int minSteps)
309 { minSteps_ = minSteps; }
310
317 void setMaxSteps(int maxSteps)
318 { maxSteps_ = maxSteps; }
319
327 void solve(Variables& vars, TimeLoop& timeLoop) override
328 {
329 if constexpr (!assemblerExportsVariables)
330 {
331 if (this->assembler().isStationaryProblem())
332 DUNE_THROW(Dune::InvalidStateException, "Using time step control with stationary problem makes no sense!");
333 }
334
335 // try solving the non-linear system
336 for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
337 {
338 // linearize & solve
339 const bool converged = solve_(vars);
340
341 if (converged)
342 return;
343
344 else if (!converged && i < maxTimeStepDivisions_)
345 {
346 if constexpr (assemblerExportsVariables)
347 DUNE_THROW(Dune::NotImplemented, "Time step reset for new assembly methods");
348 else
349 {
350 // set solution to previous solution & reset time step
351 Backend::update(vars, this->assembler().prevSol());
352 this->assembler().resetTimeStep(Backend::dofs(vars));
353
354 if (verbosity_ >= 1)
355 {
356 const auto dt = timeLoop.timeStepSize();
357 std::cout << Fmt::format("Newton solver did not converge with dt = {} seconds. ", dt)
358 << Fmt::format("Retrying with time step of dt = {} seconds.\n", dt*retryTimeStepReductionFactor_);
359 }
360
361 // try again with dt = dt * retryTimeStepReductionFactor_
362 timeLoop.setTimeStepSize(timeLoop.timeStepSize() * retryTimeStepReductionFactor_);
363 }
364 }
365
366 else
367 {
368 DUNE_THROW(NumericalProblem,
369 Fmt::format("Newton solver didn't converge after {} time-step divisions; dt = {}.\n",
370 maxTimeStepDivisions_, timeLoop.timeStepSize()));
371 }
372 }
373 }
374
381 void solve(Variables& vars) override
382 {
383 const bool converged = solve_(vars);
384 if (!converged)
385 DUNE_THROW(NumericalProblem,
386 Fmt::format("Newton solver didn't converge after {} iterations.\n", numSteps_));
387 }
388
395 virtual void newtonBegin(Variables& initVars)
396 {
397 numSteps_ = 0;
398
399 if constexpr (hasPriVarsSwitch<PriVarSwitchVariables>)
400 {
401 if constexpr (assemblerExportsVariables)
402 priVarSwitchAdapter_->initialize(Backend::dofs(initVars), initVars);
403 else // this assumes assembly with solution (i.e. Variables=SolutionVector)
404 priVarSwitchAdapter_->initialize(initVars, this->assembler().gridVariables());
405 }
406
407
408 const auto& initSol = Backend::dofs(initVars);
409
410 // write the initial residual if a convergence writer was set
411 if (convergenceWriter_)
412 {
413 this->assembler().assembleResidual(initVars);
414
415 // dummy vector, there is no delta before solving the linear system
416 ResidualVector delta = LinearAlgebraNativeBackend::zeros(Backend::size(initSol));
417 convergenceWriter_->write(initSol, delta, this->assembler().residual());
418 }
419
420 if (enablePartialReassembly_)
421 {
422 partialReassembler_->resetColors();
423 resizeDistanceFromLastLinearization_(initSol, distanceFromLastLinearization_);
424 }
425 }
426
433 virtual bool newtonProceed(const Variables &varsCurrentIter, bool converged)
434 {
435 if (numSteps_ < minSteps_)
436 return true;
437 else if (converged)
438 return false; // we are below the desired tolerance
439 else if (numSteps_ >= maxSteps_)
440 {
441 // We have exceeded the allowed number of steps. If the
442 // maximum relative shift was reduced by a factor of at least 4,
443 // we proceed even if we are above the maximum number of steps.
444 if (enableShiftCriterion_)
445 return shift_*4.0 < lastShift_;
446 else
447 return reduction_*4.0 < lastReduction_;
448 }
449
450 return true;
451 }
452
456 virtual void newtonBeginStep(const Variables& vars)
457 {
459 if (numSteps_ == 0)
460 {
461 lastReduction_ = 1.0;
462 }
463 else
464 {
466 }
467 }
468
474 virtual void assembleLinearSystem(const Variables& vars)
475 {
476 assembleLinearSystem_(this->assembler(), vars);
477
478 if (enablePartialReassembly_)
479 partialReassembler_->report(comm_, endIterMsgStream_);
480 }
481
494 {
495 bool converged = false;
496
497 try
498 {
499 if (numSteps_ == 0)
501 this->assembler().residual(), this->linearSolver(), this->assembler()
502 );
503
504 // solve by calling the appropriate implementation depending on whether the linear solver
505 // is capable of handling MultiType matrices or not
506 converged = solveLinearSystem_(deltaU);
507 }
508 catch (const Dune::Exception &e)
509 {
510 if (verbosity_ >= 1)
511 std::cout << "Newton: Caught exception from the linear solver: \"" << e.what() << "\"\n";
512
513 converged = false;
514 }
515
516 // make sure all processes converged
517 int convergedRemote = converged;
518 if (comm_.size() > 1)
519 convergedRemote = comm_.min(converged);
520
521 if (!converged)
522 {
523 DUNE_THROW(NumericalProblem, "Linear solver did not converge");
524 ++numLinearSolverBreakdowns_;
525 }
526 else if (!convergedRemote)
527 {
528 DUNE_THROW(NumericalProblem, "Linear solver did not converge on a remote process");
529 ++numLinearSolverBreakdowns_; // we keep correct count for process 0
530 }
531 }
532
551 const SolutionVector& uLastIter,
552 const ResidualVector& deltaU)
553 {
554 if (enableShiftCriterion_ || enablePartialReassembly_)
555 newtonUpdateShift_(uLastIter, deltaU);
556
557 if (enablePartialReassembly_) {
558 // Determine the threshold 'eps' that is used for the partial reassembly.
559 // Every entity where the primary variables exhibit a relative shift
560 // summed up since the last linearization above 'eps' will be colored
561 // red yielding a reassembly.
562 // The user can provide three parameters to influence the threshold:
563 // 'minEps' by 'Newton.ReassemblyMinThreshold' (1e-1*shiftTolerance_ default)
564 // 'maxEps' by 'Newton.ReassemblyMaxThreshold' (1e2*shiftTolerance_ default)
565 // 'omega' by 'Newton.ReassemblyShiftWeight' (1e-3 default)
566 // The threshold is calculated from the currently achieved maximum
567 // relative shift according to the formula
568 // eps = max( minEps, min(maxEps, omega*shift) ).
569 // Increasing/decreasing 'minEps' leads to less/more reassembly if
570 // 'omega*shift' is small, i.e., for the last Newton iterations.
571 // Increasing/decreasing 'maxEps' leads to less/more reassembly if
572 // 'omega*shift' is large, i.e., for the first Newton iterations.
573 // Increasing/decreasing 'omega' leads to more/less first and last
574 // iterations in this sense.
575 using std::max;
576 using std::min;
577 auto reassemblyThreshold = max(reassemblyMinThreshold_,
578 min(reassemblyMaxThreshold_,
579 shift_*reassemblyShiftWeight_));
580
581 updateDistanceFromLastLinearization_(uLastIter, deltaU);
582 partialReassembler_->computeColors(this->assembler(),
583 distanceFromLastLinearization_,
584 reassemblyThreshold);
585
586 // set the discrepancy of the red entities to zero
587 for (unsigned int i = 0; i < distanceFromLastLinearization_.size(); i++)
588 if (partialReassembler_->dofColor(i) == EntityColor::red)
589 distanceFromLastLinearization_[i] = 0;
590 }
591
592 if (useLineSearch_)
593 lineSearchUpdate_(vars, uLastIter, deltaU);
594
595 else if (useChop_)
596 choppedUpdate_(vars, uLastIter, deltaU);
597
598 else
599 {
600 auto uCurrentIter = uLastIter;
601 Backend::axpy(-1.0, deltaU, uCurrentIter);
602 solutionChanged_(vars, uCurrentIter);
603
604 if (enableResidualCriterion_)
606 }
607 }
608
615 virtual void newtonEndStep(Variables &vars,
616 const SolutionVector &uLastIter)
617 {
618 if constexpr (hasPriVarsSwitch<PriVarSwitchVariables>)
619 {
620 if constexpr (assemblerExportsVariables)
621 priVarSwitchAdapter_->invoke(Backend::dofs(vars), vars);
622 else // this assumes assembly with solution (i.e. Variables=SolutionVector)
623 priVarSwitchAdapter_->invoke(vars, this->assembler().gridVariables());
624 }
625
626 ++numSteps_;
627
628 if (verbosity_ >= 1)
629 {
630 if (enableDynamicOutput_)
631 std::cout << '\r'; // move cursor to beginning of line
632
633 const auto width = Fmt::formatted_size("{}", maxSteps_);
634 std::cout << Fmt::format("Newton iteration {:{}} done", numSteps_, width);
635
636 if (enableShiftCriterion_)
637 std::cout << Fmt::format(", maximum relative shift = {:.4e}", shift_);
638 if (enableResidualCriterion_ && enableAbsoluteResidualCriterion_)
639 std::cout << Fmt::format(", residual = {:.4e}", residualNorm_);
640 else if (enableResidualCriterion_)
641 std::cout << Fmt::format(", residual reduction = {:.4e}", reduction_);
642
643 std::cout << endIterMsgStream_.str() << "\n";
644 }
645 endIterMsgStream_.str("");
646
647 // When the Newton iterations are done: ask the model to check whether it makes sense
648 // TODO: how do we realize this? -> do this here in the Newton solver
649 // model_().checkPlausibility();
650 }
651
656 virtual void newtonEnd() {}
657
662 virtual bool newtonConverged() const
663 {
664 // in case the model has a priVar switch and some some primary variables
665 // actually switched their state in the last iteration, enforce another iteration
666 if (priVarSwitchAdapter_->switched())
667 return false;
668
669 if (enableShiftCriterion_ && !enableResidualCriterion_)
670 {
671 return shift_ <= shiftTolerance_;
672 }
673 else if (!enableShiftCriterion_ && enableResidualCriterion_)
674 {
675 if(enableAbsoluteResidualCriterion_)
676 return residualNorm_ <= residualTolerance_;
677 else
678 return reduction_ <= reductionTolerance_;
679 }
680 else if (satisfyResidualAndShiftCriterion_)
681 {
682 if(enableAbsoluteResidualCriterion_)
683 return shift_ <= shiftTolerance_
684 && residualNorm_ <= residualTolerance_;
685 else
686 return shift_ <= shiftTolerance_
687 && reduction_ <= reductionTolerance_;
688 }
689 else if(enableShiftCriterion_ && enableResidualCriterion_)
690 {
691 if(enableAbsoluteResidualCriterion_)
692 return shift_ <= shiftTolerance_
693 || residualNorm_ <= residualTolerance_;
694 else
695 return shift_ <= shiftTolerance_
696 || reduction_ <= reductionTolerance_;
697 }
698 else
699 {
700 return shift_ <= shiftTolerance_
701 || reduction_ <= reductionTolerance_
702 || residualNorm_ <= residualTolerance_;
703 }
704
705 return false;
706 }
707
712 virtual void newtonFail(Variables& u) {}
713
718 virtual void newtonSucceed() {}
719
723 void report(std::ostream& sout = std::cout) const
724 {
725 sout << '\n'
726 << "Newton statistics\n"
727 << "----------------------------------------------\n"
728 << "-- Total Newton iterations: " << totalWastedIter_ + totalSucceededIter_ << '\n'
729 << "-- Total wasted Newton iterations: " << totalWastedIter_ << '\n'
730 << "-- Total succeeded Newton iterations: " << totalSucceededIter_ << '\n'
731 << "-- Average iterations per solve: " << std::setprecision(3) << double(totalSucceededIter_) / double(numConverged_) << '\n'
732 << "-- Number of linear solver breakdowns: " << numLinearSolverBreakdowns_ << '\n'
733 << std::endl;
734 }
735
740 {
741 totalWastedIter_ = 0;
742 totalSucceededIter_ = 0;
743 numConverged_ = 0;
744 numLinearSolverBreakdowns_ = 0;
745 }
746
750 void reportParams(std::ostream& sout = std::cout) const
751 {
752 sout << "\nNewton solver configured with the following options and parameters:\n";
753 // options
754 if (useLineSearch_) sout << " -- Newton.UseLineSearch = true\n";
755 if (useChop_) sout << " -- Newton.EnableChop = true\n";
756 if (enablePartialReassembly_) sout << " -- Newton.EnablePartialReassembly = true\n";
757 if (enableAbsoluteResidualCriterion_) sout << " -- Newton.EnableAbsoluteResidualCriterion = true\n";
758 if (enableShiftCriterion_) sout << " -- Newton.EnableShiftCriterion = true (relative shift convergence criterion)\n";
759 if (enableResidualCriterion_) sout << " -- Newton.EnableResidualCriterion = true\n";
760 if (satisfyResidualAndShiftCriterion_) sout << " -- Newton.SatisfyResidualAndShiftCriterion = true\n";
761 // parameters
762 if (enableShiftCriterion_) sout << " -- Newton.MaxRelativeShift = " << shiftTolerance_ << '\n';
763 if (enableAbsoluteResidualCriterion_) sout << " -- Newton.MaxAbsoluteResidual = " << residualTolerance_ << '\n';
764 if (enableResidualCriterion_) sout << " -- Newton.ResidualReduction = " << reductionTolerance_ << '\n';
765 sout << " -- Newton.MinSteps = " << minSteps_ << '\n';
766 sout << " -- Newton.MaxSteps = " << maxSteps_ << '\n';
767 sout << " -- Newton.TargetSteps = " << targetSteps_ << '\n';
768 if (enablePartialReassembly_)
769 {
770 sout << " -- Newton.ReassemblyMinThreshold = " << reassemblyMinThreshold_ << '\n';
771 sout << " -- Newton.ReassemblyMaxThreshold = " << reassemblyMaxThreshold_ << '\n';
772 sout << " -- Newton.ReassemblyShiftWeight = " << reassemblyShiftWeight_ << '\n';
773 }
774 sout << " -- Newton.RetryTimeStepReductionFactor = " << retryTimeStepReductionFactor_ << '\n';
775 sout << " -- Newton.MaxTimeStepDivisions = " << maxTimeStepDivisions_ << '\n';
776 sout << std::endl;
777 }
778
787 Scalar suggestTimeStepSize(Scalar oldTimeStep) const
788 {
789 // be aggressive reducing the time-step size but
790 // conservative when increasing it. the rationale is
791 // that we want to avoid failing in the next Newton
792 // iteration which would require another linearization
793 // of the problem.
794 if (numSteps_ > targetSteps_) {
795 Scalar percent = Scalar(numSteps_ - targetSteps_)/targetSteps_;
796 return oldTimeStep/(1.0 + percent);
797 }
798
799 Scalar percent = Scalar(targetSteps_ - numSteps_)/targetSteps_;
800 return oldTimeStep*(1.0 + percent/1.2);
801 }
802
806 void setVerbosity(int val)
807 { verbosity_ = val; }
808
812 int verbosity() const
813 { return verbosity_ ; }
814
818 const std::string& paramGroup() const
819 { return paramGroup_; }
820
824 void attachConvergenceWriter(std::shared_ptr<ConvergenceWriter> convWriter)
825 { convergenceWriter_ = convWriter; }
826
831 { convergenceWriter_ = nullptr; }
832
837 { return retryTimeStepReductionFactor_; }
838
842 void setRetryTimeStepReductionFactor(const Scalar factor)
843 { retryTimeStepReductionFactor_ = factor; }
844
845protected:
846
852 virtual void solutionChanged_(Variables& vars, const SolutionVector& uCurrentIter)
853 {
854 Backend::update(vars, uCurrentIter);
855
856 if constexpr (!assemblerExportsVariables)
857 this->assembler().updateGridVariables(Backend::dofs(vars));
858 }
859
861 {
862 // we assume that the assembler works on solution vectors
863 // if it doesn't export the variables type
864 if constexpr (!assemblerExportsVariables)
865 this->assembler().assembleResidual(Backend::dofs(vars));
866 else
867 this->assembler().assembleResidual(vars);
868
870 this->assembler().residual(), this->linearSolver(), this->assembler()
871 );
872
874 }
875
877 { return enableResidualCriterion_; }
878
887
888 // residual criterion variables
893
894 // shift criterion variables
895 Scalar shift_;
897
899 std::ostringstream endIterMsgStream_;
900
901
902private:
903
908 bool solve_(Variables& vars)
909 {
910 try
911 {
912 // newtonBegin may manipulate the solution
913 newtonBegin(vars);
914
915 // the given solution is the initial guess
916 auto uLastIter = Backend::dofs(vars);
917 ResidualVector deltaU = LinearAlgebraNativeBackend::zeros(Backend::size(Backend::dofs(vars)));
918 Detail::Newton::assign(deltaU, Backend::dofs(vars));
919
920 // setup timers
921 Dune::Timer assembleTimer(false);
922 Dune::Timer solveTimer(false);
923 Dune::Timer updateTimer(false);
924
925 // execute the method as long as the solver thinks
926 // that we should do another iteration
927 bool converged = false;
928 while (newtonProceed(vars, converged))
929 {
930 // notify the solver that we're about to start
931 // a new iteration
932 newtonBeginStep(vars);
933
934 // make the current solution to the old one
935 if (numSteps_ > 0)
936 uLastIter = Backend::dofs(vars);
937
938 if (verbosity_ >= 1 && enableDynamicOutput_)
939 std::cout << "Assemble: r(x^k) = dS/dt + div F - q; M = grad r"
940 << std::flush;
941
943 // assemble
945
946 // linearize the problem at the current solution
947 assembleTimer.start();
949 assembleTimer.stop();
950
952 // linear solve
954
955 // Clear the current line using an ansi escape
956 // sequence. for an explanation see
957 // http://en.wikipedia.org/wiki/ANSI_escape_code
958 const char clearRemainingLine[] = { 0x1b, '[', 'K', 0 };
959
960 if (verbosity_ >= 1 && enableDynamicOutput_)
961 std::cout << "\rSolve: M deltax^k = r"
962 << clearRemainingLine << std::flush;
963
964 // solve the resulting linear equation system
965 solveTimer.start();
966
967 // set the delta vector to zero before solving the linear system!
968 deltaU = 0;
969
970 solveLinearSystem(deltaU);
971 solveTimer.stop();
972
974 // update
976 if (verbosity_ >= 1 && enableDynamicOutput_)
977 std::cout << "\rUpdate: x^(k+1) = x^k - deltax^k"
978 << clearRemainingLine << std::flush;
979
980 updateTimer.start();
981 // update the current solution (i.e. uOld) with the delta
982 // (i.e. u). The result is stored in u
983 newtonUpdate(vars, uLastIter, deltaU);
984 updateTimer.stop();
985
986 // tell the solver that we're done with this iteration
987 newtonEndStep(vars, uLastIter);
988
989 // if a convergence writer was specified compute residual and write output
990 if (convergenceWriter_)
991 {
992 this->assembler().assembleResidual(vars);
993 convergenceWriter_->write(Backend::dofs(vars), deltaU, this->assembler().residual());
994 }
995
996 // detect if the method has converged
997 converged = newtonConverged();
998 }
999
1000 // tell solver we are done
1001 newtonEnd();
1002
1003 // reset state if Newton failed
1004 if (!newtonConverged())
1005 {
1006 totalWastedIter_ += numSteps_;
1007 newtonFail(vars);
1008 return false;
1009 }
1010
1011 totalSucceededIter_ += numSteps_;
1012 numConverged_++;
1013
1014 // tell solver we converged successfully
1015 newtonSucceed();
1016
1017 if (verbosity_ >= 1) {
1018 const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
1019 std::cout << Fmt::format("Assemble/solve/update time: {:.2g}({:.2f}%)/{:.2g}({:.2f}%)/{:.2g}({:.2f}%)\n",
1020 assembleTimer.elapsed(), 100*assembleTimer.elapsed()/elapsedTot,
1021 solveTimer.elapsed(), 100*solveTimer.elapsed()/elapsedTot,
1022 updateTimer.elapsed(), 100*updateTimer.elapsed()/elapsedTot);
1023 }
1024 return true;
1025
1026 }
1027 catch (const NumericalProblem &e)
1028 {
1029 if (verbosity_ >= 1)
1030 std::cout << "Newton: Caught exception: \"" << e.what() << "\"\n";
1031
1032 totalWastedIter_ += numSteps_;
1033
1034 newtonFail(vars);
1035 return false;
1036 }
1037 }
1038
1040 template<class A>
1041 auto assembleLinearSystem_(const A& assembler, const Variables& vars)
1042 -> typename std::enable_if_t<decltype(isValid(Detail::Newton::supportsPartialReassembly())(assembler))::value, void>
1043 {
1044 this->assembler().assembleJacobianAndResidual(vars, partialReassembler_.get());
1045 }
1046
1048 template<class A>
1049 auto assembleLinearSystem_(const A& assembler, const Variables& vars)
1050 -> typename std::enable_if_t<!decltype(isValid(Detail::Newton::supportsPartialReassembly())(assembler))::value, void>
1051 {
1052 this->assembler().assembleJacobianAndResidual(vars);
1053 }
1054
1062 virtual void newtonUpdateShift_(const SolutionVector &uLastIter,
1063 const ResidualVector &deltaU)
1064 {
1065 auto uNew = uLastIter;
1066 Backend::axpy(-1.0, deltaU, uNew);
1067 shift_ = Detail::Newton::maxRelativeShift<Scalar>(uLastIter, uNew);
1068
1069 if (comm_.size() > 1)
1070 shift_ = comm_.max(shift_);
1071 }
1072
1073 virtual void lineSearchUpdate_(Variables &vars,
1074 const SolutionVector &uLastIter,
1075 const ResidualVector &deltaU)
1076 {
1077 Scalar lambda = 1.0;
1078 auto uCurrentIter = uLastIter;
1079
1080 while (true)
1081 {
1082 Backend::axpy(-lambda, deltaU, uCurrentIter);
1083 solutionChanged_(vars, uCurrentIter);
1084
1085 computeResidualReduction_(vars);
1086
1087 if (reduction_ < lastReduction_ || lambda <= lineSearchMinRelaxationFactor_)
1088 {
1089 endIterMsgStream_ << Fmt::format(", residual reduction {:.4e}->{:.4e}@lambda={:.4f}", lastReduction_, reduction_, lambda);
1090 return;
1091 }
1092
1093 // try with a smaller update and reset solution
1094 lambda *= 0.5;
1095 uCurrentIter = uLastIter;
1096 }
1097 }
1098
1100 virtual void choppedUpdate_(Variables& vars,
1101 const SolutionVector& uLastIter,
1102 const ResidualVector& deltaU)
1103 {
1104 DUNE_THROW(Dune::NotImplemented,
1105 "Chopped Newton update strategy not implemented.");
1106 }
1107
1108 virtual bool solveLinearSystem_(ResidualVector& deltaU)
1109 {
1110 return solveLinearSystemImpl_(this->linearSolver(),
1111 this->assembler().jacobian(),
1112 deltaU,
1113 this->assembler().residual());
1114 }
1115
1125 template<class V = ResidualVector>
1126 typename std::enable_if_t<!isMultiTypeBlockVector<V>(), bool>
1127 solveLinearSystemImpl_(LinearSolver& ls,
1128 JacobianMatrix& A,
1129 ResidualVector& x,
1130 ResidualVector& b)
1131 {
1132 return ls.solve(A, x, b);
1133 }
1134
1135
1145 template<class LS = LinearSolver, class V = ResidualVector>
1146 typename std::enable_if_t<linearSolverAcceptsMultiTypeMatrix<LS>() &&
1147 isMultiTypeBlockVector<V>(), bool>
1148 solveLinearSystemImpl_(LinearSolver& ls,
1149 JacobianMatrix& A,
1150 ResidualVector& x,
1151 ResidualVector& b)
1152 {
1153 assert(this->checkSizesOfSubMatrices(A) && "Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1154 return ls.solve(A, x, b);
1155 }
1156
1167 template<class LS = LinearSolver, class V = ResidualVector>
1168 [[deprecated("After 3.7 Newton will no longer support conversion of multitype matrices for solvers that don't support this feature!")]]
1169 typename std::enable_if_t<!linearSolverAcceptsMultiTypeMatrix<LS>() &&
1170 isMultiTypeBlockVector<V>(), bool>
1171 solveLinearSystemImpl_(LinearSolver& ls,
1172 JacobianMatrix& A,
1173 ResidualVector& x,
1174 ResidualVector& b)
1175 {
1176 assert(this->checkSizesOfSubMatrices(A) && "Sub-blocks of MultiTypeBlockMatrix have wrong sizes!");
1177
1178 // create the bcrs matrix the IterativeSolver backend can handle
1180
1181 // get the new matrix sizes
1182 const std::size_t numRows = M.N();
1183 assert(numRows == M.M());
1184
1185 // create the vector the IterativeSolver backend can handle
1187 assert(bTmp.size() == numRows);
1188
1189 // create a blockvector to which the linear solver writes the solution
1190 using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
1191 using BlockVector = typename Dune::BlockVector<VectorBlock>;
1192 BlockVector y(numRows);
1193
1194 // solve
1195 const bool converged = ls.solve(M, y, bTmp);
1196
1197 // copy back the result y into x
1198 if(converged)
1200
1201 return converged;
1202 }
1203
1205 void initParams_(const std::string& group = "")
1206 {
1207 useLineSearch_ = getParamFromGroup<bool>(group, "Newton.UseLineSearch", false);
1208 lineSearchMinRelaxationFactor_ = getParamFromGroup<Scalar>(group, "Newton.LineSearchMinRelaxationFactor", 0.125);
1209 useChop_ = getParamFromGroup<bool>(group, "Newton.EnableChop", false);
1210 if(useLineSearch_ && useChop_)
1211 DUNE_THROW(Dune::InvalidStateException, "Use either linesearch OR chop!");
1212
1213 enableAbsoluteResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableAbsoluteResidualCriterion", false);
1214 enableShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableShiftCriterion", true);
1215 enableResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableResidualCriterion", false) || enableAbsoluteResidualCriterion_;
1216 satisfyResidualAndShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.SatisfyResidualAndShiftCriterion", false);
1217 enableDynamicOutput_ = getParamFromGroup<bool>(group, "Newton.EnableDynamicOutput", true);
1218
1219 if (!enableShiftCriterion_ && !enableResidualCriterion_)
1220 {
1221 DUNE_THROW(Dune::NotImplemented,
1222 "at least one of NewtonEnableShiftCriterion or "
1223 << "NewtonEnableResidualCriterion has to be set to true");
1224 }
1225
1226 setMaxRelativeShift(getParamFromGroup<Scalar>(group, "Newton.MaxRelativeShift", 1e-8));
1227 setMaxAbsoluteResidual(getParamFromGroup<Scalar>(group, "Newton.MaxAbsoluteResidual", 1e-5));
1228 setResidualReduction(getParamFromGroup<Scalar>(group, "Newton.ResidualReduction", 1e-5));
1229 setTargetSteps(getParamFromGroup<int>(group, "Newton.TargetSteps", 10));
1230 setMinSteps(getParamFromGroup<int>(group, "Newton.MinSteps", 2));
1231 setMaxSteps(getParamFromGroup<int>(group, "Newton.MaxSteps", 18));
1232
1233 enablePartialReassembly_ = getParamFromGroup<bool>(group, "Newton.EnablePartialReassembly", false);
1234 reassemblyMinThreshold_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyMinThreshold", 1e-1*shiftTolerance_);
1235 reassemblyMaxThreshold_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyMaxThreshold", 1e2*shiftTolerance_);
1236 reassemblyShiftWeight_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyShiftWeight", 1e-3);
1237
1238 maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group, "Newton.MaxTimeStepDivisions", 10);
1239 retryTimeStepReductionFactor_ = getParamFromGroup<Scalar>(group, "Newton.RetryTimeStepReductionFactor", 0.5);
1240
1241 verbosity_ = comm_.rank() == 0 ? getParamFromGroup<int>(group, "Newton.Verbosity", 2) : 0;
1242 numSteps_ = 0;
1243
1244 // output a parameter report
1245 if (verbosity_ >= 2)
1246 reportParams();
1247 }
1248
1249 template<class SolA, class SolB>
1250 void updateDistanceFromLastLinearization_(const SolA& u, const SolB& uDelta)
1251 {
1252 if constexpr (Dune::IsNumber<SolA>::value)
1253 {
1254 auto nextPriVars = u;
1255 nextPriVars -= uDelta;
1256
1257 // add the current relative shift for this degree of freedom
1258 auto shift = Detail::Newton::maxRelativeShift<Scalar>(u, nextPriVars);
1259 distanceFromLastLinearization_[0] += shift;
1260 }
1261 else
1262 {
1263 for (std::size_t i = 0; i < u.size(); ++i)
1264 {
1265 const auto& currentPriVars(u[i]);
1266 auto nextPriVars(currentPriVars);
1267 nextPriVars -= uDelta[i];
1268
1269 // add the current relative shift for this degree of freedom
1270 auto shift = Detail::Newton::maxRelativeShift<Scalar>(currentPriVars, nextPriVars);
1271 distanceFromLastLinearization_[i] += shift;
1272 }
1273 }
1274 }
1275
1276 template<class ...ArgsA, class...ArgsB>
1277 void updateDistanceFromLastLinearization_(const Dune::MultiTypeBlockVector<ArgsA...>& uLastIter,
1279 {
1280 DUNE_THROW(Dune::NotImplemented, "Reassembly for MultiTypeBlockVector");
1281 }
1282
1283 template<class Sol>
1284 void resizeDistanceFromLastLinearization_(const Sol& u, std::vector<Scalar>& dist)
1285 {
1286 dist.assign(Backend::size(u), 0.0);
1287 }
1288
1289 template<class ...Args>
1290 void resizeDistanceFromLastLinearization_(const Dune::MultiTypeBlockVector<Args...>& u,
1291 std::vector<Scalar>& dist)
1292 {
1293 DUNE_THROW(Dune::NotImplemented, "Reassembly for MultiTypeBlockVector");
1294 }
1295
1297 Communication comm_;
1298
1300 int verbosity_;
1301
1302 Scalar shiftTolerance_;
1303 Scalar reductionTolerance_;
1304 Scalar residualTolerance_;
1305
1306 // time step control
1307 std::size_t maxTimeStepDivisions_;
1308 Scalar retryTimeStepReductionFactor_;
1309
1310 // further parameters
1311 bool useLineSearch_;
1312 Scalar lineSearchMinRelaxationFactor_;
1313 bool useChop_;
1314 bool enableAbsoluteResidualCriterion_;
1315 bool enableShiftCriterion_;
1316 bool enableResidualCriterion_;
1317 bool satisfyResidualAndShiftCriterion_;
1318 bool enableDynamicOutput_;
1319
1321 std::string paramGroup_;
1322
1323 // infrastructure for partial reassembly
1324 bool enablePartialReassembly_;
1325 std::unique_ptr<Reassembler> partialReassembler_;
1326 std::vector<Scalar> distanceFromLastLinearization_;
1327 Scalar reassemblyMinThreshold_;
1328 Scalar reassemblyMaxThreshold_;
1329 Scalar reassemblyShiftWeight_;
1330
1331 // statistics for the optional report
1332 std::size_t totalWastedIter_ = 0;
1333 std::size_t totalSucceededIter_ = 0;
1334 std::size_t numConverged_ = 0;
1335 std::size_t numLinearSolverBreakdowns_ = 0;
1336
1338 std::unique_ptr<PrimaryVariableSwitchAdapter> priVarSwitchAdapter_;
1339
1341 std::shared_ptr<ConvergenceWriter> convergenceWriter_ = nullptr;
1342};
1343
1344} // end namespace Dumux
1345
1346#endif
Definition: variablesbackend.hh:159
Base class for linear solvers.
Definition: solver.hh:27
auto norm(const Vector &x) const
Definition: solver.hh:65
static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A)
Converts the matrix to a type the IterativeSolverBackend can handle.
Definition: matrixconverter.hh:46
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:203
Comm Communication
Definition: nonlinear/newtonsolver.hh:228
virtual void newtonFail(Variables &u)
Called if the Newton method broke down. This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:712
int maxSteps_
maximum number of iterations we do before giving up
Definition: nonlinear/newtonsolver.hh:884
void setMaxSteps(int maxSteps)
Set the number of iterations after which the Newton method gives up.
Definition: nonlinear/newtonsolver.hh:317
typename Assembler::ResidualType ResidualVector
Definition: nonlinear/newtonsolver.hh:209
void solveLinearSystem(ResidualVector &deltaU)
Solve the linear system of equations .
Definition: nonlinear/newtonsolver.hh:493
void setResidualReduction(Scalar tolerance)
Set the maximum acceptable residual norm reduction.
Definition: nonlinear/newtonsolver.hh:286
void reportParams(std::ostream &sout=std::cout) const
Report the options and parameters this Newton is configured with.
Definition: nonlinear/newtonsolver.hh:750
int targetSteps_
optimal number of iterations we want to achieve
Definition: nonlinear/newtonsolver.hh:880
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:818
void setRetryTimeStepReductionFactor(const Scalar factor)
Set the factor for reducing the time step after a Newton iteration has failed.
Definition: nonlinear/newtonsolver.hh:842
Scalar reduction_
Definition: nonlinear/newtonsolver.hh:889
Scalar retryTimeStepReductionFactor() const
Return the factor for reducing the time step after a Newton iteration has failed.
Definition: nonlinear/newtonsolver.hh:836
int numSteps_
actual number of steps done so far
Definition: nonlinear/newtonsolver.hh:886
int verbosity() const
Return the verbosity level.
Definition: nonlinear/newtonsolver.hh:812
void setMinSteps(int minSteps)
Set the number of minimum iterations for the Newton method.
Definition: nonlinear/newtonsolver.hh:308
void newtonUpdate(Variables &vars, const SolutionVector &uLastIter, const ResidualVector &deltaU)
Update the current solution with a delta vector.
Definition: nonlinear/newtonsolver.hh:550
int minSteps_
minimum number of iterations we do
Definition: nonlinear/newtonsolver.hh:882
virtual void newtonBegin(Variables &initVars)
Called before the Newton method is applied to an non-linear system of equations.
Definition: nonlinear/newtonsolver.hh:395
virtual void assembleLinearSystem(const Variables &vars)
Assemble the linear system of equations .
Definition: nonlinear/newtonsolver.hh:474
bool enableResidualCriterion() const
Definition: nonlinear/newtonsolver.hh:876
virtual bool newtonProceed(const Variables &varsCurrentIter, bool converged)
Returns true if another iteration should be done.
Definition: nonlinear/newtonsolver.hh:433
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:327
virtual void newtonEndStep(Variables &vars, const SolutionVector &uLastIter)
Indicates that one Newton iteration was finished.
Definition: nonlinear/newtonsolver.hh:615
virtual void solutionChanged_(Variables &vars, const SolutionVector &uCurrentIter)
Update solution-dependent quantities like grid variables after the solution has changed.
Definition: nonlinear/newtonsolver.hh:852
void report(std::ostream &sout=std::cout) const
output statistics / report
Definition: nonlinear/newtonsolver.hh:723
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:381
virtual void newtonSucceed()
Called if the Newton method ended successfully This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:718
void attachConvergenceWriter(std::shared_ptr< ConvergenceWriter > convWriter)
Attach a convergence writer to write out intermediate results after each iteration.
Definition: nonlinear/newtonsolver.hh:824
Scalar initialResidual_
Definition: nonlinear/newtonsolver.hh:892
Scalar lastReduction_
Definition: nonlinear/newtonsolver.hh:891
virtual void newtonBeginStep(const Variables &vars)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:456
std::ostringstream endIterMsgStream_
message stream to be displayed at the end of iterations
Definition: nonlinear/newtonsolver.hh:899
void setVerbosity(int val)
Specifies the verbosity level.
Definition: nonlinear/newtonsolver.hh:806
typename Backend::DofVector SolutionVector
Definition: nonlinear/newtonsolver.hh:208
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:258
void resetReport()
reset the statistics
Definition: nonlinear/newtonsolver.hh:739
NewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCommunication(), const std::string &paramGroup="")
The Constructor.
Definition: nonlinear/newtonsolver.hh:233
void setMaxAbsoluteResidual(Scalar tolerance)
Set the maximum acceptable absolute residual for declaring convergence.
Definition: nonlinear/newtonsolver.hh:277
virtual void newtonEnd()
Called if the Newton method ended (not known yet if we failed or succeeded)
Definition: nonlinear/newtonsolver.hh:656
void setTargetSteps(int targetSteps)
Set the number of iterations at which the Newton method should aim at.
Definition: nonlinear/newtonsolver.hh:299
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:662
Scalar suggestTimeStepSize(Scalar oldTimeStep) const
Suggest a new time-step size based on the old time-step size.
Definition: nonlinear/newtonsolver.hh:787
void detachConvergenceWriter()
Detach the convergence writer to stop the output.
Definition: nonlinear/newtonsolver.hh:830
void setMaxRelativeShift(Scalar tolerance)
Set the maximum acceptable difference of any primary variable between two iterations for declaring co...
Definition: nonlinear/newtonsolver.hh:268
Scalar shift_
Definition: nonlinear/newtonsolver.hh:895
void computeResidualReduction_(const Variables &vars)
Definition: nonlinear/newtonsolver.hh:860
Scalar residualNorm_
Definition: nonlinear/newtonsolver.hh:890
Scalar lastShift_
Definition: nonlinear/newtonsolver.hh:896
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:27
A high-level interface for a PDESolver.
Definition: common/pdesolver.hh:61
const LinearSolver & linearSolver() const
Access the linear solver.
Definition: common/pdesolver.hh:122
const Assembler & assembler() const
Access the assembler.
Definition: common/pdesolver.hh:110
Detail::PDESolver::AssemblerVariables< Assembler > Variables
export the type of variables that represent a numerical solution
Definition: common/pdesolver.hh:71
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:420
An adapter for the Newton to manage models with primary variable switch.
Definition: primaryvariableswitchadapter.hh:44
Manages the handling of time dependent problems.
Definition: common/timeloop.hh:56
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 void retrieveValues(MultiTypeBlockVector &x, const BlockVector &y)
Copies the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector.
Definition: matrixconverter.hh:229
static auto multiTypeToBlockVector(const MultiTypeBlockVector &b)
Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector.
Definition: matrixconverter.hh:203
Definition: variablesbackend.hh:31
Defines a high-level interface for a PDESolver.
Manages the handling of time dependent problems.
Some exceptions thrown in DuMux
Formatting based on the fmt-library which implements std::format of C++20.
@ 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:81
A helper function for class member function introspection.
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.
Definition: nonlinear/newtonsolver.hh:54
static constexpr auto hasStaticIndexAccess
Definition: nonlinear/newtonsolver.hh:99
auto maxRelativeShift(const V &v1, const V &v2) -> std::enable_if_t< Dune::IsNumber< V >::value, Scalar >
Definition: nonlinear/newtonsolver.hh:123
void assign(To &to, const From &from)
Definition: nonlinear/newtonsolver.hh:143
decltype(std::declval< C >()[0]) dynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:96
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:102
static constexpr bool hasNorm()
Definition: nonlinear/newtonsolver.hh:92
decltype(std::declval< LinearSolver >().norm(std::declval< Residual >())) NormDetector
Definition: nonlinear/newtonsolver.hh:89
decltype(std::declval< C >()[Dune::Indices::_0]) staticIndexAccess
Definition: nonlinear/newtonsolver.hh:97
typename Assembler::GridVariables AssemblerGridVariablesType
Definition: nonlinear/newtonsolver.hh:57
static constexpr auto hasDynamicIndexAccess
Definition: nonlinear/newtonsolver.hh:98
Assembler::Scalar residualNorm(Residual &residual, const LinearSolver &linearSolver, const Assembler &assembler)
Definition: nonlinear/newtonsolver.hh:177
typename PriVarSwitchVariablesType< Assembler, assemblerExportsGridVariables< Assembler > >::Type PriVarSwitchVariables
Definition: nonlinear/newtonsolver.hh:75
constexpr bool assemblerExportsGridVariables
Definition: nonlinear/newtonsolver.hh:60
Definition: adapt.hh:17
This class provides the infrastructure to write the convergence behaviour of the newton method into a...
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Detects which entries in the Jacobian have to be recomputed.
An adapter for the Newton to manage models with primary variable switch.
Definition: nonlinear/newtonconvergencewriter.hh:27
EmptyGridVariables {} Type
Definition: nonlinear/newtonsolver.hh:70
Definition: nonlinear/newtonsolver.hh:64
typename Assembler::GridVariables Type
Definition: nonlinear/newtonsolver.hh:64
helper struct detecting if an assembler supports partial reassembly
Definition: nonlinear/newtonsolver.hh:79
auto operator()(Assembler &&a) -> decltype(a.assembleJacobianAndResidual(std::declval< const typename Assembler::SolutionVector & >(), std::declval< const PartialReassembler< Assembler > * >()))
Definition: nonlinear/newtonsolver.hh:81
Backends for operations on different solution vector types or more generic variable classes to be use...
Type traits to be used with vector types.