Advanced constraints¶
On this page, we look at some of the more advanced features of Calliope's math and configuration that can help you understand the breadth of what we offer.
See also
Base math formulation, Model definition schema, Introducing custom math to your model, "MILP" example model.
Multiple input/output carriers¶
Most technologies will define one carrier in and/or out. However, there exist technologies that co-produce different carriers or have the option to switch between consuming/producing different carriers. For example:
- Combined heat and power (CHP) plants - one carrier in, two co-produced carriers out.
- Heat pumps - one carrier in, the option to output cooling or heating.
- Partially retrofitted coal power plants - possibility to consume coal or biofuel, electricity as the only carrier out.
- Tracking auxiliary flows - nuclear power plants produce electricity and nuclear waste.
As of Calliope v0.7, these multiple carriers are defined as a list in YAML. E.g.,
techs:
chp:
name: Combined heat and power (CHP) plant
carrier_in: gas
carrier_out: [electricity, heat]
ashp:
name: Air source heat pump
carrier_in: electricity
carrier_out: [cooling, heat]
slightly_cleaner_coal_plant:
name: Dual fuel coal fired power station
carrier_in: [coal, biofuel]
carrier_out: electricity
nuclear:
name: Nuclear power station
carrier_out: [electricity, nuclear_waste]
The default math applied to these multiple carriers is that inflow carrier requirements are based on the sum of the outflow carriers and vice-versa (see the base math). This is valid for our heat pump and coal-fired power plant examples above, but not the nuclear and CHP examples. In these examples, the inflow is linked to a specific outflow (gas / nuclear fuel consumption is a function of electricity production). The other carrier outflows are then linked to the "primary" outflow.
To capture this slightly different math, you will need to apply your own custom math. For example, the CHP example is dealt with in our urban scale example model and in an example custom math file.
No matter how you formulate your math, you can (and probably will need to) extend your technology parameters to account for these different carriers.
For instance, to differentiate flow_cap_max
between carriers or to assign different conversion efficiencies / costs:
techs:
chp:
name: Combined heat and power (CHP) plant
carrier_in: gas
carrier_out: [electricity, heat]
flow_cap_max:
data: 100
index: electricity
dims: carriers
cost_flow_cap:
data: 0.1
index: [[electricity, monetary]]
dims: [carriers, costs]
ashp:
name: Air source heat pump
carrier_in: electricity
carrier_out: [cooling, heat]
flow_out_eff:
data: [3, 4]
index: [cooling, heat]
dims: carriers
slightly_cleaner_coal_plant:
name: Dual fuel coal fired power station
carrier_in: [coal, biofuel]
carrier_out: electricity
cost_flow_in:
data: [0.1, 0.5]
index: [[coal, monetary], [biofuel, monetary]]
dims: [carriers, costs]
nuclear:
name: Nuclear power station
carrier_out: [electricity, nuclear_waste]
waste_per_flow_out: 0.1 # (1)!
- This is a user-defined parameter that you won't find in our list of internal parameters. You can use it in your custom math to link nuclear waste outflow with electricity outflow.
Activating storage buffers in non-storage technologies¶
As their name suggests, storage
technologies can store carriers between timesteps.
In addition, any other abstract base technology can define a storage buffer using include_storage: true
.
This means that any inflow into the technology can be stored between timesteps and released from that technology as an outflow at a later timestep.
You may like to use this if you have a supply
source that can be stored within the system before being used to produce a carrier (think superheated fluid in a concentrated solar power array, biomass in a biogas plant, etc.),
or if you want your stored carrier to be converted on outflow (i.e., within a conversion
technology).
Revenues and carrier export¶
It is possible to specify revenues for technologies simply by setting a negative cost value. For example, to consider a feed-in tariff for PV generation, it could be given a negative operational cost equal to the real operational cost minus the level of feed-in tariff received.
Export is an extension of this, allowing a carrier to be removed from the system without meeting demand. This is analogous to e.g. domestic PV technologies being able to export excess electricity to the national grid. A cost (or negative cost: revenue) can then be applied to export. There is an example of this in our urban scale example model.
Note
Negative costs can be applied to capacity costs, but the user must an ensure a capacity limit has been set. Otherwise, optimisation will fail due to being unbounded.
Area use constraints¶
Several optional constraints can be used to specify area-related restrictions on technology use.
These constraints may reflect the fact that resources scale with area of deployed technology (think solar panels or biofuel crops).
Here you would use source_unit: per_area
for your supply
technology.
These constraints may also reflect limits on deployment according to available space (think limited rooftop space for solar panels or land available for biofuel crop cultivation).
Here you would use area_use_min/max
and then link area use with technology flow capacity with area_use_per_flow_cap
, which forces area_use
to follow flow_cap
with the given numerical ratio (e.g. setting to 1.5 means that area_use == 1.5 * flow_cap
).
At a given node, you may also have a limited amount of space that technologies need to compete for.
Setting available_area
at a node will force the combined area_use
of all technologies at that node to a given value.
One way transmission links¶
Transmission links are bidirectional by default.
To force unidirectionality for a given technology along a given link, you have to set the one_way
constraint in the definition of that technology:
This will only allow transmission from region1
to region2
.
To swap the direction, to
and from
must be swapped.
Per-distance transmission constraints¶
Transmission technologies can additionally specify per-distance efficiency (loss) with flow_out_eff_per_distance
and per-distance costs with cost_flow_cap_per_distance
:
techs:
my_transmission_tech:
# "efficiency" (1-loss) per unit of distance
flow_out_eff_per_distance: 0.99
cost_flow_cap_per_distance:
data: 10
index: monetary
dims: costs
distance: 500
The distance can be specified in transmission links (as above) or, if no distance is given, from node latitude
and longitude
coordinates.
In the latter case, Calliope will compute distances automatically based on the length of a straight line connecting the locations, following the curvature of the earth.
Note
Automatically derived distance values are provided in kilometres.
If your model has a small geographic scope, you may prefer to use metres.
You can update the configuration option config.init.distance_unit
to reflect this preference.
Cyclic storage¶
For any technologies with storage (storage
technologies or those with storage buffer), it is possible to link the storage at either end of the timeseries using the cyclic_storage
parameter.
This allows the user to better represent multiple years by just modelling one year.
Cyclic storage is activated by default (to deactivate: cyclic_storage: false
in all storage technologies).
As a result, a technology's initial stored energy at a given location will be equal to its stored energy at the end of the model's last timestep.
For example, for a model running over a full year at hourly resolution, the initial storage at Jan 1st 00:00
will be forced equal to the storage at the end of the timestep Dec 31st 23:00
.
By setting storage_initial
for a technology, it is also possible to fix the value in the last timestep.
For instance, with cyclic_storage: true
and a storage_initial: 0
, the stored energy must be zero by the end of the time horizon.
Without cyclic storage in place, technologies can have any amount of stored energy by the end of the timeseries. This may prove useful in some cases, but makes little sense if you imagine your technologies operating in the same manner year-on-year. Any excess stored energy would result in double the excess the following year, and so on.
Note
Cyclic storage also functions when time clustering, if allowing storage to be tracked between clusters.
However, it cannot be used in operate
run mode.