13#ifndef OPTIMIST_ROOTFINDER_VARONA4_HH
14#define OPTIMIST_ROOTFINDER_VARONA4_HH
39 template <
typename Real>
70 std::ostringstream os;
72 if (this->m_method == Method::ORDER_4) {os <<
"4";}
73 else if (this->m_method == Method::ORDER_8) {os <<
"8";}
74 else if (this->m_method == Method::ORDER_16) {os <<
"16";}
75 else if (this->m_method == Method::ORDER_32) {os <<
"32";}
76 else {os <<
"UNKNOWN";}
128 template <
typename FunctionLambda,
typename FirstDerivativeLambda>
129 bool solve_impl(FunctionLambda && function, FirstDerivativeLambda && first_derivative, Real x_ini,
132 #define CMD "Optimist::RootFinder::Varona::solve(...): "
141 bool damped, success;
142 Real residuals, step_norm;
143 Real x_old, x_new, function_old, function_new, step_old, step_new;
144 Real first_derivative_old;
148 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_old, function_old);
150 CMD "function evaluation failed at the initial point.");
161 success = this->
evaluate_first_derivative(std::forward<FirstDerivativeLambda>(first_derivative), x_old, first_derivative_old);
163 CMD "first derivative evaluation failed at iteration " << this->
m_iterations <<
".");
166 if (std::abs(first_derivative_old) < EPSILON_LOW) {
168 first_derivative_old = (first_derivative_old > 0.0) ? EPSILON_LOW : -EPSILON_LOW;
171 this->
compute_step(std::forward<FunctionLambda>(function), x_old, function_old, first_derivative_old, step_old);
174 residuals = std::abs(function_old);
175 step_norm = std::abs(step_old);
177 if (residuals < tolerance_residuals || step_norm < tolerance_step_norm) {
184 damped = this->
damp(std::forward<FunctionLambda>(function), x_old, function_old, step_old, x_new, function_new, step_new);
188 x_new = x_old + step_old;
189 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_new, function_new);
191 CMD "function evaluation failed at iteration " << this->
m_iterations <<
".");
196 function_old = function_new;
220 template <
typename FunctionLambda>
221 void compute_step(FunctionLambda && function, Real x_old, Real function_old, Real first_derivative_old,
224 #define CMD "Optimist::RootFinder::Varona::compute_step(...): "
227 Real function_y, function_z, function_w, function_h, step_tmp, t, s, u, v;
231 step_old = -function_old/first_derivative_old;
234 if (this->m_method == Method::ORDER_4 || this->m_method == Method::ORDER_8 ||
235 this->m_method == Method::ORDER_16 || this->m_method == Method::ORDER_32) {
236 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_old+step_old, function_y);
238 CMD "function evaluation failed during order 4 step.");
239 if (std::abs(function_y) < tolerance_residuals) {
return;}
240 t = function_y/function_old;
241 step_tmp = this->
Q(t) * (function_y/first_derivative_old);
242 if (std::isfinite(step_tmp)) {step_old -= step_tmp;}
247 if (this->m_method == Method::ORDER_8 || this->m_method == Method::ORDER_16 ||
248 this->m_method == Method::ORDER_32) {
249 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_old+step_old, function_z);
251 CMD "function evaluation failed during order 8 step.");
252 if (std::abs(function_z) < tolerance_residuals) {
return;}
253 s = function_z/function_y;
254 step_tmp = this->
W(t, s) * (function_z/first_derivative_old);
255 if (std::isfinite(step_tmp)) {step_old -= step_tmp;}
260 if (this->m_method == Method::ORDER_16 || this->m_method == Method::ORDER_32) {
261 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_old+step_old, function_w);
263 CMD "function evaluation failed during order 16 step.");
264 if (std::abs(function_w) < tolerance_residuals) {
return;}
265 u = function_w/function_z;
266 step_tmp = this->
H(t, s, u) * (function_w/first_derivative_old);
267 if (std::isfinite(step_tmp)) {step_old -= step_tmp;}
272 if (this->m_method == Method::ORDER_32) {
273 success = this->
evaluate_function(std::forward<FunctionLambda>(function), x_old+step_old, function_h);
275 CMD "function evaluation failed during order 32 step.");
276 if (std::abs(function_h) < tolerance_residuals) {
return;}
277 v = (function_h/function_w);
278 step_tmp = this->
J(t, s, u, v) * (function_h/first_derivative_old);
279 if (std::isfinite(step_tmp)) {step_old -= step_tmp;}
284 CMD "step is not finite.");
294 static Real
Q(Real t) {
return 1.0 + 2.0*t;}
302 static Real
W(Real t, Real s) {
return t*t*(1.0 - 4.0*t) + (4.0*s + 2.0)*t + s + 1.0;}
311 static Real
H(Real t, Real s, Real u) {
318 ((8.0*u + 6.0*t2 + 4.0)*s -
319 (6.0*t8 + 4.0*(s + u + 1.0))*t1 +
320 2.0*t8 - 4.0*t17 + t23 + 2.0)*t +
321 t1*(t8 + s + u + 1.0) +
322 (1.0 - 3.0*t2 + t23)*s +
334 static Real
J(Real t, Real s, Real u, Real v) {
343 Real t65{u + 1.0 + v};
344 Real t76{(-2.0*t22 + u + 4.0*v + 2.0)*u};
346 (-1.0 + 2.0*t)*(2.0 + 5.0*t)*u*t*t2 +
347 (4.0*t + 1.0)*u*s*t2 +
348 (u*t22 - 2.0*u*v - u - v - 1.0)*(4.0*t17 + 3.0*t + 1.0)*( - 1.0 + t) -
349 8.0*(t22*(t17/2.0 - 1.0/4.0) + u*(t17*t32 - 5.0/8.0*t34 - 3.0/4.0*t32 +
350 3.0/8.0*t37 + 3.0/4.0*t17 - t/8.0 - 1.0/4.0) + 3.0/4.0*t46*(t + 1.0/2.0)*(t - 2.0/3.0))*t*t1 +
351 4.0*(t22*( - 3.0/2.0*t - 1.0/4.0) + u*(t34 - t32 - 3.0/2.0*t37 + t17/4.0 - t - 1.0/4.0) -
352 t46*(t + 1.0/4.0))*s*t1 + (1.0 + v + t65*t17 - 4.0*t65*t37 - 3.0*t65*t32 + 6.0*t65*t34 +
353 t76 + 4.0*(1.0 + v + t76)*t)*s;
#define OPTIMIST_WARNING(MSG)
Definition Optimist.hh:53
#define OPTIMIST_ASSERT_WARNING(COND, MSG)
Definition Optimist.hh:61
#define OPTIMIST_BASIC_CONSTANTS(Real)
Definition Optimist.hh:71
#define OPTIMIST_ASSERT(COND, MSG)
Definition Optimist.hh:44
RootFinder()
Definition RootFinder.hh:70
void method(Method t_method)
Definition Varona.hh:90
static constexpr bool requires_second_derivative
Definition Varona.hh:45
enum class Method :Integer {ORDER_4=41, ORDER_8=8, ORDER_16=16, ORDER_32=32} Method
Definition Varona.hh:52
Varona()
Definition Varona.hh:62
static Real W(Real t, Real s)
Definition Varona.hh:302
void enable_8th_order_method()
Definition Varona.hh:100
bool solve_impl(FunctionLambda &&function, FirstDerivativeLambda &&first_derivative, Real x_ini, Real &x_sol)
Definition Varona.hh:129
void enable_4th_order_method()
Definition Varona.hh:95
void compute_step(FunctionLambda &&function, Real x_old, Real function_old, Real first_derivative_old, Real &step_old)
Definition Varona.hh:221
static constexpr bool requires_function
Definition Varona.hh:43
static Real Q(Real t)
Definition Varona.hh:294
static constexpr bool requires_first_derivative
Definition Varona.hh:44
Method m_method
Definition Varona.hh:55
static Real J(Real t, Real s, Real u, Real v)
Definition Varona.hh:334
Method method() const
Definition Varona.hh:84
void enable_16th_order_method()
Definition Varona.hh:105
static Real H(Real t, Real s, Real u)
Definition Varona.hh:311
void set_method(Method t_method)
Definition Varona.hh:116
void enable_32th_order_method()
Definition Varona.hh:110
std::string name_impl() const
Definition Varona.hh:68
bool m_damped
Definition SolverBase.hh:93
void info(Real residuals, std::string const ¬es="-")
Definition SolverBase.hh:924
Integer m_iterations
Definition SolverBase.hh:84
bool damp(FunctionLambda &&function, InputType const &x_old, InputType const &function_old, InputType const &step_old, InputType &x_new, InputType &function_new, InputType &step_new)
Definition SolverBase.hh:828
Integer m_max_iterations
Definition SolverBase.hh:85
void store_trace(InputType const &x)
Definition SolverBase.hh:813
void header()
Definition SolverBase.hh:870
void reset()
Definition SolverBase.hh:748
bool m_verbose
Definition SolverBase.hh:92
bool m_converged
Definition SolverBase.hh:98
void bottom()
Definition SolverBase.hh:900
bool evaluate_function(FunctionLambda &&function, InputType const &x, OutputType &out)
Definition SolverBase.hh:768
Real m_tolerance
Definition SolverBase.hh:91
bool evaluate_first_derivative(FirstDerivativeLambda &&function, InputType const &x, FirstDerivativeType &out)
Definition SolverBase.hh:785
Namespace for the Optimist library.
Definition Optimist.hh:88
OPTIMIST_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Optimist.hh:96