一维Riemann问题是一类常见的流体力学问题,用于研究流体在初始条件下的解的行为。它涉及到一个由两个恒定状态(称为左状态和右状态)分隔的界面,其中流体在界面两侧具有不同的性质。
在一维Riemann问题中,假设气体以压缩性欧拉方程(通常是Euler方程)描述,这些方程可以描述流体的质量、动量和能量守恒。在给定左右状态的密度、速度和压力之后,Riemann问题的目标是求解出界面上各个位置的物理量随时间的变化情况,例如密度、速度和压力等。
求解一维Riemann问题是一个非线性问题,最常用的方法之一是使用数值通量分裂方法,例如Godunov方法或HLL(Harten-Lax-van Leer)方法。这些方法通过将流体的基本守恒方程分离为左右两个通量,并根据波的传播速度来计算数值通量。通过在空间和时间上进行离散化,可以使用数值方法来逼近一维Riemann问题的解。
一维Riemann问题的解可以提供有关激波、间断、稀疏波等流体行为的重要信息,对于理解和模拟各种物理现象具有重要意义,例如爆炸、冲击波传播、流体的相变等。它在计算流体动力学(CFD)和计算气体动力学等领域中具有广泛的应用。
核心代码实现:
Gamma=1.4 # 气体常数
Pi=np.pi
L=1 #计算区域
T=0.14 #总时间
ST=0.8 #时间步长因子
J=101 #节点总数
dX=L/(J-1)
U=np.zeros((3,J))#定义二维零数组
FU=U.copy();U_1=U.copy() #同样定义Ef,Uf 为二维零数组
X=np.zeros(J)
Tools.initial(U,J,Gamma)
SumT=0
dT=0.0005
while SumT<=T:
dT=Tools.SetTimeStep(U,J,dX,Gamma)
SumT+=dT
print('T=%.10f, dT=%.10f'%(SumT,dT))
Tools.MacCormack(U,FU,U_1,dT,dX,J,Gamma)
# Tools.Steger_Warming(U,dT,dX,J,Gamma)
Tools.Boundary(U,J)
Tools.Output(U,J,dX,Gamma)
实现流通矢量 Steger_Warming 分裂法
def StegerWarming(U,dT,dX,J,Gamma):
rho=np.zeros(J)
u=np.zeros(J)
p=np.zeros(J)
c=np.zeros(J)
Lampida=np.zeros((3,J))
Lampida_Plus=np.zeros((3,J))
Lampida_Minus=np.zeros((3,J))
F_Plus=np.zeros((3,J))
F_Minus=np.zeros((3,J))
epso=1e-8
for i in range(0,J):
rho[i]=U[0][i]
u[i]=U[1][i]/rho[i]
p[i]=(Gamma-1)*(U[2][i]-0.5*rho[i]*u[i]*u[i])
c[i]=np.sqrt(Gamma*p[i]/rho[i])
Lampida[0][i]==u[i]
Lampida[1][i]==u[i]-c[i]
Lampida[2][i]=u[i]+c[i]
for d in range(0,3):
Lampida_Plus[d][i]=0.5*(Lampida[d][i]+np.sqrt(Lampida[d][i]**2+epso**2))
Lampida_Minus[d][i]=0.5*(Lampida[d][i]-np.sqrt(Lampida[d][i]**2+epso**2))
for i in range(0,J):
temp=rho[i]/(2*Gamma)
w=(3-Gamma)/(2*Gamma-2)*(Lampida_Plus[1][i]+Lampida_Plus[2][i])*c[i]**2
F_Plus[0][i]=temp*(2*(Gamma-1)*Lampida_Plus[0][i]+Lampida_Plus[1][i]+Lampida_Plus[2][i])
F_Plus[1][i]=temp*(2*(Gamma-1)*Lampida_Plus[0][i]*u[i]+Lampida_Plus[1][i]*(u[i]-c[i]) +Lampida_Plus[2][i]*(u[i]+c[i]))
F_Plus[2][i]=temp*((Gamma-1)*Lampida_Plus[0][i]*u[i]**2+0.5*Lampida_Plus[1][i]*(u[i]-c[i])**2+0.5*Lampida_Plus[2][i]*(u[i]+c[i])**2+w)
w=(3-Gamma)/(2*Gamma-2)*(Lampida_Minus[1][i]+Lampida_Minus[2][i])*c[i]**2
F_Minus[0][i]=temp*(2*(Gamma-1)*Lampida_Minus[0][i]+Lampida_Minus[1][i]+Lampida_Minus[2][i])
F_Minus[1][i]=temp*(2*(Gamma-1)*Lampida_Minus[0][i]*u[i]+Lampida_Minus[1][i]*(u[i]-c[i]) +Lampida_Minus[2][i]*(u[i]+c[i]))
F_Minus[2][i]=temp*((Gamma-1)*Lampida_Minus[0][i]*u[i]**2+0.5*Lampida_Minus[1][i]*(u[i]-c[i])**2+0.5*Lampida_Minus[2][i]*(u[i]+c[i])**2+w)
for i in range(1,J-1):
r=dT/dX
U[0][i]-=r*((F_Plus[0][i]-F_Plus[0][i-1])+(F_Minus[0][i+1]-F_Minus[0][i]))
U[1][i]-=r*((F_Plus[1][i]-F_Plus[1][i-1])+(F_Minus[1][i+1]-F_Minus[1][i]))
U[2][i]-=r*((F_Plus[2][i]-F_Plus[2][i-1])+(F_Minus[2][i+1]-F_Minus[2][i]))
结果输出与可视化:
def Output(U,J,dX,Gamma):
fp=open('ShockTubePython.txt','w')
X=np.zeros(J)
rho=np.zeros(J)
u=np.zeros(J)
p=np.zeros(J)
for i in range(0,J,1):
X[i]=i*dX
rho[i]=U[0][i]
u[i]=U[1][i]/rho[i]
p[i]=(Gamma-1)*(U[2][i]-0.5*U[0][i]*u[i]*u[i])
fp.write('%d %.4f %.10f %.10f %.10f %.10f\n'%(i,X[i],rho[i],u[i],p[i],U[2][i]))
fp.close()
plt.figure(figsize=(8,8))
plt.subplot(221)
plt.plot(X,rho,color='black',linewidth=2)
plt.title('Density', fontsize=12)
plt.ylabel(r'$\rho (x)$', fontsize=14)
plt.xlim(0,1)
plt.ylim(-0.1,1.1)
plt.subplot(222)
plt.plot(X,u,color='blue',linewidth=2)
plt.title('Velocity', fontsize=12)
plt.ylabel(r'$v(x)$', fontsize=12)
plt.xlim(0,1)
plt.ylim(-0.1,1.1)
plt.subplot(223)
plt.plot(X,p,color='red',linewidth=2)
plt.title('Pressure', fontsize=12)
plt.ylabel(r'$p(x)$', fontsize=12)
plt.xlim(0,1)
plt.ylim(-0.1,1.1)
plt.subplot(224)
plt.plot(X,U[2][:],color='pink',linewidth=2)
plt.title('Energy', fontsize=12)
plt.ylabel(r'$E(x)$', fontsize=12)
plt.xlim(0,1)
plt.ylim(-0.1,2.6)
plt.savefig('ShockTube1.jpg')
plt.show()
结果可视化如下所示: