13#include <dune/common/float_cmp.hh>
15#include <spdlog/spdlog.h>
17#include <Eigen/Sparse>
40 double maxtime = std::numeric_limits<double>::infinity();
49 double Delta_bar = std::numeric_limits<double>::infinity();
112 typename UpdateFunctionTypeImpl = utils::UpdateDefault>
115 using ValueType =
typename NonLinearOperatorImpl::template ParameterValue<0>;
123 = std::remove_cvref_t<typename NonLinearOperatorImpl::template FunctionReturnType<0>>;
127 = std::remove_cvref_t<typename NonLinearOperatorImpl::template FunctionReturnType<2>>;
134 explicit TrustRegion(
const NonLinearOperatorImpl& p_nonLinearOperator, UpdateFunctionTypeImpl p_updateFunction = {})
135 : nonLinearOperator_{p_nonLinearOperator},
136 updateFunction{p_updateFunction},
138 eta.setZero(gradient().size());
139 Heta.setZero(gradient().size());
147 options = p_settings;
148 assert(options.
rho_prime < 0.25 &&
"options.rho_prime must be strictly smaller than 1/4.");
149 assert(options.
Delta_bar > 0 &&
"options.Delta_bar must be positive.");
151 &&
"options.Delta0 must be positive and smaller than Delta_bar.");
155 struct NoPredictor {};
163 template <
typename SolutionType = NoPredictor>
164 requires std::is_same_v<SolutionType, NoPredictor> || std::is_convertible_v<SolutionType, CorrectionType>
170 NonLinearSolverInformation solverInformation;
176 if constexpr (not std::is_same_v<SolutionType, NoPredictor>) updateFunction(x, dx_predictor);
177 truncatedConjugateGradient.analyzePattern(hessian());
181 " | iter | inner_i | rho | energy | energy_p | energy_inc | norm(g) | Delta | norm(corr) | "
183 spdlog::info(
"{:-^143}",
"-");
184 while (not stoppingCriterion()) {
189 while (eta.dot(hessian() * eta) > innerInfo.
Delta * innerInfo.
Delta)
200 Heta = hessian() * eta;
207 const Eigen::VectorXd Hg = hessian() * gradient();
208 const auto g_Hg = (gradient().dot(Hg));
212 tau_c = std::min(Dune::power(stats.
gradNorm, 3) / (innerInfo.
Delta * g_Hg), 1.0);
215 const Eigen::VectorXd eta_c = -tau_c * innerInfo.
Delta / stats.
gradNorm * gradient();
216 const Eigen::VectorXd Heta_c = -tau_c * innerInfo.
Delta / stats.
gradNorm * Hg;
218 const double mdle = stats.
energy + gradient().dot(eta) + .5 * Heta.dot(eta);
219 const double mdlec = stats.
energy + gradient().dot(eta_c) + .5 * Heta_c.dot(eta_c);
220 if (mdlec < mdle && stats.
outerIter == 0) {
232 updateFunction(x, eta);
241 auto rhoden = -eta.dot(gradient() + 0.5 * Heta);
246 const auto rho_reg = std::max(1.0, abs(stats.
energy)) * eps * options.
rho_reg;
247 rhonum = rhonum + rho_reg;
248 rhoden = rhoden + rho_reg;
250 const bool model_decreased = rhoden > 0.0;
252 if (!model_decreased) info.
stopReasonString.append(
", model did not decrease");
254 stats.
rho = rhonum / rhoden;
255 stats.
rho = stats.
rho < 0.0 ? -1.0 : stats.
rho;
263 if (stats.
rho < 1e-4 || not model_decreased || std::isnan(stats.
rho) || not energyDecreased) {
265 innerInfo.
Delta /= 4.0;
270 spdlog::info(
" +++ Detected many consecutive TR- (radius decreases).");
271 spdlog::info(
" +++ Consider decreasing options.Delta_bar by an order of magnitude.");
274 }
else if (stats.
rho > 0.99
283 spdlog::info(
" +++ Detected many consecutive TR+ (radius increases)");
284 spdlog::info(
" +++ Consider increasing options.Delta_bar by an order of magnitude");
292 if (model_decreased && stats.
rho > options.
rho_prime && energyDecreased) {
295 "Energy function increased by {} (step size: {}). Since this is small we accept the step and hope for "
296 "convergence of the gradient norm.",
307 innerInfo.
Delta /= 2;
321 nonLinearOperator_.updateAll();
330 nonLinearOperator_.updateAll();
337 solverInformation.success
340 solverInformation.iterations = stats.
outerIter;
341 solverInformation.residualNorm = stats.
gradNorm;
342 if (solverInformation.success)
344 return solverInformation;
353 void logState()
const {
355 "{:>3s} {:>3s} {:>6d} {:>9d} {:>6.2f} {:>9.2e} {:>9.2e} {:>11.2e} {:>9.2e} {:>9.2e} {:>11.2e} "
362 void logFinalState() {
363 spdlog::info(
"{:>3s} {:>3s} {:>6d} {:>9d} {: ^6} {: ^9} {: ^9} {: ^11} {:>9.2e} {: ^9} {: ^11} {:<73}",
372 bool stoppingCriterion() {
373 std::ostringstream stream;
377 spdlog::info(
"CONVERGENCE: Energy: {:1.16e} norm(gradient): {:1.16e}",
nonLinearOperator().value(),
379 stream <<
"Gradient norm tolerance reached; options.tolerance = " << options.
grad_tol;
387 spdlog::info(
"CONVERGENCE: Energy: {:1.16e} norm(correction): {:1.16e}",
nonLinearOperator().value(),
389 stream <<
"Displacement norm tolerance reached; = " << options.
corr_tol <<
"." << std::endl;
399 stream <<
"Max time exceeded; options.maxtime = " << options.
maxtime <<
".";
408 stream <<
"Max iteration count reached; options.maxiter = " << options.
maxiter <<
".";
416 void solveInnerProblem() {
417 truncatedConjugateGradient.
setInfo(innerInfo);
419 truncatedConjugateGradient.factorize(hessian());
424 while (truncatedConjugateGradient.info() != Eigen::Success) {
425 choleskyInitialShift *= 5;
426 truncatedConjugateGradient.preconditioner().setInitialShift(choleskyInitialShift);
427 truncatedConjugateGradient.factorize(hessian());
428 if (attempts > 5) DUNE_THROW(Dune::MathError,
"Factorization of preconditioner failed!");
431 if (truncatedConjugateGradient.info() == Eigen::Success) choleskyInitialShift = 1e-3;
433 eta = truncatedConjugateGradient.solveWithGuess(-gradient(), eta);
434 innerInfo = truncatedConjugateGradient.
getInfo();
437 NonLinearOperatorImpl nonLinearOperator_;
439 typename NonLinearOperatorImpl::template ParameterValue<0> xOld;
442 TrustRegionSettings options;
444 double choleskyInitialShift = 1e-3;
447 static constexpr double eps = 0.0001220703125;
448 std::array<std::string, 6> tcg_stop_reason{
449 {
"negative curvature",
"exceeded trust region",
"reached target residual-kappa (linear)",
450 "reached target residual-theta (superlinear)",
"maximum inner iterations",
"model increased"}};
452 using PreConditionerType
455 typename Eigen::DiagonalPreconditioner<ScalarType>,
456 typename Eigen::IncompleteCholesky<ScalarType>>>;
458 truncatedConjugateGradient;
472 typename UpdateFunctionType = utils::UpdateDefault>
473 auto makeTrustRegion(
const NonLinearOperatorImpl& p_nonLinearOperator, UpdateFunctionType&& p_updateFunction = {}) {
474 return std::make_shared<TrustRegion<NonLinearOperatorImpl, preConditioner, UpdateFunctionType>>(p_nonLinearOperator,
Collection of fallback default functions.
Contains stl-like type traits.
Helper for the autodiff library.
Definition of TruncatedConjugateGradient class for solving linear systems using truncated conjugate g...
Enums for observer messages.
Implementation of the observer design pattern.
Implementation of the Newton-Raphson method for solving nonlinear equations.
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:258
Definition: simpleassemblers.hh:21
auto makeTrustRegion(const NonLinearOperatorImpl &p_nonLinearOperator, UpdateFunctionType &&p_updateFunction={})
Creates an instance of the TrustRegion solver.
Definition: trustregion.hh:473
StopReason
Enumeration of reasons for stopping the TrustRegion solver.
Definition: trustregion.hh:57
@ maximumIterationsReached
@ correctionNormTolReached
PreConditioner
Enumeration of available preconditioners for the trust region solver.
Definition: trustregion.hh:33
Scalar Delta
Definition: truncatedconjugategradient.hh:36
TCGStopReason stop_tCG
Definition: truncatedconjugategradient.hh:35
Eigen::Index numInnerIter
Definition: truncatedconjugategradient.hh:41
TCGInfo< typename MatrixType::RealScalar > getInfo()
Get information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:219
void setInfo(TCGInfo< typename MatrixType::RealScalar > _alginfo)
Set information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:225
Information about the result of a non-linear solver.
Definition: solverinfos.hh:18
Configuration settings for the TrustRegion solver.
Definition: trustregion.hh:38
int miniter
Minimum number of iterations.
Definition: trustregion.hh:41
double rho_reg
Regularization value for rho.
Definition: trustregion.hh:48
int verbosity
Verbosity level.
Definition: trustregion.hh:39
double grad_tol
Gradient tolerance.
Definition: trustregion.hh:44
double Delta0
Initial trust region radius.
Definition: trustregion.hh:50
int debug
Debugging flag.
Definition: trustregion.hh:43
double Delta_bar
Maximum trust region radius.
Definition: trustregion.hh:49
bool useRand
Flag for using random correction predictor.
Definition: trustregion.hh:47
int maxiter
Maximum number of iterations.
Definition: trustregion.hh:42
double rho_prime
Rho prime value.
Definition: trustregion.hh:46
double maxtime
Maximum allowable time for solving.
Definition: trustregion.hh:40
double corr_tol
Correction tolerance.
Definition: trustregion.hh:45
Additional information about the TrustRegion algorithm.
Definition: trustregion.hh:69
std::string cauchystr
Used Cauchy step string.
Definition: trustregion.hh:77
StopReason stop
Stopping reason.
Definition: trustregion.hh:80
std::string randomPredictionString
Random prediction string.
Definition: trustregion.hh:76
bool acceptProposal
Flag indicating whether the proposal is accepted.
Definition: trustregion.hh:78
std::string reasonString
String describing the stopping reason.
Definition: trustregion.hh:81
int consecutive_TRminus
Consecutive trust region decreases.
Definition: trustregion.hh:71
bool used_cauchy
Flag indicating whether Cauchy point was used.
Definition: trustregion.hh:79
int consecutive_Rejected
Consecutive rejected proposals.
Definition: trustregion.hh:72
std::string trstr
Trust region change string (TR+, TR-).
Definition: trustregion.hh:74
std::string stopReasonString
String describing the stopping reason.
Definition: trustregion.hh:73
std::string accstr
Acceptance string (REJ, acc).
Definition: trustregion.hh:75
int consecutive_TRplus
Consecutive trust region increases.
Definition: trustregion.hh:70
Information about the TrustRegion solver.
Definition: trustregion.hh:88
double rho
Definition: trustregion.hh:94
double etaNorm
Definition: trustregion.hh:90
double energyProposal
Definition: trustregion.hh:93
double energy
Definition: trustregion.hh:92
double gradNorm
Definition: trustregion.hh:89
int outerIter
Definition: trustregion.hh:95
double time
Definition: trustregion.hh:91
int innerIterSum
Definition: trustregion.hh:96
Trust Region solver for non-linear optimization problems.
Definition: trustregion.hh:113
auto & nonLinearOperator()
Access the nonlinear operator.
Definition: trustregion.hh:350
void setup(const TrustRegionSettings &p_settings)
Sets up the TrustRegion solver with the provided settings and checks feasibility.
Definition: trustregion.hh:146
NonLinearSolverInformation solve(const SolutionType &dx_predictor=NoPredictor{})
Solves the nonlinear optimization problem using the TrustRegion algorithm.
Definition: trustregion.hh:165
UpdateFunctionTypeImpl UpdateFunctionType
Type of the update function.
Definition: trustregion.hh:118
typename NonLinearOperatorImpl::template ParameterValue< 0 > ValueType
Definition: trustregion.hh:116
NonLinearOperatorImpl NonLinearOperator
Type of the non-linear operator.
Definition: trustregion.hh:120
std::remove_cvref_t< typename NonLinearOperatorImpl::template FunctionReturnType< 0 > > ScalarType
Definition: trustregion.hh:124
typename NonLinearOperatorImpl::DerivativeType CorrectionType
Type of the correction of x += deltaX.
Definition: trustregion.hh:117
std::remove_cvref_t< typename NonLinearOperatorImpl::template FunctionReturnType< 2 > > MatrixType
Type of the Hessian.
Definition: trustregion.hh:127
TrustRegion(const NonLinearOperatorImpl &p_nonLinearOperator, UpdateFunctionTypeImpl p_updateFunction={})
Constructs a TrustRegion solver instance.
Definition: trustregion.hh:134
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:125
void notify(NonLinearSolverMessages message)
Notify observers about a specific message type.
Definition: observer.hh:254