Die Advektionsgleichung muss diskretisiert werden, um für die Crank-Nicolson-Methode verwendet zu werden. Kann mir jemand zeigen, wie das geht?
Die Advektionsgleichung muss diskretisiert werden, um für die Crank-Nicolson-Methode verwendet zu werden. Kann mir jemand zeigen, wie das geht?
Antworten:
Beginnend mit der Advektionsgleichung ist konservative Form,
Die Crank-Nicolson-Methode besteht aus einer zeitlich gemittelten zentrierten Differenz.
In Bezug auf die Notation beziehen sich Indizes auf Punkte im Raum und hochgestellte Indizes auf Zeitpunkte.
Die Punkte bei liegen in der Zukunft: Sie sind unbekannt. Wir müssen nun die obige Gleichung neu anordnen, so dass alle bekannten auf der rechten und die unbekannten auf der rechten Seite stehen.
Die Substitution vornehmen,
gibt,
Dies ist die Advektionsgleichung, die nach der Crank-Nicolson-Methode diskretisiert wurde. Sie können es als Matrixgleichung schreiben,
Ein paar warnende Worte. Dies ist die grundlegende Lösung, die Sie wollten, aber Sie müssen eine Art Randbedingung für ein gut gestelltes Problem angeben. Außerdem ist Crank-Nicolson nicht unbedingt die beste Methode für die Advektionsgleichung. Es ist genau zweiter Ordnung und bedingungslos stabil , was fantastisch ist. Es wird jedoch (wie bei allen Schablonen mit zentrierter Differenz) eine Störschwingung erzeugen, wenn Sie sehr scharfe Spitzenlösungen oder Anfangsbedingungen haben.
Ich habe den folgenden Code für Sie in Python geschrieben, damit Sie loslegen können. Der Code löst die Advektionsgleichung für eine anfängliche Gaußsche Kurve, die sich mit konstanter Geschwindigkeit nach rechts bewegt.
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()