使用 NumPy 数组实现结构化网格边界条件?

计算科学 有限差分 Python 边界条件 麻木的 平流
2021-12-13 08:04:32

我正在用 Python 编写一个玩具代码来求解平流方程

ut+cux=0
例如,周期性边界条件。

背景资料

数值网格是这样指定的:

# problem parameters
lx = 2.0*np.pi    # length of the domain
c = 1.0           # advecton speed

# grid generation
nx = 50            # number of grid points
dx = lx/float(nx)  # grid spacing
x = np.linspace(-dx/2.,lx+dx/2.,nx+2) # vector of grid points

其中-dx/2.lx+dx/2.点对应于鬼点。

我目前实现这样的周期性边界条件:

def periodic_bc(u):
  u[ 0]=u[-2]
  u[-1]=u[ 1]
  return u

时间积分写成如下:

for n in range(0,nt):
    u[1:nx+1] = u0[1:nx+1] + (c*dt/dx)*(u0[0:nx]-u0[1:nx+1])
    u = periodic_bc(u)
    u0 = u

其中u0u分别是旧数据和新数据。所有数组都是 numpy 数组。

有没有人建议以更优雅的方式实现边界条件?

即使在编写这个极其简单的代码时,我也发现自己对数组切片的边界(例如 、0:nx1:nx+1和周期性边界条件函数的实现感到困惑。这并不完全直观u[0]=u[-2]相应的 Fortran 代码将是u[-1]=u[nx-1],其中u[-1]可以专门为鬼点分配。对我来说,这更加直观,并且与离散的边界条件相匹配。

或者,除了鬼点之外,还有一种不同的方法可以实现更直观的代码。任何的建议都受欢迎。

1个回答

Numpy 函数roll执行数组的周期性移位。使用它,您的 PDE 在周期性域中的显式时间步长可以简单地实现如下:

u = u - (1/2)*(c*dt/dx)*(np.roll(u,-1) - np.roll(u,1))