为什么我的 Lax Wendroff 代码中会出现此错误?

计算科学 pde Python 平流
2021-12-16 14:45:05

我想为非线性平流方程实现 Lax Wendroff 方法,它是

uin+1uint+f(ui+1n)f(ui1n)2ht2h(Fi+1/2nf(ui+1n)f(ui)nh)Fi1/2nf(uin)f(ui1n)h)=0

对于问题: for

ut+uux=0
t(0,1)

x(0,1)

u(0,x)=exp(10(4x1)2)

import numpy as np
def NLLaxWendroff(Nx,Nt,t_end):
    Nx = Nx+1                         # Number of grid points
    xmax = 1.                         # Domain limit to the right
    xmin = 0.                         # Domain limit to the left
    h = (xmax-xmin)/(Nx-1)           # Mesh size
    x = np.arange(xmin,xmax,h)       # Discretized mesh

    U =  np.exp(-10*(4*x-1)**2)       # Initial solution
                                                                 


    dt = 1.0/Nt                        # Time step
    t = 0.                            # Initial time

   # upwind scheme (7.18) from Dr.Georgoulis Notes after rearrangement (solving for u_{i}^{n+1})
    while (t <= t_end):
        t = t+dt
        v = t/(2*h)
        a = (t**2)/(2*h)
        Un = U
        Um = np.roll(Un,1)
        Up = np.roll(Un,-1)
        F_plus  = 0.5 * (Up + Un)
        F_minus = 0.5 * (Un + Um)       
        U =  Un - v * (Um-Up) + a * (F_plus  * Un-Um - F_minus *Um-Up)
      


    plt.plot(x,U)
    plt.title('t='+str(round(t_end,2)),fontsize=16)
    plt.xlabel('x',fontsize=18)
    plt.ylabel('u',fontsize=18)
    plt.show()
NLLaxWendroff(100,100,0.6)

但是会出现以下错误:

<ipython-input-55-f6e78f745ea8>:24: RuntimeWarning: overflow encountered in multiply
  U =  Un - (v * (Up-Um)) + a * (  (F_plus  * (Un-Um)) - (F_minus *(Up-Um))   )
<ipython-input-55-f6e78f745ea8>:24: RuntimeWarning: invalid value encountered in subtract
  U =  Un - (v * (Up-Um)) + a * (  (F_plus  * (Un-Um)) - (F_minus *(Up-Um))   )
<ipython-input-55-f6e78f745ea8>:22: RuntimeWarning: invalid value encountered in subtract
  F_plus  = 1/2 * (Un - Um)
<ipython-input-55-f6e78f745ea8>:23: RuntimeWarning: invalid value encountered in subtract
  F_minus = 1/2 * (Un - Up)
<ipython-input-55-f6e78f745ea8>:24: RuntimeWarning: invalid value encountered in add
  U =  Un - (v * (Up-Um)) + a * (  (F_plus  * (Un-Um)) - (F_minus *(Up-Um))   )

```
1个回答

我发现您的实施存在一些问题:

  • 替换(在您的代码和问题中),否则没有任何意义!tdt
  • 方程的第二部分(带有之间存在混合此外,您的通量评估是错误的:例如应该阅读。aFfFplus0.5*Up**2
  • 在 U 的计算中Un-Um周围也缺少括号。Um-Up

我已经基于http://folk.ntnu.no/leifh/teaching/tkt4140/._main075.html实施了 Lax-Wendroff 方案,它似乎工作正常。

以下代码将您的实现与各种修复和新修复进行了比较。两者都有效并给出相同的结果。

import numpy as np
import matplotlib.pyplot as plt

Nx=100;Nt=100;t_end=2.0
nChoice = 1

### LAX-WENDROFF SCHEME with periodic BCs
Nx = Nx+1                         # Number of grid points
xmax = 1.                         # Domain limit to the right
xmin = 0.                         # Domain limit to the left
h = (xmax-xmin)/(Nx-1)           # Mesh size
x = np.arange(xmin,xmax,h)       # Discretized mesh
U =  np.exp(-10*(4*x-1)**2)       # Initial solution
dt = 1.0/Nt                        # Time step
t = 0.                            # Initial time

aplus, aminus, Fplus, Fminus, Fn = (np.zeros(Nx-1) for i in range(5))
nsteps = 0
while (t <= t_end):
    if np.any(np.isnan(U)):
      raise Exception('NaNs detected --> exit')
      
    if nChoice==0: # your implementation
        v = dt/(2*h)
        a = (dt**2)/(2*h**2)
        Un = U
        Um = np.roll(Un,1)
        Up = np.roll(Un,-1)
        # F_plus  = 0.5 * (Up + Un)
        # F_minus = 0.5 * (Un + Um)
        F_plus = 0.5*Up**2
        F_minus = 0.5*Um**2
        Fn = 0.5*Un**2
        # U =  Un - v * (Um-Up) + a * (F_plus  * Un-Um - F_minus *Um-Up)
        U =  Un - v*(F_plus-F_minus) + a*( 0.5*(Up+U)*(F_plus-Fn)- 0.5*(U+Um)*(Fn-F_minus))
      
    else: # another implementation
        aplus[:-1] = 0.5 * (U[:-1] + U[1:])
        aplus[-1]  = 0.5 * (U[-1]  + U[0])
        aminus[1:] = aplus[:-1]
        aminus[0]   = aplus[-1]
        
        Fn[:] = 0.5*U**2
        Fplus[:-1] = Fn[1:] # or just use np.roll as you did
        Fplus[-1]  = Fn[0]
        Fminus[1:] = Fn[:-1]
        Fminus[0]  = Fn[-1]
        
        U[:] = U - dt/(2*h)*(Fplus-Fminus) + (dt**2)/(2*h**2)*(aplus*(Fplus-Fn) - aminus*(Fn-Fminus))
    
    t = t+dt
    nsteps+=1  
    
    # plot solution evolution every 10 time steps
    if np.mod(nsteps,10)==1 or t>=t_end:
        plt.figure()
        plt.plot(x,U)
        plt.title('t={:.2f}'.format(t),fontsize=16)
        plt.xlabel('x',fontsize=18)
        plt.ylabel('u',fontsize=18)
        plt.grid()
        plt.ylim(0,1)
        plt.show()
```