Energy Demand ============= **Implementation status:** Two layers. Production roll-up **Simplified** (aggregate; CASCADE computes per-route — a documented fidelity gap, not a defect; module added 2026-07-18). All **29 governing equations** of CASCADE's *Energy Demand* page are additionally implemented standalone in ``src/engine/energy-demand-full.ts`` (DL-136, Stage-1 shadow under the DL-138 integration registry — the production default is unchanged). **Source:** ``src/engine/energyDemand.ts:energyDemandAt``, ``energyDemandSeries``; ``src/engine/energy-demand-full.ts`` (full page) **Test evidence:** ``tests/energy-demand.spec.ts``; ``tests/suite-j-energy-demand-full.spec.ts`` The roll-up converts the engine's BAU emissions series into per-carrier energy demand in EJ: fossil Jet-A1, SAF (incl. PtL), methane, liquid hydrogen (produced vs delivered), gaseous hydrogen for PtL, and the electricity roll-up. Baseline energy pool -------------------- The time-series ``gross`` is BAU emissions of an all-Jet-A1 fleet at CI = 89 gCO₂e/MJ. Back-conversion (identity stated explicitly in the module header): .. math:: E_{BAU}\,[\mathrm{EJ}] = G_{gross}\,[\mathrm{GtCO_2}] \times \frac{1000}{89} \approx 11.236\ \mathrm{EJ/GtCO_2} (1 Gt = 10¹⁵ g; 1 EJ = 10¹² MJ). The module **imports** ``computeLCA`` and reads the engine's own slice and blend functions, so the roll-up can never drift from the engine. Carrier split ------------- The pool is partitioned exactly: .. math:: X_{SAF} + X_{CH_4} + X_{LH_2} + X_{JetA} = 1 * :math:`X_{SAF}(y)`, :math:`X_{CH_4}(y)` — the engine's own ``safBlend`` / ``methaneBlend`` total shares (never re-derived here). If their sum exceeds 1 both are scaled pro-rata back to 100 %. * :math:`X_{LH_2}(y) = s_{LH_2}(y) \times (1 - X_{SAF} - X_{CH_4})` — the LH₂ fleet adoption (half-S logistic from ``eis`` to ``min(2050, eis + h2\_offset)``, ceiling ``h2_ceiling``, default 80 %) applied to the **post-drop-in residual pool**: SAF and CH₄ blend into the kerosene fleet first, hydrogen aircraft capture a share of what remains. This guarantees the partition even when raw ceilings would exceed 100 %. * :math:`X_{JetA}` — the remainder (≥ 0 by construction). LH₂ produced vs delivered ------------------------- Vapor losses mean more hydrogen must be produced than is delivered to aircraft tanks (cf. CASCADE *Energy Demand*, eq. total-hydrogen-loss; *Hydrogen*, eq. hydrogen_vapor_loss_boiloff_recovery): .. math:: \frac{E_{LH_2,prod}}{E_{LH_2,del}} = \frac{1}{1 - f_{loss}\,(1 - f_{BOR})} with :math:`f_{loss} = vap/100` (default 2 %), :math:`f_{BOR} = bor/100` (default 50 %). The denominator is clamped at :math:`10^{-6}`: at ``vap`` = 100 % and ``bor`` = 0 the physical model diverges (all H₂ vented), and the module returns a large-but-finite ratio instead of ∞ so downstream roll-ups stay finite (documented guard). GH₂ for PtL vs LH₂ fuel ----------------------- Gaseous hydrogen feedstock for PtL SAF is kept strictly separate from the LH₂ aircraft-fuel terms (no conflation — the DL-024 distinction): .. math:: E_{GH_2} = E_{SAF,PtL} \times \varepsilon_{PtL,H_2}, \qquad \varepsilon_{PtL,H_2} = 1.4\ \mathrm{MJ_{H_2}/MJ_{SAF}} (FT stoichiometry, CASCADE-stable range 1.36–1.42). **Simplification:** CASCADE divides by the PtL product-slate fraction :math:`P_{PtL}` for unallocated accounting; HyFlux has no such parameter, so :math:`P_{PtL} = 1` (allocated, jet-fuel-only basis). Recorded. Electricity roll-up ------------------- .. math:: E_{elec,H_2} = (E_{GH_2} + E_{LH_2,prod}) \times \frac{1}{\eta_{elys}}, \qquad E_{elec,PtL} = E_{SAF,PtL} \times 0.61\ \mathrm{MJ_e/MJ_{SAF}} .. math:: E_{elec,total} = E_{elec,direct} + E_{elec,H_2} + E_{elec,PtL}, \qquad E_{elec,direct} \equiv 0 Direct-electric aircraft demand is zero: the ``el_*`` parameters have no consumer in the aggregate engine at this layer, so the term is reserved but identically zero (documented). Years outside the engine's 2019–2050 sweep return an all-zero demand — no slice exists and nothing is extrapolated. Known deviations / limitations ------------------------------ These apply to the **production roll-up** (``energyDemand.ts``). Each of the last four is closed in the standalone full module (``energy-demand-full.ts``, DL-136, shadow — htype decomposition, liquefaction/PtG/removals electricity, methane vapour gross-up, product slate :math:`P_{PtL}` and the α_eFuel allocated-primary-energy formulas, all test-asserted in ``tests/suite-j-energy-demand-full.spec.ts``); the production default remains bit-identical until the DL-138 stage gates pass. * **No route resolution.** CASCADE resolves demand per route from fleet composition and aircraft assignment; HyFlux partitions a global pool by aggregate shares. Totals are consistent with the CASCADE equations; per-route, per-class or range-dependent resolution is not possible. * All hydrogen is treated as electrolysed — ``smr_share`` is ignored in the production roll-up (SMR needs no electricity, so this is a conservative upper bound on electricity demand). * Liquefaction electricity (``liq`` kWh/kg) is **not** added to the production electricity roll-up — the liquefaction term is kept CI-side only. * PtG e-methane H₂/electricity and removals electricity (CASCADE's E_elec,CH4 / E_elec,removals terms) are not in the production roll-up. * Methane vapor losses are not in the production roll-up; methane demand is the delivered pool share only. * **Source defect carried, not reproduced by default:** the page's eq. 15/16 applies the LH₂ loss gross-up twice; ``CURRENT_EVIDENCE`` applies it once and ``CASCADE_PARITY`` reproduces the printed form (``src/engine/basis.ts``; regression-locked in ``tests/suite-d-divergence.spec.ts``). * **Λ(t) (total land use)** is declared as an output variable with no defining equation anywhere in the source file — not implemented, not guessed (``LAMBDA_NOT_DEFINED_NOTE``).