涡度函数产生特殊结果

问题描述 投票:0回答:1

我正在研究盖子驱动的空腔流动问题,使用涡度纳维-斯托克斯方程的离散版本:

Discretised Vorticity-form Navier-Stokes Equations

出于某种原因,我的流函数似乎正在工作(至少我相信是这样),但我认为我的涡度图有点奇怪。我根据建议改变了一些事情,现在我得到了......有趣的结果。

完整代码:

import numpy as np
import matplotlib.pyplot as plt

#Initialising Parameters:
N = 50
L = 1.0
Re = 5
dt = 0.0001
Vwall = 1.0
h = L/(N-1)


#Initialising Arrays:
u = np.zeros((N, N))
w = np.zeros((N,N))
Vx = np.zeros((N, N))
Vy = np.zeros((N, N))
P = np.zeros((N, N))

#Setting Boundary Conditions (Velocity):
Vx[:, 0] = 0  #Left wall
Vx[:, -1] = 0  #Right wall
Vx[0, :] = 0  #Bottom wall
Vx[-1, :] = 1  #Top wall

Vy[:, 0] = 0  #Left wall
Vy[:, -1] = 0  #Right wall
Vy[0, :] = 0  #Bottom wall
Vy[-1, :] = 0  #Top wall


#Update stream function using 1a (Using SOR):
def updateStreamfn(u, w, h, tolerance=1e-6, maxIter=1000, omega=1.3):
  #SOR for solving Poisson Equation (iterating using while & for loops):
  maxDiff = tolerance + 1
  iter = 0

  #New while loop replacing for loop:
  while maxDiff > tolerance and iter < maxIter:
    uOld = np.copy(u)

    for i in range(1, u.shape[0] - 1):
      for j in range(1, u.shape[1] - 1):

        #Update Equation (using discretised 1a):
        u[i, j] = (1-omega) * u[i, j] + (omega * 0.25) *(
            u[i+1, j] + u[i-1, j] + u[i, j+1] + u[i, j-1] + (h**2 * w[i, j])
            )
      
      #Break at convergence after maximum difference value reached:
    maxDiff = np.max(np.abs(u - uOld))
    iter += 1
    
    if iter >= maxIter:
      print("Reached max iterations without convergence.")
      break

  return u


#Update vorticity on wall with eqn 10 for all boundaries:
def updateWallVorticity(w, u, Vwall, h):
  N = w.shape[0]
  
  #Top wall (y=max at moving lid)
  for i in range(N):
    w[i, 0] = -((2 / h**2) * (u[i, 1] - u[i, 0]) + (2 * Vwall / h))

  #Bottom wall (y=0)
  for i in range(N):
    w[i, N-1] = -((2 / h**2) * (u[i, N-2] - u[i, N-1]))

  #Left wall (x=0)
  for j in range(N):
    w[0, j] = -((2 / h**2) * (u[1, j] - u[0, j]))

  #Right wall (x=max)
  for j in range(N):
    w[N-1, j] = -((2 / h**2) * (u[N-2, j] - u[N-1, j]))


#Update vorticity in interior with 1b:
def updateInteriorVorticity(w, u, dt, Re, h, tolerance=1e-6, maxIter=1000, omega=1.3):
  wNew = np.copy(w)
  maxDiff = tolerance + 1
  iter_count = 0

  while maxDiff > tolerance and iter_count < maxIter:
    wOld = np.copy(wNew)
    
    #For loop to update through iterations:
    for i in range(1, w.shape[0] - 1):
      for j in range(1, w.shape[1] - 1):
        
        #Advection and diffusion terms:
        advectionx = ((u[i, j+1] - u[i, j-1]) / (2 * h) * ((w[i+1, j] - w[i-1, j]) / (2 * h)))
        advectiony = ((u[i+1, j] - u[i-1, j]) / (2 * h)) * ((w[i, j+1] - w[i, j-1]) / (2 * h))
        
        diffusion = (1 / Re) * ((w[i+1, j] - (2 * w[i, j]) + w[i-1, j]) / h**2 + (
            w[i, j+1] - (2 * w[i, j]) + w[i, j-1]) / h**2)
        
        #Update formula:
        wNew[i, j] = (1 - omega) * w[i, j] + omega * (w[i, j] + dt * (-advectionx + advectiony + diffusion))
        
    #Convergence check
    maxDiff = np.max(np.abs(wNew - wOld))
    iter_count += 1

    if iter_count >= maxIter:
      print("Vorticity update reached max iterations without full convergence.")
      break
  
    return wNew


#Task 4 plots:
def plotStreamfnFin(u, Vx, Vy, title="Stream Function (u)", time_step=None):
    plt.figure(figsize=(8, 6))
    plt.contourf(u, levels=50, cmap='viridis')
    plt.colorbar(label='Stream Function Value')

    #Plotting time steps:
    if time_step is not None:
        plt.title(f"{title} at Time Step {time_step}")
    else:
        plt.title(title)
    plt.xlabel("Grid X")
    plt.ylabel("Grid Y")
    
    #Streamlines to indicate flow direction:
    Y, X = np.mgrid[0:u.shape[0], 0:u.shape[1]]
    plt.streamplot(X, Y, Vx, Vy, color='white', linewidth=0.5)
    plt.show()

def plotStreamfnInt(u, title="Stream Function (u)", time_step=None):
    plt.figure(figsize=(8, 6))
    plt.contourf(u, levels=50, cmap='viridis')
    plt.colorbar(label='Stream Function Value')

    #Plotting time steps:
    if time_step is not None:
        plt.title(f"{title} at Time Step {time_step}")
    else:
        plt.title(title)
    plt.xlabel("Grid X")
    plt.ylabel("Grid Y")


#Vorticity plot:
def plotVorticity(w, title="Vorticity (w)", time_step=None):
    plt.figure(figsize=(8, 6))
    contour = plt.contourf(w, levels=50, cmap='viridis')
    plt.colorbar(contour, label='Vorticity Value')
    
    #Overlay contour lines:
    plt.contour(w, levels=10, colors='white', linewidths=0.5, linestyles='solid')
    
    #Title and labels:
    if time_step is not None:
        plt.title(f"{title} at Time Step {time_step}")
    else:
        plt.title(title)
    plt.xlabel("Grid X")
    plt.ylabel("Grid Y")
    plt.show()


#Main time-stepping loop:
numTimesteps = 100
visualInter = 10

for n in range(numTimesteps):
    #Update stream function:
    u = updateStreamfn(u, w, h)
    
    #Update vorticity on boundaries:
    updateWallVorticity(w, u, Vwall, h)

    #Update vorticity in interior:
    w = updateInteriorVorticity(w, u, dt, Re, h)
    
    if n % visualInter == 0:
      print(f"Time Step: {n}")

      #Plotting stream function with streamlines:
      plotStreamfnInt(u, title=f"Stream Function (u)", time_step=n)

      #Plotting the vorticity:
      plotVorticity(w, title=f"Vorticity (w)", time_step=n)
    

#Calculating Vx and Vy:
      Vx[1:-1, 1:-1] = (u[1:-1, 2:] - u[1:-1, :-2]) / (2 * h)
      Vy[1:-1, 1:-1] = -(u[2:, 1:-1] - u[:-2, 1:-1]) / (2 * h)  
  
#Plotting the results at the final timestep
plotStreamfnFin(u, Vx, Vy, title="Final Stream Function (u)")
plotVorticity(w, title="Final Vorticity (w)")

现在我的最终绘图(流和涡度)如下所示:

Stream function with stream lines

Vorticity Plot

老实说,我不确定涡度图是怎么回事。它看起来仍然没有达到预期的涡度?难道我错了?

python numpy physics fluid-dynamics
1个回答
0
投票

您的主要问题是您没有正确地对涡度方程进行时间步进,并且您的 x,y 坐标与传统的 [i,j] 矩阵表示法不太相符。

您会发现很难计算平流项或最终速度场、将正确的墙设置为移动边界或绘制最终图,除非您按照如下方式对齐坐标和索引:

y,j
^
|
|
|
+--------> x, i

为了加快求解速度,我将 N 减少到 20,并将 dt 增加到 0.001。如果你想增加 N,那么这将减少空间步长,并且你将不得不减少 dt 来补偿。您可能还需要降低欧米伽的值; (请注意,我是放松不足,而不是过度放松)。

我简化了您的绘图例程。

import numpy as np
import matplotlib.pyplot as plt

#Initialising Parameters:
N = 20
L = 1.0
Re = 5
dt = 0.001
Vwall = 1.0
h = L/(N-1)


#Initialising Arrays:
u  = np.zeros((N,N))
w  = np.zeros((N,N))
Vx = np.zeros((N,N));    Vx[:,-1] = Vwall        # Top wall
Vy = np.zeros((N,N))
p  = np.zeros((N,N))


# Update stream function  ( Laplacian(psi) = -w )
def updateStreamfn( u, w, h, tolerance=1e-6, maxIter=1000, omega=0.8 ):
    maxDiff = tolerance + 1
    iter = 0

    while maxDiff > tolerance and iter < maxIter:
        uOld = np.copy(u)

        for i in range( 1, u.shape[0] - 1 ):
            for j in range( 1, u.shape[1] - 1):
                u[i,j] = (1-omega) * uOld[i,j] + omega * 0.25 * (u[i+1,j] + u[i-1,j] + u[i,j+1] + u[i,j-1] + h**2 * w[i, j] )
      
        maxDiff = np.max( np.abs( u - uOld ) )
        iter += 1
    
        if iter >= maxIter:
            print("Reached max iterations without convergence.")
            break

    return u


# Update stream function  ( dw/dt + Vx.dw/dx + Vy.dw/dy = (1/Re)Laplacian(w)
def updateWallVorticity( w, u, Vwall, h ):
    w[: ,-1] = (2/h**2) * ( u[: ,-1] - u[: ,-2] ) - (2/h) * Vwall
    w[: ,0 ] = (2/h**2) * ( u[: ,0 ] - u[: ,1 ] )
    w[0 ,: ] = (2/h**2) * ( u[0 ,: ] - u[1 ,: ] )
    w[-1,: ] = (2/h**2) * ( u[-1,: ] - u[-2,: ] )


def updateInteriorVorticity( w, u, dt, Re, h, tolerance=1e-6, maxIter=1000, omega=0.8 ):
    wPrev = np.copy(w)                 # value at end of last TIMESTEP
    maxDiff = tolerance + 1
    iter = 0

    while maxDiff > tolerance and iter < maxIter:
       wOld = np.copy(w)               # value at end of last ITERATION
    
       for i in range( 1, w.shape[0] - 1 ):
           for j in range( 1, w.shape[1] - 1 ):
               advectionx = ( u[i,j+1] - u[i,j-1] ) / (2 * h)   *   (w[i+1,j] - w[i-1,j]) / (2 * h)
               advectiony = ( u[i+1,j] - u[i-1,j] ) / (2 * h)   *   (w[i,j+1] - w[i,j-1]) / (2 * h)
               diffusion = 1/Re * ( w[i+1,j] + w[i-1,j] + w[i,j+1] + w[i,j-1] - 4*w[i,j] ) / h**2
               w[i,j] = (1-omega) * w[i,j]   +   omega * ( wPrev[i,j] + dt * ( -advectionx + advectiony + diffusion) )
        
       maxDiff = np.max(np.abs(w - wOld))
       iter += 1

       if iter >= maxIter:
           print( "Vorticity update reached max iterations without full convergence." )
           break
  
    return w



def plotStreamfn( u, title="Stream Function (u)", time_step=None ):
    plt.figure( figsize=(8, 6) )
    x = np.linspace( 0, L, u.shape[0] )
    y = np.linspace( 0, L, u.shape[1] )
    Y, X = np.meshgrid( x, y )
    plt.contourf( X, Y, u, levels=20, cmap='viridis' )
    plt.colorbar( label='Stream Function Value' )
    plt.contour( X, Y, u, levels=10, colors='white', linewidths=1.0, linestyles='solid' )

    if time_step is not None:
        plt.title(f"{title} at Time Step {time_step}")
    else:
        plt.title(title)
        Vx[1:-1, 1:-1] =  ( u[ 1 : -1 , 2 :    ] - u[ 1: -1 ,   : -2 ] ) / (2 * h)    #  d(psi)/dy
        Vy[1:-1, 1:-1] = -( u[ 2 :    , 1 : -1 ] - u[  : -2 , 1 : -1 ] ) / (2 * h)    # -d(psi)/dx
        plt.quiver( X, Y, Vx, Vy )
    plt.show()


#Vorticity plot:
def plotVorticity( w, title="Vorticity (w)", time_step=None ):
    plt.figure( figsize=(8, 6) )
    x = np.linspace( 0, L, u.shape[0] )
    y = np.linspace( 0, L, u.shape[1] )
    Y, X = np.meshgrid( x, y )
    contour = plt.contourf( X, Y, w, levels=50, cmap='viridis' )
    plt.colorbar(contour, label='Vorticity Value')
    plt.contour( X, Y, w, levels=10, colors='white', linewidths=1.0, linestyles='solid' )
    
    if time_step is not None:
        plt.title(f"{title} at Time Step {time_step}")
    else:
        plt.title(title)
    plt.xlabel("Grid X")
    plt.ylabel("Grid Y")
    plt.show()


#Main time-stepping loop:
numTimesteps = 100
visualInter = 25

for n in range(numTimesteps):
    u = updateStreamfn(u, w, h)
    updateWallVorticity(w, u, Vwall, h)
    w = updateInteriorVorticity(w, u, dt, Re, h)
    
    if n % visualInter == 0:
       print(f"Time Step: {n}")
       plotStreamfn(u, title=f"Stream Function (u)", time_step=n)
       plotVorticity(w, title=f"Vorticity (w)", time_step=n)

plotStreamfn( u, title="Final Stream Function (u)" )
plotVorticity( w, title="Final Vorticity (w)" )

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.