13#include <dune/common/float_cmp.hh>
15#include <spdlog/spdlog.h>
17#include <Eigen/Sparse>
43 double maxtime = std::numeric_limits<double>::infinity();
52 double Delta_bar = std::numeric_limits<double>::infinity();
61template <PreConditioner preConditioner = PreConditioner::IncompleteCholesky,
typename UF = utils::UpdateDefault>
64 static_assert(std::copy_constructible<UF>,
65 " The update function should be copy constructable. If it is a lambda wrap it in a std::function");
72 template <
typename UF2>
81 typename UF = utils::UpdateDefault>
92template <
typename NLO,
typename TRConfig>
93requires traits::isSpecializationNonTypeAndTypes<TrustRegionConfig, std::remove_cvref_t<TRConfig>>::value
95 static constexpr PreConditioner preConditioner = std::remove_cvref_t<TRConfig>::preConditionerType;
96 using UF = std::remove_cvref_t<TRConfig>::UpdateFunction;
97 static_assert(std::remove_cvref_t<NLO>::numberOfFunctions == 3,
98 "The number of derivatives in the nonlinear operator have to be exactly 3.");
99 auto solver = std::make_shared<TrustRegion<NLO, preConditioner, UF>>(nonLinearOperator,
100 std::forward<TRConfig>(config).updateFunction);
102 solver->setup(config.parameters);
167template <
typename NLO, PreConditioner preConditioner,
typename UF>
172 using ValueType =
typename NLO::template ParameterValue<0>;
179 using ScalarType = std::remove_cvref_t<typename NLO::template FunctionReturnType<0>>;
182 using MatrixType = std::remove_cvref_t<typename NLO::template FunctionReturnType<2>>;
189 template <
typename UF2 = UF>
192 updateFunction_{std::forward<UF2>(updateFunction)},
194 eta_.setZero(gradient().size());
195 Heta_.setZero(gradient().size());
196 truncatedConjugateGradient_.analyzePattern(hessian());
204 settings_ = settings;
205 assert(settings_.
rho_prime < 0.25 &&
"options.rho_prime must be strictly smaller than 1/4.");
206 assert(settings_.
Delta_bar > 0 &&
"options.Delta_bar must be positive.");
208 "options.Delta0 must be positive and smaller than Delta_bar.");
222 template <
typename SolutionType = NoPredictor>
223 requires std::is_same_v<SolutionType, NoPredictor> || std::is_convertible_v<SolutionType, CorrectionType>
229 NonLinearSolverInformation solverInformation;
235 if constexpr (not std::is_same_v<SolutionType, NoPredictor>)
236 updateFunction(x, dxPredictor);
237 truncatedConjugateGradient_.analyzePattern(hessian());
241 " | iter | inner_i | rho | energy | energy_p | energy_inc | norm(g) | Delta | norm(corr) | "
243 spdlog::info(
"{:-^143}",
"-");
244 while (not stoppingCriterion()) {
249 while (eta_.dot(hessian() * eta_) > innerInfo_.
Delta * innerInfo_.
Delta)
260 Heta_ = hessian() * eta_;
267 const Eigen::VectorXd Hg = hessian() * gradient();
268 const auto g_Hg = (gradient().dot(Hg));
272 tauC = std::min(Dune::power(stats_.
gradNorm, 3) / (innerInfo_.
Delta * g_Hg), 1.0);
275 const Eigen::VectorXd etaC = -tauC * innerInfo_.
Delta / stats_.
gradNorm * gradient();
276 const Eigen::VectorXd HetaC = -tauC * innerInfo_.
Delta / stats_.
gradNorm * Hg;
278 const double mdle = stats_.
energy + gradient().dot(eta_) + .5 * Heta_.dot(eta_);
279 const double mdlec = stats_.
energy + gradient().dot(etaC) + .5 * HetaC.dot(etaC);
280 if (mdlec < mdle && stats_.
outerIter == 0) {
292 updateFunction_(x, eta_);
301 auto rhoden = -eta_.dot(gradient() + 0.5 * Heta_);
306 const auto rhoReg = std::max(1.0, abs(stats_.
energy)) * eps_ * settings_.
rho_reg;
307 rhonum = rhonum + rhoReg;
308 rhoden = rhoden + rhoReg;
310 const bool modelDecreased = rhoden > 0.0;
315 stats_.
rho = rhonum / rhoden;
316 stats_.
rho = stats_.
rho < 0.0 ? -1.0 : stats_.
rho;
324 if (stats_.
rho < 1e-4 || not modelDecreased || std::isnan(stats_.
rho) || not energyDecreased) {
326 innerInfo_.
Delta /= 4.0;
331 spdlog::info(
" +++ Detected many consecutive TR- (radius decreases).");
332 spdlog::info(
" +++ Consider decreasing options.Delta_bar by an order of magnitude.");
343 spdlog::info(
" +++ Detected many consecutive TR+ (radius increases)");
344 spdlog::info(
" +++ Consider increasing options.Delta_bar by an order of magnitude");
352 if (modelDecreased && stats_.
rho > settings_.
rho_prime && energyDecreased) {
355 "Energy function increased by {} (step size: {}). Since this is small we accept the step and hope for "
356 "convergence of the gradient norm.",
367 innerInfo_.
Delta /= 2;
382 nonLinearOperator_.updateAll();
391 nonLinearOperator_.updateAll();
392 stats_.
gradNorm = gradient().norm();
398 solverInformation.success =
401 solverInformation.iterations = stats_.
outerIter;
402 solverInformation.residualNorm = stats_.
gradNorm;
403 if (solverInformation.success)
405 return solverInformation;
414 void logState()
const {
416 "{:>3s} {:>3s} {:>6d} {:>9d} {:>6.2f} {:>9.2e} {:>9.2e} {:>11.2e} {:>9.2e} {:>9.2e} {:>11.2e} "
423 void logFinalState() {
424 spdlog::info(
"{:>3s} {:>3s} {:>6d} {:>9d} {: ^6} {: ^9} {: ^9} {: ^11} {:>9.2e} {: ^9} {: ^11} {:<73}",
433 bool stoppingCriterion() {
434 std::ostringstream stream;
438 spdlog::info(
"CONVERGENCE: Energy: {:1.16e} norm(gradient): {:1.16e}",
nonLinearOperator().value(),
440 stream <<
"Gradient norm tolerance reached; options.tolerance = " << settings_.
grad_tol;
448 spdlog::info(
"CONVERGENCE: Energy: {:1.16e} norm(correction): {:1.16e}",
nonLinearOperator().value(),
450 stream <<
"Displacement norm tolerance reached; = " << settings_.
corr_tol <<
"." << std::endl;
460 stream <<
"Max time exceeded; options.maxtime = " << settings_.
maxtime <<
".";
469 stream <<
"Max iteration count reached; options.maxiter = " << settings_.
maxIter <<
".";
477 void solveInnerProblem() {
478 truncatedConjugateGradient_.
setInfo(innerInfo_);
480 truncatedConjugateGradient_.factorize(hessian());
485 while (truncatedConjugateGradient_.info() != Eigen::Success) {
486 choleskyInitialShift_ *= 5;
487 truncatedConjugateGradient_.preconditioner().setInitialShift(choleskyInitialShift_);
488 truncatedConjugateGradient_.factorize(hessian());
490 DUNE_THROW(Dune::MathError,
"Factorization of preconditioner failed!");
493 if (truncatedConjugateGradient_.info() == Eigen::Success)
494 choleskyInitialShift_ = 1e-3;
496 eta_ = truncatedConjugateGradient_.solveWithGuess(-gradient(), eta_);
497 innerInfo_ = truncatedConjugateGradient_.
getInfo();
500 NLO nonLinearOperator_;
502 typename NLO::template ParameterValue<0> xOld_;
507 double choleskyInitialShift_ = 1e-3;
510 static constexpr double eps_ = 0.0001220703125;
511 std::array<std::string, 6> tcg_stop_reason_{
512 {
"negative curvature",
"exceeded trust region",
"reached target residual-kappa (linear)",
513 "reached target residual-theta (superlinear)",
"maximum inner iterations",
"model increased"}
516 using PreConditionerType =
519 typename Eigen::DiagonalPreconditioner<ScalarType>,
520 typename Eigen::IncompleteCholesky<ScalarType>>>;
522 truncatedConjugateGradient_;
536 typename UF = utils::UpdateDefault>
538 return std::make_shared<TrustRegion<NLO, preConditioner, UF>>(nonLinearOperator, updateFunction);
542 typename UF2 = utils::UpdateDefault>
544 UF2&& updateFunction = {}) ->
TrustRegion<NLO, preConditioner, std::remove_cvref_t<UF2>>;
Contains stl-like type traits.
Collection of fallback default functions.
Helper for the autodiff library.
Definition of TruncatedConjugateGradient class for solving linear systems using truncated conjugate g...
Implementation of the Newton-Raphson method for solving nonlinear equations.
Enums for observer messages.
Implementation of the observer design pattern.
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:259
Definition: assemblermanipulatorbuildingblocks.hh:22
auto makeTrustRegion(const NLO &nonLinearOperator, UF &&updateFunction={})
Creates an instance of the TrustRegion solver.
Definition: trustregion.hh:537
::value auto createNonlinearSolver(NRConfig &&config, NLO &&nonLinearOperator)
Function to create a NewtonRaphson solver instance.
Definition: newtonraphson.hh:65
TrustRegion(const NLO &nonLinearOperator, UF2 &&updateFunction={}) -> TrustRegion< NLO, preConditioner, std::remove_cvref_t< UF2 > >
StopReason
Enumeration of reasons for stopping the TrustRegion solver.
Definition: trustregion.hh:111
@ maximumIterationsReached
@ correctionNormTolReached
PreConditioner
Enumeration of available preconditioners for the trust region solver.
Definition: trustregion.hh:34
Scalar Delta
Definition: truncatedconjugategradient.hh:38
TCGStopReason stop_tCG
Definition: truncatedconjugategradient.hh:37
Eigen::Index numInnerIter
Definition: truncatedconjugategradient.hh:43
TCGInfo< typename MatrixType::RealScalar > getInfo()
Get information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:227
void setInfo(TCGInfo< typename MatrixType::RealScalar > alginfo)
Set information about the truncated conjugate gradient algorithm.
Definition: truncatedconjugategradient.hh:233
Information about the result of a non-linear solver.
Definition: solverinfos.hh:19
Definition: trustregion.hh:41
double grad_tol
Gradient tolerance.
Definition: trustregion.hh:47
double Delta_bar
Maximum trust region radius.
Definition: trustregion.hh:52
double rho_reg
Regularization value for rho.
Definition: trustregion.hh:51
double Delta0
Initial trust region radius.
Definition: trustregion.hh:53
bool useRand
Flag for using random correction predictor.
Definition: trustregion.hh:50
int verbosity
Verbosity level.
Definition: trustregion.hh:42
int debug
Debugging flag.
Definition: trustregion.hh:46
int minIter
Minimum number of iterations.
Definition: trustregion.hh:44
double maxtime
Maximum allowable time for solving.
Definition: trustregion.hh:43
double corr_tol
Correction tolerance.
Definition: trustregion.hh:48
int maxIter
Maximum number of iterations.
Definition: trustregion.hh:45
double rho_prime
Rho prime value.
Definition: trustregion.hh:49
Definition: trustregion.hh:63
static constexpr PreConditioner preConditionerType
Definition: trustregion.hh:70
TRSettings parameters
Definition: trustregion.hh:69
UF UpdateFunction
Definition: trustregion.hh:67
UF updateFunction
Definition: trustregion.hh:71
auto rebindUpdateFunction(UF2 &&updateFunction) const
Definition: trustregion.hh:73
Trust Region solver for non-linear optimization problems.
Definition: trustregion.hh:169
typename NLO::DerivativeType CorrectionType
Type of the correction of x += deltaX.
Definition: trustregion.hh:174
std::remove_cvref_t< typename NLO::template FunctionReturnType< 0 > > ScalarType
Definition: trustregion.hh:180
void setup(const Settings &settings)
Sets up the TrustRegion solver with the provided settings and checks feasibility.
Definition: trustregion.hh:203
TRSettings Settings
Type of the settings for the TrustRegion solver.
Definition: trustregion.hh:171
typename NLO::template ParameterValue< 0 > ValueType
Definition: trustregion.hh:173
auto & nonLinearOperator()
Access the nonlinear operator.
Definition: trustregion.hh:411
std::remove_cvref_t< typename NLO::template FunctionReturnType< 2 > > MatrixType
Type of the Hessian.
Definition: trustregion.hh:182
NLO NonLinearOperator
Type of the non-linear operator.
Definition: trustregion.hh:177
UF UpdateFunction
Type of the update function.
Definition: trustregion.hh:175
TrustRegion(const NLO &nonLinearOperator, UF2 &&updateFunction={})
Constructs a TrustRegion solver instance.
Definition: trustregion.hh:190
NonLinearSolverInformation solve(const SolutionType &dxPredictor=NoPredictor{})
Solves the nonlinear optimization problem using the TrustRegion algorithm.
Definition: trustregion.hh:224
Additional information about the TrustRegion algorithm.
Definition: trustregion.hh:124
std::string cauchystr
Used Cauchy step string.
Definition: trustregion.hh:132
StopReason stop
Stopping reason.
Definition: trustregion.hh:135
std::string randomPredictionString
Random prediction string.
Definition: trustregion.hh:131
bool acceptProposal
Flag indicating whether the proposal is accepted.
Definition: trustregion.hh:133
std::string reasonString
String describing the stopping reason.
Definition: trustregion.hh:136
int consecutive_TRminus
Consecutive trust region decreases.
Definition: trustregion.hh:126
bool used_cauchy
Flag indicating whether Cauchy point was used.
Definition: trustregion.hh:134
int consecutive_Rejected
Consecutive rejected proposals.
Definition: trustregion.hh:127
std::string trstr
Trust region change string (TR+, TR-).
Definition: trustregion.hh:129
std::string stopReasonString
String describing the stopping reason.
Definition: trustregion.hh:128
std::string accstr
Acceptance string (REJ, acc).
Definition: trustregion.hh:130
int consecutive_TRplus
Consecutive trust region increases.
Definition: trustregion.hh:125
Information about the TrustRegion solver.
Definition: trustregion.hh:144
double rho
Definition: trustregion.hh:150
double etaNorm
Definition: trustregion.hh:146
double energyProposal
Definition: trustregion.hh:149
double energy
Definition: trustregion.hh:148
double gradNorm
Definition: trustregion.hh:145
int outerIter
Definition: trustregion.hh:151
double time
Definition: trustregion.hh:147
int innerIterSum
Definition: trustregion.hh:152
Generic observable interface for the Observer design pattern. See for a description of the design pa...
Definition: observer.hh:129
void notify(NonLinearSolverMessages message)
Notify observers about a specific message type.