3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
26#ifndef DUMUX_NEWTON_SOLVER_HH
27#define DUMUX_NEWTON_SOLVER_HH
28
29#include <cmath>
30#include <memory>
31#include <iostream>
32#include <type_traits>
33
34#include <dune/common/timer.hh>
35#include <dune/common/exceptions.hh>
36#include <dune/common/parallel/mpicollectivecommunication.hh>
37#include <dune/common/parallel/mpihelper.hh>
38#include <dune/common/std/type_traits.hh>
39#include <dune/istl/bvector.hh>
40#include <dune/istl/multitypeblockvector.hh>
41
51
53
54namespace Dumux {
55namespace Detail {
56
59{
60 template<class Assembler>
61 auto operator()(Assembler&& a)
62 -> decltype(a.assembleJacobianAndResidual(std::declval<const typename Assembler::ResidualType&>(),
63 std::declval<const PartialReassembler<Assembler>*>()))
64 {}
65};
66
68template<class Assembler>
69using DetectPVSwitch = typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch;
70
71template<class Assembler>
72using GetPVSwitch = Dune::Std::detected_or<int, DetectPVSwitch, Assembler>;
73
74} // end namespace Detail
75
86template <class Assembler, class LinearSolver,
87 class Reassembler = PartialReassembler<Assembler>,
88 class Comm = Dune::CollectiveCommunication<Dune::MPIHelper::MPICommunicator> >
89class NewtonSolver : public PDESolver<Assembler, LinearSolver>
90{
92 using Scalar = typename Assembler::Scalar;
93 using JacobianMatrix = typename Assembler::JacobianMatrix;
94 using SolutionVector = typename Assembler::ResidualType;
97
98 using PrimaryVariableSwitch = typename Detail::GetPVSwitch<Assembler>::type;
99 using HasPriVarsSwitch = typename Detail::GetPVSwitch<Assembler>::value_t; // std::true_type or std::false_type
100 static constexpr bool hasPriVarsSwitch() { return HasPriVarsSwitch::value; };
101
102public:
103
104 using Communication = Comm;
105
109 NewtonSolver(std::shared_ptr<Assembler> assembler,
110 std::shared_ptr<LinearSolver> linearSolver,
111 const Communication& comm = Dune::MPIHelper::getCollectiveCommunication(),
112 const std::string& paramGroup = "")
114 , endIterMsgStream_(std::ostringstream::out)
115 , comm_(comm)
116 , paramGroup_(paramGroup)
117 {
118 initParams_(paramGroup);
119
120 // set the linear system (matrix & residual) in the assembler
121 this->assembler().setLinearSystem();
122
123 // set a different default for the linear solver residual reduction
124 // within the Newton the linear solver doesn't need to solve too exact
125 this->linearSolver().setResidualReduction(getParamFromGroup<Scalar>(paramGroup, "LinearSolver.ResidualReduction", 1e-6));
126
127 // initialize the partial reassembler
128 if (enablePartialReassembly_)
129 partialReassembler_ = std::make_unique<Reassembler>(this->assembler());
130
131 if (hasPriVarsSwitch())
132 {
133 const int priVarSwitchVerbosity = getParamFromGroup<int>(paramGroup, "PrimaryVariableSwitch.Verbosity", 1);
134 priVarSwitch_ = std::make_unique<PrimaryVariableSwitch>(priVarSwitchVerbosity);
135 }
136 }
137
139 const Communication& comm() const
140 { return comm_; }
141
149 void setMaxRelativeShift(Scalar tolerance)
150 { shiftTolerance_ = tolerance; }
151
158 void setMaxAbsoluteResidual(Scalar tolerance)
159 { residualTolerance_ = tolerance; }
160
167 void setResidualReduction(Scalar tolerance)
168 { reductionTolerance_ = tolerance; }
169
180 void setTargetSteps(int targetSteps)
181 { targetSteps_ = targetSteps; }
182
189 void setMinSteps(int minSteps)
190 { minSteps_ = minSteps; }
191
198 void setMaxSteps(int maxSteps)
199 { maxSteps_ = maxSteps; }
200
205 [[deprecated("Use attachConvergenceWriter(convWriter) and solve(x, *timeLoop) instead")]]
206 void solve(SolutionVector& uCurrentIter, TimeLoop& timeLoop,
207 std::shared_ptr<ConvergenceWriter> convWriter)
208 {
209 if (!convergenceWriter_)
210 attachConvergenceWriter(convWriter);
211
212 solve(uCurrentIter, timeLoop);
213 }
214
219 void solve(SolutionVector& uCurrentIter, TimeLoop& timeLoop) override
220 {
221 if (this->assembler().isStationaryProblem())
222 DUNE_THROW(Dune::InvalidStateException, "Using time step control with stationary problem makes no sense!");
223
224 // try solving the non-linear system
225 for (std::size_t i = 0; i <= maxTimeStepDivisions_; ++i)
226 {
227 // linearize & solve
228 const bool converged = solve_(uCurrentIter);
229
230 if (converged)
231 return;
232
233 else if (!converged && i < maxTimeStepDivisions_)
234 {
235 // set solution to previous solution
236 uCurrentIter = this->assembler().prevSol();
237
238 // reset the grid variables to the previous solution
239 this->assembler().resetTimeStep(uCurrentIter);
240
241 if (verbosity_ >= 1)
242 std::cout << "Newton solver did not converge with dt = "
243 << timeLoop.timeStepSize() << " seconds. Retrying with time step of "
244 << timeLoop.timeStepSize() * retryTimeStepReductionFactor_ << " seconds\n";
245
246 // try again with dt = dt * retryTimeStepReductionFactor_
247 timeLoop.setTimeStepSize(timeLoop.timeStepSize() * retryTimeStepReductionFactor_);
248 }
249
250 else
251 {
252 DUNE_THROW(NumericalProblem, "Newton solver didn't converge after "
253 << maxTimeStepDivisions_ << " time-step divisions. dt="
254 << timeLoop.timeStepSize() << '\n');
255 }
256 }
257 }
258
263 void solve(SolutionVector& uCurrentIter) override
264 {
265 const bool converged = solve_(uCurrentIter);
266 if (!converged)
267 DUNE_THROW(NumericalProblem, "Newton solver didn't converge after "
268 << numSteps_ << " iterations.\n");
269 }
270
277 virtual void newtonBegin(SolutionVector& u)
278 {
279 numSteps_ = 0;
280 initPriVarSwitch_(u, HasPriVarsSwitch{});
281
282 // write the initial residual if a convergence writer was set
283 if (convergenceWriter_)
284 {
285 this->assembler().assembleResidual(u);
286 SolutionVector delta(u);
287 delta = 0; // dummy vector, there is no delta before solving the linear system
288 convergenceWriter_->write(u, delta, this->assembler().residual());
289 }
290 }
291
298 virtual bool newtonProceed(const SolutionVector &uCurrentIter, bool converged)
299 {
300 if (numSteps_ < minSteps_)
301 return true;
302 else if (converged)
303 return false; // we are below the desired tolerance
304 else if (numSteps_ >= maxSteps_)
305 {
306 // We have exceeded the allowed number of steps. If the
307 // maximum relative shift was reduced by a factor of at least 4,
308 // we proceed even if we are above the maximum number of steps.
309 if (enableShiftCriterion_)
310 return shift_*4.0 < lastShift_;
311 else
312 return reduction_*4.0 < lastReduction_;
313 }
314
315 return true;
316 }
317
321 virtual void newtonBeginStep(const SolutionVector& u)
322 {
324 if (numSteps_ == 0)
325 {
326 lastReduction_ = 1.0;
327 }
328 else
329 {
331 }
332 }
333
339 virtual void assembleLinearSystem(const SolutionVector& uCurrentIter)
340 {
341 assembleLinearSystem_(this->assembler(), uCurrentIter);
342
343 if (enablePartialReassembly_)
344 partialReassembler_->report(comm_, endIterMsgStream_);
345 }
346
358 void solveLinearSystem(SolutionVector& deltaU)
359 {
360 auto& b = this->assembler().residual();
361
362 try
363 {
364 if (numSteps_ == 0)
365 {
366 Scalar norm2 = b.two_norm2();
367 if (comm_.size() > 1)
368 norm2 = comm_.sum(norm2);
369
370 using std::sqrt;
371 initialResidual_ = sqrt(norm2);
372 }
373
374 // solve by calling the appropriate implementation depending on whether the linear solver
375 // is capable of handling MultiType matrices or not
376 bool converged = solveLinearSystem_(deltaU);
377
378 // make sure all processes converged
379 int convergedRemote = converged;
380 if (comm_.size() > 1)
381 convergedRemote = comm_.min(converged);
382
383 if (!converged) {
384 DUNE_THROW(NumericalProblem,
385 "Linear solver did not converge");
386 }
387 else if (!convergedRemote) {
388 DUNE_THROW(NumericalProblem,
389 "Linear solver did not converge on a remote process");
390 }
391 }
392 catch (const Dune::Exception &e) {
393 // make sure all processes converged
394 int converged = 0;
395 if (comm_.size() > 1)
396 converged = comm_.min(converged);
397
399 p.message(e.what());
400 throw p;
401 }
402 }
403
421 void newtonUpdate(SolutionVector &uCurrentIter,
422 const SolutionVector &uLastIter,
423 const SolutionVector &deltaU)
424 {
425 if (enableShiftCriterion_ || enablePartialReassembly_)
426 newtonUpdateShift_(uLastIter, deltaU);
427
428 if (enablePartialReassembly_) {
429 // Determine the threshold 'eps' that is used for the partial reassembly.
430 // Every entity where the primary variables exhibit a relative shift
431 // summed up since the last linearization above 'eps' will be colored
432 // red yielding a reassembly.
433 // The user can provide three parameters to influence the threshold:
434 // 'minEps' by 'Newton.ReassemblyMinThreshold' (1e-1*shiftTolerance_ default)
435 // 'maxEps' by 'Newton.ReassemblyMaxThreshold' (1e2*shiftTolerance_ default)
436 // 'omega' by 'Newton.ReassemblyShiftWeight' (1e-3 default)
437 // The threshold is calculated from the currently achieved maximum
438 // relative shift according to the formula
439 // eps = max( minEps, min(maxEps, omega*shift) ).
440 // Increasing/decreasing 'minEps' leads to less/more reassembly if
441 // 'omega*shift' is small, i.e., for the last Newton iterations.
442 // Increasing/decreasing 'maxEps' leads to less/more reassembly if
443 // 'omega*shift' is large, i.e., for the first Newton iterations.
444 // Increasing/decreasing 'omega' leads to more/less first and last
445 // iterations in this sense.
446 using std::max;
447 using std::min;
448 auto reassemblyThreshold = max(reassemblyMinThreshold_,
449 min(reassemblyMaxThreshold_,
450 shift_*reassemblyShiftWeight_));
451
452 updateDistanceFromLastLinearization_(uLastIter, deltaU);
453 partialReassembler_->computeColors(this->assembler(),
454 distanceFromLastLinearization_,
455 reassemblyThreshold);
456
457 // set the discrepancy of the red entities to zero
458 for (unsigned int i = 0; i < distanceFromLastLinearization_.size(); i++)
459 if (partialReassembler_->dofColor(i) == EntityColor::red)
460 distanceFromLastLinearization_[i] = 0;
461 }
462
463 if (useLineSearch_)
464 lineSearchUpdate_(uCurrentIter, uLastIter, deltaU);
465
466 else if (useChop_)
467 choppedUpdate_(uCurrentIter, uLastIter, deltaU);
468
469 else
470 {
471 uCurrentIter = uLastIter;
472 uCurrentIter -= deltaU;
473
474 if (enableResidualCriterion_)
475 computeResidualReduction_(uCurrentIter);
476
477 else
478 {
479 // If we get here, the convergence criterion does not require
480 // additional residual evaluations. Thus, the grid variables have
481 // not yet been updated to the new uCurrentIter.
482 this->assembler().updateGridVariables(uCurrentIter);
483 }
484 }
485 }
486
493 virtual void newtonEndStep(SolutionVector &uCurrentIter,
494 const SolutionVector &uLastIter)
495 {
496 invokePriVarSwitch_(uCurrentIter, HasPriVarsSwitch{});
497
498 ++numSteps_;
499
500 if (verbosity_ >= 1)
501 {
502 if (enableDynamicOutput_)
503 std::cout << '\r'; // move cursor to beginning of line
504
505 auto width = std::to_string(maxSteps_).size();
506 std::cout << "Newton iteration " << std::setw(width) << numSteps_ << " done";
507
508 auto formatFlags = std::cout.flags();
509 auto prec = std::cout.precision();
510 std::cout << std::scientific << std::setprecision(3);
511
512 if (enableShiftCriterion_)
513 std::cout << ", maximum relative shift = " << shift_;
514 if (enableResidualCriterion_ && enableAbsoluteResidualCriterion_)
515 std::cout << ", residual = " << residualNorm_;
516 else if (enableResidualCriterion_)
517 std::cout << ", residual reduction = " << reduction_;
518
519 std::cout.flags(formatFlags);
520 std::cout.precision(prec);
521
522 std::cout << endIterMsgStream_.str() << "\n";
523 }
524 endIterMsgStream_.str("");
525
526 // When the Newton iterations are done: ask the model to check whether it makes sense
527 // TODO: how do we realize this? -> do this here in the Newton solver
528 // model_().checkPlausibility();
529 }
530
535 virtual void newtonEnd() {}
536
541 virtual bool newtonConverged() const
542 {
543 // in case the model has a priVar switch and some some primary variables
544 // actually switched their state in the last iteration, enforce another iteration
545 if (priVarsSwitchedInLastIteration_)
546 return false;
547
548 if (enableShiftCriterion_ && !enableResidualCriterion_)
549 {
550 return shift_ <= shiftTolerance_;
551 }
552 else if (!enableShiftCriterion_ && enableResidualCriterion_)
553 {
554 if(enableAbsoluteResidualCriterion_)
555 return residualNorm_ <= residualTolerance_;
556 else
557 return reduction_ <= reductionTolerance_;
558 }
559 else if (satisfyResidualAndShiftCriterion_)
560 {
561 if(enableAbsoluteResidualCriterion_)
562 return shift_ <= shiftTolerance_
563 && residualNorm_ <= residualTolerance_;
564 else
565 return shift_ <= shiftTolerance_
566 && reduction_ <= reductionTolerance_;
567 }
568 else if(enableShiftCriterion_ && enableResidualCriterion_)
569 {
570 if(enableAbsoluteResidualCriterion_)
571 return shift_ <= shiftTolerance_
572 || residualNorm_ <= residualTolerance_;
573 else
574 return shift_ <= shiftTolerance_
575 || reduction_ <= reductionTolerance_;
576 }
577 else
578 {
579 return shift_ <= shiftTolerance_
580 || reduction_ <= reductionTolerance_
581 || residualNorm_ <= residualTolerance_;
582 }
583
584 return false;
585 }
586
591 virtual void newtonFail(SolutionVector& u) {}
592
597 virtual void newtonSucceed() {}
598
602 void report(std::ostream& sout = std::cout) const
603 {
604 sout << '\n'
605 << "Newton statistics\n"
606 << "----------------------------------------------\n"
607 << "-- Total Newton iterations: " << totalWastedIter_ + totalSucceededIter_ << '\n'
608 << "-- Total wasted Newton iterations: " << totalWastedIter_ << '\n'
609 << "-- Total succeeded Newton iterations: " << totalSucceededIter_ << '\n'
610 << "-- Average iterations per solve: " << std::setprecision(3) << double(totalSucceededIter_) / double(numConverged_) << '\n'
611 << std::endl;
612 }
613
618 {
619 totalWastedIter_ = 0;
620 totalSucceededIter_ = 0;
621 numConverged_ = 0;
622 }
623
627 void reportParams(std::ostream& sout = std::cout) const
628 {
629 sout << "\nNewton solver configured with the following options and parameters:\n";
630 // options
631 if (useLineSearch_) sout << " -- Newton.UseLineSearch = true\n";
632 if (useChop_) sout << " -- Newton.EnableChop = true\n";
633 if (enablePartialReassembly_) sout << " -- Newton.EnablePartialReassembly = true\n";
634 if (enableAbsoluteResidualCriterion_) sout << " -- Newton.EnableAbsoluteResidualCriterion = true\n";
635 if (enableShiftCriterion_) sout << " -- Newton.EnableShiftCriterion = true (relative shift convergence criterion)\n";
636 if (enableResidualCriterion_) sout << " -- Newton.EnableResidualCriterion = true\n";
637 if (satisfyResidualAndShiftCriterion_) sout << " -- Newton.SatisfyResidualAndShiftCriterion = true\n";
638 // parameters
639 if (enableShiftCriterion_) sout << " -- Newton.MaxRelativeShift = " << shiftTolerance_ << '\n';
640 if (enableAbsoluteResidualCriterion_) sout << " -- Newton.MaxAbsoluteResidual = " << residualTolerance_ << '\n';
641 if (enableResidualCriterion_) sout << " -- Newton.ResidualReduction = " << reductionTolerance_ << '\n';
642 sout << " -- Newton.MinSteps = " << minSteps_ << '\n';
643 sout << " -- Newton.MaxSteps = " << maxSteps_ << '\n';
644 sout << " -- Newton.TargetSteps = " << targetSteps_ << '\n';
645 if (enablePartialReassembly_)
646 {
647 sout << " -- Newton.ReassemblyMinThreshold = " << reassemblyMinThreshold_ << '\n';
648 sout << " -- Newton.ReassemblyMaxThreshold = " << reassemblyMaxThreshold_ << '\n';
649 sout << " -- Newton.ReassemblyShiftWeight = " << reassemblyShiftWeight_ << '\n';
650 }
651 sout << " -- Newton.RetryTimeStepReductionFactor = " << retryTimeStepReductionFactor_ << '\n';
652 sout << " -- Newton.MaxTimeStepDivisions = " << maxTimeStepDivisions_ << '\n';
653 sout << std::endl;
654 }
655
664 Scalar suggestTimeStepSize(Scalar oldTimeStep) const
665 {
666 // be aggressive reducing the time-step size but
667 // conservative when increasing it. the rationale is
668 // that we want to avoid failing in the next Newton
669 // iteration which would require another linearization
670 // of the problem.
671 if (numSteps_ > targetSteps_) {
672 Scalar percent = Scalar(numSteps_ - targetSteps_)/targetSteps_;
673 return oldTimeStep/(1.0 + percent);
674 }
675
676 Scalar percent = Scalar(targetSteps_ - numSteps_)/targetSteps_;
677 return oldTimeStep*(1.0 + percent/1.2);
678 }
679
683 [[deprecated("Has been replaced by setVerbosity(int). Will be removed after 3.1 release!")]]
684 void setVerbose(bool val)
685 { verbosity_ = val; }
686
690 [[deprecated("Has been replaced by int verbosity(). Will be removed after 3.1 release!")]]
691 bool verbose() const
692 { return verbosity_ ; }
693
697 void setVerbosity(int val)
698 { verbosity_ = val; }
699
703 int verbosity() const
704 { return verbosity_ ; }
705
709 const std::string& paramGroup() const
710 { return paramGroup_; }
711
715 void attachConvergenceWriter(std::shared_ptr<ConvergenceWriter> convWriter)
716 { convergenceWriter_ = convWriter; }
717
722 { convergenceWriter_ = nullptr; }
723
724protected:
725
726 void computeResidualReduction_(const SolutionVector &uCurrentIter)
727 {
728 residualNorm_ = this->assembler().residualNorm(uCurrentIter);
731 }
732
734 { return enableResidualCriterion_; }
735
739 void initPriVarSwitch_(SolutionVector&, std::false_type) {}
740
744 void initPriVarSwitch_(SolutionVector& sol, std::true_type)
745 {
746 priVarSwitch_->reset(sol.size());
747 priVarsSwitchedInLastIteration_ = false;
748
749 const auto& problem = this->assembler().problem();
750 const auto& gridGeometry = this->assembler().gridGeometry();
751 auto& gridVariables = this->assembler().gridVariables();
752 priVarSwitch_->updateBoundary(problem, gridGeometry, gridVariables, sol);
753 }
754
758 void invokePriVarSwitch_(SolutionVector&, std::false_type) {}
759
763 void invokePriVarSwitch_(SolutionVector& uCurrentIter, std::true_type)
764 {
765 // update the variable switch (returns true if the pri vars at at least one dof were switched)
766 // for disabled grid variable caching
767 const auto& gridGeometry = this->assembler().gridGeometry();
768 const auto& problem = this->assembler().problem();
769 auto& gridVariables = this->assembler().gridVariables();
770
771 // invoke the primary variable switch
772 priVarsSwitchedInLastIteration_ = priVarSwitch_->update(uCurrentIter, gridVariables,
773 problem, gridGeometry);
774
775 if (priVarsSwitchedInLastIteration_)
776 {
777 for (const auto& element : elements(gridGeometry.gridView()))
778 {
779 // if the volume variables are cached globally, we need to update those where the primary variables have been switched
780 priVarSwitch_->updateSwitchedVolVars(problem, element, gridGeometry, gridVariables, uCurrentIter);
781
782 // if the flux variables are cached globally, we need to update those where the primary variables have been switched
783 priVarSwitch_->updateSwitchedFluxVarsCache(problem, element, gridGeometry, gridVariables, uCurrentIter);
784 }
785 }
786 }
787
796
797 // residual criterion variables
802
803 // shift criterion variables
804 Scalar shift_;
806
808 std::ostringstream endIterMsgStream_;
809
810
811private:
812
817 bool solve_(SolutionVector& uCurrentIter)
818 {
819 // the given solution is the initial guess
820 SolutionVector uLastIter(uCurrentIter);
821 SolutionVector deltaU(uCurrentIter);
822
823 Dune::Timer assembleTimer(false);
824 Dune::Timer solveTimer(false);
825 Dune::Timer updateTimer(false);
826
827 if (enablePartialReassembly_)
828 {
829 partialReassembler_->resetColors();
830 resizeDistanceFromLastLinearization_(uCurrentIter, distanceFromLastLinearization_);
831 }
832
833 try
834 {
835 newtonBegin(uCurrentIter);
836
837 // execute the method as long as the solver thinks
838 // that we should do another iteration
839 bool converged = false;
840 while (newtonProceed(uCurrentIter, converged))
841 {
842 // notify the solver that we're about to start
843 // a new timestep
844 newtonBeginStep(uCurrentIter);
845
846 // make the current solution to the old one
847 if (numSteps_ > 0)
848 uLastIter = uCurrentIter;
849
850 if (verbosity_ >= 1 && enableDynamicOutput_)
851 std::cout << "Assemble: r(x^k) = dS/dt + div F - q; M = grad r"
852 << std::flush;
853
855 // assemble
857
858 // linearize the problem at the current solution
859 assembleTimer.start();
860 assembleLinearSystem(uCurrentIter);
861 assembleTimer.stop();
862
864 // linear solve
866
867 // Clear the current line using an ansi escape
868 // sequence. for an explanation see
869 // http://en.wikipedia.org/wiki/ANSI_escape_code
870 const char clearRemainingLine[] = { 0x1b, '[', 'K', 0 };
871
872 if (verbosity_ >= 1 && enableDynamicOutput_)
873 std::cout << "\rSolve: M deltax^k = r"
874 << clearRemainingLine << std::flush;
875
876 // solve the resulting linear equation system
877 solveTimer.start();
878
879 // set the delta vector to zero before solving the linear system!
880 deltaU = 0;
881
882 solveLinearSystem(deltaU);
883 solveTimer.stop();
884
886 // update
888 if (verbosity_ >= 1 && enableDynamicOutput_)
889 std::cout << "\rUpdate: x^(k+1) = x^k - deltax^k"
890 << clearRemainingLine << std::flush;
891
892 updateTimer.start();
893 // update the current solution (i.e. uOld) with the delta
894 // (i.e. u). The result is stored in u
895 newtonUpdate(uCurrentIter, uLastIter, deltaU);
896 updateTimer.stop();
897
898 // tell the solver that we're done with this iteration
899 newtonEndStep(uCurrentIter, uLastIter);
900
901 // if a convergence writer was specified compute residual and write output
902 if (convergenceWriter_)
903 {
904 this->assembler().assembleResidual(uCurrentIter);
905 convergenceWriter_->write(uCurrentIter, deltaU, this->assembler().residual());
906 }
907
908 // detect if the method has converged
909 converged = newtonConverged();
910 }
911
912 // tell solver we are done
913 newtonEnd();
914
915 // reset state if Newton failed
916 if (!newtonConverged())
917 {
918 totalWastedIter_ += numSteps_;
919 newtonFail(uCurrentIter);
920 return false;
921 }
922
923 totalSucceededIter_ += numSteps_;
924 numConverged_++;
925
926 // tell solver we converged successfully
928
929 if (verbosity_ >= 1) {
930 const auto elapsedTot = assembleTimer.elapsed() + solveTimer.elapsed() + updateTimer.elapsed();
931 std::cout << "Assemble/solve/update time: "
932 << assembleTimer.elapsed() << "(" << 100*assembleTimer.elapsed()/elapsedTot << "%)/"
933 << solveTimer.elapsed() << "(" << 100*solveTimer.elapsed()/elapsedTot << "%)/"
934 << updateTimer.elapsed() << "(" << 100*updateTimer.elapsed()/elapsedTot << "%)"
935 << "\n";
936 }
937 return true;
938
939 }
940 catch (const NumericalProblem &e)
941 {
942 if (verbosity_ >= 1)
943 std::cout << "Newton: Caught exception: \"" << e.what() << "\"\n";
944
945 totalWastedIter_ += numSteps_;
946 newtonFail(uCurrentIter);
947 return false;
948 }
949 }
950
952 template<class A>
953 auto assembleLinearSystem_(const A& assembler, const SolutionVector& uCurrentIter)
954 -> typename std::enable_if_t<decltype(isValid(Detail::supportsPartialReassembly())(assembler))::value, void>
955 {
956 this->assembler().assembleJacobianAndResidual(uCurrentIter, partialReassembler_.get());
957 }
958
960 template<class A>
961 auto assembleLinearSystem_(const A& assembler, const SolutionVector& uCurrentIter)
962 -> typename std::enable_if_t<!decltype(isValid(Detail::supportsPartialReassembly())(assembler))::value, void>
963 {
964 this->assembler().assembleJacobianAndResidual(uCurrentIter);
965 }
966
974 virtual void newtonUpdateShift_(const SolutionVector &uLastIter,
975 const SolutionVector &deltaU)
976 {
977 shift_ = 0;
978 newtonUpdateShiftImpl_(uLastIter, deltaU);
979
980 if (comm_.size() > 1)
981 shift_ = comm_.max(shift_);
982 }
983
984 template<class SolVec>
985 void newtonUpdateShiftImpl_(const SolVec &uLastIter,
986 const SolVec &deltaU)
987 {
988 for (int i = 0; i < int(uLastIter.size()); ++i) {
989 typename SolVec::block_type uNewI = uLastIter[i];
990 uNewI -= deltaU[i];
991
992 Scalar shiftAtDof = relativeShiftAtDof_(uLastIter[i], uNewI);
993 using std::max;
994 shift_ = max(shift_, shiftAtDof);
995 }
996 }
997
998 template<class ...Args>
999 void newtonUpdateShiftImpl_(const Dune::MultiTypeBlockVector<Args...> &uLastIter,
1000 const Dune::MultiTypeBlockVector<Args...> &deltaU)
1001 {
1002 // There seems to be a bug in g++5 which which prevents compilation when
1003 // passing the call to the implementation directly to Dune::Hybrid::forEach.
1004 // We therefore store this call in a lambda and pass it to the for loop afterwards.
1005 auto doUpdate = [&](const auto subVectorIdx)
1006 {
1007 this->newtonUpdateShiftImpl_(uLastIter[subVectorIdx], deltaU[subVectorIdx]);
1008 };
1009
1010 using namespace Dune::Hybrid;
1011 forEach(integralRange(Dune::Hybrid::size(uLastIter)), doUpdate);
1012 }
1013
1014 virtual void lineSearchUpdate_(SolutionVector &uCurrentIter,
1015 const SolutionVector &uLastIter,
1016 const SolutionVector &deltaU)
1017 {
1018 Scalar lambda = 1.0;
1019 SolutionVector tmp(uLastIter);
1020
1021 while (true)
1022 {
1023 uCurrentIter = deltaU;
1024 uCurrentIter *= -lambda;
1025 uCurrentIter += uLastIter;
1026
1027 computeResidualReduction_(uCurrentIter);
1028
1029 if (reduction_ < lastReduction_ || lambda <= 0.125) {
1030 endIterMsgStream_ << ", residual reduction " << lastReduction_ << "->" << reduction_ << "@lambda=" << lambda;
1031 return;
1032 }
1033
1034 // try with a smaller update
1035 lambda /= 2.0;
1036 }
1037 }
1038
1040 virtual void choppedUpdate_(SolutionVector &uCurrentIter,
1041 const SolutionVector &uLastIter,
1042 const SolutionVector &deltaU)
1043 {
1044 DUNE_THROW(Dune::NotImplemented,
1045 "Chopped Newton update strategy not implemented.");
1046 }
1047
1048 virtual bool solveLinearSystem_(SolutionVector& deltaU)
1049 {
1050 return solveLinearSystemImpl_(this->linearSolver(),
1051 this->assembler().jacobian(),
1052 deltaU,
1053 this->assembler().residual());
1054 }
1055
1065 template<class V = SolutionVector>
1066 typename std::enable_if_t<!isMultiTypeBlockVector<V>(), bool>
1067 solveLinearSystemImpl_(LinearSolver& ls,
1068 JacobianMatrix& A,
1069 SolutionVector& x,
1070 SolutionVector& b)
1071 {
1078 constexpr auto blockSize = JacobianMatrix::block_type::rows;
1079 using BlockType = Dune::FieldVector<Scalar, blockSize>;
1080 Dune::BlockVector<BlockType> xTmp; xTmp.resize(b.size());
1081 Dune::BlockVector<BlockType> bTmp(xTmp);
1082 for (unsigned int i = 0; i < b.size(); ++i)
1083 for (unsigned int j = 0; j < blockSize; ++j)
1084 bTmp[i][j] = b[i][j];
1085
1086 const int converged = ls.solve(A, xTmp, bTmp);
1087
1088 for (unsigned int i = 0; i < x.size(); ++i)
1089 for (unsigned int j = 0; j < blockSize; ++j)
1090 x[i][j] = xTmp[i][j];
1091
1092 return converged;
1093 }
1094
1095
1106 template<class LS = LinearSolver, class V = SolutionVector>
1107 typename std::enable_if_t<linearSolverAcceptsMultiTypeMatrix<LS>() &&
1108 isMultiTypeBlockVector<V>(), bool>
1109 solveLinearSystemImpl_(LinearSolver& ls,
1110 JacobianMatrix& A,
1111 SolutionVector& x,
1112 SolutionVector& b)
1113 {
1114 // check matrix sizes
1115 assert(checkMatrix_(A) && "Sub blocks of MultiType matrix have wrong sizes!");
1116
1117 // TODO: automatically derive the precondBlockLevel
1118 return ls.template solve</*precondBlockLevel=*/2>(A, x, b);
1119 }
1120
1131 template<class LS = LinearSolver, class V = SolutionVector>
1132 typename std::enable_if_t<!linearSolverAcceptsMultiTypeMatrix<LS>() &&
1133 isMultiTypeBlockVector<V>(), bool>
1134 solveLinearSystemImpl_(LinearSolver& ls,
1135 JacobianMatrix& A,
1136 SolutionVector& x,
1137 SolutionVector& b)
1138 {
1139 // check matrix sizes
1140 assert(checkMatrix_(A) && "Sub blocks of MultiType matrix have wrong sizes!");
1141
1142 // create the bcrs matrix the IterativeSolver backend can handle
1144
1145 // get the new matrix sizes
1146 const std::size_t numRows = M.N();
1147 assert(numRows == M.M());
1148
1149 // create the vector the IterativeSolver backend can handle
1151 assert(bTmp.size() == numRows);
1152
1153 // create a blockvector to which the linear solver writes the solution
1154 using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
1155 using BlockVector = typename Dune::BlockVector<VectorBlock>;
1156 BlockVector y(numRows);
1157
1158 // solve
1159 const bool converged = ls.solve(M, y, bTmp);
1160
1161 // copy back the result y into x
1162 if(converged)
1164
1165 return converged;
1166 }
1167
1169 template<class M = JacobianMatrix>
1170 typename std::enable_if_t<!isBCRSMatrix<M>(), bool>
1171 checkMatrix_(const JacobianMatrix& A)
1172 {
1173 bool matrixHasCorrectSize = true;
1174 using namespace Dune::Hybrid;
1175 using namespace Dune::Indices;
1176 forEach(A, [&matrixHasCorrectSize](const auto& rowOfMultiTypeMatrix)
1177 {
1178 const auto numRowsLeftMostBlock = rowOfMultiTypeMatrix[_0].N();
1179
1180 forEach(rowOfMultiTypeMatrix, [&matrixHasCorrectSize, &numRowsLeftMostBlock](const auto& subBlock)
1181 {
1182 if (subBlock.N() != numRowsLeftMostBlock)
1183 matrixHasCorrectSize = false;
1184 });
1185 });
1186 return matrixHasCorrectSize;
1187 }
1188
1190 void initParams_(const std::string& group = "")
1191 {
1192 useLineSearch_ = getParamFromGroup<bool>(group, "Newton.UseLineSearch");
1193 useChop_ = getParamFromGroup<bool>(group, "Newton.EnableChop");
1194 if(useLineSearch_ && useChop_)
1195 DUNE_THROW(Dune::InvalidStateException, "Use either linesearch OR chop!");
1196
1197 enableAbsoluteResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableAbsoluteResidualCriterion");
1198 enableShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableShiftCriterion");
1199 enableResidualCriterion_ = getParamFromGroup<bool>(group, "Newton.EnableResidualCriterion") || enableAbsoluteResidualCriterion_;
1200 satisfyResidualAndShiftCriterion_ = getParamFromGroup<bool>(group, "Newton.SatisfyResidualAndShiftCriterion");
1201 enableDynamicOutput_ = getParamFromGroup<bool>(group, "Newton.EnableDynamicOutput", true);
1202
1203 if (!enableShiftCriterion_ && !enableResidualCriterion_)
1204 {
1205 DUNE_THROW(Dune::NotImplemented,
1206 "at least one of NewtonEnableShiftCriterion or "
1207 << "NewtonEnableResidualCriterion has to be set to true");
1208 }
1209
1210 setMaxRelativeShift(getParamFromGroup<Scalar>(group, "Newton.MaxRelativeShift"));
1211 setMaxAbsoluteResidual(getParamFromGroup<Scalar>(group, "Newton.MaxAbsoluteResidual"));
1212 setResidualReduction(getParamFromGroup<Scalar>(group, "Newton.ResidualReduction"));
1213 setTargetSteps(getParamFromGroup<int>(group, "Newton.TargetSteps"));
1214 setMinSteps(getParamFromGroup<int>(group, "Newton.MinSteps"));
1215 setMaxSteps(getParamFromGroup<int>(group, "Newton.MaxSteps"));
1216
1217 enablePartialReassembly_ = getParamFromGroup<bool>(group, "Newton.EnablePartialReassembly");
1218 reassemblyMinThreshold_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyMinThreshold", 1e-1*shiftTolerance_);
1219 reassemblyMaxThreshold_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyMaxThreshold", 1e2*shiftTolerance_);
1220 reassemblyShiftWeight_ = getParamFromGroup<Scalar>(group, "Newton.ReassemblyShiftWeight", 1e-3);
1221
1222 maxTimeStepDivisions_ = getParamFromGroup<std::size_t>(group, "Newton.MaxTimeStepDivisions", 10);
1223 retryTimeStepReductionFactor_ = getParamFromGroup<Scalar>(group, "Newton.RetryTimeStepReductionFactor", 0.5);
1224
1225 verbosity_ = comm_.rank() == 0 ? getParamFromGroup<int>(group, "Newton.Verbosity", 2) : 0;
1226 numSteps_ = 0;
1227
1228 // output a parameter report
1229 if (verbosity_ >= 2)
1230 reportParams();
1231 }
1232
1233 template<class Sol>
1234 void updateDistanceFromLastLinearization_(const Sol& u, const Sol& uDelta)
1235 {
1236 for (size_t i = 0; i < u.size(); ++i) {
1237 const auto& currentPriVars(u[i]);
1238 auto nextPriVars(currentPriVars);
1239 nextPriVars -= uDelta[i];
1240
1241 // add the current relative shift for this degree of freedom
1242 auto shift = relativeShiftAtDof_(currentPriVars, nextPriVars);
1243 distanceFromLastLinearization_[i] += shift;
1244 }
1245 }
1246
1247 template<class ...Args>
1248 void updateDistanceFromLastLinearization_(const Dune::MultiTypeBlockVector<Args...>& uLastIter,
1249 const Dune::MultiTypeBlockVector<Args...>& deltaU)
1250 {
1251 DUNE_THROW(Dune::NotImplemented, "Reassembly for MultiTypeBlockVector");
1252 }
1253
1254 template<class Sol>
1255 void resizeDistanceFromLastLinearization_(const Sol& u, std::vector<Scalar>& dist)
1256 {
1257 dist.assign(u.size(), 0.0);
1258 }
1259
1260 template<class ...Args>
1261 void resizeDistanceFromLastLinearization_(const Dune::MultiTypeBlockVector<Args...>& u,
1262 std::vector<Scalar>& dist)
1263 {
1264 DUNE_THROW(Dune::NotImplemented, "Reassembly for MultiTypeBlockVector");
1265 }
1266
1274 template<class PrimaryVariables>
1275 Scalar relativeShiftAtDof_(const PrimaryVariables &priVars1,
1276 const PrimaryVariables &priVars2) const
1277 {
1278 Scalar result = 0.0;
1279 using std::abs;
1280 using std::max;
1281 // iterate over all primary variables
1282 for (int j = 0; j < PrimaryVariables::dimension; ++j) {
1283 Scalar eqErr = abs(priVars1[j] - priVars2[j]);
1284 eqErr /= max<Scalar>(1.0,abs(priVars1[j] + priVars2[j])/2);
1285
1286 result = max(result, eqErr);
1287 }
1288 return result;
1289 }
1290
1292 Communication comm_;
1293
1295 int verbosity_;
1296
1297 Scalar shiftTolerance_;
1298 Scalar reductionTolerance_;
1299 Scalar residualTolerance_;
1300
1301 // time step control
1302 std::size_t maxTimeStepDivisions_;
1303 Scalar retryTimeStepReductionFactor_;
1304
1305 // further parameters
1306 bool useLineSearch_;
1307 bool useChop_;
1308 bool enableAbsoluteResidualCriterion_;
1309 bool enableShiftCriterion_;
1310 bool enableResidualCriterion_;
1311 bool satisfyResidualAndShiftCriterion_;
1312 bool enableDynamicOutput_;
1313
1315 std::string paramGroup_;
1316
1317 // infrastructure for partial reassembly
1318 bool enablePartialReassembly_;
1319 std::unique_ptr<Reassembler> partialReassembler_;
1320 std::vector<Scalar> distanceFromLastLinearization_;
1321 Scalar reassemblyMinThreshold_;
1322 Scalar reassemblyMaxThreshold_;
1323 Scalar reassemblyShiftWeight_;
1324
1325 // statistics for the optional report
1326 std::size_t totalWastedIter_ = 0;
1327 std::size_t totalSucceededIter_ = 0;
1328 std::size_t numConverged_ = 0;
1329
1331 std::unique_ptr<PrimaryVariableSwitch> priVarSwitch_;
1333 bool priVarsSwitchedInLastIteration_ = false;
1334
1336 std::shared_ptr<ConvergenceWriter> convergenceWriter_ = nullptr;
1337};
1338
1339} // end namespace Dumux
1340
1341#endif
Detects which entries in the Jacobian have to be recomputed.
A helper function for class member function introspection.
Type traits to be used with vector types.
Some exceptions thrown in DuMux
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Manages the handling of time dependent problems.
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
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
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
Property tag Indices
Definition: porousmediumflow/sequential/properties.hh:59
Dune::Std::detected_or< int, DetectPVSwitch, Assembler > GetPVSwitch
Definition: nonlinear/newtonsolver.hh:72
typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch DetectPVSwitch
helper aliases to extract a primary variable switch from the VolumeVariables (if defined,...
Definition: nonlinear/newtonsolver.hh:69
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:424
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:39
A high-level interface for a PDESolver.
Definition: common/pdesolver.hh:46
const Assembler & assembler() const
Access the assembler.
Definition: common/pdesolver.hh:83
const LinearSolver & linearSolver() const
Access the linear solver.
Definition: common/pdesolver.hh:95
Manages the handling of time dependent problems.
Definition: timeloop.hh:65
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:59
static void retrieveValues(MultiTypeBlockVector &x, const BlockVector &y)
Copys the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector.
Definition: matrixconverter.hh:242
static auto multiTypeToBlockVector(const MultiTypeBlockVector &b)
Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector.
Definition: matrixconverter.hh:214
Base class for linear solvers.
Definition: dumux/linear/solver.hh:37
void setResidualReduction(double r)
set the linear solver residual reduction
Definition: dumux/linear/solver.hh:101
Definition: newtonconvergencewriter.hh:39
helper struct detecting if an assembler supports partial reassembly
Definition: nonlinear/newtonsolver.hh:59
auto operator()(Assembler &&a) -> decltype(a.assembleJacobianAndResidual(std::declval< const typename Assembler::ResidualType & >(), std::declval< const PartialReassembler< Assembler > * >()))
Definition: nonlinear/newtonsolver.hh:61
An implementation of a Newton solver.
Definition: nonlinear/newtonsolver.hh:90
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:263
Comm Communication
Definition: nonlinear/newtonsolver.hh:104
int maxSteps_
maximum number of iterations we do before giving up
Definition: nonlinear/newtonsolver.hh:793
void setMaxSteps(int maxSteps)
Set the number of iterations after which the Newton method gives up.
Definition: nonlinear/newtonsolver.hh:198
void setResidualReduction(Scalar tolerance)
Set the maximum acceptable residual norm reduction.
Definition: nonlinear/newtonsolver.hh:167
void invokePriVarSwitch_(SolutionVector &, std::false_type)
Switch primary variables if necessary, noop if there is no priVarSwitch.
Definition: nonlinear/newtonsolver.hh:758
void newtonUpdate(SolutionVector &uCurrentIter, const SolutionVector &uLastIter, const SolutionVector &deltaU)
Update the current solution with a delta vector.
Definition: nonlinear/newtonsolver.hh:421
void reportParams(std::ostream &sout=std::cout) const
Report the options and parameters this Newton is configured with.
Definition: nonlinear/newtonsolver.hh:627
void initPriVarSwitch_(SolutionVector &, std::false_type)
Initialize the privar switch, noop if there is no priVarSwitch.
Definition: nonlinear/newtonsolver.hh:739
int targetSteps_
optimal number of iterations we want to achieve
Definition: nonlinear/newtonsolver.hh:789
const std::string & paramGroup() const
Returns the parameter group.
Definition: nonlinear/newtonsolver.hh:709
Scalar reduction_
Definition: nonlinear/newtonsolver.hh:798
int numSteps_
actual number of steps done so far
Definition: nonlinear/newtonsolver.hh:795
int verbosity() const
Return the verbosity level.
Definition: nonlinear/newtonsolver.hh:703
void setMinSteps(int minSteps)
Set the number of minimum iterations for the Newton method.
Definition: nonlinear/newtonsolver.hh:189
void solve(SolutionVector &uCurrentIter, TimeLoop &timeLoop, std::shared_ptr< ConvergenceWriter > convWriter)
Run the Newton method to solve a non-linear system. Does time step control when the Newton fails to c...
Definition: nonlinear/newtonsolver.hh:206
int minSteps_
minimum number of iterations we do
Definition: nonlinear/newtonsolver.hh:791
bool enableResidualCriterion() const
Definition: nonlinear/newtonsolver.hh:733
bool verbose() const
Returns true if the Newton method ought to be chatty.
Definition: nonlinear/newtonsolver.hh:691
void report(std::ostream &sout=std::cout) const
output statistics / report
Definition: nonlinear/newtonsolver.hh:602
virtual void newtonBeginStep(const SolutionVector &u)
Indicates the beginning of a Newton iteration.
Definition: nonlinear/newtonsolver.hh:321
virtual void newtonEndStep(SolutionVector &uCurrentIter, const SolutionVector &uLastIter)
Indicates that one Newton iteration was finished.
Definition: nonlinear/newtonsolver.hh:493
void initPriVarSwitch_(SolutionVector &sol, std::true_type)
Initialize the privar switch.
Definition: nonlinear/newtonsolver.hh:744
NewtonSolver(std::shared_ptr< Assembler > assembler, std::shared_ptr< LinearSolver > linearSolver, const Communication &comm=Dune::MPIHelper::getCollectiveCommunication(), const std::string &paramGroup="")
The Constructor.
Definition: nonlinear/newtonsolver.hh:109
virtual void newtonSucceed()
Called if the Newton method ended successfully This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:597
void attachConvergenceWriter(std::shared_ptr< ConvergenceWriter > convWriter)
Attach a convergence writer to write out intermediate results after each iteration.
Definition: nonlinear/newtonsolver.hh:715
Scalar initialResidual_
Definition: nonlinear/newtonsolver.hh:801
Scalar lastReduction_
Definition: nonlinear/newtonsolver.hh:800
std::ostringstream endIterMsgStream_
message stream to be displayed at the end of iterations
Definition: nonlinear/newtonsolver.hh:808
void setVerbose(bool val)
Specifies if the Newton method ought to be chatty.
Definition: nonlinear/newtonsolver.hh:684
void setVerbosity(int val)
Specifies the verbosity level.
Definition: nonlinear/newtonsolver.hh:697
void invokePriVarSwitch_(SolutionVector &uCurrentIter, std::true_type)
Switch primary variables if necessary.
Definition: nonlinear/newtonsolver.hh:763
virtual void assembleLinearSystem(const SolutionVector &uCurrentIter)
Assemble the linear system of equations .
Definition: nonlinear/newtonsolver.hh:339
const Communication & comm() const
the communicator for parallel runs
Definition: nonlinear/newtonsolver.hh:139
void resetReport()
reset the statistics
Definition: nonlinear/newtonsolver.hh:617
virtual void newtonFail(SolutionVector &u)
Called if the Newton method broke down. This method is called after newtonEnd()
Definition: nonlinear/newtonsolver.hh:591
void setMaxAbsoluteResidual(Scalar tolerance)
Set the maximum acceptable absolute residual for declaring convergence.
Definition: nonlinear/newtonsolver.hh:158
virtual void newtonEnd()
Called if the Newton method ended (not known yet if we failed or succeeded)
Definition: nonlinear/newtonsolver.hh:535
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:219
void setTargetSteps(int targetSteps)
Set the number of iterations at which the Newton method should aim at.
Definition: nonlinear/newtonsolver.hh:180
virtual void newtonBegin(SolutionVector &u)
Called before the Newton method is applied to an non-linear system of equations.
Definition: nonlinear/newtonsolver.hh:277
virtual bool newtonConverged() const
Returns true if the error of the solution is below the tolerance.
Definition: nonlinear/newtonsolver.hh:541
Scalar suggestTimeStepSize(Scalar oldTimeStep) const
Suggest a new time-step size based on the old time-step size.
Definition: nonlinear/newtonsolver.hh:664
void solveLinearSystem(SolutionVector &deltaU)
Solve the linear system of equations .
Definition: nonlinear/newtonsolver.hh:358
void computeResidualReduction_(const SolutionVector &uCurrentIter)
Definition: nonlinear/newtonsolver.hh:726
void detachConvergenceWriter()
Detach the convergence writer to stop the output.
Definition: nonlinear/newtonsolver.hh:721
void setMaxRelativeShift(Scalar tolerance)
Set the maximum acceptable difference of any primary variable between two iterations for declaring co...
Definition: nonlinear/newtonsolver.hh:149
Scalar shift_
Definition: nonlinear/newtonsolver.hh:804
virtual bool newtonProceed(const SolutionVector &uCurrentIter, bool converged)
Returns true if another iteration should be done.
Definition: nonlinear/newtonsolver.hh:298
Scalar residualNorm_
Definition: nonlinear/newtonsolver.hh:799
Scalar lastShift_
Definition: nonlinear/newtonsolver.hh:805
Defines a high-level interface for a PDESolver.