Phương trình tiến lên cần được rời rạc để được sử dụng cho phương pháp Crank-Nicolson. Ai đó có thể chỉ cho tôi làm thế nào để làm điều đó?
Phương trình tiến lên cần được rời rạc để được sử dụng cho phương pháp Crank-Nicolson. Ai đó có thể chỉ cho tôi làm thế nào để làm điều đó?
Câu trả lời:
Bắt đầu với phương trình thăng tiến là hình thức bảo thủ,
Phương pháp Crank-Nicolson bao gồm thời gian trung bình chênh lệch trung tâm.
Về ký hiệu, kí hiệu là cho điểm trong không gian, và superscript là cho điểm trong thời gian.
Các điểm tại là trong tương lai: chúng là ẩn số. Bây giờ chúng ta cần sắp xếp lại các phương trình trên để tất cả các điều đã biết đều nằm trên rhs và ẩn số nằm trên lhs.
Thay thế,
cho
Đây là phương trình thăng tiến được sử dụng bằng phương pháp Crank-Nicolson. Bạn có thể viết nó như một phương trình ma trận,
Một vài lời cảnh báo. Đây là giải pháp cơ bản mà bạn muốn, nhưng bạn sẽ cần đưa vào một số loại điều kiện biên cho một vấn đề được đặt ra. Ngoài ra, Crank-Nicolson không nhất thiết là phương pháp tốt nhất cho phương trình thăng tiến. Đó là thứ hai chính xác và ổn định vô điều kiện , đó là tuyệt vời. Tuy nhiên, nó sẽ tạo ra (như với tất cả các bút chì khác biệt tập trung) dao động giả nếu bạn có các giải pháp cực đại rất sắc nét hoặc các điều kiện ban đầu.
Tôi đã viết đoạn mã sau cho bạn bằng Python, nó sẽ giúp bạn bắt đầu. Mã giải phương trình thăng tiến cho một đường cong Gaussian ban đầu di chuyển sang phải với vận tốc không đổi.
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()