In [1]:
import xarray as xr
import pandas as pd
import numpy as np

import calliope

calliope.set_log_verbosity('INFO', include_solver_output=False)

Model input

In [2]:
# Initialise the model with the Urban Scale example model
m = calliope.examples.urban_scale()
[2021-07-29 16:01:30] INFO     Model: initialising
[2021-07-29 16:01:30] INFO     Model: preprocessing stage 1 (model_run)
[2021-07-29 16:01:31] INFO     NumExpr defaulting to 8 threads.
[2021-07-29 16:01:31] INFO     Model: preprocessing stage 2 (model_data)
[2021-07-29 16:01:31] INFO     Model: preprocessing complete
In [3]:
# Get information on the model
m.info()
Out[3]:
'Model name:   Urban-scale example model\nModel size:   4 locations, 9 technologies, 48 timesteps'

model_run

m._model_run is a python dictionary. The underscore before the method indicates that it defaults to being hidden (i.e. you wouldn't see it by trying a tab auto-complete and it isn't documented)

In [4]:
# Model run holds all the data from the YAML and CSV files, restructured into one dictionary
m._model_run.keys()
Out[4]:
dict_keys(['scenario', 'applied_overrides', 'techs', 'tech_groups', 'locations', 'timeseries_data', 'run', 'model', 'group_constraints', 'sets', 'constraint_sets'])
In [5]:
# All locations now hold all information about a technology at that location

m._model_run['locations']['X2']['techs']['pv']
Out[5]:
{'costs': {'monetary': {'export': -0.0491,
   'om_prod': -0.0203,
   'depreciation_rate': 0.11016807219002081,
   'energy_cap': 1350}},
 'constraints': {'energy_cap_max': 250,
  'energy_prod': True,
  'export_carrier': 'electricity',
  'force_resource': True,
  'lifetime': 25,
  'parasitic_eff': 0.85,
  'resource': 'file=pv_resource.csv:per_area',
  'resource_area_max': 1500,
  'resource_area_per_energy_cap': 7,
  'resource_eff': 1.0,
  'resource_unit': 'energy_per_area'}}
In [6]:
# This includes location-specific overrides, such as energy_cap_max of 50 for the pv technology at location X3

m._model_run['locations']['X3']['techs']['pv']
Out[6]:
{'constraints': {'energy_cap_max': 50,
  'energy_prod': True,
  'export_carrier': 'electricity',
  'force_resource': True,
  'lifetime': 25,
  'parasitic_eff': 0.85,
  'resource': 'file=pv_resource.csv:per_area',
  'resource_area_max': 1500,
  'resource_area_per_energy_cap': 7,
  'resource_eff': 1.0,
  'resource_unit': 'energy_per_area'},
 'costs': {'monetary': {'om_annual': -80.5,
   'depreciation_rate': 0.11016807219002081,
   'energy_cap': 1350}}}
In [7]:
# All sets have also been collated.
# locations and technologies are concatenated into loc::tech sets, 
# to create a dense matrix and smaller overall model size

m._model_run['sets']['loc_techs']
Out[7]:
['X2::demand_electricity',
 'X3::power_lines:X1',
 'X2::supply_gas',
 'X1::demand_heat',
 'X3::boiler',
 'X3::demand_heat',
 'X3::supply_gas',
 'X1::heat_pipes:N1',
 'N1::heat_pipes:X3',
 'X2::demand_heat',
 'X3::demand_electricity',
 'X1::supply_grid_power',
 'X3::pv',
 'N1::heat_pipes:X2',
 'X1::chp',
 'X1::power_lines:X3',
 'N1::heat_pipes:X1',
 'X1::pv',
 'X2::power_lines:X1',
 'X1::power_lines:X2',
 'X1::supply_gas',
 'X1::demand_electricity',
 'X2::heat_pipes:N1',
 'X3::heat_pipes:N1',
 'X2::pv',
 'X2::boiler']
In [8]:
# For every constraint, a set of loc_techs (or loc_tech_carriers) is prepared, 
# so we only build the constraint over that set

m._model_run['constraint_sets']['loc_techs_energy_capacity_constraint']
Out[8]:
['X2::demand_electricity',
 'X3::power_lines:X1',
 'X2::supply_gas',
 'X1::demand_heat',
 'X3::boiler',
 'X3::demand_heat',
 'X3::supply_gas',
 'X1::heat_pipes:N1',
 'N1::heat_pipes:X3',
 'X2::demand_heat',
 'X3::demand_electricity',
 'X1::supply_grid_power',
 'X3::pv',
 'N1::heat_pipes:X2',
 'X1::chp',
 'X1::power_lines:X3',
 'N1::heat_pipes:X1',
 'X1::pv',
 'X2::power_lines:X1',
 'X1::power_lines:X2',
 'X1::supply_gas',
 'X1::demand_electricity',
 'X2::heat_pipes:N1',
 'X3::heat_pipes:N1',
 'X2::pv',
 'X2::boiler']
In [9]:
m._model_run['constraint_sets']['loc_techs_resource_area_constraint']
Out[9]:
['X1::pv', 'X2::pv', 'X3::pv']
In [10]:
# timeseries data is stored as dataframes, having been loaded from CSV
m._model_run['timeseries_data']['pv_resource.csv'].head()
Out[10]:
per_area per_cap
2005-07-01 00:00:00 0.0 0.0
2005-07-01 01:00:00 0.0 0.0
2005-07-01 02:00:00 0.0 0.0
2005-07-01 03:00:00 0.0 0.0
2005-07-01 04:00:00 0.0 0.0

model_data

m._model_data is an xarray Dataset

In [11]:
# Users would usually access information for the initialised model using m.inputs 
m.inputs
Out[11]:
<xarray.Dataset>
Dimensions:                               (carrier_tiers: 3, carriers: 3, coordinates: 2, costs: 1, loc_carriers: 10, loc_tech_carriers_conversion_plus: 3, loc_techs: 26, loc_techs_area: 3, loc_techs_conversion: 2, loc_techs_conversion_plus: 1, loc_techs_export: 4, loc_techs_finite_resource: 9, loc_techs_investment_cost: 20, loc_techs_non_conversion: 23, loc_techs_om_cost: 9, loc_techs_supply_plus: 3, loc_techs_transmission: 10, locs: 4, techs: 9, timesteps: 48)
Coordinates: (12/20)
  * carrier_tiers                         (carrier_tiers) <U5 'out_2' 'in' 'out'
  * carriers                              (carriers) <U11 'gas' ... 'electric...
  * coordinates                           (coordinates) object 'x' 'y'
  * costs                                 (costs) object 'monetary'
  * loc_carriers                          (loc_carriers) object 'X3::heat' .....
  * loc_tech_carriers_conversion_plus     (loc_tech_carriers_conversion_plus) object ...
    ...                                    ...
  * loc_techs_om_cost                     (loc_techs_om_cost) object 'X2::sup...
  * loc_techs_supply_plus                 (loc_techs_supply_plus) object 'X1:...
  * loc_techs_transmission                (loc_techs_transmission) object 'X3...
  * locs                                  (locs) object 'N1' 'X2' 'X1' 'X3'
  * techs                                 (techs) object 'pv' ... 'demand_heat'
  * timesteps                             (timesteps) datetime64[ns] 2005-07-...
Data variables: (12/38)
    energy_cap_max                        (loc_techs) float64 nan ... 600.0
    resource                              (loc_techs_finite_resource, timesteps) float64 ...
    resource_area_per_energy_cap          (loc_techs_area) int64 7 7 7
    force_resource                        (loc_techs_finite_resource) bool Tr...
    parasitic_eff                         (loc_techs_supply_plus) float64 0.8...
    resource_eff                          (loc_techs_finite_resource) float64 ...
    ...                                    ...
    lookup_loc_techs_conversion_plus      (carrier_tiers, loc_techs_conversion_plus) object ...
    lookup_loc_techs_export               (loc_techs_export) object 'X1::pv::...
    lookup_loc_techs_area                 (locs) object '' 'X2::pv' ... 'X3::pv'
    timestep_resolution                   (timesteps) float64 1.0 1.0 ... 1.0
    timestep_weights                      (timesteps) float64 1.0 1.0 ... 1.0
    max_demand_timesteps                  (carriers) datetime64[ns] 2005-07-0...
Attributes:
    calliope_version:    0.6.7-dev
    applied_overrides:   
    scenario:            None
    defaults:            available_area: null\ncarrier_ratios: false\ncharge_...
    allow_operate_mode:  1
In [12]:
# This is just a filtered view on the model_data Dataset, which includes all the information
# which will be sent to the solver
m._model_data
Out[12]:
<xarray.Dataset>
Dimensions:                                                      (carrier_tiers: 3, carriers: 3, coordinates: 2, costs: 1, loc_carriers: 10, loc_carriers_system_balance_constraint: 10, loc_carriers_update_system_balance_constraint: 3, loc_tech_carriers_carrier_consumption_max_constraint: 16, loc_tech_carriers_carrier_production_max_constraint: 19, loc_tech_carriers_con: 19, loc_tech_carriers_conversion_all: 4, loc_tech_carriers_conversion_plus: 3, loc_tech_carriers_demand: 6, loc_tech_carriers_export: 4, loc_tech_carriers_export_balance_constraint: 4, loc_tech_carriers_prod: 21, loc_tech_carriers_supply_all: 7, loc_tech_carriers_supply_conversion_all: 11, loc_techs: 26, loc_techs_area: 3, loc_techs_balance_conversion_constraint: 2, loc_techs_balance_conversion_plus_out_2_constraint: 1, loc_techs_balance_conversion_plus_primary_constraint: 1, loc_techs_balance_demand_constraint: 6, loc_techs_balance_supply_plus_constraint: 3, loc_techs_balance_transmission_constraint: 10, loc_techs_carrier_production_max_conversion_plus_constraint: 1, loc_techs_conversion: 2, loc_techs_conversion_all: 3, loc_techs_conversion_plus: 1, loc_techs_cost: 20, loc_techs_cost_constraint: 20, loc_techs_cost_investment_constraint: 20, loc_techs_cost_var_constraint: 6, loc_techs_cost_var_conversion_constraint: 2, loc_techs_cost_var_conversion_plus_constraint: 1, loc_techs_costs_export: 2, loc_techs_demand: 6, loc_techs_energy_capacity_constraint: 26, loc_techs_export: 4, loc_techs_finite_resource: 9, loc_techs_finite_resource_demand: 6, loc_techs_finite_resource_supply_plus: 3, loc_techs_investment_cost: 20, loc_techs_non_conversion: 23, loc_techs_non_transmission: 16, loc_techs_om_cost: 9, loc_techs_om_cost_conversion: 2, loc_techs_om_cost_conversion_plus: 1, loc_techs_om_cost_supply: 4, loc_techs_om_cost_supply_plus: 2, loc_techs_out_2: 1, loc_techs_resource_area_constraint: 3, loc_techs_resource_area_per_energy_capacity_constraint: 3, loc_techs_resource_availability_supply_plus_constraint: 3, loc_techs_resource_max_constraint: 3, loc_techs_supply: 4, loc_techs_supply_all: 7, loc_techs_supply_conversion_all: 10, loc_techs_supply_plus: 3, loc_techs_symmetric_transmission_constraint: 10, loc_techs_transmission: 10, loc_techs_update_costs_var_constraint: 3, locs: 4, locs_resource_area_capacity_per_loc_constraint: 3, resources: 4, techs: 9, techs_conversion: 1, techs_conversion_plus: 1, techs_demand: 2, techs_non_transmission: 7, techs_supply: 2, techs_supply_plus: 1, techs_transmission: 7, techs_transmission_names: 2, timesteps: 48)
Coordinates: (12/76)
  * carrier_tiers                                                (carrier_tiers) <U5 ...
  * carriers                                                     (carriers) <U11 ...
  * coordinates                                                  (coordinates) object ...
  * costs                                                        (costs) object ...
  * loc_carriers                                                 (loc_carriers) object ...
  * loc_carriers_system_balance_constraint                       (loc_carriers_system_balance_constraint) <U15 ...
    ...                                                           ...
  * techs_non_transmission                                       (techs_non_transmission) <U18 ...
  * techs_supply                                                 (techs_supply) <U17 ...
  * techs_supply_plus                                            (techs_supply_plus) <U2 ...
  * techs_transmission                                           (techs_transmission) <U14 ...
  * techs_transmission_names                                     (techs_transmission_names) <U11 ...
  * timesteps                                                    (timesteps) datetime64[ns] ...
Data variables: (12/38)
    energy_cap_max                                               (loc_techs) float64 ...
    resource                                                     (loc_techs_finite_resource, timesteps) float64 ...
    resource_area_per_energy_cap                                 (loc_techs_area) int64 ...
    force_resource                                               (loc_techs_finite_resource) bool ...
    parasitic_eff                                                (loc_techs_supply_plus) float64 ...
    resource_eff                                                 (loc_techs_finite_resource) float64 ...
    ...                                                           ...
    lookup_loc_techs_conversion_plus                             (carrier_tiers, loc_techs_conversion_plus) object ...
    lookup_loc_techs_export                                      (loc_techs_export) object ...
    lookup_loc_techs_area                                        (locs) object ...
    timestep_resolution                                          (timesteps) float64 ...
    timestep_weights                                             (timesteps) float64 ...
    max_demand_timesteps                                         (carriers) datetime64[ns] ...
Attributes:
    calliope_version:    0.6.7-dev
    applied_overrides:   
    scenario:            None
    defaults:            available_area: null\ncarrier_ratios: false\ncharge_...
    allow_operate_mode:  1
    model_config:        calliope_version: 0.6.7\nname: Urban-scale example m...
    run_config:          backend: pyomo\nbigM: 1000000.0\ncyclic_storage: tru...
In [13]:
# If timeseries aggregation of any kind has taken place, then m._model_data_original can be accessed to see the 
# model data prior to aggregation
m._model_data_original  # In this case, it is the same as m._model_data
Out[13]:
<xarray.Dataset>
Dimensions:                                                      (carrier_tiers: 3, carriers: 3, coordinates: 2, costs: 1, loc_carriers: 10, loc_carriers_system_balance_constraint: 10, loc_carriers_update_system_balance_constraint: 3, loc_tech_carriers_carrier_consumption_max_constraint: 16, loc_tech_carriers_carrier_production_max_constraint: 19, loc_tech_carriers_con: 19, loc_tech_carriers_conversion_all: 4, loc_tech_carriers_conversion_plus: 3, loc_tech_carriers_demand: 6, loc_tech_carriers_export: 4, loc_tech_carriers_export_balance_constraint: 4, loc_tech_carriers_prod: 21, loc_tech_carriers_supply_all: 7, loc_tech_carriers_supply_conversion_all: 11, loc_techs: 26, loc_techs_area: 3, loc_techs_balance_conversion_constraint: 2, loc_techs_balance_conversion_plus_out_2_constraint: 1, loc_techs_balance_conversion_plus_primary_constraint: 1, loc_techs_balance_demand_constraint: 6, loc_techs_balance_supply_plus_constraint: 3, loc_techs_balance_transmission_constraint: 10, loc_techs_carrier_production_max_conversion_plus_constraint: 1, loc_techs_conversion: 2, loc_techs_conversion_all: 3, loc_techs_conversion_plus: 1, loc_techs_cost: 20, loc_techs_cost_constraint: 20, loc_techs_cost_investment_constraint: 20, loc_techs_cost_var_constraint: 6, loc_techs_cost_var_conversion_constraint: 2, loc_techs_cost_var_conversion_plus_constraint: 1, loc_techs_costs_export: 2, loc_techs_demand: 6, loc_techs_energy_capacity_constraint: 26, loc_techs_export: 4, loc_techs_finite_resource: 9, loc_techs_finite_resource_demand: 6, loc_techs_finite_resource_supply_plus: 3, loc_techs_investment_cost: 20, loc_techs_non_conversion: 23, loc_techs_non_transmission: 16, loc_techs_om_cost: 9, loc_techs_om_cost_conversion: 2, loc_techs_om_cost_conversion_plus: 1, loc_techs_om_cost_supply: 4, loc_techs_om_cost_supply_plus: 2, loc_techs_out_2: 1, loc_techs_resource_area_constraint: 3, loc_techs_resource_area_per_energy_capacity_constraint: 3, loc_techs_resource_availability_supply_plus_constraint: 3, loc_techs_resource_max_constraint: 3, loc_techs_supply: 4, loc_techs_supply_all: 7, loc_techs_supply_conversion_all: 10, loc_techs_supply_plus: 3, loc_techs_symmetric_transmission_constraint: 10, loc_techs_transmission: 10, loc_techs_update_costs_var_constraint: 3, locs: 4, locs_resource_area_capacity_per_loc_constraint: 3, resources: 4, techs: 9, techs_conversion: 1, techs_conversion_plus: 1, techs_demand: 2, techs_non_transmission: 7, techs_supply: 2, techs_supply_plus: 1, techs_transmission: 7, techs_transmission_names: 2, timesteps: 48)
Coordinates: (12/76)
  * carriers                                                     (carriers) <U11 ...
  * timesteps                                                    (timesteps) datetime64[ns] ...
  * locs                                                         (locs) object ...
  * loc_techs_export                                             (loc_techs_export) object ...
  * loc_techs_conversion_plus                                    (loc_techs_conversion_plus) <U7 ...
  * loc_carriers                                                 (loc_carriers) object ...
    ...                                                           ...
  * loc_techs_cost_var_conversion_constraint                     (loc_techs_cost_var_conversion_constraint) <U10 ...
  * loc_techs_balance_conversion_plus_primary_constraint         (loc_techs_balance_conversion_plus_primary_constraint) <U7 ...
  * loc_techs_carrier_production_max_conversion_plus_constraint  (loc_techs_carrier_production_max_conversion_plus_constraint) <U7 ...
  * loc_techs_cost_var_conversion_plus_constraint                (loc_techs_cost_var_conversion_plus_constraint) <U7 ...
  * loc_techs_balance_conversion_plus_out_2_constraint           (loc_techs_balance_conversion_plus_out_2_constraint) <U7 ...
  * loc_techs_symmetric_transmission_constraint                  (loc_techs_symmetric_transmission_constraint) <U18 ...
Data variables: (12/38)
    energy_cap_max                                               (loc_techs) float64 ...
    resource                                                     (loc_techs_finite_resource, timesteps) float64 ...
    resource_area_per_energy_cap                                 (loc_techs_area) int64 ...
    force_resource                                               (loc_techs_finite_resource) bool ...
    parasitic_eff                                                (loc_techs_supply_plus) float64 ...
    resource_eff                                                 (loc_techs_finite_resource) float64 ...
    ...                                                           ...
    lookup_loc_techs_conversion_plus                             (loc_techs_conversion_plus, carrier_tiers) object ...
    lookup_loc_techs_export                                      (loc_techs_export) object ...
    lookup_loc_techs_area                                        (locs) object ...
    timestep_resolution                                          (timesteps) float64 ...
    timestep_weights                                             (timesteps) float64 ...
    max_demand_timesteps                                         (carriers) datetime64[ns] ...
Attributes:
    calliope_version:    0.6.7-dev
    applied_overrides:   
    scenario:            None
    defaults:            available_area: null\ncarrier_ratios: false\ncharge_...
    allow_operate_mode:  1
In [14]:
# We can find the same PV energy_cap_max data as seen in m._model_run
m._model_data.energy_cap_max.loc[{'loc_techs': 'X2::pv'}]
Out[14]:
<xarray.DataArray 'energy_cap_max' ()>
array(250.)
Coordinates:
    loc_techs  <U6 'X2::pv'
Attributes:
    is_result:  0
In [15]:
m._model_data.energy_cap_max.loc[{'loc_techs': 'X3::pv'}]
Out[15]:
<xarray.DataArray 'energy_cap_max' ()>
array(50.)
Coordinates:
    loc_techs  <U6 'X3::pv'
Attributes:
    is_result:  0
In [16]:
# We can also see the constraint-specific set of loc::techs for setting the energy capacity constraint
m._model_data.loc_techs_energy_capacity_constraint
Out[16]:
<xarray.DataArray 'loc_techs_energy_capacity_constraint' (loc_techs_energy_capacity_constraint: 26)>
array(['X2::demand_electricity', 'X3::power_lines:X1', 'X2::supply_gas',
       'X1::demand_heat', 'X3::boiler', 'X3::demand_heat', 'X3::supply_gas',
       'X1::heat_pipes:N1', 'N1::heat_pipes:X3', 'X2::demand_heat',
       'X3::demand_electricity', 'X1::supply_grid_power', 'X3::pv',
       'N1::heat_pipes:X2', 'X1::chp', 'X1::power_lines:X3',
       'N1::heat_pipes:X1', 'X1::pv', 'X2::power_lines:X1',
       'X1::power_lines:X2', 'X1::supply_gas', 'X1::demand_electricity',
       'X2::heat_pipes:N1', 'X3::heat_pipes:N1', 'X2::pv', 'X2::boiler'],
      dtype='<U22')
Coordinates:
  * loc_techs_energy_capacity_constraint  (loc_techs_energy_capacity_constraint) <U22 ...
In [17]:
# It is these constraint sets that we cannot see in m.inputs
m.inputs.loc_techs_energy_capacity_constraint
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-17-42f363389220> in <module>
      1 # It is these constraint sets that we cannot see in m.inputs
----> 2 m.inputs.loc_techs_energy_capacity_constraint

~/miniconda3/envs/calliope/lib/python3.8/site-packages/xarray/core/common.py in __getattr__(self, name)
    237                 with suppress(KeyError):
    238                     return source[name]
--> 239         raise AttributeError(
    240             "{!r} object has no attribute {!r}".format(type(self).__name__, name)
    241         )

AttributeError: 'Dataset' object has no attribute 'loc_techs_energy_capacity_constraint'

Run the model

In [18]:
m.run()
[2021-07-29 16:01:51] INFO     Backend: starting model run
[2021-07-29 16:01:52] INFO     Loading sets
[2021-07-29 16:01:52] INFO     Loading parameters
[2021-07-29 16:01:52] INFO     constraints are loaded in the following order: ['capacity', 'dispatch', 'policy', 'energy_balance', 'costs', 'network', 'conversion', 'group', 'conversion_plus', 'export', 'milp']
[2021-07-29 16:01:52] INFO     creating capacity constraints
[2021-07-29 16:01:52] INFO     creating dispatch constraints
[2021-07-29 16:01:52] INFO     creating policy constraints
[2021-07-29 16:01:52] INFO     creating energy_balance constraints
[2021-07-29 16:01:52] INFO     creating costs constraints
[2021-07-29 16:01:52] INFO     creating network constraints
[2021-07-29 16:01:52] INFO     creating conversion constraints
[2021-07-29 16:01:52] INFO     creating group constraints
[2021-07-29 16:01:52] INFO     creating conversion_plus constraints
[2021-07-29 16:01:52] INFO     creating export constraints
[2021-07-29 16:01:52] INFO     creating milp constraints
[2021-07-29 16:01:52] INFO     Backend: model generated. Time since start of model run: 0:00:00.631226
[2021-07-29 16:01:52] INFO     Backend: sending model to solver
[2021-07-29 16:01:52] INFO     Backend: solver finished running. Time since start of model run: 0:00:00.981061
[2021-07-29 16:01:52] INFO     Backend: loaded results
[2021-07-29 16:01:52] INFO     Backend: generated solution array. Time since start of model run: 0:00:01.057160
[2021-07-29 16:01:52] INFO     Postprocessing: started
[2021-07-29 16:01:53] INFO     Postprocessing: All values < 1e-10 set to 0 in system_balance
[2021-07-29 16:01:53] INFO     Postprocessing: ended. Time since start of model run: 0:00:01.166295
In [19]:
# Results are processed and merged into m.model data, and can be viewed in m.results
m.results
Out[19]:
<xarray.Dataset>
Dimensions:                                 (carriers: 3, costs: 1, loc_carriers: 10, loc_carriers_system_balance_constraint: 10, loc_tech_carriers_con: 19, loc_tech_carriers_export: 4, loc_tech_carriers_prod: 21, loc_techs: 26, loc_techs_area: 3, loc_techs_balance_demand_constraint: 6, loc_techs_cost: 20, loc_techs_cost_investment_constraint: 20, loc_techs_investment_cost: 20, loc_techs_om_cost: 9, loc_techs_supply_plus: 3, techs: 16, timesteps: 48)
Coordinates: (12/17)
  * carriers                                (carriers) <U11 'electricity' ......
  * loc_carriers                            (loc_carriers) object 'N1::heat' ...
  * loc_carriers_system_balance_constraint  (loc_carriers_system_balance_constraint) object ...
  * loc_tech_carriers_con                   (loc_tech_carriers_con) object 'N...
  * loc_tech_carriers_export                (loc_tech_carriers_export) object ...
  * loc_tech_carriers_prod                  (loc_tech_carriers_prod) object '...
    ...                                      ...
  * techs                                   (techs) object 'boiler' ... 'supp...
  * costs                                   (costs) object 'monetary'
  * loc_techs                               (loc_techs) object 'X2::demand_el...
  * loc_techs_area                          (loc_techs_area) object 'X1::pv' ...
  * loc_techs_supply_plus                   (loc_techs_supply_plus) object 'X...
  * timesteps                               (timesteps) datetime64[ns] 2005-0...
Data variables: (12/19)
    energy_cap                              (loc_techs) float64 269.3 ... 192.8
    carrier_prod                            (loc_tech_carriers_prod, timesteps) float64 ...
    carrier_con                             (loc_tech_carriers_con, timesteps) float64 ...
    cost                                    (costs, loc_techs_cost) float64 0...
    resource_area                           (loc_techs_area) float64 0.0 ... ...
    resource_con                            (loc_techs_supply_plus, timesteps) float64 ...
    ...                                      ...
    cost_investment_rhs                     (costs, loc_techs_cost_investment_constraint) float64 ...
    cost_var_rhs                            (costs, loc_techs_om_cost, timesteps) float64 ...
    capacity_factor                         (timesteps, loc_tech_carriers_prod) float64 ...
    systemwide_capacity_factor              (carriers, techs) float64 0.0 ......
    systemwide_levelised_cost               (carriers, costs, techs) float64 ...
    total_levelised_cost                    (carriers, costs) float64 0.08069...
Attributes:
    termination_condition:     optimal
    objective_function_value:  842.3529094335402
    solution_time:             1.05716
    time_finished:             2021-07-29 16:01:52
    calliope_version:          0.6.7-dev
    applied_overrides:         
    scenario:                  None
    defaults:                  available_area: null\ncarrier_ratios: false\nc...
    allow_operate_mode:        1
    model_config:              calliope_version: 0.6.7\nname: Urban-scale exa...
    run_config:                backend: pyomo\nbigM: 1000000.0\ncyclic_storag...
In [20]:
# As with inputs, the results dataset is a filtered view of m._model_data.
# All variables in `m.results` have the attribute `is_result` = 1
m._model_data.energy_cap
Out[20]:
<xarray.DataArray 'energy_cap' (loc_techs: 26)>
array([2.6934435e+02, 4.5778336e+01, 2.2685938e+02, 1.7197109e+00,
       1.5600000e-02, 9.3982291e+00, 1.8352941e-02, 5.9805562e+02,
       1.0382599e+01, 3.6513767e+02, 6.4927357e+01, 3.3620147e+01,
       5.0000000e+01, 1.9024262e+02, 2.6094670e+02, 4.5778336e+01,
       5.9805562e+02, 0.0000000e+00, 2.7451170e+02, 2.7451170e+02,
       6.4431283e+02, 1.3079378e+00, 1.9024262e+02, 1.0382599e+01,
       6.3309509e+01, 1.9283047e+02])
Coordinates:
  * loc_techs  (loc_techs) object 'X2::demand_electricity' ... 'X2::boiler'
Attributes:
    is_result:  1
In [21]:
# Data can also be reformatted to be easier to read (removes dimension concatenation).
# Conversion to a pandas DataFrame is a good idea for greater readibility.
m.get_formatted_array('energy_cap').to_pandas()
Out[21]:
techs boiler chp demand_electricity demand_heat heat_pipes:N1 heat_pipes:X1 heat_pipes:X2 heat_pipes:X3 power_lines:X1 power_lines:X2 power_lines:X3 pv supply_gas supply_grid_power
locs
N1 NaN NaN NaN NaN NaN 598.05562 190.24262 10.382599 NaN NaN NaN NaN NaN NaN
X1 NaN 260.9467 1.307938 1.719711 598.055620 NaN NaN NaN NaN 274.5117 45.778336 0.000000 644.312830 33.620147
X2 192.83047 NaN 269.344350 365.137670 190.242620 NaN NaN NaN 274.511700 NaN NaN 63.309509 226.859380 NaN
X3 0.01560 NaN 64.927357 9.398229 10.382599 NaN NaN NaN 45.778336 NaN NaN 50.000000 0.018353 NaN
In [22]:
# >2 dimensions cannot be easily viewed in a pandas dataframe, unless a MultiIndex is used.
# To view a 4-dimensional result, we can use `to_series()`
m.get_formatted_array('carrier_prod').to_series().dropna()  # drop_na() removes all NaN values
Out[22]:
carriers     locs  techs          timesteps          
electricity  X1    chp            2005-07-01 00:00:00    116.076700
                                  2005-07-01 01:00:00     98.082871
                                  2005-07-01 02:00:00     98.596008
                                  2005-07-01 03:00:00     98.596709
                                  2005-07-01 04:00:00    104.005810
                                                            ...    
heat         X3    heat_pipes:N1  2005-07-02 19:00:00      0.860291
                                  2005-07-02 20:00:00      0.015600
                                  2005-07-02 21:00:00      0.844700
                                  2005-07-02 22:00:00      0.000000
                                  2005-07-02 23:00:00      0.844690
Name: carrier_prod, Length: 1008, dtype: float64

backend_model

m._backend_model is a Pyomo data structure, attached to which are Pyomo objects including Sets, Parameters, Constraints, and Variables

In [23]:
# A set
m._backend_model.loc_techs_energy_capacity_constraint.pprint()
loc_techs_energy_capacity_constraint : Size=1, Index=None, Ordered=Insertion
    Key  : Dimen : Domain : Size : Members
    None :     1 :    Any :   26 : {'X2::demand_electricity', 'X3::power_lines:X1', 'X2::supply_gas', 'X1::demand_heat', 'X3::boiler', 'X3::demand_heat', 'X3::supply_gas', 'X1::heat_pipes:N1', 'N1::heat_pipes:X3', 'X2::demand_heat', 'X3::demand_electricity', 'X1::supply_grid_power', 'X3::pv', 'N1::heat_pipes:X2', 'X1::chp', 'X1::power_lines:X3', 'N1::heat_pipes:X1', 'X1::pv', 'X2::power_lines:X1', 'X1::power_lines:X2', 'X1::supply_gas', 'X1::demand_electricity', 'X2::heat_pipes:N1', 'X3::heat_pipes:N1', 'X2::pv', 'X2::boiler'}
In [24]:
# A Parameter
m._backend_model.energy_cap_max.pprint()
energy_cap_max : Size=26, Index=loc_techs, Domain=NonNegativeReals, Default=inf, Mutable=True
    Key                    : Value
         N1::heat_pipes:X1 : 2000.0
         N1::heat_pipes:X2 : 2000.0
         N1::heat_pipes:X3 : 2000.0
                   X1::chp : 1500.0
    X1::demand_electricity :    inf
           X1::demand_heat :    inf
         X1::heat_pipes:N1 : 2000.0
        X1::power_lines:X2 : 2000.0
        X1::power_lines:X3 : 2000.0
                    X1::pv :  250.0
            X1::supply_gas : 2000.0
     X1::supply_grid_power : 2000.0
                X2::boiler :  600.0
    X2::demand_electricity :    inf
           X2::demand_heat :    inf
         X2::heat_pipes:N1 : 2000.0
        X2::power_lines:X1 : 2000.0
                    X2::pv :  250.0
            X2::supply_gas : 2000.0
                X3::boiler :  600.0
    X3::demand_electricity :    inf
           X3::demand_heat :    inf
         X3::heat_pipes:N1 : 2000.0
        X3::power_lines:X1 : 2000.0
                    X3::pv :   50.0
            X3::supply_gas : 2000.0
In [25]:
# A constraint
m._backend_model.energy_capacity_constraint.pprint()
energy_capacity_constraint : Size=20, Index=loc_techs_energy_capacity_constraint, Active=True
    Key                   : Lower : Body                                : Upper                                   : Active
        N1::heat_pipes:X1 :   0.0 :     energy_cap['N1::heat_pipes:X1'] :     energy_cap_max['N1::heat_pipes:X1'] :   True
        N1::heat_pipes:X2 :   0.0 :     energy_cap['N1::heat_pipes:X2'] :     energy_cap_max['N1::heat_pipes:X2'] :   True
        N1::heat_pipes:X3 :   0.0 :     energy_cap['N1::heat_pipes:X3'] :     energy_cap_max['N1::heat_pipes:X3'] :   True
                  X1::chp :   0.0 :               energy_cap['X1::chp'] :               energy_cap_max['X1::chp'] :   True
        X1::heat_pipes:N1 :   0.0 :     energy_cap['X1::heat_pipes:N1'] :     energy_cap_max['X1::heat_pipes:N1'] :   True
       X1::power_lines:X2 :   0.0 :    energy_cap['X1::power_lines:X2'] :    energy_cap_max['X1::power_lines:X2'] :   True
       X1::power_lines:X3 :   0.0 :    energy_cap['X1::power_lines:X3'] :    energy_cap_max['X1::power_lines:X3'] :   True
                   X1::pv :   0.0 :                energy_cap['X1::pv'] :                energy_cap_max['X1::pv'] :   True
           X1::supply_gas :   0.0 :        energy_cap['X1::supply_gas'] :        energy_cap_max['X1::supply_gas'] :   True
    X1::supply_grid_power :   0.0 : energy_cap['X1::supply_grid_power'] : energy_cap_max['X1::supply_grid_power'] :   True
               X2::boiler :   0.0 :            energy_cap['X2::boiler'] :            energy_cap_max['X2::boiler'] :   True
        X2::heat_pipes:N1 :   0.0 :     energy_cap['X2::heat_pipes:N1'] :     energy_cap_max['X2::heat_pipes:N1'] :   True
       X2::power_lines:X1 :   0.0 :    energy_cap['X2::power_lines:X1'] :    energy_cap_max['X2::power_lines:X1'] :   True
                   X2::pv :   0.0 :                energy_cap['X2::pv'] :                energy_cap_max['X2::pv'] :   True
           X2::supply_gas :   0.0 :        energy_cap['X2::supply_gas'] :        energy_cap_max['X2::supply_gas'] :   True
               X3::boiler :   0.0 :            energy_cap['X3::boiler'] :            energy_cap_max['X3::boiler'] :   True
        X3::heat_pipes:N1 :   0.0 :     energy_cap['X3::heat_pipes:N1'] :     energy_cap_max['X3::heat_pipes:N1'] :   True
       X3::power_lines:X1 :   0.0 :    energy_cap['X3::power_lines:X1'] :    energy_cap_max['X3::power_lines:X1'] :   True
                   X3::pv :   0.0 :                energy_cap['X3::pv'] :                energy_cap_max['X3::pv'] :   True
           X3::supply_gas :   0.0 :        energy_cap['X3::supply_gas'] :        energy_cap_max['X3::supply_gas'] :   True
In [26]:
# A variable
m._backend_model.energy_cap.pprint()
energy_cap : Size=26, Index=loc_techs
    Key                    : Lower : Value       : Upper : Fixed : Stale : Domain
         N1::heat_pipes:X1 :     0 :   598.05562 :  None : False : False : NonNegativeReals
         N1::heat_pipes:X2 :     0 :   190.24262 :  None : False : False : NonNegativeReals
         N1::heat_pipes:X3 :     0 :   10.382599 :  None : False : False : NonNegativeReals
                   X1::chp :     0 :    260.9467 :  None : False : False : NonNegativeReals
    X1::demand_electricity :     0 :   1.3079378 :  None : False : False : NonNegativeReals
           X1::demand_heat :     0 :   1.7197109 :  None : False : False : NonNegativeReals
         X1::heat_pipes:N1 :     0 :   598.05562 :  None : False : False : NonNegativeReals
        X1::power_lines:X2 :     0 :    274.5117 :  None : False : False : NonNegativeReals
        X1::power_lines:X3 :     0 :   45.778336 :  None : False : False : NonNegativeReals
                    X1::pv :     0 :         0.0 :  None : False : False : NonNegativeReals
            X1::supply_gas :     0 :   644.31283 :  None : False : False : NonNegativeReals
     X1::supply_grid_power :     0 :   33.620147 :  None : False : False : NonNegativeReals
                X2::boiler :     0 :   192.83047 :  None : False : False : NonNegativeReals
    X2::demand_electricity :     0 :   269.34435 :  None : False : False : NonNegativeReals
           X2::demand_heat :     0 :   365.13767 :  None : False : False : NonNegativeReals
         X2::heat_pipes:N1 :     0 :   190.24262 :  None : False : False : NonNegativeReals
        X2::power_lines:X1 :     0 :    274.5117 :  None : False : False : NonNegativeReals
                    X2::pv :     0 :   63.309509 :  None : False : False : NonNegativeReals
            X2::supply_gas :     0 :   226.85938 :  None : False : False : NonNegativeReals
                X3::boiler :     0 :      0.0156 :  None : False : False : NonNegativeReals
    X3::demand_electricity :     0 :   64.927357 :  None : False : False : NonNegativeReals
           X3::demand_heat :     0 :   9.3982291 :  None : False : False : NonNegativeReals
         X3::heat_pipes:N1 :     0 :   10.382599 :  None : False : False : NonNegativeReals
        X3::power_lines:X1 :     0 :   45.778336 :  None : False : False : NonNegativeReals
                    X3::pv :     0 :        50.0 :  None : False : False : NonNegativeReals
            X3::supply_gas :     0 : 0.018352941 :  None : False : False : NonNegativeReals

Backend interface

There are a few interface methods available to the standard user, i.e. avoiding m._backend_model

In [27]:
# The inputs as used by Pyomo can be printed. This includes filled default data where necessary
pd.concat(
    (m.backend.access_model_inputs()['energy_cap_max'].to_pandas().rename('backend'),  # get the data from Pyomo
     m.inputs['energy_cap_max'].to_pandas().rename('pre-run')),  # get the data from model_data (via inputs)
    axis=1, sort=True
)
Out[27]:
backend pre-run
loc_techs
N1::heat_pipes:X1 2000.0 2000.0
N1::heat_pipes:X2 2000.0 2000.0
N1::heat_pipes:X3 2000.0 2000.0
X1::chp 1500.0 1500.0
X1::demand_electricity inf NaN
X1::demand_heat inf NaN
X1::heat_pipes:N1 2000.0 2000.0
X1::power_lines:X2 2000.0 2000.0
X1::power_lines:X3 2000.0 2000.0
X1::pv 250.0 250.0
X1::supply_gas 2000.0 2000.0
X1::supply_grid_power 2000.0 2000.0
X2::boiler 600.0 600.0
X2::demand_electricity inf NaN
X2::demand_heat inf NaN
X2::heat_pipes:N1 2000.0 2000.0
X2::power_lines:X1 2000.0 2000.0
X2::pv 250.0 250.0
X2::supply_gas 2000.0 2000.0
X3::boiler 600.0 600.0
X3::demand_electricity inf NaN
X3::demand_heat inf NaN
X3::heat_pipes:N1 2000.0 2000.0
X3::power_lines:X1 2000.0 2000.0
X3::pv 50.0 50.0
X3::supply_gas 2000.0 2000.0
In [28]:
# We can activate and deactivate constraints, such as switching off the energy capacity constraint

m.backend.activate_constraint('energy_capacity_constraint', False)  # set to True to activate
m._backend_model.energy_capacity_constraint.pprint()
energy_capacity_constraint : Size=20, Index=loc_techs_energy_capacity_constraint, Active=False
    Key                   : Lower : Body                                : Upper                                   : Active
        N1::heat_pipes:X1 :   0.0 :     energy_cap['N1::heat_pipes:X1'] :     energy_cap_max['N1::heat_pipes:X1'] :  False
        N1::heat_pipes:X2 :   0.0 :     energy_cap['N1::heat_pipes:X2'] :     energy_cap_max['N1::heat_pipes:X2'] :  False
        N1::heat_pipes:X3 :   0.0 :     energy_cap['N1::heat_pipes:X3'] :     energy_cap_max['N1::heat_pipes:X3'] :  False
                  X1::chp :   0.0 :               energy_cap['X1::chp'] :               energy_cap_max['X1::chp'] :  False
        X1::heat_pipes:N1 :   0.0 :     energy_cap['X1::heat_pipes:N1'] :     energy_cap_max['X1::heat_pipes:N1'] :  False
       X1::power_lines:X2 :   0.0 :    energy_cap['X1::power_lines:X2'] :    energy_cap_max['X1::power_lines:X2'] :  False
       X1::power_lines:X3 :   0.0 :    energy_cap['X1::power_lines:X3'] :    energy_cap_max['X1::power_lines:X3'] :  False
                   X1::pv :   0.0 :                energy_cap['X1::pv'] :                energy_cap_max['X1::pv'] :  False
           X1::supply_gas :   0.0 :        energy_cap['X1::supply_gas'] :        energy_cap_max['X1::supply_gas'] :  False
    X1::supply_grid_power :   0.0 : energy_cap['X1::supply_grid_power'] : energy_cap_max['X1::supply_grid_power'] :  False
               X2::boiler :   0.0 :            energy_cap['X2::boiler'] :            energy_cap_max['X2::boiler'] :  False
        X2::heat_pipes:N1 :   0.0 :     energy_cap['X2::heat_pipes:N1'] :     energy_cap_max['X2::heat_pipes:N1'] :  False
       X2::power_lines:X1 :   0.0 :    energy_cap['X2::power_lines:X1'] :    energy_cap_max['X2::power_lines:X1'] :  False
                   X2::pv :   0.0 :                energy_cap['X2::pv'] :                energy_cap_max['X2::pv'] :  False
           X2::supply_gas :   0.0 :        energy_cap['X2::supply_gas'] :        energy_cap_max['X2::supply_gas'] :  False
               X3::boiler :   0.0 :            energy_cap['X3::boiler'] :            energy_cap_max['X3::boiler'] :  False
        X3::heat_pipes:N1 :   0.0 :     energy_cap['X3::heat_pipes:N1'] :     energy_cap_max['X3::heat_pipes:N1'] :  False
       X3::power_lines:X1 :   0.0 :    energy_cap['X3::power_lines:X1'] :    energy_cap_max['X3::power_lines:X1'] :  False
                   X3::pv :   0.0 :                energy_cap['X3::pv'] :                energy_cap_max['X3::pv'] :  False
           X3::supply_gas :   0.0 :        energy_cap['X3::supply_gas'] :        energy_cap_max['X3::supply_gas'] :  False
In [29]:
# Rerun the model with this constraint switched off. 
# This will dump results to a new dataset, *NOT* to m._model_data (or m.results)
new_model = m.backend.rerun()
[2021-07-29 16:02:07] INFO     model_creation
[2021-07-29 16:02:07] INFO     Backend: starting model run
[2021-07-29 16:02:07] INFO     Backend: sending model to solver
[2021-07-29 16:02:07] INFO     Backend: solver finished running. Time since start of model run: 0:00:00.369686
[2021-07-29 16:02:07] INFO     Backend: loaded results
[2021-07-29 16:02:07] INFO     Backend: generated solution array. Time since start of model run: 0:00:00.459862
[2021-07-29 16:02:07] INFO     Postprocessing: started
[2021-07-29 16:02:07] INFO     Postprocessing: All values < 1e-10 set to 0 in system_balance
[2021-07-29 16:02:07] INFO     Postprocessing: ended. Time since start of model run: 0:00:00.566121
[2021-07-29 16:02:07] WARNING  /Users/brynmorp/Repos/calliope-project/calliope/calliope/exceptions.py:60: ModelWarning:

The results of rerunning the backend model are only available within the Calliope model returned by this function call.


[2021-07-29 16:02:07] INFO     Model: initialising
[2021-07-29 16:02:07] INFO     Model: loaded model_data
In [30]:
# The results are now updated, which we can compare to our old results
pd.concat((new_model.results.energy_cap.to_pandas().rename('new'), m.results.energy_cap.to_pandas().rename('old')), 
          axis=1, sort=True)
Out[30]:
new old
loc_techs
N1::heat_pipes:X1 577.990760 598.055620
N1::heat_pipes:X2 184.854000 190.242620
N1::heat_pipes:X3 10.382599 10.382599
X1::chp 253.679380 260.946700
X1::demand_electricity 1.307938 1.307938
X1::demand_heat 1.719711 1.719711
X1::heat_pipes:N1 577.990760 598.055620
X1::power_lines:X2 274.841170 274.511700
X1::power_lines:X3 66.370659 45.778336
X1::pv 0.000000 0.000000
X1::supply_gas 626.368830 644.312830
X1::supply_grid_power 40.808044 33.620147
X2::boiler 197.824970 192.830470
X2::demand_electricity 269.344350 269.344350
X2::demand_heat 365.137670 365.137670
X2::heat_pipes:N1 184.854000 190.242620
X2::power_lines:X1 274.841170 274.511700
X2::pv 0.000000 63.309509
X2::supply_gas 232.735260 226.859380
X3::boiler 0.015600 0.015600
X3::demand_electricity 64.927357 64.927357
X3::demand_heat 9.398229 9.398229
X3::heat_pipes:N1 10.382599 10.382599
X3::power_lines:X1 66.370659 45.778336
X3::pv 128.571430 50.000000
X3::supply_gas 0.018353 0.018353
In [31]:
# We can also see that the Pyomo backend_model has updated to the new values 
m._backend_model.energy_cap.pprint()
energy_cap : Size=26, Index=loc_techs
    Key                    : Lower : Value       : Upper : Fixed : Stale : Domain
         N1::heat_pipes:X1 :     0 :   577.99076 :  None : False : False : NonNegativeReals
         N1::heat_pipes:X2 :     0 :     184.854 :  None : False : False : NonNegativeReals
         N1::heat_pipes:X3 :     0 :   10.382599 :  None : False : False : NonNegativeReals
                   X1::chp :     0 :   253.67938 :  None : False : False : NonNegativeReals
    X1::demand_electricity :     0 :   1.3079378 :  None : False : False : NonNegativeReals
           X1::demand_heat :     0 :   1.7197109 :  None : False : False : NonNegativeReals
         X1::heat_pipes:N1 :     0 :   577.99076 :  None : False : False : NonNegativeReals
        X1::power_lines:X2 :     0 :   274.84117 :  None : False : False : NonNegativeReals
        X1::power_lines:X3 :     0 :   66.370659 :  None : False : False : NonNegativeReals
                    X1::pv :     0 :         0.0 :  None : False : False : NonNegativeReals
            X1::supply_gas :     0 :   626.36883 :  None : False : False : NonNegativeReals
     X1::supply_grid_power :     0 :   40.808044 :  None : False : False : NonNegativeReals
                X2::boiler :     0 :   197.82497 :  None : False : False : NonNegativeReals
    X2::demand_electricity :     0 :   269.34435 :  None : False : False : NonNegativeReals
           X2::demand_heat :     0 :   365.13767 :  None : False : False : NonNegativeReals
         X2::heat_pipes:N1 :     0 :     184.854 :  None : False : False : NonNegativeReals
        X2::power_lines:X1 :     0 :   274.84117 :  None : False : False : NonNegativeReals
                    X2::pv :     0 :         0.0 :  None : False : False : NonNegativeReals
            X2::supply_gas :     0 :   232.73526 :  None : False : False : NonNegativeReals
                X3::boiler :     0 :      0.0156 :  None : False : False : NonNegativeReals
    X3::demand_electricity :     0 :   64.927357 :  None : False : False : NonNegativeReals
           X3::demand_heat :     0 :   9.3982291 :  None : False : False : NonNegativeReals
         X3::heat_pipes:N1 :     0 :   10.382599 :  None : False : False : NonNegativeReals
        X3::power_lines:X1 :     0 :   66.370659 :  None : False : False : NonNegativeReals
                    X3::pv :     0 :   128.57143 :  None : False : False : NonNegativeReals
            X3::supply_gas :     0 : 0.018352941 :  None : False : False : NonNegativeReals

Plot

In [32]:
# With the original data (i.e. capacity constraint is active), we can plot the capacities
m.plot.capacity()
[2021-07-29 16:02:13] WARNING  /Users/brynmorp/Repos/calliope-project/calliope/calliope/postprocess/plotting/plotting.py:105: FutureWarning:

Plotting will no longer be available as a method of the Calliope model object infuture versions of Calliope. In the meantime, as of v0.6.6, plotting is untested; this functionality should now be used with caution. We expect to reintroduce it as a seperate module in v0.7.0.