All method pages

MethodFeatures

partial some parts checked against the code, others not yet · what the statuses mean

How feasibility works — the hourly model

The dispatch engine (a linear program), how a re-solve runs, why it costs more than screening, and what each sub-room shows.

In a project, this page is the feasibility stage’s How it works tab: the tab shows the same text, after the list of the tools in the stage. The choices under How it runs in the design panel are explained in How it runs — the feasibility run settings; the charts of the Operations tab in How to read the Operations tab; the screening stage in How prefeasibility works; what no stage models in What the model leaves out.

The sizing method — how to reach a plant you can defend

the step-by-step

There is no single “right” plant — there is the one you can defend operating and the one that is theoretically possible. This stage helps you find the first and measure it against the second. You size step by step, read one plain takeaway at each step, and always know which number is honest and which is optimistic.

  • Goal & commitment → what each product must deliver a year (its promise, below), or what your site can make.
  • Power supply → “your supply delivers X GWh/yr”.
  • Conversion (electrolyser) → “it captures Y%; the rest is spilled”.
  • Storage & strategy → “you cover the gaps except N episodes/yr”.
  • Product → “you make P t/yr”.
  • Check it (Operations · Reliability · Results) → “P t/yr at C $/t, N episodes short”.
  • Compare to the ideal → “perfect control would make more for less — the gap is what better operation is worth”.

Steps 2–5 are coupled — storage size depends on the supply-to-electrolyser ratio and on product flexibility, and the battery (short swings) trades against the H₂ buffer (longer gaps). So sizing loops: size → simulate → read the signals → adjust → repeat, until the plant is balanced (energy balance closes; both stores actually cycle; curtailment vs shortfall is a trade you accepted; no stage sits idle). The Base case (rule-based) runs this loop from the outside; the Ideal (LP) converges it internally, which is why it lands leaner.

The full walk-through — the loop, the stopping rule, commitments, and how to read shortfall as episodes — is in Sizing a project — the method.

The promise — what each product owes

one number, three places

The promise is how much of each product the plant owes in a year, in t/yr — the offtake. It is not part of the design: the design panel shows what you build, and no solve reads the promise — an ordinary solve makes what the plant can make. It is kept once per product and used in three places, each of which says under its field what it does with the number:

  • Reliability — “Judge against a promise of … t/yr”. Where the promise is saved. The tab compares what each product delivered in the result on screen with its promise, and splits a shortfall into hours without enough hydrogen and hours without enough power. Saving a promise needs no new solve. Empty: no promise — the tab reports each product’s production and utilization (output ÷ unit size) only.
  • Design lab › Find a design — “Deliver how much per year?” The search looks for the cheapest plant that delivers this. It starts from the saved promise; a number typed there is for that run only and is not saved. Empty: the search asks for a number — it never aims at the unit size, which would ask for full output in every hour of the year.
  • Design lab › Least cost (LP) — “Deliver how much per year?”, one row per product. The solver sizes each product to make at least this, at the least cost. It starts from the saved promises; a change is for that run only. Empty: the unit size — the unit at full load in every hour, which renewables cannot supply cheaply.

Try every combination does not use a promise unless you tick its “Delivers at least” check, which offers the saved promise as a starting number.

Delivered or not is decided by the rule Find a design uses to keep a design: under an annual tonnage the year’s output reaches the promise; under a firm promise it must also never have held a unit at its minimum on hydrogen the plant did not have — the engine does that to a starved firm unit, so its tonnes alone overstate what it delivered (the solver always reports firm). The judgement is in the Results workbook and the Summary report too (Reliability, “Delivered against promised”).

How to read this stage

the bankable hourly answer

Feasibility replays the plant hour by hour for a whole year under the real operating limits — either with coded rules or with an optimising solver (the two modes below). Where prefeasibility screens, feasibility proves: it respects min-loads, ramps and storage dynamics and tells you when the plant physically can’t hold its floor.

  • A run with no look-ahead — the rule-based engine here, or prefeasibility’s hour-by-hour mode — and the LP with perfect foresight bracket how the plant really runs; the rule-based base case is the number you defend.
  • Prefeasibility annual averages assume a curtailment floor and know no hourly limits — a quick screen, not one side of the bracket.

The LP usually comes out higher, because foresight lets it keep energy and hydrogen for the hours that need them; the annual figure can land above or below both, because it rests on the curtailment floor you assume rather than on the hours. The Operations room’s vs-Prefeasibility card shows the engines side by side so you can judge it directly.

Two dispatch modes — same year, two ways to run it

Rule-based vs Solver (LP)

Feasibility offers two dispatch managers, chosen under How it runs in the design panel. Both run on the same hourly timeseries and honour the same operating + storage limits (min-load, ramps, electrolyser standby, BESS C-rate, H₂ buffer). The only difference is how the hourly schedule is decided.

  • Rule-based — a single pass: coded rules decide each hour in order, with no look-ahead. Fast (a fraction of a second) and always available. It’s how a plant runs in real time, without knowing the future.
  • Solver (LP) — HiGHS optimises the whole storage-linked year at once with perfect foresight of the weather (~10–15 s). The best a perfect operator could do.

Together they bracket how a plant actually runs: rule-based (real limits, no foresight) and LP-optimal (real limits, perfect foresight). Prefeasibility’s hour-by-hour run has no foresight either but no operating limits, so its tonnes can land on either side of the rule-based engine’s.

Reading the two honestly

  • Raw production is not cleanly ordered: the rule-based pass is optimistic on tonnes because always-on units keep running at their minimum rate on backup power when the plant can’t supply them — and those backup hours are exactly the hours below minimum run.
  • The honest comparison is on reliability: the LP’s foresight achieves the fewest possible hours below minimum run, so the LP’s shortfall is always ≤ the rule-based shortfall.

The battery strategy and the H₂ buffer policy — what each of the four battery strategies and the two buffer policies does, and when to choose it — are explained once, in How it runs — the feasibility run settings: the same text the design panel’s ⓘ shows.

The rule-based instruction sheet (per hour)

  • Standby first — the electrolyser’s kept-warm parasitic load is served (renewables → battery → grid → shortfall) before anything productive.
  • Then the synthesis units’ electricity — their whole operating band is reserved before the electrolyser draws, so making more hydrogen can never leave the ammonia or methanol loop unpowered. An unpowered loop can’t turn hydrogen into product, so keeping it running comes first; it is cheap, because the loop needs a few megawatts against the electrolyser’s hundreds. This is a reservation, not a draw — whatever the units don’t use goes on to the battery or curtailment.
  • Classify the balance — excess (RE above what the electrolyser can absorb): run it to max, surplus → charge BESS → curtail; normal: the electrolyser follows RE within its min-load + ramp band; shortfall: discharge BESS to hold synthesis (and, under Push output, to push the electrolyser), then draw the H₂ buffer to keep synthesis ≥ min-load.
  • What a power shortfall now means — with the units’ electricity reserved first, a remaining shortfall means the renewables genuinely fell below the plant’s must-run need that hour, not that the electrolyser outbid the loop. More battery, grid or renewables move it; more H₂ storage will not.
  • Anything it still can’t supply at the minimum rate is a shortfall — the same verdict the LP reports (via its penalty terms).

Because a rule-based pass has no shadow prices, the Storage tab’s “storage value” card is computed by finite difference instead — re-running the fast sim at +Δ buffer and +Δ BESS and measuring the gain in H₂ delivered to synthesis (net of slack). It reports the same “tH₂/yr per +1 t / +1 MWh” as the LP’s duals.

Part-load electrolyser & modules

Both modes · efficiency curve

A real electrolyser is more efficient at part load than at full power — the same megawatt makes a little more hydrogen when the stack runs gently. Both modes model this with a part-load efficiency curve (six anchor points from the book, seeded per electrolyser technology) instead of a single fixed rate. Leaving the book at its linear default reproduces the old constant-rate behaviour exactly.

The electrolyser can also be split into modules (a sizing input). Two policies trade hydrogen against wear:

  • Spread (default) — run more modules at efficient part-load: the most hydrogen, and the exact behaviour the solver’s optimum also finds. More module running-hours (a faster maintenance clock).
  • Pack — run the fewest modules hard: less wear and fewer module-hours, but systematically less hydrogen than the solver on a curved efficiency profile — a deliberate rule-vs-solver gap you opt into.

How the solver matches it

The curve is concave (efficiency falls as load rises), so the solver represents the electrolyser as a few parallel segments — each a slice of power at its own rate, steepest first. Because the solver maximises hydrogen, it fills the most efficient segment first, reproducing the spread policy’s envelope with no integer variables (still a pure LP). A linear book collapses to a single segment — identical to before. If a user enters a non-concave curve, the solver sees its concave hull (the rule engine still follows the exact curve).

Plant lifetime — multi-annual

Both modes · horizon

A single-year solve is a fresh plant in a typical year. Over decades the generation equipment degrades — panels and turbines produce less from the same sun and wind — and the electrolyser ages (efficiency falls with operating hours, resetting at each stack maintenance). Equipment degradation is a book assumption (a %/yr rate) applied to every site; a multi-year dataset that already carries its own measured decline is left as-is (no double-count). Prefeasibility always screens on year 1; only feasibility ages the plant. The Horizon setting chooses how much of that life to model:

  • Single year — one representative year (the standard solve).
  • Checkpoints — re-solve an aged year at a ladder (1·5·10·15·20…). A few solves sketch the lifetime trend; each is independent (no state carried between them). Works for both engines.
  • Every year — run all years in sequence, carrying storage and the electrolyser’s age across each boundary. The full picture. The rule engine does this in seconds; the solver takes a full LP per year (several minutes).

Aging, replacements & the year-end handling

The electrolyser’s efficiency multiplier is 1 − degradation × (hours ÷ 1000), resetting to 1.0 at each maintenance interval — so hydrogen per megawatt falls as the stack ages. A discounted stack replacement cost is charged in each maintenance year.

The lifetime levelized cost discounts each year’s cost and production:

LCO = ( Σ costᵧ·dᵞ + Σ replacementsᵧ·dᵞ ) / ( Σ productionᵧ·dᵞ )

with d = (1 + WACC)⁻¹. It reduces exactly to the single-year CRF cost when every year is identical. In Every year mode the solver appends a 3-week look-ahead from the following year so it doesn’t drain storage on 31 Dec for free — state is carried at the true year boundary and the look-ahead hours are discarded from the results. The honest bracket still holds each year: greedy < rule-based < solver on shortfall hours.

The engine — a linear program

Solver mode · PyPSA + HiGHS

The whole year is written as one linear program (LP): pick the hourly dispatch of every component that minimizes cost while meeting demand and every operating limit. It’s built with PyPSA and solved by the open-source HiGHS solver.

In plain terms

  • Decisions — for each of the 8,760 hours: how much wind/solar to use vs curtail, grid import, BESS charge/discharge, electrolyser load, H₂ into/out of the buffer, and each synthesis unit’s throughput.
  • Rules — supply must equal demand every hour; storage carries over correctly; units stay within their operating limits (below); the grid stays under its cap.
  • Goal — keep every synthesis unit at or above its minimum run rate at least cost, and if it physically can’t, say so (as a shortfall) rather than pretend.

The maths behind it

Over hours t = 1…8760 and components, minimize a lexicographic-weighted cost so priorities never trade against each other:

min Σₜ [ w₁·shortfallₜ + w₂·(−productₜ) + w₃·grid_priceₜ + ε·|Δp|ₜ ]

with w₁ ≫ w₂ ≫ w₃ ≫ ε — avoiding a shortfall beats making product, which beats cheap grid, which beats a tiny smoothing term. Subject to, each hour:

  • Energy balance per bus (electricity, H₂): inflows = outflows.
  • Storage dynamics: SoCₜ = SoCₜ₋₁ + η·chargeₜ − dischargeₜ, within [0, capacity].
  • Min-load & ramps: a running synthesis unit stays ≥ its minimum load and can’t jump faster than its ramp; the electrolyser has a standby draw + a cost on |Δp|.
  • Grid share cap, capacity limits, and penalty terms on the H₂ + electricity buses (their non-zero value is the hours below minimum run).

HiGHS solves this with an interior-point method + crossover (a vertex-exact optimum), extracting the hourly schedule and the dual prices (below) in one pass.

How a re-solve works

edit → solve → persist → derive

  1. You change a sizing input (or an assumption) and hit re-solve.
  2. The network is rebuilt from the config on the site’s hourly weather frame.
  3. HiGHS solves the year (async — a few seconds; you poll for it).
  4. The hourly frame + duals + solver metadata are persisted (Parquet + sidecar), stamped with the sizing that produced them.
  5. Everything else — duration curve, heatmap, reliability, monthly, curtailment-by-cause — is derived on read from that frame, no re-solve needed.

That’s the SOLVE / POST-PROCESS split: the expensive optimisation runs once; the views are cheap re-derivations of its output.

Freshness. A solve is expensive, so we keep the last one and don’t re-run it silently. If you change the design elsewhere afterwards — right-size in the cockpit, edit sizing, switch a version — the stored solve no longer matches. Because it carries its sizing stamp, the Operations and Reliability rooms compare it to the current design and show a “sizing changed — re-solve” banner rather than presenting stale numbers as current. Saving a promise does not make a result stale: no solve reads it, and the Reliability tab judges the stored result against the promise as it stands.

Why it’s slower than screening

≈ seconds vs milliseconds

Prefeasibility timeseries (greedy) is a single forward pass with fixed priority rules — no solver, no foresight (milliseconds). Feasibility optimises the whole storage-coupled year at once — thousands of coupled variables and constraints solved to a global optimum (seconds).

Is it the assumptions? Partly: feasibility adds the operating-constraint parameters (min-load, ramps, standby, cycling) that greedy ignores, and each adds variables/constraints that grow the LP. But the root cause is the algorithm class — optimising a schedule vs applying rules. The detail amplifies; the optimisation is the cost.

Operating constraints

the defining content of feasibility

These are exactly what prefeasibility leaves out — modelling them is why feasibility exists. All stay linear (no on/off integers in v1):

  • Min-load / turndown — a running synthesis unit can’t go below a floor (% of nameplate).
  • Ramps — throughput changes are rate-limited hour to hour.
  • Standby — the electrolyser draws a small load even when idle.
  • Cycling cost — a small penalty on swinging load, purely to steer the schedule away from needless churn. It is not added to the LCO: equipment wear is costed explicitly by the plant-lifetime model (fade + replacement), so a separate cycling charge would double-count.

When the plant can’t hold its minimum run rate (a lull the stores can’t cover), the LP reports it as hours below minimum run — a verdict, not a crash.

The sub-rooms

what each one shows

  • Operations — the year’s hourly schedule (supply stack, electrolyser draw, curtailment), week zoom, duration/operating profile, monthly production, balance ledger, and the vs-prefeasibility bracket. The design panel’s Storage section is the room’s inner loop.
  • Storage — how the stores fill and drain over the year (state-of-charge bands), the LP’s storage value (duals), and the storage sweep (below; it runs in the Design lab’s One component view): the same design re-solved at several storage sizes to find the cost-effective size.
  • Reliability — each product delivered against its promise (above), then hours below minimum run treated as events (contiguous episodes: when, how long, how deep, and what the stores held), plus seasonal clustering and ride-through margins.
  • What this run consumed (the second view of this tab) — read-only provenance: the resource frames, plant/storage sizes, the active operating-constraint values with their source, and the solver identity.

The storage sweep

size the stores against the LP

Duals tell you whether one more unit of storage helps right now; the sweep answers the bigger question — how much storage to buy. It re-solves the same design (same book, same weather) at a ladder of storage sizes and plots how the hours below minimum run and production respond. The project is never touched — every point is a solve on a copy.

  • H₂ buffer or BESS energy alone — a 1-D curve, holding the other store at its current size (up to 40 points).
  • Both (H₂ × BESS) — a 2-D grid, drawn as a heatmap so you can see the two stores interact (one can substitute for the other).
  • You set the ladder. Each axis takes its own start · step · points — pick the range and resolution that matter. In the 2-D grid each axis is capped at 8 points (≤ 64 solves); a time estimate (points × the last solve time) shows before you run, since each LP solve is ~10–15 s.
  • The “best” pick. Every point carries both sizes and the storage CAPEX (from the book’s per-kg / per-kWh costs — the common yardstick across two otherwise-incomparable axes). The recommended pick is the cheapest storage that lands within tolerance of the fewest hours below minimum run the sweep achieved — i.e. don’t pay for capacity past the point where it stops helping.

Reading the curve — where it flattens, and why output can dip

Find where the curve flattens. Hours below minimum run fall steeply as you add the first storage, then level off — past that point more storage buys almost nothing, because the remaining shortfall is a duration limit (a long winter lull no reasonable buffer covers), not a size limit. Buy up to that point, not beyond.

Why reported output can dip. Production can actually fall as you add storage: with too little buffer the plant runs on backup to stay at its minimum rate, which overstates output. As real storage replaces that backup, production settles to the honest number. A dip is the model getting more truthful, not worse.

Convention. BESS-energy points assume a 4-hour duration (power = energy ÷ 4), the same C/4 convention as the cockpit — so one number sizes both power and energy.

Duals — the value of one more unit

shadow prices, free from the LP

Solving the LP also yields dual prices — the marginal value of relaxing a constraint. We surface the ones that matter as physical units: +1 t of H₂ buffer or +1 MWh of BESS → how much more product per year it would buy. A zero dual means that capacity never binds (adding more wouldn’t help); its absence means there’s none installed to value. It’s the cheapest, most honest “should I add storage?” signal — computed for free alongside the schedule.

In Rule-based mode there are no shadow prices, so the same card is computed by finite difference — re-running the fast sim at ±Δ storage and measuring the gain in delivered H₂. Same units, same question, computed numerically.

Limits & honesty

optimistic bound

The LP assumes perfect foresight — it knows the whole year in advance, so it’s an optimistic bound on how well the plant can actually be run. Real operations, with imperfect forecasts, land between the greedy pass and this LP. Costs still rest on the assumption book until quotes and contracts replace them at the later gates.

From the app’s documentation, docs/02-features/how-feasibility-works.md · Hyprisma 1.0.5