Esquemas de Diferenças Finitas Explícitos e Implícitos para a Equação de Onda Unidimensional

Introdução à Equação de Onda

A equação de onda é uma equação diferencial parcial fundamental na física para modelar a propagação de ondas. Em sua forma unidimensional, a expressão matemática é dada por:

$$ \frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2} $$

Onde $u$ representa a amplitude da onda, $t$ é a variável temporal, $x$ é a coordenada espacial e $c$ denota a velocidade de propagação da onda.

Abordagem Explícita

O método de diferenças finitas explícito calcula o estado futuro do sistema utilizando exclusivamente valores conhecidos dos passos de tempo atuais e anteriores. Aplicando diferenças centrais tanto para o tempo quanto para o espaço, obtemos a seguinte discretização:

$$ \frac{u_i^{n+1} - 2u_i^n + u_i^{n-1}}{\Delta t^2} = c^2 \frac{u_{i+1}^n - 2u_i^n + u_{i-1}^n}{\Delta x^2} $$

Nesta formulação, $u_i^n$ é o valor da onda na posição $i$ e no instante $n$. O isolamento de $u_i^{n+1}$ permite o cálculo direto e iterativo da malha.

Abordagem Impllícita

Por outro lado, o esquema implícito avalia as derivadas espaciais no passo de tempo futuro ($n+1$). A equação discretizada assume a forma:

$$ \frac{u_i^{n+1} - 2u_i^n + u_i^{n-1}}{\Delta t^2} = c^2 \frac{u_{i+1}^{n+1} - 2u_i^{n+1} + u_{i-1}^{n+1}}{\Delta x^2} $$

Essa escolha exige a resolução de um sistema de equações lineares a cada iteração temporal, uma vez que os valores de $u^{n+1}$ estão acoplados espacialmente.

Implementação Computacional em Python

Abaixo estão apresentadas implementações otimizadas para ambos os esqeumas. O código explícito utiliza operações vetorizadas do NumPy para evitar laços aninhados, enquanto o código implícito emprega matrizes esparsas para resolver o sistema linear de forma eficiente.

Simulação com Método Explícito


import numpy as np
import matplotlib.pyplot as plt

# Configuração do domínio e parâmetros físicos
domain_length = 10.0
grid_points = 150
spatial_step = domain_length / (grid_points - 1)
total_time = 2.0
time_steps = 800
time_step = total_time / time_steps
wave_speed = 1.0

# Malhas espaciais e temporais
x_grid = np.linspace(0, domain_length, grid_points)
t_grid = np.linspace(0, total_time, time_steps)

# Matriz de solução e condição inicial
wave_field = np.zeros((grid_points, time_steps))
wave_field[:, 0] = np.sin(np.pi * x_grid / domain_length)
wave_field[:, 1] = wave_field[:, 0]  # Condição de velocidade inicial nula

# Constante de Courant ao quadrado
courant_sq = (wave_speed * time_step / spatial_step) ** 2

# Iteração temporal vetorizada
for step in range(1, time_steps - 1):
    wave_field[1:-1, step + 1] = (
        2 * wave_field[1:-1, step] - wave_field[1:-1, step - 1] +
        courant_sq * (wave_field[2:, step] - 2 * wave_field[1:-1, step] + wave_field[:-2, step])
    )

# Visualização dos resultados
plt.figure(figsize=(8, 5))
plt.imshow(wave_field, extent=[0, total_time, 0, domain_length], origin='lower', aspect='auto', cmap='viridis')
plt.colorbar(label='Amplitude da Onda')
plt.xlabel('Tempo (s)')
plt.ylabel('Posição (m)')
plt.title('Propagação de Onda - Esquema Explícito')
plt.show()

Simulação com Método Implícito


import numpy as np
import matplotlib.pyplot as plt
from scipy.sparse import diags
from scipy.sparse.linalg import spsolve

# Parâmetros do sistema
L_x = 10.0
N_x = 150
dx = L_x / (N_x - 1)
T_max = 2.0
N_t = 800
dt = T_max / N_t
c_wave = 1.0

x_vals = np.linspace(0, L_x, N_x)
t_vals = np.linspace(0, T_max, N_t)

# Inicialização do campo
U = np.zeros((N_x, N_t))
U[:, 0] = np.sin(np.pi * x_vals / L_x)
U[:, 1] = U[:, 0]

# Parâmetro de malha
r = (c_wave * dt / dx) ** 2

# Construção da matriz tridiagonal esparsa (constante no tempo)
main_diag = (1 + 2 * r) * np.ones(N_x - 2)
off_diag = -r * np.ones(N_x - 3)
A_sparse = diags([off_diag, main_diag, off_diag], [-1, 0, 1], format='csr')

# Resolução do sistema linear a cada passo
for k in range(1, N_t - 1):
    # Vetor do lado direito (RHS)
    rhs = 2 * U[1:-1, k] - U[1:-1, k - 1]
    
    # Ajuste para condições de contorno de Dirichlet (u=0 nas bordas)
    # Como U[0, k+1] e U[-1, k+1] são 0, não precisamos adicionar termos extras ao rhs.
    
    # Resolve o sistema para o passo k+1
    U[1:-1, k + 1] = spsolve(A_sparse, rhs)

# Plotagem do campo de onda
plt.figure(figsize=(8, 5))
plt.imshow(U, extent=[0, T_max, 0, L_x], origin='lower', aspect='auto', cmap='plasma')
plt.colorbar(label='Amplitude da Onda')
plt.xlabel('Tempo (s)')
plt.ylabel('Posição (m)')
plt.title('Propagação de Onda - Esquema Implícito')
plt.show()

Análise Comparativa dos Esquemas

1. Tratamento da Derivada Temporal

  • Esquema Explícito: A derivada temporal é avaliada com base em estados passados e presentes. A atualização do estado futuro é uma função direta e desacoplada: $u^{n+1} = \mathcal{F}(u^n, u^{n-1})$.
  • Esquema Implícito: A formulação envolve o estado futuro na avaliação das derivadas espaciais, resultando em uma dependência implícita: $u^{n+1} = \mathcal{F}(u^n, u^{n-1}, u^{n+1})$, o que obriga a inversão de matrizes.

2. Estabilidade Numérica

  • Explícito: Sofre de estabilidade condicional. O passo de tempo deve obedecer estritamente ao critério de Courant-Friedrichs-Lewy (CFL). Violações desse limite resultam em explosões numéricas.
  • Implícito: Geralmente exibe estabilidade incondicional. Permite o uso de passos de tempo arbitrariamente grandes sem que a solução diverja, sendo ideal para problemas rígidos (stiff).

3. Custo Computacional

  • Explícito: Baixo custo por iteração, pois envolve apenas multiplicações e adições de matrizes/vetores. É altamente paralelizável e eficiente para malhas massivas.
  • Implícito: Alto custo por iteração devido à necessidade de fatorar e resolver sistemas lineares (ou não lineares). O uso de matrizes esparsas e pré-condicionadores é mandatório para viabilizar a simulação em larga escala.

4. Cenários de Aplicação

  • Explícito: Preferido em dinâmica de fluidos computacional (CFD), acústica e simulações de ondas sísmicas onde a precisão temporal exige passos de tempo pequenos.
  • Implícito: Amplamente adotado em difusão térmica, mecânica dos sólidos e simulações de circuitos, onde os fenômenos de interesse ocorrem em escalas de tempo muito maiores que as constantes de estabilidade explícita.

5. Dissipação e Dispersão Numérica

  • Explícito: Pode introduzir erros de dispersão significativos, causando a separação artificial de frequências e distorcendo a frente de onda ao longo do tempo.
  • Implícito: Tende a ser mais dissipativo, amortecendo as componentes de alta frequência da solução, o que pode suavizar artificialmente gradientes íngremes, mas preserva a estabilidade global.

Tags: equação de onda diferenças finitas método explícito método implícito Python

Publicado em 10-20 08:14