Running the national scale example model¶
This notebook will show you how to load, build, solve, and examine the results of the national scale example model.
import calliope
import pandas as pd
import plotly.express as px
# We increase logging verbosity
calliope.set_log_verbosity("INFO", include_solver_output=False)
Load model and examine inputs¶
model = calliope.examples.national_scale()
[2024-01-27 14:24:39] INFO Model: initialising
[2024-01-27 14:24:39] INFO Model: preprocessing stage 1 (model_run)
[2024-01-27 14:24:42] INFO Model: preprocessing stage 2 (model_data)
[2024-01-27 14:24:42] INFO Model: preprocessing complete
Model inputs can be viewed at model.inputs
.
Variables are indexed over any combination of techs
, nodes
, carriers
, costs
and timesteps
.
model.inputs
<xarray.Dataset> Dimensions: (costs: 1, techs: 8, nodes: 5, carriers: 1, timesteps: 120) Coordinates: * costs (costs) object 'monetary' * techs (techs) object 'battery' ... 'region1_to_re... * carriers (carriers) object 'power' * nodes (nodes) <U9 'region1' ... 'region2' * timesteps (timesteps) datetime64[ns] 2005-01-01 ... 2... Data variables: (12/37) objective_cost_weights (costs) float64 1.0 bigM float64 1e+06 base_tech (techs) object 'storage' ... 'transmission' carrier_in (nodes, techs, carriers) float64 nan ... 1.0 color (techs) object '#3B61E3' ... '#8465A9' name (techs) object 'Battery storage' ... 'AC po... ... ... source_use_max (timesteps, nodes, techs) float64 nan ... nan sink_use_equals (timesteps, nodes, techs) float64 nan ... nan definition_matrix (nodes, techs, carriers) bool False ... True distance (techs) float64 nan nan nan ... 111.0 512.3 timestep_resolution (timesteps) float64 1.0 1.0 1.0 ... 1.0 1.0 timestep_weights (timesteps) float64 1.0 1.0 1.0 ... 1.0 1.0 Attributes: calliope_version_defined: 0.7.0 calliope_version_initialised: 0.7.0.dev2 applied_overrides: scenario: None defaults: {'available_area': inf, 'bigM': 1000000000... allow_operate_mode: 1 config: {'build': {'backend': 'pyomo', 'ensure_fea... applied_custom_math: [] math: {'constraints': {'flow_capacity_per_storag... name: National-scale example model
- costs: 1
- techs: 8
- nodes: 5
- carriers: 1
- timesteps: 120
- costs(costs)object'monetary'
array(['monetary'], dtype=object)
- techs(techs)object'battery' ... 'region1_to_region2'
array(['battery', 'ccgt', 'csp', 'demand_power', 'region1_to_region1_1', 'region1_to_region1_2', 'region1_to_region1_3', 'region1_to_region2'], dtype=object)
- carriers(carriers)object'power'
array(['power'], dtype=object)
- nodes(nodes)<U9'region1' 'region1_1' ... 'region2'
array(['region1', 'region1_1', 'region1_2', 'region1_3', 'region2'], dtype='<U9')
- timesteps(timesteps)datetime64[ns]2005-01-01 ... 2005-01-05T23:00:00
array(['2005-01-01T00:00:00.000000000', '2005-01-01T01:00:00.000000000', '2005-01-01T02:00:00.000000000', '2005-01-01T03:00:00.000000000', '2005-01-01T04:00:00.000000000', '2005-01-01T05:00:00.000000000', '2005-01-01T06:00:00.000000000', '2005-01-01T07:00:00.000000000', '2005-01-01T08:00:00.000000000', '2005-01-01T09:00:00.000000000', '2005-01-01T10:00:00.000000000', '2005-01-01T11:00:00.000000000', '2005-01-01T12:00:00.000000000', '2005-01-01T13:00:00.000000000', '2005-01-01T14:00:00.000000000', '2005-01-01T15:00:00.000000000', '2005-01-01T16:00:00.000000000', '2005-01-01T17:00:00.000000000', '2005-01-01T18:00:00.000000000', '2005-01-01T19:00:00.000000000', '2005-01-01T20:00:00.000000000', '2005-01-01T21:00:00.000000000', '2005-01-01T22:00:00.000000000', '2005-01-01T23:00:00.000000000', '2005-01-02T00:00:00.000000000', '2005-01-02T01:00:00.000000000', '2005-01-02T02:00:00.000000000', '2005-01-02T03:00:00.000000000', '2005-01-02T04:00:00.000000000', '2005-01-02T05:00:00.000000000', '2005-01-02T06:00:00.000000000', '2005-01-02T07:00:00.000000000', '2005-01-02T08:00:00.000000000', '2005-01-02T09:00:00.000000000', '2005-01-02T10:00:00.000000000', '2005-01-02T11:00:00.000000000', '2005-01-02T12:00:00.000000000', '2005-01-02T13:00:00.000000000', '2005-01-02T14:00:00.000000000', '2005-01-02T15:00:00.000000000', '2005-01-02T16:00:00.000000000', '2005-01-02T17:00:00.000000000', '2005-01-02T18:00:00.000000000', '2005-01-02T19:00:00.000000000', '2005-01-02T20:00:00.000000000', '2005-01-02T21:00:00.000000000', '2005-01-02T22:00:00.000000000', '2005-01-02T23:00:00.000000000', '2005-01-03T00:00:00.000000000', '2005-01-03T01:00:00.000000000', '2005-01-03T02:00:00.000000000', '2005-01-03T03:00:00.000000000', '2005-01-03T04:00:00.000000000', '2005-01-03T05:00:00.000000000', '2005-01-03T06:00:00.000000000', '2005-01-03T07:00:00.000000000', '2005-01-03T08:00:00.000000000', '2005-01-03T09:00:00.000000000', '2005-01-03T10:00:00.000000000', '2005-01-03T11:00:00.000000000', '2005-01-03T12:00:00.000000000', '2005-01-03T13:00:00.000000000', '2005-01-03T14:00:00.000000000', '2005-01-03T15:00:00.000000000', '2005-01-03T16:00:00.000000000', '2005-01-03T17:00:00.000000000', '2005-01-03T18:00:00.000000000', '2005-01-03T19:00:00.000000000', '2005-01-03T20:00:00.000000000', '2005-01-03T21:00:00.000000000', '2005-01-03T22:00:00.000000000', '2005-01-03T23:00:00.000000000', '2005-01-04T00:00:00.000000000', '2005-01-04T01:00:00.000000000', '2005-01-04T02:00:00.000000000', '2005-01-04T03:00:00.000000000', '2005-01-04T04:00:00.000000000', '2005-01-04T05:00:00.000000000', '2005-01-04T06:00:00.000000000', '2005-01-04T07:00:00.000000000', '2005-01-04T08:00:00.000000000', '2005-01-04T09:00:00.000000000', '2005-01-04T10:00:00.000000000', '2005-01-04T11:00:00.000000000', '2005-01-04T12:00:00.000000000', '2005-01-04T13:00:00.000000000', '2005-01-04T14:00:00.000000000', '2005-01-04T15:00:00.000000000', '2005-01-04T16:00:00.000000000', '2005-01-04T17:00:00.000000000', '2005-01-04T18:00:00.000000000', '2005-01-04T19:00:00.000000000', '2005-01-04T20:00:00.000000000', '2005-01-04T21:00:00.000000000', '2005-01-04T22:00:00.000000000', '2005-01-04T23:00:00.000000000', '2005-01-05T00:00:00.000000000', '2005-01-05T01:00:00.000000000', '2005-01-05T02:00:00.000000000', '2005-01-05T03:00:00.000000000', '2005-01-05T04:00:00.000000000', '2005-01-05T05:00:00.000000000', '2005-01-05T06:00:00.000000000', '2005-01-05T07:00:00.000000000', '2005-01-05T08:00:00.000000000', '2005-01-05T09:00:00.000000000', '2005-01-05T10:00:00.000000000', '2005-01-05T11:00:00.000000000', '2005-01-05T12:00:00.000000000', '2005-01-05T13:00:00.000000000', '2005-01-05T14:00:00.000000000', '2005-01-05T15:00:00.000000000', '2005-01-05T16:00:00.000000000', '2005-01-05T17:00:00.000000000', '2005-01-05T18:00:00.000000000', '2005-01-05T19:00:00.000000000', '2005-01-05T20:00:00.000000000', '2005-01-05T21:00:00.000000000', '2005-01-05T22:00:00.000000000', '2005-01-05T23:00:00.000000000'], dtype='datetime64[ns]')
- objective_cost_weights(costs)float641.0
- is_result :
- False
- default :
- 1
array([1.])
- bigM()float641e+06
- is_result :
- False
- default :
- 1000000000.0
array(1000000.)
- base_tech(techs)object'storage' ... 'transmission'
- is_result :
- False
array(['storage', 'supply', 'supply', 'demand', 'transmission', 'transmission', 'transmission', 'transmission'], dtype=object)
- carrier_in(nodes, techs, carriers)float64nan nan nan 1.0 ... nan nan nan 1.0
- is_result :
- False
array([[[nan], [nan], [nan], [ 1.], [ 1.], [ 1.], [ 1.], [ 1.]], [[nan], [nan], [nan], [nan], [ 1.], [nan], [nan], [nan]], [[nan], [nan], ... [nan], [nan]], [[nan], [nan], [nan], [nan], [nan], [nan], [ 1.], [nan]], [[ 1.], [nan], [nan], [ 1.], [nan], [nan], [nan], [ 1.]]])
- color(techs)object'#3B61E3' '#E37A72' ... '#8465A9'
- is_result :
- False
- default :
- nan
array(['#3B61E3', '#E37A72', '#F9CF22', '#072486', '#6783E3', '#6783E3', '#6783E3', '#8465A9'], dtype=object)
- name(techs)object'Battery storage' ... 'AC power ...
- is_result :
- False
- default :
- nan
array(['Battery storage', 'Combined cycle gas turbine', 'Concentrating solar power', 'Power demand', 'Local power transmission', 'Local power transmission', 'Local power transmission', 'AC power transmission'], dtype=object)
- carrier_out(nodes, techs, carriers)float64nan 1.0 nan nan ... nan nan nan 1.0
- is_result :
- False
array([[[nan], [ 1.], [nan], [nan], [ 1.], [ 1.], [ 1.], [ 1.]], [[nan], [nan], [ 1.], [nan], [ 1.], [nan], [nan], [nan]], [[nan], [nan], ... [nan], [nan]], [[nan], [nan], [ 1.], [nan], [nan], [nan], [ 1.], [nan]], [[ 1.], [nan], [nan], [nan], [nan], [nan], [nan], [ 1.]]])
- cost_area_use(techs, costs)float64nan nan 200.0 nan nan nan nan nan
- is_result :
- False
- default :
- 0
array([[ nan], [ nan], [200.], [ nan], [ nan], [ nan], [ nan], [ nan]])
- cost_flow_cap(techs, costs)float64nan 750.0 1e+03 ... nan nan 200.0
- is_result :
- False
- default :
- 0
array([[ nan], [ 750.], [1000.], [ nan], [ nan], [ nan], [ nan], [ 200.]])
- cost_flow_in(techs, costs)float64nan 0.02 nan nan nan nan nan nan
- is_result :
- False
- default :
- 0
array([[ nan], [0.02], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]])
- cost_flow_out(techs, costs)float64nan nan 0.002 nan nan nan nan 0.002
- is_result :
- False
- default :
- 0
array([[ nan], [ nan], [0.002], [ nan], [ nan], [ nan], [ nan], [0.002]])
- cost_interest_rate(techs, costs)float640.1 0.1 0.1 nan nan nan nan 0.1
- is_result :
- False
- default :
- 0
array([[0.1], [0.1], [0.1], [nan], [nan], [nan], [nan], [0.1]])
- cost_source_cap(techs, costs)float64nan nan 200.0 nan nan nan nan nan
- is_result :
- False
- default :
- 0
array([[ nan], [ nan], [200.], [ nan], [ nan], [ nan], [ nan], [ nan]])
- cost_storage_cap(techs, costs)float64200.0 nan 50.0 nan nan nan nan nan
- is_result :
- False
- default :
- 0
array([[200.], [ nan], [ 50.], [ nan], [ nan], [ nan], [ nan], [ nan]])
- flow_cap_max(nodes, techs)float64nan 3e+04 nan nan ... nan nan 1e+04
- is_result :
- False
- default :
- inf
array([[ nan, 30000., nan, nan, nan, nan, nan, 10000.], [ nan, nan, 10000., nan, nan, nan, nan, nan], [ nan, nan, 10000., nan, nan, nan, nan, nan], [ nan, nan, 10000., nan, nan, nan, nan, nan], [ 1000., nan, nan, nan, nan, nan, nan, 10000.]])
- flow_cap_max_systemwide(techs)float64nan 1e+05 nan nan nan nan nan nan
- is_result :
- False
- default :
- inf
array([ nan, 100000., nan, nan, nan, nan, nan, nan])
- flow_out_eff(techs)float640.95 0.5 0.4 nan nan nan nan 0.85
- is_result :
- False
- default :
- 1.0
array([0.95, 0.5 , 0.4 , nan, nan, nan, nan, 0.85])
- flow_ramping(techs)float64nan 0.8 nan nan nan nan nan nan
- is_result :
- False
- default :
- 1.0
array([nan, 0.8, nan, nan, nan, nan, nan, nan])
- lifetime(techs)float6425.0 25.0 25.0 nan nan nan nan 25.0
- is_result :
- False
- default :
- inf
array([25., 25., 25., nan, nan, nan, nan, 25.])
- techs_inheritance(techs)object'cost_dim_setter' ... 'cost_dim_...
- is_result :
- False
array(['cost_dim_setter', 'cost_dim_setter', 'cost_dim_setter', nan, 'free_transmission', 'free_transmission', 'free_transmission', 'cost_dim_setter'], dtype=object)
- area_use_max(techs)float64nan nan inf nan nan nan nan nan
- is_result :
- False
- default :
- inf
array([nan, nan, inf, nan, nan, nan, nan, nan])
- flow_cap_per_storage_cap_max(techs)float644.0 nan 1.0 nan nan nan nan nan
- is_result :
- False
- default :
- inf
array([ 4., nan, 1., nan, nan, nan, nan, nan])
- flow_out_parasitic_eff(techs)float64nan nan 0.9 nan nan nan nan nan
- is_result :
- False
- default :
- 1.0
array([nan, nan, 0.9, nan, nan, nan, nan, nan])
- include_storage(techs)float64nan nan 1.0 nan nan nan nan nan
- is_result :
- False
- default :
- False
array([nan, nan, 1., nan, nan, nan, nan, nan])
- source_unit(techs)objectnan nan 'per_area' ... nan nan nan
- is_result :
- False
- default :
- absolute
array([nan, nan, 'per_area', nan, nan, nan, nan, nan], dtype=object)
- storage_cap_max(techs)float64inf nan 6.14e+05 ... nan nan nan
- is_result :
- False
- default :
- inf
array([ inf, nan, 614033., nan, nan, nan, nan, nan])
- storage_loss(techs)float640.0 nan 0.002 nan nan nan nan nan
- is_result :
- False
- default :
- 0
array([0. , nan, 0.002, nan, nan, nan, nan, nan])
- flow_in_eff(techs)float640.95 nan nan nan nan nan nan nan
- is_result :
- False
- default :
- 1.0
array([0.95, nan, nan, nan, nan, nan, nan, nan])
- latitude(nodes)float6440.0 41.0 39.0 39.0 40.0
- is_result :
- False
array([40., 41., 39., 39., 40.])
- longitude(nodes)float64-2.0 -2.0 -1.0 -2.0 -8.0
- is_result :
- False
array([-2., -2., -1., -2., -8.])
- nodes_inheritance(nodes)objectnan 'csp_regions' ... nan
- is_result :
- False
array([nan, 'csp_regions', 'csp_regions', 'csp_regions', nan], dtype=object)
- source_use_max(timesteps, nodes, techs)float64nan nan nan nan ... nan nan nan nan
- is_result :
- False
- default :
- inf
array([[[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], ..., [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]]])
- sink_use_equals(timesteps, nodes, techs)float64nan nan nan ... nan nan nan
- is_result :
- False
- default :
- nan
array([[[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], ..., [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]]])
- definition_matrix(nodes, techs, carriers)boolFalse True False ... False True
- is_result :
- False
array([[[False], [ True], [False], [ True], [ True], [ True], [ True], [ True]], [[False], [False], [ True], [False], [ True], [False], [False], [False]], [[False], [False], ... [False], [False]], [[False], [False], [ True], [False], [False], [False], [ True], [False]], [[ True], [False], [False], [ True], [False], [False], [False], [ True]]])
- distance(techs)float64nan nan nan ... 140.4 111.0 512.3
- is_result :
- False
- default :
- nan
array([ nan, nan, nan, nan, 111.04426088, 140.44294774, 111.02504555, 512.26635523])
- timestep_resolution(timesteps)float641.0 1.0 1.0 1.0 ... 1.0 1.0 1.0 1.0
- is_result :
- False
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
- timestep_weights(timesteps)float641.0 1.0 1.0 1.0 ... 1.0 1.0 1.0 1.0
- is_result :
- False
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
- costsPandasIndex
PandasIndex(Index(['monetary'], dtype='object', name='costs'))
- techsPandasIndex
PandasIndex(Index(['battery', 'ccgt', 'csp', 'demand_power', 'region1_to_region1_1', 'region1_to_region1_2', 'region1_to_region1_3', 'region1_to_region2'], dtype='object', name='techs'))
- carriersPandasIndex
PandasIndex(Index(['power'], dtype='object', name='carriers'))
- nodesPandasIndex
PandasIndex(Index(['region1', 'region1_1', 'region1_2', 'region1_3', 'region2'], dtype='object', name='nodes'))
- timestepsPandasIndex
PandasIndex(DatetimeIndex(['2005-01-01 00:00:00', '2005-01-01 01:00:00', '2005-01-01 02:00:00', '2005-01-01 03:00:00', '2005-01-01 04:00:00', '2005-01-01 05:00:00', '2005-01-01 06:00:00', '2005-01-01 07:00:00', '2005-01-01 08:00:00', '2005-01-01 09:00:00', ... '2005-01-05 14:00:00', '2005-01-05 15:00:00', '2005-01-05 16:00:00', '2005-01-05 17:00:00', '2005-01-05 18:00:00', '2005-01-05 19:00:00', '2005-01-05 20:00:00', '2005-01-05 21:00:00', '2005-01-05 22:00:00', '2005-01-05 23:00:00'], dtype='datetime64[ns]', name='timesteps', length=120, freq=None))
- calliope_version_defined :
- 0.7.0
- calliope_version_initialised :
- 0.7.0.dev2
- applied_overrides :
- scenario :
- None
- defaults :
- {'available_area': inf, 'bigM': 1000000000.0, 'objective_cost_weights': 1, 'area_use': inf, 'area_use_max': inf, 'area_use_min': 0, 'area_use_per_flow_cap': nan, 'cap_method': 'continuous', 'color': nan, 'cost_area_use': 0, 'cost_depreciation_rate': 1, 'cost_export': 0, 'cost_flow_cap': 0, 'cost_flow_cap_per_distance': 0, 'cost_flow_in': 0, 'cost_flow_out': 0, 'cost_interest_rate': 0, 'cost_om_annual': 0, 'cost_om_annual_investment_fraction': 0, 'cost_purchase': 0, 'cost_purchase_per_distance': 0, 'cost_source_cap': 0, 'cost_storage_cap': 0, 'cyclic_storage': True, 'distance': nan, 'export_max': inf, 'flow_cap': inf, 'flow_cap_max': inf, 'flow_cap_max_systemwide': inf, 'flow_cap_min': 0, 'flow_cap_min_systemwide': 0, 'flow_cap_per_storage_cap_max': inf, 'flow_cap_per_storage_cap_min': 0, 'flow_cap_per_unit': nan, 'flow_in_eff': 1.0, 'flow_in_eff_per_distance': 1.0, 'flow_out_eff': 1.0, 'flow_out_eff_per_distance': 1.0, 'flow_out_min_relative': 0, 'flow_out_parasitic_eff': 1.0, 'flow_ramping': 1.0, 'force_async_flow': False, 'include_storage': False, 'integer_dispatch': False, 'lifetime': inf, 'name': nan, 'one_way': False, 'purchased_units': inf, 'purchased_units_max': inf, 'purchased_units_max_systemwide': inf, 'purchased_units_min': 0, 'purchased_units_min_systemwide': 0, 'sink_unit': 'absolute', 'sink_use_equals': nan, 'sink_use_max': inf, 'sink_use_min': 0, 'source_cap': inf, 'source_cap_equals_flow_cap': False, 'source_cap_max': inf, 'source_cap_min': 0, 'source_eff': 1.0, 'source_unit': 'absolute', 'source_use_equals': nan, 'source_use_max': inf, 'source_use_min': 0, 'storage_cap': inf, 'storage_cap_max': inf, 'storage_cap_min': 0, 'storage_cap_per_unit': nan, 'storage_discharge_depth': 0, 'storage_initial': 0, 'storage_loss': 0}
- allow_operate_mode :
- 1
- config :
- {'build': {'backend': 'pyomo', 'ensure_feasibility': True, 'mode': 'plan', 'objective': 'min_cost_optimisation', 'operate_use_cap_results': False}, 'solve': {'save_logs': None, 'solver': 'cbc', 'solver_io': None, 'solver_options': None, 'spores_number': 3, 'spores_save_per_spore': False, 'spores_score_cost_class': 'spores_score', 'spores_skip_cost_op': False, 'zero_threshold': 1e-10}}
- applied_custom_math :
- []
- math :
- {'constraints': {'flow_capacity_per_storage_capacity_min': {'description': 'Set the lower bound of storage flow capacity relative to its storage capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage_cap AND flow_cap_per_storage_cap_min', 'equations': [{'expression': 'flow_cap >= storage_cap * flow_cap_per_storage_cap_min'}]}, 'flow_capacity_per_storage_capacity_max': {'description': 'Set the upper bound of storage flow capacity relative to its storage capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage_cap AND flow_cap_per_storage_cap_max', 'equations': [{'expression': 'flow_cap <= storage_cap * flow_cap_per_storage_cap_max'}]}, 'source_capacity_equals_flow_capacity': {'description': "Set a `supply` technology's flow capacity to equal its source capacity.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'source_cap AND source_cap_equals_flow_cap=True', 'equations': [{'expression': 'source_cap == flow_cap'}]}, 'force_zero_area_use': {'description': "Set a technology's area use to zero if its flow capacity upper bound is zero.", 'foreach': ['nodes', 'techs'], 'where': 'area_use AND flow_cap_max=0', 'equations': [{'expression': 'area_use == 0'}]}, 'area_use_per_flow_capacity': {'description': "Set a fixed relationship between a technology's flow capacity and its area use.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'area_use AND area_use_per_flow_cap', 'equations': [{'expression': 'area_use == flow_cap * area_use_per_flow_cap'}]}, 'area_use_capacity_per_loc': {'description': 'Set an upper bound on the total area that all technologies with `area_use` can occupy at a given node.', 'foreach': ['nodes'], 'where': 'area_use AND available_area', 'equations': [{'expression': 'sum(area_use, over=techs) <= available_area'}]}, 'flow_capacity_systemwide_max': {'description': 'Set an upper bound on flow capacity of a technology across all nodes in which the technology exists.', 'foreach': ['techs', 'carriers'], 'where': 'flow_cap_max_systemwide', 'equations': [{'expression': 'sum(flow_cap, over=nodes) <= flow_cap_max_systemwide'}]}, 'flow_capacity_systemwide_min': {'description': 'Set a lower bound on flow capacity of a technology across all nodes in which the technology exists.', 'foreach': ['techs', 'carriers'], 'where': 'flow_cap_min_systemwide', 'equations': [{'expression': 'sum(flow_cap, over=nodes) >= flow_cap_min_systemwide'}]}, 'balance_conversion': {'description': "Fix the relationship between a `conversion` technology's outflow and consumption.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'base_tech=conversion AND NOT include_storage=true', 'equations': [{'expression': 'sum(flow_out_inc_eff, over=carriers) == sum(flow_in_inc_eff, over=carriers)'}]}, 'flow_out_max': {'description': "Set the upper bound of a technology's outflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_out AND NOT operating_units', 'equations': [{'expression': 'flow_out <= flow_cap * timestep_resolution * flow_out_parasitic_eff'}]}, 'flow_out_min': {'description': "Set the lower bound of a technology's outflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out_min_relative AND NOT operating_units', 'equations': [{'expression': 'flow_out >= flow_cap * timestep_resolution * flow_out_min_relative'}]}, 'flow_in_max': {'description': "Set the upper bound of a technology's inflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_in AND NOT operating_units', 'equations': [{'expression': 'flow_in <= flow_cap * timestep_resolution'}]}, 'source_max': {'description': "Set the upper bound of a `supply` technology's source consumption.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_cap', 'equations': [{'expression': 'source_use <= timestep_resolution * source_cap'}]}, 'storage_max': {'description': 'Set the upper bound of the amount of carrier a technology can store.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'storage', 'equations': [{'expression': 'storage <= storage_cap'}]}, 'storage_discharge_depth_limit': {'description': 'Set the lower bound of the stored carrier a technology must keep in reserve at all times.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'storage AND storage_discharge_depth', 'equations': [{'expression': 'storage - storage_discharge_depth * storage_cap >= 0'}]}, 'system_balance': {'description': 'Set the global carrier balance of the optimisation problem by fixing the total production of a given carrier to equal the total consumption of that carrier at every node in every timestep.', 'foreach': ['nodes', 'carriers', 'timesteps'], 'equations': [{'expression': 'sum(flow_out, over=techs) - sum(flow_in, over=techs) - $flow_export + $unmet_demand_and_unused_supply == 0'}], 'sub_expressions': {'flow_export': [{'where': 'any(carrier_export, over=techs)', 'expression': 'sum(flow_export, over=techs)'}, {'where': 'NOT any(carrier_export, over=techs)', 'expression': '0'}], 'unmet_demand_and_unused_supply': [{'where': 'config.ensure_feasibility=True', 'expression': 'unmet_demand + unused_supply'}, {'where': 'NOT config.ensure_feasibility=True', 'expression': '0'}]}}, 'balance_demand': {'description': 'Set the upper bound on, or a fixed total of, that a demand technology must dump to its sink in each timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'base_tech=demand', 'equations': [{'where': 'sink_use_equals', 'expression': 'flow_in_inc_eff == sink_use_equals * $sink_scaler'}, {'where': 'NOT sink_use_equals AND sink_use_max', 'expression': 'flow_in_inc_eff <= sink_use_max * $sink_scaler'}], 'sub_expressions': {'sink_scaler': [{'where': 'sink_unit=per_area', 'expression': 'area_use'}, {'where': 'sink_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'sink_unit=absolute', 'expression': '1'}]}}, 'balance_demand_min_use': {'description': 'Set the lower bound on the quantity of flow a `demand` technology must dump to its sink in each timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'sink_use_min AND NOT sink_use_equals AND base_tech=demand', 'equations': [{'expression': 'flow_in_inc_eff >= sink_use_min * $sink_scaler'}], 'sub_expressions': {'sink_scaler': [{'where': 'sink_unit=per_area', 'expression': 'area_use'}, {'where': 'sink_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'sink_unit=absolute', 'expression': '1'}]}}, 'balance_supply_no_storage': {'description': 'Fix the outflow of a `supply` technology to its consumption of the available source.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'base_tech=supply AND NOT include_storage=True', 'equations': [{'expression': 'flow_out_inc_eff == source_use * source_eff'}]}, 'balance_supply_with_storage': {'description': 'Fix the outflow of a `supply` technology to its consumption of the available source, with a storage buffer to temporally offset the outflow from source consumption.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'storage AND base_tech=supply', 'equations': [{'expression': 'storage == $storage_previous_step + source_use * source_eff - flow_out_inc_eff'}], 'sub_expressions': {'storage_previous_step': [{'where': 'timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True', 'expression': 'storage_initial * storage_cap'}, {'where': '(\n (timesteps=get_val_at_index(timesteps=0) AND cyclic_storage=True)\n OR NOT timesteps=get_val_at_index(timesteps=0)\n) AND NOT lookup_cluster_first_timestep=True', 'expression': '(1 - storage_loss) ** roll(timestep_resolution, timesteps=1) * roll(storage, timesteps=1)'}, {'where': 'lookup_cluster_first_timestep=True AND NOT (timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True)', 'expression': '(1 - storage_loss) ** select_from_lookup_arrays(timestep_resolution, timesteps=lookup_cluster_last_timestep) * select_from_lookup_arrays(storage, timesteps=lookup_cluster_last_timestep)'}]}}, 'source_availability_supply': {'description': "Set the upper bound on, or a fixed total of, a `supply` technology's ability to consume its available resource.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_use AND (source_use_equals OR source_use_max)', 'equations': [{'where': 'source_use_equals', 'expression': 'source_use == source_use_equals * $source_scaler'}, {'where': 'NOT source_use_equals AND source_use_max', 'expression': 'source_use <= source_use_max * $source_scaler'}], 'sub_expressions': {'source_scaler': [{'where': 'source_unit=per_area', 'expression': 'area_use'}, {'where': 'source_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'source_unit=absolute', 'expression': '1'}]}}, 'balance_supply_min_use': {'description': 'Set the lower bound on the quantity of its source a `supply` technology must use in each timestep.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_use_min AND NOT source_use_equals AND base_tech=supply', 'equations': [{'expression': 'source_use >= source_use_min * $source_scaler'}], 'sub_expressions': {'source_scaler': [{'where': 'source_unit=per_area', 'expression': 'area_use'}, {'where': 'source_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'source_unit=absolute', 'expression': '1'}]}}, 'balance_storage': {'description': 'Fix the quantity of carrier stored in a `storage` technology at the end of each timestep based on the net flow of carrier charged and discharged and the quantity of carrier stored at the start of the timestep.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': '(include_storage=true or base_tech=storage) AND NOT (base_tech=supply OR base_tech=demand)', 'equations': [{'expression': 'storage == $storage_previous_step -\n sum(flow_out_inc_eff, over=carriers) + sum(flow_in_inc_eff, over=carriers)'}], 'sub_expressions': {'storage_previous_step': [{'where': 'timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True', 'expression': 'storage_initial * storage_cap'}, {'where': '(\n (timesteps=get_val_at_index(timesteps=0) AND cyclic_storage=True)\n OR NOT timesteps=get_val_at_index(timesteps=0)\n) AND NOT lookup_cluster_first_timestep=True', 'expression': '(1 - storage_loss) ** roll(timestep_resolution, timesteps=1) * roll(storage, timesteps=1)'}, {'where': 'lookup_cluster_first_timestep=True AND NOT (timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True)', 'expression': '(1 - storage_loss) ** select_from_lookup_arrays(timestep_resolution, timesteps=lookup_cluster_last_timestep) * select_from_lookup_arrays(storage, timesteps=lookup_cluster_last_timestep)'}]}}, 'set_storage_initial': {'description': 'Fix the relationship between carrier stored in a `storage` technology at the start and end of the whole model period.', 'foreach': ['nodes', 'techs'], 'where': 'storage AND storage_initial AND cyclic_storage=True', 'equations': [{'expression': 'storage[timesteps=$final_step] * (\n (1 - storage_loss) ** timestep_resolution[timesteps=$final_step]\n) == storage_initial * storage_cap'}], 'slices': {'final_step': [{'expression': 'get_val_at_index(timesteps=-1)'}]}, 'active': True}, 'balance_transmission': {'description': 'Fix the relationship between between carrier flowing into and out of a `transmission` link in each timestep.', 'foreach': ['techs', 'timesteps'], 'where': 'base_tech=transmission', 'equations': [{'expression': 'sum(flow_out_inc_eff, over=[nodes, carriers]) == sum(flow_in_inc_eff, over=[nodes, carriers])'}]}, 'symmetric_transmission': {'description': 'Fix the flow capacity of two `transmission` technologies representing the same link in the system.', 'foreach': ['nodes', 'techs'], 'where': 'base_tech=transmission', 'equations': [{'expression': 'sum(flow_cap, over=carriers) == link_flow_cap'}]}, 'export_balance': {'description': "Set the lower bound of a technology's outflow to a technology's carrier export, for any technologies that can export carriers out of the system.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_export', 'equations': [{'expression': 'flow_out >= flow_export'}]}, 'flow_export_max': {'description': "Set the upper bound of a technology's carrier export, for any technologies that can export carriers out of the system.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_export AND export_max', 'equations': [{'where': 'operating_units', 'expression': 'flow_export <= export_max * operating_units'}, {'where': 'NOT operating_units', 'expression': 'flow_export <= export_max'}]}, 'unit_commitment_milp': {'description': 'Set the upper bound of the number of integer units of technology that can exist, for any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'operating_units AND purchased_units', 'equations': [{'expression': 'operating_units <= purchased_units'}]}, 'available_flow_cap_binary': {'description': 'Limit flow capacity to zero if the technology is not operating in a given timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap <= flow_cap_max * operating_units'}]}, 'available_flow_cap_continuous': {'description': 'Limit flow capacity to the value of the `flow_cap` decision variable when the technology is operating in a given timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap <= flow_cap'}]}, 'available_flow_cap_max_binary_continuous_switch': {'description': 'Force flow capacity to equal the value of the `flow_cap` decision variable if the technology is operating in a given timestep, zero otherwise.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap >= flow_cap + ((operating_units - purchased_units) * flow_cap_max)'}]}, 'flow_out_max_milp': {'description': "Set the upper bound of a technology's ability to produce carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out AND operating_units AND flow_cap_per_unit', 'equations': [{'expression': 'flow_out <= operating_units * timestep_resolution * flow_cap_per_unit * flow_out_parasitic_eff'}]}, 'flow_in_max_milp': {'description': "Set the upper bound of a technology's ability to consume carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_in AND operating_units AND flow_cap_per_unit', 'equations': [{'expression': 'flow_in <= operating_units * timestep_resolution * flow_cap_per_unit'}]}, 'flow_out_min_milp': {'description': "Set the lower bound of a technology's ability to produce carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out AND operating_units AND flow_out_min_relative', 'equations': [{'where': 'flow_cap_per_unit', 'expression': 'flow_out >= operating_units * timestep_resolution * flow_cap_per_unit * flow_out_min_relative'}, {'where': 'available_flow_cap', 'expression': 'flow_out >= available_flow_cap * timestep_resolution * flow_out_min_relative'}]}, 'storage_capacity_units_milp': {'description': 'Fix the storage capacity of any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage AND purchased_units AND storage_cap_per_unit', 'equations': [{'expression': 'storage_cap == purchased_units * storage_cap_per_unit'}]}, 'flow_capacity_units_milp': {'description': 'Fix the flow capacity of any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'operating_units', 'equations': [{'where': 'flow_cap_per_unit', 'expression': 'flow_cap == purchased_units * flow_cap_per_unit'}, {'where': 'NOT flow_cap_per_unit', 'expression': 'flow_cap <= purchased_units * bigM'}]}, 'flow_capacity_max_purchase_milp': {'description': "Set the upper bound on a technology's flow capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'purchased_units AND flow_cap_max', 'equations': [{'expression': 'flow_cap <= flow_cap_max * purchased_units'}]}, 'flow_capacity_min_purchase_milp': {'description': "Set the lower bound on a technology's flow capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'purchased_units AND flow_cap_min', 'equations': [{'expression': 'flow_cap >= flow_cap_min * purchased_units'}]}, 'storage_capacity_max_purchase_milp': {'description': "Set the upper bound on a technology's storage capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs'], 'where': 'purchased_units AND storage_cap_max', 'equations': [{'expression': 'storage_cap <= storage_cap_max * purchased_units'}]}, 'storage_capacity_min_purchase_milp': {'description': "Set the lower bound on a technology's storage capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs'], 'where': 'purchased_units AND storage_cap_min', 'equations': [{'expression': 'storage_cap >= storage_cap_min * purchased_units'}]}, 'unit_capacity_max_systemwide_milp': {'description': 'Set the upper bound on the total number of units of a technology that can be purchased across all nodes where the technology can exist, for any technology using integer units to define its capacity.', 'foreach': ['techs'], 'where': 'purchased_units AND purchased_units_max_systemwide', 'equations': [{'expression': 'sum(purchased_units, over=nodes) <= purchased_units_max_systemwide'}]}, 'unit_capacity_min_systemwide_milp': {'description': 'Set the lower bound on the total number of units of a technology that can be purchased across all nodes where the technology can exist, for any technology using integer units to define its capacity.', 'foreach': ['techs'], 'where': 'purchased_units AND purchased_units_max_systemwide', 'equations': [{'expression': 'sum(purchased_units, over=nodes) >= purchased_units_min_systemwide'}]}, 'async_flow_in_milp': {'description': "Set a technology's ability to have inflow in the same timestep that it has outflow, for any technology using the asynchronous flow binary switch.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'async_flow_switch', 'equations': [{'expression': 'sum(flow_in, over=carriers) <= (1 - async_flow_switch) * bigM'}]}, 'async_flow_out_milp': {'description': "Set a technology's ability to have outflow in the same timestep that it has inflow, for any technology using the asynchronous flow binary switch.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'async_flow_switch', 'equations': [{'expression': 'sum(flow_out, over=carriers) <= async_flow_switch * bigM'}]}, 'ramping_up': {'description': "Set the upper bound on a technology's ability to ramp outflow up beyond a certain percentage compared to the previous timestep.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_ramping AND NOT timesteps=get_val_at_index(timesteps=0)', 'equations': [{'expression': '$flow - roll($flow, timesteps=1) <= flow_ramping * flow_cap'}], 'sub_expressions': {'flow': [{'where': 'carrier_out AND NOT carrier_in', 'expression': 'flow_out / timestep_resolution'}, {'where': 'carrier_in AND NOT carrier_out', 'expression': 'flow_in / timestep_resolution'}, {'where': 'carrier_in AND carrier_out', 'expression': '(flow_out - flow_in) / timestep_resolution'}]}}, 'ramping_down': {'description': "Set the upper bound on a technology's ability to ramp outflow down beyond a certain percentage compared to the previous timestep.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_ramping AND NOT timesteps=get_val_at_index(timesteps=0)', 'equations': [{'expression': '-1 * flow_ramping * flow_cap <= $flow - roll($flow, timesteps=1)'}], 'sub_expressions': {'flow': [{'where': 'carrier_out AND NOT carrier_in', 'expression': 'flow_out / timestep_resolution'}, {'where': 'carrier_in AND NOT carrier_out', 'expression': 'flow_in / timestep_resolution'}, {'where': 'carrier_in AND carrier_out', 'expression': '(flow_out - flow_in) / timestep_resolution'}]}}}, 'variables': {'flow_cap': {'description': "A technology's flow capacity, also known as its nominal or nameplate capacity.", 'unit': 'power', 'foreach': ['nodes', 'techs', 'carriers'], 'bounds': {'min': 'flow_cap_min', 'max': 'flow_cap_max'}}, 'link_flow_cap': {'description': "A transmission technology's flow capacity, also known as its nominal or nameplate capacity.", 'unit': 'power', 'foreach': ['techs'], 'where': 'base_tech=transmission', 'bounds': {'min': 0, 'max': inf}}, 'flow_out': {'description': 'The outflow of a technology per timestep, also known as the flow discharged (from `storage` technologies) or the flow received (by `transmission` technologies) on a link.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_out', 'bounds': {'min': 0, 'max': inf}}, 'flow_in': {'description': 'The inflow to a technology per timestep, also known as the flow consumed (by `storage` technologies) or the flow sent (by `transmission` technologies) on a link.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_in', 'bounds': {'min': 0, 'max': inf}}, 'flow_export': {'description': 'The flow of a carrier exported outside the system boundaries by a technology per timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_export', 'bounds': {'min': 0, 'max': inf}}, 'area_use': {'description': 'The area in space utilised directly (e.g., solar PV panels) or indirectly (e.g., biofuel crops) by a technology.', 'unit': 'area', 'foreach': ['nodes', 'techs'], 'where': '(area_use_min OR area_use_max OR area_use_per_flow_cap OR sink_unit=per_area OR source_unit=per_area)', 'bounds': {'min': 'area_use_min', 'max': 'area_use_max'}}, 'source_use': {'description': 'The carrier flow consumed from outside the system boundaries by a `supply` technology.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'base_tech=supply', 'bounds': {'min': 0, 'max': inf}}, 'source_cap': {'description': 'The upper limit on a flow that can be consumed from outside the system boundaries by a `supply` technology in each timestep.', 'unit': 'power', 'foreach': ['nodes', 'techs'], 'where': 'base_tech=supply', 'bounds': {'min': 'source_cap_min', 'max': 'source_cap_max'}}, 'storage_cap': {'description': 'The upper limit on a carrier that can be stored by a technology in any timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs'], 'where': 'include_storage=True OR base_tech=storage', 'domain': 'real', 'bounds': {'min': 'storage_cap_min', 'max': 'storage_cap_max'}, 'active': True}, 'storage': {'description': 'The carrier stored by a `storage` technology in each timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'include_storage=True OR base_tech=storage', 'bounds': {'min': 0, 'max': inf}}, 'purchased_units': {'description': 'Integer number of a technology that has been purchased,\nfor any technology set to require integer capacity purchasing.\nThis is used to allow installation of fixed capacity units of technologies (\nif `flow_cap_max` == `flow_cap_min`) and/or to set a fixed cost for a technology,\nirrespective of its installed capacity.\nOn top of a fixed technology cost,\na continuous cost for the quantity of installed capacity can still be applied.\n\nSince technology capacity is no longer a continuous decision variable,\nit is possible for these technologies to have a lower bound set on outflow/consumption\nwhich will only be enforced in those timesteps that the technology is operating.\nOtherwise, the same lower bound forces the technology to produce/consume\nthat minimum amount of carrier in *every* timestep.\n', 'unit': 'integer', 'foreach': ['nodes', 'techs'], 'where': 'cap_method=integer', 'domain': 'integer', 'bounds': {'min': 'purchased_units_min', 'max': 'purchased_units_max'}}, 'operating_units': {'description': 'Integer number of a technology that is operating in each timestep, for any technology set to require integer capacity purchasing.', 'unit': 'integer', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'integer_dispatch=True AND cap_method=integer', 'domain': 'integer', 'bounds': {'min': 0, 'max': inf}}, 'available_flow_cap': {'description': 'Flow capacity that will be set to zero if the technology is not operating in a given timestep and will be set to the value of the decision variable `flow_cap` otherwise.', 'unit': 'power', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'integer_dispatch=True AND flow_cap_max AND NOT flow_cap_per_unit', 'bounds': {'min': 0, 'max': inf}}, 'async_flow_switch': {'description': 'Binary switch to force asynchronous outflow/consumption of technologies with both `flow_in` and `flow_out` defined. This ensures that a technology with carrier flow efficiencies < 100% cannot produce and consume a flow simultaneously to remove unwanted carrier from the system.', 'unit': 'integer', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'force_async_flow=True', 'domain': 'integer', 'bounds': {'min': 0, 'max': 1}}, 'unmet_demand': {'description': 'Virtual source of carrier flow to ensure model feasibility. This should only be considered a debugging rather than a modelling tool as it may distort the model in other ways due to the large impact it has on the objective function value. When present in a model in which it has been requested, it indicates an inability for technologies in the model to reach a sufficient combined supply capacity to meet demand.', 'unit': 'energy', 'foreach': ['nodes', 'carriers', 'timesteps'], 'where': 'config.ensure_feasibility=True', 'bounds': {'min': 0, 'max': inf}}, 'unused_supply': {'description': 'Virtual sink of carrier flow to ensure model feasibility. This should only be considered a debugging rather than a modelling tool as it may distort the model in other ways due to the large impact it has on the objective function value. In model results, the negation of this variable is combined with `unmet_demand` and presented as only one variable: `unmet_demand`. When present in a model in which it has been requested, it indicates an inability for technologies in the model to reach a sufficient combined consumption capacity to meet required outflow (e.g. from renewables without the possibility of curtailment).', 'unit': 'energy', 'foreach': ['nodes', 'carriers', 'timesteps'], 'where': 'config.ensure_feasibility=True', 'bounds': {'min': -inf, 'max': 0}}}, 'objectives': {'min_cost_optimisation': {'description': 'Minimise the total cost of installing and operating all technologies in the system. If multiple cost classes are present (e.g., monetary and co2 emissions), the weighted sum of total costs is minimised. Cost class weights can be defined in the indexed parameter `objective_cost_weights`.', 'equations': [{'where': 'any(cost, over=[nodes, techs, costs])', 'expression': 'sum(\n sum(cost, over=[nodes, techs])\n * objective_cost_weights,\n over=costs\n) + $unmet_demand'}, {'where': 'NOT any(cost, over=[nodes, techs, costs])', 'expression': '$unmet_demand'}], 'sub_expressions': {'unmet_demand': [{'where': 'config.ensure_feasibility=True', 'expression': 'sum(\n sum(unmet_demand - unused_supply, over=[carriers, nodes])\n * timestep_weights,\n over=timesteps\n) * bigM'}, {'where': 'NOT config.ensure_feasibility=True', 'expression': '0'}]}, 'sense': 'minimise', 'active': True}}, 'global_expressions': {'flow_out_inc_eff': {'description': 'Outflows after taking efficiency losses into account.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out', 'equations': [{'where': 'base_tech=transmission', 'expression': 'flow_out / (\n flow_out_eff * flow_out_parasitic_eff *\n flow_out_eff_per_distance ** default_if_empty(distance, 1)\n)'}, {'where': 'NOT base_tech=transmission', 'expression': 'flow_out / (flow_out_eff * flow_out_parasitic_eff)'}]}, 'flow_in_inc_eff': {'description': 'Inflows after taking efficiency losses into account.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_in', 'equations': [{'where': 'base_tech=transmission', 'expression': 'flow_in * flow_in_eff * flow_in_eff_per_distance ** default_if_empty(distance, 1)'}, {'where': 'NOT base_tech=transmission', 'expression': 'flow_in * flow_in_eff'}]}, 'cost_var': {'description': 'The operating costs per timestep of a technology.', 'unit': 'cost_per_time', 'foreach': ['nodes', 'techs', 'costs', 'timesteps'], 'where': 'cost_export OR cost_flow_in OR cost_flow_out', 'equations': [{'expression': 'timestep_weights * ($cost_export + $cost_flow_out + $cost_flow_in)'}], 'sub_expressions': {'cost_export': [{'where': 'flow_export', 'expression': 'sum(cost_export * default_if_empty(flow_export, 0), over=carriers)'}, {'where': 'NOT flow_export', 'expression': '0'}], 'cost_flow_in': [{'where': 'base_tech=supply', 'expression': 'cost_flow_in * source_use'}, {'where': 'NOT base_tech=supply', 'expression': 'sum(cost_flow_in * default_if_empty(flow_in, 0), over=carriers)'}], 'cost_flow_out': [{'expression': 'sum(cost_flow_out * default_if_empty(flow_out, 0), over=carriers)'}]}}, 'cost_investment_flow_cap': {'description': 'The investment costs associated with the nominal/rated capacity of a technology.', 'foreach': ['nodes', 'techs', 'carriers', 'costs'], 'where': 'flow_cap AND (cost_flow_cap OR cost_flow_cap_per_distance)', 'equations': [{'expression': '$cost_sum * flow_cap'}], 'sub_expressions': {'cost_sum': [{'where': 'base_tech=transmission', 'expression': '(cost_flow_cap + cost_flow_cap_per_distance * default_if_empty(distance, 0)) * 0.5'}, {'where': 'NOT base_tech=transmission', 'expression': 'cost_flow_cap'}]}}, 'cost_investment_storage_cap': {'description': 'The investment costs associated with the storage capacity of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_storage_cap AND storage_cap', 'equations': [{'expression': 'cost_storage_cap * storage_cap'}]}, 'cost_investment_source_cap': {'description': 'The investment costs associated with the source consumption capacity of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_source_cap AND source_cap', 'equations': [{'expression': 'cost_source_cap * source_cap'}]}, 'cost_investment_area_use': {'description': 'The investment costs associated with the area used by a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_area_use AND area_use', 'equations': [{'expression': 'cost_area_use * area_use'}]}, 'cost_investment_purchase': {'description': 'The investment costs associated with the binary purchase of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_purchase AND purchased_units', 'equations': [{'where': 'base_tech=transmission', 'expression': '(cost_purchase + cost_purchase_per_distance * default_if_empty(distance, 0)) * purchased_units * 0.5'}, {'where': 'NOT base_tech=transmission', 'expression': 'cost_purchase * purchased_units'}]}, 'cost_investment': {'description': 'The installation costs of a technology, including annualised investment costs and annual maintenance costs.', 'unit': 'cost', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_investment_flow_cap OR cost_investment_storage_cap OR cost_investment_source_cap OR cost_investment_area_use OR cost_investment_purchase', 'equations': [{'expression': '$annualisation_weight * (\n $depreciation_rate * (\n sum(default_if_empty(cost_investment_flow_cap, 0), over=carriers) +\n default_if_empty(cost_investment_storage_cap, 0) +\n default_if_empty(cost_investment_source_cap, 0) +\n default_if_empty(cost_investment_area_use, 0) +\n default_if_empty(cost_investment_purchase, 0)\n ) * (1 + cost_om_annual_investment_fraction)\n + sum(cost_om_annual * default_if_empty(flow_cap, 0), over=carriers)\n)\n'}], 'sub_expressions': {'annualisation_weight': [{'expression': 'sum(timestep_resolution * timestep_weights, over=timesteps) / 8760'}], 'depreciation_rate': [{'where': 'cost_depreciation_rate', 'expression': 'cost_depreciation_rate'}, {'where': 'NOT cost_depreciation_rate AND cost_interest_rate=0', 'expression': '1 / lifetime'}, {'where': 'NOT cost_depreciation_rate AND cost_interest_rate>0', 'expression': '(cost_interest_rate * ((1 + cost_interest_rate) ** lifetime)) / (((1 + cost_interest_rate) ** lifetime) - 1)'}]}}, 'cost': {'description': 'The total annualised costs of a technology, including installation and operation costs.', 'unit': 'cost', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_investment OR cost_var', 'equations': [{'expression': '$cost_investment + $cost_var_sum'}], 'sub_expressions': {'cost_investment': [{'where': 'cost_investment', 'expression': 'cost_investment'}, {'where': 'NOT cost_investment', 'expression': '0'}], 'cost_var_sum': [{'where': 'cost_var', 'expression': 'sum(cost_var, over=timesteps)'}, {'where': 'NOT cost_var', 'expression': '0'}]}, 'active': True}}}
- name :
- National-scale example model
Individual data variables can be accessed easily, to_series().dropna()
allows us to view the data in a nice tabular format.
model.inputs.flow_cap_max.to_series().dropna()
nodes techs region1 ccgt 30000.0 region1_to_region2 10000.0 region1_1 csp 10000.0 region1_2 csp 10000.0 region1_3 csp 10000.0 region2 battery 1000.0 region1_to_region2 10000.0 Name: flow_cap_max, dtype: float64
You can apply node/tech/carrier/timesteps only operations, like summing information over timesteps
model.inputs.sink_use_equals.sum(
"timesteps", min_count=1, skipna=True
).to_series().dropna()
nodes techs region1 demand_power 3793748.48 region2 demand_power 288114.75 Name: sink_use_equals, dtype: float64
Build and solve the optimisation problem.¶
Results are loaded into model.results
.
By setting the log verbosity at the start of this tutorial to "INFO", we can see the timing of parts of the run, as well as the solver's log.
model.build()
model.solve()
[2024-01-27 14:24:43] INFO Optimisation Model | parameters | Generated.
[2024-01-27 14:24:43] INFO Optimisation Model | variables | Generated.
[2024-01-27 14:24:44] INFO Optimisation Model | global_expressions | Generated.
[2024-01-27 14:24:46] INFO Optimisation Model | constraints | Generated.
[2024-01-27 14:24:46] INFO Optimisation Model | objectives | Generated.
[2024-01-27 14:24:46] INFO Optimisation model | starting model in plan mode.
[2024-01-27 14:24:47] INFO Backend: solver finished running. Time since start of solving optimisation problem: 0:00:00.635795
[2024-01-27 14:24:47] INFO Postprocessing: started
[2024-01-27 14:24:47] INFO Postprocessing: All values < 1e-10 set to 0 in flow_out, flow_in, storage, flow_out_inc_eff, flow_in_inc_eff, capacity_factor
[2024-01-27 14:24:47] INFO Postprocessing: ended. Time since start of solving optimisation problem: 0:00:00.808240
[2024-01-27 14:24:47] INFO Model: loaded model_data
Model results are held in the same structure as model inputs. The results consist of the optimal values for all decision variables, including capacities and carrier flow. There are also results, like system capacity factor and levelised costs, which are calculated in postprocessing before being added to the results Dataset
Examine results¶
model.results
<xarray.Dataset> Dimensions: (nodes: 5, techs: 8, carriers: 1, timesteps: 120, costs: 1) Coordinates: * techs (techs) object 'battery' ... 'region1_to_reg... * carriers (carriers) <U5 'power' * nodes (nodes) <U9 'region1' 'region1_1' ... 'region2' * timesteps (timesteps) datetime64[ns] 2005-01-01 ... 20... * costs (costs) object 'monetary' Data variables: (12/23) flow_cap (nodes, techs, carriers) float64 nan ... 3.2... link_flow_cap (techs) float64 nan nan ... 2.28e+03 3.23e+03 flow_out (nodes, techs, carriers, timesteps) float64 ... flow_in (nodes, techs, carriers, timesteps) float64 ... area_use (nodes, techs) float64 nan nan nan ... nan nan source_use (nodes, techs, timesteps) float64 nan ... nan ... ... cost_investment (nodes, techs, costs) float64 nan ... 487.5 cost (nodes, techs, costs) float64 nan ... 1.067e+03 capacity_factor (nodes, techs, carriers, timesteps) float64 ... systemwide_capacity_factor (techs, carriers) float64 0.1317 ... 0.3738 systemwide_levelised_cost (carriers, techs, costs) float64 0.1 ... 0.0... total_levelised_cost (carriers, costs) float64 0.06701 Attributes: termination_condition: optimal calliope_version_defined: 0.7.0 calliope_version_initialised: 0.7.0.dev2 applied_overrides: scenario: None defaults: {'available_area': inf, 'bigM': 1000000000... allow_operate_mode: 1 config: {'build': {'backend': 'pyomo', 'ensure_fea... applied_custom_math: [] math: {'constraints': {'flow_capacity_per_storag... name: National-scale example model
- nodes: 5
- techs: 8
- carriers: 1
- timesteps: 120
- costs: 1
- techs(techs)object'battery' ... 'region1_to_region2'
array(['battery', 'ccgt', 'csp', 'demand_power', 'region1_to_region1_1', 'region1_to_region1_2', 'region1_to_region1_3', 'region1_to_region2'], dtype=object)
- carriers(carriers)<U5'power'
array(['power'], dtype='<U5')
- nodes(nodes)<U9'region1' 'region1_1' ... 'region2'
array(['region1', 'region1_1', 'region1_2', 'region1_3', 'region2'], dtype='<U9')
- timesteps(timesteps)datetime64[ns]2005-01-01 ... 2005-01-05T23:00:00
array(['2005-01-01T00:00:00.000000000', '2005-01-01T01:00:00.000000000', '2005-01-01T02:00:00.000000000', '2005-01-01T03:00:00.000000000', '2005-01-01T04:00:00.000000000', '2005-01-01T05:00:00.000000000', '2005-01-01T06:00:00.000000000', '2005-01-01T07:00:00.000000000', '2005-01-01T08:00:00.000000000', '2005-01-01T09:00:00.000000000', '2005-01-01T10:00:00.000000000', '2005-01-01T11:00:00.000000000', '2005-01-01T12:00:00.000000000', '2005-01-01T13:00:00.000000000', '2005-01-01T14:00:00.000000000', '2005-01-01T15:00:00.000000000', '2005-01-01T16:00:00.000000000', '2005-01-01T17:00:00.000000000', '2005-01-01T18:00:00.000000000', '2005-01-01T19:00:00.000000000', '2005-01-01T20:00:00.000000000', '2005-01-01T21:00:00.000000000', '2005-01-01T22:00:00.000000000', '2005-01-01T23:00:00.000000000', '2005-01-02T00:00:00.000000000', '2005-01-02T01:00:00.000000000', '2005-01-02T02:00:00.000000000', '2005-01-02T03:00:00.000000000', '2005-01-02T04:00:00.000000000', '2005-01-02T05:00:00.000000000', '2005-01-02T06:00:00.000000000', '2005-01-02T07:00:00.000000000', '2005-01-02T08:00:00.000000000', '2005-01-02T09:00:00.000000000', '2005-01-02T10:00:00.000000000', '2005-01-02T11:00:00.000000000', '2005-01-02T12:00:00.000000000', '2005-01-02T13:00:00.000000000', '2005-01-02T14:00:00.000000000', '2005-01-02T15:00:00.000000000', '2005-01-02T16:00:00.000000000', '2005-01-02T17:00:00.000000000', '2005-01-02T18:00:00.000000000', '2005-01-02T19:00:00.000000000', '2005-01-02T20:00:00.000000000', '2005-01-02T21:00:00.000000000', '2005-01-02T22:00:00.000000000', '2005-01-02T23:00:00.000000000', '2005-01-03T00:00:00.000000000', '2005-01-03T01:00:00.000000000', '2005-01-03T02:00:00.000000000', '2005-01-03T03:00:00.000000000', '2005-01-03T04:00:00.000000000', '2005-01-03T05:00:00.000000000', '2005-01-03T06:00:00.000000000', '2005-01-03T07:00:00.000000000', '2005-01-03T08:00:00.000000000', '2005-01-03T09:00:00.000000000', '2005-01-03T10:00:00.000000000', '2005-01-03T11:00:00.000000000', '2005-01-03T12:00:00.000000000', '2005-01-03T13:00:00.000000000', '2005-01-03T14:00:00.000000000', '2005-01-03T15:00:00.000000000', '2005-01-03T16:00:00.000000000', '2005-01-03T17:00:00.000000000', '2005-01-03T18:00:00.000000000', '2005-01-03T19:00:00.000000000', '2005-01-03T20:00:00.000000000', '2005-01-03T21:00:00.000000000', '2005-01-03T22:00:00.000000000', '2005-01-03T23:00:00.000000000', '2005-01-04T00:00:00.000000000', '2005-01-04T01:00:00.000000000', '2005-01-04T02:00:00.000000000', '2005-01-04T03:00:00.000000000', '2005-01-04T04:00:00.000000000', '2005-01-04T05:00:00.000000000', '2005-01-04T06:00:00.000000000', '2005-01-04T07:00:00.000000000', '2005-01-04T08:00:00.000000000', '2005-01-04T09:00:00.000000000', '2005-01-04T10:00:00.000000000', '2005-01-04T11:00:00.000000000', '2005-01-04T12:00:00.000000000', '2005-01-04T13:00:00.000000000', '2005-01-04T14:00:00.000000000', '2005-01-04T15:00:00.000000000', '2005-01-04T16:00:00.000000000', '2005-01-04T17:00:00.000000000', '2005-01-04T18:00:00.000000000', '2005-01-04T19:00:00.000000000', '2005-01-04T20:00:00.000000000', '2005-01-04T21:00:00.000000000', '2005-01-04T22:00:00.000000000', '2005-01-04T23:00:00.000000000', '2005-01-05T00:00:00.000000000', '2005-01-05T01:00:00.000000000', '2005-01-05T02:00:00.000000000', '2005-01-05T03:00:00.000000000', '2005-01-05T04:00:00.000000000', '2005-01-05T05:00:00.000000000', '2005-01-05T06:00:00.000000000', '2005-01-05T07:00:00.000000000', '2005-01-05T08:00:00.000000000', '2005-01-05T09:00:00.000000000', '2005-01-05T10:00:00.000000000', '2005-01-05T11:00:00.000000000', '2005-01-05T12:00:00.000000000', '2005-01-05T13:00:00.000000000', '2005-01-05T14:00:00.000000000', '2005-01-05T15:00:00.000000000', '2005-01-05T16:00:00.000000000', '2005-01-05T17:00:00.000000000', '2005-01-05T18:00:00.000000000', '2005-01-05T19:00:00.000000000', '2005-01-05T20:00:00.000000000', '2005-01-05T21:00:00.000000000', '2005-01-05T22:00:00.000000000', '2005-01-05T23:00:00.000000000'], dtype='datetime64[ns]')
- costs(costs)object'monetary'
array(['monetary'], dtype=object)
- flow_cap(nodes, techs, carriers)float64nan 3e+04 nan ... nan nan 3.23e+03
- description :
- A technology's flow capacity, also known as its nominal or nameplate capacity.
- unit :
- power
- is_result :
- 1
array([[[ nan], [30000. ], [ nan], [39033.52 ], [ 9000. ], [ 0. ], [ 2280.3859], [ 3230.4729]], [[ nan], [ nan], [10000. ], [ nan], [ 9000. ], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 2533.7621], [ nan], [ nan], [ nan], [ 2280.3859], [ nan]], [[ 1000. ], [ nan], [ nan], [ 2909.836 ], [ nan], [ nan], [ nan], [ 3230.4729]]])
- link_flow_cap(techs)float64nan nan nan ... 2.28e+03 3.23e+03
- description :
- A transmission technology's flow capacity, also known as its nominal or nameplate capacity.
- unit :
- power
- is_result :
- 1
array([ nan, nan, nan, nan, 9000. , -0. , 2280.3859, 3230.4729])
- flow_out(nodes, techs, carriers, timesteps)float64nan nan nan ... 2.254e+03 2.295e+03
- description :
- The outflow of a technology per timestep, also known as the flow discharged (from `storage` technologies) or the flow received (by `transmission` technologies) on a link.
- unit :
- energy
- is_result :
- 1
array([[[[ nan, nan, nan, ..., nan, nan, nan]], [[27936.36 , 26894.673 , 26189.672 , ..., 25234.128 , 23042.504 , 22834.531 ]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]]], ... [[[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 2254.098 , 2131.148 , 2090.164 , ..., 2459.016 , 2254.098 , 2295.082 ]]]])
- flow_in(nodes, techs, carriers, timesteps)float64nan nan nan nan ... 0.0 0.0 0.0 0.0
- description :
- The inflow to a technology per timestep, also known as the flow consumed (by `storage` technologies) or the flow sent (by `transmission` technologies) on a link.
- unit :
- energy
- is_result :
- 1
array([[[[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[2651.88 , 2507.2329, 2459.0165, ..., 2892.96 , 2651.88 , 2700.0965]]], ... [[[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]]]])
- area_use(nodes, techs)float64nan nan nan nan ... nan nan nan nan
- description :
- The area in space utilised directly (e.g., solar PV panels) or indirectly (e.g., biofuel crops) by a technology.
- unit :
- area
- is_result :
- 1
array([[ nan, nan, nan, nan, nan, nan, nan, nan], [ nan, nan, 130384.99 , nan, nan, nan, nan, nan], [ nan, nan, 0. , nan, nan, nan, nan, nan], [ nan, nan, 8486.0609, nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan, nan, nan, nan]])
- source_use(nodes, techs, timesteps)float64nan nan nan nan ... nan nan nan nan
- description :
- The carrier flow consumed from outside the system boundaries by a `supply` technology.
- unit :
- energy
- is_result :
- 1
array([[[ nan, nan, nan, ..., nan, nan, nan], [55872.72 , 53789.346, 52379.345, ..., 50468.256, 46085.008, 45669.062], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ 0. , 0. , 0. , ..., 0. , 0. , 0. ], ... [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]])
- source_cap(nodes, techs)float64nan 6e+04 nan nan ... nan nan nan
- description :
- The upper limit on a flow that can be consumed from outside the system boundaries by a `supply` technology in each timestep.
- unit :
- power
- is_result :
- 1
array([[ nan, 60000. , nan, nan, nan, nan, nan, nan], [ nan, nan, 67215.287 , nan, nan, nan, nan, nan], [ nan, nan, 0. , nan, nan, nan, nan, nan], [ nan, nan, 2291.9577, nan, nan, nan, nan, nan], [ nan, nan, nan, nan, nan, nan, nan, nan]])
- storage_cap(nodes, techs)float64nan nan nan nan ... nan nan nan nan
- description :
- The upper limit on a carrier that can be stored by a technology in any timestep.
- unit :
- energy
- is_result :
- 1
array([[ nan, nan, nan, nan, nan, nan, nan, nan], [ nan, nan, 244300.4 , nan, nan, nan, nan, nan], [ nan, nan, 0. , nan, nan, nan, nan, nan], [ nan, nan, 25300.418 , nan, nan, nan, nan, nan], [ 5239.2461, nan, nan, nan, nan, nan, nan, nan]])
- storage(nodes, techs, timesteps)float64nan nan nan nan ... nan nan nan nan
- description :
- The carrier stored by a `storage` technology in each timestep.
- unit :
- energy
- is_result :
- 1
array([[[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ 0. , 0. , 0. , ..., 47357.277, 22262.562, 0. ], ... [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], ..., [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan], [ nan, nan, nan, ..., nan, nan, nan]]])
- unmet_demand(nodes, carriers, timesteps)float640.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
- is_result :
- 1
array([[[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., ... 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], [[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]]])
- flow_out_inc_eff(nodes, techs, carriers, timesteps)float64nan nan nan ... 2.652e+03 2.7e+03
- description :
- Outflows after taking efficiency losses into account.
- is_result :
- 1
array([[[[ nan, nan, nan, ..., nan, nan, nan]], [[55872.72 , 53789.346 , 52379.344 , ..., 50468.256 , 46085.008 , 45669.062 ]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]]], ... [[[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 2651.88 , 2507.23294118, 2459.01647059, ..., 2892.96 , 2651.88 , 2700.09647059]]]])
- flow_in_inc_eff(nodes, techs, carriers, timesteps)float64nan nan nan nan ... 0.0 0.0 0.0 0.0
- description :
- Inflows after taking efficiency losses into account.
- is_result :
- 1
array([[[[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[2651.88 , 2507.2329, 2459.0165, ..., 2892.96 , 2651.88 , 2700.0965]]], ... [[[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]]]])
- cost_var(nodes, techs, costs, timesteps)float64nan nan nan ... 4.918 4.508 4.59
- description :
- The operating costs per timestep of a technology.
- unit :
- cost_per_time
- is_result :
- 1
array([[[[ nan, nan, nan, ..., nan, nan, nan]], [[1117.4544 , 1075.78692 , 1047.5869 , ..., 1009.36512 , 921.70016 , 913.38124 ]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 0. , 0. , 0. , ..., 0. , 0. , 0. ]]], ... [[[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], ..., [[ nan, nan, nan, ..., nan, nan, nan]], [[ nan, nan, nan, ..., nan, nan, nan]], [[ 4.508196 , 4.262296 , 4.180328 , ..., 4.918032 , 4.508196 , 4.590164 ]]]])
- cost_investment_flow_cap(nodes, techs, carriers, costs)float64nan 2.25e+07 nan ... nan 3.23e+05
- description :
- The investment costs associated with the nominal/rated capacity of a technology.
- is_result :
- 1
array([[[[ nan]], [[22500000. ]], [[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ 323047.29]]], [[[ nan]], [[ nan]], ... [[ nan]], [[ nan]]], [[[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ nan]], [[ 323047.29]]]])
- cost_investment_storage_cap(nodes, techs, costs)float64nan nan nan nan ... nan nan nan nan
- description :
- The investment costs associated with the storage capacity of a technology.
- is_result :
- 1
array([[[ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], [12215020. ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 1265020.9 ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ 1047849.22], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]]])
- cost_investment_source_cap(nodes, techs, costs)float64nan nan nan nan ... nan nan nan nan
- description :
- The investment costs associated with the source consumption capacity of a technology.
- is_result :
- 1
array([[[ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], [13443057.4 ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 458391.54], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]]])
- cost_investment_area_use(nodes, techs, costs)float64nan nan nan nan ... nan nan nan nan
- description :
- The investment costs associated with the area used by a technology.
- is_result :
- 1
array([[[ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], [26076998. ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 1697212.18], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan]]])
- cost_investment(nodes, techs, costs)float64nan 3.396e+04 nan ... nan nan 487.5
- description :
- The installation costs of a technology, including annualised investment costs and annual maintenance costs.
- unit :
- cost
- is_result :
- 1
array([[[ nan], [33955.91266131], [ nan], [ nan], [ nan], [ nan], [ nan], [ 487.52735843]], [[ nan], [ nan], [93167.5923743 ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 8986.07268515], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ 1581.36340429], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ 487.52735843]]])
- cost(nodes, techs, costs)float64nan 1.703e+05 nan ... nan 1.067e+03
- description :
- The total annualised costs of a technology, including installation and operation costs.
- unit :
- cost
- is_result :
- 1
array([[[ nan], [170306.86648131], [ nan], [ nan], [ nan], [ nan], [ nan], [ 487.52735843]], [[ nan], [ nan], [ 94592.4283661 ], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ nan], [ nan], ... [ nan], [ nan]], [[ nan], [ nan], [ 9013.12138729], [ nan], [ nan], [ nan], [ nan], [ nan]], [[ 1581.36340429], [ nan], [ nan], [ nan], [ nan], [ nan], [ nan], [ 1067.17246823]]])
- capacity_factor(nodes, techs, carriers, timesteps)float640.0 0.0 0.0 ... 0.6978 0.7104
- is_result :
- 1
array([[[[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0.931212 , 0.8964891 , 0.87298907, ..., 0.8411376 , 0.76808347, 0.76115103]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], ..., [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]]], ... [[[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], ..., [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0. , 0. , 0. , ..., 0. , 0. , 0. ]], [[0.697761 , 0.65970156, 0.64701487, ..., 0.76119382, 0.697761 , 0.71044769]]]])
- systemwide_capacity_factor(techs, carriers)float640.1317 0.9469 ... 0.02471 0.3738
- is_result :
- 1
array([[0.13173452], [0.94688162], [0.48265792], [0. ], [0.32982315], [0. ], [0.02471137], [0.37381338]])
- systemwide_levelised_cost(carriers, techs, costs)float640.1 0.04996 0.1427 ... nan 0.005364
- is_result :
- 1
array([[[0.10003474], [0.04996133], [0.1427187 ], [ nan], [ nan], [ nan], [ nan], [0.00536432]]])
- total_levelised_cost(carriers, costs)float640.06701
- is_result :
- 1
array([[0.06700544]])
- techsPandasIndex
PandasIndex(Index(['battery', 'ccgt', 'csp', 'demand_power', 'region1_to_region1_1', 'region1_to_region1_2', 'region1_to_region1_3', 'region1_to_region2'], dtype='object', name='techs'))
- carriersPandasIndex
PandasIndex(Index(['power'], dtype='object', name='carriers'))
- nodesPandasIndex
PandasIndex(Index(['region1', 'region1_1', 'region1_2', 'region1_3', 'region2'], dtype='object', name='nodes'))
- timestepsPandasIndex
PandasIndex(DatetimeIndex(['2005-01-01 00:00:00', '2005-01-01 01:00:00', '2005-01-01 02:00:00', '2005-01-01 03:00:00', '2005-01-01 04:00:00', '2005-01-01 05:00:00', '2005-01-01 06:00:00', '2005-01-01 07:00:00', '2005-01-01 08:00:00', '2005-01-01 09:00:00', ... '2005-01-05 14:00:00', '2005-01-05 15:00:00', '2005-01-05 16:00:00', '2005-01-05 17:00:00', '2005-01-05 18:00:00', '2005-01-05 19:00:00', '2005-01-05 20:00:00', '2005-01-05 21:00:00', '2005-01-05 22:00:00', '2005-01-05 23:00:00'], dtype='datetime64[ns]', name='timesteps', length=120, freq=None))
- costsPandasIndex
PandasIndex(Index(['monetary'], dtype='object', name='costs'))
- termination_condition :
- optimal
- calliope_version_defined :
- 0.7.0
- calliope_version_initialised :
- 0.7.0.dev2
- applied_overrides :
- scenario :
- None
- defaults :
- {'available_area': inf, 'bigM': 1000000000.0, 'objective_cost_weights': 1, 'area_use': inf, 'area_use_max': inf, 'area_use_min': 0, 'area_use_per_flow_cap': nan, 'cap_method': 'continuous', 'color': nan, 'cost_area_use': 0, 'cost_depreciation_rate': 1, 'cost_export': 0, 'cost_flow_cap': 0, 'cost_flow_cap_per_distance': 0, 'cost_flow_in': 0, 'cost_flow_out': 0, 'cost_interest_rate': 0, 'cost_om_annual': 0, 'cost_om_annual_investment_fraction': 0, 'cost_purchase': 0, 'cost_purchase_per_distance': 0, 'cost_source_cap': 0, 'cost_storage_cap': 0, 'cyclic_storage': True, 'distance': nan, 'export_max': inf, 'flow_cap': inf, 'flow_cap_max': inf, 'flow_cap_max_systemwide': inf, 'flow_cap_min': 0, 'flow_cap_min_systemwide': 0, 'flow_cap_per_storage_cap_max': inf, 'flow_cap_per_storage_cap_min': 0, 'flow_cap_per_unit': nan, 'flow_in_eff': 1.0, 'flow_in_eff_per_distance': 1.0, 'flow_out_eff': 1.0, 'flow_out_eff_per_distance': 1.0, 'flow_out_min_relative': 0, 'flow_out_parasitic_eff': 1.0, 'flow_ramping': 1.0, 'force_async_flow': False, 'include_storage': False, 'integer_dispatch': False, 'lifetime': inf, 'name': nan, 'one_way': False, 'purchased_units': inf, 'purchased_units_max': inf, 'purchased_units_max_systemwide': inf, 'purchased_units_min': 0, 'purchased_units_min_systemwide': 0, 'sink_unit': 'absolute', 'sink_use_equals': nan, 'sink_use_max': inf, 'sink_use_min': 0, 'source_cap': inf, 'source_cap_equals_flow_cap': False, 'source_cap_max': inf, 'source_cap_min': 0, 'source_eff': 1.0, 'source_unit': 'absolute', 'source_use_equals': nan, 'source_use_max': inf, 'source_use_min': 0, 'storage_cap': inf, 'storage_cap_max': inf, 'storage_cap_min': 0, 'storage_cap_per_unit': nan, 'storage_discharge_depth': 0, 'storage_initial': 0, 'storage_loss': 0}
- allow_operate_mode :
- 1
- config :
- {'build': {'backend': 'pyomo', 'ensure_feasibility': True, 'mode': 'plan', 'objective': 'min_cost_optimisation', 'operate_use_cap_results': False}, 'solve': {'save_logs': None, 'solver': 'cbc', 'solver_io': None, 'solver_options': None, 'spores_number': 3, 'spores_save_per_spore': False, 'spores_score_cost_class': 'spores_score', 'spores_skip_cost_op': False, 'zero_threshold': 1e-10}}
- applied_custom_math :
- []
- math :
- {'constraints': {'flow_capacity_per_storage_capacity_min': {'description': 'Set the lower bound of storage flow capacity relative to its storage capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage_cap AND flow_cap_per_storage_cap_min', 'equations': [{'expression': 'flow_cap >= storage_cap * flow_cap_per_storage_cap_min'}]}, 'flow_capacity_per_storage_capacity_max': {'description': 'Set the upper bound of storage flow capacity relative to its storage capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage_cap AND flow_cap_per_storage_cap_max', 'equations': [{'expression': 'flow_cap <= storage_cap * flow_cap_per_storage_cap_max'}]}, 'source_capacity_equals_flow_capacity': {'description': "Set a `supply` technology's flow capacity to equal its source capacity.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'source_cap AND source_cap_equals_flow_cap=True', 'equations': [{'expression': 'source_cap == flow_cap'}]}, 'force_zero_area_use': {'description': "Set a technology's area use to zero if its flow capacity upper bound is zero.", 'foreach': ['nodes', 'techs'], 'where': 'area_use AND flow_cap_max=0', 'equations': [{'expression': 'area_use == 0'}]}, 'area_use_per_flow_capacity': {'description': "Set a fixed relationship between a technology's flow capacity and its area use.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'area_use AND area_use_per_flow_cap', 'equations': [{'expression': 'area_use == flow_cap * area_use_per_flow_cap'}]}, 'area_use_capacity_per_loc': {'description': 'Set an upper bound on the total area that all technologies with `area_use` can occupy at a given node.', 'foreach': ['nodes'], 'where': 'area_use AND available_area', 'equations': [{'expression': 'sum(area_use, over=techs) <= available_area'}]}, 'flow_capacity_systemwide_max': {'description': 'Set an upper bound on flow capacity of a technology across all nodes in which the technology exists.', 'foreach': ['techs', 'carriers'], 'where': 'flow_cap_max_systemwide', 'equations': [{'expression': 'sum(flow_cap, over=nodes) <= flow_cap_max_systemwide'}]}, 'flow_capacity_systemwide_min': {'description': 'Set a lower bound on flow capacity of a technology across all nodes in which the technology exists.', 'foreach': ['techs', 'carriers'], 'where': 'flow_cap_min_systemwide', 'equations': [{'expression': 'sum(flow_cap, over=nodes) >= flow_cap_min_systemwide'}]}, 'balance_conversion': {'description': "Fix the relationship between a `conversion` technology's outflow and consumption.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'base_tech=conversion AND NOT include_storage=true', 'equations': [{'expression': 'sum(flow_out_inc_eff, over=carriers) == sum(flow_in_inc_eff, over=carriers)'}]}, 'flow_out_max': {'description': "Set the upper bound of a technology's outflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_out AND NOT operating_units', 'equations': [{'expression': 'flow_out <= flow_cap * timestep_resolution * flow_out_parasitic_eff'}]}, 'flow_out_min': {'description': "Set the lower bound of a technology's outflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out_min_relative AND NOT operating_units', 'equations': [{'expression': 'flow_out >= flow_cap * timestep_resolution * flow_out_min_relative'}]}, 'flow_in_max': {'description': "Set the upper bound of a technology's inflow.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_in AND NOT operating_units', 'equations': [{'expression': 'flow_in <= flow_cap * timestep_resolution'}]}, 'source_max': {'description': "Set the upper bound of a `supply` technology's source consumption.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_cap', 'equations': [{'expression': 'source_use <= timestep_resolution * source_cap'}]}, 'storage_max': {'description': 'Set the upper bound of the amount of carrier a technology can store.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'storage', 'equations': [{'expression': 'storage <= storage_cap'}]}, 'storage_discharge_depth_limit': {'description': 'Set the lower bound of the stored carrier a technology must keep in reserve at all times.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'storage AND storage_discharge_depth', 'equations': [{'expression': 'storage - storage_discharge_depth * storage_cap >= 0'}]}, 'system_balance': {'description': 'Set the global carrier balance of the optimisation problem by fixing the total production of a given carrier to equal the total consumption of that carrier at every node in every timestep.', 'foreach': ['nodes', 'carriers', 'timesteps'], 'equations': [{'expression': 'sum(flow_out, over=techs) - sum(flow_in, over=techs) - $flow_export + $unmet_demand_and_unused_supply == 0'}], 'sub_expressions': {'flow_export': [{'where': 'any(carrier_export, over=techs)', 'expression': 'sum(flow_export, over=techs)'}, {'where': 'NOT any(carrier_export, over=techs)', 'expression': '0'}], 'unmet_demand_and_unused_supply': [{'where': 'config.ensure_feasibility=True', 'expression': 'unmet_demand + unused_supply'}, {'where': 'NOT config.ensure_feasibility=True', 'expression': '0'}]}}, 'balance_demand': {'description': 'Set the upper bound on, or a fixed total of, that a demand technology must dump to its sink in each timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'base_tech=demand', 'equations': [{'where': 'sink_use_equals', 'expression': 'flow_in_inc_eff == sink_use_equals * $sink_scaler'}, {'where': 'NOT sink_use_equals AND sink_use_max', 'expression': 'flow_in_inc_eff <= sink_use_max * $sink_scaler'}], 'sub_expressions': {'sink_scaler': [{'where': 'sink_unit=per_area', 'expression': 'area_use'}, {'where': 'sink_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'sink_unit=absolute', 'expression': '1'}]}}, 'balance_demand_min_use': {'description': 'Set the lower bound on the quantity of flow a `demand` technology must dump to its sink in each timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'sink_use_min AND NOT sink_use_equals AND base_tech=demand', 'equations': [{'expression': 'flow_in_inc_eff >= sink_use_min * $sink_scaler'}], 'sub_expressions': {'sink_scaler': [{'where': 'sink_unit=per_area', 'expression': 'area_use'}, {'where': 'sink_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'sink_unit=absolute', 'expression': '1'}]}}, 'balance_supply_no_storage': {'description': 'Fix the outflow of a `supply` technology to its consumption of the available source.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'base_tech=supply AND NOT include_storage=True', 'equations': [{'expression': 'flow_out_inc_eff == source_use * source_eff'}]}, 'balance_supply_with_storage': {'description': 'Fix the outflow of a `supply` technology to its consumption of the available source, with a storage buffer to temporally offset the outflow from source consumption.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'storage AND base_tech=supply', 'equations': [{'expression': 'storage == $storage_previous_step + source_use * source_eff - flow_out_inc_eff'}], 'sub_expressions': {'storage_previous_step': [{'where': 'timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True', 'expression': 'storage_initial * storage_cap'}, {'where': '(\n (timesteps=get_val_at_index(timesteps=0) AND cyclic_storage=True)\n OR NOT timesteps=get_val_at_index(timesteps=0)\n) AND NOT lookup_cluster_first_timestep=True', 'expression': '(1 - storage_loss) ** roll(timestep_resolution, timesteps=1) * roll(storage, timesteps=1)'}, {'where': 'lookup_cluster_first_timestep=True AND NOT (timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True)', 'expression': '(1 - storage_loss) ** select_from_lookup_arrays(timestep_resolution, timesteps=lookup_cluster_last_timestep) * select_from_lookup_arrays(storage, timesteps=lookup_cluster_last_timestep)'}]}}, 'source_availability_supply': {'description': "Set the upper bound on, or a fixed total of, a `supply` technology's ability to consume its available resource.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_use AND (source_use_equals OR source_use_max)', 'equations': [{'where': 'source_use_equals', 'expression': 'source_use == source_use_equals * $source_scaler'}, {'where': 'NOT source_use_equals AND source_use_max', 'expression': 'source_use <= source_use_max * $source_scaler'}], 'sub_expressions': {'source_scaler': [{'where': 'source_unit=per_area', 'expression': 'area_use'}, {'where': 'source_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'source_unit=absolute', 'expression': '1'}]}}, 'balance_supply_min_use': {'description': 'Set the lower bound on the quantity of its source a `supply` technology must use in each timestep.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'source_use_min AND NOT source_use_equals AND base_tech=supply', 'equations': [{'expression': 'source_use >= source_use_min * $source_scaler'}], 'sub_expressions': {'source_scaler': [{'where': 'source_unit=per_area', 'expression': 'area_use'}, {'where': 'source_unit=per_cap', 'expression': 'sum(flow_cap, over=carriers)'}, {'where': 'source_unit=absolute', 'expression': '1'}]}}, 'balance_storage': {'description': 'Fix the quantity of carrier stored in a `storage` technology at the end of each timestep based on the net flow of carrier charged and discharged and the quantity of carrier stored at the start of the timestep.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': '(include_storage=true or base_tech=storage) AND NOT (base_tech=supply OR base_tech=demand)', 'equations': [{'expression': 'storage == $storage_previous_step -\n sum(flow_out_inc_eff, over=carriers) + sum(flow_in_inc_eff, over=carriers)'}], 'sub_expressions': {'storage_previous_step': [{'where': 'timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True', 'expression': 'storage_initial * storage_cap'}, {'where': '(\n (timesteps=get_val_at_index(timesteps=0) AND cyclic_storage=True)\n OR NOT timesteps=get_val_at_index(timesteps=0)\n) AND NOT lookup_cluster_first_timestep=True', 'expression': '(1 - storage_loss) ** roll(timestep_resolution, timesteps=1) * roll(storage, timesteps=1)'}, {'where': 'lookup_cluster_first_timestep=True AND NOT (timesteps=get_val_at_index(timesteps=0) AND NOT cyclic_storage=True)', 'expression': '(1 - storage_loss) ** select_from_lookup_arrays(timestep_resolution, timesteps=lookup_cluster_last_timestep) * select_from_lookup_arrays(storage, timesteps=lookup_cluster_last_timestep)'}]}}, 'set_storage_initial': {'description': 'Fix the relationship between carrier stored in a `storage` technology at the start and end of the whole model period.', 'foreach': ['nodes', 'techs'], 'where': 'storage AND storage_initial AND cyclic_storage=True', 'equations': [{'expression': 'storage[timesteps=$final_step] * (\n (1 - storage_loss) ** timestep_resolution[timesteps=$final_step]\n) == storage_initial * storage_cap'}], 'slices': {'final_step': [{'expression': 'get_val_at_index(timesteps=-1)'}]}, 'active': True}, 'balance_transmission': {'description': 'Fix the relationship between between carrier flowing into and out of a `transmission` link in each timestep.', 'foreach': ['techs', 'timesteps'], 'where': 'base_tech=transmission', 'equations': [{'expression': 'sum(flow_out_inc_eff, over=[nodes, carriers]) == sum(flow_in_inc_eff, over=[nodes, carriers])'}]}, 'symmetric_transmission': {'description': 'Fix the flow capacity of two `transmission` technologies representing the same link in the system.', 'foreach': ['nodes', 'techs'], 'where': 'base_tech=transmission', 'equations': [{'expression': 'sum(flow_cap, over=carriers) == link_flow_cap'}]}, 'export_balance': {'description': "Set the lower bound of a technology's outflow to a technology's carrier export, for any technologies that can export carriers out of the system.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_export', 'equations': [{'expression': 'flow_out >= flow_export'}]}, 'flow_export_max': {'description': "Set the upper bound of a technology's carrier export, for any technologies that can export carriers out of the system.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_export AND export_max', 'equations': [{'where': 'operating_units', 'expression': 'flow_export <= export_max * operating_units'}, {'where': 'NOT operating_units', 'expression': 'flow_export <= export_max'}]}, 'unit_commitment_milp': {'description': 'Set the upper bound of the number of integer units of technology that can exist, for any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'operating_units AND purchased_units', 'equations': [{'expression': 'operating_units <= purchased_units'}]}, 'available_flow_cap_binary': {'description': 'Limit flow capacity to zero if the technology is not operating in a given timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap <= flow_cap_max * operating_units'}]}, 'available_flow_cap_continuous': {'description': 'Limit flow capacity to the value of the `flow_cap` decision variable when the technology is operating in a given timestep.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap <= flow_cap'}]}, 'available_flow_cap_max_binary_continuous_switch': {'description': 'Force flow capacity to equal the value of the `flow_cap` decision variable if the technology is operating in a given timestep, zero otherwise.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'available_flow_cap', 'equations': [{'expression': 'available_flow_cap >= flow_cap + ((operating_units - purchased_units) * flow_cap_max)'}]}, 'flow_out_max_milp': {'description': "Set the upper bound of a technology's ability to produce carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out AND operating_units AND flow_cap_per_unit', 'equations': [{'expression': 'flow_out <= operating_units * timestep_resolution * flow_cap_per_unit * flow_out_parasitic_eff'}]}, 'flow_in_max_milp': {'description': "Set the upper bound of a technology's ability to consume carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_in AND operating_units AND flow_cap_per_unit', 'equations': [{'expression': 'flow_in <= operating_units * timestep_resolution * flow_cap_per_unit'}]}, 'flow_out_min_milp': {'description': "Set the lower bound of a technology's ability to produce carriers, for any technology using integer units to define its capacity.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out AND operating_units AND flow_out_min_relative', 'equations': [{'where': 'flow_cap_per_unit', 'expression': 'flow_out >= operating_units * timestep_resolution * flow_cap_per_unit * flow_out_min_relative'}, {'where': 'available_flow_cap', 'expression': 'flow_out >= available_flow_cap * timestep_resolution * flow_out_min_relative'}]}, 'storage_capacity_units_milp': {'description': 'Fix the storage capacity of any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'storage AND purchased_units AND storage_cap_per_unit', 'equations': [{'expression': 'storage_cap == purchased_units * storage_cap_per_unit'}]}, 'flow_capacity_units_milp': {'description': 'Fix the flow capacity of any technology using integer units to define its capacity.', 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'operating_units', 'equations': [{'where': 'flow_cap_per_unit', 'expression': 'flow_cap == purchased_units * flow_cap_per_unit'}, {'where': 'NOT flow_cap_per_unit', 'expression': 'flow_cap <= purchased_units * bigM'}]}, 'flow_capacity_max_purchase_milp': {'description': "Set the upper bound on a technology's flow capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'purchased_units AND flow_cap_max', 'equations': [{'expression': 'flow_cap <= flow_cap_max * purchased_units'}]}, 'flow_capacity_min_purchase_milp': {'description': "Set the lower bound on a technology's flow capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs', 'carriers'], 'where': 'purchased_units AND flow_cap_min', 'equations': [{'expression': 'flow_cap >= flow_cap_min * purchased_units'}]}, 'storage_capacity_max_purchase_milp': {'description': "Set the upper bound on a technology's storage capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs'], 'where': 'purchased_units AND storage_cap_max', 'equations': [{'expression': 'storage_cap <= storage_cap_max * purchased_units'}]}, 'storage_capacity_min_purchase_milp': {'description': "Set the lower bound on a technology's storage capacity, for any technology with integer capacity purchasing.", 'foreach': ['nodes', 'techs'], 'where': 'purchased_units AND storage_cap_min', 'equations': [{'expression': 'storage_cap >= storage_cap_min * purchased_units'}]}, 'unit_capacity_max_systemwide_milp': {'description': 'Set the upper bound on the total number of units of a technology that can be purchased across all nodes where the technology can exist, for any technology using integer units to define its capacity.', 'foreach': ['techs'], 'where': 'purchased_units AND purchased_units_max_systemwide', 'equations': [{'expression': 'sum(purchased_units, over=nodes) <= purchased_units_max_systemwide'}]}, 'unit_capacity_min_systemwide_milp': {'description': 'Set the lower bound on the total number of units of a technology that can be purchased across all nodes where the technology can exist, for any technology using integer units to define its capacity.', 'foreach': ['techs'], 'where': 'purchased_units AND purchased_units_max_systemwide', 'equations': [{'expression': 'sum(purchased_units, over=nodes) >= purchased_units_min_systemwide'}]}, 'async_flow_in_milp': {'description': "Set a technology's ability to have inflow in the same timestep that it has outflow, for any technology using the asynchronous flow binary switch.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'async_flow_switch', 'equations': [{'expression': 'sum(flow_in, over=carriers) <= (1 - async_flow_switch) * bigM'}]}, 'async_flow_out_milp': {'description': "Set a technology's ability to have outflow in the same timestep that it has inflow, for any technology using the asynchronous flow binary switch.", 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'async_flow_switch', 'equations': [{'expression': 'sum(flow_out, over=carriers) <= async_flow_switch * bigM'}]}, 'ramping_up': {'description': "Set the upper bound on a technology's ability to ramp outflow up beyond a certain percentage compared to the previous timestep.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_ramping AND NOT timesteps=get_val_at_index(timesteps=0)', 'equations': [{'expression': '$flow - roll($flow, timesteps=1) <= flow_ramping * flow_cap'}], 'sub_expressions': {'flow': [{'where': 'carrier_out AND NOT carrier_in', 'expression': 'flow_out / timestep_resolution'}, {'where': 'carrier_in AND NOT carrier_out', 'expression': 'flow_in / timestep_resolution'}, {'where': 'carrier_in AND carrier_out', 'expression': '(flow_out - flow_in) / timestep_resolution'}]}}, 'ramping_down': {'description': "Set the upper bound on a technology's ability to ramp outflow down beyond a certain percentage compared to the previous timestep.", 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_ramping AND NOT timesteps=get_val_at_index(timesteps=0)', 'equations': [{'expression': '-1 * flow_ramping * flow_cap <= $flow - roll($flow, timesteps=1)'}], 'sub_expressions': {'flow': [{'where': 'carrier_out AND NOT carrier_in', 'expression': 'flow_out / timestep_resolution'}, {'where': 'carrier_in AND NOT carrier_out', 'expression': 'flow_in / timestep_resolution'}, {'where': 'carrier_in AND carrier_out', 'expression': '(flow_out - flow_in) / timestep_resolution'}]}}}, 'variables': {'flow_cap': {'description': "A technology's flow capacity, also known as its nominal or nameplate capacity.", 'unit': 'power', 'foreach': ['nodes', 'techs', 'carriers'], 'bounds': {'min': 'flow_cap_min', 'max': 'flow_cap_max'}}, 'link_flow_cap': {'description': "A transmission technology's flow capacity, also known as its nominal or nameplate capacity.", 'unit': 'power', 'foreach': ['techs'], 'where': 'base_tech=transmission', 'bounds': {'min': 0, 'max': inf}}, 'flow_out': {'description': 'The outflow of a technology per timestep, also known as the flow discharged (from `storage` technologies) or the flow received (by `transmission` technologies) on a link.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_out', 'bounds': {'min': 0, 'max': inf}}, 'flow_in': {'description': 'The inflow to a technology per timestep, also known as the flow consumed (by `storage` technologies) or the flow sent (by `transmission` technologies) on a link.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_in', 'bounds': {'min': 0, 'max': inf}}, 'flow_export': {'description': 'The flow of a carrier exported outside the system boundaries by a technology per timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'carrier_export', 'bounds': {'min': 0, 'max': inf}}, 'area_use': {'description': 'The area in space utilised directly (e.g., solar PV panels) or indirectly (e.g., biofuel crops) by a technology.', 'unit': 'area', 'foreach': ['nodes', 'techs'], 'where': '(area_use_min OR area_use_max OR area_use_per_flow_cap OR sink_unit=per_area OR source_unit=per_area)', 'bounds': {'min': 'area_use_min', 'max': 'area_use_max'}}, 'source_use': {'description': 'The carrier flow consumed from outside the system boundaries by a `supply` technology.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'base_tech=supply', 'bounds': {'min': 0, 'max': inf}}, 'source_cap': {'description': 'The upper limit on a flow that can be consumed from outside the system boundaries by a `supply` technology in each timestep.', 'unit': 'power', 'foreach': ['nodes', 'techs'], 'where': 'base_tech=supply', 'bounds': {'min': 'source_cap_min', 'max': 'source_cap_max'}}, 'storage_cap': {'description': 'The upper limit on a carrier that can be stored by a technology in any timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs'], 'where': 'include_storage=True OR base_tech=storage', 'domain': 'real', 'bounds': {'min': 'storage_cap_min', 'max': 'storage_cap_max'}, 'active': True}, 'storage': {'description': 'The carrier stored by a `storage` technology in each timestep.', 'unit': 'energy', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'include_storage=True OR base_tech=storage', 'bounds': {'min': 0, 'max': inf}}, 'purchased_units': {'description': 'Integer number of a technology that has been purchased,\nfor any technology set to require integer capacity purchasing.\nThis is used to allow installation of fixed capacity units of technologies (\nif `flow_cap_max` == `flow_cap_min`) and/or to set a fixed cost for a technology,\nirrespective of its installed capacity.\nOn top of a fixed technology cost,\na continuous cost for the quantity of installed capacity can still be applied.\n\nSince technology capacity is no longer a continuous decision variable,\nit is possible for these technologies to have a lower bound set on outflow/consumption\nwhich will only be enforced in those timesteps that the technology is operating.\nOtherwise, the same lower bound forces the technology to produce/consume\nthat minimum amount of carrier in *every* timestep.\n', 'unit': 'integer', 'foreach': ['nodes', 'techs'], 'where': 'cap_method=integer', 'domain': 'integer', 'bounds': {'min': 'purchased_units_min', 'max': 'purchased_units_max'}}, 'operating_units': {'description': 'Integer number of a technology that is operating in each timestep, for any technology set to require integer capacity purchasing.', 'unit': 'integer', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'integer_dispatch=True AND cap_method=integer', 'domain': 'integer', 'bounds': {'min': 0, 'max': inf}}, 'available_flow_cap': {'description': 'Flow capacity that will be set to zero if the technology is not operating in a given timestep and will be set to the value of the decision variable `flow_cap` otherwise.', 'unit': 'power', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'integer_dispatch=True AND flow_cap_max AND NOT flow_cap_per_unit', 'bounds': {'min': 0, 'max': inf}}, 'async_flow_switch': {'description': 'Binary switch to force asynchronous outflow/consumption of technologies with both `flow_in` and `flow_out` defined. This ensures that a technology with carrier flow efficiencies < 100% cannot produce and consume a flow simultaneously to remove unwanted carrier from the system.', 'unit': 'integer', 'foreach': ['nodes', 'techs', 'timesteps'], 'where': 'force_async_flow=True', 'domain': 'integer', 'bounds': {'min': 0, 'max': 1}}, 'unmet_demand': {'description': 'Virtual source of carrier flow to ensure model feasibility. This should only be considered a debugging rather than a modelling tool as it may distort the model in other ways due to the large impact it has on the objective function value. When present in a model in which it has been requested, it indicates an inability for technologies in the model to reach a sufficient combined supply capacity to meet demand.', 'unit': 'energy', 'foreach': ['nodes', 'carriers', 'timesteps'], 'where': 'config.ensure_feasibility=True', 'bounds': {'min': 0, 'max': inf}}, 'unused_supply': {'description': 'Virtual sink of carrier flow to ensure model feasibility. This should only be considered a debugging rather than a modelling tool as it may distort the model in other ways due to the large impact it has on the objective function value. In model results, the negation of this variable is combined with `unmet_demand` and presented as only one variable: `unmet_demand`. When present in a model in which it has been requested, it indicates an inability for technologies in the model to reach a sufficient combined consumption capacity to meet required outflow (e.g. from renewables without the possibility of curtailment).', 'unit': 'energy', 'foreach': ['nodes', 'carriers', 'timesteps'], 'where': 'config.ensure_feasibility=True', 'bounds': {'min': -inf, 'max': 0}}}, 'objectives': {'min_cost_optimisation': {'description': 'Minimise the total cost of installing and operating all technologies in the system. If multiple cost classes are present (e.g., monetary and co2 emissions), the weighted sum of total costs is minimised. Cost class weights can be defined in the indexed parameter `objective_cost_weights`.', 'equations': [{'where': 'any(cost, over=[nodes, techs, costs])', 'expression': 'sum(\n sum(cost, over=[nodes, techs])\n * objective_cost_weights,\n over=costs\n) + $unmet_demand'}, {'where': 'NOT any(cost, over=[nodes, techs, costs])', 'expression': '$unmet_demand'}], 'sub_expressions': {'unmet_demand': [{'where': 'config.ensure_feasibility=True', 'expression': 'sum(\n sum(unmet_demand - unused_supply, over=[carriers, nodes])\n * timestep_weights,\n over=timesteps\n) * bigM'}, {'where': 'NOT config.ensure_feasibility=True', 'expression': '0'}]}, 'sense': 'minimise', 'active': True}}, 'global_expressions': {'flow_out_inc_eff': {'description': 'Outflows after taking efficiency losses into account.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_out', 'equations': [{'where': 'base_tech=transmission', 'expression': 'flow_out / (\n flow_out_eff * flow_out_parasitic_eff *\n flow_out_eff_per_distance ** default_if_empty(distance, 1)\n)'}, {'where': 'NOT base_tech=transmission', 'expression': 'flow_out / (flow_out_eff * flow_out_parasitic_eff)'}]}, 'flow_in_inc_eff': {'description': 'Inflows after taking efficiency losses into account.', 'foreach': ['nodes', 'techs', 'carriers', 'timesteps'], 'where': 'flow_in', 'equations': [{'where': 'base_tech=transmission', 'expression': 'flow_in * flow_in_eff * flow_in_eff_per_distance ** default_if_empty(distance, 1)'}, {'where': 'NOT base_tech=transmission', 'expression': 'flow_in * flow_in_eff'}]}, 'cost_var': {'description': 'The operating costs per timestep of a technology.', 'unit': 'cost_per_time', 'foreach': ['nodes', 'techs', 'costs', 'timesteps'], 'where': 'cost_export OR cost_flow_in OR cost_flow_out', 'equations': [{'expression': 'timestep_weights * ($cost_export + $cost_flow_out + $cost_flow_in)'}], 'sub_expressions': {'cost_export': [{'where': 'flow_export', 'expression': 'sum(cost_export * default_if_empty(flow_export, 0), over=carriers)'}, {'where': 'NOT flow_export', 'expression': '0'}], 'cost_flow_in': [{'where': 'base_tech=supply', 'expression': 'cost_flow_in * source_use'}, {'where': 'NOT base_tech=supply', 'expression': 'sum(cost_flow_in * default_if_empty(flow_in, 0), over=carriers)'}], 'cost_flow_out': [{'expression': 'sum(cost_flow_out * default_if_empty(flow_out, 0), over=carriers)'}]}}, 'cost_investment_flow_cap': {'description': 'The investment costs associated with the nominal/rated capacity of a technology.', 'foreach': ['nodes', 'techs', 'carriers', 'costs'], 'where': 'flow_cap AND (cost_flow_cap OR cost_flow_cap_per_distance)', 'equations': [{'expression': '$cost_sum * flow_cap'}], 'sub_expressions': {'cost_sum': [{'where': 'base_tech=transmission', 'expression': '(cost_flow_cap + cost_flow_cap_per_distance * default_if_empty(distance, 0)) * 0.5'}, {'where': 'NOT base_tech=transmission', 'expression': 'cost_flow_cap'}]}}, 'cost_investment_storage_cap': {'description': 'The investment costs associated with the storage capacity of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_storage_cap AND storage_cap', 'equations': [{'expression': 'cost_storage_cap * storage_cap'}]}, 'cost_investment_source_cap': {'description': 'The investment costs associated with the source consumption capacity of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_source_cap AND source_cap', 'equations': [{'expression': 'cost_source_cap * source_cap'}]}, 'cost_investment_area_use': {'description': 'The investment costs associated with the area used by a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_area_use AND area_use', 'equations': [{'expression': 'cost_area_use * area_use'}]}, 'cost_investment_purchase': {'description': 'The investment costs associated with the binary purchase of a technology.', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_purchase AND purchased_units', 'equations': [{'where': 'base_tech=transmission', 'expression': '(cost_purchase + cost_purchase_per_distance * default_if_empty(distance, 0)) * purchased_units * 0.5'}, {'where': 'NOT base_tech=transmission', 'expression': 'cost_purchase * purchased_units'}]}, 'cost_investment': {'description': 'The installation costs of a technology, including annualised investment costs and annual maintenance costs.', 'unit': 'cost', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_investment_flow_cap OR cost_investment_storage_cap OR cost_investment_source_cap OR cost_investment_area_use OR cost_investment_purchase', 'equations': [{'expression': '$annualisation_weight * (\n $depreciation_rate * (\n sum(default_if_empty(cost_investment_flow_cap, 0), over=carriers) +\n default_if_empty(cost_investment_storage_cap, 0) +\n default_if_empty(cost_investment_source_cap, 0) +\n default_if_empty(cost_investment_area_use, 0) +\n default_if_empty(cost_investment_purchase, 0)\n ) * (1 + cost_om_annual_investment_fraction)\n + sum(cost_om_annual * default_if_empty(flow_cap, 0), over=carriers)\n)\n'}], 'sub_expressions': {'annualisation_weight': [{'expression': 'sum(timestep_resolution * timestep_weights, over=timesteps) / 8760'}], 'depreciation_rate': [{'where': 'cost_depreciation_rate', 'expression': 'cost_depreciation_rate'}, {'where': 'NOT cost_depreciation_rate AND cost_interest_rate=0', 'expression': '1 / lifetime'}, {'where': 'NOT cost_depreciation_rate AND cost_interest_rate>0', 'expression': '(cost_interest_rate * ((1 + cost_interest_rate) ** lifetime)) / (((1 + cost_interest_rate) ** lifetime) - 1)'}]}}, 'cost': {'description': 'The total annualised costs of a technology, including installation and operation costs.', 'unit': 'cost', 'foreach': ['nodes', 'techs', 'costs'], 'where': 'cost_investment OR cost_var', 'equations': [{'expression': '$cost_investment + $cost_var_sum'}], 'sub_expressions': {'cost_investment': [{'where': 'cost_investment', 'expression': 'cost_investment'}, {'where': 'NOT cost_investment', 'expression': '0'}], 'cost_var_sum': [{'where': 'cost_var', 'expression': 'sum(cost_var, over=timesteps)'}, {'where': 'NOT cost_var', 'expression': '0'}]}, 'active': True}}}
- name :
- National-scale example model
We can sum electricity output over all locations and turn the result into a pandas DataFrame.
Note: electricity output of transmission technologies (e.g., region1_to_region2
) is the import of electricity at nodes.
df_electricity = model.results.flow_out.sel(carriers="power").sum("nodes").to_series()
df_electricity.head()
techs timesteps battery 2005-01-01 00:00:00 0.0 2005-01-01 01:00:00 0.0 2005-01-01 02:00:00 0.0 2005-01-01 03:00:00 0.0 2005-01-01 04:00:00 0.0 Name: flow_out, dtype: float64
We can also view total costs associated with each of our technologies at each of our nodes:
costs = model.results.cost.to_series().dropna()
costs.head()
nodes techs costs region1 ccgt monetary 170306.866481 region1_to_region2 monetary 487.527358 region1_1 csp monetary 94592.428366 region1_2 csp monetary 0.000000 region1_3 csp monetary 9013.121387 Name: cost, dtype: float64
We can also examine levelized costs for each location and technology, which is calculated in a post-processing step:
lcoes = model.results.systemwide_levelised_cost.to_series().dropna()
lcoes
carriers techs costs power battery monetary 0.100035 ccgt monetary 0.049961 csp monetary 0.142719 region1_to_region2 monetary 0.005364 Name: systemwide_levelised_cost, dtype: float64
# We set the color mapping to use in all our plots by extracting the colors defined in the technology definitions of our model.
colors = model.inputs.color.to_series().to_dict()
Plotting flows¶
We do this by combinging in- and out-flows and separating demand from other technologies. First, we look at the aggregated result across all nodes, then we look at each node separately.
df_electricity = (
(model.results.flow_out.fillna(0) - model.results.flow_in.fillna(0))
.sel(carriers="power")
.sum("nodes")
.to_series()
.where(lambda x: x != 0)
.dropna()
.to_frame("Flow in/out (kWh)")
.reset_index()
)
df_electricity_demand = df_electricity[df_electricity.techs == "demand_power"]
df_electricity_other = df_electricity[df_electricity.techs != "demand_power"]
print(df_electricity.head())
fig1 = px.bar(
df_electricity_other,
x="timesteps",
y="Flow in/out (kWh)",
color="techs",
color_discrete_map=colors,
)
fig1.add_scatter(
x=df_electricity_demand.timesteps,
y=-1 * df_electricity_demand["Flow in/out (kWh)"],
marker_color="black",
name="demand",
)
techs timesteps Flow in/out (kWh) 0 battery 2005-01-01 14:00:00 -76.402643 1 battery 2005-01-01 15:00:00 -286.886000 2 battery 2005-01-01 16:00:00 163.934000 3 battery 2005-01-01 17:00:00 122.950000 4 battery 2005-01-01 18:00:00 40.984000