Simulasi Gelombang 1 Dimensi#

Berikut adalah langkah-langkah pendekatan finite difference dari persamaan gelombang:

\[ \frac{\partial^2 y}{\partial x^2} = \frac{1}{c^2} \frac{\partial^2 y}{\partial t^2} \]

hingga menjadi bentuk skema numerik eksplisit:

\[ y[1:-1, n+1] = 2y[1:-1, n] - y[1:-1, n-1] + \left(\frac{c \, dt}{dx} \right)^2 \left( y[2:, n] - 2y[1:-1, n] + y[:-2, n] \right) \]

1. Diskritisasi dengan Skema Selisih Hingga#

Gunakan skema finite difference untuk mendekati turunan parsial:

a. Turunan Kedua terhadap Waktu (t)#

\[ \frac{\partial^2 y}{\partial t^2} \approx \frac{y_{i}^{n+1} - 2y_{i}^{n} + y_{i}^{n-1}}{dt^2} \]

b. Turunan Kedua terhadap Ruang (x)#

\[ \frac{\partial^2 y}{\partial x^2} \approx \frac{y_{i+1}^{n} - 2y_{i}^{n} + y_{i-1}^{n}}{dx^2} \]

2. Substitusi ke dalam Persamaan Gelombang#

\[ \frac{y_{i+1}^{n} - 2y_{i}^{n} + y_{i-1}^{n}}{dx^2} = \frac{1}{c^2} \frac{y_{i}^{n+1} - 2y_{i}^{n} + y_{i}^{n-1}}{dt^2} \]

Pindah ruas:

\[ \frac{y_{i}^{n+1} - 2y_{i}^{n} + y_{i}^{n-1}}{dt^2} = {c^2} \frac{y_{i+1}^{n} - 2y_{i}^{n} + y_{i-1}^{n}}{dx^2} \]

Kali silang dengan \(dt^2\) untuk menyingkirkan penyebut:

\[ y_{i}^{n+1} - 2y_{i}^{n} + y_{i}^{n-1} = {c^2}{dt^2} \frac{y_{i+1}^{n} - 2y_{i}^{n} + y_{i-1}^{n}}{dx^2} \]

Sehingga diperoleh:

\[ y_{i}^{n+1} = 2y_{i}^{n} - y_{i}^{n-1} + \left(\frac{c dt}{dx} \right)^2 \left( y_{i+1}^{n} - 2y_{i}^{n} + y_{i-1}^{n} \right) \]

3. Penulisan dalam Notasi Array#

Dalam notasi array Python dengan NumPy:

  • ( i ) → indeks spasial ([1:-1]) (menghindari batas)

  • ( n ) → indeks waktu

\[ y[1:-1, n+1] = 2y[1:-1, n] - y[1:-1, n-1] + \left(\frac{c dt}{dx} \right)^2 (y[2:, n] - 2y[1:-1, n] + y[:-2, n]) \]

Persamaan ini merupakan bentuk eksplisit Finite Difference Method (FDM) untuk menyelesaikan persamaan gelombang 1D.

Semoga jelas! 😊

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Parameter simulasi
c = 1.0           # Kecepatan gelombang
L = 10.0          # Panjang domain
T = 15.0          # Waktu simulasi
dx = 0.02         # Spasi grid spasial
dt = 0.01         # Interval waktu
frame_step = 10    # Ambil 1 frame setiap n langkah waktu (diubah sesuai kebutuhan)

x = np.arange(0, L, dx)  # Array posisi
t = np.arange(0, T, dt)  # Array waktu
Nx = len(x)              # Jumlah titik grid spasial
Nt = len(t)              # Jumlah langkah waktu

# Cek CFL
CFL = c * dt / dx
print(f"Angka CFL: {CFL:.2f}")
if CFL >= 1:
    print("Peringatan: Simulasi mungkin tidak stabil!")

# Kondisi awal (Gaussian pulse)
x0 = L/2           # Posisi pusat gelombang
sigma = 0.5        # Lebar gelombang
y0 = np.exp(-(x - x0)**2 / (2*sigma**2))  # Displacement awal
vy0 = np.zeros(Nx) # Kecepatan awal (nol)

# Inisialisasi array solusi
y = np.zeros((Nx, Nt))
y[:, 0] = y0

# Mengisi langkah waktu pertama (n=1)
y[1:-1, 1] = y[1:-1, 0] + 0.5*(c*dt/dx)**2 * (y[2:, 0] - 2*y[1:-1, 0] + y[:-2, 0])

# Boundary condition tetap (Dirichlet)
y[0, 0] = y[0, 1] = 0
y[-1, 0] = y[-1, 1] = 0

# Iterasi waktu menggunakan metode finite difference
for n in range(1, Nt-1):
    # Update persamaan gelombang
    y[1:-1, n+1] = 2*y[1:-1, n] - y[1:-1, n-1] + (c*dt/dx)**2 * (y[2:, n] - 2*y[1:-1, n] + y[:-2, n])
    
    # Boundary condition
    y[0, n+1] = 0
    y[-1, n+1] = 0

# Setup plot
fig, ax = plt.subplots(figsize=(10,5))
line, = ax.plot(x, y[:,0], lw=2)
ax.set_xlim(0, L)
ax.set_ylim(-1.1, 1.1)
ax.set_xlabel('Posisi (x)')
ax.set_ylabel('Simpangan (y)')
ax.set_title('Simulasi Gelombang 1D (Frame Reduced)')
ax.grid(True)

# Fungsi animasi dengan frame skipping
def animate(frame):
    line.set_ydata(y[:, frame])
    return line,

# Hitung jumlah frame yang akan dirender
total_frames = Nt // frame_step
print(f"Jumlah frame asli: {Nt}")
print(f"Jumlah frame setelah reduksi: {total_frames}")

# Buat animasi dengan frame yang direduksi
ani = FuncAnimation(
    fig, 
    animate,
    frames=range(0, Nt, frame_step),  # Ambil frame setiap n langkah
    interval=20*frame_step,           # Sesuaikan interval untuk mempertahankan kecepatan
    blit=True
)

plt.close()

# Tampilkan animasi
from IPython.display import HTML
HTML(ani.to_jshtml())
Angka CFL: 0.50
Jumlah frame asli: 1500
Jumlah frame setelah reduksi: 150
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Parameter simulasi
c = 1.0           # Kecepatan gelombang
L = 10.0          # Panjang domain
T = 15.0          # Waktu simulasi
dx = 0.02         # Spasi grid spasial
dt = 0.01         # Interval waktu
frame_step = 10    # Ambil 1 frame setiap n langkah waktu (diubah sesuai kebutuhan)

x = np.arange(0, L, dx)  # Array posisi
t = np.arange(0, T, dt)  # Array waktu
Nx = len(x)              # Jumlah titik grid spasial
Nt = len(t)              # Jumlah langkah waktu

# Cek CFL
CFL = c * dt / dx
print(f"Angka CFL: {CFL:.2f}")
if CFL >= 1:
    print("Peringatan: Simulasi mungkin tidak stabil!")

# Kondisi awal (Gaussian pulse)
x0 = L/2           # Posisi pusat gelombang
sigma = 0.5        # Lebar gelombang
y0 = -(x - x0) / (sigma**2) * np.exp(-(x - x0)**2 / (2 * sigma**2))  # Displacement awal
vy0 = np.zeros(Nx) # Kecepatan awal (nol)

# Inisialisasi array solusi
y = np.zeros((Nx, Nt))
y[:, 0] = y0

# Mengisi langkah waktu pertama (n=1)
y[1:-1, 1] = y[1:-1, 0] + 0.5*(c*dt/dx)**2 * (y[2:, 0] - 2*y[1:-1, 0] + y[:-2, 0])

# Boundary condition tetap (Dirichlet)
y[0, 0] = y[0, 1] = 0
y[-1, 0] = y[-1, 1] = 0

# Iterasi waktu menggunakan metode finite difference
for n in range(1, Nt-1):
    # Update persamaan gelombang
    y[1:-1, n+1] = 2*y[1:-1, n] - y[1:-1, n-1] + (c*dt/dx)**2 * (y[2:, n] - 2*y[1:-1, n] + y[:-2, n])
    
    # Boundary condition
    y[0, n+1] = 0
    y[-1, n+1] = 0

# Setup plot
fig, ax = plt.subplots(figsize=(10,5))
line, = ax.plot(x, y[:,0], lw=2)
ax.set_xlim(0, L)
ax.set_ylim(-1.1, 1.1)
ax.set_xlabel('Posisi (x)')
ax.set_ylabel('Simpangan (y)')
ax.set_title('Simulasi Gelombang 1D (Frame Reduced)')
ax.grid(True)

# Fungsi animasi dengan frame skipping
def animate(frame):
    line.set_ydata(y[:, frame])
    return line,

# Hitung jumlah frame yang akan dirender
total_frames = Nt // frame_step
print(f"Jumlah frame asli: {Nt}")
print(f"Jumlah frame setelah reduksi: {total_frames}")

# Buat animasi dengan frame yang direduksi
ani = FuncAnimation(
    fig, 
    animate,
    frames=range(0, Nt, frame_step),  # Ambil frame setiap n langkah
    interval=20*frame_step,           # Sesuaikan interval untuk mempertahankan kecepatan
    blit=True
)

plt.close()

# Tampilkan animasi
from IPython.display import HTML
HTML(ani.to_jshtml())
Angka CFL: 0.50
Jumlah frame asli: 1500
Jumlah frame setelah reduksi: 150