2D Euler 方程与 Runge Kutta 的直接积分显示了振荡的 Courant-Friedrichs-Lewy 系数。僵硬还是虫子?

计算科学 pde 流体动力学 龙格库塔
2021-12-21 06:47:17

通过使用 Runge Kutta O(4) 方法将 2D Euler 方程的直接积分写在一个宽而短的盒子中,在该盒子中流体通过水平面进入和离开,我发现 CFL 系数,这里近似计算如下,振荡随着时间的推移,幅度增加。如果积分没有停止,速度场就会发散。

我是否面临通常被称为直接求解器对于刚性方程不稳定的情况?

CFLcoefficient=max(u,v)dth

在哪里u,v分别是 x 和 y 中的速度

h空间特征长度

dt整合步骤。

密度被视为常数。

一些笔记。我尝试在边界处强制执行零切向速度,作为模拟粘度的一种简单近似,而没有明确添加粘性项,它似乎会促进不稳定性。不清楚。

主要注意事项是考虑到质量守恒,如下所示,根本没有被强制执行。

ux+vy=0

Python3 中的最小工作示例如下。不要在已经存在名为“results”的文件夹的任何空间中运行它。要求是 numpy 和 matplotlib。

编辑:的确,答案是有一个错误。我按照接受的答案的建议简化了求解器以使用 O(1) Euler 方法。我已经更新了 MWE。现在计算时间步长以满足每个积分步长的 CLF 系数。

import numpy as np
import matplotlib.pyplot as plt
import os,sys

try:
    os.mkdir('results')
except:
    pass
try:
    os.system('rm results/*')
except:
    pass

Lx,Ly = (30,30)




RHO = 12
DT = 0.02 # Main integration timestep
H = 1
RHO_H = RHO / H
BOUNDARYVAL = 0.1


Ux = np.ones((Lx, Ly)) * BOUNDARYVAL / 2
Uy = np.zeros((Lx, Ly))

Ux[0,:] = BOUNDARYVAL
#Ux[1,:] = BOUNDARYVAL/2
#Ux[2,:] = BOUNDARYVAL/4


# Enforce the Courant-Friedrichs-Lewy condition
CFL = BOUNDARYVAL * DT / H
assert(CFL <= 0.5)


LAPS = 300
FREQ = 15
D = len(str(LAPS))
for _ in range(LAPS*FREQ):


    if _>0: 
        DT = CFL * H / max([max(Uy.flatten()), max(Ux.flatten())])
    

    # Down to up velocity vertically
    Ux[0,:] = BOUNDARYVAL
    #Ux[-1,:] = BOUNDARYVAL

    # Vertical velocity in the borders can be whatever because there is no viscosity
    #Ux[:,-1] = 0
    #Ux[:,0] = 0

    # Horizonal velocity in the horizontal borders can be whatever
    #Uy[0,:] = 0
    #Uy[-1,:] = 0

    # Horizontal velocity in the vertical borders must be zero as "fluid cant escape through the sides"
    Uy[:,0] = 0
    Uy[:,-1] = 0

    # Plot
    if _%FREQ==0:
        print(f"DT is {DT}")
        print(f"Lap {_+1} of {FREQ*LAPS}!")
        plt.imshow(Ux * Ux + Uy * Uy, cmap = 'coolwarm', vmin=min([BOUNDARYVAL,0]), vmax=max([BOUNDARYVAL,0]))
        plt.colorbar()
        plt.savefig(f'results/{str(_//FREQ).zfill(D)}.png')
        plt.close()
    
    # Compute next state
    # Mass conservation eq. is divergence(U)=0
    # Momentum conservation eqs. are dU/dt + (U \cdot \grad) U = 0
    # Where there is no gravity, viscosity, nor external pressure gradient being enforced
    
    # dU/dt = -RHO * (Ux d/dx + Uy d/dy)U
    #
    # so we compute auxiliaries 
    #
    dUx_dx = (Ux[2:,1:-1] - Ux[:-2,1:-1]) / 2 / H
    dUx_dy = (Ux[1:-1,2:] - Ux[1:-1,:-2]) / 2 / H
    dUy_dx = (Uy[2:,1:-1] - Uy[:-2,1:-1]) / 2 / H
    dUy_dy = (Uy[1:-1,2:] - Uy[1:-1,:-2]) / 2 / H
    # 
    # and evolve the field
    #
    #print(dUx_dx.shape, Ux.shape)
    #plt.imshow(dUx_dx);plt.show()
    #MX = np.max((DT * RHO * (Ux[1:-1,1:-1] * dUx_dx + Uy[1:-1,1:-1] * dUx_dy)).flatten())
    #print(f'max incoming update is {MX}')
    Ux[1:-1,1:-1] -= DT * RHO * (Ux[1:-1,1:-1] * dUx_dx + Uy[1:-1,1:-1] * dUx_dy)
    Uy[1:-1,1:-1] -= DT * RHO * (Ux[1:-1,1:-1] * dUy_dx + Uy[1:-1,1:-1] * dUy_dy)



try:
    os.remove('result.avi')
except: pass

print(f'To make a GIF showing the evolution please run ffmpeg  -framerate 5 -i "results/%0{D}d.png" -vcodec mpeg4 result.avi')





1个回答

这里有很多可以提到的,所以我要开始了。

  1. CFL 从来都不是稳定性的充分标准,而是必要的标准。也就是说,仅仅因为您遵守 CFL 条件,并不能保证您获得稳定的结果。这是绝对有道理的,因为你的方法可能是任意糟糕的。

  2. 在我看来,您试图不解决“典型”欧拉方程(本质上是用于可压缩情况) 而是像不可压缩的 Navier-Stokes 一样,忽略了粘度、压力和体力: 上面的公式是超定的,因为我们有方程,但只有两个未知数:

    t(ρρuE)+(ρuρuTu(E+p)u)=(000)
    u=0,tu+(u)u=0
    1+2ux,uy. 好吧,就像你做的那样,我们不要强制质量守恒,而是根据动量方程 u
    ux=uxxuxuyyuxuy=uxxuyuyyuy

我不确定你在用 RK1 量做什么,即你想如何获得梯度。也许最好从欧拉开始时间离散化和空间导数的(中心)有限差分,以获得第一个简单的版本。