1% ex_reaction_diffusion.m — A time-dependent PDE on a surface.
2%
3% The complex Ginzburg-Landau equation
4%
5% du/dt = delta (1 + i*alpha) Delta_Gamma u + u - (1 + i*beta) u |u|^2
6%
7% is integrated with a semi-implicit (backward-Euler) scheme: the
8% diffusion term is treated implicitly, the reaction term explicitly. The
9% diffusion operator is time-independent, so one surfaceop factorization
10% is reused at every step. We use a sphere and a short run to stay quick.
12mip load --install flatironinstitute/flatironinstitute/surfacefun
14% Parameters.
15dt = 0.1;
16nsteps = 60;
17alpha = 0;
18beta = 1.5;
19delta = 5e-3;
21% Nonlinear (reaction) term.
22N = @(u) u - (1 + beta*1i)*u .* (abs(u).^2);
24% Mesh and the reusable implicit solver for (I - dt*delta*(1+i*alpha) Lap).
25p = 8;
26nref = 1;
27dom = surfacemesh.sphere(p + 1, nref);
28pdo = struct('lap', -dt*delta*(1 + alpha*1i), 'c', 1);
29L = surfaceop(dom, pdo);
30L.build();
32% Random initial condition.
33rng(1)
34f = randnfun3(0.5, boundingbox(dom));
35u = surfacefun(@(x, y, z) f(x, y, z), dom);
37figure(1);
38plot(real(u)), colorbar
39title('Initial condition');
41% Time stepping: each step is one solve with a fresh right-hand side.
42for k = 1:nsteps
43 L.rhs = u + dt*N(u);
44 u = L.solve();
45end
47figure(2);
48plot(real(u)), colorbar
49title(sprintf('Re(u) after %d steps (t = %.1f)', nsteps, nsteps*dt));
51fprintf('done: %d steps, ||Re(u)|| = %.4f\n', nsteps, norm(real(u)));