Dr. Eshan Singh

Optimizer Documentation

Technical documentation for the capacity expansion optimization engine.
← Back to Grid Planner  |  Simulation Model Docs →

1. Introduction

The optimizer performs least-cost capacity expansion planning under a CO2 emissions constraint. Given a target annual CO2 level (in million metric tons), it determines the optimal mix of new generation, storage, and carbon removal technologies to add to the existing grid that minimizes total annualized system cost while meeting the emissions target and reliability constraints.

Unlike Manual Mode, where the user adjusts technology sliders by hand and observes the impact, Optimize Mode automates this process. It runs hundreds of dispatch simulations internally, evaluating different capacity combinations to find the most cost-effective portfolio that meets the CO2 target.

Key outputs: Recommended capacity additions (GW or GWh per technology), total system cost ($/year), achieved CO2 emissions, reserve margin, curtailment rate, and a detailed cost breakdown including abatement costs.

Recent Updates (February 2026)

1. Deterministic Multi-Start Optimization: The optimizer now uses a seeded PRNG (Mulberry32) for full reproducibility. By default, 3 runs with different seeds (42, 137, 2024) are executed, and the best result is selected. This addresses non-determinism caused by the multimodal solution space.

2. Supply Curves for Resource-Constrained Technologies: Geothermal (0-2 GW: 1.0×, 2-4 GW: 1.3×, 4-5 GW: 1.6×) and Biomass (0-1.5 GW: 1.0×, 1.5-3 GW: 1.4×) now have stepped cost curves reflecting resource scarcity. Marginal CAPEX guides selection; blended CAPEX calculates total cost.

3. Tightened Resource Bounds: Geothermal max reduced from 20 GW to 5 GW (hydrothermal + EGS resource limit). Biomass max reduced from 20 GW to 3 GW (sustainable feedstock constraint).

4. Updated Solar & Wind CAPEX: Solar reduced from $1,200/kW to $800/kW (2025-2026 utility-scale market prices). Wind reduced from $1,500/kW to $1,200/kW. This significantly improves VRE competitiveness (solar LCOE ~$42/MWh, wind ~$41/MWh).

5. RNG & Hydrogen Dispatch Fix: Moved from inflexible (24/7 must-run) to flexible dispatch. They now respond to net load, operating only when needed, improving system efficiency and correctly counting toward reserve margin.

6. Inter-Day Storage Carryover: Long-duration storage (24-hr) can now carry state-of-charge across days with 1% monthly self-discharge, enabling multi-day energy shifting. Short-term batteries (4-hr, 8-hr) remain day-independent.

7. Storage Dispatch by Type: Each storage type (4-hr, 8-hr, 24-hr) now dispatches independently with type-specific parameters, replacing the previous pooled dispatch model.

8. Nelder-Mead Exploration: Simplex refinement now includes "exploration points" for up to 3 inactive technologies, allowing discovery of cost-effective technologies missed by the greedy search phase.

9. Bug Fixes: Corrected storage variable O&M double-counting, fixed SoC tracking (gross vs net charge), and reordered thermal dispatch (CCGT → Coal → CT).

2. Time Resolution & Demand Model

The model uses a 288-hour representative year, consisting of 12 months × 24 hours. Each month is represented by a single "typical day" of 24 hourly time steps. This compact representation captures seasonal and diurnal variation while keeping computation fast enough for interactive use.

To convert hourly simulation values to annual totals, each hour is weighted by the number of days in its month:

Annual Value = ∑i=0287 Hourly[i] × DaysInMonth[⌊i/24⌋]

where:

MonthJanFebMarAprMayJunJulAugSepOctNovDec
Days312831303130313130313031

Demand is provided as a 288-element array in GW (12 months × 24 hours). For California, the system uses direct CAISO-derived monthly profiles where each of the 12 months has a complete 24-hour demand pattern with realistic diurnal variation. For other regions, four seasonal base 24-hour shapes (spring, summer, fall, winter) are scaled by per-month multipliers to generate 12 monthly profiles, preserving backward compatibility while capturing month-to-month variation.

3. Technology Cost Model

3.1 Cost Data

Each technology has four cost parameters plus a lifetime. Users can edit these values in the "Edit Cost & Performance Assumptions" panel. Default values are:

TechnologyCAPEXFixed O&MVariable O&MLifetimeCapacity Factor
Solar PV$800/kW$15/kW-yr$0/MWh30 yr25%
Onshore Wind$1,200/kW$35/kW-yr$1/MWh30 yr35%
Offshore Wind$5,000/kW$100/kW-yr$0/MWh30 yr50%
Nuclear$7,242/kW$140/kW-yr$10/MWh60 yr90%
Geothermal$3,329/kW*$120/kW-yr$5/MWh30 yr90%
Biomass$3,500/kW*$100/kW-yr$10/MWh25 yr85%
RNG (Biogas)$3,000/kW$95/kW-yr$50/MWh25 yr85%
Hydrogen$3,500/kW$90/kW-yr$410/MWh30 yr20%
Gas CCGT$1,300/kW$20/kW-yr$35–80/MWh30 yr55%
Coal$4,407/kW$40/kW-yr$30/MWh40 yr60%
Battery (4-hr)$350/kWh$15/kW-yr$2/MWh15 yr
Battery (8-hr)$300/kWh$15/kW-yr$2/MWh15 yr
Long-Duration (24-hr)$300/kWh$60/kW-yr$1/MWh25 yr
DAC$1,000/ton-yr$20/ton-yr$400/ton25 yr

Note: Storage CAPEX is in $/kWh of energy capacity. DAC costs are per annual ton of CO2 capture capacity.

* Geothermal and Biomass use supply curves: CAPEX increases with deployment. Base costs shown; see section 3.2 Supply Curves for details.

3.2 Supply Curves for Resource-Constrained Technologies

Some technologies face increasing costs as deployment grows, reflecting resource scarcity and site quality degradation. The model implements supply curves for geothermal and biomass, where CAPEX increases in steps as cumulative capacity grows.

Geothermal Supply Curve
Capacity RangeCost MultiplierEffective CAPEXMarginal LCOE
0-2 GW1.0×$3,329/kW~$49/MWh
2-4 GW1.3×$4,328/kW~$64/MWh
4-5 GW1.6×$5,326/kW~$78/MWh

The first 2 GW represents the best hydrothermal resources (The Geysers, Salton Sea). The 2-4 GW band captures good sites requiring deeper drilling and higher reservoir development costs. Beyond 4 GW, only marginal sites and enhanced geothermal systems (EGS) remain feasible, significantly increasing costs.

Biomass Supply Curve
Capacity RangeCost MultiplierEffective CAPEXMarginal LCOE
0-1.5 GW1.0×$3,500/kW~$54/MWh
1.5-3 GW1.4×$4,900/kW~$75/MWh

The first 1.5 GW uses cheapest feedstocks: waste residues, agricultural waste, and forest thinnings with minimal transport costs. Beyond 1.5 GW, dedicated energy crops are required with longer transport distances, increasing both feedstock and logistics costs.

How Supply Curves Work

The optimizer uses two CAPEX values:

  • Marginal CAPEX: Used in LCOE calculations to guide technology selection. This is the cost of the next GW at the current deployment level. For example, if 3 GW of geothermal is already deployed, the marginal CAPEX for the 4th GW is $4,328/kW (1.3× multiplier).
  • Blended CAPEX: Used in total system cost calculations. This is the capacity-weighted average cost across all deployment bands. For example, if 3 GW is deployed, blended CAPEX = (2 GW × $3,329 + 1 GW × $4,328) / 3 GW = $3,662/kW.

This dual approach ensures the optimizer sees accurate marginal economics (guiding incremental decisions) while calculating correct total costs (reflecting what was actually paid for all deployed capacity).

3.3 Capital Recovery Factor (CRF)

Capital costs are annualized using the Capital Recovery Factor, which converts a lump-sum investment into equal annual payments over the asset's lifetime at a given discount rate:

CRF(d, n) = d × (1 + d)n / [(1 + d)n − 1]

where d is the discount rate (default: 7% = 0.07) and n is the asset lifetime in years.

For example, a solar plant (30 years, 7% discount): CRF = 0.07 × 1.0730 / (1.0730 − 1) ≈ 0.0806, meaning ~8.06% of capital cost is paid annually.

3.4 Annualized Cost Formulas

Generation Technologies (Solar, Wind, Nuclear, etc.)
Annual CAPEX = Capacity (kW) × CAPEX ($/kW) × CRF(d, n)
Annual Fixed O&M = Capacity (kW) × Fixed O&M ($/kW-yr)
Annual Variable O&M = Annual Generation (MWh) × Variable O&M ($/MWh)

Total Annual Cost = Annual CAPEX + Fixed O&M + Variable O&M

Annual generation is computed by summing hourly dispatch across all 288 hours, weighted by days in each month.

Storage Technologies (Battery, Long-Duration)

Storage is specified in GWh of energy capacity. Power capacity is derived from the duration:

Power (kW) = Energy (kWh) / Duration (hours)
  4-hr battery: Duration = 4 hours
  8-hr battery: Duration = 8 hours
  Long-duration: Duration = 24 hours

Annual CAPEX = Energy (kWh) × CAPEX ($/kWh) × CRF(d, n)
Annual Fixed O&M = Power (kW) × Fixed O&M ($/kW-yr)
Annual Variable O&M = Annual Discharge (MWh) × Variable O&M ($/MWh)

Round-trip efficiency for all storage types is 85%. This means for every 1 MWh charged, only 0.85 MWh is available for discharge.

Direct Air Capture (DAC)
Annual Capture Capacity = Hourly Rate (t/hr) × 24 × 365 (tons/yr)
Annual CAPEX = Annual Capacity × CAPEX ($/ton-yr) × CRF(d, n)
Annual Fixed O&M = Annual Capacity × Fixed O&M ($/ton-yr)
Annual Variable O&M = Annual Capacity × Variable O&M ($/ton)

3.5 Incentives

Government incentives reduce technology costs:

  • Production Tax Credit (PTC): Applied as $/MWh to annual generation. Reduces the annual cost of the technology by Annual Generation (MWh) × PTC rate. Available for solar, wind, offshore wind, nuclear, geothermal, biomass, RNG, and hydrogen.
  • Investment Tax Credit (ITC): Applied to storage. Reduces cost by Energy Capacity (kWh) × CAPEX × ITC rate × CRF (annualized).
  • DAC Incentive: Per-ton subsidy that directly reduces DAC annual cost.
  • Carbon Tax: Adds cost: (Annual CO2 in kg / 1000) × Carbon Tax ($/ton).
  • Export Price: Curtailed energy can be "exported" at a given price (can be negative). Revenue = Curtailment (GWh) × 1000 × Export Price ($/MWh).

3.6 Total System Cost

Total System Cost ($/yr) =
  ∑ Generation Tech Costs (CAPEX + Fixed O&M + Var O&M − PTC)
+ ∑ Storage Costs (CAPEX + Fixed O&M + Var O&M − ITC)
+ DAC Cost (CAPEX + Fixed O&M + Var O&M − DAC Incentive)
+ Carbon Tax Cost
− Export Revenue

This cost includes both existing baseline capacity and new additions. The optimizer minimizes this total while meeting the CO2 constraint.

4. Dispatch Simulation

Every candidate solution is evaluated by running a full hourly dispatch simulation (getSimulationResult). This determines how the grid operates each hour: which plants run, how storage charges/discharges, what gets curtailed, and the resulting emissions. The dispatch follows a merit order, prioritizing low-cost and zero-carbon sources.

Dispatch Order (each hour)
  1. Must-run baseload: Nuclear, geothermal, and biomass run at their capacity factor regardless of demand. Hydro runs at its country-specific capacity factor.
  2. Variable Renewable Energy (VRE): Solar and wind generation is computed as Capacity (GW) × CF Profile[hour]. The CF profile varies by hour and month, capturing diurnal and seasonal patterns.
  3. Net Load calculation: Net Load = Demand − Must-run − VRE. If net load is negative, there is excess generation.
  4. Storage dispatch: Storage operates via economic arbitrage. Short-term batteries (4-hr, 8-hr) charge/discharge within each day. Long-duration storage (24-hr) can carry state-of-charge across days with 1% monthly self-discharge, enabling multi-day energy shifting. All storage has 85% round-trip efficiency. The algorithm sorts hours by net load, identifying arbitrage opportunities (charge during excess generation, discharge during high net load) while respecting energy and power constraints.
  5. Flexible clean dispatch: RNG (biogas) and Hydrogen are dispatched only when net load is positive, operating as flexible zero-carbon resources. Unlike the old inflexible dispatch (24/7 must-run), they now respond to system needs.
  6. Thermal dispatch: Remaining net load (after storage and flexible clean) is met by fossil fuels in merit order: Natural Gas CCGT (cheapest) → Coal → Natural Gas CT (most expensive peakers). Each plant ramps between a minimum and maximum output, with the marginal cost increasing linearly as output increases.
  7. Curtailment: If total generation exceeds demand after all dispatch, the excess is curtailed. Curtailment Rate = Curtailed Energy / (Total Generation + Curtailment).

4.1 Emissions Calculation

Hourly emissions are computed by multiplying each technology's generation by its emission factor:

Hourly CO2 (kg/hr) = ∑ Generation[tech] (GW) × 1000 × EmissionFactor[tech] (kg/MWh) − DAC Rate (kg/hr)
TechnologyEmission Factor (kg CO2/MWh)
Natural Gas (generic)410
Natural Gas CCGT370
Natural Gas CT500
Coal920
Biomass50 (net, after regrowth offset)
All other (solar, wind, nuclear, etc.)0

Annual CO2 is then computed by summing hourly emissions weighted by days per month:

Annual CO2 (kg) = ∑i=0287 HourlyEmissions[i] × DaysInMonth[⌊i/24⌋]

5. Optimization Algorithm

The optimizer uses a multi-start deterministic search consisting of three phases: (1) a heuristic initial guess, (2) an iterative neighbor-search main loop guided by system-value adjusted LCOE, and (3) a Nelder-Mead simplex refinement. This hybrid approach balances exploration (finding good regions of the solution space) with exploitation (fine-tuning the best solution found).

Multi-Start Approach

By default, the optimizer runs 3 independent optimization runs with different random seeds (42, 137, 2024), then selects the lowest-cost feasible solution. This multi-start approach addresses the fact that capacity expansion planning has a multimodal fitness landscape—many local minima with similar costs but different technology mixes. Running multiple trajectories significantly improves the chance of finding the global optimum (or a near-optimal solution).

All randomness is controlled by a seeded pseudo-random number generator (Mulberry32), ensuring that:

  • The same seed produces identical results every time (fully reproducible)
  • Different seeds explore different solution trajectories
  • No dependence on browser-specific Math.random() implementation

Randomness is used in five locations: perturbation technology selection, perturbation magnitude, random exploration candidate tech, random exploration step size, and panic mode technology selection (if reserve margin fails repeatedly).

5.1 Initial Guess Heuristic

Rather than starting from zero capacity, the optimizer estimates a reasonable starting point based on the CO2 reduction needed:

Baseline CO2 = Emissions from existing grid with zero new capacity
CO2 Reduction Needed = max(0, Baseline CO2 − Target CO2)

Total Clean Capacity Needed (GW) = CO2 Reduction / 1.1 × 109
(Empirical rate: ~1.1 million MT CO2 reduced per GW of clean capacity)

Initial Solar = min(100, 60% of Total Clean Capacity)
Initial Wind = min(80, 40% of Total Clean Capacity)
Initial Battery = min(50, 25% of VRE Capacity) [GWh, 4-hr]
Reserve Margin Gap Check

Before starting the main loop, the optimizer checks whether the existing grid plus the initial guess has sufficient flexible capacity. If the reserve margin target (20%) is not met, it adds:

  • 80% of the gap as 4-hr battery (GWh = gap × 4 × 0.8)
  • 15% as RNG
  • 5% as Hydrogen
Adaptive Scaling

If a previous optimization overshot the target (CO2 came in >5% below target), the initial guess is scaled down to prevent the same overshoot. The scale factor is max(0.5, 1.0 − previousGapPercent/100), capping at 50% reduction.

5.2 Main Optimization Loop

The core loop runs up to 1000 iterations (configurable). Each iteration:

  1. Compute system-value adjusted LCOE for each technology using calculateMarginalLCOEWithSystemValue. This starts from the base LCOE but adjusts based on current system conditions:
    • If curtailment > 10%: VRE LCOE is penalized (solar ×(1 + curtailment rate), wind ×(1 + curtailment × 0.5), offshore ×(1 + curtailment × 0.3)) since adding more VRE will further increase curtailment.
    • If reserve margin < target: Flexible technology LCOEs receive a 90% discount (multiplied by 0.1), and firm baseload (nuclear, geothermal) gets a 50% discount.
    • If CO2 gap exists: All zero-carbon technologies get a 10% discount. If the gap is severe (>1.5× target), DAC gets a 30% discount.
  2. Generate candidate solutions: Technologies are ranked by adjusted LCOE. For each technology (in LCOE order), candidates are generated by adding or subtracting a step size. Step sizes vary by technology:
    TechnologyStep SizeUnit
    Solar1.0 – 5.0GW
    Wind1.0 – 5.0GW
    Offshore Wind0.5 – 2.0GW
    Nuclear0.5 – 2.0GW
    Geothermal0.5 – 1.0GW
    Biomass0.5 – 1.0GW
    RNG / Hydrogen0.5 – 2.0GW
    Battery (4-hr / 8-hr)2.0 – 10.0GWh
    Long-Duration5.0 – 20.0GWh
    DAC100 – 500t/hr

    The step size adapts based on iteration count (larger early, smaller later) and system conditions.

  3. Quick feasibility pre-screen: Before running a full simulation, candidates are checked with a fast reserve margin estimate. Candidates that clearly fail are skipped.
  4. Full evaluation: Remaining candidates are evaluated via complete dispatch simulation, computing cost, CO2, reserve margin, curtailment, and energy balance.
  5. Selection: The best feasible candidate is selected. Under normal operation, the lowest-cost feasible solution wins. When the current best solution is >10% below the CO2 target, a weighted objective is used: 70% cost + 30% proximity to target, to push the solution back toward the target.
  6. Improvement check: An improvement is "meaningful" if cost improves by >0.01% or the CO2 gap narrows by >1%. If meaningful, the no-improvement counter resets. Otherwise, it increments.

5.3 Feasibility Constraints

A solution must pass all four constraints to be considered feasible:

ConstraintRequirementTolerance
CO2 TargetAnnual CO2 ≤ Target CO22% above target allowed
Reserve MarginFlexible Capacity / Peak Demand − 1 ≥ 0.20None
Curtailment CapCurtailment Rate ≤ 20%Only if enabled by user
Energy BalanceUnmet Energy < 10 MWh/yrNone

The quick feasibility check only tests reserve margin (fast to compute). The full feasibility check tests all four constraints after running the complete dispatch simulation.

5.4 Convergence & Early Stopping

The optimizer stops when no meaningful improvement is found for a number of consecutive iterations:

  • Normal convergence: 50 iterations with no meaningful improvement.
  • Below-target mode: When the best solution's CO2 is >10% below target, the threshold increases to 200 iterations to allow the optimizer more time to find solutions closer to the target.
  • Near-minimum capacity: If baseload capacity < 1 GW and total non-flexible capacity < 8 GW, the threshold reverts to 50 since we've hit a physical limit.
Perturbation (Escaping Local Minima)

After 30 iterations without improvement, the current solution is randomly perturbed. Each technology's capacity is multiplied by a random factor between 0.7 and 1.3 (up to ±30% change). This helps the optimizer explore different regions of the solution space.

5.5 Nelder-Mead Local Refinement

After the main loop converges, the best solution is refined using the Nelder-Mead simplex algorithm. This derivative-free optimization method works in the space of "active" technologies (those with non-zero capacity in the best solution), plus a limited set of inactive technologies for exploration.

Simplex Initialization

For N active technologies plus up to 3 inactive "exploration" technologies, a simplex of (N+M)+1 points is created. The first point is the current best solution. The remaining points are created by:

  • Active tech points: Perturb each active technology dimension by ±0.5 GW (generation) or ±2.0 GWh (storage)
  • Exploration points: Introduce small positive amounts of inactive technologies (1 GW for generation, 5 GWh for storage), allowing Nelder-Mead to discover cost-effective technologies that the greedy search phase missed

This enhancement addresses a limitation of the original algorithm: Nelder-Mead could only refine technologies already in the solution, never discovering new ones. By including exploration points, the refinement phase can now find and add previously unused technologies if they improve the objective.

Simplex Operations

Each iteration sorts the simplex by cost, then attempts to replace the worst point using these transformations:

Centroid: c = (1/N) × ∑(all points except worst)

Reflection:    xr = c + α(c − xworst)    [α = 1.0]
Expansion:    xe = c + γ(xr − c)      [γ = 2.0]
Contraction:  xc = c + ρ(xworst − c)   [ρ = 0.5]
Shrink:       xi = xbest + σ(xi − xbest) [σ = 0.5]

The algorithm first tries reflection. If the reflected point is the best so far, it tries expansion. If reflection is worse than the second-worst, it tries contraction. If all fail, it shrinks the entire simplex toward the best point.

Convergence: The refinement stops when the cost range across the simplex (worst − best) is less than 1% of the best cost, or after 150 iterations.

6. Direct Air Capture (DAC)

DAC is a technology that actively removes CO2 from the atmosphere. In the optimizer, it acts as negative emissions.

When DAC is Enabled

DAC is only added to the candidate technology list when the CO2 target is aggressive: specifically, when the target is less than 60% of the baseline emissions. For easier targets, DAC is excluded because conventional clean generation is more cost-effective. DAC can also be manually disabled by the user via a checkbox.

LCOE Adjustments for DAC

When the CO2 gap is severe (>1.5× the target), DAC receives a 30% LCOE discount to make it more competitive. This reflects that DAC becomes increasingly valuable when other options are insufficient.

7. Reserve Margin

The reserve margin measures how much flexible, dispatchable capacity exceeds peak demand. It is a proxy for grid reliability—ensuring there is enough backup capacity for unexpected demand spikes or generator outages.

Reserve Margin = (Total Flexible Capacity / Peak Demand) − 1.0

Target: ≥ 0.20 (20%)
What Counts as Flexible Capacity
Resource TypeCapacity CreditNotes
Fully Flexible (100% capacity credit)
Natural Gas (all types)100%Fully dispatchable
RNG (Biogas)100%Flexible dispatch (responds to net load)
Hydrogen100%Flexible dispatch (responds to net load)
Hydro100%Fully dispatchable
Battery StoragePower capacity (GWh ÷ duration)4-hr: GWh/4; 8-hr: GWh/8; 24-hr: GWh/24
Not Counted (Intermittent or Inflexible)
Solar, Wind, Offshore Wind0%Intermittent generation (VRE)
Nuclear, Geothermal, Biomass, Coal0%Inflexible baseload (24/7 operation)

Example: A 100 GWh, 4-hour battery provides 25 GW of flexible power capacity toward the reserve margin.

8. Capacity Bounds

Each technology has minimum and maximum capacity limits. These prevent unrealistic solutions and keep the optimization space manageable:

TechnologyMinMaxUnit
Solar0100GW
Onshore Wind080GW
Offshore Wind050GW
Nuclear030GW
Geothermal05GW
Biomass03GW
RNG020GW
Hydrogen020GW
Battery (4-hr)0100GWh
Battery (8-hr)0100GWh
Long-Duration (24-hr)0200GWh
DAC010,000t/hr

These bounds represent new capacity additions only, not total installed capacity. Existing baseline capacity is separate.

9. Stranded Asset Detection

After optimization, the model checks whether existing fossil fuel capacity is underutilized. If the optimized grid's peak hourly usage of natural gas or coal is less than 80% of the installed capacity, the system flags these as potentially stranded assets.

Stranded if: Max Hourly Usage < 0.80 × Installed Capacity

When stranded capacity is detected, the user is offered the option to re-optimize with reduced fossil baseline. The suggested new capacity is set to 110% of the peak optimized usage (a 10% buffer). Reducing fossil capacity lowers Fixed O&M costs but may require additional flexible clean resources (batteries, RNG, hydrogen) to maintain the reserve margin.

10. Configuration Parameters

Optimization Configuration

ParameterValueDescription
MAX_ITERATIONS1000Maximum iterations in main loop
RESERVE_MARGIN_TARGET0.2020% flexible capacity above peak demand
Discount Rate0.077% real discount rate for CRF
CO2 Tolerance2%Solutions up to 2% above target are feasible
Curtailment Cap20%Max allowed curtailment (if enabled)
Convergence Threshold50 / 200Iterations without improvement before stopping
Perturbation Trigger30No-improvement iterations before random perturbation
Nelder-Mead Iterations150Maximum iterations for local refinement
Storage Efficiency85%Round-trip efficiency for all storage
Cache Precision0.1 GWSolution hashing rounds to nearest 0.1 GW

Monthly VRE Capacity Factor Profiles

Capacity factor profiles for solar, onshore wind, and offshore wind vary by month to capture seasonal patterns. Two approaches are used:

  • California: Uses direct 12-month × 24-hour profiles extracted from CAISO 2025 Summer Assessment (Figures 2.4 & 2.5). Each month has a unique diurnal pattern with realistic shapes and all capacity factors ≤ 1.0.
  • Other regions: Uses a base 24-hour profile scaled by monthly multipliers. All resulting CFs are capped at 1.0 via Math.min(1, baseCF × multiplier).
California Monthly Profiles (CAISO-derived, rescaled to peak=1.0)
MonthSolar Peak CFWind Peak CFOffshore Wind Peak CFPattern Notes
January0.580.300.5010 sun hours, winter-boosted offshore
February0.700.390.6511 sun hours, strengthening wind
March0.810.570.8013 sun hours, spring transition
April0.910.791.0014 sun hours, wind ramping up
May0.980.910.9315 sun hours, peak solar & wind correlation
June1.001.000.8916 sun hours, strongest wind, reduced offshore
July0.960.790.8015 sun hours, sustained summer peak
August0.910.660.7614 sun hours, beginning descent
September0.830.630.7212 sun hours, fall transition
October0.700.390.5011 sun hours, weakening wind
November0.560.300.4610 sun hours, winter approaching
December0.480.290.449 sun hours, winter minimum

Key California pattern: Unlike most US regions, California wind is summer-peaking due to the coastal-to-inland thermal gradient driving strong winds through mountain passes (Tehachapi, Altamont, San Gorgonio). Both solar and wind peak in May–June (positively correlated). Offshore wind uses season-dependent transformation: winter-boosted (1.3×), summer-reduced (0.7×), then smoothed to reflect steadier marine winds. All profiles have been rescaled so the peak CF across all months equals 1.0, providing accurate relative seasonal variation while allowing maximum theoretical output during optimal conditions.

Default (other regions)
MonthSolarOnshore WindOffshore Wind
January0.601.151.15
February0.701.101.10
March0.851.051.05
April0.950.951.00
May1.050.900.95
June1.150.850.90
July1.150.800.85
August1.100.800.85
September0.950.850.90
October0.800.951.00
November0.651.101.10
December0.551.151.15

In the default pattern, solar is strongest in summer and weakest in winter, while wind has the opposite pattern (strongest in winter). This seasonal complementarity is typical for most US and European regions.

Monthly Demand Profiles

Demand profiles vary by month to capture seasonal load patterns. Two approaches are used:

  • California: Uses direct 12-month × 24-hour demand profiles derived from CAISO operational data. Each month has a complete hourly pattern with realistic diurnal variation, including subtle midday plateau characteristics.
  • Other regions: Uses seasonal base 24-hour profiles (spring, summer, fall, winter) scaled by per-month multipliers. Each month maps to its season's shape, then is scaled by a multiplier to capture month-to-month intensity variation.
California Monthly Demand Profiles (CAISO-derived)
MonthPeak Demand (GW)Overnight Min (GW)Pattern Characteristics
January29.519.3Moderate winter, evening peak
February28.018.2Mildest month (lowest peak)
March27.016.3Spring transition, lowest demand season
April26.516.4Annual minimum, mild spring weather
May31.017.5Warming, early AC usage begins
June38.521.7Early summer, AC demand rising
July45.025.3Peak summer heat, AC-driven evening peak
August46.526.2Hottest month (highest consistent peak)
September46.026.9Late summer heatwaves, volatile (historical record 52 GW)
October34.520.1Fall transition, cooling down
November29.018.5Cooling down, lower demand
December30.019.1Winter, holiday lighting and heating

California pattern: Profiles exhibit subtle midday plateau (1-2 GW dip below morning peak) before the evening peak, characteristic of CAISO operational data. Demand follows a clear seasonal pattern: spring (March-April) represents the annual minimum at ~26-27 GW due to mild weather and high solar output offsetting daytime load. Summer months (July-September) show the highest peaks at 45-46 GW driven by air conditioning demand, with September being particularly volatile due to late-season heatwaves (CAISO's all-time record of 52 GW occurred in September 2022). Winter and fall months range from 28-35 GW. All values based on typical CAISO operational ranges.

Default (other regions)

For non-California regions, the system uses four seasonal base 24-hour profiles (spring, summer, fall, winter) scaled by per-month multipliers ranging from 0.92 to 1.11. This preserves backward compatibility while still capturing month-to-month demand variation.

Solution Caching

To avoid redundant dispatch simulations, the optimizer caches evaluation results. Solutions are hashed by rounding each technology's capacity to the nearest 0.1 GW (or GWh for storage, t/hr for DAC). If a solution with the same hash has been evaluated before, the cached result is returned directly. The cache is cleared at the start of each optimization run.