Rooftop Solar Model¶
The rooftop solar model simulates distributed solar PV adoption and generation. It is implemented in models/solar_rooftop.py.
Overview¶
Unlike utility-scale solar (modeled as generators with investment decisions), rooftop solar follows an exogenous adoption curve. The model:
- Projects rooftop PV adoption per node using S-curve scenarios
- Estimates available rooftop area and installable capacity
- Generates stochastic availability profiles with weather variability
- Injects behind-the-meter generation that reduces net demand
Rooftop solar is activated by setting rooftop_solar_config.enabled: true in the system configuration and enabling simulate_rooftop: true in the system settings.
Adoption Model¶
Rooftop solar adoption follows a logistic growth curve with three scenarios:
| Scenario | Growth Rate | Max Penetration | Typical Use Case |
|---|---|---|---|
low |
Conservative | 15-20% of potential | Minimal policy support, low feed-in tariffs |
medium |
Moderate | 40-60% of potential | Standard incentive programs |
high |
Aggressive | 70-90% of potential | Strong mandates, net metering, subsidies |
The number of rooftop systems at node \(n\) in year \(y\):
where:
- \(N^{roof,0}_n\) is the initial number of systems at node \(n\) (initial_systems_per_node)
- \(K^{roof}\) is the carrying capacity ratio (max_systems_per_node / initial_systems_per_node)
- \(r^{roof}\) is the growth rate (determined by the adoption scenario)
- \(y_{mid}\) is the inflection year (midpoint of the planning horizon)
Total rooftop capacity:
where \(\bar{P}^{avg}_{roof}\) is the average system size (typically 3-10 kW), configured via avg_system_size_kw.
Adoption Curve Example¶
For a node with 100 initial systems and 5000 maximum under the medium scenario:
| Year | Systems | Capacity (5 kW avg) |
|---|---|---|
| 1 | 120 | 0.6 MW |
| 5 | 350 | 1.75 MW |
| 10 | 1,500 | 7.5 MW |
| 15 | 3,800 | 19.0 MW |
| 20 | 4,700 | 23.5 MW |
| 25 | 4,950 | 24.75 MW |
The S-curve shape reflects typical technology adoption patterns: slow initial uptake, rapid growth during the "takeoff" phase, and saturation as the market matures.
Area Estimation¶
The maximum installable capacity at each node can be constrained by available rooftop area:
where: - \(A^{roof}_n\) is the suitable rooftop area in m² (estimated from building footprints × suitability factor) - \(\eta^{panel}\) is the panel efficiency (typically 0.18-0.22 for modern panels) - \(G^{peak}\) is the peak solar irradiance (1.0 kW/m² standard)
A typical suitability factor of 0.3-0.5 accounts for shading, orientation, structural constraints, and architectural features that prevent installation.
Orientation and Tilt¶
Rooftop solar output depends on panel orientation and tilt angle. The availability profile implicitly captures these effects through location-specific solar resource data. Key factors:
| Factor | Effect | Typical Range |
|---|---|---|
| Tilt angle | Optimal tilt ≈ latitude for annual energy | 10-45 degrees |
| Azimuth | South-facing (Northern hemisphere) optimal | ±30° from optimal |
| Shading | Trees, adjacent buildings reduce output | 5-20% loss |
| Soiling | Dust accumulation | 2-5% loss |
These losses are incorporated into the base availability profile rather than modeled explicitly, keeping the optimization problem linear and tractable.
Availability Profiles¶
Rooftop solar generation profiles include:
- Base irradiance: Hourly solar resource profile (similar to utility-scale)
- Weather variability: Stochastic perturbation with configurable levels:
low: \(\sigma = 0.05\) — clear-sky dominated regionsnormal: \(\sigma = 0.10\) — typical temperate climatehigh: \(\sigma = 0.15\) — tropical or highly variable climate- Panel degradation: Annual capacity reduction (typically 0.5%/year)
The hourly generation at node \(n\) in time step \(t\):
where: - \(\alpha^{roof}_{n,t}\) is the availability factor (0-1) from the profile - \(\delta^{roof}\) is the annual degradation rate - \(age\) is the average fleet age in years
Generated by generate_rooftop_solar_profiles().
Profile Generation¶
The availability profile can be:
- Provided externally: A CSV file with hourly capacity factors (8760 values for one year)
- Generated internally: Using the built-in solar resource model with location coordinates and weather variability
Example availability profile CSV (solar_rooftop_profile.csv):
hour,capacity_factor
0,0.000
1,0.000
...
6,0.050
7,0.180
8,0.420
9,0.650
10,0.820
11,0.910
12,0.950
13,0.920
14,0.830
15,0.680
16,0.450
17,0.200
18,0.060
19,0.000
...
Self-Consumption vs Grid Injection¶
Rooftop solar generation is split between self-consumption (consumed locally, never enters the grid) and grid injection (surplus exported to the network):
In the current ESFEX implementation, all rooftop generation is treated as grid-visible supply injection. Self-consumption can be modeled by reducing the net demand profile before optimization:
This approach is valid when self-consumption follows a predictable pattern (e.g., a fixed fraction of generation during business hours).
Power System Integration¶
Rooftop solar generation appears in the power balance as supply:
where \(C^{roof}_{n,t}\) is rooftop curtailment (penalized but allowed).
Behind-the-Meter
Rooftop solar is treated as negative demand (or supply injection). It is not dispatchable -- the optimizer can only curtail it, not increase it.
Interaction with Utility-Scale Solar¶
Rooftop and utility-scale solar are modeled independently:
| Aspect | Utility-Scale | Rooftop |
|---|---|---|
| Investment | Optimized (decision variable) | Exogenous (S-curve) |
| Dispatch | Curtailable, scheduled | Non-dispatchable |
| Location | At network buses | Behind-the-meter |
| Size | 10-500 MW | 3-10 kW per system |
| Grid visibility | Full | Reduced net demand |
| Degradation | Per-generator | Fleet average |
Interaction with Battery Storage¶
Rooftop solar excess can charge batteries at the same node. The optimizer naturally coordinates rooftop injection with battery charging to minimize system costs. High rooftop penetration often drives battery investment to shift midday solar surplus to evening peak demand.
Capacity Expansion Interaction¶
In the master problem, rooftop solar capacity is not a decision variable. Instead:
- The adoption model projects rooftop capacity for each planning year
- This capacity is subtracted from gross demand to compute net demand
- The master problem optimizes investments in utility-scale generation and storage to meet the remaining net demand
This means rooftop solar acts as a demand modifier in capacity expansion, reducing the need for centralized generation investments.
Configuration¶
rooftop_solar_config:
enabled: true
adoption_scenario: medium # low, medium, high
avg_system_size_kw: 5.0
initial_systems_per_node: [100]
max_systems_per_node: [5000]
degradation_rate: 0.005 # 0.5%/year
availability_file: solar_rooftop_profile.csv
weather_variability: normal # low, normal, high
| Parameter | Type | Default | Description |
|---|---|---|---|
enabled |
bool | false |
Enable rooftop solar simulation |
adoption_scenario |
str | "medium" |
Growth scenario: low, medium, high |
avg_system_size_kw |
float | 5.0 |
Average rooftop system size in kW |
initial_systems_per_node |
list[int] | [0] |
Starting number of systems per node |
max_systems_per_node |
list[int] | [1000] |
Maximum installable systems per node |
degradation_rate |
float | 0.005 |
Annual panel degradation (0.5%/year) |
availability_file |
str | -- | Path to hourly capacity factor CSV |
weather_variability |
str | "normal" |
Stochastic variability level |
Output¶
The model produces:
| Output | Shape | Description |
|---|---|---|
rooftop_generation |
(hours, nodes) | Hourly generation in MW |
rooftop_curtailment |
(hours, nodes) | Curtailed rooftop generation |
adoption_factors |
(nodes,) | Adoption multiplier per node per year |
max_potential |
(nodes,) | Maximum installable capacity per node |
degradation_factor |
scalar | Fleet-average degradation multiplier |
Accessing Results¶
Rooftop solar results are stored in the HDF5 output file under each year's group:
/year_1/rooftop/generation # (hours, nodes) array
/year_1/rooftop/curtailment # (hours, nodes) array
/year_1/rooftop/capacity # (nodes,) installed capacity
Limitations¶
- No individual system modeling: All systems at a node are aggregated; individual orientation, shading, and sizing are averaged.
- No battery pairing: Rooftop batteries (home storage) are not explicitly modeled; use grid-level battery investment instead.
- Fixed adoption curve: The adoption trajectory is exogenous and does not respond to electricity prices or incentives within the optimization.
- No net metering tariff: Feed-in tariff or net metering compensation is not modeled; all generation is valued at the system marginal cost.
References¶
The distributed generation market demand modeling follows the NREL dGen model by Sigrin et al. [54]. Rooftop suitability estimation methods are reviewed by Melius et al. [55]. IRENA renewable cost benchmarks [48] are used for default PV cost assumptions.
See the full bibliography for complete citation details.