Aufgaben

Lösung zu Aufgabe 11.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 Totalreflexion 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 Totalreflexion 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)
# Anzahl der Strahlen.
n_strahlen = 7
# Breite des einfallenden Strahlenbündes [m].
breite = 10.0
# Anfangsabstand des Mittelstrahls von der Grenzfläche [m].
abstand = 21.0
# Dargestellter Bereich in x- und y-Richtung: -xy_max bis +xy_max.
xy_max = 15.0
# Zeitschrittweite [s].
dt = 0.05

# Bestimme die normierten Richtungsvektoren der einfallenden,
# der reflektierten und der gebrochenen Strahlen.
e_ein = np.array([np.sin(alpha), -np.cos(alpha)])
e_ref = np.array([np.sin(alpha), np.cos(alpha)])

# Bestimme einen Einheitsvektor, der senkrecht auf dem einfallenden
# Strahl steht.
e_ein_senkrecht = np.array([np.cos(alpha), np.sin(alpha)])

# Berechne die Startpunkte der einzelnen Strahlen. Die Strahlen
# sollen parallel einlaufen und gleichmäßig über die Strahlbreite
# verteilt sein.
b = np.linspace(-breite / 2, breite / 2, n_strahlen)
startorte = b.reshape(-1, 1) * e_ein_senkrecht - abstand * e_ein

# Berechne die Auftreffzeitpunkte der einzelnen Strahlen. Diese
# ergeben sich aus der Bedingung y = 0.
auftreffzeiten = -startorte[:, 1] / (c1 * e_ein[1])

# Berechne die Auftrefforte der Strahlen auf der Grenzfläche.
auftrefforte = (startorte +
                c1 * auftreffzeiten.reshape(-1, 1) * e_ein)

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

# Erzeuge leere Listen für die einfallenden, reflektierten und
# transmittierten Strahlen sowie für die Kreisbögen der
# Elementarwellen.
strahlen_ein = []
strahlen_ref = []
kreise_ref = []
kreise_geb = []

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

    # Erzeuge den reflektierten Lichtstrahl mit
    # der jeweils gleichen Farbe, wie der einfallende Lichtstrahl.
    farbe = strahl_ref.get_color()
    strahlen_ref.extend(ax.plot([], [], ':', color=farbe))

    # Erzeuge die Kreisbögen für die Elementarwellen der Reflexion.
    kreis_ref = mpl.patches.Arc(auftrefforte[i], width=1, height=1,
                                theta1=0, theta2=180,
                                visible=False,
                                fill=False, color=farbe)
    ax.add_patch(kreis_ref)
    kreise_ref.append(kreis_ref)

    # Erzeuge die Kreisbögen für die Elementarwellen der Brechung.
    kreis_geb = mpl.patches.Arc(auftrefforte[i], width=1, height=1,
                                theta1=180, theta2=360,
                                visible=False,
                                fill=False, color=farbe)
    ax.add_patch(kreis_geb)
    kreise_geb.append(kreis_geb)

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

# Färbe die untere Hälfte des Koordinatensystems etwas dunkler ein.
hintergrund_unten = mpl.patches.Rectangle((-xy_max, -xy_max),
                                          2 * xy_max, xy_max,
                                          color='0.8', zorder=0)
ax.add_patch(hintergrund_unten)


def update(n):
    """Aktualisiere die Grafik zum n-ten Zeitschritt."""
    # Berechne den aktuellen Zeitpunkt.
    t = dt * n

    # Aktualisiere die einfallenden Strahlen.
    for strahl, r, t0 in zip(strahlen_ein,
                             startorte, auftreffzeiten):
        punkte = np.array([r, r + c1 * min(t, t0) * e_ein])
        strahl.set_data(punkte.T)

    # Aktualisiere die reflektierten Strahlen.
    for strahl, r, t0 in zip(strahlen_ref,
                             auftrefforte, auftreffzeiten):
        punkte = np.array([r, r + c1 * max(0, (t - t0)) * e_ref])
        strahl.set_data(punkte.T)

    # Aktualisiere die Kreise in der oberen Halbebene.
    for kreis, t0 in zip(kreise_ref, auftreffzeiten):
        if t > t0:
            kreis.width = kreis.height = 2 * (t - t0) * c1
        kreis.set_visible(t > t0)

    # Aktualisiere die Kreise in der unteren Halbebene.
    for kreis, t0 in zip(kreise_geb, auftreffzeiten):
        if t > t0:
            kreis.width = kreis.height = 2 * (t - t0) * c2
        kreis.set_visible(t > t0)

    return (strahlen_ein + strahlen_ref +
            kreise_ref + kreise_geb)


# 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 ebener Wellen im Grenzfall der Totalreflexion."""

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 = 0.25
# Ausbreitungsgeschwindigkeit der Welle [m/s].
c1 = 3.5
c2 = 5.0
# Wählen den Einfallswinkel so, dass er genau dem Grenzwinkel
# für die Totalreflexion entspricht.
alpha = np.arcsin(c1 / c2)
# Dargestellter Bereich in x- und y-Richtung: -xy_max bis +xy_max.
xy_max = 15.0
# Anzahl der Punkte in jeder Koordinatenrichtung.
n_punkte = 500

# Wir wollen die Wellenfunktionen auf einem Raster der angegebenen
# Größe auswerten.
x_lin = np.linspace(-xy_max, xy_max, n_punkte)
y_lin = np.linspace(-xy_max, xy_max, n_punkte)
x, y = np.meshgrid(x_lin, y_lin)

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

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

# Berechne die Kreisfrequenz und die Wellenzahlvektoren.
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)])

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

# Stelle das Wellenfeld als Bild dar.
image = ax.imshow(0 * x, origin='lower',
                  extent=(np.min(x_lin), np.max(x_lin),
                          np.min(y_lin), np.max(y_lin)),
                  cmap='jet', clim=(-2, 2),
                  interpolation='bicubic')

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

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


def update(n):
    """Aktualisiere die Grafik zum n-ten Zeitschritt."""
    # 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, plot_trennlinie


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