A equação de advecção precisa ser discretizada para ser usada no método Crank-Nicolson. Alguém pode me mostrar como fazer isso?
A equação de advecção precisa ser discretizada para ser usada no método Crank-Nicolson. Alguém pode me mostrar como fazer isso?
Respostas:
Começando com a equação de advecção é de forma conservadora,
O método Crank-Nicolson consiste em uma diferença centrada no tempo médio.
Em relação à notação, os subscritos são para pontos no espaço e os sobrescritos são para pontos no tempo.
Os pontos em estão no futuro: são desconhecidos. Agora precisamos reorganizar a equação acima para que todos os conhecidos estejam no rhs e os desconhecidos no lhs.
Fazendo a substituição,
dá,
Esta é a equação de advecção discretizada usando o método Crank-Nicolson. Você pode escrevê-lo como uma equação matricial,
β=1/2
Algumas palavras de aviso. Esta é a solução básica que você queria, mas precisará incluir algum tipo de condição de contorno para um problema bem colocado. Além disso, Crank-Nicolson não é necessariamente o melhor método para a equação de advecção. É de segunda ordem precisa e incondicionalmente estável , o que é fantástico. No entanto, ele gerará (como em todos os estênceis de diferença centralizada) uma oscilação espúria se você tiver soluções pontiagudas muito acentuadas ou condições iniciais.
Eu escrevi o código a seguir para você em Python, ele deve começar. O código resolve a equação de advecção para uma curva gaussiana inicial movendo-se para a direita com velocidade constante.
from __future__ import division
from scipy.sparse import spdiags
from scipy.sparse.linalg import spsolve
import numpy as np
import pylab
def make_advection_matrices(z, r):
"""Return matrices A and M for advection equations"""
ones = np.ones(len(z))
A = spdiags( [-beta*r, ones, beta*r], (-1,0,1), len(z), len(z) )
M = spdiags( [(1-beta) * r, ones, -(1-beta) * r], (-1,0,1), len(z), len(z) )
return A.tocsr(), M.tocsr()
def plot_iteration(z, u, iteration):
"""Plot the solver progress"""
pylab.plot(z, u, label="Iteration %d" % iteration)
# Set up basic constants
beta = 0.5
J = 200 # total number of mesh points
z = np.linspace(-10,10,J) # vertices
dz = abs(z[1]-z[0]) # space step
dt = 0.2 # time step
v = 2 * np.ones(len(z)) # velocity field (constant)
r = v / 2 * dt / dz
# Initial conditions (peak function)
gaussian = lambda z, height, position, hwhm: height * np.exp(-np.log(2) * ((z - position)/hwhm)**2)
u_init = gaussian(z, 1, -3, 2)
A, M = make_advection_matrices(z, r)
u = u_init
for i in range(10):
u = spsolve(A, M * u)
plot_iteration(z, u, i)
pylab.legend()
pylab.show()