Skip to main content

JAX-native fusion power plant costing framework

Project description

1costingfe

JAX-native fusion power plant costing framework. Replaces the PyFECONS adapter in the fusion-tea SysML pipeline with a differentiable, 5-layer customer-first model.

Install

pip install -e .
# or with dev dependencies:
pip install -e ".[dev]"

Requires Python 3.10+.

Quick Start

from costingfe import CostModel, ConfinementConcept, Fuel

# Create a model for a DT tokamak
model = CostModel(concept=ConfinementConcept.TOKAMAK, fuel=Fuel.DT)

# Forward costing: customer requirements -> LCOE
result = model.forward(
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
)

print(f"LCOE: {result.costs.lcoe:.1f} $/MWh")
print(f"Overnight cost: {result.costs.overnight_cost:.0f} $/kW")
print(f"Fusion power: {result.power_table.p_fus:.0f} MW")

Sensitivity Analysis (JAX autodiff)

sens = model.sensitivity(result.params)

# Engineering levers (sorted by |elasticity|)
for k, v in sorted(sens["engineering"].items(), key=lambda x: abs(x[1]), reverse=True):
    print(f"  {k:25s} {v:+.4f}")

# Financial parameters
for k, v in sens["financial"].items():
    print(f"  {k:25s} {v:+.4f}")

Elasticity = (dLCOE/dp) * (p/LCOE) -- dimensionless, comparable across parameters.

Batch Parameter Sweeps (JAX vmap)

# Sweep blanket thickness from 0.5m to 1.0m
lcoes = model.batch_lcoe(
    {"blanket_t": [0.5, 0.6, 0.7, 0.8, 0.9, 1.0]},
    result.params,
)

Cross-Concept Comparison

from costingfe import compare_all

results = compare_all(net_electric_mw=1000.0, availability=0.85, lifetime_yr=30)
for r in results[:5]:
    print(f"  {r.concept.value:15s} {r.fuel.value:5s} {r.lcoe:6.1f} $/MWh")

Backcasting

from costingfe.analysis.backcast import backcast_single

# What availability achieves 60 $/MWh?
avail = backcast_single(
    model, target_lcoe=60.0, param_name="availability",
    param_range=(0.70, 0.98), base_params=result.params,
)

Cost Overrides

Override any CAS account or CAS22 sub-account with a known value (M$). Downstream totals (CAS20, total capital, LCOE) recompute automatically.

# Override an entire CAS account
result = model.forward(
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
    cost_overrides={"CAS21": 50.0},  # "I know my building cost"
)
assert result.costs.cas21 == 50.0
print(result.overridden)  # ["CAS21"]

# Override a CAS22 sub-account (coils)
result = model.forward(
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
    cost_overrides={"C220103": 300.0},  # "Use this coil cost"
)
# CAS22 total is recomputed from patched sub-accounts
print(result.cas22_detail["C220103"])  # 300.0
print(result.cas22_detail["C220000"])  # Recomputed total

Available CAS-level keys: CAS10, CAS21-CAS28.

Available CAS22 sub-account keys: C220101 (blanket), C220102 (shield), C220103 (coils), C220104 (heating), C220105 (structure), C220106 (vacuum), C220107 (power supplies), C220108 (divertor), C220109 (DEC), C220111 (installation), C220112 (isotope sep), C220200 (coolant), C220300 (aux cooling), C220400 (rad waste), C220500 (fuel handling), C220600 (other equipment), C220700 (I&C).

Sub-line convention: an account that bundles components with distinct cost bases also emits informational <CODE>_<component> keys alongside the canonical total — currently C220106_vessel and C220106_pump (vessel shell vs gas-load pumping). These sub-lines are excluded from all aggregation and are for visibility/sensitivity only; the canonical C220106 carries the sum.

CAS70 sub-accounts: CAS71 (annual O&M), CAS72 (annualized scheduled replacement — blanket/FW + divertor, PV-discounted at interest rate).

Sensitivity analysis works with overrides -- overridden accounts become constants with zero gradient:

sens = model.sensitivity(result.params, cost_overrides={"CAS21": 50.0})

Fusion-Tea Adapter

from costingfe.adapter import FusionTeaInput, run_costing

inp = FusionTeaInput(
    concept="tokamak",
    fuel="dt",
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
)
out = run_costing(inp)
# out.lcoe, out.costs (CAS-keyed dict), out.power_table, out.sensitivity

The adapter supports two additional override mechanisms for the fusion-tea pipeline:

inp = FusionTeaInput(
    concept="tokamak",
    fuel="dt",
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
    # Inject known CAS account values (M$)
    cost_overrides={"CAS21": 50.0, "C220103": 300.0},
    # Override costing constants (unit costs, fractions, etc.)
    costing_overrides={"blanket_unit_cost_dt": 1.0},
)
out = run_costing(inp)
print(out.overridden)           # ["CAS21", "C220103"]
print(out.costs["C220103"])     # 300.0 (CAS22 sub-accounts included in costs dict)
  • cost_overrides -- replace computed CAS account values with known costs. Passed through to CostModel.forward().
  • costing_overrides -- override fields on CostingConstants (unit costs, scaling coefficients). Applied via cc.replace() before model construction.
  • out.overridden -- list of keys that were injected rather than computed.

Supported Concepts

Family Concept Key features
MFE tokamak Toroidal confinement, TF/CS/PF coils
MFE stellarator Steady-state, complex 3D coils
MFE mirror Cylindrical, end-loss DEC opportunity
IFE laser_ife Split laser drivers, target factory
IFE zpinch Pulsed power driver
IFE heavy_ion Heavy ion accelerator
MIF mag_target Magnetized target, liner factory
MIF plasma_jet Plasma jet driver

Fuels

  • dt -- Deuterium-Tritium (breeding blanket, heavy shielding)
  • dd -- Deuterium-Deuterium (no breeding, moderate shielding)
  • dhe3 -- Deuterium-Helium-3 (mostly aneutronic)
  • pb11 -- Proton-Boron-11 (fully aneutronic, minimal shielding)

Engineering Overrides

Pass any engineering parameter as a keyword argument:

result = model.forward(
    net_electric_mw=1000.0,
    availability=0.85,
    lifetime_yr=30,
    eta_th=0.50,        # Override thermal efficiency
    blanket_t=0.90,     # Thicker blanket
    axis_t=7.0,         # Larger major radius
)

See src/costingfe/data/defaults/ YAML files for all available parameters.

Power Cycle Selection

Select the thermal cycle used for power conversion. This sets eta_th and BOP cost coefficients (CAS23, CAS26) appropriate for the chosen cycle.

from costingfe import CostModel, ConfinementConcept, Fuel, PowerCycle

# sCO2 Brayton cycle
model = CostModel(
    concept=ConfinementConcept.TOKAMAK,
    fuel=Fuel.DT,
    power_cycle=PowerCycle.BRAYTON_SCO2,
)
result = model.forward(net_electric_mw=1000.0, availability=0.85, lifetime_yr=30)

Available cycles:

Cycle eta_th Description
RANKINE (default) 0.40 Steam Rankine (sub/supercritical)
BRAYTON_SCO2 0.47 Supercritical CO2 recompression Brayton
COMBINED 0.53 Gas topping + steam bottoming

You can override eta_th or BOP coefficients independently:

# sCO2 Brayton but with custom efficiency
result = model.forward(
    net_electric_mw=1000.0, availability=0.85, lifetime_yr=30,
    eta_th=0.50,  # Override preset's 0.47
)

Tests

pytest tests/ -v

Architecture

Customer Requirements (net_electric_mw, availability, lifetime_yr)
    |
    v
Layer 2: Physics (power balance, inverse for target p_net)
    |
    v
Layer 3: Engineering (radial build -> geometry -> volumes)
    |
    v
Layer 4: Costs (CAS 10-60 accounts, volume-based + power-scaled)
    |
    v
Layer 5: Economics (CAS 70-90, LCOE)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

costingfe-0.1.0a1.tar.gz (1.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

costingfe-0.1.0a1-py3-none-any.whl (122.9 kB view details)

Uploaded Python 3

File details

Details for the file costingfe-0.1.0a1.tar.gz.

File metadata

  • Download URL: costingfe-0.1.0a1.tar.gz
  • Upload date:
  • Size: 1.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for costingfe-0.1.0a1.tar.gz
Algorithm Hash digest
SHA256 5e1be24ce1159acc31cf9f1ec41a425d97332a817bbd54ba9a517f0d18cee183
MD5 a14f4b533d9459dfe0a5613de37b5ec5
BLAKE2b-256 2714cc002bda441861fbb551f516f5de0f7e20d3f8a655b48ccf888712e41165

See more details on using hashes here.

File details

Details for the file costingfe-0.1.0a1-py3-none-any.whl.

File metadata

  • Download URL: costingfe-0.1.0a1-py3-none-any.whl
  • Upload date:
  • Size: 122.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.9

File hashes

Hashes for costingfe-0.1.0a1-py3-none-any.whl
Algorithm Hash digest
SHA256 8e8c76a824306d821e0091d063e1ce54ab40c765b294f682a148e79c1c9fc7d3
MD5 4871afa611ca8ee14b4c853e2809f81c
BLAKE2b-256 7225f6adc419f01bf10b67d4790d373364ca3dc6c2265fef3ffe522937d61686

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page