OGS
Root1D.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include <cassert>
14 #include <cmath>
15 #include <limits>
16 #include <type_traits>
17 #include <utility>
18 
19 #include "BaseLib/Error.h"
20 
21 namespace MathLib
22 {
23 namespace Nonlinear
24 {
25 
26 namespace detail
27 {
28 
30 inline bool same_sign(double a, double b)
31 {
32  // note: signbit() casts integers to double and distinguishes between +0.0 and
33  // -0.0. However, the latter is not a problem, because if f(x0) == 0, we've
34  // already found the root x0 that we are searching for.
35  return std::signbit(a) == std::signbit(b);
36 }
37 
38 inline bool almost_zero(double a)
39 {
40  return std::abs(a) <= std::numeric_limits<double>::epsilon();
41 }
42 
43 } // namespace detail
44 
47 template<typename SubType, typename Function>
49 {
50 public:
53  RegulaFalsi(Function&& f, double a, double b)
54  : f_(f), a_(a), b_(b), fa_(f(a)), fb_(f(b))
55  {
56  static_assert(std::is_same_v<double, decltype(f(0.0))>,
57  "Using this class for functions that do not return double"
58  " involves a lot of casts. Hence it is disabled.");
59 
61  {
62  b_ = a_;
63  }
64  else if (detail::almost_zero(fb_))
65  {
66  a_ = b_;
67  }
68  else if (detail::same_sign(fa_, fb_))
69  {
70  OGS_FATAL("Regula falsi cannot be done, because the function values"
71  " at the interval ends have the same sign.");
72  }
73  }
74 
76  void step(const unsigned num_steps)
77  {
78  for (unsigned i=0; i<num_steps; ++i)
79  {
80  if (a_ == b_)
81  {
82  return;
83  }
84 
85  const double s = (fb_ - fa_) / (b_ - a_);
86  const double c = a_ - fa_ / s;
87  const double fc = f_(c);
88 
89  if (detail::almost_zero(fc)) {
90  a_ = b_ = c;
91  return;
92  }
93  if (!detail::same_sign(fc, fb_))
94  {
95  a_ = b_;
96  fa_ = fb_;
97  b_ = c;
98  fb_ = fc;
99  } else {
100  const double m = SubType::get_m(fa_, fb_, fc);
101  fa_ *= m;
102  b_ = c;
103  fb_ = fc;
104  }
105  }
106  }
107 
109  double getResult() const
110  {
111  if (a_ == b_)
112  {
113  return a_;
114  }
115 
116  const double s = (fb_ - fa_) / (b_ - a_);
117  const double c = a_ - fa_ / s;
118 
119  return c;
120  }
121 
123  double getRange() const { return std::abs(a_ - b_); }
124 
125 private:
127  double a_, b_, fa_, fb_;
128 };
129 
130 
136 template <typename SubType, typename Function>
138  double const a,
139  double const b)
140 {
141  return RegulaFalsi<SubType, Function>(std::forward<Function>(f), a, b);
142 }
143 
144 
147 {
148  static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
149  { return 1.0; }
150 };
151 
153 struct Illinois
154 {
155  static double get_m(const double /*fa*/, const double /*fb*/, const double /*fc*/)
156  { return 0.5; }
157 };
158 
160 struct Pegasus
161 {
162  static double get_m(const double /*fa*/, const double fb, const double fc)
163  { return fb / (fb+fc); }
164 };
165 
168 {
169  static double get_m(const double /*fa*/, const double fb, const double fc)
170  {
171  const double f = 1.0 - fc / fb;
172  return (f >= 0.0) ? f : 0.5;
173  }
174 };
175 
176 } // namespace Nonlinear
177 
178 } // namespace MathLib
#define OGS_FATAL(...)
Definition: Error.h:26
void step(const unsigned num_steps)
Do num_steps iteration of regula falsi.
Definition: Root1D.h:76
double getResult() const
Returns the current estimate of the root.
Definition: Root1D.h:109
RegulaFalsi(Function &&f, double a, double b)
Definition: Root1D.h:53
double getRange() const
Returns the size of the current search interval.
Definition: Root1D.h:123
std::function< bool(const double t, MappedConstVector< N > const &y, MappedVector< N > &ydot)> Function
bool almost_zero(double a)
Definition: Root1D.h:38
bool same_sign(double a, double b)
Tells if a and b have the same sign.
Definition: Root1D.h:30
RegulaFalsi< SubType, Function > makeRegulaFalsi(Function &&f, double const a, double const b)
Definition: Root1D.h:137
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition: Root1D.h:168
static double get_m(const double, const double fb, const double fc)
Definition: Root1D.h:169
Used by RegulaFalsi in a modified version of the regula falsi algorithm.
Definition: Root1D.h:154
static double get_m(const double, const double, const double)
Definition: Root1D.h:155
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 the original regula falsi algorithm.
Definition: Root1D.h:147
static double get_m(const double, const double, const double)
Definition: Root1D.h:148