Carbon Offsets & Removals ========================= **Implementation status:** Fixed (DL-012: capacity-constrained net is the default; DL-027: applied to residual emissions). Sectoral CORSIA subset **Equivalent on a simplified base** (coverage matrix rows *Offsets & Removals*, *CORSIA*) **Source:** ``src/engine/removals.ts:offsetBlend``, ``src/engine/cascade.ts:computeLCA`` (offsets wedge + CORSIA block) **Test evidence:** ``tests/removal-capacity.spec.ts``, ``tests/corsia-parity.spec.ts`` Two offset modes ---------------- ``offset_mode`` (DL-012) selects how the offsets wedge enters net emissions: * ``'constrained'`` (default): the wedge is the **capacity-capped physical removal output** plus traditional offsets, in MtCO₂, converted ÷1000 to GtCO₂. Net emissions can never be reduced by more removal than the deployed capacity allows. * ``'percent'``: the legacy unconstrained behaviour — a flat percentage of gross — retained only to reproduce the frozen parity baseline. Since DL-027 the constrained base is **residual** emissions (after the aircraft, operations and energy wedges), matching the CASCADE accounting order (cf. CASCADE *Carbon Offsets & Removals*, emissions-reductions equations): .. math:: G_{res} = G_{gross} - \Delta_{ac} - \Delta_{ops} - \Delta_{en}, \qquad G_{net} = \max\!\big(0,\; G_{res} - (R_{rem} + R_{trad})/1000\big) Removal pathways ---------------- Total offset demand at year :math:`y` ramps with an S-curve adoption :math:`s(t)`, :math:`t = (y-2019)/31`: .. math:: D_{total}(y) = G_{base}(y) \times 1000 \times \frac{X_{off}}{100} \times s(t) \qquad [\mathrm{MtCO_2}] allocated across traditional offsets and four removal pathways (nature, biomass/BECCS, mineralisation, DACCS) by normalised scenario shares. Each pathway :math:`k` has its own adoption curve, a Wright's-law-style cost trajectory and a capacity ramp: .. math:: C_k(y) = C_{k,2050} + (C_{k,2025} - C_{k,2050}) \left(\frac{2050 - y}{25}\right)^{lr} .. math:: Cap_k(y) = Cap_{k,2050}\left(\frac{y - 2019}{31}\right)^{1.8} .. math:: R_k(y) = \min\!\big(D_k(y),\; Cap_k(y)\big) Defaults (editable; cost sources: Fuss et al. 2018, Keith et al. 2018, IEA NZE; capacity potentials: IPCC AR6 WGIII Ch. 12 :cite:`ipcc_ar6`): .. list-table:: :header-rows: 1 * - Pathway - Cost 2025 ($/t) - Cost 2050 ($/t) - Capacity 2050 (Mt/yr) - Energy (GJ/t) * - Nature-based - 15 - 10 - 3,500 - 0.5 * - Biomass (BECCS) - 150 - 80 - 2,000 - 3.5 * - Mineralisation - 80 - 40 - 1,000 - 6.0 * - DACCS - 400 - 100 - 5,000 - 8.0 Total cost :math:`\sum_k R_k \times C_k` is reported in $B/yr with the weighted-average $/t; the Gt/Mt/$ unit chain is pinned by tests. The σ-cap note -------------- CASCADE's σ(t) renormalisation caps total offset demand so net stays non-negative. Under HyFlux's parameterisation this normalisation is **vacuous**: the total offset share :math:`X_{off} + \sum_k X_k \le 100\%` by construction and the base is residual emissions, so net is provably ≥ 0 without the clamp ever engaging — tested across scenarios (DL-027). CORSIA subset ------------- The sectoral accounting subset is implemented (cf. CASCADE *CORSIA*, sector-emissions-baseline / sectoral-growth-factor equations): .. math:: SEB = 0.85 \times G_{2019} = 0.85 \times 0.92\ \mathrm{Gt} .. math:: SGF(y) = \max\!\left(0,\; \frac{G(y) - SEB}{G(y)}\right), \qquad \Delta_{CORSIA}(y) = G(y) \times SGF(y) This subset is **Equivalent on a simplified base**: eligibility uses total gross with no route-scope filter (cf. CASCADE's own documented route-homogeneous simplification). Documented CORSIA gaps (updated 2026-08-02) ------------------------------------------- * Operator-level accounting (OEB, OGF, the w(t) phase weighting schedule 1.0 to 2032 / 0.85 from 2033–35, operator emission reductions, and the CGI operator analogues) is **implemented standalone** in ``src/engine/routes/corsia-operator.ts`` (DL-045/046, ``tests/corsia-operator.spec.ts``), with the sectoral-vs-operator-sum aggregation identities and the printed-vs-floored SGF divergence made measurable in ``src/engine/corsia-aggregation.ts`` (DL-137, ``tests/suite-n-corsia-tensor.spec.ts``). It is **not wired into** ``computeLCA``: the operator set is synthetic (one per origin state, allocating emissions, not flights), so the block stays at shadow stage under the DL-138 integration registry. * Automatic offset wiring for 2024–2035 and the CGI extension to 2100 are **implemented** (DL-044: ``cgi_enabled`` / ``cgi_gamma_end``, constrained offset mode only; ``tests/horizon-2100.spec.ts``) — see :doc:`trafficGrowth`. * Still open: the σ(t) / σ_removals(t) renormalisation pair (argued vacuous under HyFlux's parameterisation, but not implemented — an over-100 % offsets+removals combination is not renormalised the way CASCADE renormalises it), and a consumption model for the removals resource parameters (C_biomass, ε_biomass, ε_mineral, ε_daccs). Known deviations / limitations ------------------------------ * Legacy ``'percent'`` mode applies the wedge to gross (frozen); the historical gross-vs-residual deviation is closed in the default constrained mode (DL-027). * Removal energy demand (``energyGJ`` per pathway) is computed but not consumed by the energy-demand roll-up — pinned open item. * Traditional offsets (VER/CER) carry no cost or capacity model.