xroot.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "xerror.h"
4 #include <gsl/gsl_errno.h>
5 #include <gsl/gsl_roots.h>
6 #include <optional>
7 
8 namespace nmx::gsl {
9 
15 {
16 private:
17  //gsl interne Struktur
18  const gsl_root_fsolver_type *_solver_type = nullptr;
19  //legt Algorithmus fest
20  gsl_root_fsolver *_solver = nullptr;
21 
22  //Intervallgrenzen
23  double _xmin, _xmax;
24 
25  //mögliche Nullstelle nach jedem Iterationsschritt
26  double _currentRoot;
27 
28  //Ergebnis hat noch keinen gültigen Wert
29  std::optional<double> _result;
30 
31  // Status der Iteration
32  int _status = GSL_CONTINUE;
33 
34  //suche Nullstelle für diese Funktion (gsl-Funktion)
35  gsl_function F;
36  //obere Iterationsgrenze damit keine Endlosschleife entsteht
37  size_t MAX_STEPS = 100;
38 
45  inline int next_step(double epsabs, double epsrel) {
46  //nach jeder Iteration...
47  if (gsl_root_fsolver_iterate(_solver) != GSL_SUCCESS) {
48  throw std::runtime_error(nmx_msgx(_status));
49  }
50  //...ermittelte Nullstelle
51  _currentRoot = gsl_root_fsolver_root(_solver);
52  //untere Grenze des Intervalls
53  _xmin = gsl_root_fsolver_x_lower(_solver);
54  //obere Grenze des Intervalls
55  _xmax = gsl_root_fsolver_x_upper(_solver);
56  // ist die Bedingung
57  //|xmin-xmax| < eposabs + epsrel min(|xmin|,|xmax|)
58  //erfüllt?
59  _status = gsl_root_test_interval(_xmin, _xmax, epsabs, epsrel);
60  return _status;
61  }
62 
63 public:
70  template<class T>
71  RootBracketing(T &pobj, const gsl_root_fsolver_type *type = gsl_root_fsolver_bisection)
72  : _solver_type{ type } {
73  //gsl -Routine zur Lösung der Gleichung wird initialisiert
74  _solver = gsl_root_fsolver_alloc(_solver_type);
75  //definiere eine gsl-konforme Funktion
76  //zusätzlicher Parameter zeigt auf pobj
77  F.params = &pobj;
78  //sie ruft intern pobj auf und übergibt x
79  F.function = [](double x, void *params) -> double {
80  auto *myFn = static_cast<T *>(params);
81  return (*myFn)(x);
82  };
83  }
84 
89  if (_solver != nullptr) {
90  gsl_root_fsolver_free(_solver);
91  }
92  }
93 
98  inline bool converged() const { return _status == GSL_SUCCESS; }
99 
104  inline auto xminmax() const { return std::make_pair(_xmin, _xmax); }
105 
110  inline const char *method_used() const { //
111  return gsl_root_fsolver_name(_solver);
112  }
113 
123  template<class FN>
124  auto apply(double xmin, double xmax, FN fn, double epsabs, double epsrel) {
125  _xmin = xmin;
126  _xmax = xmax;
127  gsl_root_fsolver_set(_solver, &F, _xmin, _xmax);
128  for (size_t i = 1; i <= MAX_STEPS && _status == GSL_CONTINUE; ++i) {
129  next_step(epsabs, epsrel);
130  if (_status == GSL_SUCCESS) {
131  _result = _currentRoot;
132  }
133  fn(i, _xmin, _xmax, _currentRoot);
134  }
135  return _result;
136  }
137 
146  inline auto apply(double xmin, double xmax, double epsabs, double epsrel) {
147  _xmin = xmin;
148  _xmax = xmax;
149  gsl_root_fsolver_set(_solver, &F, _xmin, _xmax);
150  for (size_t i = 1; i <= MAX_STEPS && _status == GSL_CONTINUE; ++i) {
151  next_step(epsabs, epsrel);
152  if (_status == GSL_SUCCESS) {
153  _result = _currentRoot;
154  }
155  }
156  return _result;
157  }
158 
164  inline double result() const {
165  //teste Status der Variablen (für die Nullstelle)
166  Check::error_if(nmx_msg, !_result);
167  return *_result;
168  }
169 }; //RootBracketing
170 
176 {
177 private:
178  //gsl interne Struktur
179  const gsl_root_fdfsolver_type *_solverType;
180  //Algorithmus
181  gsl_root_fdfsolver *_solver = nullptr;
182  //suche Nullstelle für diese Funktion (gsl-Funktion)
183  gsl_function_fdf FDF;
184  //x_(i+1),x_i
185  double _xnew, _xold;
186  //Status der Iteration
187  int _status;
188  //Anzahl der Iterationen
189  size_t _iteration = 0;
190  //gefundene Nullstelle
191  std::optional<double> _foundRoot;
192 
193 public:
194  size_t MAX_STEPS = 100;
195 
196 private:
203  inline void next_step(double epsabs, double epsrel) {
204  _iteration++;
205  _status = gsl_root_fdfsolver_iterate(_solver);
206  //speichere zuletzt bekannte Nullstelle
207  _xold = _xnew;
208  //berechne neue Nullstelle
209  _xnew = gsl_root_fdfsolver_root(_solver);
210  //teste Konvergenz
211  _status = gsl_root_test_delta(_xnew, _xold, epsabs, epsrel);
212 
213  if (_status == GSL_SUCCESS) {
214  _foundRoot = _xnew;
215  }
216  }
217 
218 public:
223  template<typename T>
224  FDFSolver(T &obj, const gsl_root_fdfsolver_type *type = gsl_root_fdfsolver_newton) {
225  _solverType = type;
226  _solver = gsl_root_fdfsolver_alloc(_solverType);
227  //verbinde obj mit gsl
228  FDF.params = &obj;
229  //Funktion
230  FDF.f = [](double x, void *params) { //
231  return static_cast<T *>(params)->f(x);
232  };
233  //Ableitung
234  FDF.df = [](double x, void *params) { //
235  return static_cast<T *>(params)->df(x);
236  };
237  //Funktion und Ableitung in einem Aufruf
238  FDF.fdf = [](double x, void *params, double *f, double *df) {
239  T *obj = static_cast<T *>(params);
240  *f = obj->f(x);
241  *df = obj->df(x);
242  };
243  }
244 
248  inline ~FDFSolver() {
249  if (_solver != nullptr) {
250  gsl_root_fdfsolver_free(_solver);
251  }
252  }
253 
258  inline const char *method_used() const { //
259  return gsl_root_fdfsolver_name(_solver);
260  }
261 
266  inline bool converged() const { return _status == GSL_SUCCESS; }
267 
272  inline double result() const {
273  //teste Status der Variablen (für die Nullstelle)
274  Check::error_if(nmx_msg, !_foundRoot);
275  return *_foundRoot;
276  }
277 
285  inline auto apply(double startval, double epsabs = 0, double epsrel = 1e-3) {
286  _xnew = startval;
287  gsl_root_fdfsolver_set(_solver, &FDF, _xnew);
288  do {
289  next_step(epsabs, epsrel);
290  } while (_status == GSL_CONTINUE && _iteration < MAX_STEPS);
291 
292  return _foundRoot;
293  }
294 
302  template<class FN>
303  auto apply(double startval, FN fn, double epsabs = 0, double epsrel = 1e-3) {
304  _xnew = startval;
305  gsl_root_fdfsolver_set(_solver, &FDF, _xnew);
306  do {
307  next_step(epsabs, epsrel);
308  fn(_iteration, _xold, _xnew);
309 
310  } while (_status == GSL_CONTINUE && _iteration < MAX_STEPS);
311 
312  return _foundRoot;
313  }
314 }; //FDFSolver
315 
316 } // namespace nmx::gsl
auto xminmax() const
xminmax obere und untere Intervallgrenze
Definition: xroot.h:104
auto apply(double startval, FN fn, double epsabs=0, double epsrel=1e-3)
apply Nullstellensuche
Definition: xroot.h:303
const char * method_used() const
method_used
Definition: xroot.h:110
auto apply(double xmin, double xmax, FN fn, double epsabs, double epsrel)
apply startet Nullstellensuche
Definition: xroot.h:124
static void error_if(const std::string &s, bool arg)
error_if Fehler wenn Bedingung erfüllt ist
Definition: xerror.h:51
auto apply(double xmin, double xmax, double epsabs, double epsrel)
apply startet Nullstellensuche
Definition: xroot.h:146
bool converged() const
converged Status der Nullstellensuche
Definition: xroot.h:98
#define nmx_msg
Definition: xerror.h:113
bool converged() const
converged Status der Nullstellensuche
Definition: xroot.h:266
FDFSolver(T &obj, const gsl_root_fdfsolver_type *type=gsl_root_fdfsolver_newton)
FDFSolver Konstruktor.
Definition: xroot.h:224
double result() const
getRoot Abfrage der gefundenen Nullstelle
Definition: xroot.h:272
The RootBracketing class gsl-Klasse für das Bisektionsverfahren.
Definition: xroot.h:14
#define nmx_msgx(msg)
Definition: xerror.h:125
double result() const
result liefert die Nullstelle nur falls eine gefunden wurde, sonst wird eine Ausnahme ausgeworfen...
Definition: xroot.h:164
RootBracketing(T &pobj, const gsl_root_fsolver_type *type=gsl_root_fsolver_bisection)
RootBracketing Konstruktor.
Definition: xroot.h:71
const char * method_used() const
method_used
Definition: xroot.h:258
double f(double x, void *params)
f
Definition: x035.h:15
auto apply(double startval, double epsabs=0, double epsrel=1e-3)
apply Nullstellensuche
Definition: xroot.h:285
The FDFSolver class Nullstellensuche Funktion und ihre Ableitung werden benötigt. ...
Definition: xroot.h:175