Considere uma corda elástica de comprimento
cujas extremidades estão fixas. A corda é posta em movimento sem velocidade inicial a partir de uma posição inicial
. Em cada um dos Problemas 1 a 4, execute os seguintes passos. Deixe
e
nas partes (b) a (d).
(d) Construa uma animação da solução no tempo por pelo menos um período.
3.
(d) Construa uma animação da solução no tempo por pelo menos um período.
3.
Passo 1
Estamos resolvendo o problema da onda numa corda de comprimento fixo L com extremidades presas, velocidade de propagação a e condicionada pela forma inicial u(x,0)=f(x)=8x(L−x)²/L³, sem velocidade inicial. Na parte (d) queremos montar uma animação da solução u(x,t) para um período completo com L=10 e a=1.
Passo 2
Para extremidades presas temos a expansão em série de senos:
onde os coeficientes são
Passo 3
Para implementar a animação numericamente, truncamos a série em N termos (por exemplo N=50) e calculamos cada A_n por quadratura numérica: geramos um vetor x no intervalo [0,L], avaliamos f(x)·sin(nπx/L) e usamos método trapezoidal para aproximar a integral.
Passo 4
Definimos então uma grade de posições x e de instantes t que cubra ao menos um período completo T=2L/a. Construímos uma função u(x,t) que soma até N termos:
Passo 5
Usamos matplotlib.animation.FuncAnimation para criar a animação, definindo uma função de atualização que recalcula u(x,t_k) e atualiza o gráfico para cada quadro k.
Resposta
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# parâmetros
L = 10.0
a = 1.0
N = 50 # número de modos na série
nx = 500 # pontos no espaço
nt = 200 # quadros da animação
# definição de f(x)
def f(x):
return 8 * x * (L - x)**2 / L**3
# malha espacial
x = np.linspace(0, L, nx)
# cálculo dos coeficientes A_n via regra do trapézio
def compute_An(n):
y = f(x) * np.sin(n * np.pi * x / L)
return (2.0 / L) * np.trapz(y, x)
A_n = np.array([compute_An(n) for n in range(1, N+1)])
# função que calcula u(x,t) truncada em N modos
def u_xt(t):
n = np.arange(1, N+1)
# forma vetorizada: (A_n * cos(...) * sin(...)) somados
modes = A_n[:, None] * np.cos(n * np.pi * a * t / L)[:, None] * \
np.sin(n * np.pi * x[None, :] / L)
return modes.sum(axis=0)
# preparar figura
total_time = 2 * L / a # um período completo
ts = np.linspace(0, total_time, nt)
fig, ax = plt.subplots()
line, = ax.plot(x, u_xt(0), lw=2)
ax.set_xlim(0, L)
ax.set_ylim(1.2 * f(x).min(), 1.2 * f(x).max())
ax.set_xlabel('x')
ax.set_ylabel('u(x,t)')
ax.set_title('Animação da onda na corda')
# função de atualização para cada quadro
def update(frame):
t = ts[frame]
y = u_xt(t)
line.set_data(x, y)
ax.set_title(f't = {t:.2f} s')
return line,
anim = FuncAnimation(fig, update, frames=nt, blit=True, interval=50)
# para salvar como GIF ou MP4:
# anim.save('onda_corda.gif', writer='imagemagick', fps=30)
# ou
# anim.save('onda_corda.mp4', writer='ffmpeg', fps=30)
plt.show()