OGS
Root1D.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <cassert>
7#include <cmath>
8#include <limits>
9#include <type_traits>
10#include <utility>
11
12#include "BaseLib/Error.h"
13
14namespace MathLib
15{
16namespace Nonlinear
17{
18
19namespace detail
20{
21
23inline bool same_sign(double a, double b)
24{
25 // note: signbit() casts integers to double and distinguishes between +0.0 and
26 // -0.0. However, the latter is not a problem, because if f(x0) == 0, we've
27 // already found the root x0 that we are searching for.
28 return std::signbit(a) == std::signbit(b);
29}
30
31inline bool almost_zero(double a)
32{
33 return std::abs(a) <= std::numeric_limits<double>::epsilon();
34}
35
36} // namespace detail
37
40template<typename SubType, typename Function>
42{
43public:
46 RegulaFalsi(Function&& f, double a, double b)
47 : f_(f), a_(a), b_(b), fa_(f(a)), fb_(f(b))
48 {
49 static_assert(std::is_same_v<double, decltype(f(0.0))>,
50 "Using this class for functions that do not return double"
51 " involves a lot of casts. Hence it is disabled.");
52
54 {
55 b_ = a_;
56 }
57 else if (detail::almost_zero(fb_))
58 {
59 a_ = b_;
60 }
61 else if (detail::same_sign(fa_, fb_))
62 {
63 OGS_FATAL("Regula falsi cannot be done, because the function values"
64 " at the interval ends have the same sign.");
65 }
66 }
67
69 void step(const unsigned num_steps)
70 {
71 for (unsigned i=0; i<num_steps; ++i)
72 {
73 if (a_ == b_)
74 {
75 return;
76 }
77
78 const double s = (fb_ - fa_) / (b_ - a_);
79 const double c = a_ - fa_ / s;
80 const double fc = f_(c);
81
82 if (detail::almost_zero(fc)) {
83 a_ = b_ = c;
84 return;
85 }
86 if (!detail::same_sign(fc, fb_))
87 {
88 a_ = b_;
89 fa_ = fb_;
90 b_ = c;
91 fb_ = fc;
92 } else {
93 const double m = SubType::get_m(fa_, fb_, fc);
94 fa_ *= m;
95 b_ = c;
96 fb_ = fc;
97 }
98 }
99 }
100
102 double getResult() const
103 {
104 if (a_ == b_)
105 {
106 return a_;
107 }
108
109 const double s = (fb_ - fa_) / (b_ - a_);
110 const double c = a_ - fa_ / s;
111
112 return c;
113 }
114
116 double getRange() const { return std::abs(a_ - b_); }
117
118private:
119 Function f_;
120 double a_, b_, fa_, fb_;
121};
122
123
129template <typename SubType, typename Function>
131 double const a,
132 double const b)
133{
134 return RegulaFalsi<SubType, Function>(std::forward<Function>(f), a, b);
135}
136
137
140{
141 static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
142 { return 1.0; }
143};
144
147{
148 static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
149 { return 0.5; }
150};
151
154{
155 static double get_m(const double /*fa*/, const double fb, const double fc)
156 { return fb / (fb+fc); }
157};
158
161{
162 static double get_m(const double /*fa*/, const double fb, const double fc)
163 {
164 const double v = 1.0 - fc / fb;
165 return (v >= 0.0) ? v : 0.5;
166 }
167};
168
169} // namespace Nonlinear
170
171} // namespace MathLib
#define OGS_FATAL(...)
Definition Error.h:19
void step(const unsigned num_steps)
Do num_steps iteration of regula falsi.
Definition Root1D.h:69
double getResult() const
Returns the current estimate of the root.
Definition Root1D.h:102
RegulaFalsi(Function &&f, double a, double b)
Definition Root1D.h:46
double getRange() const
Returns the size of the current search interval.
Definition Root1D.h:116
bool almost_zero(double a)
Definition Root1D.h:31
bool same_sign(double a, double b)
Tells if a and b have the same sign.
Definition Root1D.h:23
RegulaFalsi< SubType, Function > makeRegulaFalsi(Function &&f, double const a, double const b)
Definition Root1D.h:130
static const double s
static const double v
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:161
static double get_m(const double, const double fb, const double fc)
Definition Root1D.h:162
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:147
static double get_m(const double, const double, const double)
Definition Root1D.h:148
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition Root1D.h:154
static double get_m(const double, const double fb, const double fc)
Definition Root1D.h:155
Used by RegulaFalsi in the original regula falsi algorithm.
Definition Root1D.h:140
static double get_m(const double, const double, const double)
Definition Root1D.h:141