8#ifndef DUNE_PDELAB_NEWTON_NEWTON_HH
9#define DUNE_PDELAB_NEWTON_NEWTON_HH
26#include <dune/pdelab/backend/solver.hh>
27#include <dune/pdelab/constraints/common/constraints.hh>
28#include <dune/pdelab/solver/newton.hh>
41 class NewtonLineSearchError :
public NewtonError {};
42 class NewtonNotConverged :
public NewtonError {};
45 template<
class RFType>
46 struct NewtonResult : LinearSolverResult<RFType>
50 double assembler_time;
51 double linear_solver_time;
52 int linear_solver_iterations;
55 first_defect(0.0), defect(0.0), assembler_time(0.0), linear_solver_time(0.0),
56 linear_solver_iterations(0) {}
59 template<
class GOS,
class TrlV,
class TstV>
62 typedef GOS GridOperator;
63 typedef TrlV TrialVector;
64 typedef TstV TestVector;
66 typedef typename TestVector::ElementType RFType;
67 typedef typename GOS::Traits::Jacobian Matrix;
72 typedef NewtonResult<RFType> Result;
74 void setVerbosityLevel(
unsigned int verbosity_level)
76 if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
79 verbosity_level_ = verbosity_level;
83 void setKeepMatrix(
bool b)
89 bool keepMatrix()
const
102 const GridOperator& gridoperator_;
104 std::shared_ptr<TrialVector> z_;
105 std::shared_ptr<TestVector> r_;
106 std::shared_ptr<Matrix> A_;
108 unsigned int verbosity_level_;
110 RFType linear_reduction_;
116 NewtonBase(
const GridOperator& go, TrialVector& u)
119 , verbosity_level_(1)
122 if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
123 verbosity_level_ = 0;
126 NewtonBase(
const GridOperator& go)
129 , verbosity_level_(1)
132 if (gridoperator_.trialGridFunctionSpace().gridView().comm().rank()>0)
133 verbosity_level_ = 0;
136 virtual ~NewtonBase() { }
138 virtual bool terminate() = 0;
139 virtual void prepare_step(Matrix& A, TestVector& r) = 0;
140 virtual void line_search(TrialVector& z, TestVector& r) = 0;
141 virtual void defect(TestVector& r) = 0;
144 template<
class GOS,
class S,
class TrlV,
class TstV>
145 class NewtonSolver :
public virtual NewtonBase<GOS,TrlV,TstV>
148 typedef GOS GridOperator;
149 typedef TrlV TrialVector;
150 typedef TstV TestVector;
152 typedef typename TestVector::ElementType RFType;
153 typedef typename GOS::Traits::Jacobian Matrix;
156 typedef NewtonResult<RFType> Result;
158 NewtonSolver(
const GridOperator& go, TrialVector& u_, Solver& solver)
159 : NewtonBase<GOS,TrlV,TstV>(go,u_)
161 , result_valid_(false)
162 , use_maxnorm_(false)
165 NewtonSolver(
const GridOperator& go, Solver& solver)
166 : NewtonBase<GOS,TrlV,TstV>(go)
168 , result_valid_(false)
169 , use_maxnorm_(false)
170 , hanging_node_modifications_(false)
175 void apply(TrialVector& u_);
177 const Result& result()
const
181 "NewtonSolver::result() called before NewtonSolver::solve()");
186 void setUseMaxNorm(
bool b)
191 void setHangingNodeModifications(
bool b)
193 hanging_node_modifications_ = b;
197 virtual void defect(TestVector& r)
override
199 if (hanging_node_modifications_){
200 auto dirichletValues = *this->u_;
208 this->gridoperator_.localAssembler().backtransform(*this->u_);
212 this->gridoperator_.residual(*this->u_, r);
218 auto rank_max = Backend::native(r).infinity_norm();
219 this->res_.defect = this->gridoperator_.testGridFunctionSpace().gridView().comm().max(rank_max);
223 this->res_.defect = this->solver_.norm(r);
225 if (!std::isfinite(this->res_.defect))
227 "NewtonSolver::defect(): Non-linear defect is NaN or Inf");
232 void linearSolve(Matrix& A, TrialVector& z, TestVector& r)
const
234 if (this->verbosity_level_ >= 4)
235 std::cout <<
" Solving linear system..." << std::endl;
238 Impl::setLinearSystemReuse(this->solver_, !this->reassembled_);
239 this->solver_.apply(A, z, r, this->linear_reduction_);
241 ios_base_all_saver restorer(std::cout);
243 if (!this->solver_.result().converged)
245 "NewtonSolver::linearSolve(): Linear solver did not converge "
246 "in " << this->solver_.result().iterations <<
" iterations");
247 if (this->verbosity_level_ >= 4)
248 std::cout <<
" linear solver iterations: "
249 << std::setw(12) << solver_.result().iterations << std::endl
250 <<
" linear defect reduction: "
251 << std::setw(12) << std::setprecision(4) << std::scientific
252 << solver_.result().reduction << std::endl;
258 bool hanging_node_modifications_;
261 template<
class GOS,
class S,
class TrlV,
class TstV>
268 template<
class GOS,
class S,
class TrlV,
class TstV>
271 this->res_.iterations = 0;
272 this->res_.converged =
false;
273 this->res_.reduction = 1.0;
274 this->res_.conv_rate = 1.0;
275 this->res_.elapsed = 0.0;
276 this->res_.assembler_time = 0.0;
277 this->res_.linear_solver_time = 0.0;
278 this->res_.linear_solver_iterations = 0;
279 result_valid_ =
true;
286 this->r_ = std::make_shared<TestVector>(this->gridoperator_.testGridFunctionSpace());
293 this->defect(*this->r_);
294 this->res_.first_defect = this->res_.defect;
295 this->prev_defect_ = this->res_.defect;
297 if (this->verbosity_level_ >= 2)
300 ios_base_all_saver restorer(std::cout);
301 std::cout <<
" Initial defect: "
302 << std::setw(12) << std::setprecision(4) << std::scientific
303 << this->res_.defect << std::endl;
308 this->A_ = std::make_shared<Matrix>(this->gridoperator_);
312 this->z_ = std::make_shared<TrialVector>(this->gridoperator_.trialGridFunctionSpace());
315 while (!this->terminate())
317 if (this->verbosity_level_ >= 3)
318 std::cout <<
" Newton iteration " << this->res_.iterations
319 <<
" --------------------------------" << std::endl;
321 Timer assembler_timer;
330 this->prepare_step(*this->A_,*this->r_);
334 this->res_.assembler_time += assembler_timer.elapsed();
337 double assembler_time = assembler_timer.elapsed();
338 this->res_.assembler_time += assembler_time;
339 if (this->verbosity_level_ >= 3)
340 std::cout <<
" matrix assembly time: "
341 << std::setw(12) << std::setprecision(4) << std::scientific
342 << assembler_time << std::endl;
344 Timer linear_solver_timer;
351 this->linearSolve(*this->A_, *this->z_, *this->r_);
355 this->res_.linear_solver_time += linear_solver_timer.elapsed();
356 this->res_.linear_solver_iterations += this->solver_.result().iterations;
359 double linear_solver_time = linear_solver_timer.elapsed();
360 this->res_.linear_solver_time += linear_solver_time;
361 this->res_.linear_solver_iterations += this->solver_.result().iterations;
367 this->line_search(*this->z_, *this->r_);
369 catch (NewtonLineSearchError&)
371 if (this->reassembled_)
373 if (this->verbosity_level_ >= 3)
374 std::cout <<
" line search failed - trying again with reassembled matrix" << std::endl;
378 this->res_.reduction = this->res_.defect/this->res_.first_defect;
379 this->res_.iterations++;
380 this->res_.conv_rate = std::pow(this->res_.reduction, 1.0/this->res_.iterations);
383 ios_base_all_saver restorer(std::cout);
385 if (this->verbosity_level_ >= 3)
386 std::cout <<
" linear solver time: "
387 << std::setw(12) << std::setprecision(4) << std::scientific
388 << linear_solver_time << std::endl
389 <<
" defect reduction (this iteration):"
390 << std::setw(12) << std::setprecision(4) << std::scientific
391 << this->res_.defect/this->prev_defect_ << std::endl
392 <<
" defect reduction (total): "
393 << std::setw(12) << std::setprecision(4) << std::scientific
394 << this->res_.reduction << std::endl
396 << std::setw(12) << std::setprecision(4) << std::scientific
397 << this->res_.defect << std::endl;
398 if (this->verbosity_level_ == 2)
399 std::cout <<
" Newton iteration " << std::setw(2) << this->res_.iterations
401 << std::setw(12) << std::setprecision(4) << std::scientific
403 <<
". Reduction (this): "
404 << std::setw(12) << std::setprecision(4) << std::scientific
405 << this->res_.defect/this->prev_defect_
406 <<
". Reduction (total): "
407 << std::setw(12) << std::setprecision(4) << std::scientific
408 << this->res_.reduction << std::endl;
413 this->res_.elapsed = timer.elapsed();
416 this->res_.elapsed = timer.elapsed();
418 ios_base_all_saver restorer(std::cout);
420 if (this->verbosity_level_ == 1)
421 std::cout <<
" Newton converged after " << std::setw(2) << this->res_.iterations
422 <<
" iterations. Reduction: "
423 << std::setw(12) << std::setprecision(4) << std::scientific
424 << this->res_.reduction
425 <<
" (" << std::setprecision(4) << this->res_.elapsed <<
"s)"
428 if(!this->keep_matrix_)
432 template<
class GOS,
class TrlV,
class TstV>
433 class NewtonTerminate :
public virtual NewtonBase<GOS,TrlV,TstV>
435 typedef GOS GridOperator;
436 typedef TrlV TrialVector;
438 typedef typename TstV::ElementType RFType;
441 NewtonTerminate(
const GridOperator& go, TrialVector& u_)
442 : NewtonBase<GOS,TrlV,TstV>(go,u_)
444 , force_iteration_(false)
446 this->reduction_ = 1e-8;
447 this->abs_limit_ = 1e-12;
450 NewtonTerminate(
const GridOperator& go)
451 : NewtonBase<GOS,TrlV,TstV>(go)
453 , force_iteration_(false)
455 this->reduction_ = 1e-8;
456 this->abs_limit_ = 1e-12;
459 void setReduction(RFType reduction)
461 this->reduction_ = reduction;
464 void setMaxIterations(
unsigned int maxit)
469 void setForceIteration(
bool force_iteration)
471 force_iteration_ = force_iteration;
474 void setAbsoluteLimit(RFType abs_limit_)
476 this->abs_limit_ = abs_limit_;
479 virtual bool terminate()
override
481 if (force_iteration_ && this->res_.iterations == 0)
483 this->res_.converged = this->res_.defect < this->abs_limit_
484 || this->res_.defect < this->res_.first_defect * this->reduction_;
485 if (this->res_.iterations >= maxit_ && !this->res_.converged)
487 "NewtonTerminate::terminate(): Maximum iteration count reached");
488 return this->res_.converged;
493 bool force_iteration_;
496 template<
class GOS,
class TrlV,
class TstV>
497 class NewtonPrepareStep :
public virtual NewtonBase<GOS,TrlV,TstV>
499 typedef GOS GridOperator;
500 typedef TrlV TrialVector;
502 typedef typename TstV::ElementType RFType;
503 typedef typename GOS::Traits::Jacobian Matrix;
506 NewtonPrepareStep(
const GridOperator& go, TrialVector& u_)
507 : NewtonBase<GOS,TrlV,TstV>(go,u_)
508 , min_linear_reduction_(1e-3)
509 , fixed_linear_reduction_(0.0)
510 , reassemble_threshold_(0.0)
513 NewtonPrepareStep(
const GridOperator& go)
514 : NewtonBase<GOS,TrlV,TstV>(go)
515 , min_linear_reduction_(1e-3)
516 , fixed_linear_reduction_(0.0)
517 , reassemble_threshold_(0.0)
518 , hanging_node_modifications_(false)
527 void setMinLinearReduction(RFType min_linear_reduction)
529 min_linear_reduction_ = min_linear_reduction;
536 void setFixedLinearReduction(
bool fixed_linear_reduction)
538 fixed_linear_reduction_ = fixed_linear_reduction;
548 void setReassembleThreshold(RFType reassemble_threshold)
550 reassemble_threshold_ = reassemble_threshold;
553 void setHangingNodeModifications(
bool b)
555 hanging_node_modifications_ = b;
558 virtual void prepare_step(Matrix& A, TstV& )
override
560 this->reassembled_ =
false;
561 if (this->res_.defect/this->prev_defect_ > reassemble_threshold_)
563 if (hanging_node_modifications_){
564 auto dirichletValues = *this->u_;
572 this->gridoperator_.localAssembler().backtransform(*this->u_);
575 if (this->verbosity_level_ >= 3)
576 std::cout <<
" Reassembling matrix..." << std::endl;
578 this->gridoperator_.jacobian(*this->u_, A);
579 this->reassembled_ =
true;
582 if (fixed_linear_reduction_ ==
true)
583 this->linear_reduction_ = min_linear_reduction_;
587 std::max(this->res_.first_defect * this->reduction_,
598 if ( stop_defect/(10*this->res_.defect) >
599 this->res_.defect*this->res_.defect/(this->prev_defect_*this->prev_defect_) )
600 this->linear_reduction_ =
601 stop_defect/(10*this->res_.defect);
603 this->linear_reduction_ =
604 std::min(min_linear_reduction_,this->res_.defect*this->res_.defect/(this->prev_defect_*this->prev_defect_));
607 this->prev_defect_ = this->res_.defect;
609 ios_base_all_saver restorer(std::cout);
611 if (this->verbosity_level_ >= 3)
612 std::cout <<
" requested linear reduction: "
613 << std::setw(12) << std::setprecision(4) << std::scientific
614 << this->linear_reduction_ << std::endl;
618 RFType min_linear_reduction_;
619 bool fixed_linear_reduction_;
620 RFType reassemble_threshold_;
621 bool hanging_node_modifications_;
624 template<
class GOS,
class TrlV,
class TstV>
625 class NewtonLineSearch :
public virtual NewtonBase<GOS,TrlV,TstV>
627 typedef GOS GridOperator;
628 typedef TrlV TrialVector;
629 typedef TstV TestVector;
631 typedef typename TestVector::ElementType RFType;
642 hackbuschReuskenAcceptBest };
644 NewtonLineSearch(
const GridOperator& go, TrialVector& u_)
645 : NewtonBase<GOS,TrlV,TstV>(go,u_)
646 , strategy_(hackbuschReusken)
648 , damping_factor_(0.5)
651 NewtonLineSearch(
const GridOperator& go)
652 : NewtonBase<GOS,TrlV,TstV>(go)
653 , strategy_(hackbuschReusken)
655 , damping_factor_(0.5)
658 void setLineSearchStrategy(Strategy strategy)
660 strategy_ = strategy;
663 void setLineSearchStrategy(std::string strategy)
665 strategy_ = strategyFromName(strategy);
668 void setLineSearchMaxIterations(
unsigned int maxit)
673 void setLineSearchDampingFactor(RFType damping_factor)
675 damping_factor_ = damping_factor;
678 virtual void line_search(TrialVector& z, TestVector& r)
override
680 if ((strategy_ == noLineSearch) || (this->res_.defect < this->abs_limit_))
682 this->u_->axpy(-1.0, z);
687 if (this->verbosity_level_ >= 4)
688 std::cout <<
" Performing line search..." << std::endl;
690 RFType best_lambda = 0.0;
691 RFType best_defect = this->res_.defect;
692 TrialVector prev_u(*this->u_);
694 ios_base_all_saver restorer(std::cout);
698 if (this->verbosity_level_ >= 4)
699 std::cout <<
" trying line search damping factor: "
700 << std::setw(12) << std::setprecision(4) << std::scientific
704 this->u_->axpy(-lambda, z);
708 catch (NewtonDefectError&)
710 if (this->verbosity_level_ >= 4)
711 std::cout <<
" NaNs detected" << std::endl;
714 if (this->res_.defect <= (1.0 - lambda/4) * this->prev_defect_)
716 if (this->verbosity_level_ >= 4)
717 std::cout <<
" line search converged" << std::endl;
721 if (this->res_.defect < best_defect)
723 best_defect = this->res_.defect;
724 best_lambda = lambda;
729 if (this->verbosity_level_ >= 4)
730 std::cout <<
" max line search iterations exceeded" << std::endl;
733 case hackbuschReusken:
737 "NewtonLineSearch::line_search(): line search failed, "
738 "max iteration count reached, "
739 "defect did not improve enough");
740 case hackbuschReuskenAcceptBest:
741 if (best_lambda == 0.0)
746 "NewtonLineSearch::line_search(): line search failed, "
747 "max iteration count reached, "
748 "defect did not improve in any of the iterations");
750 if (best_lambda != lambda)
753 this->u_->axpy(-best_lambda, z);
763 lambda *= damping_factor_;
766 if (this->verbosity_level_ >= 4)
767 std::cout <<
" line search damping factor: "
768 << std::setw(12) << std::setprecision(4) << std::scientific
769 << lambda << std::endl;
774 Strategy strategyFromName(
const std::string & s) {
775 if (s ==
"noLineSearch")
777 if (s ==
"hackbuschReusken")
778 return hackbuschReusken;
779 if (s ==
"hackbuschReuskenAcceptBest")
780 return hackbuschReuskenAcceptBest;
781 DUNE_THROW(Exception,
"unknown line search strategy" << s);
787 RFType damping_factor_;
790 template<
class GOS,
class S,
class TrlV,
class TstV = TrlV>
791 class Newton :
public NewtonSolver<GOS,S,TrlV,TstV>
792 ,
public NewtonTerminate<GOS,TrlV,TstV>
793 ,
public NewtonLineSearch<GOS,TrlV,TstV>
794 ,
public NewtonPrepareStep<GOS,TrlV,TstV>
796 typedef GOS GridOperator;
798 typedef TrlV TrialVector;
801 Newton(
const GridOperator& go, TrialVector& u_, Solver& solver_)
802 DUNE_DEPRECATED_MSG(
"This Newton is deprecated. Use NewtonMethod from dune/pdelab/solver/newton.hh instead.")
803 : NewtonBase<GOS,TrlV,TstV>(go,u_)
804 , NewtonSolver<GOS,S,TrlV,TstV>(go,u_,solver_)
805 , NewtonTerminate<GOS,TrlV,TstV>(go,u_)
806 , NewtonLineSearch<GOS,TrlV,TstV>(go,u_)
807 , NewtonPrepareStep<GOS,TrlV,TstV>(go,u_)
809 Newton(
const GridOperator& go, Solver& solver_)
810 DUNE_DEPRECATED_MSG(
"This Newton is deprecated. Use NewtonMethod from dune/pdelab/solver/newton.hh instead.")
811 : NewtonBase<GOS,TrlV,TstV>(go)
812 , NewtonSolver<GOS,S,TrlV,TstV>(go,solver_)
813 , NewtonTerminate<GOS,TrlV,TstV>(go)
814 , NewtonLineSearch<GOS,TrlV,TstV>(go)
815 , NewtonPrepareStep<GOS,TrlV,TstV>(go)
841 typedef typename TstV::ElementType RFType;
842 if (param.
hasKey(
"VerbosityLevel"))
843 this->setVerbosityLevel(
844 param.
get<
unsigned int>(
"VerbosityLevel"));
845 if (param.
hasKey(
"Reduction"))
847 param.
get<RFType>(
"Reduction"));
848 if (param.
hasKey(
"MaxIterations"))
849 this->setMaxIterations(
850 param.
get<
unsigned int>(
"MaxIterations"));
851 if (param.
hasKey(
"ForceIteration"))
852 this->setForceIteration(
853 param.
get<
bool>(
"ForceIteration"));
854 if (param.
hasKey(
"AbsoluteLimit"))
855 this->setAbsoluteLimit(
856 param.
get<RFType>(
"AbsoluteLimit"));
857 if (param.
hasKey(
"MinLinearReduction"))
858 this->setMinLinearReduction(
859 param.
get<RFType>(
"MinLinearReduction"));
860 if (param.
hasKey(
"FixedLinearReduction"))
861 this->setFixedLinearReduction(
862 param.
get<
bool>(
"FixedLinearReduction"));
863 if (param.
hasKey(
"ReassembleThreshold"))
864 this->setReassembleThreshold(
865 param.
get<RFType>(
"ReassembleThreshold"));
866 if (param.
hasKey(
"LineSearchStrategy"))
867 this->setLineSearchStrategy(
868 param.
get<std::string>(
"LineSearchStrategy"));
869 if (param.
hasKey(
"LineSearchMaxIterations"))
870 this->setLineSearchMaxIterations(
871 param.
get<
unsigned int>(
"LineSearchMaxIterations"));
872 if (param.
hasKey(
"LineSearchDampingFactor"))
873 this->setLineSearchDampingFactor(
874 param.
get<RFType>(
"LineSearchDampingFactor"));
875 if (param.
hasKey(
"KeepMatrix"))
877 param.
get<
bool>(
"KeepMatrix"));
878 if (param.
hasKey(
"UseMaxNorm"))
880 param.
get<
bool>(
"UseMaxNorm"));
Hierarchical structure of string parameters.
Definition: parametertree.hh:35
std::string get(const std::string &key, const std::string &defaultValue) const
get value as string
Definition: parametertree.cc:183
bool hasKey(const std::string &key) const
test for key
Definition: parametertree.cc:46
A few common exception classes.
decltype(auto) apply(F &&f, ArgTuple &&args)
Apply function with arguments given as tuple.
Definition: apply.hh:46
#define DUNE_DEPRECATED_MSG(text)
Mark some entity as deprecated.
Definition: deprecated.hh:169
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
void set_constrained_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
construct constraints from given boundary condition function
Definition: constraints.hh:796
void set_shifted_dofs(const CG &cg, typename XG::ElementType x, XG &xg)
Definition: constraints.hh:1014
void copy_constrained_dofs(const CG &cg, const XG &xgin, XG &xgout)
Definition: constraints.hh:936
auto min(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::min()
Definition: defaults.hh:87
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
Utility class for storing and resetting stream attributes.
Dune namespace.
Definition: alignedallocator.hh:14
A hierarchical structure of string parameters.
Standard Dune debug streams.