import numpy as np
import pandas as pd
from numpy import linalg as LA
import math
from scipy.sparse import csr_matrix, diags
from scipy.sparse.linalg import spsolve, spsolve_triangular
# Timer
from timeit import default_timer as timer
import warnings
warnings.filterwarnings('ignore')
The wave equation in time domain can be stated as follows, \begin{equation} \frac{\partial^2 u}{\partial t^2}=c^2 \nabla^2 u+f,\qquad x\in \Omega \subset \mathbb{R}^d,~t\in(T_1,T_2] \end{equation} where $\Delta$ is the Laplacian, $f$ is a forcing function (for example our source) and $c$ is the wave velocity at which the time and spatially varying wave $u$ propagates.
A Fourth-Order Finite-Difference Method for
the Three Dimensional Wave Equation in Time Domain
Let $I=(a,b)\times(c,d)\times(e,f)$ and $J=[a,b]\times[c,d]\times[e,f]$. A three-dimensional form of the wave equation can be found as follows, \begin{align} \begin{cases} \dfrac{\partial^2 u}{\partial t^2} = c^2(x,y,z) \Delta u +f(x,y,z,t),&(x,y,z)\in I,~t\in(T_1,T_2],\\ u(x,y,z,T_1)=g(x,y,z),&(x,y,z)\in J,\\ \dfrac{\partial }{\partial t}u(x,y,z,T_1) = s(x,y,z),&(x,y,z)\in J,\\ u(a,y,z,t) = f_{a}(y,z,t),&(y,z)\in [c,d]\times[e,f],~t \in[T_1,T_2],\\ u(b,y,z,t) = f_{b}(y,z,t),&(y,z)\in [c,d]\times[e,f],~t \in[T_1,T_2],\\ u(x,c,z,t) = f_{c}(x,z,t),&(x,z)\in [a,b]\times[e,f],~t \in[T_1,T_2],\\ u(x,d,z,t) = f_{d}(x,z,t),&(x,z)\in [a,b]\times[e,f],~t \in[T_1,T_2],\\ u(x,y,e,t) = f_{e}(x,y,t),&(x,y)\in [a,b]\times[c,d],~t \in[T_1,T_2],\\ u(x,y,f,t) = f_{f}(x,y,t),&(x,y)\in [a,b]\times[c,d],~t \in[T_1,T_2]. \end{cases} \qquad \qquad (1) \end{align}
Consider the following notations:
A fourth-order finite difference scheme for solving the problem (1) can be considered as follows, \begin{align} \left(1+\frac{1}{12}\delta_t^2\right)^{-1}\frac{\delta_t^2}{\tau^2} u_{i,j,k}^{n}&= c^2\left(1+\frac{1}{12}\delta_x^2\right)^{-1}\frac{\delta_x^2}{h_x^2} u_{i,j,k}^{n}+ c^2\left(1+\frac{1}{12}\delta_y^2\right)^{-1}\frac{\delta_y^2}{h_y^2} u_{i,j,k}^{n}\notag \\ &+ c^2\left(1+\frac{1}{12}\delta_z^2\right)^{-1}\frac{\delta_z^2}{h_z^2} u_{i,j,k}^{n}+f_{i,j,k}^{n}. \end{align} Expanding terms, \begin{align} &\left[\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right) -\frac{r_x^2}{12} \left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_x^2 \right. \notag \\ & \left. -\frac{r_y^2}{12}\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_y^2 -\frac{r_z^2}{12}\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\delta_z^2 \right]\delta_t^2u_{i,j,k}^{n}= \notag \\ & \left[r_x^2 \left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_x^2 +r_y^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_y^2 +r_z^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\delta_z^2 \right]u_{i,j,k}^{n} \notag \\ & +\tau^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\left(1+\frac{1}{12}\delta_t^2\right)f_{i,j,k}^{n}, \end{align} where $r_x^2=c^2\frac{\tau^2}{h_x^2}$, $r_y^2=c^2\frac{\tau^2}{h_y^2}$ and $r_z^2=c^2\frac{\tau^2}{h_z^2}$.
Let \begin{align} \rho_x=\frac{1-r_x^2}{12},~\rho_y=\frac{1-r_y^2}{12},~\rho_z=\frac{1-r_z^2}{12}. \end{align}
On the other hand, note that, \begin{align} &\left| \left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)u_{i,j,k}^{n} -\frac{r_x^2}{12} \left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_x^2u_{i,j,k}^{n} -\frac{r_y^2}{12}\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_y^2u_{i,j,k}^{n} \right. \notag \\ & \left. -\frac{r_z^2}{12}\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\delta_z^2u_{i,j,k}^{n} -\left(1+\rho_x\delta_x^2\right)\left(1+\rho_y\delta_y^2\right)\left(1+\rho_z\delta_z^2\right)u_{i,j,k}^{n} \right|= \frac{1}{144}\left[r_x^2 r_y^2 \delta_x^2 \delta_y^2 +r_x^2 r_z^2 \delta_x^2 \delta_z^2+r_y^2 r_z^2 \delta_y^2 \delta_z^2\right]u_{i,j,k}^{n} \notag \\ & +\frac{1}{1728}\left[r_x^2 r_y^2 +r_x^2 r_z^2 +r_y^2 r_z^2 -r_x^2 r_y^2 r_z^2 \right] \delta_x^2 \delta_y^2 \delta_z^2 u_{i,j,k}^{n} \approx O(h^4) \end{align}
It follows from (5) that, \begin{align} \left(1+\rho_x\delta_x^2\right)\left(1+\rho_y\delta_y^2\right)\left(1+\rho_z\delta_z^2\right) \delta_t^2 u_{i,j,k}^{n}=\mathbf{F}_{i,j,k}^{n} \end{align} where, \begin{align} \mathbf{F}_{i,j,k}^{n} &=+\left[r_x^2 \left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_x^2 +r_y^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\delta_y^2 \right. \notag \\ & \left. +r_z^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\delta_z^2 \right]u_{i,j,k}^{n} \notag \\ & +\tau^2\left(1+\frac{1}{12}\delta_x^2\right)\left(1+\frac{1}{12}\delta_y^2\right)\left(1+\frac{1}{12}\delta_z^2\right)\left(1+\frac{1}{12}\delta_t^2\right)f_{i,j,k}^{n}. \end{align}
The three-dimensional problem can be efficiently solved in three steps using ADI with the following steps,
The equation (6) also can be written as follows, \begin{align} \rho_x(\mathbf{X}_{i+1,j,k}+\mathbf{X}_{i-1,j,k})+(1-2\rho_x)\mathbf{X}_{i,j,k}=\mathbf{F}_{i,j,k}^{n}, \end{align}
Matrix form: $$ A_{j,k}=\begin{bmatrix} (1-2\rho_x) & \rho_x & 0 & \dots & \dots &0 \\ \rho_x & (1-2\rho_x) & \rho_x & 0 & \vdots &\vdots \\ 0 & \rho_x & (1-2\rho_x) & \rho_x &0 &\vdots \\ 0 &0 & \ddots & \ddots &\ddots &\vdots \\ \vdots &\vdots & \rho_x & (1-2\rho_x) & \rho_x & 0 \\ \vdots &\vdots & 0 & \rho_x & (1-2\rho_x) & \rho_x \\ 0 &0 & \dots & 0 & \rho_x & (1-2\rho_x) \end{bmatrix}, $$ $$ \mathbf{X}_{j,k}=\begin{bmatrix} \mathbf{X}_{1,j,k} \\ \mathbf{X}_{2,j,k}\\ \vdots\\ \mathbf{X}_{N_x-2,j,k}\\ \mathbf{X}_{N_x-1,j,k} \end{bmatrix},~ \mathbf{b}_j^n= \begin{bmatrix} -\rho_x \mathbf{X}_{0,j,k}\\ 0\\ \vdots\\ 0\\ -\rho_x \mathbf{X}_{N_x,j,k}, \end{bmatrix} \text{ and } \mathbf{F}_{j}^{n}= \begin{bmatrix} \mathbf{F}_{1,j,k}^{n}\\ \mathbf{F}_{2,j,k}^{n}\\ \vdots\\ \mathbf{F}_{N_x-2,j,k}^{n}\\ \mathbf{F}_{N_x-1,j,k}^{n} \end{bmatrix}, $$ where \begin{align} \mathbf{X}_{0,j,k}&= \left(1+\rho_y\delta_y^2\right)\left(1+\rho_z\delta_z^2\right)\delta_t^2 f_{a,j,k}^{n}, \\ \mathbf{X}_{N_x,j,k}&= \left(1+\rho_y\delta_y^2\right)\left(1+\rho_z\delta_z^2\right)\delta_t^2 f_{b,j,k}^{n}. \end{align}
Therefore \begin{equation*} \mathbf{X}_{j,k}=A_j^{-1}\left(\mathbf{F}_{j,k}^{n}+\mathbf{b}_j^n\right). \end{equation*}
Next, we need to find $\mathbf{Y}_{i,k}$ for $1\leq i \leq N_x-1$ and $1\leq k\leq N_z-1$. We have \begin{align} \rho_y\left(\mathbf{Y}_{i,j-1,k}+\mathbf{Y}_{i,j+1,k}\right)+(1-2\rho_y)\mathbf{Y}_{i,j,k}=\mathbf{X}_{i,j,k}, \end{align}
In addition, $$ A_{i,k}=\begin{bmatrix} (1-2\rho_y) & \rho_y & 0 & \dots & \dots &0 \\ \rho_y & (1-2\rho_y) & \rho_y & 0 & \vdots &\vdots \\ 0 & \rho_y & (1-2\rho_y) & \rho_y &0 &\vdots \\ 0 &0 & \ddots & \ddots &\ddots &\vdots \\ \vdots &\vdots & \rho_y & (1-2\rho_y) & \rho_y & 0 \\ \vdots &\vdots & 0 & \rho_y & (1-2\rho_y) & \rho_y \\ 0 &0 & \dots & 0 & \rho_y & (1-2\rho_y) \end{bmatrix}, $$ and \begin{equation*} \mathbf{b}_{i,k}^{n}= \begin{bmatrix} -\rho_y \mathbf{Y}_{i,0,k}\\ 0\\ \vdots\\ 0\\ -\rho_y \mathbf{Y}_{i,N_y,k} \end{bmatrix},~ \mathbf{X}_{i,k}=\begin{bmatrix} \mathbf{X}_{i,1,k} \\ \mathbf{X}_{i,2,k}\\ \vdots\\ \mathbf{X}_{i,N_y-2,k}\\ \mathbf{X}_{i,N_y-1,k} \end{bmatrix} \text{ and } \mathbf{Y}_{i,k}=\begin{bmatrix} \mathbf{Y}_{i,1,k} \\ \mathbf{Y}_{i,2,k}\\ \vdots\\ \mathbf{Y}_{i,N_y-2,k}\\ \mathbf{Y}_{i,N_y-1,k} \end{bmatrix}, \end{equation*} where \begin{align} \mathbf{Y}_{i,0,k}&=\left(1+\rho_z\delta_z^2\right)\delta_t^2f_{c,i,k}^{n},\\ \mathbf{Y}_{i,N_y,k}&=\left(1+\rho_z\delta_z^2\right)\delta_t^2 f_{d,i,k}^{n}. \end{align}
Hence, \begin{equation*} \label{eq1C6.15-1}\mathbf{Y}_{i,k}=A_{i,k}^{-1}\left(\mathbf{X}_{i,k}+\mathbf{b}_{i,k}^n\right), \end{equation*}
Finally, solving the following linear system is needed to find $\mathbf{Z}_{i,j,k}$
\begin{align} \begin{cases} \rho_z( \mathbf{Z}_{i,j,k+1}+\mathbf{Z}_{i,j,k-1})+(1-2\rho_z)\mathbf{Z}_{i,j,k}=\mathbf{Y}_{i,j,k},\\ u_{i,j,k+1}^{n+1}=\mathbf{Z}_{i,j,k}+2u_{i,j,k}^{n}-u_{i,j,k}^{n-1} \end{cases} \end{align}As a result, \begin{equation*} \mathbf{u}_{i,j}^{n+1}=A_{i,j}^{-1}\left(\mathbf{Y}_{i,j}+\mathbf{b}_{i,j}^n\right), \end{equation*} where \begin{equation*} A_{i,j}=\begin{bmatrix} (1-2\rho_z) & \rho_z & 0 & \dots & \dots &0 \\ \rho_z & (1-2\rho_z) & \rho_z & 0 & \vdots &\vdots \\ 0 & \rho_z & (1-2\rho_z) & \rho_z &0 &\vdots \\ 0 &0 & \ddots & \ddots &\ddots &\vdots \\ \vdots &\vdots & \rho_z & (1-2\rho_z) & \rho_z & 0 \\ \vdots &\vdots & 0 & \rho_z & (1-2\rho_z) & \rho_z \\ 0 &0 & \dots & 0 & \rho_z & (1-2\rho_z) \end{bmatrix}, \end{equation*} and \begin{equation*} \mathbf{b}_{i,j}^{n}= \begin{bmatrix} -\rho_z \delta_t^2 f_{e,i,j}^{n}\\ 0\\ \vdots\\ 0\\ -\rho_z \delta_t^2 f_{f,i,j}^{n} \end{bmatrix} \text{ and } \mathbf{u}_{i,j}^{n+1}=\begin{bmatrix} u_{i,j,1}^{n+1} \\ u_{i,j,2}^{n+1}\\ \vdots\\ u_{i,j,N_z-2}^{n+1}\\ u_{i,j,N_z-1}^{n+1} \end{bmatrix}. \end{equation*}
For stability, convergence and dispersion analyses, please see [1,2].
Consider the following problem, \begin{align} \begin{cases} \dfrac{\partial^2 u}{\partial t^2} = \frac{1}{4} \Delta u +\frac{1}{4}e^{t+x+y+z},&(x,y,z)\in I,~t\in(0,1],\\ u(x,y,z,0)=g(x,y,z),&(x,y,z)\in J,\\ \dfrac{\partial }{\partial t}u(x,y,z,0) = s(x,y,z),&(x,y,z)\in J,\\ u(0,y,z,t) = e^{t+y+z},&(y,z)\in [0,1]\times[0,1],~t \in[0,1],\\ u(1,y,z,t) = e^{t+y+z+1},&(y,z)\in [0,1]\times[0,1],~t \in[0,1],\\ u(x,0,z,t) = e^{t+x+z},&(x,z)\in [0,1]\times[0,1],~t \in[0,1],\\ u(x,1,z,t) = e^{t+x+z+1},&(x,z)\in [0,1]\times[0,1],~t \in[0,1],\\ u(x,y,0,t) = e^{t+x+y},&(x,y)\in [0,1]\times[0,1],~t \in[0,1],\\ u(x,y,1,t) = e^{t+x+y+1},&(x,y)\in [0,1]\times[0,1],~t \in[0,1]. \end{cases} \end{align}
The exact solution corresponding to the problem can be found as follows, $$ u(x,t)=e^{t+x+y+z} $$
We can consider one of the following algorithms for this scheme.
def Example01_4thSolver3D(N,Nt):
# N = the number of mesh points for space
# Nt = the number of mesh points for time
Nx=N
Ny=N
Nz=N
# (x,y,z) \in [a_1,a_2]*[b_1,b_2]*[c_1,c_2]
a1 = 0.0
a2 = 1.0
b1 = 0.0
b2 = 1.0
c1 = 0.0
c2 = 1.0
# t \in [T_1,T_2]
T1=0
T2=1
# Delta x, Delta y, Delta z and Delta t
hx =(a2-a1)/Nx
hy =(b2-b1)/Ny
hz =(c2-c1)/Nz
ht =(T2-T1)/Nt
# \lambda_x, \lambda_y and \lambda_z
lx2=(ht/hx)**2
ly2=(ht/hy)**2
lz2=(ht/hz)**2
# Initial and Boundary Conditions
C2 =1/4
g=lambda x,y,z: np.exp(x+y+z)
fa=lambda y,z,t: np.exp(y+z+t)
fb=lambda y,z,t: np.exp(y+z+t+1)
fc=lambda x,z,t: np.exp(x+z+t)
fd=lambda x,z,t: np.exp(x+z+t+1)
fe=lambda x,y,t: np.exp(x+y+t)
ff=lambda x,y,t: np.exp(x+y+t+1)
f=lambda x,y,z,t: np.exp(x+y+z+t)/4
# the exact solution
Ue=lambda x,y,z,t: np.exp(x+y+z+t)
# Additional Constants
rx2=C2*(ht/hx)**2
ry2=C2*(ht/hy)**2
rz2=C2*(ht/hz)**2
px=(1-rx2)/12
py=(1-ry2)/12
pz=(1-rz2)/12
# indeces
mid=list(range(1,Nx))
midp=[i+1 for i in mid]
midm=[i-1 for i in mid]
sup=list(range(1,Nx-1))
sub=list(range(2,Nx))
# Null Matrices
U_exact=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
u0=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
u1=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
F=np.zeros((Nx+1,Ny+1,Nz+1,Nt+1), dtype=float)
FA=np.zeros((Ny+1,Nz+1,Nt+1), dtype=float)
FB=np.zeros((Ny+1,Nz+1,Nt+1), dtype=float)
FC=np.zeros((Nx+1,Nz+1,Nt+1), dtype=float)
FD=np.zeros((Nx+1,Nz+1,Nt+1), dtype=float)
FE=np.zeros((Nx+1,Nz+1,Nt+1), dtype=float)
FF=np.zeros((Nx+1,Nz+1,Nt+1), dtype=float)
# x, y, z and t
xx=np.linspace(a1, a2, Nx+1)
yy=np.linspace(b1, b2, Ny+1)
zz=np.linspace(c1, c2, Nz+1)
tt=np.linspace(T1, T2, Nt+1)
#
for n in range(Nt+1):
for k in range(Nz+1):
for j in range(Ny+1):
F[:,j,k,n] = f(xx,yy[j],zz[k],tt[n])
U_exact[:,j,k] = Ue(xx,yy[j],zz[k],T2)
u0[:,j,k] = g(xx,yy[j],zz[k])
# f{a,j,k}^{n+1} and f{b,j,k}^{n+1}
FA[:,k,n]=fa(yy,zz[k],tt[n])
FB[:,k,n]=fb(yy,zz[k],tt[n])
# f{c,i,k}^{n+1} and f{d,i,k}^{n+1}
FC[:,k,n]= fc(xx,zz[k],tt[n])
FD[:,k,n]= fd(xx,zz[k],tt[n])
for j in range(Ny+1):
# f{e,i,j}^{n+1} and f{f,i,j}^{n+1}
FE[:,j,n]= fc(xx,yy[j],tt[n])
FF[:,j,n]= fd(xx,yy[j],tt[n])
# Computing the solution at the first time step
GG=lambda x,y,z: np.exp(x+y+z+T1)+np.exp(x+y+z+T1)*ht+(0.5)*np.exp(x+y+z+T1)*ht**2\
+(1/6)*np.exp(x+y+z+T1)*ht**3+(1/24)*np.exp(x+y+z+T1)*ht**4
for k in mid:
for j in mid:
u1[mid,j,k]=GG(xx[mid],yy[j],zz[k])
del g, T1, T2
for j in range(Ny+1):
u1[:,j,0]=fe(xx,yy[j],tt[1])
u1[:,j,Nz]=ff(xx,yy[j],tt[1])
for k in range(Nz+1):
u1[0,:,k]=fa(yy,zz[k],tt[1])
u1[Nx,:,k]=fb(yy,zz[k],tt[1])
u1[:,0,k]=fc(xx,zz[k],tt[1])
u1[:,Ny,k]=fd(xx,zz[k],tt[1])
# Marices Ajk, Aik
Ajk = diags([px*np.ones(Nx-2),(1-2*px)*np.ones(Nx-1),px*np.ones(Nx-2)], [-1,0,1])
Aik = diags([py*np.ones(Ny-2),(1-2*py)*np.ones(Ny-1),py*np.ones(Ny-2)], [-1,0,1])
Aij = diags([pz*np.ones(Nz-2),(1-2*pz)*np.ones(Nz-1),pz*np.ones(Nz-2)], [-1,0,1])
# for loop (n>2)
for n in range(1,Nt):
u=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
X=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
Y=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
Z=np.zeros((Nx+1,Ny+1,Nz+1), dtype=float)
# Part 1: Finding the values of Y for current time step
for k in mid:
for j in mid:
A2=(1/144)*rx2*(u1[midp,j+1,k+1]-2*u1[mid,j+1,k+1]+u1[midm,j+1,k+1])+\
(10/144)*rx2*(u1[midp,j+1,k]-2*u1[mid,j+1,k]+u1[midm,j+1,k])+\
(1/144)*rx2*(u1[midp,j+1,k-1]-2*u1[mid,j+1,k-1]+u1[midm,j+1,k-1])+\
(10/144)*rx2*(u1[midp,j,k+1]-2*u1[mid,j,k+1]+u1[midm,j,k+1])+\
(100/144)*rx2*(u1[midp,j,k]-2*u1[mid,j,k]+u1[midm,j,k])+\
(10/144)*rx2*(u1[midp,j,k-1]-2*u1[mid,j,k-1]+u1[midm,j,k-1])+\
(1/144)*rx2*(u1[midp,j-1,k+1]-2*u1[mid,j-1,k+1]+u1[midm,j-1,k+1])+\
(10/144)*rx2*(u1[midp,j-1,k]-2*u1[mid,j-1,k]+u1[midm,j-1,k])+\
(1/144)*rx2*(u1[midp,j-1,k-1]-2*u1[mid,j-1,k-1]+u1[midm,j-1,k-1])
#
A3=(1/144)*ry2*(u1[midp,j+1,k+1]-2*u1[midp,j,k+1]+u1[midp,j-1,k+1])+\
(10/144)*ry2*(u1[midp,j+1,k]-2*u1[midp,j,k]+u1[midp,j-1,k])+\
(1/144)*ry2*(u1[midp,j+1,k-1]-2*u1[midp,j,k-1]+u1[midp,j-1,k-1])+\
(10/144)*ry2*(u1[mid,j+1,k+1]-2*u1[mid,j,k+1]+u1[mid,j-1,k+1])+\
(100/144)*ry2*(u1[mid,j+1,k]-2*u1[mid,j,k]+u1[mid,j-1,k])+\
(10/144)*ry2*(u1[mid,j+1,k-1]-2*u1[mid,j,k-1]+u1[mid,j-1,k-1])+\
(1/144)*ry2*(u1[midm,j+1,k+1]-2*u1[midm,j,k+1]+u1[midm,j-1,k+1])+\
(10/144)*ry2*(u1[midm,j+1,k]-2*u1[midm,j,k]+u1[midm,j-1,k])+\
(1/144)*ry2*(u1[midm,j+1,k-1]-2*u1[midm,j,k-1]+u1[midm,j-1,k-1])
#
A4=(1/144)*rz2*(u1[midp,j+1,k+1]-2*u1[midp,j+1,k]+u1[midp,j+1,k-1])+\
(10/144)*rz2*(u1[midp,j,k+1]-2*u1[midp,j,k]+u1[midp,j,k-1])+\
(1/144)*rz2*(u1[midp,j-1,k+1]-2*u1[midp,j-1,k]+u1[midp,j-1,k-1])+\
(10/144)*rz2*(u1[mid,j+1,k+1]-2*u1[mid,j+1,k]+u1[mid,j+1,k-1])+\
(100/144)*rz2*(u1[mid,j,k+1]-2*u1[mid,j,k]+u1[mid,j,k-1])+\
(10/144)*rz2*(u1[mid,j-1,k+1]-2*u1[mid,j-1,k]+u1[mid,j-1,k-1])+\
(1/144)*rz2*(u1[midm,j+1,k+1]-2*u1[midm,j+1,k]+u1[midm,j+1,k-1])+\
(10/144)*rz2*(u1[midm,j,k+1]-2*u1[midm,j,k]+u1[midm,j,k-1])+\
(1/144)*rz2*(u1[midm,j-1,k+1]-2*u1[midm,j-1,k]+u1[midm,j-1,k-1])
#
S=(1/20736)*(F[midp,j+1,k+1,n+1]+10*F[midp,j+1,k+1,n]+F[midp,j+1,k+1,n-1])+\
(10/20736)*(F[midp,j+1,k,n+1]+10*F[midp,j+1,k,n]+F[midp,j+1,k,n-1])+\
(1/20736)*(F[midp,j+1,k-1,n+1]+10*F[midp,j+1,k-1,n]+F[midp,j+1,k-1,n-1])+\
(10/20736)*(F[midp,j,k+1,n+1]+10*F[midp,j,k+1,n]+F[midp,j,k+1,n-1])+\
(100/20736)*(F[midp,j,k,n+1]+10*F[midp,j,k,n]+F[midp,j,k,n-1])+\
(10/20736)*(F[midp,j,k-1,n+1]+10*F[midp,j,k-1,n]+F[midp,j,k-1,n-1])+\
(1/20736)*(F[midp,j-1,k+1,n+1]+10*F[midp,j-1,k+1,n]+F[midp,j-1,k+1,n-1])+\
(10/20736)*(F[midp,j-1,k,n+1]+10*F[midp,j-1,k,n]+F[midp,j-1,k,n-1])+\
(1/20736)*(F[midp,j-1,k-1,n+1]+10*F[midp,j-1,k-1,n]+F[midp,j-1,k-1,n-1])+\
(10/20736)*(F[mid,j+1,k+1,n+1]+10*F[mid,j+1,k+1,n]+F[mid,j+1,k+1,n-1])+\
(100/20736)*(F[mid,j+1,k,n+1]+10*F[mid,j+1,k,n]+F[mid,j+1,k,n-1])+\
(10/20736)*(F[mid,j+1,k-1,n+1]+10*F[mid,j+1,k-1,n]+F[mid,j+1,k-1,n-1])+\
(100/20736)*(F[mid,j,k+1,n+1]+10*F[mid,j,k+1,n]+F[mid,j,k+1,n-1])+\
(1000/20736)*(F[mid,j,k,n+1]+10*F[mid,j,k,n]+F[mid,j,k,n-1])+\
(100/20736)*(F[mid,j,k-1,n+1]+10*F[mid,j,k-1,n]+F[mid,j,k-1,n-1])+\
(10/20736)*(F[mid,j-1,k+1,n+1]+10*F[mid,j-1,k+1,n]+F[mid,j-1,k+1,n-1])+\
(100/20736)*(F[mid,j-1,k,n+1]+10*F[mid,j-1,k,n]+F[mid,j-1,k,n-1])+\
(10/20736)*(F[mid,j-1,k-1,n+1]+10*F[mid,j-1,k-1,n]+F[mid,j-1,k-1,n-1])+\
(1/20736)*(F[midm,j+1,k+1,n+1]+10*F[midm,j+1,k+1,n]+F[midm,j+1,k+1,n-1])+\
(10/20736)*(F[midm,j+1,k,n+1]+10*F[midm,j+1,k,n]+F[midm,j+1,k,n-1])+\
(1/20736)*(F[midm,j+1,k-1,n+1]+10*F[midm,j+1,k-1,n]+F[midm,j+1,k-1,n-1])+\
(10/20736)*(F[midm,j,k+1,n+1]+10*F[midm,j,k+1,n]+F[midm,j,k+1,n-1])+\
(100/20736)*(F[midm,j,k,n+1]+10*F[midm,j,k,n]+F[midm,j,k,n-1])+\
(10/20736)*(F[midm,j,k-1,n+1]+10*F[midm,j,k-1,n]+F[midm,j,k-1,n-1])+\
(1/20736)*(F[midm,j-1,k+1,n+1]+10*F[midm,j-1,k+1,n]+F[midm,j-1,k+1,n-1])+\
(10/20736)*(F[midm,j-1,k,n+1]+10*F[midm,j-1,k,n]+F[midm,j-1,k,n-1])+\
(1/20736)*(F[midm,j-1,k-1,n+1]+10*F[midm,j-1,k-1,n]+F[midm,j-1,k-1,n-1])
#
Fjk=A2+A3+A4+(ht**2)*S
del A2, A3, A4, S
# X_{0jk}
X_0jk=py*pz*(FA[j+1,k+1,n+1]+FA[j+1,k-1,n+1]+FA[j-1,k+1,n+1]+FA[j-1,k-1,n+1]+\
FA[j+1,k+1,n-1]+FA[j+1,k-1,n-1]+FA[j-1,k+1,n-1]+FA[j-1,k-1,n-1]+\
-2*(FA[j+1,k+1,n]+FA[j+1,k-1,n]+FA[j-1,k+1,n]+FA[j-1,k-1,n]))\
+(1-2*py)*pz*(FA[j,k+1,n+1]+FA[j,k-1,n+1]+FA[j,k+1,n-1]+FA[j,k-1,n-1]+\
-2*(FA[j,k+1,n]+FA[j,k-1,n]))\
+py*(1-2*pz)*(FA[j+1,k,n+1]+FA[j-1,k,n+1]+FA[j+1,k,n-1]+FA[j-1,k,n-1]+\
-2*(FA[j+1,k,n]+FA[j-1,k,n]))\
+(1-2*py)*(1-2*pz)*(FA[j,k,n+1]-2*FA[j,k,n]+FA[j,k,n-1])
# X_{Nxjk}
X_Nxjk=py*pz*(FB[j+1,k+1,n+1]+FB[j+1,k-1,n+1]+FB[j-1,k+1,n+1]+FB[j-1,k-1,n+1]+\
FB[j+1,k+1,n-1]+FB[j+1,k-1,n-1]+FB[j-1,k+1,n-1]+FB[j-1,k-1,n-1]+\
-2*(FB[j+1,k+1,n]+FB[j+1,k-1,n]+FB[j-1,k+1,n]+FB[j-1,k-1,n]))\
+(1-2*py)*pz*(FB[j,k+1,n+1]+FB[j,k-1,n+1]+FB[j,k+1,n-1]+FB[j,k-1,n-1]+\
-2*(FB[j,k+1,n]+FB[j,k-1,n]))\
+py*(1-2*pz)*(FB[j+1,k,n+1]+FB[j-1,k,n+1]+FB[j+1,k,n-1]+FB[j-1,k,n-1]+\
-2*(FB[j+1,k,n]+FB[j-1,k,n]))\
+(1-2*py)*(1-2*pz)*(FB[j,k,n+1]-2*FB[j,k,n]+FB[j,k,n-1])
# b_jk
bjk=np.zeros(len(mid), dtype=float)
bjk[0]=-px*X_0jk
bjk[Nx-2]=-px*X_Nxjk
# Y
X[mid,j,k]=spsolve(Ajk,Fjk+bjk, use_umfpack=True)
del bjk, X_0jk, X_Nxjk
# Part 2: Finding the values of Y for current time step
for k in mid:
for i in mid:
Y_i0k=pz*(FC[i,k-1,n+1]+FC[i,k+1,n+1]+FC[i,k-1,n-1]+FC[i,k+1,n-1]\
-2.*(FC[i,k-1,n]+FC[i,k+1,n]))+(1-2*pz)*(FC[i,k,n+1]-2*FC[i,k,n]+FC[i,k,n-1])
Y_iNyj=pz*(FD[i,k-1,n+1]+FD[i,k+1,n+1]+FD[i,k-1,n-1]+FD[i,k+1,n-1]+\
-2.*(FD[i,k-1,n]+FD[i,k+1,n]))+(1-2*pz)*(FD[i,k,n+1]-2*FD[i,k,n]+FD[i,k,n-1])
# b_ik
bik=np.zeros(len(mid), dtype=float)
bik[0]=-py*Y_i0k
bik[Nx-2]=-py*Y_iNyj
# Y
Y[i,mid,k]=spsolve(Aik,X[i,mid,k]+bik, use_umfpack=True)
del bik
# Part 3: Finding the values of u**{n+1} for current time step
for j in mid:
for i in mid:
bij=np.zeros(len(mid), dtype=float)
bij[0]=-pz*(FE[i,j,n+1]-2*FE[i,j,n]+FE[i,j,n-1])
bij[Nx-2]=-pz*(FF[i,j,n+1]-2*FF[i,j,n]+FF[i,j,n-1])
Z[i,j,mid]=spsolve(Aij,Y[i,j,mid]+bij, use_umfpack=True)
u=Z+2*u1-u0
u[0,:,:]=FA[:,:,n+1]
u[Nx,:,:]=FB[:,:,n+1]
u[:,0,:]=FC[:,:,n+1]
u[:,Ny,:]=FD[:,:,n+1]
u[:,:,0]=FE[:,:,n+1]
u[:,:,Nz]=FF[:,:,n+1]
u0=u1
u1=u
# Norm
U_Comp = u
Norm=np.max(np.abs(U_Comp - U_exact))
return Norm, U_exact, U_Comp
The results of analyzing the numerical solution of the problem, using the explicit scheme, is available at the following tables.
it=3
Norm=np.zeros(it, dtype=float)
N0=5;
Nt0=100;
N=np.asarray([N0*2**n for n in range(0,it)])
Nt=np.asarray([Nt0 for n in range(0,it)])
Ratio=np.zeros(it, dtype=float)
LOG=np.zeros(it, dtype=float)
CPU_Time=np.zeros(it, dtype=float)
# iteration
for n in range(it):
start = timer()
Norm[n],_,_ =Example01_4thSolver3D(N[n],Nt[n])
CPU_Time[n] = timer() - start
if (n>0):
Ratio[n]=Norm[n-1]/Norm[n]
LOG[n]=math.log(Ratio[n],2)
data = pd.DataFrame({'Nx': N, 'Ny': N, 'Nz': N, 'Nt': Nt, 'Norm': Norm, 'Ratio': Ratio, 'Log': LOG, 'CPU Time': CPU_Time})
del it, Norm, N0, Nt0, N, Nt, Ratio, LOG, CPU_Time, n, start
display(data.style.format({'Norm': "{:.4e}"}))
Nx | Ny | Nz | Nt | Norm | Ratio | Log | CPU Time | |
---|---|---|---|---|---|---|---|---|
0 | 5 | 5 | 5 | 100 | 1.9403e-05 | 0.000000 | 0.000000 | 1.959819 |
1 | 10 | 10 | 10 | 100 | 1.2460e-06 | 15.571977 | 3.960880 | 9.779507 |
2 | 20 | 20 | 20 | 100 | 7.8091e-08 | 15.956298 | 3.996054 | 46.719550 |
it=3
Norm=np.zeros(it, dtype=float)
N0=10;
Nt0=20;
N=np.asarray([N0*2**n for n in range(0,it)])
Nt=np.asarray([Nt0*2**n for n in range(0,it)])
Ratio=np.zeros(it, dtype=float)
LOG=np.zeros(it, dtype=float)
CPU_Time=np.zeros(it, dtype=float)
# iteration
for n in range(it):
start = timer()
Norm[n],_,_ =Example01_4thSolver3D(N[n],Nt[n])
CPU_Time[n] = timer() - start
if (n>0):
Ratio[n]=Norm[n-1]/Norm[n]
LOG[n]=math.log(Ratio[n],2)
data = pd.DataFrame({'Nx': N, 'Ny': N, 'Nz': N, 'Nt': Nt, 'Norm': Norm, 'Ratio': Ratio, 'Log': LOG, 'CPU Time': CPU_Time})
del it, Norm, N0, Nt0, N, Nt, Ratio, LOG, CPU_Time, n, start
display(data.style.format({'Norm': "{:.4e}"}))
Nx | Ny | Nz | Nt | Norm | Ratio | Log | CPU Time | |
---|---|---|---|---|---|---|---|---|
0 | 10 | 10 | 10 | 20 | 1.2471e-06 | 0.000000 | 0.000000 | 1.921903 |
1 | 20 | 20 | 20 | 40 | 8.1117e-08 | 15.374460 | 3.942464 | 18.566368 |
2 | 40 | 40 | 40 | 80 | 5.0688e-09 | 16.003099 | 4.000279 | 177.805493 |
What stands out from the tables is that the order of the method is 4 (in space and time). Moreover, consider the following experiment to test the stability condition.
Das, Sambit, Wenyuan Liao, and Anirudh Gupta. "An efficient fourth-order low dispersive finite difference scheme for a 2-D acoustic wave equation." Journal of computational and Applied Mathematics 258 (2014): 151-167.
Liao, Wenyuan. "On the dispersion, stability and accuracy of a compact higher-order finite difference scheme for 3D acoustic wave equation." Journal of Computational and Applied Mathematics 270 (2014): 571-583.
Liao, Wenyuan. "An implicit fourth-order compact finite difference scheme for one-dimensional Burgers’ equation." Applied Mathematics and Computation 206.2 (2008): 755-764.