Korteweg-de Vries 方程¶
日期 | 2018-10-24(最后修改),2010-09-06(创建) |
---|
此页面展示了如何使用 Korteweg-de Vries 方程 在周期域上求解,使用 线方法,空间导数使用伪谱方法计算。在此方法中,导数在频域中计算,首先对数据应用 FFT,然后乘以适当的值,并使用逆 FFT 转换回空间域。这种微分方法由 scipy.fftpack 模块中的 diff 函数实现。
我们离散化空间域,并使用 scipy.fftpack 模块中定义的 diff 函数计算空间导数。在以下代码中,此函数被赋予别名 psdiff,以避免将其与 numpy 函数 diff 混淆。通过仅离散化空间维度,我们得到一个常微分方程组,该方程组在 kdv(u, t, L) 函数中实现。kdv_solution(u0, t, L) 函数使用 scipy.integrate.odeint 来求解此系统。
在 [1]
#!python
import numpy as np
from scipy.integrate import odeint
from scipy.fftpack import diff as psdiff
def kdv_exact(x, c):
"""Profile of the exact solution to the KdV for a single soliton on the real line."""
u = 0.5*c*np.cosh(0.5*np.sqrt(c)*x)**(-2)
return u
def kdv(u, t, L):
"""Differential equations for the KdV equation, discretized in x."""
# Compute the x derivatives using the pseudo-spectral method.
ux = psdiff(u, period=L)
uxxx = psdiff(u, period=L, order=3)
# Compute du/dt.
dudt = -6*u*ux - uxxx
return dudt
def kdv_solution(u0, t, L):
"""Use odeint to solve the KdV equation on a periodic domain.
`u0` is initial condition, `t` is the array of time values at which
the solution is to be computed, and `L` is the length of the periodic
domain."""
sol = odeint(kdv, u0, t, args=(L,), mxstep=5000)
return sol
if __name__ == "__main__":
# Set the size of the domain, and create the discretized grid.
L = 50.0
N = 64
dx = L / (N - 1.0)
x = np.linspace(0, (1-1.0/N)*L, N)
# Set the initial conditions.
# Not exact for two solitons on a periodic domain, but close enough...
u0 = kdv_exact(x-0.33*L, 0.75) + kdv_exact(x-0.65*L, 0.4)
# Set the time sample grid.
T = 200
t = np.linspace(0, T, 501)
print("Computing the solution.")
sol = kdv_solution(u0, t, L)
print("Plotting.")
import matplotlib.pyplot as plt
plt.figure(figsize=(6,5))
plt.imshow(sol[::-1, :], extent=[0,L,0,T])
plt.colorbar()
plt.xlabel('x')
plt.ylabel('t')
plt.axis('normal')
plt.title('Korteweg-de Vries on a Periodic Domain')
plt.show()
章节作者:WarrenWeckesser,Warren Weckesser
附件