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