1% Brusselator reaction-diffusion on a closed surface.
2%
3% du/dt = D1*lap_g(u) + A - (B+1)*u + u^2*v
4% dv/dt = D2*lap_g(v) + B*u - u^2*v
5%
6% Same scheme as models/schnakenberg.m, including the grouped transforms:
7% [a, b] = synth(x, y) runs the group as batched Legendre dispatches.
9% Seeded from a smooth random field -- see models/schnakenberg.m.
10function [U, V, u, v] = init(lam3, gx, gy, gz, A, B)
11 f = randnfun3(lam3, gx, gy, gz);
12 [U, V] = analys(A + 0.01*f, (B / A) * ones(numel(f), 1));
13 [u, v] = synth(U, V);
14end
16function [Un, Vn, u, v] = step(U, V, lam, filt, gx, gy, gz, p1, p2, q2, r, jhat, A, B, D1, D2, dt, niter)
17 [u, v] = synth(U, V);
18 uuv = u .* u .* v;
20 ru = A - (B + 1) * u + uuv;
21 rv = B * u - uuv;
22 [Ru, Rv] = analys(ru, rv);
23 Bu = U + dt * Ru;
24 Bv = V + dt * Rv;
26 % Mean-J preconditioning -- see models/schnakenberg.m.
27 lamJ = lam ./ jhat;
28 Un = Bu ./ (1 + (dt * D1) * lamJ);
29 Vn = Bv ./ (1 + (dt * D2) * lamJ);
31 for k = 1:niter
32 % dlap = lap_g - lap_s, evaluated at the current iterate in flux form
33 % (see models/schnakenberg.m, docs/richardson-iteration.md and
34 % docs/reduced-transforms.md for the derivation and the ordering).
35 Fu = Un .* filt;
36 Fv = Vn .* filt;
37 vtu = dthetac(Fu);
38 vpu = dphic(Fu);
39 vtv = dthetac(Fv);
40 vpv = dphic(Fv);
41 [Ftu, Fpu, Ftv, Fpv] = synth(vtu, vpu, vtv, vpv);
42 Pu = p1 .* Ftu + p2 .* Fpu;
43 Qu = p2 .* Ftu + q2 .* Fpu;
44 Pv = p1 .* Ftv + p2 .* Fpv;
45 Qv = p2 .* Ftv + q2 .* Fpv;
46 [PAu, PAv] = analys(Pu, Pv);
47 Pcu = PAu .* filt;
48 Pcv = PAv .* filt;
49 scu = dthetac(Pcu);
50 scv = dthetac(Pcv);
51 [Lu, Lv] = synth(scu, scv);
52 dQu = dphig(Qu);
53 dQv = dphig(Qv);
54 lapu = r .* (Lu + dQu);
55 lapv = r .* (Lv + dQv);
56 [LAu, LAv] = analys(lapu, lapv);
57 dLu = (LAu + lamJ .* Un) .* filt;
58 dLv = (LAv + lamJ .* Vn) .* filt;
60 Un = (Bu + (dt * D1) * dLu) ./ (1 + (dt * D1) * lamJ);
61 Vn = (Bv + (dt * D2) * dLv) ./ (1 + (dt * D2) * lamJ);
62 end
63end