32  Zugabe: Schall — dieselben Gleichungen in deiner Werkstatt

Das Buch ist zu Ende — das Schlusswort ist gesprochen. Aber wie bei einem guten Konzert gibt es eine Zugabe, und sie beginnt mit einem Geständnis: Du hast in 31 Kapiteln gar kein „Elektromagnetik-Programm” gebaut. Du hast einen Wellenlöser gebaut. Der Beweis dauert etwa zehn Zeilen: Wir nehmen den 2D-FDTD-Kern aus Kapitel 9, beschriften die Variablen um — aus dem Feld \(E_z\) wird der Schalldruck \(p\), aus den Magnetfeldern wird die Luftbewegung — und plötzlich rechnet dasselbe Programm Akustik. Alles, was du gelernt hast, reist mit: Impedanz und Reflexion, Interferenz, Bandlücken, sogar das inverse Design aus Kapitel 31.

Warum sich diese Zugabe lohnt, ist schnell gesagt: Bei Schall im Kilohertz-Bereich liegen die Wellenlängen zwischen Zentimetern und Metern — genau im Arbeitsbereich von Bohrmaschine, CNC-Fräse und 3D-Drucker. Und das Messgerät besitzt du längst: Lautsprecher, Mikrofon und die FFT aus Kapitel 10. Schall ist damit das einzige Wellengebiet dieses Buchs, in dem du den vollen Kreis vorhersagen → simulieren → bauen → selbst messen zu Hause schließen kannst. Bei der Yagi aus Kapitel 24 musstest du der WLAN-Anzeige glauben; den phononischen Kristall, den wir gleich entwerfen — ein Stäbchengitter aus Rundholz, das einen ganzen Frequenzbereich des Hörschalls aussperrt —, kannst du bohren, besingen und sein Loch im Spektrum mit eigenen Ohren und eigenem Mikrofon nachweisen.

Lernziele

Nach diesem Kapitel kannst du …

  1. … die Akustik-Gleichungen (Newton plus Massenerhaltung) als Strukturzwilling der Maxwell-Paare erkennen und die Übersetzungstabelle \(E \leftrightarrow p\), \(\varepsilon \leftrightarrow 1/\kappa\), \(\mu \leftrightarrow \rho\) anwenden,
  2. … den 2D-FDTD-Kern aus Kapitel 9 in wenigen Zeilen auf Schall portieren und weißt, wie ein schallharter Streuer ins Gitter kommt (und warum am harten Rand der Druck nicht flippt — anders als \(E\) am PEC),
  3. … mit der Impedanz \(Z = \rho c\) Reflexionen an Materialgrenzen berechnen (warum Holz für Schall ein besserer Spiegel ist als Silber für Licht — und wozu Ultraschall-Gel gut ist),
  4. … die Wellenlängen-Werkstatt-Landkarte aufstellen: welche Frequenzen sich mit CNC, 3D-Druck, Holz und Aluminium bauen und mit Hobbymitteln messen lassen,
  5. … einen phononischen Kristall entwerfen (Bandlücke, N-Reihen-Gesetz, Defekt-Kanal) und seinen Bauplan samt Messprotokoll ableiten,
  6. … die Kapitel-31-Methode auf Schall übertragen (ein Bit-Flip-Optimierer puzzelt einen Schall-Umlenker zusammen).

32.1 Zwei Gleichungen, neu beschriftet

Schall in Luft ist eine winzige Störung: Der Luftdruck weicht um den Schalldruck \(p\) vom Ruhewert ab (bei Zimmerlautstärke um etwa ein Millionstel), und die Luft selbst bewegt sich mit der Schnelle \(\vec{v}\) ein paar Mikrometer hin und her. Zwei Gesetze koppeln die beiden Größen. Erstens Newton: Ein Druckgefälle schiebt die Luft an,

\[\rho\,\frac{\partial \vec{v}}{\partial t} = -\nabla p .\]

Zweitens die Massenerhaltung: Wo Luft zusammenströmt (negative Divergenz der Schnelle), steigt der Druck,

\[\frac{\partial p}{\partial t} = -\kappa\, \nabla \cdot \vec{v} ,\]

mit der Dichte \(\rho\) und dem Kompressionsmodul \(\kappa\) (wie steif sich die Luft gegen Zusammendrücken wehrt). Zwei Größen, erste Zeitableitungen, jede treibt die andere über Raumableitungen — das ist exakt der Bauplan unseres 1D-FDTD-Paars aus Kapitel 6. Die Übersetzungstabelle:

Tabelle 32.1: Die Übersetzungstabelle. Die letzten beiden Zeilen sind die interessantesten — dazu gleich mehr.
Elektromagnetik Akustik
\(E\) (Feld) \(p\) (Schalldruck)
\(H\) bzw. \(B\) \(\vec{v}\) (Schnelle)
\(\varepsilon\) (Permittivität) \(1/\kappa\) (Kompressibilität)
\(\mu\) (Permeabilität) \(\rho\) (Dichte)
\(c = 1/\sqrt{\varepsilon\mu}\) \(c = \sqrt{\kappa/\rho}\)
Wellenwiderstand \(Z = \sqrt{\mu/\varepsilon}\) Impedanz \(Z = \rho c\)
PEC (\(E = 0\)) offenes Rohrende (\(p = 0\))
schallharte Wand (\(v_\perp = 0\))

Ein Unterschied versteckt sich nicht in der Tabelle, sondern in der Geometrie: \(p\) ist eine Zahl, kein Vektor. Schall in Luft ist eine Longitudinalwelle — es gibt keine Polarisation, und alles aus Kapitel 4 und Kapitel 13 über Schwingungsrichtungen bleibt ohne Gegenstück. Dafür passt die skalare 2D-Welt, in der wir seit Kapitel 9 rechnen (\(E_z\), \(H_x\), \(H_y\)), strukturell perfekt: \((E_z, H_x, H_y) \to (p, v_x, v_y)\).

Die Impedanz-Zeile der Tabelle lohnt eine Handrechnung, denn an ihr hängt die ganze Werkstatt-Tauglichkeit. Die Spiegelformel aus Kapitel 6 gilt wörtlich weiter: \(r = (Z_2 - Z_1)/(Z_2 + Z_1)\).

import numpy as np

C_LUFT = 343.0                  # m/s bei 20 Grad
Z_LUFT = 1.2 * C_LUFT           # rho = 1,2 kg/m^3
print(f"Luft: Z = {Z_LUFT:.0f} kg/(m^2 s)")
for name, rho, c in (("Wasser", 1000.0, 1480.0),
                     ("Holz (Buche, laengs)", 700.0, 4000.0),
                     ("Aluminium", 2700.0, 6320.0),
                     ("PLA (3D-Druck)", 1240.0, 2200.0)):
    Z = rho * c
    R = ((Z - Z_LUFT) / (Z + Z_LUFT)) ** 2
    print(f"{name}: Z = {Z:.2e} -> R an Luft = {R*100:.2f} %")
Luft: Z = 412 kg/(m^2 s)
Wasser: Z = 1.48e+06 -> R an Luft = 99.89 %
Holz (Buche, laengs): Z = 2.80e+06 -> R an Luft = 99.94 %
Aluminium: Z = 1.71e+07 -> R an Luft = 99.99 %
PLA (3D-Druck): Z = 2.73e+06 -> R an Luft = 99.94 %

Holz reflektiert 99,94 Prozent der Schallleistung, Aluminium 99,99 — zum Vergleich: Ein Silberspiegel reflektiert sichtbares Licht zu etwa 98 Prozent. Für Schall ist ein Besenstiel ein besserer Spiegel, als es Silber für Licht ist. Der Grund ist das Impedanzverhältnis: Luft zu Holz liegt bei fast 1:7000, Luft zu Glas (optisch) nur bei 1:1,5. Genau deshalb dürfen wir gleich alle festen Materialien — Holz, Aluminium, PLA — als ideal schallhart nähern: Die Luftbewegung an ihrer Oberfläche ist praktisch null, \(v_\perp = 0\). Das ist für die Akustik, was der PEC für unsere Antennen war. Und es erklärt nebenbei, warum beim Ultraschall am Arzt ein Gel aufgetragen wird: Schon eine hauchdünne Luftschicht zwischen Schallkopf und Haut wäre eine 99,9-Prozent-Spiegelwand (Übung 32.1 rechnet nach).

32.2 Der Kern, portiert

Versuchsaufbau: Wir bauen den Kapitel-9-Kern als Akustik-Fassung neu auf — gleiche Bühne wie immer: ein Rechteckgebiet, eine \(\sigma\)-Dämpfungsrampe an allen Rändern (diesmal dick, dazu unten mehr), eine weiche Quelle, die \(\sin\)-Schwingungen oder Gauß-Pulse in den Druck drückt, und „Mikrofone”, die \(p\) an gewählten Punkten mitschreiben. Neu ist ein einziges Argument: ein Bool-Feld hart, das markiert, welche Zellen aus festem Material bestehen. Auf allen Kanten harter Zellen wird die Schnelle nach jedem Update auf null gesetzt — Luft strömt nicht in den Stab.

Die drei tragenden Zeilen, entzerrt — du erkennst jede aus Kapitel 5 und Kapitel 9 wieder, nur die Schilder sind neu:

  • vx -= DT * np.diff(p, axis=0) — Newton. np.diff bildet die Nachbar-Differenz pro Lücke: \(p\) lebt auf den Zellen (Länge \(N\)), \(v_x\) auf den Kanten dazwischen (Länge \(N-1\)) — der vertraute Yee-Versatz, nur dass jetzt der Druckunterschied zwischen zwei Zellen die Luft in der Kante dazwischen anschiebt.
  • vx[m_vx] = 0.0 — die Materialregel. m_vx markiert jede Kante, die eine harte Zelle berührt (hart[1:,:] | hart[:-1,:]oder-Verknüpfung der beiden Nachbarzellen jeder Kante).
  • p = daempf * p - DT * div — Massenerhaltung mit Randdämpfung: Die Divergenz sammelt ein, wie viel Luft pro Zelle zusammenströmt; daempf ist die \((1-\sigma\Delta t/2)\)- Rampe aus Kapitel 9, unverändert.
DT = 0.5                        # Courant S = 0,5 < 1/sqrt(2)


def daempfung(nx, ny, rand, s_max=0.3):
    """Sigma-Rampe an allen Raendern (kubisch und DICK)."""
    sig = np.zeros((nx, ny))
    for i in range(rand):
        s = s_max * ((rand - i) / rand) ** 3
        sig[i, :] = np.maximum(sig[i, :], s)
        sig[nx-1-i, :] = np.maximum(sig[nx-1-i, :], s)
        sig[:, i] = np.maximum(sig[:, i], s)
        sig[:, ny-1-i] = np.maximum(sig[:, ny-1-i], s)
    return (1 - sig * DT / 2) / (1 + sig * DT / 2)


def schall_lauf(hart, daempf, q_pos, f_tr, nt, tau=None, t0=0.0,
                mikros=(), schnappschuesse=()):
    """2D-Akustik-FDTD: p auf den Zellen, vx/vy auf den Kanten."""
    nx, ny = hart.shape
    m_vx = hart[1:, :] | hart[:-1, :]   # Kanten an harten Zellen
    m_vy = hart[:, 1:] | hart[:, :-1]
    p = np.zeros((nx, ny))
    vx = np.zeros((nx-1, ny))
    vy = np.zeros((nx, ny-1))
    reihen = np.zeros((nt, len(mikros)))
    bilder = {}
    for n in range(nt):
        # Newton: die Schnelle folgt dem Druckgefaelle (rho = 1)
        vx -= DT * np.diff(p, axis=0)
        vy -= DT * np.diff(p, axis=1)
        vx[m_vx] = 0.0              # Luft kommt nicht in den Stab
        vy[m_vy] = 0.0
        # Massenerhaltung: der Druck folgt der Kompression (kappa = 1)
        div = np.zeros((nx, ny))
        div[1:-1, 1:-1] = ((vx[1:, 1:-1] - vx[:-1, 1:-1])
                           + (vy[1:-1, 1:] - vy[1:-1, :-1]))
        p = daempf * p - DT * div
        t = n * DT
        anregung = np.sin(2 * np.pi * f_tr * t)
        if tau is not None:         # Gauss-Puls statt Dauerton
            anregung *= np.exp(-((t - t0) / tau) ** 2)
        p[q_pos] += anregung        # weiche Quelle (Kapitel 6)
        for k, (mi, mj) in enumerate(mikros):
            reihen[n, k] = p[mi, mj]
        if n in schnappschuesse:
            bilder[n] = p.copy()
    return reihen, p, bilder

Mehr ist es nicht — vergleiche mit dem TMz-Kern aus Kapitel 9: gleiche Schleifenstruktur, gleiche np.diff-Buchhaltung, gleiche Rampe. Bevor wir ihm trauen, zwei Proben. Die erste ist Pflicht seit Kapitel 10: Läuft ein Puls mit der richtigen Geschwindigkeit? In unseren Einheiten (Zellgröße 1, \(\rho = 1\), \(\kappa = 1\)) muss \(c = \sqrt{\kappa/\rho} = 1\) herauskommen.

NXc, NYc = 420, 232
RANDc = 40
daempf_c = daempfung(NXc, NYc, RANDc)
fronten = {}
for nt_stop in (200, 380):
    _, p_end, _ = schall_lauf(np.zeros((NXc, NYc), bool), daempf_c,
                              (60, NYc // 2), 0.035, nt_stop,
                              tau=12.0, t0=60.0)
    profil = np.abs(p_end[60:, NYc // 2])
    fronten[nt_stop] = np.max(np.nonzero(profil
                                         > 0.02 * profil.max())[0])
c_mess = (fronten[380] - fronten[200]) / ((380 - 200) * DT)
print(f"Front-Differenzmessung: c = {c_mess:.3f} (Soll: 1)")
Front-Differenzmessung: c = 1.000 (Soll: 1)
HinweisVorhersage (PRIMM)

Die zweite Probe ist die interessantere. In Kapitel 6 hast du gesehen, dass ein Puls am PEC-Spiegel mit umgekehrtem Vorzeichen zurückkommt (\(E\) muss am Leiter null sein). Gleich schicken wir einen Druckpuls gegen eine schallharte Wand — und an ein „offenes Rohrende”, an dem wir \(p = 0\) festhalten. Kommt das Echo jeweils aufrecht oder gespiegelt zurück? Notiere beide Antworten, bevor du weiterliest.

import matplotlib.pyplot as plt

N1, NT1 = 400, 700
p1 = np.exp(-((np.arange(N1) - 120) / 8.0) ** 2)
start = p1.copy()
v1 = np.zeros(N1 - 1)
hart1 = np.zeros(N1, bool)
hart1[300:] = True              # rechts: schallharte Wand
m_v1 = hart1[1:] | hart1[:-1]
for n in range(NT1):
    v1 -= DT * np.diff(p1)
    v1[m_v1] = 0.0
    p1[1:-1] -= DT * np.diff(v1)   # p[0] bleibt 0: offenes Ende

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 4.6), sharex=True)
ax1.plot(start, "C0")
ax1.axvspan(300, N1, color="0.75")
ax1.set_ylabel("p (Start)")
ax1.set_ylim(-0.7, 1.1)
ax2.plot(p1, "C0")
ax2.axvspan(300, N1, color="0.75")
ax2.axhline(0.5, ls=":", color="C2", lw=0.8)
ax2.axhline(-0.5, ls=":", color="C3", lw=0.8)
ax2.annotate("von der harten Wand:\naufrecht (+0,5)", xy=(130, 0.5),
             xytext=(160, 0.75), arrowprops=dict(arrowstyle="->"),
             fontsize=9)
ax2.annotate("vom offenen Ende:\ngespiegelt (-0,5)", xy=(230, -0.5),
             xytext=(40, -0.55), arrowprops=dict(arrowstyle="->"),
             fontsize=9)
ax2.set_ylabel("p (nach den Echos)")
ax2.set_ylim(-0.7, 1.1)
ax2.set_xlabel("Zelle")
plt.tight_layout()
plt.show()
spitze = p1[:300].max()
print(f"Echo von der Wand: {spitze:+.3f}   "
      f"Echo vom offenen Ende: {p1[:300].min():+.3f}")
Abbildung 32.1: Die Vorzeichen-Probe in 1D: Ein Druckpuls (Höhe 1) zerfällt in zwei halbe Pulse (Kapitel 5). Der rechte trifft die schallharte Wand und kommt AUFRECHT zurück (+0,5): Am Stillstand der Luft staut sich der Druck — die Wand ist ein Druckbauch. Der linke trifft das offene Ende (p = 0 festgehalten) und kommt GESPIEGELT zurück (−0,5): Das offene Rohrende ist ein Druckknoten. Genau umgekehrt zum E-Feld am PEC — die Übersetzungstabelle vertauscht die Rollen der Randbedingungen.
Echo von der Wand: +0.495   Echo vom offenen Ende: -0.495

Der Druck flippt an der Wand nicht — die Wand ist ein Druckbauch, kein Knoten. Wer schon einmal bemerkt hat, wie laut die eigene Stimme in einer gefliesten Duschecke klingt, hat diesen Druckbauch gehört. Geflippt wird stattdessen am offenen Ende — dort, wo der Druck auf den Außendruck festgenagelt ist. Die Übersetzungstabelle vertauscht also die Rollen: Die harte Wand verhält sich wie der magnetische Spiegel der EM-Welt, das offene Rohr wie der PEC. Für Orgelpfeifen und Flaschen-Resonanzen ist das die halbe Physik — für uns ist es die Warnung, beim Übersetzen nicht nur Variablen, sondern auch Randbedingungen zu übersetzen.

32.3 Die Wellenlängen-Werkstatt-Landkarte

WarnungNaheliegende Vermutung: „Je kürzer die Wellenlänge, desto schwieriger wird das Bauen“

Warum sie naheliegt: Kleinere Strukturen verlangen feinere Werkzeuge — Mikrochips brauchen Reinräume, optische Gitter Nanometer-Maschinen. Also scheint die Faustregel zu gelten: Lange Wellen leicht, kurze Wellen schwer.

Was stattdessen stimmt: Für den Hobbybereich ist nicht die Fertigung der Engpass, sondern die Messtechnik. Eine 3-cm-Mikrowellenlinse (10 GHz) fräst jede CNC mühelos — aber das Messgerät dafür (ein Netzwerkanalysator) kostet mehr als die Fräse. Beim Schall dagegen liegt beides im Hobbybudget: Die Wellenlängen des Hörschalls (1 kHz: 34 cm, 10 kHz: 3,4 cm) treffen genau die Skala von Bohrmaschine, Fräse und 3D-Drucker, und das komplette Messlabor — Lautsprecher, Mikrofon, FFT-Software aus Kapitel 10 — kostet etwa so viel wie das Holz.

Konkret, erst die EM-Seite (mit \(\lambda = c/f\)):

Tabelle 32.2: EM-Wellen und die Werkstatt: ab 10 GHz wird die Fertigung einfach — und die Messung zum Engpass.
Frequenz \(\lambda\) bauen mit messen mit
2,4 GHz (WLAN) 12,5 cm Alu-Rohr, Draht (Kapitel 24) WLAN-Anzeige (grob)
10 GHz 3 cm CNC, 3D-Druck (PLA-Linsen) VNA/SDR — teuer
100 GHz+ < 3 mm Feinmechanik Laborgerät
Licht 0,5 µm gar nicht (kaufen) Photodiode

Und die Schall-Seite (\(c = 343\) m/s — das macht die Wellen bei gleicher Frequenz fast eine Million Mal kürzer):

Tabelle 32.3: Schall und die Werkstatt: vom Hörbereich bis ~15 kHz ist alles mit Bordmitteln baubar UND messbar.
Frequenz \(\lambda\) bauen mit messen mit
100 Hz 3,4 m Zimmerwände Mikrofon
1 kHz 34 cm Holz, Säge Mikrofon
3 kHz 11 cm Rundholz-Gitter (dieses Kapitel) Mikrofon
10 kHz 3,4 cm 3D-Druck Mikrofon (96 kHz)
40 kHz (Ultraschall) 8,6 mm 3D-Druck, fein Transducer + schneller ADC

Die Zeile bei 3 kHz ist unser Ziel: Wellenlänge 11 cm, Strukturen von einigen Zentimetern — Baumarktware. Dass ein Mikrofon plus Soundkarte ein vollwertiges Messgerät ist, hast du in Kapitel 10 implizit schon gelernt: Ein Sweep durch alle Frequenzen, eine FFT der Aufnahme, und du hältst ein Spektrum in der Hand. Genau so werden wir gleich die Bandlücke nachweisen.

32.4 Der phononische Kristall

In Kapitel 26 hat ein periodischer Stapel durchsichtiger Schichten Licht perfekt gespiegelt — die Bandlücke. Das akustische Gegenstück heißt phononischer Kristall, und seine einfachste baubare Form ist ein Gitter aus runden Stäben in Luft: Holzdübel in ein Brett gesteckt, fertig. Jede Stabreihe reflektiert ein wenig; liegen die Reihen im richtigen Abstand \(a\), addieren sich die Echos konstruktiv (die Bragg-Bedingung aus Kapitel 26: \(\lambda \approx 2a\), also \(f \approx c/2a\)), und der Kristall sperrt.

Versuchsaufbau: Quadratgitter mit Gitterkonstante \(a = 16\) Zellen, Stabradius \(r = 0{,}35\,a\) (Füllfaktor \(\pi \cdot 0{,}35^2 \approx 0{,}38\)), 9 Säulen quer, 1 bis 5 Reihen in Laufrichtung. Links eine breite Quellzeile, die einen Gauß-Puls (Mittenfrequenz 0,035, Band etwa 0,012 bis 0,06) abstrahlt; rechts eine ganze Mikrofon-Zeile, deren Leistungsspektren wir summieren — ein einzelner Messpunkt säße womöglich in einem Beugungs-Minimum. Transmission \(T(f)\) = Spektrum mit Kristall geteilt durch Spektrum ohne (zwei Läufe, wie bei jeder Referenzmessung seit Kapitel 12). Die Dämpfungsrampe ist mit 40 Zellen ungewohnt dick: Die längsten Wellen im Band messen 80 Zellen, und eine dünne Rampe wirft sie zurück ins Messgebiet (das Kleingedruckte erzählt, wie sich dieser Fehler bemerkbar machte).

HinweisVorhersage (PRIMM)

Die Bragg-Peilung sagt: Lücke um \(f \approx c/2a\), also \(f \cdot a/c \approx 0{,}5\). Zwei Fragen vor dem Lauf: (1) Eine einzelne Stabreihe lässt bei dieser Frequenz noch knapp die Hälfte durch. Wie tief drücken fünf Reihen die Transmission — auf ein Viertel? Ein Zehntel? Weniger? (2) Was erwartest du weit unterhalb der Lücke, wo die Welle zehnmal länger ist als ein Stab dick?

A_GIT = 16
R_STAB = 0.35 * A_GIT
N_SAEULEN = 9
X_KRIST, X_Q, X_MIK = 160, 60, 330
NT_SPEK = 8000
ii_c, jj_c = np.meshgrid(np.arange(NXc), np.arange(NYc),
                         indexing="ij")


def kristall_bauen(n_reihen):
    hart = np.zeros((NXc, NYc), bool)
    y0 = (NYc - N_SAEULEN * A_GIT) / 2
    for r in range(n_reihen):
        for s in range(N_SAEULEN):
            cx = X_KRIST + (r + 0.5) * A_GIT
            cy = y0 + (s + 0.5) * A_GIT
            hart |= (ii_c - cx) ** 2 + (jj_c - cy) ** 2 < R_STAB ** 2
    return hart


quelle_c = (X_Q, slice(RANDc + 8, NYc - RANDc - 8))
mik_zeile = [(X_MIK, j) for j in range(RANDc + 12, NYc - RANDc - 12)]


def leistungsspektrum(hart):
    reihen, _, _ = schall_lauf(hart, daempf_c, quelle_c, 0.035,
                               NT_SPEK, tau=12.0, t0=60.0,
                               mikros=mik_zeile)
    return np.sum(np.abs(np.fft.rfft(reihen, axis=0)) ** 2, axis=1)


fs = np.fft.rfftfreq(NT_SPEK, DT)
spek_frei = leistungsspektrum(np.zeros((NXc, NYc), bool))
band = ((fs > 0.012) & (fs < 0.06)
        & (spek_frei > 0.01 * spek_frei.max()))
fb = fs[band]
T_leiter = {}
for n_r in (1, 2, 3, 5):
    T_leiter[n_r] = (leistungsspektrum(kristall_bauen(n_r))[band]
                     / spek_frei[band])

# Lueckenkanten der ersten Luecke (T < 0,05) suchen
T5 = T_leiter[5]
i_tief = np.argmin(np.where(fb < 0.045, T5, 1.0))
i = i_tief
while T5[i] < 0.05:
    i -= 1
f_unten = fb[i + 1]
i = i_tief
while T5[i] < 0.05:
    i += 1
f_oben = fb[i - 1]

fig, ax = plt.subplots(figsize=(8.4, 4.6))
for n_r, farbe in ((1, "C1"), (2, "C2"), (3, "C3"), (5, "C0")):
    ax.semilogy(fb * A_GIT, T_leiter[n_r], color=farbe,
                label=f"{n_r} Reihe{'n' if n_r > 1 else ''}")
ax.axvspan(f_unten * A_GIT, f_oben * A_GIT, color="gold", alpha=0.25)
ax.axvline(0.5, ls="--", color="0.5", lw=1)
ax.text(0.505, 1.2, "Bragg-Peilung c/2a", fontsize=8, color="0.4")
ax.set_xlabel("f·a/c (dimensionslos)")
ax.set_ylabel("Transmission T")
ax.set_ylim(1e-3, 3)
ax.legend(fontsize=9)
ax.grid(alpha=0.3)
plt.tight_layout()
plt.show()
print(f"Luecke (T < 0,05): f*a/c = {f_unten*A_GIT:.3f} "
      f"bis {f_oben*A_GIT:.3f}")
for n_r in (1, 2, 3, 5):
    i = np.argmin(np.abs(fb - 0.030))
    print(f"  {n_r} Reihen: T(f*a/c = 0,48) = {T_leiter[n_r][i]:.3f}")
Abbildung 32.2: Das Transmissionsspektrum des Stab-Kristalls für 1, 2, 3 und 5 Reihen (Leistung, logarithmisch). Links der Lücke (f·a/c < 0,3) ist das Gitter fast durchsichtig — die langen Wellen laufen um die Stäbe herum. In der Bandlücke (gold, T < 0,05 von f·a/c = 0,33 bis 0,59) drückt JEDE zusätzliche Reihe die Transmission um etwa den Faktor 4: bei f·a/c = 0,48 von 0,42 (eine Reihe) über 0,073 und 0,018 auf 0,007 (fünf Reihen) — das exponentielle N-Reihen-Gesetz aus Kapitel 26. Die gestrichelte Bragg-Peilung c/2a liegt IN der Lücke, trifft aber nicht ihre Mitte: Der 2D-Kristall ist kein 1D-Schichtstapel. Oberhalb des Durchlassfensters um 0,65 beginnt die zweite Lücke.
Luecke (T < 0,05): f*a/c = 0.332 bis 0.592
  1 Reihen: T(f*a/c = 0,48) = 0.416
  2 Reihen: T(f*a/c = 0,48) = 0.073
  3 Reihen: T(f*a/c = 0,48) = 0.018
  5 Reihen: T(f*a/c = 0,48) = 0.007

Drei Lesefrüchte. Erstens das N-Reihen-Gesetz: 0,42 → 0,073 → 0,018 → 0,007 — jede Reihe drückt um etwa den Faktor 4, eine Gerade im Log-Plot. Das ist exakt das Bild der Bragg-Spiegel-Reihe aus Kapitel 26: In der Lücke fällt die Welle exponentiell, wie im Tunnel-Kapitel Kapitel 17. Wer also tiefer sperren will, baut nicht dickere Stäbe, sondern mehr Reihen. Zweitens: Weit unterhalb der Lücke ist das Gitter fast durchsichtig (\(T \approx 1\)) — die 80-Zellen-Welle umfließt die 5-Zellen-Stäbe, sie sieht nur ein leicht zäheres effektives Medium. Ein Lattenzaun hält den Verkehrslärm nicht auf. Drittens liegt die Bragg-Peilung zwar in der Lücke, aber nicht in ihrer Mitte — der 2D-Kristall mit dicken Stäben ist eben kein 1D-Stapel; die Peilung taugt zum Zielen, die Kanten liefert die Messung.

Der Film macht die Lücke unmittelbar sichtbar: Derselbe Kristall, zwei schmalbandige Pulse — einer mitten in der Lücke, einer im Durchlassfenster darüber. Sieh auf die rechte Seite des Kristalls: Einmal kommt dort praktisch nichts an, einmal fast alles.

Code der Animation (nur in der HTML-Fassung)
from matplotlib import animation
from IPython.display import HTML

NT_FILM = 1200
takte = tuple(range(40, NT_FILM, 33))
laeufe = {}
for f_film in (0.030, 0.045):
    _, _, bilder = schall_lauf(kristall_bauen(5), daempf_c, quelle_c,
                               f_film, NT_FILM, tau=40.0, t0=160.0,
                               schnappschuesse=takte)
    laeufe[f_film] = bilder

hart5 = kristall_bauen(5)
fig, achsen = plt.subplots(1, 2, figsize=(7.8, 3.2))
vm = 0.6
kacheln = []
for ax, f_film, name in ((achsen[0], 0.030, "in der Luecke"),
                         (achsen[1], 0.045, "im Fenster")):
    b = laeufe[f_film][takte[12]].copy()
    b[hart5] = np.nan
    k = ax.imshow(b.T, origin="lower", cmap="RdBu",
                  vmin=-vm, vmax=vm)
    kacheln.append(k)
    ax.set_title(f"f·a/c = {f_film*A_GIT:.2f} ({name})", fontsize=9)
    ax.set_xticks([])
    ax.set_yticks([])
titel = fig.suptitle("", fontsize=10)
fig.subplots_adjust(top=0.82, bottom=0.05, wspace=0.08)


def bild(i):
    for k, f_film in zip(kacheln, (0.030, 0.045)):
        b = laeufe[f_film][takte[i]].copy()
        b[hart5] = np.nan
        k.set_data(b.T)
    titel.set_text(f"Gleicher Kristall, zwei Frequenzen — "
                   f"Schritt {takte[i]}")
    return kacheln + [titel]


anim = animation.FuncAnimation(fig, bild, frames=len(takte),
                               interval=120)
plt.close(fig)
HTML(anim.to_jshtml(default_mode="loop"))

Die Spielwiese ist dein Bandlücken-Designer in Werkstatt-Einheiten: Stell Raster und Stabdurchmesser in Millimetern ein, und die Simulation liefert das Transmissionsspektrum in Hertz (gröberes Gitter als oben, die Kanten verschieben sich also leicht). Aufträge: (1) Ersetze die 35er-Stäbe durch 28-mm-Rundholz — wie viel schmaler wird die Lücke? (2) Stelle das Raster auf 70 mm: Rutscht die Lücke wie vorhergesagt unter 2,3 kHz?

32.5 Vom Gitter zum Bauplan

Bis hier war alles dimensionslos — mit Absicht, denn die Skaleninvarianz aus Kapitel 11 gilt für Schall genauso: Der Lauf oben beschreibt jeden Stab-Kristall mit \(r/a = 0{,}35\); erst die Wahl von \(a\) in Metern klebt Etiketten auf die Achsen. Die Umrechnung ist eine Zeile: \(f_\text{Hz} = (f \cdot a/c) \cdot c_\text{Luft} / a_\text{real}\).

A_REAL = 0.050                  # Raster 50 mm
D_STAB = 0.035                  # Buche-Rundstab 35 mm (= 0,7 a)
print(f"r/a = {D_STAB/2/A_REAL:.2f}  (Simulation: 0,35)")
print(f"Luecke: {f_unten*A_GIT*C_LUFT/A_REAL:.0f} bis "
      f"{f_oben*A_GIT*C_LUFT/A_REAL:.0f} Hz")
r/a = 0.35  (Simulation: 0,35)
Luecke: 2278 bis 4061 Hz

Die Lücke landet bei 2,3 bis 4,1 Kilohertz — mitten im empfindlichsten Bereich des Gehörs und bequem im Arbeitsbereich jedes Lautsprechers und Mikrofons. Damit ist der Bauplan festgelegt:

fig, ax = plt.subplots(figsize=(6.4, 6.4))
for i in range(9):
    for j in range(9):
        ax.add_patch(plt.Circle((50 + i * 50, 50 + j * 50), 17.5,
                                facecolor="burlywood",
                                edgecolor="saddlebrown"))
ax.add_patch(plt.Rectangle((0, 0), 500, 500, fill=False, lw=1.5))
ax.annotate("", xy=(100, 22), xytext=(50, 22),
            arrowprops=dict(arrowstyle="<->"))
ax.text(75, 6, "a = 50 mm", ha="center", fontsize=9)
ax.annotate("", xy=(67.5, 100), xytext=(32.5, 100),
            arrowprops=dict(arrowstyle="<->"))
ax.text(50, 121, "d = 35 mm", ha="center", fontsize=9)
ax.text(250, 520, "Brett >= 450 x 450 mm, 81 Bohrungen",
        ha="center", fontsize=10)
ax.set_xlim(-20, 520)
ax.set_ylim(-20, 545)
ax.set_aspect("equal")
ax.axis("off")
plt.tight_layout()
plt.show()
Abbildung 32.3: Die Bohrschablone: 9 × 9 Buche-Rundstäbe (Durchmesser 35 mm, Länge ≥ 30 cm) im Quadratraster a = 50 mm, gesteckt in ein Brett ab 45 × 45 cm — 81 Bohrungen, mit CNC oder Bohrständer eine Stunde Arbeit. Vorhersage der Simulation: Transmissions-Einbruch von etwa 2,3 bis 4,1 kHz, um Faktor 100 oder mehr (fünf Reihen in jeder Richtung — das Gitter wirkt in beiden Achsen). Wer nur die Lücke hören will, dem genügen schon 5 × 9 Stäbe.

Und so wird gemessen — das Messprotokoll, Schritt für Schritt wie bei jeder Referenzmessung dieses Buchs:

  1. Aufbau: Lautsprecher und Mikrofon etwa einen Meter auseinander auf Stabhöhe (Mitte des Gitters), dazwischen später der Kristall. Beides auf weichem Untergrund (Handtuch), damit der Tisch nicht mitspielt.
  2. Referenzlauf: Einen langsamen Sinus-Sweep von 1 bis 6 kHz abspielen (20 Sekunden; jede Tongenerator-App kann das) und aufnehmen. FFT der Aufnahme — das ist \(S_\text{ohne}(f)\), dein „Lauf ohne Kristall”.
  3. Messlauf: Kristall dazwischenstellen, exakt gleiche Aufnahme wiederholen: \(S_\text{mit}(f)\).
  4. Auswertung: \(T(f) = S_\text{mit}/S_\text{ohne}\) — dieselbe Division wie in jeder Simulation seit Kapitel 12. In der Lücke sollte \(T\) um 20 Dezibel oder mehr einbrechen.
  5. Gegenprobe (die Methode aus Kapitel 10): Messung wiederholen, ohne irgendetwas zu ändern — die Differenz zweier identischer Läufe zeigt dir dein Messrauschen. Erst was deutlich darüber liegt, ist Signal.

Das Wohnzimmer ist kein reflexionsfreier Raum: Echos von Wänden und Tisch wellen das Spektrum (das Kleingedruckte verrät den Profi-Trick dagegen). Aber ein Faktor-100-Einbruch über eine Oktave ist robust gegen alle Raum-Wellen — genau deshalb haben wir einen Kristall mit tiefer Lücke entworfen und nicht einen mit eleganter schmaler.

32.6 Schall um die Ecke: der Defekt-Kanal

Die Bandlücke sperrt — richtig spannend wird sie, wenn man sie gezielt durchlöchert. Wie in Kapitel 26 (Punktdefekt-Kavität) gilt: Ein Defekt im Kristall ist der einzige Ort, an dem eine Lücken-Frequenz existieren darf. Entfernen wir eine ganze Stab-Zeile, entsteht ein Kanal, in dem der Schall laufen kann — ringsum von Bandlücken-Wänden eingesperrt, die kein Loch und keinen Spalt haben (anders als jeder reale Flur).

Versuchsaufbau: Ein größerer Kristall (11 Reihen, 15 Säulen — die äußeren Säulen reichen bis in die Dämpfungsrampe, damit nichts außen herumläuft), Dauerton-Quelle dicht vor dem Kanalmund, Messpunkt in einer Pore kurz vor dem Kanalende. Eine Feinheit, die uns beim Entwickeln zuerst entgangen ist: Quelle und Messpunkte müssen an Stellen liegen, die in beiden Konfigurationen (mit und ohne Kanal) freie Luft sind — wer den Vergleichspunkt dorthin legt, wo im intakten Kristall ein Stab steht, vergleicht mit einer Zelle, in der der Druck schlicht für immer null bleibt. Die Frequenz wählen wir bei \(f \cdot a/c = 0{,}53\), mitten im Leitungsband des Kanals: Auch der Kanal hat nämlich ein eigenes Durchlassband innerhalb der Lücke — er ist ein periodisch beladener Wellenleiter, kein leeres Rohr (ein Puls-Vorablauf, wie wir ihn für das Spektrum oben benutzt haben, findet es).

RANDk, PUFk = 40, 24
NREI, NSAE = 11, 15
NXk = 2 * (RANDk + PUFk) + NREI * A_GIT
NYk = 16 + NSAE * A_GIT
X_K, Y_K = RANDk + PUFk, 8
S_KAN = 7
Y_MITTE = Y_K + int((S_KAN + 0.5) * A_GIT)
daempf_k = daempfung(NXk, NYk, RANDk)
ii_k, jj_k = np.meshgrid(np.arange(NXk), np.arange(NYk),
                         indexing="ij")


def kristall_kanal(fehlend=()):
    hart = np.zeros((NXk, NYk), bool)
    for r in range(NREI):
        for s in range(NSAE):
            if (r, s) in fehlend:
                continue
            cx = X_K + (r + 0.5) * A_GIT
            cy = Y_K + (s + 0.5) * A_GIT
            hart |= ((ii_k - cx) ** 2 + (jj_k - cy) ** 2
                     < R_STAB ** 2)
    return hart


quelle_k = (X_K - 4, slice(Y_MITTE - 4, Y_MITTE + 5))
M_END = (X_K + 9 * A_GIT, Y_MITTE)        # Pore: immer freie Luft
M_KNICK = (X_K + int(6.5 * A_GIT), Y_K + 12 * A_GIT)
kanal_gerade = [(r, S_KAN) for r in range(NREI)]
kanal_knick = ([(r, S_KAN) for r in range(7)]
               + [(6, s) for s in range(S_KAN, NSAE)])
NT_CW = 5000


def dauerton(fehlend, mess, f_cw):
    reihen, p_end, _ = schall_lauf(kristall_kanal(fehlend), daempf_k,
                                   quelle_k, f_cw, NT_CW,
                                   mikros=[mess])
    return np.sum(reihen[NT_CW * 2 // 3:, 0] ** 2), p_end


F_KANAL = 0.033
e_gerade, p_gerade = dauerton(kanal_gerade, M_END, F_KANAL)
e_intakt, p_intakt = dauerton([], M_END, F_KANAL)

fig, achsen = plt.subplots(1, 2, figsize=(9.6, 4.2))
for ax, p_b, fehlend, tit in (
        (achsen[0], p_gerade, kanal_gerade,
         f"mit Kanal: Faktor {e_gerade/e_intakt:.0f}"),
        (achsen[1], p_intakt, [], "intakt: fast nichts kommt an")):
    b = p_b.copy()
    b[kristall_kanal(fehlend)] = np.nan
    vm = np.nanpercentile(np.abs(b), 99.3)
    ax.imshow(b.T, origin="lower", cmap="RdBu", vmin=-vm, vmax=vm)
    ax.plot(*M_END, "k+", ms=11)
    ax.set_title(tit, fontsize=10)
    ax.set_xticks([])
    ax.set_yticks([])
plt.tight_layout()
plt.show()
print(f"Kanalende, mit Kanal gegen intakt: "
      f"Faktor {e_gerade/e_intakt:.0f}")
Abbildung 32.4: Eine fehlende Stab-Zeile wird zur Schall-Leitung (Dauerton mitten in der Bandlücke, f·a/c = 0,53). Links: Mit Kanal läuft der Schall als eingesperrte Welle bis zum Messpunkt (Kreuz) — am Kanalende kommt 158-mal mehr Leistung an als im intakten Kristall (rechts), wo nach wenigen Reihen praktisch nichts mehr lebt. Die Bandlücke wirkt dabei als perfekte Kanalwand: Sie hat keine Fugen, durch die der Schall seitlich entweichen könnte.
Kanalende, mit Kanal gegen intakt: Faktor 158

Faktor 158 — die fehlende Zeile leitet. Auch das ist baubar: Beim Bestücken des Bretts eine Dübelreihe weglassen, fertig ist der Schall-Flur. Jetzt der Ehrgeiz: Wir lassen den Kanal um 90 Grad abbiegen (halbe Strecke geradeaus, dann seitlich hinaus). In Kapitel 26 hat der EM-Knick verlustfrei funktioniert — eine berühmte Eigenschaft photonischer Wellenleiter. Gilt das auch hier?

F_KNICK = 0.034
e_knick, p_knick = dauerton(kanal_knick, M_KNICK, F_KNICK)
e_ecke, p_ecke = dauerton(kanal_knick + [(5, 8)], M_KNICK, F_KNICK)
e_seite, _ = dauerton([], M_KNICK, F_KNICK)

fig, achsen = plt.subplots(1, 2, figsize=(9.6, 4.2))
for ax, p_b, fehlend, tit in (
        (achsen[0], p_knick, kanal_knick,
         f"Knick pur: Faktor {e_knick/e_seite:.0f}"),
        (achsen[1], p_ecke, kanal_knick + [(5, 8)],
         f"Innenecke geoeffnet: Faktor {e_ecke/e_seite:.0f}")):
    b = p_b.copy()
    b[kristall_kanal(fehlend)] = np.nan
    vm = np.nanpercentile(np.abs(b), 99.3)
    ax.imshow(b.T, origin="lower", cmap="RdBu", vmin=-vm, vmax=vm)
    ax.plot(*M_KNICK, "k+", ms=11)
    ax.set_title(tit, fontsize=10)
    ax.set_xticks([])
    ax.set_yticks([])
plt.tight_layout()
plt.show()
print(f"Knick pur: Faktor {e_knick/e_seite:.0f}, "
      f"Innenecke geoeffnet: Faktor {e_ecke/e_seite:.0f}")
Abbildung 32.5: Der 90-Grad-Knick ist wählerischer als die Gerade (Dauerton bei f·a/c = 0,54). Links der pure Knick: Am Seitenausgang (Kreuz) kommt nur Faktor 7 gegenüber intakt an — die Ecke wirft den größten Teil zurück. Rechts derselbe Knick, nachdem EIN einziger Stab an der Innenecke zusätzlich entfernt wurde: Faktor 22, das Dreifache. Die Kapitel-26-Erfahrung „der Knick kostet nichts“ war also kein Naturgesetz, sondern das Ergebnis eines gut abgestimmten Designs — Ecken sind ein eigenes Handwerk, und Übung 32.4 überlässt es dem Optimierer.
Knick pur: Faktor 7, Innenecke geoeffnet: Faktor 22

Nein — die Ecke reflektiert kräftig (Faktor 7 statt 158). Aber ein einziger zusätzlich entfernter Stab an der Innenecke verdreifacht die Ausbeute: Die Kurve wird innen aufgeweitet, die Welle bekommt Platz zum Abbiegen. In der Photonik ist genau dieses Ecken-Tuning ein Standard-Handgriff. Merke: Defekt-Bauteile (Kanäle, Kurven, Verzweigungen) haben eigene Resonanzen und eigene Bänder — wer sie entwirft, misst nach. Oder lässt entwerfen: In Übung 32.4 darf der Kapitel-31-Optimierer die Ecke selbst kurieren — und findet den Innenecken-Trick ohne je ein Photonik-Lehrbuch gesehen zu haben.

Eine Begriffsfalle noch, weil sie naheliegt: Unser Kanal ist kein Hohlleiter im Sinn von Kapitel 17. Der EM-Hohlleiter (PEC-Wände, \(E = 0\)) hat eine Cutoff-Frequenz, unter der nichts läuft. Ein schallharter Kanal hat keinen Cutoff — an harten Wänden darf der Druck ja gerade maximal sein (die Vorzeichen-Probe von oben!), und eine ebene Welle läuft durch jeden noch so engen harten Schlauch. Was unseren Kanal nach unten begrenzt, ist nicht die Kanalbreite, sondern die Bandlücke seiner Wände.

Im Film siehst du den Dauerton in den Knick-Kanal (mit geöffneter Innenecke) einlaufen: erst den Flur entlang, dann um die Ecke und den Seitenarm hinauf bis zum Messpunkt (Kreuz) — während der Kristall ringsum dunkel bleibt. Links davor siehst du außerdem, was der Faktor 22 verschweigt: das kräftige Ringmuster der an Mund und Ecke zurückgeworfenen Wellen.

Code der Animation (nur in der HTML-Fassung)
NT_FILM2 = 2400
takte2 = tuple(range(60, NT_FILM2, 65))
hart_film = kristall_kanal(kanal_knick + [(5, 8)])
_, _, bilder2 = schall_lauf(hart_film, daempf_k, quelle_k, F_KNICK,
                            NT_FILM2, schnappschuesse=takte2)

fig, ax = plt.subplots(figsize=(5.4, 4.6))
b0 = bilder2[takte2[20]].copy()
b0[hart_film] = np.nan
vm2 = np.nanpercentile(np.abs(b0), 99.3)
kachel = ax.imshow(b0.T, origin="lower", cmap="RdBu",
                   vmin=-vm2, vmax=vm2)
ax.plot(*M_KNICK, "k+", ms=11)
ax.set_xticks([])
ax.set_yticks([])
titel = ax.set_title("", fontsize=10)
fig.subplots_adjust(top=0.9, bottom=0.04)


def bild2(i):
    b = bilder2[takte2[i]].copy()
    b[hart_film] = np.nan
    kachel.set_data(b.T)
    titel.set_text(f"Der Schall nimmt die Kurve — Schritt {takte2[i]}")
    return [kachel, titel]


anim = animation.FuncAnimation(fig, bild2, frames=len(takte2),
                               interval=130)
plt.close(fig)
HTML(anim.to_jshtml(default_mode="loop"))

32.7 Das akustische Pixel-Puzzle

Zum Schluss schließt sich der Kreis zu Kapitel 31: Wenn der Kern derselbe ist, muss auch das inverse Design wörtlich übertragbar sein. Wir stellen dem Optimierer dieselbe Aufgabe wie dort — lenke die Welle zu einem schräg versetzten Zielpunkt —, nur dass die 36 Pixel diesmal nicht aus \(\varepsilon = 6\) bestehen, sondern schallhart sind: Jedes gesetzte Pixel ist ein kleiner Klotz, das gesamte Suchgebiet ein 3D-Druckteil von wenigen Zentimetern.

Versuchsaufbau: Wörtlich Kapitel 31 — Design-Region aus 6 × 6 Pixeln à 4 × 4 Zellen, eine Dauerton-Quellzeile links, Zielpunkt schräg rechts oben, Zielgröße die dort aufsummierte Druckleistung. Optimierer: Bit-Flip-Bergsteigen, 250 Münzwürfe, behalte jede Verbesserung. Ein Lauf dauert 0,04 Sekunden — der ganze Entwurf gut zehn Sekunden.

NXp, NYp = 150, 110
RANDp = 10
daempf_p = daempfung(NXp, NYp, RANDp, s_max=0.35)
PIX, NPX, NPY = 4, 6, 6
X0, Y0 = 60, 43
ZIEL = (130, 88)
quelle_p = (18, slice(RANDp + 5, NYp - RANDp - 5))


def bewerte(pixel, feld_zurueck=False):
    hart = np.zeros((NXp, NYp), bool)
    for i in range(NPX):
        for j in range(NPY):
            if pixel[i, j]:
                hart[X0+i*PIX:X0+(i+1)*PIX,
                     Y0+j*PIX:Y0+(j+1)*PIX] = True
    reihen, p_end, bilder = schall_lauf(hart, daempf_p, quelle_p,
                                        1 / 20.0, 500,
                                        mikros=[ZIEL],
                                        schnappschuesse=(range(150, 500)
                                            if feld_zurueck else ()))
    summe = np.sum(reihen[151:, 0] ** 2)
    if feld_zurueck:
        karte = np.max([np.abs(b) for b in bilder.values()], axis=0)
        return summe, karte
    return summe


leer = bewerte(np.zeros((NPX, NPY), bool))
rng = np.random.default_rng(32)
pixel = np.zeros((NPX, NPY), bool)
wert = leer
verlauf = [wert]
for it in range(250):
    i, j = rng.integers(0, NPX), rng.integers(0, NPY)
    pixel[i, j] = ~pixel[i, j]
    neu = bewerte(pixel)
    if neu > wert:
        wert = neu
    else:
        pixel[i, j] = ~pixel[i, j]
    verlauf.append(wert)
zufall = [bewerte(rng.random((NPX, NPY)) > 0.5) for _ in range(20)]
_, karte = bewerte(pixel, feld_zurueck=True)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9.6, 4.0))
ax1.plot(verlauf)
ax1.axhline(leer, ls="--", color="gray", label="leere Region")
ax1.axhline(max(zufall), ls=":", color="C3",
            label="bestes Zufallsmuster")
ax1.set_xlabel("Flip-Versuche")
ax1.set_ylabel("Leistung am Ziel")
ax1.legend(fontsize=8)
ax2.imshow(karte.T, origin="lower", cmap="inferno")
for i in range(NPX):
    for j in range(NPY):
        if pixel[i, j]:
            ax2.add_patch(plt.Rectangle((X0 + i*PIX, Y0 + j*PIX),
                                        PIX, PIX, facecolor="none",
                                        edgecolor="c", lw=0.8))
ax2.plot(*ZIEL, "w+", ms=11)
ax2.set_xticks([])
ax2.set_yticks([])
plt.tight_layout()
plt.show()
print(f"leer {leer:.1f} -> optimiert {wert:.1f} "
      f"(Faktor {wert/leer:.1f}); "
      f"bestes Zufallsmuster {max(zufall):.1f}")
Abbildung 32.6: Das Pixel-Puzzle, akustische Fassung: Links der Optimierungs-Verlauf — von 37 (leere Region) auf 284, Faktor 7,7; das beste von 20 Zufallsmustern (rot) bleibt bei 149. Rechts der gefundene Umlenker bei der Arbeit (Karte: max |p|): Die schallharten Pixel (cyan) wirken zusammengewürfelt — kein Mensch hätte dieses Muster gezeichnet —, lenken aber nachweislich Faktor 7,7 mehr Leistung zum Kreuz als die leere Region. Dasselbe Verfahren, derselbe Kern, anderes Etikett — und das Ergebnis wäre als Zentimeter-Klötzchen druckbar.
leer 37.1 -> optimiert 284.0 (Faktor 7.7); bestes Zufallsmuster 149.3

Faktor 7,7 — sogar etwas mehr als die elektromagnetische Fassung in Kapitel 31 (dort 5,9), denn schallharte Pixel streuen stärker als \(\varepsilon = 6\). Damit ist der Bogen geschlossen: Die Methode des letzten Kapitels — Ziel formulieren, Vorwärtsmaschine einspannen, Optimierer würfeln lassen — funktioniert unverändert in einer anderen Physik. Das ist keine Schall-Besonderheit, sondern die eigentliche Lehre der Zugabe: Wer einen Wellenlöser und eine Zielfunktion hat, kann entwerfen — egal, welche Welle.

In der Spielwiese läuft das Puzzle live in deinem Browser (60 Flips statt 250, damit es flott bleibt). Aufträge: (1) Verschiebe das Ziel mit ZIEL_J = 20 nach unten — der Optimierer sollte den Umlenker spiegelbildlich neu erfinden. (2) Stelle ZIEL_J = 55, mitten in den Strahl: Jetzt findet er fast nichts. Warum? (Schau, wie hell das leere Feld dort schon ist — wo ohnehin ein Maximum liegt, kann Material nur stören.) (3) Erhöhe auf FLIPS = 150: Wie viel holt die zweite Hälfte der Flips noch heraus?

32.8 Das Kapitel-Programm

programme/kap32/kap32_akustik.py bündelt alle Befunde eigenständig und mit assert-Schranken: die Port-Probe (\(c = 1{,}000\)), das Transmissionsspektrum mit N-Reihen-Leiter und Lückenkanten samt Werkstatt-Umrechnung, den geraden Kanal und den Knick mit Innenecken-Kur, das akustische Pixel-Puzzle (Faktor > 4 gegen leer, besser als 20 Zufallsmuster) und die Impedanz-Tabelle. Reines NumPy mit fester Zufalls-Saat; Laufzeit etwa zwei Minuten.

TippMerkkasten
  • Übersetzungstabelle: \(E \to p\), \(H \to v\), \(\varepsilon \to 1/\kappa\), \(\mu \to \rho\), \(Z = \rho c\) — die Maxwell-Werkzeugkiste rechnet Akustik, weil die Gleichungsstruktur identisch ist. Aber: Randbedingungen mitübersetzen! Harte Wand = Druckbauch (kein Flip), offenes Ende = Druckknoten (Flip).
  • Schallhart: Holz, Alu, PLA reflektieren > 99,9 % — feste Körper sind für Luftschall, was PEC für Mikrowellen ist. Im Gitter: \(v = 0\) auf allen Kanten harter Zellen.
  • Werkstatt-Landkarte: Beim Schall im kHz-Bereich treffen sich baubare Wellenlänge (cm bis dm) und kostenloses Messgerät (Mikrofon + FFT) — der volle Kreis vorhersagen → simulieren → bauen → messen wird zu Hause schließbar.
  • Phononischer Kristall: Stabgitter mit \(r/a = 0{,}35\) sperrt \(f \cdot a/c \approx 0{,}33\) bis \(0{,}59\); jede Reihe drückt \(T\) um ≈ Faktor 4 (N-Reihen-Gesetz). Bei \(a = 50\) mm: Lücke 2,3 bis 4,1 kHz.
  • Defekte sind Bauteile: Eine fehlende Stab-Zeile leitet (Faktor 158); Ecken reflektieren und brauchen Tuning — Defekt-Bauteile haben eigene Bänder, also: nachmessen.
  • Methoden reisen: Bit-Flip-Bergsteigen + Akustik-Kern = druckbarer Schall-Umlenker. Wellenlöser + Zielfunktion = Entwurfsmaschine, unabhängig von der Wellensorte.

Roter Faden

Die Zugabe erntet quer durchs Buch: Der Kern aus Kapitel 9 wurde wortwörtlich übernommen (nur die Schilder getauscht), die Spiegelformel aus Kapitel 6 lieferte mit \(Z = \rho c\) die Schallhart-Näherung, die Messmethodik aus Kapitel 10 (Sweep, FFT, Referenzlauf, Rausch-Gegenprobe) wurde zum Wohnzimmer-Protokoll, die Bandlücken-Physik aus Kapitel 26 (Bragg-Bedingung, N-Reihen-Gesetz, Defekt-Logik) fand ihr akustisches Double, die Skaleninvarianz aus Kapitel 11 klebte die Hertz-Etiketten auf, und das inverse Design aus Kapitel 31 lief unverändert auf der neuen Physik. Dass all das funktioniert, ist die letzte und vielleicht wichtigste Lektion des Buchs: Du hast nicht 31 Kapitel Elektromagnetik gelernt, sondern 31 Kapitel Wellen, Numerik und Messkultur — Maxwell war der Lehrmeister, aber das Gelernte gehört dir überall.

Übungen

Ü 32.1 — Gel, Taucher, Stäbe (Verstehen). (a) Körpergewebe hat etwa \(Z \approx 1{,}6 \cdot 10^6\) kg/(m²s). Welcher Anteil der Leistung eines Ultraschallkopfs käme durch eine dünne Luftschicht ins Gewebe — und warum löst das Gel das Problem? (b) Jemand ruft einem Taucher vom Boot aus etwas zu. Wie viel Rufleistung erreicht sein Ohr unter Wasser? (c) Begründe mit den Zahlen aus dem Impedanz-Block, warum wir Holzstäbe als ideal schallhart rechnen durften.

Z_GEWEBE = 1.6e6
T_gel = 1 - ((Z_GEWEBE - Z_LUFT) / (Z_GEWEBE + Z_LUFT)) ** 2
Z_WASSER = 1000.0 * 1480.0
T_wasser = 1 - ((Z_WASSER - Z_LUFT) / (Z_WASSER + Z_LUFT)) ** 2
print(f"(a) durch Luft ins Gewebe: T = {T_gel*100:.2f} %")
print(f"(b) Luft -> Wasser: T = {T_wasser*100:.2f} %")
(a) durch Luft ins Gewebe: T = 0.10 %
(b) Luft -> Wasser: T = 0.11 %
  1. Nur etwa 0,1 Prozent — eine Luftschicht von Bruchteilen eines Millimeters genügt für Totalblockade, denn die Grenzen Luft–Gewebe wirken doppelt (hinein und am Schallkopf zurück). Das Gel (\(Z\) nahe Wasser/Gewebe) ersetzt die Luftschicht durch einen fast stufenlosen Übergang — dieselbe Logik wie die Anpassung in Kapitel 22, nur dass hier Weglassen der Fehlstelle genügt. (b) Ebenfalls ~0,1 Prozent: Die Wasseroberfläche ist von oben ein fast perfekter Spiegel — unter Wasser klingt die Welt über Wasser darum so dumpf und fern. (c) Holz steht mit \(Z = 2{,}8 \cdot 10^6\) noch über Gewebe und Wasser: 99,94 Prozent Reflexion. Der Fehler der Ideal-hart-Näherung (0,06 Prozent pro Stabkontakt) liegt weit unter jeder anderen Unsicherheit des Modells.

Ü 32.2 — Die Füllfaktor-Reihe (Verändern). Miss das Transmissionsspektrum (5 Reihen) für \(r/a = 0{,}25\), \(0{,}30\) und \(0{,}35\). Wie ändern sich Breite und Tiefe der Lücke? Formuliere eine Faustregel für den Werkstatt-Einsatz.

for r_a in (0.25, 0.30, 0.35):
    R_test = r_a * A_GIT
    hart = np.zeros((NXc, NYc), bool)
    y0 = (NYc - N_SAEULEN * A_GIT) / 2
    for r in range(5):
        for s in range(N_SAEULEN):
            cx = X_KRIST + (r + 0.5) * A_GIT
            cy = y0 + (s + 0.5) * A_GIT
            hart |= ((ii_c - cx) ** 2 + (jj_c - cy) ** 2
                     < R_test ** 2)
    T = leistungsspektrum(hart)[band] / spek_frei[band]
    it = np.argmin(np.where(fb < 0.045, T, 1.0))
    i = it
    while T[i] < 0.05:
        i -= 1
    fu = fb[i + 1]
    i = it
    while T[i] < 0.05:
        i += 1
    fo = fb[i - 1]
    print(f"r/a = {r_a}: T_min = {T[it]:.4f}, Luecke "
          f"f*a/c = {fu*A_GIT:.2f}..{fo*A_GIT:.2f} "
          f"(Breite {(fo-fu)*A_GIT:.2f})")
r/a = 0.25: T_min = 0.0159, Luecke f*a/c = 0.42..0.54 (Breite 0.12)
r/a = 0.3: T_min = 0.0055, Luecke f*a/c = 0.37..0.57 (Breite 0.20)
r/a = 0.35: T_min = 0.0024, Luecke f*a/c = 0.33..0.59 (Breite 0.26)

Dickere Stäbe wirken doppelt: Die Lücke wird breiter (Breite 0,12 → 0,20 → 0,26 — mehr als verdoppelt) und tiefer (\(T_\text{min}\) 0,015 → 0,005 → 0,002), und ihre Unterkante rutscht nach unten (die Welle wird im engeren Porenraum effektiv langsamer). Faustregel für die Werkstatt: So dicke Stäbe wie beschaffbar — die Lücke verzeiht dann auch Bohr-Toleranzen; mit \(d/a \lesssim 0{,}5\) wird die Lücke schmal und kippelig. Nach oben begrenzt die Nachbarschaft: Ab \(d/a \approx 0{,}9\) berühren sich die Stäbe fast und aus dem Gitter wird eine Wand mit Schlitzen.

Ü 32.3 — Dasselbe Gitter bei 40 kHz (Übertragen). Dein 3D-Drucker soll den Kristall für Ultraschall (40 kHz) drucken. (a) Welche Gitterkonstante und welcher Stabdurchmesser folgen aus der Skaleninvarianz? Ist das druckbar? (b) Kann deine 96-kHz-Soundkarte die Messung übernehmen? (c) Wie viele neue Simulationen brauchst du für den Entwurf?

f_mitte = (f_unten + f_oben) / 2 * A_GIT      # f*a/c der Lueckenmitte
a_us = f_mitte * C_LUFT / 40e3
print(f"f*a/c (Mitte) = {f_mitte:.2f}")
print(f"(a) a = {a_us*1000:.1f} mm, d = {0.7*a_us*1000:.1f} mm")
f*a/c (Mitte) = 0.46
(a) a = 4.0 mm, d = 2.8 mm
  1. \(a \approx 4\) mm mit \(d \approx 2{,}8\) mm — für einen 0,4-mm-Düsendrucker problemlos; das ganze 9 × 9-Gitter misst keine 4 Zentimeter. (b) Knapp nein: Nyquist erlaubt bei 96 kHz zwar theoretisch 48 kHz, aber gewöhnliche Mikrofone und Lautsprecher geben weit oberhalb von 20 kHz fast nichts mehr ab beziehungsweise auf — du bräuchtest 40-kHz- Ultraschallkapseln (Centartikel, in jedem Park-Sensor) und einen schnelleren Analog-Digital-Wandler oder ein Oszilloskop. Die Messkette, nicht die Mathematik, setzt die Grenze — die Landkarten-Lektion dieses Kapitels. (c) Null. Die Simulation war dimensionslos; nur die Etiketten ändern sich — die Skaleninvarianz aus Kapitel 11 in ihrer ganzen Pracht.

Ü 32.4 — Der Ecken-Doktor (Übertragen). Lass den Kapitel-31-Optimierer die Knick-Ecke kurieren: Die neun Stäbe der 3 × 3-Region innen an der Ecke (Reihen 3–5, Säulen 8–10) dürfen einzeln verschwinden. Optimiere mit Bit-Flip-Bergsteigen (30 Flips, Start: alle Stäbe vorhanden) die Leistung am Seitenausgang. Findet er den Innenecken-Trick?

ECKE = [(r, s) for r in (3, 4, 5) for s in (8, 9, 10)]


def knick_wert(frei_bits):
    fehlend = kanal_knick + [e for e, b in zip(ECKE, frei_bits)
                             if b]
    return dauerton(fehlend, M_KNICK, F_KNICK)[0]


bits = np.zeros(9, bool)
wert_k = knick_wert(bits)
print(f"Start (Knick pur): Faktor {wert_k/e_seite:.0f}")
rng_e = np.random.default_rng(7)
for it in range(30):
    k = rng_e.integers(0, 9)
    bits[k] = ~bits[k]
    neu = knick_wert(bits)
    if neu > wert_k:
        wert_k = neu
        frei = [e for e, b in zip(ECKE, bits) if b]
        print(f"  Flip {it}: entfernt {frei} -> "
              f"Faktor {wert_k/e_seite:.0f}")
    else:
        bits[k] = ~bits[k]
print(f"Ende: Faktor {wert_k/e_seite:.0f}")
Start (Knick pur): Faktor 7
  Flip 2: entfernt [(5, 8)] -> Faktor 22
  Flip 4: entfernt [(4, 10), (5, 8)] -> Faktor 31
Ende: Faktor 31

Ja — und zwar als ersten erfolgreichen Zug: Flip 2 entfernt genau den Innenecken-Stab (5, 8) und springt von Faktor 7 auf 22; Flip 4 legt mit (4, 10) nach (Faktor 31), danach ist der kleine Suchraum ausgereizt. Der Optimierer hat den Photonik-Standard-Handgriff in Sekunden wiederentdeckt — wie beim Bragg-Spiegel in Kapitel 31 gilt: Er kennt keine Regeln, aber er findet, was die Zielfunktion belohnt. Wer mag, vergrößert die Region auf 4 × 4 — der Suchraum wächst auf \(2^{16}\), das Bergsteigen bleibt bei ein paar Dutzend Läufen.

Das Kleingedruckte

Die Skulptur, die zuerst sperrte. Die erste experimentell vermessene akustische Bandlücke steckte in einem Kunstwerk: Órgano, eine minimalistische Skulptur von Eusebio Sempere im Museumspark von Madrid — Edelstahlrohre, 2,9 cm dick, im 10-cm-Raster. Martínez-Sala und Kollegen vermaßen sie 1995 (Nature 378, 241) und fanden den vorhergesagten Transmissions-Einbruch um 1,7 kHz. Unser Rundholz-Gitter ist also in bester Gesellschaft — und die Originalarbeit eine schöne Bestätigung dafür, dass die Hobby-Messung funktioniert: Auch dort stand die Skulptur unter freiem Himmel, nicht im Labor.

Festkörper: „Maxwell plus mehr”. Unsere Übersetzungstabelle gilt für Schall in Fluiden (Luft, Wasser). In Festkörpern wird es nicht einfacher, sondern reicher: Dort gibt es zusätzlich Scherwellen mit eigener, langsamerer Geschwindigkeit, und an jeder Grenzfläche wandeln Druck- und Scherwellen ineinander um (Modenkonversion). Die Elastodynamik hat darum mehr Feldkomponenten als Maxwell, nicht weniger. Für unser Gitter ist das egal — der Schall bleibt in der Luft, die Stäbe sind nur harte Ränder —, aber wer Ultraschall durch Bauteile schicken will (Werkstoffprüfung), braucht das volle Programm.

Akustische Metamaterialien und schwebende Tröpfchen. Auch Block D reist mit: Es gibt akustische Metamaterialien mit negativer effektiver Dichte oder Kompressibilität (Resonatoren statt Drähte und Ringe), akustische Tarnkappen-Prototypen und Labyrinth-Strukturen, die Schall auf Bruchteile seiner Wellenlänge falten. Und die Levitation gibt es wörtlich: Ein Raster aus 40-kHz-Kapseln (das TinyLev-Design ist quelloffen und 3D-druckbar) hält Styroporkugeln und Wassertröpfchen in den Druckknoten einer Stehwelle schweben — Strahlungsdruck wie in Kapitel 18, nur in Luft statt Licht.

Messen im Wohnzimmer, ehrlich. Der Raum reflektiert, und \(T(f)\) aus zwei Sweeps wellt sich entsprechend. Der Profi-Trick heißt Zeitfensterung (Gating): Statt eines Sweeps nimmt man die Impulsantwort auf (Händeklatschen genügt zur Probe) und schneidet im Zeitsignal alles ab, was nach dem Direktschall eintrifft — Wandechos brauchen ein paar Millisekunden länger, und nach der FFT des gefensterten Signals ist der Raum fast verschwunden. Das ist exakt die Fenster-Logik aus Kapitel 10, nur auf Echos statt auf Spektren angewandt. Für unseren Faktor-100-Einbruch ist sie Kür, nicht Pflicht; wer aber die Lückenkanten auf Prozent genau mit der Simulation vergleichen will, kommt an ihr nicht vorbei.

Und damit ist die Zugabe gespielt. Das Brett liegt im Baumarkt, der Bohrplan in Abbildung 32.3 — was du daraus baust und misst, ist dein erstes eigenes Wellen-Experiment nach diesem Buch. Viel Freude dabei.