Roadmap: milestones, tasks, acceptance criteria
Status: v0.2 (2026-11-10), updated with the grill decisions. Durations are rough estimates for part-time work and will be revised after M1.
Conventions: milestone Mn, task Mn.m. A milestone is done when all its acceptance criteria (AC) are checked by an automated test or a recorded experiment, just check is green, and the docs reflect the result. Experiments En are specified in 04-experiments.md, tests in 03-verification.md, crates in 05-architecture.md.
1. Overview
flowchart TD
M0[M0 Plan and literature] --> M1[M1 Workspace, core types, CI]
M1 --> M2[M2 Disk model]
M2 --> M3[M3 Kinematics, rates, outcomes]
M1 --> M4a[M4a Kernel framework + analytic kernels]
M3 --> M4b[M4b Physical kernels:<br/>coag, frag, bouncing]
M4a --> M4b
M4a --> M5[M5 Explicit integrators<br/>+ analytic benchmarks]
M5 --> M6[M6 Implicit integrators,<br/>own Radau IIA]
M4b --> M6
M6 --> R[R Thesis reproduction<br/>baseline]
R --> M7[M7 Unbiased sampling,<br/>implicit sampled form]
M7 --> M8[M8 Variance reduction,<br/>noise, Jacobians, cost]
M8 --> M9[M9 Second property:<br/>filling factor]
M0 --> V1[M10a Web app: design]
V1 --> V2[M10b Views ship with<br/>each milestone M2 to M9]
M2 --> V2
V2 --> V3[M10c Web app: integration,<br/>sampling, comparisons]
M8 --> V3
M4b --> P0[M11a Short note to Dullemond<br/>with website URL]
M7 --> P1[M11b Full pitch:<br/>bias result, paper proposal]
M9 --> P2[M11c Paper draft,<br/>reproducibility package]
P1 --> P2
gantt
title Indicative timeline (part-time)
dateFormat YYYY-MM-DD
axisFormat %b %y
section Foundations
M0 Plan and literature :done, m0, 2026-11-10, 14d
M1 Workspace and core :m1, after m0, 14d
section Physics
M2 Disk model :m2, after m1, 14d
M3 Kinematics and outcomes :m3, after m2, 21d
M4a Kernel framework :m4a, after m1, 14d
M4b Physical kernels :m4b, after m3, 21d
section Numerics
M5 Explicit integrators :m5, after m4a, 14d
M6 Implicit integrators, Radau :m6, after m4b, 28d
R Thesis reproduction :r, after m6, 14d
section Research
M7 Unbiased sampling :m7, after r, 28d
M8 Variance, noise, cost :m8, after m7, 42d
M9 Second property :m9, after m8, 42d
section Visualization
M10a Design :m10a, after m0, 28d
M10b Views per milestone :m10b, after m2, 280d
M10c Integration and sampling :m10c, after m8, 28d
section Paper
M11a Short note to Dullemond :milestone, m11a, after m4b, 0d
M11b Full pitch :milestone, m11b, after m7, 0d
M11c Draft and package :m11c, after m9, 42d
2. Milestones
M0: Plan and literature (this document set)
- M0.1 Read thesis, code,
coag_py, Dullemond notes, local papers. Done. - M0.2 Thesis review with findings (01-thesis-review.md). Done.
- M0.3 Literature map, glossary, notation. Done.
- M0.4 Vision, roadmap, verification, experiments, architecture, ADR set. Done (drafts).
- M0.5 Iterate on the plan with Vincent (grill session, 27 decisions in the decision log); ADRs 0001 to 0016 accepted. Done.
- M0.6 Decide audience and licence, repo hosting. Done: private until submission, open-source with the paper (06-risks-and-open-questions.md, Q1).
AC: Vincent has accepted the vision, roadmap, and ADRs. Done 2026-11-10.
M1: Workspace, core types, CI
- M1.1 Done.
git initinrepo/(done with this plan;related/stays outside and read-only), Cargo workspace per ADR 0002,justfile(check,test,bench,run), lints,deny.toml, projectAGENTS.md. - M1.2 Done (constants moved to M2.1, where the disk model needs them and the thesis-vs-CODATA parity question arises).
coag-core:Realtrait (f64, double-double; f128 behind a nightly feature, ADR 0016), physical constants (CODATA, IAU),Axis(linear, logarithmic; edges, centers, widths, index lookup),ParticleGridwith flattened multi-index (ADR 0004),State(N per cell and bin; one cell for now, ADR 0015) with mass and number moments. - M1.3 Done. Config schema with serde + TOML, every toggle explicit, config hash (ADR 0010).
- M1.4 Done (
coag-sim:.npywriter and reader,manifest.jsonwith SHA-256 config hash). Output writer and run manifest (ADR 0011). - M1.5 Done (ChaCha8 keyed by the seed, injective stream ids, golden values pinned). Deterministic RNG streams (ADR 0009).
- M1.6 Repository and CI done (vincentmader/coagulation,
.github/workflows/check.yml); docs site built and tested locally (site/docs), deploy pending (DNS points to mk1, Caddy site file not yet in vps-infra). Private GitHub repositorycoagulation; CI runsjust check; a deploy job publishes a docs page rendered fromdoc/to https://coag.mader.xyz (static site on mk11, Caddy site file invps-infra, perhetzner-deploy; DNS is set up). Localjust checkbefore each commit stays the primary gate.
AC: axis round-trip index(value(k)) = k for 10⁶ random k; geometric centers and q_m match the thesis grid to 10⁻¹⁵; manifest written and parsed back; same seed gives bit-identical draws on macOS and wasm32; f64 and double-double builds of coag-core pass the same tests; https://coag.mader.xyz serves the rendered docs.
M2: Disk model
- M2.1 Physical constants (CODATA, IAU; thesis values behind a toggle for parity). Star, gas surface density power law with normalization to M_gas (thesis) and alternative normalization (Σ at 1 au), radial grid.
- M2.2 Temperature (irradiated, optional floor), c_s, Ω_K, H_p, ρ_g(r, z), n_g, λ_mfp, u_th, ν_mol, ν_t, Re, pressure gradient, u_n, u_g with both viscosity choices (finding F6).
- M2.3
LocalConditionsevaluated at (r₀, z₀) and passed down as plain data (no lower crate calls the disk model, ADR 0015); the cell position is a config key; analytic derivatives where available instead of finite differences. - M2.4 Parity with thesis
Disk/DiskRegionand with Dullemond’sdiskmodel.py(for σ = 1). - M2.5 Export radial profiles for the web app and for figures (thesis Figs. temperature, sound speed, gas density 2×2).
- M2.6 Disk view live on coag.mader.xyz (first app view, after the M10a design is approved).
AC: all profiles match thesis Python to 10⁻¹² relative (same inputs, molecular viscosity); u_g with ν_t matches an independent closed form for a power-law disk; profile figures regenerated.
M3: Dust kinematics, collision rates, outcomes
- M3.1 Particle properties per bin: a(m, φ), St (Epstein; Stokes regime as toggle), stopping time.
- M3.2 Relative velocities as separate, toggleable terms: Brownian, radial drift, azimuthal drift, turbulence (Ormel and Cuzzi 2007, all three regimes, cross checked with
coag_py/dv_rel.py), differential settling (fixed), combination rule (quadrature; option for a velocity PDF). - M3.3 Cross sections (compact; porous form for M9) and C_ij.
- M3.4 Outcome models: hard threshold, Maxwell-Boltzmann fragmentation probability (Stammler and Birnstiel 2022), bouncing with the Dominik and Dullemond (2024) local recipe implemented verbatim (ambiguities logged for the first contact) and validated against one of their local figures, v_frag scaling options.
- M3.5 Parity with thesis
relative_velocity,collision_rate,collision_outcome_probabilities. - M3.6 DustPy (uv, project-local) as an external oracle at one radius with transport off; matched settings documented; the DustPy-like robustness setup defined.
- M3.7 Δv and collision views live on the website.
AC: each Δv term matches thesis Python to 10⁻¹² (thesis settings); turbulent Δv reproduces Ormel and Cuzzi limiting cases; P^coag + P^bounce + P^frag = 1 to round-off for all pairs; Δv and C_ij maps regenerated (thesis Figs. relative velocity, cross section, rate coefficient).
M4a: Kernel framework and analytic kernels
- M4a.1 Sparse collision recipes (ADR 0005): per pair a list of (k, weight); assembly into RHS, Jacobian, dense K_kij export.
- M4a.2 Kovetz and Olund mapping with near-cancellation handling; upper boundary policies (drop pair, as thesis; pile up; outflow with accounting).
- M4a.3 Analytic test kernels: constant, sum, product.
- M4a.4 Diagnostics: per-pair mass defect, ΔX^rel, sparsity, ΔM^net_ij.
- M4a.5 f64 vs double-double comparison of per-pair mass defects and cancellation handling (E3).
AC: dense export equals coag_py.create_coag_kernel to 10⁻¹⁴ relative on its test grids (symmetric and asymmetric forms); per-pair mass defect < 10 ε_mach (m_i + m_j) for all pairs with cancellation handling; with handling disabled, the 10²⁰-span test from the coag_py docstring shows the breakdown.
M4b: Physical kernels
- M4b.1 Coagulation kernel R^coag X^coag.
- M4b.2 Fragmentation: pulverization; power-law shattering with configurable slope (MRN -11/6, Kun and Herrmann -3.27), upper cut-off m_i + m_j (thesis) or independent shattering up to max(i, j) (notes Eqs. 1.37 to 1.39); cratering with reverse Kovetz and Olund and its cancellation handling; bouncing with mass loss.
- M4b.3 Total kernel = Σ over outcomes; component kernels kept separately for visualization.
- M4b.4 Parity with thesis
Kernelfor coag, frag (MRN), total; thesis kernel figures (101, 102, 34) regenerated. - M4b.5 Kernel and recipe-inspector views live; this triggers the short note to Dullemond (M11a).
AC: kernel parity to 10⁻¹² with thesis settings; ΔX^rel ≤ 10⁻¹² for coag, frag, total (thesis claim reproduced); sparsity 3 % / 30 % at N_m = 100 reproduced.
M5: Explicit integrators and analytic benchmarks
- M5.1
Integratortrait (ADR 0008); explicit Euler and Dormand-Prince 5(4) with step control (Heun and RK4 dropped: no experiment needs them). - M5.2 Explicit stability limit estimator (CFL-like, Laibe and Lombart 2021).
- M5.3 Benchmarks: constant, sum, product kernels against analytic solutions (Ohtsuki 1990;
coag_pyexamples), including coarse-grid artificial acceleration; an aggregation-fragmentation benchmark with known steady state (Sekiyama et al. 2017) if feasible.
AC: observed convergence orders 1 and 5 within ±0.2 on the constant kernel; Euler on the thesis linear-grid example reproduces thesis Fig. 112; analytic solutions matched to the discretization error documented by coag_py tests.
M6: Implicit integrators, own Radau IIA
- M6.1 Backward Euler with Newton (matches
coag_pybackwardeuler,niter), linearized one-step form (Brauer 2008 App. C). - M6.2 One Rosenbrock-W method (tolerates approximate Jacobians; needed for E13).
- M6.3 Radau IIA order 5 after Hairer and Wanner: transformed stage system, simplified Newton, step-size control and error estimate, Jacobian reuse, dense output; analytic Jacobian from recipes.
- M6.4 Scaled variables and per-component tolerances (ADR 0003); positivity reporting instead of silent clipping (F7).
- M6.5 Parity with scipy Radau (via the Python bridge, ADR 0013) on the full thesis kernel.
- M6.6 Stiffness study: eigenvalue spectrum of J along the trajectory; step sizes chosen by each method.
- M6.7 Integration view live (trajectories, mass error, step sizes).
AC: Radau matches scipy Radau to 10⁻⁸ relative at rtol = 10⁻¹⁰; convergence order 5 on a smooth test; steady state of the thesis full model reached with mass error ≤ 10⁻¹² and no negativity events at default tolerances.
R: Thesis reproduction baseline
- R.1 Re-run thesis chapter 3 integrations (pure coag lin/log, pure frag, full model) and chapter 4 sampling runs with the thesis estimator (without replacement, scalar weights, as found in F1/F2) and with the documented proposal.
- R.2 Write
results/baseline/with all figures and a short report: what matches, what differs and why.
AC: thesis Figs. 103, 104, 106, 107, 109 reproduced qualitatively (same features); quantitative deviations explained.
M7: Unbiased sampling and implicit sampled form
- M7.1
Estimatortrait (ADR 0007): full sum; thesis estimator (baseline); IS with replacement; HT without replacement (e.g. Poisson or conditional Poisson sampling); 1D (index) sampling for hit-and-stick. - M7.2 Proposals: uniform, ρ_i ρ_j, F_i F_j factorized (Dullemond, W_i = 1, m_i, m_i²), ΔM^net N_i N_j, ‖K_·ij‖ N_i N_j; alias-method sampler.
- M7.3 Detailed balance per sample: each draw adds its full recipe (ADR 0006).
- M7.4 Implicit sampled kernel (Eq. 1.71) as a sparse quadratic kernel, usable by all implicit integrators.
- M7.5 Statistical test harness: replicas, bias with confidence intervals, variance, CRN.
- M7.6 Experiments E5, E6, E7, E8.
AC: for all unbiased estimators, |bias| < 3 standard errors over 10³ replicas on fixed N; mass conservation per step at round-off for every sampled step; E6 answers RQ1 with a figure.
Checkpoint M11b: after M7, the full pitch to Dullemond: bias finding, corrected estimator, first plots, paper proposal (German draft per email-writing, Vincent approves and sends). Sampling views go live on the website at the same time.
M8: Variance reduction, noise, Jacobians, cost
- M8.1 Hybrid split estimator (exact top-q pairs + sampled remainder), stratified sampling by k-blocks or by outcome type, control variates (previous-step sum, coarse-grid sum), common random numbers across replicas and stages.
- M8.2 Sample handling in integrators: frozen per step, averaged batches, resampling per step with step-size control decoupled from noise.
- M8.3 Noise floor and stability at steady state (E11, E12); balance-preserving sampling for the growth-fragmentation equilibrium.
- M8.4 Jacobian strategies: dense exact, sparse from sampled recipes, approximate (dominant pairs), JFNK with GMRES; preconditioners (E13).
- M8.5 Cost model: counted recipe evaluations, flops, wall-clock; work-precision diagrams (E14).
- M8.6 Performance pass: Rayon parallelism over pairs, SIMD-friendly layouts, benchmarks (criterion).
AC: η (work-normalized efficiency) reported for every estimator and integrator combination at N_m ∈ {50, 100, 200, 400}; the best combination beats full summation in η at some N_m, or a documented negative result with reasons.
Go/no-go gate for M9 (criteria fixed 2026-11-10, before any results): go if the best p = 1 scheme reaches η ≥ 2 × full summation at N_m = 200 at the 1 % target, or if the measured cost model projects ≥ 5 × for p = 2 at N_m × N_φ = 100 × 20. Otherwise publish p = 1 as a methods paper (bias analysis, optimal proposal, Jacobian study) and move p = 2 to follow-up work. The decision and its numbers are written into this file. Compute for the p = 2 sweeps is estimated here; paid server time needs Vincent’s OK.
M9: Second particle property (filling factor)
- M9.1 Filling factor grid, φ-dependent radius, St, cross section.
- M9.2 Minimal porosity physics behind a swappable
PorosityModeltrait, so richer physics (static compression after Kataoka et al. 2013, Ormel et al. 2007 regimes) can be added later: the Okuzumi et al. (2012) hit-and-stick volume rule, one published collisional compaction rule, compact fragments; φ enters radius, St, and cross section. - M9.3 2D recipes (bilinear Kovetz and Olund in (m, V) or (m, φ)) with conservation of mass and the chosen second moment.
- M9.4 Full 2D sum as reference at modest resolution; sampled schemes at production resolution (E15).
- M9.5 Compare with φ(m, t) as dependent variable (Schöll et al. 2026) where the comparison is meaningful.
AC: 2D full and sampled results agree within noise at N_m × N_φ = 50 × 20; break-even surface over (N_m, N_φ, accuracy) computed; H5 decided.
M10: Interactive web visualization
See 07-visualization.md. Public at https://coag.mader.xyz from M2 on. Design before code (global rule).
- M10a Requirements, information architecture, and a design in Claude Design (or similar), in parallel with M1 and M2; Vincent approves.
- M10b Views ship with their milestones (disk M2, Δv and collisions M3, kernels M4b, integration M6, sampling M7), each with a screenshot review per
ui-design. - M10c Comparison views and run browser for experiment outputs (M8).
- M10d Shared Impressum and privacy pages for the mader.xyz family (
static-website), linked from the app before the first public view.
AC: every config toggle from M2 to M8 reachable in the UI; live recomputation for N_m ≤ 100 under 1 s for kernels; screenshot review passed.
M11: Paper and outreach
- M11a Short note to Dullemond once the kernel views are live (after M4b): the thesis work continues, here is the URL, a paper is planned. German draft, Vincent approves and sends.
- M11b Full pitch after M7 (see the M7 checkpoint).
- M11c Paper draft (LaTeX or Typst per journal), figures from experiment outputs only, reproducibility package (tagged release, configs, scripts, data DOI e.g. Zenodo).
- M11d Internal review loop with co-authors; submission.
AC: every figure regenerates from a tagged commit with one command; co-authors sign off.
3. Task tracking
Until the repo has an issue tracker, track tasks in this file: mark finished tasks with “Done (commit abc1234)”. When GitHub is set up (Q1), convert each milestone into a GitHub milestone and each task into an issue with the same ID.