https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NewtonInversionControl.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11
12#include "MooseUtils.h"
13
15
18{
21 "Adjusts a parameter postprocessor to match a sub-app output to a target function using a "
22 "finite-difference Newton update formed over two consecutive fixed-point iterations.");
23
24 params.addRangeCheckedParam<Real>(
25 "parameter_delta",
26 1e-3,
27 "parameter_delta>0",
28 "Finite-difference perturbation applied on each base iteration to estimate df/dp.");
29 // Invariant: this sentinel must stay far above the fixed-point Convergence tolerance (1 for the
30 // generated PostprocessorConvergence) so a perturbed iteration is never seen as converged. The
31 // odd/even scheme's correctness depends on that gap never closing.
32 params.addRangeCheckedParam<Real>(
33 "nonconverged_residual",
34 1e30,
35 "nonconverged_residual>0",
36 "Large residual written on perturbed iterations so that convergence is only ever declared on "
37 "a base iteration (where the recorded parameter is un-perturbed). Must stay well above the "
38 "convergence tolerance so a perturbed iteration is never accepted.");
39
40 return params;
41}
42
44 : InversionControlBase(parameters),
45 _parameter_delta(getParam<Real>("parameter_delta")),
46 _nonconverged_residual(getParam<Real>("nonconverged_residual")),
47 _p_base(0.0),
48 _y_base(0.0)
49{
50}
51
53NewtonInversionControl::computeUpdate(unsigned int it, Real p_used, Real y, Real y_target)
54{
55 // Odd -> base solve at p; even -> perturbed solve at p + parameter_delta. _p_base/_y_base are
56 // plain members re-seeded on every base iteration, so no restartable state is needed.
57 if (it % 2 == 1)
58 {
59 // Base solve: record the sample, publish it as the solution of record, report the normalized
60 // residual, and set the perturbed parameter for the next (even) iteration.
61 _p_base = p_used;
62 _y_base = y;
63 return {p_used + _parameter_delta, normalizedResidual(y), true};
64 }
65
66 // Perturbed solve. The base iteration set the parameter to _p_base + _parameter_delta and nothing
67 // else should touch it before this solve reads it back, so p_used must equal that perturbed
68 // value. If it does not, an external object changed the parameter between the two solves -- most
69 // likely the parameter postprocessor was relaxed by listing it in the executioner's
70 // transformed_postprocessors
71 // -- so the finite-difference slope below would reflect a perturbation the model never actually
72 // saw. Fail loudly rather than return a silently wrong update. The fuzzy comparison only absorbs
73 // last-bit rounding (the value is written and read as the same double); a relaxation moves it by
74 // O(_parameter_delta), far above the default relative tolerance.
75 const Real p_perturbed = _p_base + _parameter_delta;
76 if (!MooseUtils::relativeFuzzyEqual(p_used, p_perturbed))
77 mooseError("The parameter postprocessor '",
79 "' changed between the base and perturbed solves (expected ",
80 p_perturbed,
81 ", read ",
82 p_used,
83 "); the finite-difference derivative would be invalid. Do not relax it via the "
84 "executioner's 'transformed_postprocessors' or otherwise modify it between "
85 "iterations.");
86
87 // A single guarded linear-model step over the base and perturbed samples is the finite-difference
88 // Newton update. Force a non-converged residual (and do not publish) so that convergence is only
89 // ever declared on a base iteration (where the recorded parameter is un-perturbed).
90 const Real p_next = linearRootUpdate(_p_base, _y_base, p_used, y, y_target);
91 return {p_next, _nonconverged_residual, false};
92}
const std::vector< double > y
registerMooseObject("OptimizationApp", NewtonInversionControl)
void addClassDescription(const std::string &doc_string)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Base class for controls that adjust a single scalar parameter (held in a postprocessor) once per fixe...
Real normalizedResidual(Real y) const
Normalized convergence residual for output value y: |y - targetValue()| / max(absolute_tolerance,...
Real linearRootUpdate(Real p_a, Real y_a, Real p_b, Real y_b, Real y_target)
One guarded linear-model root update from two (parameter, output) samples – a secant step shared by t...
const PostprocessorName _param_name
Name of the parameter postprocessor to update with the next guess.
static InputParameters validParams()
void mooseError(Args &&... args) const
Control that adjusts a scalar parameter (held in a postprocessor) to match a sub-app output to a targ...
Real _y_base
Output value of the current base solve (re-seeded each fixed-point solve; not restartable)
Real _p_base
Parameter value of the current base solve (re-seeded each fixed-point solve; not restartable)
virtual IterationUpdate computeUpdate(unsigned int it, Real p_used, Real y, Real y_target) override
Compute this iteration's update from the current sample: the 1-based fixed-point iteration it and the...
const Real _parameter_delta
Finite-difference perturbation applied on each base iteration to form df/dp.
NewtonInversionControl(const InputParameters &parameters)
const Real _nonconverged_residual
Residual written on perturbed iterations so convergence is only declared on base iterations.
static InputParameters validParams()
One iteration's update, produced by the derived scheme and applied by execute().