Das folgende System wird für verschiedene Anfangswerte simuliert, um zu zeigen, dass alle Trajektorien in einen Grenzzyklus einlaufen:
\begin{equation*} \ddot x(t) - 2 \frac{c}{m}(1 - x^2(t))\dot x(t) + \frac{k}{m} x(t) = 0 \end{equation*}mit $c, k, m > 0$. Es handelt sich um die van-der-Pol-Gleichung.
In den Zellen 2 und 3 können Sie Einstellungen vornehmen, die die Simulation beeinflussen (sofern dieses Notebook lokal oder auf mybinder läuft).
Die aktuelle Fassung dieses Notebooks findet sich in folgendem Repositorium:
https://gitlab.hrz.tu-chemnitz.de/rst/public/teaching/nl1-nbviewer-content
Sie können zur Entwicklung/ Verbesserung über Merge Requests beitragen!
Copyright (c) 2019-2022 Max Pritzkoleit und Jan Winkler, TU Dresden, Germany
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details:
https://www.gnu.org/licenses/gpl-3.0.txt.
import numpy as np
import scipy.integrate as sci
import matplotlib.pyplot as plt
import matplotlib.animation as mpla
import os
from dataclasses import dataclass
Setzen Sie DoAnmim
auf True
, damit am Ende der Simulation eine Animation gestartet wird. Dies setzt voraus, dass die Bibliothek ffmpeg installiert ist. Sie müssen diese ggf. installieren und den Pfad in der nachfolgenden Zelle bekannt machen:
DoAnimation = False
# Unter Windows den Pfad bitte korrekt einstellen
if os.name == 'nt':
plt.rcParams['animation.ffmpeg_path'] = 'C:\\Progs\\ffmpeg\\bin\\ffmpeg.exe'
@dataclass
class sim_para:
t0 = 0 # start time
tf = 50 # final time
dt = 0.04 # step-size
Definition der rechten Seit der Dgl. Dazu wird die Dgl. zweiter Ordnung in zwei Dgls. erster Ordnung mittels der Transformation $x_1 := x$, $x_2 := \dot x$ überführt.
def ode(t, x):
m = 1
c = 0.1
K = 0.4
x1, x2 = x # state vector
# dxdt = f(x):
dxdt = np.array([x2,
-K/m*x1-2*c/m*(x1**2-1)*x2])
return dxdt
In dieser Funktion wird definiert, wie die Animation durchgeführt wird. Dazu wird ein FuncAnimation
-Objekt der matplotlib-Bibliothek verwendet.
def sys_animation(sols, t):
""" Funktion zur Animation des Ergebnisses """
%matplotlib widget
fig2, ax = plt.subplots()
ax.set_xlim(-3,3)
ax.set_ylim(-3,3)
ax.set_aspect('equal')
ax.set_xlabel(r'$y_1$')
ax.set_ylabel(r'$y_2$')
colors = ["r", "b", "g", "y"]
# Axis handles
lines = []
for i, xi in enumerate(sols):
lines.append(xi)
lines[i], = ax.plot([], [], colors[i])
def init():
""" Init-Funktion für Matplotlib Animation """
for line in lines:
line.set_data([],[])
return lines
def animate(i):
""" Eigentliche Zeichenfunktion für Matplotlib Animation """
k = i % len(t)
for j, line in enumerate(lines):
line.set_xdata(sols[j][0, 0:k])
line.set_ydata(sols[j][1, 0:k])
return lines
# Animator
anim = mpla.FuncAnimation(fig2, animate, init_func=init, frames=len(t) + 1,
interval=5, repeat=True, blit=True)
plt.grid()
plt.show()
return anim
Die Simulation erfolgt mit variabler Schrittweite, es werden jedoch an den in tt
definierten Zeitpunkten Lösungsergebnisse angefordert, um einen schönen und glatten Verlauf der Kurven zu erhalten.
Insgesamt werden vier Simulationen, startend bei x0A
bis x0D
, durchgeführt.
tt = np.arange(sim_para.t0, sim_para.tf + sim_para.dt, sim_para.dt)
# Anfangszustand
x0A = [0, .3]
x0B = [1, 0]
x0C = [1.5, 1.5]
x0D = [-.5, .5]
x0_vec = [x0A, x0B, x0C, x0D]
# Simulation
outputs = []
for x0 in x0_vec:
sol = sci.solve_ivp(ode, [sim_para.t0, sim_para.tf], x0, max_step=sim_para.dt)
outputs.append(sol.y)
Animation bzw. statisch
if DoAnimation:
anim = sys_animation(outputs, tt)
else:
#%matplotlib widget
plt.rcParams['font.size'] = '16'
plt.figure(figsize=(10, 8))
for out in outputs:
plt.plot(out[0, :], out[1, :])
plt.plot(out[0, 0], out[1, 0], color='k', marker='x') # Anfangswert
plt.xlabel('$x_1 = x$')
plt.ylabel('$x_2 = \dot x$')
plt.grid()