The 3D companion sim animates ~500 discrete instanced spheres doing an independent random walk across the perovskite thickness. This 2D version solves the same drift-diffusion continuity equation as a continuum concentration field c(x,t) on a 90-cell spatial grid spanning the absorber thickness — a genuinely different numerical method (finite-volume PDE vs. stochastic particles), not a flattened camera view:
Continuity: ∂c/∂t = -∂J_ion/∂x
Ion flux: J_ion = μ·E·c - D·∂c/∂x
Einstein relation: D = μ·k_BT
Arrhenius mobility: μ(T) = μ₀·exp[-E_a/k_B (1/T - 1/T₀)]
Each animation frame the flux is evaluated at every cell face with an upwind advective term and a central-difference diffusive term, then the field is updated with as many stability-limited sub-steps as the local Courant/diffusion numbers demand (so a fast, hot, mobile sweep still integrates correctly instead of going unstable). The field's first moment ⟨x⟩ = ∫x·c dx / ∫c dx plays the same role as the 3D scene's averaged discrete ion positions:
V_eff(t) = V(t) - α·⟨x⟩(t)
J(V_eff) = J_sc - J₀·[exp(V_eff / nV_t) - 1]
Because ⟨x⟩ lags the applied voltage (set by mobility and vacancy density), forward and reverse sweeps trace different J-V paths — the same scan-rate-dependent hysteresis as the 3D view, now visible directly as a heatmap: the field brightens and piles up against one electrode as it screens the bias, then visibly relaxes back once the sweep reverses.
- Scan rate — how fast V(t) sweeps; slow scans let the field keep up (less hysteresis), fast scans outrun it (more hysteresis).
- Ion mobility μ and vacancy density — set the drift speed/diffusion and the field's total inventory (brightness), same as the 3D view's spread and instance count.
- Temperature — mobility follows an Arrhenius law with a ~0.35 eV migration barrier, so hysteresis collapses at high T and worsens in the cold.
Units are normalized for a responsive, illustrative animation, as in the 3D version.