为什么我对一阶波动方程的模拟不稳定?

计算科学 有限差分 稳定 波传播
2021-12-13 10:09:34

根据等式

yt=ayx

我在python中模拟了这个。我使用了中心微分,并根据线性方程 的 Von-Neumann 稳定性标准确定了步长。Δt=Δx22a

这就是我得到的:https ://gyazo.com/86024db42f71a6b5cb34eca7eb0d115f

import os
import numpy as np

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.animation as animation

alpha = 1
seconds = 1000
dx = 1
dt = .1/alpha*dx**2
iter = int(np.round(seconds/dt))
print(iter, dt)


x = np.linspace(0,1000,1000)
# z = np.linspace(0,990, 10, dtype= int)
y = np.zeros([iter,1000])
y[0,:] = 50*np.sin(x[:]*np.pi/1000)
dy_t = np.zeros(1000)


for t in range(0,iter-1):

    for x in range(1, 998):

        dy_t[x] = -alpha*(y[t, x+1]-y[t,x-1])/(2*dx)


    for x in range(1,998):
        y[t+1,x] = y[t,x]+dy_t[x]*dt


# animation
fig, ax = plt.subplots()
line, = ax.plot(y[0,:])
def init():
    line.set_ydata([np.nan] * 1000)
    return line,

def animate(i):
    line.set_ydata(y[i,:])
    return line,

ani = animation.FuncAnimation(
fig, animate, range(0, iter), init_func=init, interval=5, blit=True, save_count=50)
plt.show()
2个回答

空间中心差和时间前向欧拉平流方程的数值解是无条件不稳定的。因此,您看到的行为是预期的。

这是 Gil Strang ( MIT 18.086 ) 的精彩讲座,他在其中讨论了这种方法的不稳定性。他还展示了如何修改简单的中心差分法以产生条件稳定的 Lax-Friedrichs 和 Lax-Wendroff 方法。

假设您真的想在空间中使用中心差分方案并在时间上使用前差分,我将回答这个问题。

考虑问题

ut+aux=0,x(xL,xR),t[0,T]
和一个数字方案
ujn+1=Hj(un;a,Δt,h)
如果存在,则称该方案是弱稳定的C=C(T)这样
unCu0,nΔtT
一个等价的定义是 如果,那么我们说它是稳定的(强稳定)。FTCS 方案 从来都不是强稳定的。它在条件 下是弱稳定的 这不是一个有用的方案: (1) 时间步太小。(2) 长时间积分无用。
un+1(1+CΔt)un
C=1
ujn+1ujnΔt+uj+1nuj1n2h=0
Δt(ha)2

您的代码中似乎有一些错误,您必须自己修复。我在下面给出了我自己的实现,其中时间步长被选择为 用 Python2 运行它;对于 Python3,您必须进行一些更改。

Δt=CFL(ha)2

import numpy as np
import matplotlib.pyplot as plt

def smooth(x):
    return np.sin(2*np.pi*x)

def update_ftcs(nu, u):
    unew = np.empty_like(u)
    unew[0] = u[0] + 0.5*nu*(u[-2] - u[1])
    unew[1:-1] = u[1:-1] + 0.5*nu*(u[0:-2] - u[2:])
    unew[-1] = unew[0]
    return unew

def solve():
    scheme     = 'FTCS'
    N          = 100
    cfl        = 0.95
    Tf         = 1.0
    uinit      = smooth
    xmin, xmax = 0.0, 1.0
    a          = 1.0

    h = (xmax - xmin)/N
    dt= cfl * (h / np.abs(a))**2
    nu= a * dt / h

    x = np.linspace(xmin, xmax, N+1)
    u = uinit(x)

    fig = plt.figure()
    ax = fig.add_subplot(111)
    line1, = ax.plot(x, u, 'r')
    line2, = ax.plot(x, u, 'b')
    ax.set_xlabel('x'); ax.set_ylabel('u')
    plt.legend(('Numerical','Exact'))
    plt.title('N='+str(N)+', CFL='+str(cfl)+', Scheme='+scheme)
    plt.draw(); plt.pause(0.1)
    wait = raw_input("Press enter to continue ")

    t, it = 0.0, 0
    while t < Tf:
        u = update_ftcs(nu, u)
        t += dt; it += 1
        if it%100 == 0:
            line1.set_ydata(u)
            line2.set_ydata(uinit(x-a*t))
            plt.draw(); plt.pause(0.1)
    plt.show()

solve()