x036.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "xdata.h"
4 #include "xode.h"
5 #include "xoutput.h"
6 #include "xphysics.h"
7 #include <cmath>
8 #include <gsl/gsl_errno.h>
9 #include <gsl/gsl_matrix.h>
10 #include <gsl/gsl_odeiv2.h>
11 #include <iostream>
12 #include <stdio.h>
13 
14 namespace nmx::apps::x036 {
15 
24 int func(double x, const double yin[], double yout[], void *params) {
25  (void) params;
26  yout[0] = yin[0] - 2 * x / yin[0];
27  return GSL_SUCCESS;
28 }
29 
35 double fexact(double x) {
36  return std::sqrt(2 * x + 1);
37 }
38 
42 inline void ex1() {
43  //Teil 1: Definition des Dgl-Systems
44  gsl_odeiv2_system sys = {
45  func, // rechte Seite des Dgl-Systems
46  nullptr, //Jacobi-Matrix
47  1, //Anzahl der Gleichungen des Dgl-Systems
48  nullptr //zusätzliche Parameter
49  };
50  //Teil2: Name des Lösungsalgorithmus
51  const gsl_odeiv2_step_type *type = gsl_odeiv2_step_rk4;
52  //Initialisierung des Lösungsalgorithmus
53  gsl_odeiv2_driver *d = //
54  gsl_odeiv2_driver_alloc_y_new(&sys, // Dgl-System
55  type, // Lösungsalgorithmus
56  1e-6, // Schrittweite (Start)
57  1e-6, // absoluter Fehler
58  0.0); // relativer Fehler
59  //Teil 3: Berechnung der Lösung
60  double x = 0;
61  double y[] = { 1.0 };
62  for (double xi = 0; xi < 2; xi += 0.25) {
63  int status = gsl_odeiv2_driver_apply(d, &x, xi, y);
64  if (status != GSL_SUCCESS) {
65  printf("error, return value=%d\n", status);
66  break;
67  }
68 
69  printf("%.5e %.5e %.5e\n", x, y[0], fexact(x));
70  }
71  //Teil 4: Ressourcen werden freigegeben
72  gsl_odeiv2_driver_free(d);
73 }
74 
80 inline auto get_output_stream(const char *name, Format fmt) {
81  return Output::get_stream("x036", fmt, name);
82 }
83 
87 inline void ode1() {
88  //eindimensionale Gleichung, kein ()-Operator
89  //zweiter Template -Parameter false
90  using ODESolver = gsl::Odeiv2<1, false>;
91  using Data = Data<4>;
92  //Datenobjekt
93  Data data;
94 
95  //die DGL mit Schnittstelle zur gsl
96  struct MyODE {
97  int odefn(double t, const double fin[], double fout[]) {
98  fout[0] = fin[0] - 2 * t / fin[0];
99  return GSL_SUCCESS;
100  }
101  } myObj;
102 
103  //analytisch hergeleitete Lösung
104  auto exactSolutionFn = [](double t) { return sqrt(2 * t + 1); };
105 
106  //numerische Lösung der DGL
107  ODESolver ode{ myObj, 1e-2, 1e-9, 0 };
108  ode.set_init_conditions(0, { 1 });
109  double t = 0, dt = 0.25;
110  while (t < 2.5) {
111  const double numSolution = ode[0];
112  const double exactSolution = exactSolutionFn(t);
113  const double absError = abs(numSolution - exactSolution);
114  data += { t, numSolution, exactSolution, absError };
115  t += dt;
116  //nächste Lösung
117  ode.solve(t);
118  }
119 
120  std::ofstream mystable = get_output_stream(__func__, Output::latex);
121  data.save(mystable, Output::latex);
122 }
123 
127 inline void ode2() {
128  // zweiter Template-Parameter true
129  // die Implementierung des DGL-Systems erfordert
130  // einen () -Operator
131  using ODESolver = gsl::Odeiv2<2, true>;
132  using Data = nmx::Data<7>;
133 
134  const double acceleration = 2;
135  const double x0 = 0, v0 = 0;
136 
137  Data data;
138  //Implementierung des DGL-Systems
139  auto obj = [](double t, const double fin[], double fout[]) {
140  (void) t;
141  fout[0] = fin[1];
142  fout[1] = 2;
143  return GSL_SUCCESS;
144  };
145 
146  //exakte Lösung
147  auto v = [&acceleration](double t) { //
148  return acceleration * t;
149  };
150  auto x = [&acceleration](double t) { //
151  return 0.5 * acceleration * pow(t, 2);
152  };
153 
154  //numerische Lösung
155  ODESolver myOde{ obj, 1e-2, 1e-9, 0 };
156  myOde.set_init_conditions(0, { x0, v0 });
157  double t = 0, dt = 0.5;
158  while (t < 5) {
159  const double xnum = myOde[0];
160  const double xexact = x(t);
161  const double vnum = myOde[1];
162  const double vexact = v(t);
163  const double verror = abs(vnum - vexact);
164  const double xerror = abs(xnum - xexact);
165 
166  //registriere Daten
167  data += { t, xnum, xexact, xerror, vnum, vexact, verror };
168  t += dt;
169  //berechne Lösung für den nächsten Schritt
170  myOde.solve(t);
171  }
172  //Ausgabe
173  std::ofstream mystable = get_output_stream(__func__, Output::latex);
174  data.save(mystable, Output::latex);
175 }
176 
180 void ode3() {
181  // Daten der Aufgabe
182  const double mass = 40.0;
183  const double mu = 0.4;
184  const double force = 200.0;
185  const double s = 5.0;
186  const double g = gravitation::Earth::g;
187  //Anfangsbedingungen
188  const double x0 = 0, v0 = 0;
189 
190  //**-----------------------------------------------
191  //Lösungen über den Arbeitssatz zum Vergleich
192  const double a = force / mass - mu * g;
193  const double vs = std::sqrt(2 * a * s);
194  const double tval = vs / a;
195  std::cout << std::setw(3) << tval << "," //
196  << std::setw(3) << vs << std::endl;
197 
198  //**---------------------------------------------
199  //das Differenzialgleichungssystem, durch das =
200  // in der Erfassungsliste, können alle Aufgabendaten
201  //innerhalb der lambda-Funktion genutzt werden.
202  auto acceleration = [=](double t, //
203  const double fin[],
204  double fout[]) {
205  (void) t;
206  fout[0] = fin[1];
207  fout[1] = a;
208  return GSL_SUCCESS;
209  };
210 
211  //**----------------------------------------------
212  //lege Dgl fest, der zweite Template-Parameter muss true sein,
213  // da das System als lambda implementiert ist.
214  using Ode = gsl::Odeiv2<2, true>;
215  using Data = nmx::Data<4>;
216  Data data;
217  Ode ode{ acceleration, 1e-2, 1e-9, 0 };
218  ode.set_init_conditions(0, { x0, v0 });
219  double t = 0, dt = 0.01;
220  //berechne solange Lösungen bis die Strecke s ist
221  while (ode[0] < s) {
222  data += { t, ode[0], ode[1], 0.5 * mass * pow(ode[1], 2) };
223  t += dt;
224  ode.solve(t);
225  }
226 
227  //**---------------------------------------------
228  //Ausgabe
229  std::ofstream mystable = get_output_stream(__func__, Output::latex);
230  data.select_total_rows(5).save(mystable, Output::latex);
231  std::ofstream mysplot = get_output_stream(__func__, Output::plot);
232  data.save(mysplot, Output::plot);
233 }
234 
235 } // namespace nmx::apps::x036
void ex1()
ex1 Beispiel (Vorlage)
Definition: x036.h:42
auto get_output_stream(const char *name, Format fmt)
get_output_stream generiere Ausgabestrom
Definition: x036.h:80
void save(std::ostream &ofs, Format fmt) const
save Schreibe Tabelle in Datei
Definition: xdata.h:160
The Data class Eine Klasse für Zahlentabellen mit fester Anzahl von Spalten. Die Anzahl der Reihen wä...
Definition: xdata.h:22
int func(double x, const double yin[], double yout[], void *params)
func rechte Seite der Differenzialgleichung
Definition: x036.h:24
The Odeiv2 class numerische Lösung eines Systems von N Differenzialgleichungen Schnittstelle zur gsl...
Definition: xode.h:20
void ode2()
ex2 DGL 2. Grades
Definition: x036.h:127
static std::ofstream get_stream(const std::string &fname)
get_output_stream Öffnen einer Ausgabedatei falls die Datei nicht geöffnet werden kann wird ein Fehle...
Definition: xoutput.h:29
void ode3()
ode3 Konstante Kraft wirkt auf Holzblock
Definition: x036.h:180
auto select_total_rows(size_t n, size_t start=0, bool l=true) const
get_total_rows generiere View mit eine Instanz vom Typ View bestimmter Anzahl von Spalten ...
Definition: xdata.h:338
void ode1()
ode Lösung einer DGL
Definition: x036.h:87
The Format class Formatierte Ausgabe von Arrays.
Definition: xfmt.h:10
static const Format latex
Definition: xoutput.h:17
double fexact(double x)
fexact exakte Lösung
Definition: x036.h:35
static constexpr double g
Definition: xphysics.h:20
static const Format plot
Definition: xoutput.h:18