Hi all,
I am quite new to FiPy, which I have been using to simulate a
reaction-diffusion model of bacterial colony growth:
# Simulation parameters
d = 0.12
a0 = 1.; a1 = 1./2400; a2 = 1./120;
v0 = 0.071
# Source terms
Suu = uu*vv - uu/((1+uu/a1)*(1+vv/a2))
Svv = -uu*vv
Sww = uu/((1+uu/a1)*(1+vv/a2))
# Equations
eqXuu = TransientTerm() - ImplicitDiffusionTerm(coeff=d) - Suu
eqXvv = TransientTerm() - ImplicitDiffusionTerm(coeff=1.) - Svv
eqXww = TransientTerm() - Sww
There are three PDEs, two of which have linear diffusion terms,
and
the
equations are coupled via nonlinear reaction terms. I hope to be
able to use
Fipy on a fairly large mesh to explore the pattern formation
possibilities
of the system as certain parameters are varied, but the
simulations
run
significantly slower than I'd expected, about 4-5 minutes per run
(with
--inline and the pysparse solver on a 2008 Mac Pro) on a 150x150
square
mesh; 600x600 is more like what I'd like to be able to use.
Before using FiPy, I'd implemented the system in Matlab, just
using
finite
differences with a 9 point stencil. I haven't gotten much, if
any,
speed up
using FiPy, but I think I'm not using FiPy's full capabilities,
or
I've not
implemented the model in FiPy as efficiently as I could have. The
script I'm
using is below. I suspect that the looping I'm doing for the
sweeps
of each
variable in succession is not the right way to go about things.
I've played
around with sweeps and time step sizes, but haven't gotten much
improvement.
If the looping isn't the problem, should I try moving to
trilinos?
Or should
I not expect particularly fast solution of this kind of system?
Any suggestions for better performance would be welcome.
Thanks,
Erik
from fipy import *
from time import clock
# Setting up the mesh
nx = 150
ny = nx
dx = 1.0
dy = dx
L = dx*nx
mesh = Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
# Simulation parameters
d = 0.12
a0 = 1.; a1 = 1./2400; a2 = 1./120;
v0 = 0.071
# Simulation variables
uu = CellVariable(name="active bacteria",
mesh=mesh,
value=0.0, hasOld=1)
ww = CellVariable(name="inactive bacteria",
mesh=mesh,
value=0.0, hasOld=1)
vv = CellVariable(name="nutrient concentration",
mesh=mesh,
value=v0, hasOld=1)
# Source terms
Suu = uu*vv - uu/((1+uu/a1)*(1+vv/a2))
Svv = -uu*vv
Sww = uu/((1+uu/a1)*(1+vv/a2))
# Equations
eqXuu = TransientTerm() - ImplicitDiffusionTerm(coeff=d) - Suu
#ImplicitSourceTerm(Suu)
eqXvv = TransientTerm() - ImplicitDiffusionTerm(coeff=1.) - Svv
#ImplicitSourceTerm(Svv)
eqXww = TransientTerm() - Sww #ImplicitSourceTerm(Sww)
# Initial conditions
x,y = mesh.getCellCenters()
radius = 10*dx
C = (nx*dx/2, ny*dy/2)
C =(0,0)
uu.setValue(UniformNoiseVariable(mesh=mesh, minimum=0.09,
maximum=0.115))
uu.setValue(0.0,where=(0.05*(x-C[0])**2 + (y-C[1])**2) >
radius**2)
eqns = ((uu, eqXuu), (vv, eqXvv), (ww, eqXww))
if __name__ == '__main__':
# Do plotting if executing script from commandline
Uview = uu
Uview.setName('Active')
Uviewer = Viewer(vars=uu, datamin=0., datamax=0.1)
Vview = vv
Vview.setName('Nutrient')
Vviewer = Viewer(vars=Vview, datamin=0., datamax=0.1)
Wview = ww
Wview.setName('Inactive')
Wviewer = Viewer(vars=Wview, datamin=0., datamax=0.1)
dt = 2.0
steps = 1000
desiredResidual = 1e-6
# Loop through timesteps
tic = clock()
for step in range(steps):
print "Step %d"%(step)
# For each variable, equation pair, do sufficient sweeps to
# get residual to acceptable level. When all three variables
# have been taken care of, then we take the next time step
for var, eqn in eqns:
residual = 10
var.updateOld()
sweepcount = 0
while residual > desiredResidual and sweepcount < 300:
#print "Sweep %d"%(sweepcount+1)
residual = eqn.sweep(var=var, dt=dt)
sweepcount += 1
# Bail if residual remains too large
if residual > desiredResidual:
print "Unable to reduce residual!"
break
if residual > desiredResidual:
break
# Update the plots
if __name__ == '__main__':
Uviewer.plot()
Vviewer.plot()
Wviewer.plot()
#
toc = clock()
print "Finished in %.3f secs."%(toc-tic)