I am trying to reproduce Matlab example https://se.mathworks.com/help/matlab/math/solve-system-of-pdes.html using FiPy. However, I am unable to reproduce the Matlab results (I am newbie when using Fipy). I think the problem is probably in function or in boundary condition declarations. Also, I did not find Fipy setValue property for variable with respect of t for initial conditions, so I override it with very clumsy loop structure. Here is my test code:
from fipy import *
from fipy import Grid2D, CellVariable,TransientTerm, DiffusionTerm
from fipy.tools import numerix
import matplotlib.pyplot as plt
import numpy as np
from sys import stdout
from builtins import range
import plotly.graph_objects as go
nx = 100
ny = 100
Lx = 1
Ly = 2
mesh = Grid2D(nx=nx, ny=ny,Lx=Lx,Ly=Ly)
u1 = CellVariable(name = "solution variable u1", hasOld=True, mesh = mesh, value = 0.)
u2 = CellVariable(name = "solution variable u2", hasOld=True, mesh = mesh, value = 0.)
z1=np.zeros((nx,ny))
z2=np.zeros((nx,ny))
u_mask1=np.zeros(nx*ny)
u_mask2=np.zeros(nx*ny)
#initial conditions
#compute mask
z1[:,0]=1
z2[:,0]=0
for i in range(nx): #x
for j in range(ny): #t
if i==0:
position=j
else:
position=i*ny+j-1
u_mask1[position]=z1[i,j]
u_mask2[position]=z2[i,j]
u1.setValue(1, where=u_mask1)
#u2.setValue(0, where=u_mask2) #unnecessary
#constrains
u1.constrain(1.0, where=mesh.facesRight) #Direction?
u2.constrain(0.0, where=mesh.facesLeft) #Direction?
u1.grad.dot([1.0, 0.0]).constrain(0.0, where=mesh.facesLeft)
u2.grad.dot([1.0, 0.0]).constrain(0.0, where=mesh.facesRight)
eqn0 = TransientTerm(var=u1) == DiffusionTerm(0.024, var=u1) - (numerix.exp(5.73*(u1-u2))-numerix.exp(-11.46*(u1-u2)))
eqn1 = TransientTerm(var=u2) == DiffusionTerm(0.170, var=u2) + (numerix.exp(5.73*(u1-u2))-numerix.exp(-11.46*(u1-u2)))
eqn = eqn0 & eqn1
#compute equations
max_range=1000
for t in range(0,max_range):
stdout.write("\r%3.2f" % (t/max_range*100))
stdout.flush()
u1.updateOld()
u2.updateOld()
eqn.sweep(dt=0.002)
#eqn.solve(dt=1.e-3)
z1=np.zeros((nx,ny))
z2=np.zeros((nx,ny))
for i in range(nx): #x
for j in range(ny): #t
if i==0:
position=j
else:
position=i*ny+j-1
z1[i,j]=u1[position]
z2[i,j]=u2[position]
x, y = np.linspace(0, Lx, nx), np.linspace(0, Ly, ny)
fig = go.Figure(data=[go.Surface(z=z1, x=x, y=y)])
fig.update_layout(scene = dict(
xaxis_title='X',
yaxis_title='T',
zaxis_title='Z'),
title='u1',
width=600,
height=600,
margin=dict(r=20, b=10, l=10, t=10)
)
fig.show()
fig = go.Figure(data=[go.Surface(z=z2, x=x, y=y)])
fig.update_layout(scene = dict(
xaxis_title='X',
yaxis_title='T',
zaxis_title='Z'),
title='u2',
width=600,
height=600,
margin=dict(r=20, b=10, l=10, t=10)
)
fig.show()