# Mathematical formulation¶

This section details the mathematical formulation of the different components. For each component, a link to the actual implementing function in the Calliope code is given.

## Decision variables¶

calliope.backend.pyomo.variables.initialize_decision_variables(backend_model)[source]

Defines decision variables.

Variable

Dimensions

energy_cap

loc_techs

carrier_prod

loc_tech_carriers_prod, timesteps

carrier_con

loc_tech_carriers_con, timesteps

cost

costs, loc_techs_cost

resource_area

loc_techs_area,

storage_cap

loc_techs_store

storage

loc_techs_store, timesteps

resource_con

loc_techs_supply_plus, timesteps

resource_cap

loc_techs_supply_plus

carrier_export

loc_tech_carriers_export, timesteps

cost_var

costs, loc_techs_om_cost, timesteps

cost_investment

costs, loc_techs_investment_cost

purchased

loc_techs_purchase

units

loc_techs_milp

operating_units

loc_techs_milp, timesteps

unmet_demand

loc_carriers, timesteps

unused_supply

loc_carriers, timesteps

## Objective functions¶

calliope.backend.pyomo.objective.minmax_cost_optimization(backend_model)[source]

Minimize or maximise total system cost for specified cost class or a set of cost classes. cost_class is a string or dictionary. If a string, it is automatically converted to a dictionary with a single key:value pair where value == 1. The dictionary provides a weight for each cost class of interest: {cost_1: weight_1, cost_2: weight_2, etc.}.

If unmet_demand is in use, then the calculated cost of unmet_demand is added or subtracted from the total cost in the opposite sense to the objective.

\begin{align}\begin{aligned}min: z = \sum_{loc::tech_{cost},k} (cost(loc::tech, cost=cost_{k}) \times weight_{k}) + \sum_{loc::carrier,timestep} (unmet\_demand(loc::carrier, timestep) \times bigM)\\max: z = \sum_{loc::tech_{cost},k} (cost(loc::tech, cost=cost_{k}) \times weight_{k}) - \sum_{loc::carrier,timestep} (unmet\_demand(loc::carrier, timestep) \times bigM)\end{aligned}\end{align}
calliope.backend.pyomo.objective.check_feasibility(backend_model)[source]

Dummy objective, to check that there are no conflicting constraints.

$min: z = 1$

## Energy Balance¶

calliope.backend.pyomo.constraints.energy_balance.system_balance_constraint_rule(backend_model, loc_carrier, timestep)[source]

System balance ensures that, within each location, the production and consumption of each carrier is balanced.

$\sum_{loc::tech::carrier_{prod} \in loc::carrier} \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) + \sum_{loc::tech::carrier_{con} \in loc::carrier} \boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) + \sum_{loc::tech::carrier_{export} \in loc::carrier} \boldsymbol{carrier_{export}}(loc::tech::carrier, timestep) \quad \forall loc::carrier \in loc::carriers, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.energy_balance.balance_supply_constraint_rule(backend_model, loc_tech, timestep)[source]

Limit production from supply techs to their available resource

$min\_use(loc::tech) \times available\_resource(loc::tech, timestep) \leq \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{\eta_{energy}(loc::tech, timestep)} \geq available\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{supply}, \forall timestep \in timesteps$

If $$force\_resource(loc::tech)$$ is set:

$\frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{\eta_{energy}(loc::tech, timestep)} = available\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{supply}, \forall timestep \in timesteps$

Where:

$available\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource\_scale(loc::tech)$

if $$loc::tech$$ is in $$loc::techs_{area}$$:

$available\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource\_scale(loc::tech) \times \boldsymbol{resource_{area}}(loc::tech)$
calliope.backend.pyomo.constraints.energy_balance.balance_demand_constraint_rule(backend_model, loc_tech, timestep)[source]

Limit consumption from demand techs to their required resource.

$\boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) \geq required\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{demand}, \forall timestep \in timesteps$

If $$force\_resource(loc::tech)$$ is set:

$\boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) = required\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{demand}, \forall timestep \in timesteps$

Where:

$required\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource\_scale(loc::tech)$

if $$loc::tech$$ is in $$loc::techs_{area}$$:

$required\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource\_scale(loc::tech) \times \boldsymbol{resource_{area}}(loc::tech)$
calliope.backend.pyomo.constraints.energy_balance.resource_availability_supply_plus_constraint_rule(backend_model, loc_tech, timestep)[source]

Limit production from supply_plus techs to their available resource.

$\boldsymbol{resource_{con}}(loc::tech, timestep) \leq available\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{supply^{+}}, \forall timestep \in timesteps$

If $$force\_resource(loc::tech)$$ is set:

$\boldsymbol{resource_{con}}(loc::tech, timestep) = available\_resource(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{supply^{+}}, \forall timestep \in timesteps$

Where:

$available\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource_{scale}(loc::tech)$

if $$loc::tech$$ is in $$loc::techs_{area}$$:

$available\_resource(loc::tech, timestep) = resource(loc::tech, timestep) \times resource_{scale}(loc::tech) \times resource_{area}(loc::tech)$
calliope.backend.pyomo.constraints.energy_balance.balance_transmission_constraint_rule(backend_model, loc_tech, timestep)[source]

Balance carrier production and consumption of transmission technologies

$-1 * \boldsymbol{carrier_{con}}(loc_{from}::tech:loc_{to}::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) = \boldsymbol{carrier_{prod}}(loc_{to}::tech:loc_{from}::carrier, timestep) \quad \forall loc::tech:loc \in locs::techs:locs_{transmission}, \forall timestep \in timesteps$

Where a link is the connection between $$loc_{from}::tech:loc_{to}$$ and $$loc_{to}::tech:loc_{from}$$ for locations to and from.

calliope.backend.pyomo.constraints.energy_balance.balance_supply_plus_constraint_rule(backend_model, loc_tech, timestep)[source]

Balance carrier production and resource consumption of supply_plus technologies alongside any use of resource storage.

$\boldsymbol{storage}(loc::tech, timestep) = \boldsymbol{storage}(loc::tech, timestep_{previous}) \times (1 - storage\_loss(loc::tech, timestep))^{timestep\_resolution(timestep)} + \boldsymbol{resource_{con}}(loc::tech, timestep) \times \eta_{resource}(loc::tech, timestep) - \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{\eta_{energy}(loc::tech, timestep) \times \eta_{parasitic}(loc::tech, timestep)} \quad \forall loc::tech \in loc::techs_{supply^{+}}, \forall timestep \in timesteps$

If no storage is defined for the technology, this reduces to:

$\boldsymbol{resource_{con}}(loc::tech, timestep) \times \eta_{resource}(loc::tech, timestep) = \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{\eta_{energy}(loc::tech, timestep) \times \eta_{parasitic}(loc::tech, timestep)} \quad \forall loc::tech \in loc::techs_{supply^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.energy_balance.balance_storage_constraint_rule(backend_model, loc_tech, timestep)[source]

Balance carrier production and consumption of storage technologies, alongside any use of the stored volume.

$\boldsymbol{storage}(loc::tech, timestep) = \boldsymbol{storage}(loc::tech, timestep_{previous}) \times (1 - storage\_loss(loc::tech, timestep))^{resolution(timestep)} - \boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) - \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{\eta_{energy}(loc::tech, timestep)} \quad \forall loc::tech \in loc::techs_{storage}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.energy_balance.balance_storage_inter_cluster_rule(backend_model, loc_tech, datestep)[source]

When clustering days, to reduce the timeseries length, balance the daily stored energy across all days of the original timeseries.

Ref: DOI 10.1016/j.apenergy.2018.01.023

$\boldsymbol{storage_{inter\_cluster}}(loc::tech, datestep) = \boldsymbol{storage_{inter\_cluster}}(loc::tech, datestep_{previous}) \times (1 - storage\_loss(loc::tech, timestep))^{24} + \boldsymbol{storage}(loc::tech, timestep_{final, cluster(datestep))}) \quad \forall loc::tech \in loc::techs_{store}, \forall datestep \in datesteps$

Where $$timestep_{final, cluster(datestep_{previous}))}$$ is the final timestep of the cluster in the clustered timeseries corresponding to the previous day

calliope.backend.pyomo.constraints.energy_balance.storage_initial_rule(backend_model, loc_tech)[source]

If storage is cyclic, allow an initial storage to still be set. This is applied to the storage of the final timestep/datestep of the series as that, in cyclic storage, is the ‘storage_previous_step’ for the first timestep/datestep.

If clustering and storage_inter_cluster exists:

$\boldsymbol{storage_{inter\_cluster}}(loc::tech, datestep_{final}) \times ((1 - storage_loss) ** 24) = storage_{initial}(loc::tech) \times storage_{cap}(loc::tech) \quad \forall loc::tech \in loc::techs_{store}, \forall datestep \in datesteps$

Where $$datestep_{final}$$ is the last datestep of the timeseries

Else: .. container:: scrolling-wrapper

$\boldsymbol{storage}(loc::tech, timestep_{final}) \times ((1 - storage_loss) ** 24) = storage_{initial}(loc::tech) \times storage_{cap}(loc::tech) \quad \forall loc::tech \in loc::techs_{store}, \forall timestep \in timesteps$

Where $$timestep_{final}$$ is the last timestep of the timeseries

## Capacity¶

calliope.backend.pyomo.constraints.capacity.storage_capacity_constraint_rule(backend_model, loc_tech)[source]

Set maximum storage capacity. Supply_plus & storage techs only

The first valid case is applied:

$\begin{split}\boldsymbol{storage_{cap}}(loc::tech) \begin{cases} = storage_{cap, equals}(loc::tech),& \text{if } storage_{cap, equals}(loc::tech)\\ \leq storage_{cap, max}(loc::tech),& \text{if } storage_{cap, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs_{store}\end{split}$

and (if equals not enforced):

$\boldsymbol{storage_{cap}}(loc::tech) \geq storage_{cap, min}(loc::tech) \quad \forall loc::tech \in loc::techs_{store}$
calliope.backend.pyomo.constraints.capacity.energy_capacity_storage_constraint_rule_old(backend_model, loc_tech)[source]

Set an additional energy capacity constraint on storage technologies, based on their use of charge_rate.

This is deprecated and will be removed in Calliope 0.7.0. Instead of charge_rate, please use energy_cap_per_storage_cap_max.

$\boldsymbol{energy_{cap}}(loc::tech) \leq \boldsymbol{storage_{cap}}(loc::tech) \times charge\_rate(loc::tech) \quad \forall loc::tech \in loc::techs_{store}$
calliope.backend.pyomo.constraints.capacity.energy_capacity_storage_min_constraint_rule(backend_model, loc_tech)[source]

Limit energy capacities of storage technologies based on their storage capacities.

$\begin{split}\boldsymbol{energy_{cap}}(loc::tech) \geq \boldsymbol{storage_{cap}}(loc::tech) \times energy\_cap\_per\_storage\_cap\_min(loc::tech)\\ \forall loc::tech \in loc::techs_{store}\end{split}$
calliope.backend.pyomo.constraints.capacity.energy_capacity_storage_max_constraint_rule(backend_model, loc_tech)[source]

Limit energy capacities of storage technologies based on their storage capacities.

$\begin{split}\boldsymbol{energy_{cap}}(loc::tech) \leq \boldsymbol{storage_{cap}}(loc::tech) \times energy\_cap\_per\_storage\_cap\_max(loc::tech)\\ \forall loc::tech \in loc::techs_{store}\end{split}$
calliope.backend.pyomo.constraints.capacity.energy_capacity_storage_equals_constraint_rule(backend_model, loc_tech)[source]

Limit energy capacities of storage technologies based on their storage capacities.

$\boldsymbol{energy_{cap}}(loc::tech) = \boldsymbol{storage_{cap}}(loc::tech) \times energy\_cap\_per\_storage\_cap\_equals(loc::tech) \forall loc::tech \in loc::techs_{store}$
calliope.backend.pyomo.constraints.capacity.resource_capacity_constraint_rule(backend_model, loc_tech)[source]

Add upper and lower bounds for resource_cap.

The first valid case is applied:

$\begin{split}\boldsymbol{resource_{cap}}(loc::tech) \begin{cases} = resource_{cap, equals}(loc::tech),& \text{if } resource_{cap, equals}(loc::tech)\\ \leq resource_{cap, max}(loc::tech),& \text{if } resource_{cap, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs_{finite\_resource\_supply\_plus}\end{split}$

and (if equals not enforced):

$\boldsymbol{resource_{cap}}(loc::tech) \geq resource_{cap, min}(loc::tech) \quad \forall loc::tech \in loc::techs_{finite\_resource\_supply\_plus}$
calliope.backend.pyomo.constraints.capacity.resource_capacity_equals_energy_capacity_constraint_rule(backend_model, loc_tech)[source]

Add equality constraint for resource_cap to equal energy_cap, for any technologies which have defined resource_cap_equals_energy_cap.

$\boldsymbol{resource_{cap}}(loc::tech) = \boldsymbol{energy_{cap}}(loc::tech) \quad \forall loc::tech \in loc::techs_{finite\_resource\_supply\_plus} \text{ if } resource\_cap\_equals\_energy\_cap = \text{True}$
calliope.backend.pyomo.constraints.capacity.resource_area_constraint_rule(backend_model, loc_tech)[source]

Set upper and lower bounds for resource_area.

The first valid case is applied:

$\begin{split}\boldsymbol{resource_{area}}(loc::tech) \begin{cases} = resource_{area, equals}(loc::tech),& \text{if } resource_{area, equals}(loc::tech)\\ \leq resource_{area, max}(loc::tech),& \text{if } resource_{area, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs_{area}\end{split}$

and (if equals not enforced):

$\boldsymbol{resource_{area}}(loc::tech) \geq resource_{area, min}(loc::tech) \quad \forall loc::tech \in loc::techs_{area}$
calliope.backend.pyomo.constraints.capacity.resource_area_per_energy_capacity_constraint_rule(backend_model, loc_tech)[source]

Add equality constraint for resource_area to equal a percentage of energy_cap, for any technologies which have defined resource_area_per_energy_cap

$\boldsymbol{resource_{area}}(loc::tech) = \boldsymbol{energy_{cap}}(loc::tech) \times area\_per\_energy\_cap(loc::tech) \quad \forall loc::tech \in locs::techs_{area} \text{ if } area\_per\_energy\_cap(loc::tech)$
calliope.backend.pyomo.constraints.capacity.resource_area_capacity_per_loc_constraint_rule(backend_model, loc)[source]

Set upper bound on use of area for all locations which have available_area constraint set. Does not consider resource_area applied to demand technologies

$\sum_{tech} \boldsymbol{resource_{area}}(loc::tech) \leq available\_area \quad \forall loc \in locs \text{ if } available\_area(loc)$
calliope.backend.pyomo.constraints.capacity.energy_capacity_constraint_rule(backend_model, loc_tech)[source]

Set upper and lower bounds for energy_cap.

The first valid case is applied:

$\begin{split}\frac{\boldsymbol{energy_{cap}}(loc::tech)}{energy_{cap, scale}(loc::tech)} \begin{cases} = energy_{cap, equals}(loc::tech),& \text{if } energy_{cap, equals}(loc::tech)\\ \leq energy_{cap, max}(loc::tech),& \text{if } energy_{cap, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs\end{split}$

and (if equals not enforced):

$\frac{\boldsymbol{energy_{cap}}(loc::tech)}{energy_{cap, scale}(loc::tech)} \geq energy_{cap, min}(loc::tech) \quad \forall loc::tech \in loc::techs$
calliope.backend.pyomo.constraints.capacity.energy_capacity_systemwide_constraint_rule(backend_model, tech)[source]

Set constraints to limit the capacity of a single technology type across all locations in the model.

The first valid case is applied:

$\begin{split}\sum_{loc}\boldsymbol{energy_{cap}}(loc::tech) \begin{cases} = energy_{cap, equals, systemwide}(loc::tech),& \text{if } energy_{cap, equals, systemwide}(loc::tech)\\ \leq energy_{cap, max, systemwide}(loc::tech),& \text{if } energy_{cap, max, systemwide}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall tech \in techs\end{split}$

## Dispatch¶

calliope.backend.pyomo.constraints.dispatch.carrier_production_max_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set maximum carrier production. All technologies.

$\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \leq energy_{cap}(loc::tech) \times timestep\_resolution(timestep) \times parasitic\_eff(loc::tec)$
calliope.backend.pyomo.constraints.dispatch.carrier_production_min_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set minimum carrier production. All technologies except conversion_plus.

$\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \geq energy_{cap}(loc::tech) \times timestep\_resolution(timestep) \times energy_{cap,min\_use}(loc::tec)$
calliope.backend.pyomo.constraints.dispatch.carrier_consumption_max_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set maximum carrier consumption for demand, storage, and transmission techs.

$\boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \geq -1 \times energy_{cap}(loc::tech) \times timestep\_resolution(timestep)$
calliope.backend.pyomo.constraints.dispatch.resource_max_constraint_rule(backend_model, loc_tech, timestep)[source]

Set maximum resource consumed by supply_plus techs.

$\boldsymbol{resource_{con}}(loc::tech, timestep) \leq timestep\_resolution(timestep) \times resource_{cap}(loc::tech)$
calliope.backend.pyomo.constraints.dispatch.storage_max_constraint_rule(backend_model, loc_tech, timestep)[source]

Set maximum stored energy. Supply_plus & storage techs only.

$\boldsymbol{storage}(loc::tech, timestep) \leq storage_{cap}(loc::tech)$
calliope.backend.pyomo.constraints.dispatch.storage_discharge_depth_constraint_rule(backend_model, loc_tech, timestep)[source]

Forces storage state of charge to be greater than the allowed depth of discharge.

$\boldsymbol{storage}(loc::tech, timestep) >= \boldsymbol{storage_discharge_depth}\forall loc::tech \in loc::techs_{storage}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.dispatch.ramping_up_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Ramping up constraint.

$diff(loc::tech::carrier, timestep) \leq max\_ramping\_rate(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.dispatch.ramping_down_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Ramping down constraint.

$-1 \times max\_ramping\_rate(loc::tech::carrier, timestep) \leq diff(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.dispatch.ramping_constraint(backend_model, loc_tech_carrier, timestep, direction=0)[source]

Ramping rate constraints.

Direction: 0 is up, 1 is down.

\begin{align}\begin{aligned}\boldsymbol{max\_ramping\_rate}(loc::tech::carrier, timestep) = energy_{ramping}(loc::tech, timestep) \times energy_{cap}(loc::tech)\\\boldsymbol{diff}(loc::tech::carrier, timestep) = (carrier_{prod}(loc::tech::carrier, timestep) + carrier_{con}(loc::tech::carrier, timestep)) / timestep\_resolution(timestep) - (carrier_{prod}(loc::tech::carrier, timestep-1) + carrier_{con}(loc::tech::carrier, timestep-1)) / timestep\_resolution(timestep-1)\end{aligned}\end{align}
calliope.backend.pyomo.constraints.dispatch.storage_intra_max_rule(backend_model, loc_tech, timestep)[source]

When clustering days, to reduce the timeseries length, set limits on intra-cluster auxiliary maximum storage decision variable. Ref: DOI 10.1016/j.apenergy.2018.01.023

$\boldsymbol{storage}(loc::tech, timestep) \leq \boldsymbol{storage_{intra\_cluster, max}}(loc::tech, cluster(timestep)) \quad \forall loc::tech \in loc::techs_{store}, \forall timestep \in timesteps$

Where $$cluster(timestep)$$ is the cluster number in which the timestep is located.

calliope.backend.pyomo.constraints.dispatch.storage_intra_min_rule(backend_model, loc_tech, timestep)[source]

When clustering days, to reduce the timeseries length, set limits on intra-cluster auxiliary minimum storage decision variable. Ref: DOI 10.1016/j.apenergy.2018.01.023

$\boldsymbol{storage}(loc::tech, timestep) \geq \boldsymbol{storage_{intra\_cluster, min}}(loc::tech, cluster(timestep)) \quad \forall loc::tech \in loc::techs_{store}, \forall timestep \in timesteps$

Where $$cluster(timestep)$$ is the cluster number in which the timestep is located.

calliope.backend.pyomo.constraints.dispatch.storage_inter_max_rule(backend_model, loc_tech, datestep)[source]

When clustering days, to reduce the timeseries length, set maximum limit on the intra-cluster and inter-date stored energy. intra-cluster = all timesteps in a single cluster datesteps = all dates in the unclustered timeseries (each has a corresponding cluster) Ref: DOI 10.1016/j.apenergy.2018.01.023

$\boldsymbol{storage_{inter\_cluster}}(loc::tech, datestep) + \boldsymbol{storage_{intra\_cluster, max}}(loc::tech, cluster(datestep)) \leq \boldsymbol{storage_{cap}}(loc::tech) \quad \forall loc::tech \in loc::techs_{store}, \forall datestep \in datesteps$

Where $$cluster(datestep)$$ is the cluster number in which the datestep is located.

calliope.backend.pyomo.constraints.dispatch.storage_inter_min_rule(backend_model, loc_tech, datestep)[source]

When clustering days, to reduce the timeseries length, set minimum limit on the intra-cluster and inter-date stored energy. intra-cluster = all timesteps in a single cluster datesteps = all dates in the unclustered timeseries (each has a corresponding cluster) Ref: DOI 10.1016/j.apenergy.2018.01.023

$\boldsymbol{storage_{inter\_cluster}}(loc::tech, datestep) \times (1 - storage\_loss(loc::tech, timestep))^{24} + \boldsymbol{storage_{intra\_cluster, min}}(loc::tech, cluster(datestep)) \geq 0 \quad \forall loc::tech \in loc::techs_{store}, \forall datestep \in datesteps$

Where $$cluster(datestep)$$ is the cluster number in which the datestep is located.

## Costs¶

calliope.backend.pyomo.constraints.costs.cost_constraint_rule(backend_model, cost, loc_tech)[source]

Combine investment and time varying costs into one cost per technology.

$\boldsymbol{cost}(cost, loc::tech) = \boldsymbol{cost_{investment}}(cost, loc::tech) + \sum_{timestep \in timesteps} \boldsymbol{cost_{var}}(cost, loc::tech, timestep)$
calliope.backend.pyomo.constraints.costs.cost_investment_constraint_rule(backend_model, cost, loc_tech)[source]

Calculate costs from capacity decision variables.

Transmission technologies “exist” at two locations, so their cost is divided by 2.

\begin{align}\begin{aligned}\boldsymbol{cost_{investment}}(cost, loc::tech) = cost_{fractional\_om}(cost, loc::tech) + cost_{fixed\_om}(cost, loc::tech) + cost_{cap}(cost, loc::tech)\\cost_{cap}(cost, loc::tech) = depreciation\_rate * ts\_weight * (cost_{energy\_cap}(cost, loc::tech) \times \boldsymbol{energy_{cap}}(loc::tech) + cost_{storage\_cap}(cost, loc::tech) \times \boldsymbol{storage_{cap}}(loc::tech) + cost_{resource\_cap}(cost, loc::tech) \times \boldsymbol{resource_{cap}}(loc::tech) + cost_{resource\_area}(cost, loc::tech)) \times \boldsymbol{resource_{area}}(loc::tech)\\\begin{split}depreciation\_rate = \begin{cases} = 1 / plant\_life,& \text{if } interest\_rate = 0\\ = \frac{interest\_rate \times (1 + interest\_rate)^{plant\_life}}{(1 + interest\_rate)^{plant\_life} - 1},& \text{if } interest\_rate \gt 0\\ \end{cases}\end{split}\\ts\_weight = \sum_{timestep \in timesteps} (time\_res(timestep) \times weight(timestep)) \times \frac{1}{8760}\end{aligned}\end{align}
calliope.backend.pyomo.constraints.costs.cost_var_constraint_rule(backend_model, cost, loc_tech, timestep)[source]

Calculate costs from time-varying decision variables

\begin{align}\begin{aligned}\boldsymbol{cost_{var}}(cost, loc::tech, timestep) = cost_{prod}(cost, loc::tech, timestep) + cost_{con}(cost, loc::tech, timestep)\\cost_{prod}(cost, loc::tech, timestep) = cost_{om\_prod}(cost, loc::tech, timestep) \times weight(timestep) \times \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)\\\begin{split}prod\_con\_eff = \begin{cases} = \boldsymbol{resource_{con}}(loc::tech, timestep),& \text{if } loc::tech \in loc\_techs\_supply\_plus \\ = \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{energy_eff(loc::tech, timestep)},& \text{if } loc::tech \in loc\_techs\_supply \\ \end{cases}\end{split}\\cost_{con}(cost, loc::tech, timestep) = cost_{om\_con}(cost, loc::tech, timestep) \times weight(timestep) \times prod\_con\_eff\end{aligned}\end{align}

## Export¶

calliope.backend.pyomo.constraints.export.update_system_balance_constraint(backend_model, loc_carrier, timestep)[source]

Update system balance constraint (from energy_balance.py) to include export

Math given in system_balance_constraint_rule()

calliope.backend.pyomo.constraints.export.export_balance_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Ensure no technology can ‘pass’ its export capability to another technology with the same carrier_out, by limiting its export to the capacity of its production

$\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \geq \boldsymbol{carrier_{export}}(loc::tech::carrier, timestep) \quad \forall loc::tech::carrier \in locs::tech::carriers_{export}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.export.update_costs_var_constraint(backend_model, cost, loc_tech, timestep)[source]

Update time varying cost constraint (from costs.py) to include export

$\boldsymbol{cost_{var}}(cost, loc::tech, timestep) += cost_{export}(cost, loc::tech, timestep) \times \boldsymbol{carrier_{export}}(loc::tech::carrier, timestep) * timestep_{weight} \quad \forall cost \in costs, \forall loc::tech \in loc::techs_{cost_{var}, export}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.export.export_max_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set maximum export. All exporting technologies.

$\boldsymbol{carrier_{export}}(loc::tech::carrier, timestep) \leq export_{cap}(loc::tech) \quad \forall loc::tech::carrier \in locs::tech::carriers_{export}, \forall timestep \in timesteps$

If the technology is defined by integer units, not a continuous capacity, this constraint becomes:

$\boldsymbol{carrier_{export}}(loc::tech::carrier, timestep) \leq export_{cap}(loc::tech) \times \boldsymbol{operating_{units}}(loc::tech, timestep)$

## MILP¶

calliope.backend.pyomo.constraints.milp.unit_commitment_milp_constraint_rule(backend_model, loc_tech, timestep)[source]

Constraining the number of integer units $$operating_units(loc_tech, timestep)$$ of a technology which can operate in a given timestep, based on maximum purchased units $$units(loc_tech)$$

$\boldsymbol{operating\_units}(loc::tech, timestep) \leq \boldsymbol{units}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.unit_capacity_milp_constraint_rule(backend_model, loc_tech)[source]

Add upper and lower bounds for purchased units of a technology

$\begin{split}\boldsymbol{units}(loc::tech) \begin{cases} = units_{equals}(loc::tech),& \text{if } units_{equals}(loc::tech)\\ \leq units_{max}(loc::tech),& \text{if } units_{max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \quad \forall loc::tech \in loc::techs_{milp}\end{split}$

and (if equals not enforced):

$\boldsymbol{units}(loc::tech) \geq units_{min}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp}$
calliope.backend.pyomo.constraints.milp.carrier_production_max_milp_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set maximum carrier production of MILP techs that aren’t conversion plus

$\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \leq energy_{cap, per unit}(loc::tech) \times timestep\_resolution(timestep) \times \boldsymbol{operating\_units}(loc::tech, timestep) \times \eta_{parasitic}(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{milp}, \forall timestep \in timesteps$

$$\eta_{parasitic}$$ is only activated for supply_plus technologies

calliope.backend.pyomo.constraints.milp.carrier_production_max_conversion_plus_milp_constraint_rule(backend_model, loc_tech, timestep)[source]

Set maximum carrier production of conversion_plus MILP techs

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \leq energy_{cap, per unit}(loc::tech) \times timestep\_resolution(timestep) \times \boldsymbol{operating\_units}(loc::tech, timestep) \times \eta_{parasitic}(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{milp, conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.carrier_production_min_milp_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set minimum carrier production of MILP techs that aren’t conversion plus

$\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \geq energy_{cap, per unit}(loc::tech) \times timestep\_resolution(timestep) \times \boldsymbol{operating\_units}(loc::tech, timestep) \times energy_{cap, min use}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.carrier_production_min_conversion_plus_milp_constraint_rule(backend_model, loc_tech, timestep)[source]

Set minimum carrier production of conversion_plus MILP techs

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \geq energy_{cap, per unit}(loc::tech) \times timestep\_resolution(timestep) \times \boldsymbol{operating\_units}(loc::tech, timestep) \times energy_{cap, min use}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp, conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.carrier_consumption_max_milp_constraint_rule(backend_model, loc_tech_carrier, timestep)[source]

Set maximum carrier consumption of demand, storage, and transmission MILP techs

$\boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \geq -1 * energy_{cap, per unit}(loc::tech) \times timestep\_resolution(timestep) \times \boldsymbol{operating\_units}(loc::tech, timestep) \times \eta_{parasitic}(loc::tech, timestep) \quad \forall loc::tech \in loc::techs_{milp, con}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.energy_capacity_units_milp_constraint_rule(backend_model, loc_tech)[source]

Set energy capacity decision variable as a function of purchased units

$\boldsymbol{energy_{cap}}(loc::tech) = \boldsymbol{units}(loc::tech) \times energy_{cap, per unit}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp}$
calliope.backend.pyomo.constraints.milp.storage_capacity_units_milp_constraint_rule(backend_model, loc_tech)[source]

Set storage capacity decision variable as a function of purchased units

$\boldsymbol{storage_{cap}}(loc::tech) = \boldsymbol{units}(loc::tech) \times storage_{cap, per unit}(loc::tech) \quad \forall loc::tech \in loc::techs_{milp, store}$
calliope.backend.pyomo.constraints.milp.energy_capacity_max_purchase_milp_constraint_rule(backend_model, loc_tech)[source]

Set maximum energy capacity decision variable upper bound as a function of binary purchase variable

The first valid case is applied:

$\begin{split}\frac{\boldsymbol{energy_{cap}}(loc::tech)}{energy_{cap, scale}(loc::tech)} \begin{cases} = energy_{cap, equals}(loc::tech) \times \boldsymbol{purchased}(loc::tech),& \text{if } energy_{cap, equals}(loc::tech)\\ \leq energy_{cap, max}(loc::tech) \times \boldsymbol{purchased}(loc::tech),& \text{if } energy_{cap, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs_{purchase}\end{split}$
calliope.backend.pyomo.constraints.milp.energy_capacity_min_purchase_milp_constraint_rule(backend_model, loc_tech)[source]

Set minimum energy capacity decision variable upper bound as a function of binary purchase variable

and (if equals not enforced):

$\frac{\boldsymbol{energy_{cap}}(loc::tech)}{energy_{cap, scale}(loc::tech)} \geq energy_{cap, min}(loc::tech) \times \boldsymbol{purchased}(loc::tech) \quad \forall loc::tech \in loc::techs$
calliope.backend.pyomo.constraints.milp.storage_capacity_max_purchase_milp_constraint_rule(backend_model, loc_tech)[source]

Set maximum storage capacity.

The first valid case is applied:

$\begin{split}\boldsymbol{storage_{cap}}(loc::tech) \begin{cases} = storage_{cap, equals}(loc::tech) \times \boldsymbol{purchased},& \text{if } storage_{cap, equals} \\ \leq storage_{cap, max}(loc::tech) \times \boldsymbol{purchased},& \text{if } storage_{cap, max}(loc::tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall loc::tech \in loc::techs_{purchase, store}\end{split}$
calliope.backend.pyomo.constraints.milp.storage_capacity_min_purchase_milp_constraint_rule(backend_model, loc_tech)[source]

Set minimum storage capacity decision variable as a function of binary purchase variable

if equals not enforced for storage_cap:

$\boldsymbol{storage_{cap}}(loc::tech) \geq storage_{cap, min}(loc::tech) \times \boldsymbol{purchased}(loc::tech) \quad \forall loc::tech \in loc::techs_{purchase, store}$
calliope.backend.pyomo.constraints.milp.update_costs_investment_units_milp_constraint(backend_model, cost, loc_tech)[source]

Add MILP investment costs (cost * number of units purchased)

$\boldsymbol{cost_{investment}}(cost, loc::tech) += \boldsymbol{units}(loc::tech) \times cost_{purchase}(cost, loc::tech) * timestep_{weight} * depreciation \quad \forall cost \in costs, \forall loc::tech \in loc::techs_{cost_{investment}, milp}$
calliope.backend.pyomo.constraints.milp.update_costs_investment_purchase_milp_constraint(backend_model, cost, loc_tech)[source]

Add binary investment costs (cost * binary_purchased_unit)

$\boldsymbol{cost_{investment}}(cost, loc::tech) += \boldsymbol{purchased}(loc::tech) \times cost_{purchase}(cost, loc::tech) * timestep_{weight} * depreciation \quad \forall cost \in costs, \forall loc::tech \in loc::techs_{cost_{investment}, purchase}$
calliope.backend.pyomo.constraints.milp.unit_capacity_systemwide_milp_constraint_rule(backend_model, tech)[source]

Set constraints to limit the number of purchased units of a single technology type across all locations in the model.

The first valid case is applied:

$\begin{split}\sum_{loc}\boldsymbol{units}(loc::tech) + \boldsymbol{purchased}(loc::tech) \begin{cases} = units_{equals, systemwide}(tech),& \text{if } units_{equals, systemwide}(tech)\\ \leq units_{max, systemwide}(tech),& \text{if } units_{max, systemwide}(tech)\\ \text{unconstrained},& \text{otherwise} \end{cases} \forall tech \in techs\end{split}$
calliope.backend.pyomo.constraints.milp.asynchronous_con_milp_constraint_rule(backend_model, loc_tech, timestep)[source]

BigM limit set on carrier_con, forcing it to either be zero or non-zero, depending on whether con is zero or one, respectively.

$- \boldsymbol{carrier_con}[loc::tech::carrier, timestep] \leq \text{bigM} \times (1 - \boldsymbol{prod_con_switch}[loc::tech, timestep]) \forall loc::tech \in loc::techs_{asynchronous_prod_con}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.milp.asynchronous_prod_milp_constraint_rule(backend_model, loc_tech, timestep)[source]

BigM limit set on carrier_prod, forcing it to either be zero or non-zero, depending on whether prod is zero or one, respectively.

$\boldsymbol{carrier_prod}[loc::tech::carrier, timestep] \leq \text{bigM} \times \boldsymbol{prod_con_switch}[loc::tech, timestep] \forall loc::tech \in loc::techs_{asynchronous_prod_con}, \forall timestep \in timesteps$

## Conversion¶

calliope.backend.pyomo.constraints.conversion.balance_conversion_constraint_rule(backend_model, loc_tech, timestep)[source]

Balance energy carrier consumption and production

$-1 * \boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) = \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \times \eta_{energy}(loc::tech, timestep) \quad \forall loc::tech \in locs::techs_{conversion}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.conversion.cost_var_conversion_constraint_rule(backend_model, cost, loc_tech, timestep)[source]

$\boldsymbol{cost_{var}}(loc::tech, cost, timestep) = \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \times timestep_{weight}(timestep) \times cost_{om, prod}(loc::tech, cost, timestep) + \boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) \times timestep_{weight}(timestep) \times cost_{om, con}(loc::tech, cost, timestep) \quad \forall loc::tech \in loc::techs_{cost_{var}, conversion}$

## Conversion_plus¶

calliope.backend.pyomo.constraints.conversion_plus.balance_conversion_plus_primary_constraint_rule(backend_model, loc_tech, timestep)[source]

Balance energy carrier consumption and production for carrier_in and carrier_out

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{ carrier\_ratio(loc::tech::carrier, out')} = -1 * \sum_{loc::tech::carrier \in loc::tech::carriers_{in}} ( \boldsymbol{carrier_{con}}(loc::tech::carrier, timestep) * carrier\_ratio(loc::tech::carrier, in') * \eta_{energy}(loc::tech, timestep)) \quad \forall loc::tech \in loc::techs_{conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.conversion_plus.carrier_production_max_conversion_plus_constraint_rule(backend_model, loc_tech, timestep)[source]

Set maximum conversion_plus carrier production.

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \leq \boldsymbol{energy_{cap}}(loc::tech) \times timestep\_resolution(timestep) \quad \forall loc::tech \in loc::techs_{conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.conversion_plus.carrier_production_min_conversion_plus_constraint_rule(backend_model, loc_tech, timestep)[source]

Set minimum conversion_plus carrier production.

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} \boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep) \leq \boldsymbol{energy_{cap}}(loc::tech) \times timestep\_resolution(timestep) \times energy_{cap, min use}(loc::tech) \quad \forall loc::tech \in loc::techs_{conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.conversion_plus.cost_var_conversion_plus_constraint_rule(backend_model, cost, loc_tech, timestep)[source]

$\boldsymbol{cost_{var}}(loc::tech, cost, timestep) = \boldsymbol{carrier_{prod}}(loc::tech::carrier_{primary}, timestep) \times timestep_{weight}(timestep) \times cost_{om, prod}(loc::tech, cost, timestep) + \boldsymbol{carrier_{con}}(loc::tech::carrier_{primary}, timestep) \times timestep_{weight}(timestep) \times cost_{om, con}(loc::tech, cost, timestep) \quad \forall loc::tech \in loc::techs_{cost_{var}, conversion^{+}}$
calliope.backend.pyomo.constraints.conversion_plus.balance_conversion_plus_tiers_constraint_rule(backend_model, tier, loc_tech, timestep)[source]

Force all carrier_in_2/carrier_in_3 and carrier_out_2/carrier_out_3 to follow carrier_in and carrier_out (respectively).

If tier in [‘out_2’, ‘out_3’]:

$\sum_{loc::tech::carrier \in loc::tech::carriers_{out}} ( \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{ carrier\_ratio(loc::tech::carrier, out')} = \sum_{loc::tech::carrier \in loc::tech::carriers_{tier}} ( \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{ carrier\_ratio(loc::tech::carrier, tier)} \quad \forall \text { tier } \in [out_2', out_3'], \forall loc::tech \in loc::techs_{conversion^{+}}, \forall timestep \in timesteps$

If tier in [‘in_2’, ‘in_3’]:

$\sum_{loc::tech::carrier \in loc::tech::carriers_{in}} \frac{\boldsymbol{carrier_{con}}(loc::tech::carrier, timestep)}{ carrier\_ratio(loc::tech::carrier, in')} = \sum_{loc::tech::carrier \in loc::tech::carriers_{tier}} \frac{\boldsymbol{carrier_{prod}}(loc::tech::carrier, timestep)}{ carrier\_ratio(loc::tech::carrier, tier)} \quad \forall \text{ tier } \in [in_2', in_3'], \forall loc::tech \in loc::techs_{conversion^{+}}, \forall timestep \in timesteps$
calliope.backend.pyomo.constraints.conversion_plus.conversion_plus_prod_con_to_zero_constraint_rule(backend_model, loc_tech_carrier_tier, timestep)[source]

Force any carrier production or consumption for a conversion plus technology to zero in timesteps where its carrier_ratio is zero

## Network¶

calliope.backend.pyomo.constraints.network.symmetric_transmission_constraint_rule(backend_model, loc_tech)[source]

Constrain e_cap symmetrically for transmission nodes. Transmission techs only.

$energy_{cap}(loc1::tech:loc2) = energy_{cap}(loc2::tech:loc1)$

## Policy¶

calliope.backend.pyomo.constraints.policy.group_share_energy_cap_constraint_rule(backend_model, techlist, what)[source]

Enforce shares in energy_cap for groups of technologies. Applied to supply and supply_plus technologies only.

$\sum_{loc::tech \in given\_group} energy_{cap}(loc::tech) = fraction \times \sum_{loc::tech \in loc\_techs\_supply \or loc\_techs\_supply\_plus} energy_{cap}(loc::tech)$
calliope.backend.pyomo.constraints.policy.group_share_carrier_prod_constraint_rule(backend_model, techlist_carrier, what)[source]

Enforce shares in carrier_prod for groups of technologies. Applied to loc_tech_carriers_supply_conversion_all, which includes supply, supply_plus, conversion, and conversion_plus.

$\sum_{loc::tech::carrier \in given\_group, timestep \in timesteps} carrier_{prod}(loc::tech::carrier, timestep) = fraction \times \sum_{loc::tech:carrier \in loc\_tech\_carriers\_supply\_all, timestep\in timesteps} carrier_{prod}(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.policy.reserve_margin_constraint_rule(backend_model, carrier)[source]

Enforces a system reserve margin per carrier.

$\sum_{loc::tech::carrier \in loc\_tech\_carriers\_supply\_all} energy_{cap}(loc::tech::carrier, timestep_{max\_demand}) \geq \sum_{loc::tech::carrier \in loc\_tech\_carriers\_demand} carrier_{con}(loc::tech::carrier, timestep_{max\_demand}) \times -1 \times \frac{1}{time\_resolution_{max\_demand}} \times (1 + reserve\_margin)$

## Group constraints¶

calliope.backend.pyomo.constraints.group.demand_share_constraint_rule(backend_model, group_name, what)[source]

Enforces shares of demand of a carrier to be met by the given groups of technologies at the given locations, on average over the entire model period. The share is relative to demand technologies only.

$\sum_{loc::tech::carrier \in given\_group, timestep \in timesteps} carrier_{prod}(loc::tech::carrier, timestep) \leq share \times \sum_{loc::tech:carrier \in loc\_techs\_demand \in given\_locations, timestep\in timesteps} carrier_{con}(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.group.demand_share_per_timestep_constraint_rule(backend_model, group_name, timestep, what)[source]

Enforces shares of demand of a carrier to be met by the given groups of technologies at the given locations, in each timestep. The share is relative to demand technologies only.

$\sum_{loc::tech::carrier \in given\_group} carrier_{prod}(loc::tech::carrier, timestep) \leq share \times \sum_{loc::tech:carrier \in loc\_techs\_demand \in given\_locations} carrier_{con}(loc::tech::carrier, timestep) for timestep \in timesteps$
calliope.backend.pyomo.constraints.group.demand_share_per_timestep_decision_main_constraint_rule(backend_model, group_name, loc_tech_carrier, timestep)[source]

Allows the model to decide on how a fraction demand for a carrier is met by the given groups, which will all have the same share in each timestep. The share is relative to the actual demand from demand technologies only.

The main constraint enforces that the shares are the same in each timestep.

\begin{align}\begin{aligned}\sum_{loc::tech::carrier \in given\_group} carrier_{prod}(loc::tech::carrier, timestep)\\=\\\sum_{loc::tech::carrier \in given\_group} required\_resource(loc::tech::carrier, timestep)\\\times \sum_{loc::tech::carrier \in given\_group} demand\_share\_per\_timestep\_decision(loc::tech::carrier)\\\forall timestep \in timesteps\\\forall tech \in techs\end{aligned}\end{align}
calliope.backend.pyomo.constraints.group.demand_share_per_timestep_decision_sum_constraint_rule(backend_model, group_name)[source]

Allows the model to decide on how a fraction of demand for a carrier is met by the given groups, which will all have the same share in each timestep. The share is relative to the actual demand from demand technologies only.

The sum constraint ensures that all decision shares add up to the share of carrier demand specified in the constraint.

This constraint is only applied if the share of carrier demand has been set to a not-None value.

$share = \sum_{loc::tech::carrier \in given\_group} demand\_share\_per\_timestep\_decision(loc::tech::carrier)$
calliope.backend.pyomo.constraints.group.carrier_prod_share_constraint_rule(backend_model, group_name, what)[source]

Enforces shares of carrier_prod for groups of technologies and locations, on average over the entire model period. The share is relative to supply and supply_plus technologies only.

$\sum_{loc::tech::carrier \in given\_group, timestep \in timesteps} carrier_{prod}(loc::tech::carrier, timestep) \leq share \times \sum_{loc::tech:carrier \in loc\_tech\_carriers\_supply\_all \in given\_locations, timestep\in timesteps} carrier_{prod}(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.group.carrier_prod_share_per_timestep_constraint_rule(backend_model, group_name, timestep, what)[source]

Enforces shares of carrier_prod for groups of technologies and locations, in each timestep. The share is relative to supply and supply_plus technologies only.

$\sum_{loc::tech::carrier \in given\_group} carrier_{prod}(loc::tech::carrier, timestep) \leq share \times \sum_{loc::tech:carrier \in loc\_tech\_carriers\_supply\_all \in given\_locations} carrier_{prod}(loc::tech::carrier, timestep) for timestep \in timesteps$
calliope.backend.pyomo.constraints.group.net_import_share_constraint_rule(backend_model, group_name, what)[source]

Enforces demand shares of net imports from transmission technologies for groups of locations, on average over the entire model period. Transmission within the group are ignored. The share is relative to demand technologies only.

$\sum_{loc::tech::carrier \in loc\_tech\_carriers\_transmission \in given\_locations, timestep \in timesteps} carrier_{prod}(loc::tech::carrier, timestep) + \sum_{loc::tech::carrier \in loc\_tech\_carriers\_transmission \in given\_locations, timestep \in timesteps} carrier_{con}(loc::tech::carrier, timestep) \leq share \times \sum_{loc::tech:carrier \in loc\_tech\_demand \in given\_locations, timestep\in timesteps} carrier_{con}(loc::tech::carrier, timestep)$
calliope.backend.pyomo.constraints.group.carrier_prod_constraint_rule(backend_model, group_name, what)[source]

Enforces carrier_prod for groups of technologies and locations, as a sum over the entire model period.

$\sum_{loc::tech::carrier \in given\_group, timestep \in timesteps} carrier_{prod}(loc::tech::carrier, timestep) \leq carrier_prod_max$
calliope.backend.pyomo.constraints.group.carrier_con_constraint_rule(backend_model, constraint_group, what)[source]

Enforces carrier_con for groups of technologies and locations, as a sum over the entire model period. limits are always negative, so min/max is relative to zero (i.e. min = -1 means carrier_con must be -1 or less)

$\sum_{loc::tech::carrier \in given\_group, timestep \in timesteps} carrier_{con}(loc::tech::carrier, timestep) \geq carrier_con_max$
calliope.backend.pyomo.constraints.group.energy_cap_share_constraint_rule(backend_model, constraint_group, what)[source]

Enforces shares of energy_cap for groups of technologies and locations. The share is relative to supply, supply_plus, conversion, and conversion_plus technologies only.

$\sum_{loc::tech \in given\_group} energy_{cap}(loc::tech) \leq share \times \sum_{loc::tech \in loc\_tech\_supply\_all \in given\_locations} energy_{cap}(loc::tech)$
calliope.backend.pyomo.constraints.group.energy_cap_constraint_rule(backend_model, constraint_group, what)[source]

Enforce upper and lower bounds for energy_cap of energy_cap for groups of technologies and locations.

\begin{align}\begin{aligned}\begin{split}\sum_{loc::tech \in given\_group} energy_{cap}(loc::tech) \leq energy\_cap\_max\\\end{split}\\\sum_{loc::tech \in given\_group} energy_{cap}(loc::tech) \geq energy\_cap\_min\end{aligned}\end{align}
calliope.backend.pyomo.constraints.group.storage_cap_constraint_rule(backend_model, constraint_group, what)[source]

Enforce upper and lower bounds for storage_cap of storage_cap for groups of technologies and locations.

\begin{align}\begin{aligned}\begin{split}\sum_{loc::tech \in given\_group} storage_{cap}(loc::tech) \leq storage\_cap\_max\\\end{split}\\\sum_{loc::tech \in given\_group} storage_{cap}(loc::tech) \geq storage\_cap\_min\end{aligned}\end{align}
calliope.backend.pyomo.constraints.group.cost_cap_constraint_rule(backend_model, group_name, cost, what)[source]

Limit cost for a specific cost class to a certain value, i.e. Ɛ-constrained costs, for groups of technologies and locations.

$\sum{loc::tech \in loc\_techs_{group\_name}, timestep \in timesteps} \boldsymbol{cost}(cost, loc::tech, timestep) \begin{cases} \leq cost\_max(cost) \geq cost\_min(cost) = cost\_equals(cost) \end{cases}$
calliope.backend.pyomo.constraints.group.cost_investment_cap_constraint_rule(backend_model, group_name, cost, what)[source]

Limit investment costs specific to a cost class to a certain value, i.e. Ɛ-constrained costs, for groups of technologies and locations.

$\sum{loc::tech \in loc\_techs_{group\_name}, timestep \in timesteps} \boldsymbol{cost\_{investment}}(cost, loc::tech, timestep) \begin{cases} \leq cost\_investment\_max(cost) \geq cost\_investment\_min(cost) = cost\_investment\_equals(cost) \end{cases}$
calliope.backend.pyomo.constraints.group.cost_var_cap_constraint_rule(backend_model, group_name, cost, what)[source]

Limit variable costs specific to a cost class to a certain value, i.e. Ɛ-constrained costs, for groups of technologies and locations.

$\sum{loc::tech \in loc\_techs_{group\_name}, timestep \in timesteps} \boldsymbol{cost\_{var}}(cost, loc::tech, timestep) \begin{cases} \leq cost\_var\_max(cost) \geq cost\_var\_min(cost) = cost\_var\_equals(cost) \end{cases}$
calliope.backend.pyomo.constraints.group.resource_area_constraint_rule(backend_model, constraint_group, what)[source]

Enforce upper and lower bounds of resource_area for groups of technologies and locations.

\begin{align}\begin{aligned}\begin{split}\boldsymbol{resource_{area}}(loc::tech) \leq group\_resource\_area\_max\\\end{split}\\\boldsymbol{resource_{area}}(loc::tech) \geq group\_resource\_area\_min\end{aligned}\end{align}

Previous: Configuration reference | Next: Development guide