Aufgaben

Lösung zu Aufgabe 10.9

In der Animation erkennt man sehr deutlich, warum sich im unteren Bereich nun keine Wellenfront mehr ausbilden kann: Da die Ausbreitungsgeschwindigkeit der Wellen hier größer ist, überholen sich die halbkreisförmigen Wellen oberhalb eines bestimmten Einfallswinkels gegenseitig, sodass man keine gemeinsame Tangente mehr an diese Halbkreise anlegen kann. Da sich im unteren Bereich keine Welle ausbreiten kann, muss die gesamte Welle reflektiert werden.

Link    Zur fertigen Animation.

Die zweite Animation zeigt den Fall, dass der Einfallswinkel exakt gleich dem Grenzwinkel für die Totalreflektion ist, im Wellenbild. Da die Ausbreitungsgeschwindigkeit im unteren Bereich größer ist, als im oberen Bereich und die Wellenberge und -täler stetig ineinander übergehen müssen, muss die Welle im unteren Bereich flacher verlaufen. Im Grenzfall der Totalreflektion muss die Welle im unteren Bereich schon parallel zur Grenzfläche verlaufen. Bei noch größeren Einfallswinkeln kann es somit im unteren Bereich keine Welle mehr geben, die die Stetigkeitsbedingung erfüllt.

Link    Zur fertigen Animation.

Download    Wellen/Loesungen/totalreflexion_huygens.py

"""Animation zur Totalreflexion mit dem huygensschen Prinzip. """

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.animation

# Ausbreitungsgeschwindigkeit in den beiden Medien [m/s].
c1 = 0.7
c2 = 1.0

# Einfallswinkel [rad].
alpha = np.radians(50)

# Dargestellter Ortsbereich -xlim ... xlim, -ylim ... ylim [m].
xlim = 15
ylim = 15

# Zeitschrittweite [s].
dt = 0.05

# Anzahl der Strahlen.
n_strahlen = 7

# Breite des einfallenden Strahlenbündes [m].
breite = 10.0

# Anfangsabstand des Mittelstrahls von der Grenzfläche [m].
dist0 = 21.0

# Berechne die Startpunkte r_start der einzelnen Strahlen.
b = np.linspace(-breite / 2, breite / 2, n_strahlen)
r_start = np.empty((n_strahlen, 2))
r_start[:, 0] = -dist0 * np.sin(alpha) + b * np.cos(alpha)
r_start[:, 1] = dist0 * np.cos(alpha) + b * np.sin(alpha)

# Berechne die Auftreffzeitpunkte der einzelnen Strahlen.
t_auf = (dist0 + b * np.tan(alpha)) / c1

# Richtungsvektor der einfallenden und reflektierten Strahlen.
e1 = np.array([np.sin(alpha), -np.cos(alpha)])
er = np.array([np.sin(alpha), np.cos(alpha)])

# Berechne die Auftreffzeitpunkte der Strahlen.
r_auf = r_start + t_auf.reshape(-1, 1) * c1 * e1

# Erzeuge eine Figure und eine Axes.
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_xlim(-xlim, xlim)
ax.set_ylim(-ylim, ylim)
ax.set_aspect('equal')
ax.set_xlabel('x [m]')
ax.set_ylabel('y [m]')

# Erzeuge leere Listen für die einfallenden und reflektierten
# Strahlen sowie für die Kreisbögen der Elementarwellen.
strahl_1, strahl_r = [], []
kreis_r, kreis_t = [], []

# Erzeuge die entsprechenden Grafikelemente und füge sie den
# Listen hinzu.
for i in range(n_strahlen):
    # Erzeuge einen einfallenden Lichtstrahl.
    l, = ax.plot([0], [0])
    farbe = l.get_color()
    strahl_1.append(l)

    # Erzeuge den reflektierten und transmittierten Lichtstrahl
    # mit der gleichen Farbe, wie der entsprechende einfallende
    # Lichtstrahl.
    lr, = ax.plot([0], [0], ':', color=farbe)
    strahl_r.append(lr)

    # Erzeuge die Kreisbögen für die Elementarwellen.
    kr = mpl.patches.Arc(r_auf[i], width=1, height=1,
                         theta1=0, theta2=180,
                         fill=False, color=farbe)
    kt = mpl.patches.Arc(r_auf[i], width=1, height=1,
                         theta1=180, theta2=360,
                         fill=False, color=farbe)
    ax.add_artist(kr)
    ax.add_artist(kt)
    kreis_r.append(kr)
    kreis_t.append(kt)

# Färbe die obere Hälfte des Koordinatensystems hellgrau ein.
rec = mpl.patches.Rectangle((-xlim, 0),2 * xlim, ylim,
                            color='0.9', zorder=0)
ax.add_artist(rec)

# Fäbe die untere Hälfte des Koordinatensystem etwas dunkler ein.
rec2 = mpl.patches.Rectangle((-xlim, -ylim), 2 * xlim, ylim,
                             color='0.8', zorder=0)
ax.add_artist(rec2)


def update(n):
    # Berechne den aktuellen Zeitpunkt.
    t = dt * n

    # Aktualisiere die einfallenden Strahlen.
    for strahl1, r0, ta in zip(strahl_1, r_start, t_auf):
        p = np.array([r0, r0 + c1 * min(t, ta) * e1])
        strahl1.set_data(p.T)

    # Aktualisiere die reflektierten Strahlen.
    for strahl, ra, ta in zip(strahl_r, r_auf, t_auf):
        t1 = max(0, (t - ta))
        p = np.array([ra, ra + c1 * t1 * er])
        strahl.set_data(p.T)

    # Aktualisiere die Kreise.
    for k1, k2, ta in zip(kreis_r, kreis_t, t_auf):
        if t > ta:
            k1.width = k1.height = 2 * (t - ta) * c1
            k2.width = k2.height = 2 * (t - ta) * c2
        k1.set_visible(t > ta)
        k2.set_visible(t > ta)

    return strahl_1 + strahl_r + kreis_r + kreis_t


# Erstelle die Animation und zeige die Grafik an.
ani = mpl.animation.FuncAnimation(fig, update,
                                  interval=30, blit=True)
plt.show()

Download    Wellen/Loesungen/totalreflexion_welle.py

"""Brechungsgesetz mit ebenen Wellen. """

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.animation

# Zeitschrittweite [s].
dt = 0.02

# Frequenz der Sender [Hz].
f = 1.0

# Ausbreitungsgeschwindigkeit der Welle [m/s].
c1 = 3.5
c2 = 5.0

# Wir wählen den Einfallswinkel so, dass er genau dem Grenzwinkel
# für die Totalreflexion entspricht.
alpha = np.arcsin(c1 / c2)

# Austrittswinkel der gebrochenen Strahlen nach Snellius [rad].
beta = np.arcsin(np.sin(alpha) * c2 / c1)

# Berechne die Kreisfrequenz und die Wellenzahlvektoren beider
# Wellen.
omega = 2 * np.pi * f
k1 = omega / c1 * np.array([np.sin(alpha), -np.cos(alpha)])
k2 = omega / c2 * np.array([np.sin(beta), -np.cos(beta)])

# Wir wollen die Wellenfunktionen auf einem 200 x 200 Raster
# von x = -15 m ... +15m und y = -15m .. +15m auswerten.
x1 = np.linspace(-15, 15, 500)
y1 = np.linspace(-15, 15, 500)
x, y = np.meshgrid(x1, y1)

# Erzeuge ein 200 x 200 x 2 - Array, das für jeden Punkt den
# Ortsvektor beinhaltet.
r = np.stack((x, y), axis=2)

# Erzeuge eine Figure und eine Axes.
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_aspect('equal')
ax.set_xlabel('x [m]')
ax.set_ylabel('y [m]')

# Stelle eine Array als Bild dar.
image = ax.imshow(0 * x, origin='lower',
                  extent=(np.min(x1), np.max(x1),
                          np.min(y1), np.max(y1)),
                  cmap='jet', clim=(-2, 2),
                  interpolation='bicubic')

# Zeichne eine dünne schwarze Linie, die die Grenze der beiden
# Gebiete darstellt.
linie, = ax.plot([np.min(x1), np.max(x1)], [0, 0], '-k',
                 linewidth=0.5, zorder=5)

# Füge einen Farbbalken hinzu.
fig.colorbar(image, label='Auslenkung [a.u.]')


def update(n):
    # Bestimme die aktuelle Zeit.
    t = dt * n

    # Werte die beiden Wellenfunktionen aus.
    u1 = np.cos(r @ k1 - omega * t)
    u2 = np.cos(r @ k2 - omega * t)

    # Erzeuge ein Array, das in der oberen Halbebene die Welle
    # u1 darstellt und in der unteren Halbebene die Welle u2.
    u = u1
    u[y < 0] = u2[y < 0]

    # Aktualisiere die Bilddaten.
    image.set_data(u)
    return image, linie


# Erstelle die Animation und zeige die Grafik an.
ani = mpl.animation.FuncAnimation(fig, update,
                                  interval=30, blit=True)
plt.show()