【发布时间】:2020-04-22 23:51:24
【问题描述】:
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from math import pi
# wave speed
c = 1
# spatial domain
xmin = 0
xmax = 1
#time domain
m=500; # num of time steps
tmin=0
T = tmin + np.arange(m+1);
tmax=500
n = 50 # num of grid points
# x grid of n points
X, dx = np.linspace(xmin, xmax, n+1, retstep=True);
X = X[:-1] # remove last point, as u(x=1,t)=u(x=0,t)
# for CFL of 0.1
CFL = 0.3
dt = CFL*dx/c
# initial conditions
def initial_u(x):
return np.sin(2*pi*x)
# each value of the U array contains the solution for all x values at each timestep
U = np.zeros((m+1,n),dtype=float)
U[0] = u = initial_u(X);
def derivatives(t,u,c,dx):
uvals = [] # u values for this time step
for j in range(len(X)):
if j == 0: # left boundary
uvals.append((-c/(2*dx))*(u[j+1]-u[n-1]))
elif j == n-1: # right boundary
uvals.append((-c/(2*dx))*(u[0]-u[j-1]))
else:
uvals.append((-c/(2*dx))*(u[j+1]-u[j-1]))
return np.asarray(uvals)
# solve for 500 time steps
for k in range(m):
t = T[k];
k1 = derivatives(t,u,c,dx)*dt;
k2 = derivatives(t+0.5*dt,u+0.5*k1,c,dx)*dt;
k3 = derivatives(t+0.5*dt,u+0.5*k2,c,dx)*dt;
k4 = derivatives(t+dt,u+k3,c,dx)*dt;
U[k+1] = u = u + (k1+2*k2+2*k3+k4)/6;
# plot solution
plt.style.use('dark_background')
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
line, = ax1.plot(X,U[0],color='cyan')
ax1.grid(True)
ax1.set_ylim([-2,2])
ax1.set_xlim([0,1])
def animate(i):
line.set_ydata(U[i])
return line,
我想用 Python 编写一个平流方程,它是 (∂u/∂t) +c (∂u/∂x) = 0。时间应该用 Runge-kutta 4 阶离散化。空间离散化是二阶有限差分。当我运行我的代码时,我得到了转换成正弦波的直线。但我给出了初始条件正弦波。为什么它以直线开始?我想让正弦波向前移动。您对如何使正弦波前进有任何想法吗?我感谢您的帮助。提前致谢!
【问题讨论】:
-
首先,你需要使用更少的全局变量,尤其是。
U数组。传递更多作为参数。请注意,对于 RK4,您将需要在距离上一个时间节点非欧拉步长的状态下进行 3 次导数评估。此外,k向量应该是导数函数的结果(此更改可能足以更正您的代码)。为了进一步简化代码,请考虑如何使用切片或卷积实现二阶导数。 -
感谢您的回答。在从最后一个时间节点开始不是欧拉步的状态下的 3 个导数评估到底是什么意思?你能澄清一下吗?
-
稍后再读,这里不相关。您只是使用一种非常非常规的方法来获取阶段值。然而,在那之后的点仍然存在,函数
u计算一个点/状态,而k向量应该包含斜率/导数。 -
我在 k 个向量中包含了导数函数。所以 k 值是使用导数函数计算的。但我现在得到了强烈的振荡。我编辑了我的代码。所以你可以看到它的新形式。
-
您在除以
(dx+deltax)时做了一些非常奇怪的事情。通过它的使用,deltax应该是deltat,并且在任何时候它都不会添加到dx。
标签: python numerical-methods runge-kutta