urbs.py module description¶
Overview¶
The following is a minimum “hello world” script that shows the life cycle of
the optimization object prob, and how the various urbs
module
functions create it, modify it and process it.:
import urbs
from pyomo.opt.base import SolverFactory
# read input, create optimisation problem
data = urbs.read_excel('mimo-example.xlsx')
prob = urbs.create_model(data)
# solve problem, read results
optim = SolverFactory('glpk')
result = optim.solve(prob)
prob.solutions.load_from(result)
# save problem instance (incl. input and result) for later analyses
urbs.save(prob, 'mimo-example.pgz')
# write report and plot timeseries
urbs.report(prob, 'report.xlsx')
urbs.plot(prob, 'Elec', 'Mid')
The following lists and describes the use of all module-level functions. They are roughly ordered from high-level to low-level access, followed by helper functions.
Create model¶
-
urbs.
read_excel
(filename)¶ Parameters: filename (str) – spreadsheet filename Returns: urbs input dict The spreadsheet must contain 7 sheets labelled ‘Commodity’, ‘Process’, ‘Process-Commodity’, ‘Transmission’, ‘Storage’, ‘Demand’ and ‘SupIm’. It can contain 2 additional sheets called ‘Buy-Sell-Price’ and ‘Hacks’. If present, function
add_hacks()
is called bycreate_model()
upon model creation.Refer to the mimo-example.xlsx file for exemplary documentation of the table contents and definitions of all attributes by selecting the column titles.
-
urbs.
create_model
(data, timesteps)¶ Returns a Pyomo ConcreteModel object.
Parameters: - data (dict) – input like created by
read_excel()
- timesteps (list) – consecutive list of modelled timesteps
Returns: urbs model object
Timestep numbers must match those of the demand and supim timeseries.
If argument
data
has the key'hacks'
, functionadd_hacks()
is called withdata['hacks']
as the second argument.- data (dict) – input like created by
-
urbs.
add_hacks
(model, hacks)¶ Is called by
create_model()
to add special elements, e.g. constraints, to the model. Each hack, if present, can trigger the creation of additional sets, parameters, variables or constraints. Refer to the code of this function to see which hacks exists and what they do.
As of v0.3, only one hack exists: if a line “Global CO2 limit” exists in the hacks DataFrame, its value is used as a global upper limit for a constraint that limits the annual creation of the commodity “CO2”.
param model: urbs model object (not instance!) param hacks: a DataFrame of hacks return model: the modified urbs model object
Report & plotting¶
These two high-level functions cover the envisioned use of the unmodified urbs model and should cover most use cases.
-
urbs.
plot
(prob, com, sit[, timesteps=None])¶ Parameters: Return fig: matplotlib figure handle
-
urbs.
report
(prob, filename, commodities, sites)¶ Write optimisation result summary to spreadsheet.
Parameters:
Retrieve results¶
While report()
and plot()
are quite flexible, custom
result analysis scripts might be needed. These can be built on top of the
following two medium-level functions. They retrieve all time-dependent and
-independent quantities and return them as ready-to-use DataFrames.
-
urbs.
get_constants
(prob)¶ Return summary DataFrames for time-independent variables
Parameters: prob – urbs model instance Returns: tuple of constants (costs, process, transmission, storage)
-
urbs.
get_timeseries
(prob, com, sit, timesteps=None)¶ Return DataFrames of all timeseries referring to a given commodity and site
Parameters: Returns: tuple of timeseries (created, consumed, storage, imported, exported) tuple of DataFrames timeseries. These are:
- created: timeseries of commodity creation, including stock source
- consumed: timeseries of commodity consumption, including demand
- storage: timeseries of commodity storage (level, stored, retrieved)
- imported: timeseries of commodity import (by site)
- exported: timeseries of commodity export (by site)
Persistence¶
To store valuable results for later analysis, or cross-scenario comparisons
weeks after the original run, saving a problem instance with loaded results
makes it possible to use one’s comparison scripts without having to solve the
optimisation problem again. Simply load()
the previously stored object
using save()
:
-
urbs.
save
(prob, filename)¶ Save rivus model instance to a gzip’ed pickle file
Pickle is the standard Python way of serializing and de-serializing Python objects. By using it, saving any object, in case of this function a Pyomo ConcreteModel, becomes a twoliner.
GZip is a standard Python compression library that is used to transparently compress the pickle file further.
It is used over the possibly more compact bzip2 compression due to the lower runtime. Source: <http://stackoverflow.com/a/18475192/2375855>
Parameters: - prob – a rivus model instance
- filename (str) – pickle file to be written
Returns: nothing
Low-level access¶
If the previous functions still don’t cut it, there are three low-level functions.
-
urbs.
list_entities
(prob, entity_type)¶ Parameters: - prob – urbs model instance
- entity_type (str) – allowed values: set, par, var, con, obj
Returns: a DataFrame with name, description and domain of entities
-
urbs.
get_entity
(prob, name)¶ Parameters: - prob – urbs model instance
- name (str) – name of a model entity
Returns: Series with values of model entity
-
urbs.
get_entities
(prob, names)¶ Parameters: - prob – urbs model instance
- name (list) – list of model entity names
Returns: DataFrame with values entities in columns
Only call
get_entities
for entities that share identical domains. This can be checked withlist_entities()
. For example, variablecap_pro
naturally has the same domain ascap_pro_new
.
Helper functions¶
-
urbs.
annuity_factor
(n, i)¶ Annuity factor formula.
Evaluates the annuity factor formula for depreciation duration and interest rate. Works also well for equally sized numpy arrays as input.
Parameters: Returns: value of the expression \(\frac{(1+i)^n i}{(1+i)^n - 1}\)
-
urbs.
commodity_balance
(m, tm, sit, com)¶ Calculate commodity balance at given timestep.
For a given commodity, site and timestep, calculate the balance of consumed (to process/storage/transmission, counts positive) and provided (from process/storage/transmission, counts negative) energy. Used as helper function in
create_model()
for defining constraints on demand and stock commodities.Parameters: - m – the ConcreteModel object
- tm – the timestep number
- sit – the site
- co – the commodity
Returns: amount of consumed (positive) or provided (negative) energy
-
urbs.
split_columns
(columns[, sep='.'])¶ Given a list of column labels containing a separator string (default: ‘.’), derive a MulitIndex that is split at the separator string.
Parameters: Returns: a MultiIndex corresponding to input, with levels split at separator
-
urbs.
to_color
(obj=None)¶ Assign a deterministic pseudo-random color to argument.
If
COLORS[obj]
is set, return that. Otherwise, create a deterministically random color from thehash()
of that object. For strings, this value depends only on the string content, so that identical strings always yield the same color.Parameters: obj – any hashable object Returns: a (r,g,b) tuple if COLORS[obj] exists, otherwise a hexstring
-
urbs.
COLORS
¶ dict
of process and site colors. Colors are stored as (r,g,b) tuples in range 0-255 each. To retrieve a color in a form usable with matplotlib, used the helper functionto_color()
.This snippet from the example script runme.py shows how to add custom colors:
# add or change plot colours my_colors = { 'South': (230, 200, 200), 'Mid': (200, 230, 200), 'North': (200, 200, 230)} for country, color in my_colors.items(): urbs.COLORS[country] = color