Multidimensional PDEs

FTCS method

$$f_{i,j}^{n+1} = f_{i,j}^n + \frac{\alpha\Delta t}{\Delta x^2}(f_{i-1,j}^n-2f_{i,j}^n+f_{i+1,j}^n) + \frac{\alpha\Delta t}{\Delta y^2}(f_{i,j-1}^n-2f_{i,j}^n+f_{i,j+1}^n) + \Delta tS_{i,j}.$$
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import time
from IPython.display import display, clear_output

Lxy     = 1.0                 # domain length Lx=Ly
nTauRun = 0.2                 # number of intrinsic timescale to run for
nxy     = 22                  # number of grid points in x and y directions
α       = 1.0                 # thermal diffusivity
tFac    = 0.5                 # timestep size factor. 
         
tau  = Lxy**2/α               # diffusive timescale based on the whole domain.
tend = nTauRun*tau            # run time
dxy  = Lxy/(nxy-1)            # grid spacing in x and y directions
dt   = tFac*dxy**2*α/4        # timestep size
nt   = int(np.ceil(tend/dt))  # number of timesteps
nPlt = np.ceil(1/tFac)*10     # how often to plot

f = np.zeros((nxy,nxy))       # solution array
S = np.ones((nxy,nxy))    # source term array

X,Y = np.meshgrid(np.linspace(0,Lxy,nxy), np.linspace(0,Lxy,nxy))
i = np.arange(1,nxy-1)
j = np.arange(1,nxy-1)
IJ = np.ix_

for it in range(nt):
    f[IJ(i,j)] += α*dt/dxy**2*(f[IJ(i-1,j)] - 2*f[IJ(i,j)] + f[IJ(i+1,j)]) + \
                  α*dt/dxy**2*(f[IJ(i,j-1)] - 2*f[IJ(i,j)] + f[IJ(i,j+1)]) + \
                  dt*S[IJ(i,j)]
    
    if it%nPlt==0:
        plt.clf()
        plt.contourf(X,Y,f,levels=np.linspace(0,dt*260,21))
        plt.colorbar()
        plt.gca().set_aspect('equal', adjustable='box')
        clear_output(wait=True)
        display(plt.gcf())
        time.sleep(0.1)
plt.clf()
multiD
<Figure size 768x480 with 0 Axes>

BTCS method

$$f_{i,j}^{n+1} = f_{i,j}^n + \frac{\alpha\Delta t}{\Delta x^2}(f_{i-1,j}^{n+1}-2f_{i,j}^{n+1}+f_{i+1,j}^{n+1}) + \frac{\alpha\Delta t}{\Delta y^2}(f_{i,j-1}^{n+1}-2f_{i,j}^{n+1}+f_{i,j+1}^{n+1}) + \Delta tS_{i,j}.$$

Matrix form

Matrix structure:

multiD

Here is the matrix in terms of coefficients:

multiD
A = np.zeros((5,5))
A[1:4,1:4] = 1
A
array([[0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 0.],
       [0., 1., 1., 1., 0.],
       [0., 1., 1., 1., 0.],
       [0., 0., 0., 0., 0.]])
A[1:4,1:4]
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
i = [1,2,3]
j = [1,2,3]

A[i,j]
array([1., 1., 1.])
i = [1,2,3]
j = [1,2,3]

A[np.ix_(i,j)]
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
a = -4*np.array([1,1,1,1])
b = [1,1,1]
c = [1,1,1]

A = np.diag(a) + np.diag(b,-1) + np.diag(c,1)
A
array([[-4,  1,  0,  0],
       [ 1, -4,  1,  0],
       [ 0,  1, -4,  1],
       [ 0,  0,  1, -4]])