Economic Assumptions#
This page documents how GreenBubble translates technology investment data into annual capital charges, how the discount rate is applied, and how brownfield initial conditions are parameterised.
—
Technology-data source#
Investment costs, fixed O&M rates, efficiencies, and technical lifetimes come
from the technology-data
repository (branch pypsa-eur_AA), which is a fork of the
PyPSA-Eur technology-data catalogue.
The repository provides separate CSV files for each 5-year planning horizon: 2020, 2025, 2030, 2035, 2040, 2045, 2050. All cost projections are in constant real EUR of a fixed base year (i.e. they represent technology learning curves, not nominal price inflation — see Real costs and currency).
The CSV files are downloaded automatically by the retrieve_tech_data rule
(all years at once) and stored in data/technology-data/outputs/. A git
blob SHA is cached alongside each file so that Snakemake detects upstream
changes without a manual --forcerun.
Project-specific overrides (compressor sizing, GLS-specific equipment) are
defined as ("technology", "parameter") tuples in
scripts/technology_inputs.py and merged into the cost table via
helpers.merge_into_costs() before the annuity is computed.
—
Capital cost annualisation#
The annual capital charge for a technology with investment cost I (EUR/MW), fixed O&M rate f (% of investment per year), and technical lifetime L (years) is:
where the annuity factor is:
r is the project discount rate (see Discount rate).
This is computed in helpers.read_costs() and stored in the fixed
column of the cost DataFrame. PyPSA then multiplies fixed by the
optimised capacity (p_nom_opt) to obtain the annual capital expenditure
in n.statistics.capex().
Amortization period
By default the annuity denominator equals the technical lifetime L.
Setting amortization_period in config.yaml to a positive number
(e.g. 15) overrides L for all new expandable capacity:
amortization_period: 15 # recover new investments over 15 years
A shorter amortization period → higher annual charge → harder to invest.
null (default) restores the technical-lifetime behaviour.
For existing capacity the effective period is always amortization_period
(warn if it exceeds the asset’s remaining technical lifetime — reinvestment
may be implied; see Brownfield initial conditions).
—
Discount rate#
discount_rate in config.yaml is a real rate — it excludes
inflation. All cost data are expressed in constant real EUR of a fixed
base year, so comparing costs across planning years (2020 vs 2030) is
valid without any price-level adjustment.
Note
Do not use a nominal rate (which includes expected inflation). Mixing real costs with a nominal discount rate would systematically over-penalise future costs.
Typical real discount rates for energy projects range from 5 % (public finance) to 10 % (private equity). The default is 7 %.
—
year_investment#
year_investment selects which year’s cost CSV is used for new
expandable capacity. For example, year_investment: 2030 loads
data/technology-data/outputs/costs_2030.csv.
This is independent of the energy/weather year (En_price_year) used
for electricity prices and capacity factors.
Available values: 2020, 2025, 2030, 2035, 2040, 2045, 2050.
—
Brownfield initial conditions#
When initial capacity > 0 in n_config.yaml, an existing (EXI_)
component is added to the network. Three parameters control its annual
capital charge:
construction_yearThe year the asset was built. Used to look up the investment cost at the actual build year:
I(construction_year). Technology costs change between years (learning curves), so an older plant typically cost more than a plant built today.If not set (
null), defaults toyear_investment - 10(i.e. 10 years before the current planning year), capped at 2020 (the earliest available cost data).remaining_investment_fractionThe fraction of
I(construction_year)that is financially still outstanding. This is independent of the technical remaining lifetime: a fully paid-off asset hasremaining_investment_fraction = 0even if it still has many years of useful life ahead.0(default) = sunk cost; the EXI_ component carries no annual CAPEX.1= the full original investment is still outstanding.
Annual charge formula
where rif = remaining_investment_fraction and the effective
amortization period comes from amortization_period in config.yaml
(or the technical lifetime if null).
Note
If the asset’s remaining technical lifetime
(\(\text{construction\_year} + L - \text{year\_investment}\))
is shorter than the amortization period, a UserWarning is issued:
re-investment within the planning horizon may be implied.
Example
Existing electrolysis unit, commissioned in 2020, 60 % of original investment still outstanding, no new capacity to be built on top:
# config/n_config.yaml
electrolysis:
initial capacity: 5 # MW_el
expansion: false
construction_year: 2020
remaining_investment_fraction: 0.6
With year_investment: 2030, amortization_period: null,
discount_rate: 0.07, and a 25-year technical lifetime:
remaining_lifetime = 2020 + 25 − 2030 = 15 yearsI(2020)is read fromcosts_2020.csvannuity(15, 0.07) ≈ 0.110(Python call:annuity(n, r))Annual charge =
0.6 × I(2020) × 0.110EUR/MW/year
Relationship to amortization_period and remaining lifetime
remaining_lifetime |
amortization_period |
Outcome |
|---|---|---|
> amortization_period |
set |
Recovery accelerated; asset financially clear before technical end-of-life. |
< amortization_period |
set |
Warning issued; implies re-investment before full recovery. |
= amortization_period |
null (default) |
Standard case; annuity uses remaining technical life. |
—
Real costs and currency#
All monetary values in GreenBubble are expressed in real EUR of a fixed base year (the base year is inherited from the technology-data repository). The cost trajectories from 2020 to 2050 represent technology learning (e.g. falling solar costs) — not changes in the general price level.
Consequence: there is no need to inflate or deflate investment costs
between construction_year and year_investment. I(2022)
and I(2030) are already in the same real EUR, so comparing or dividing
them is financially consistent.
USD-denominated technologies are converted at the USD_to_EUR exchange
rate set in config.yaml.