src/diffusion.h
Time-implicit discretisation of reaction–diffusion equations
We want to discretise implicitly the reaction–diffusion equation \theta\partial_tf = \nabla\cdot(D\nabla f) + \beta f + r where \beta f + r is a reactive term, D is the diffusion coefficient and \theta can be a density term.
Using a time-implicit backward Euler discretisation, this can be written \theta\frac{f^{n+1} - f^{n}}{dt} = \nabla\cdot(D\nabla f^{n+1}) + \beta f^{n+1} + r Rearranging the terms we get \nabla\cdot(D\nabla f^{n+1}) + (\beta - \frac{\theta}{dt}) f^{n+1} = - \frac{\theta}{dt}f^{n} - r This is a Poisson–Helmholtz problem which can be solved with a multigrid solver.
#include "poisson.h"
The parameters of the diffusion()
function are a scalar
field f
, scalar fields r
and \beta defining the reactive term, the
timestep dt
and a face vector field containing the
diffusion coefficient D
. If D
or \theta are omitted they are set to one. If
\beta is omitted it is set to zero.
Both D
and \beta may be
constant fields.
Note that the r
, \beta
and \theta fields will be modified by
the solver.
The function returns the statistics of the Poisson solver.
trace
mgstats diffusion (scalar f, double dt,
face vector D = {{-1}}, // default 1
scalar r = {-1}, // default 0
scalar beta = {-1}, // default 0
scalar theta = {-1}) // default 1
{
If dt is zero we don’t do anything.
if (dt == 0.) {
mgstats s = {0};
return s;
}
We define f and r for convenience.
scalar ar = automatic (r);
We define a (possibly constant) field equal to \theta/dt.
const scalar idt[] = - 1./dt;
(const) scalar theta_idt = theta.i >= 0 ? theta : idt;
if (theta.i >= 0)
foreach()
[] *= idt[]; theta
We use r
to store the r.h.s. of the Poisson–Helmholtz
solver.
if (r.i >= 0)
foreach()
[] = theta_idt[]*f[] - ar[];
arelse // r was not passed by the user
foreach()
[] = theta_idt[]*f[]; ar
If \beta is provided, we use it to store the diagonal term \lambda.
scalar lambda = theta_idt;
if (beta.i >= 0) {
foreach()
[] += theta_idt[];
beta= beta;
lambda }
Finally we solve the system.
return poisson (f, ar, D, lambda);
}