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.
Helper for the autodiff library.
Collection of fallback default functions.
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: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.