~~NOTOC~~
Falls numpy etc. auf Schulrechnern nicht verfügbar:
https://trinket.io/embed/python3/a5bd54189b
====== Wellengleichung ======
(alle Programme recht rasch erstellt, geht sicher eleganter...) Die Mathematik und Formeln für die Iteration sind hier noch nicht dokumentiert (bisher an Tafel erklärt). Wellengleichung $u_{tt}=\Delta u$ bzw. $v=u_t$ und $v_t=\Delta u$.
{{:lehrkraefte:snr:informatik:glf4-23:schwingende-saite.gif?400|}}
{{:lehrkraefte:snr:informatik:glf4-23:trommel.gif?400|}}
===== 1-dimensional: Simulation einer schwingenden Saite =====
=== Lernen, wie man den Graphen einer Funktion zeichnet (function plot) ===
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colormaps
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
# maximale x-Koordinate.
n = 40
# Gezeichnet werden soll die folgende Funktion f.
# Bitte damit herumspielen.
def f(x):
return 100 * np.sin(x * 3 * np.pi / n)
# Die Liste u wird die Funktionswerte von f an allen ganzzahligen Argumenten zwischen 0 und n-1 enthalten.
# Zuerst wird sie initialisiert (alle Einträge Null).
u = np.zeros(n)
# Dann werden die Funktionswerte von f berechnet.
for x in range(n):
u[x] = f(x)
fig, ax = plt.subplots()
# Ausdehnung der y-Achse.
ax.set(xlim=(0, n), ylim=(-100, 100))
# Die Plot-Funktion benötigt zu jedem y-Wert den zugehörigen x-Wert.
# Der folgende Befehl erstellt eine Liste aller ganzan Zahlen von 0 bis n-1.
x_werte = np.linspace(0, n, n)
ax.plot(x_werte, u)[0]
plt.show()
=== Lernen, wie man den Graphen einer zeitabhängigen Funktion animiert zeichnet ===
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colormaps
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
# maximale x-Koordinate.
n = 40
iterationen = 1000
geschwindigkeit = 20 # je höher, desto schneller
# In der folgenden Funktion ist i die Iterationsvariable = die Zeit.
# Zur Zeit i soll die Funktion f(i, ?) gezeigt werden.
# Bitte damit herumspielen.
def f(i, x):
return i * x / n
# u enthält die Funktionswerte zu allen Zeiten i und Orten x.
# Initialisierung.
u = np.zeros((iterationen + 1, n))
# Berechnung der Werte.
for i in range(1, iterationen + 1):
for x_werte in range(1, n):
u[i, x_werte] = f(i, x_werte)
fig, ax = plt.subplots()
x_werte = np.linspace(0, n, n)
def animate(i):
ax.cla()
ax.set(xlim=(0, n), ylim=(-100, 100))
ax.plot(x_werte, u[geschwindigkeit * i])[0]
anim = FuncAnimation(fig, animate, interval=1, frames=iterationen // geschwindigkeit)
# anim = FuncAnimation(fig, animate, frames=iterationen)
plt.show()
=== Schwingende Saite simulieren ===
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colormaps
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
# Grösse des quadratischen Feldes
n = 40
iterationen = 1000
geschwindigkeit = 20 # je höher, desto schneller
delta_t = 0.01
# Auslenkungen u und Geschwindigkeiten v auf Null setzen für alle Zeiten und $x$-Werte.
u = np.zeros((iterationen + 1, n))
v = np.zeros((iterationen + 1, n))
# Randwerte
for i in range(iterationen):
# Die schwingende Saite ist am Rand befestigt:
# Auslenkung am Rand ist zu jedem Zeitupunkt Null.
u[i, 0] = 0
u[i, n - 1] = 0
# Geschwindigkeit am Rand ist zu jedem Zeitpunkt Null.
v[i, 0] = 0
v[i, n - 1] = 0
print("Randwerte initialisiert (Werte am Rand des Intervalls zu allen Zeiten)")
def f(x):
return np.sin(3 * np.pi * x)
# Aufgabe: Statt dieser Sinusfunktion nimm andere Funktionen auf dem Intervall [0, 1].
# Empfehlung: Die Randwerte (also die Werte bei 0 und 1) sollten Null sein.
# Die Funktion sollte Werte im Intervall [-1, 1] annehmen.
# Vorschläge: Sinusfunktion mit anderer Sequenz, stückweise lineare Funktion, Parabel.
# Startwerte zur Zeit t=0:
for x_werte in range(n):
# Auslenkung zur Zeit t=0 an der Stelle x:
u[0, x_werte] = 100 * f(x_werte / (n - 1))
# Geschwindigkeit zur Zeit t=0 an der Stelle x:
v[0, x_werte] = 0
print("Startwerte initialisiert (Positionen und Geschwindigkeiten zur Zeit t=0)")
# Start der Simulation
for i in range(1, iterationen + 1):
if i % 100 == 0:
print(f"Berechnung der Iteration {i}")
for x_werte in range(1, n - 1):
v[i, x_werte] = v[i - 1, x_werte] + 0.05
u[i, x_werte] = u[i - 1, x_werte] + v[i - 1, x_werte] * delta_t
fig, ax = plt.subplots()
x_werte = np.linspace(0, n, n)
def animate(i):
ax.cla()
ax.set(xlim=(0, n), ylim=(-100, 100))
ax.plot(x_werte, u[geschwindigkeit * i])[0]
anim = FuncAnimation(fig, animate, interval=1, frames=iterationen // geschwindigkeit)
plt.show()
==== Wikipedia dazu ====
https://de.wikipedia.org/wiki/Saitenschwingung
===== 2-dimensional: Schwingung einer Trommel/Membran simulieren =====
=== Lernen, wie man eine Fläche zeichnet (surface plot) ===
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colormaps
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
# Grösse des quadratischen Feldes
n = 40
u = np.zeros((n, n))
def f(z, s):
return np.sin(np.pi * z) * np.sin(2 * np.pi * s)
for z in range(1, n - 1):
for s in range(1, n - 1):
u[z, s] = 100 * f(z / (n-1), s/(n-1))
(z, s) = np.meshgrid(np.arange(n), np.arange(n))
fig = plt.figure()
koordinatensystem = fig.add_subplot(projection = '3d')
koordinatensystem.set_zlim(-100, 100)
plot = koordinatensystem.plot_surface(z, s, u, cmap = plt.cm.jet, vmin=-100, vmax = 100)
# fig.colorbar(plot, ax = koordinatensystem, shrink = 0.5, aspect = 10)
fig.colorbar(plot, ax = koordinatensystem)
plt.show()
=== Simulation einer schwingenden Trommel ===
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import colormaps
import matplotlib.animation as animation
from matplotlib.animation import FuncAnimation
# Grösse des quadratischen Feldes
n = 40
# iterationen = 2600
iterationen = 1000
delta_t = 0.02
geschwindigkeit = 40
u = np.zeros((iterationen + 1, n, n))
v = np.zeros((iterationen + 1, n, n))
# Randwerte
for i in range(iterationen):
for s in range(n):
u[i, 0, s] = 0
u[i, n - 1, s] = 0
v[i, 0, s] = 0
v[i, n - 1, s] = 0
for z in range(n):
u[i, z, 0] = 0
u[i, z, n - 1] = 0
v[i, z, 0] = 0
v[i, z, n - 1] = 0
print("Randwerte initialisiert (Werte am Rand des Quadrats zu allen Zeiten)")
def f(z, s):
return np.sin(np.pi * z) * np.sin(2 * np.pi * s)
# Startwerte
for z in range(n):
for s in range(n):
u[0, z, s] = 100 * f(z / (n -1), s / (n - 1))
v[0, z, s] = 0
print("Startwerte initialisiert (Positionen und Geschwindigkeiten zur Zeit t=0)")
# Start der Simulation
for i in range(1, iterationen + 1):
if i % 100 == 0:
print(f"Simuliert bis zur Zeit {i * delta_t:.1f} bzw. bis Iteration {i}")
for z in range(1, n - 1):
for s in range(1, n - 1):
v[i, z, s] = v[i - 1, z, s] + 0.05
u[i, z, s] = u[i - 1, z, s] + v[i - 1, z, s] * delta_t
(z, s) = np.meshgrid(np.arange(n), np.arange(n))
fig = plt.figure()
koordinatensystem = fig.add_subplot(projection = '3d')
koordinatensystem.set_zlim(0, 100)
plot = koordinatensystem.plot_surface(z, s, u[0], cmap = plt.cm.jet, vmin=-100, vmax = 100)
# fig.colorbar(plot, ax = koordinatensystem, shrink = 0.5, aspect = 10)
fig.colorbar(plot, ax = koordinatensystem)
def animiere(i):
j = i * geschwindigkeit
if i % 10 == 0:
print(f'Animationsbild zum Iterationsschritt {j}')
koordinatensystem.cla()
plt.title(f"Heatmap, Zeit t = {j * delta_t:.3f}")
plt.xlabel("s")
plt.ylabel("z")
koordinatensystem.set_zlim(-100, 100)
plot = koordinatensystem.plot_surface(z, s, u[i * geschwindigkeit], cmap = plt.cm.jet, vmin=-100, vmax = 100)
return fig
anim = animation.FuncAnimation(fig, animiere, interval=1, frames=iterationen // geschwindigkeit, repeat=False)
anim.save("trommel.gif")
plt.show()
=== Simulation ===
Die beim Simulieren nötige Formel findet sich hier:
# Start der Simulation
for i in range(1, iterationen + 1):
if i % 100 == 0:
print(f"Simuliert bis zur Zeit {i * delta_t:.1f} bzw. bis Iteration {i}")
for z in range(1, n - 1):
for s in range(1, n - 1):
v[i, z, s] = v[i - 1, z, s] + ((u[i - 1, z - 1, s] - 2 * u[i - 1, z, s] + u[i - 1, z + 1, s]) + (u[i - 1, z, s - 1] - 2 * u[i - 1, z, s] + u[i - 1, z, s + 1])) * delta_t
u[i, z, s] = u[i - 1, z, s] + v[i - 1, z, s] * delta_t