Technologies

The technology class is a subclass of the ModelComponent class. In the model, we further distinguish between generic technologies and specific technologies. Generic technologies offer a framework that can be adjusted for multiple technologies: only the performance parameters, and the input and output carriers change, while the equations remain the same.

Technology types, divided by generic and specific technologies:

  • Generic technologies:

    • RES

    • CONV1

    • CONV2

    • CONV3

    • CONV4

    • STOR

  • Specific technologies:

    • DAC adsorption

    • Gas turbine

    • Heat pump

    • Hydro open

All technology types listed above are modelled as subclasses of the Technology class. An overview of all technologies that are currently modelled, and the technology classes / types used to model them, can be found below.

Additionally, you can attach a post combustion CCS to any technology (see here)

List of Technologies

All technologies that are modelled are listed below, as well as their respective technology models (i.e., types of technologies that follow similar constraints, which are explained here).

Technology name

Technology model (Tec_type)

GasTurbine_H2_250

GasTurbine_H2_250

GasTurbine_H2_400

GasTurbine_H2_400

GasTurbine_simple_CCS

CONV1

SteamTurbine

CONV2

GasTurbine_NG_250

GasTurbine_NG_250

GasTurbine_H2_10

GasTurbine_H2_10

GasTurbine_simple

CONV1

GasTurbine_NG_100

GasTurbine_NG_100

GasTurbine_NG_10

GasTurbine_NG_10

GasTurbine_NG_400

GasTurbine_NG_400

GasTurbine_H2_100

GasTurbine_H2_100

WindTurbine_Offshore_6000

RES

WindTurbine_Offshore_11000

RES

WindTurbine_Onshore_1500

RES

SolarThermal

RES

WindTurbine_Onshore_4000

RES

WindTurbine_Offshore_9500

RES

WindTurbine_Onshore_2500

RES

Photovoltaic

RES

Boiler_Small_NG

CONV2

Boiler_Small_H2

CONV2

Boiler_Industrial_NG

CONV2

HeatPump_AirSourced

HeatPump_AirSourced

Boiler_El

CONV2

HeatPump_GroundSourced

HeatPump_GroundSourced

Furnace_H2

CONV2

HeatPump_WaterSourced

HeatPump_WaterSourced

Furnace_NG

CONV2

Storage_H2_Cavern

STOR

Storage_PCM

STOR

Storage_NG

STOR

Storage_H2

STOR

Storage_Ethylene

STOR

TemporaryStorage_CO2

STOR

Storage_Battery

STOR

Storage_HotWater

STOR

DAC_Adsorption

DAC_Adsorption

PermanentStorage_CO2_simple

SINK

EthyleneSeparation

CONV3

CrackerFurnace

CONV3

SteamReformer_CCS

CONV2

EthyleneCompression_Electric

CONV3

SteamReformer

CONV2

CrackerFurnace_Electric

CONV3

EthyleneCompression

CONV3

PumpedHydro_Open

HydroOpen

Hydro_Reservoir

Hydro_Open

PumpedHydro_Closed

STOR

Technology Class

As mentioned, the technology class is a subclass of the ModelComponent class. In general, all technology subclasses share the equations of this class, though some exceptions are there for specific technologies (the subclass then overwrites the class method).

class Technology(tec_data: dict)

Class to read and manage data for technologies

This class is parent class to all generic and specific technologies. It creates the variables, parameters, constraints and sets of a technology.

This function is extented in the generic/specific technology classes. It adds Sets, Parameters, Variables and Constraints that are common for all technologies. The following description is true for new technologies. For existing technologies a few adaptions are made (see below). When CCS is available, we add heat and electricity to the input carriers Set and CO2captured to the output carriers Set. Moreover, we create extra Parameters and Variables equivalent to the ones created for the technology, but specific for CCS. In addition, we create Variables that are the sum of the input, output, CAPEX and OPEX of the technology and of CCS. We calculate the emissions of the technology discounting already what is being captured by the CCS.

Set declarations:

  • set_input_carriers: Set of input carriers

  • set_output_carriers: Set of output carriers

If ccs is possible:

  • set_input_carriers_ccs: Set of CCS input carriers

  • set_output_carriers_ccs: Set of CCS output carriers

** Set declarations for time aggregation:**

Three sets are declared for each technology. These are required for time averaging algorithms:

  • set_t_full: set of all time steps before clustering

  • set_t_performance: set of time steps, on which the technology performance is based on

  • set_t_global: set of time steps, on which the energy balance is based on

Parameter declarations:

The following is a list of declared pyomo parameters.

  • para_size_min: minimal possible size

  • para_size_max: maximal possible size

  • para_unit_capex: investment costs per unit

  • para_unit_capex_annual: Unit CAPEX annualized (annualized from given data on up-front CAPEX, lifetime and discount rate)

  • para_fix_capex: fixed costs independent of size

  • para_fix_capex_annual: Fixed CAPEX annualized (annualized from given data on up-front CAPEX, lifetime and discount rate)

  • para_opex_variable: operational cost EUR/output or input

  • para_opex_fixed: fixed opex as fraction of annualized capex

  • para_tec_emissionfactor: emission factor per output or input

If ccs is possible:

  • para_size_min_ccs: minimal possible size

  • para_size_max_ccs: maximal possible size

  • para_unit_capex_annual_ccs: investment costs per unit (annualized from given data on up-front CAPEX, lifetime and discount rate)

  • para_fix_capex_annual_ccs: Fixed CAPEX annualized (annualized from given data on up-front CAPEX, lifetime and discount rate)

  • para_opex_variable_ccs: operational cost EUR/output or input

  • para_opex_fixed_ccs: fixed opex as fraction of annualized capex

For existing technologies:

  • para_size_initial: initial size

  • para_decommissioning_cost: Decommissioning cost

Variable declarations:

  • var_size: Size of the technology, can be integer or continuous

  • var_input: input to the technology, defined for each input carrier and time slice

  • var_output: output of the technology, defined for each output carrier and time slice

  • var_input_tot: input aggregation of technology and CCS input

  • var_output_tot: output aggregation of technology and CCS output

  • var_capex: annualized investment of the technology

  • var_opex_variable: variable operation costs, defined for each time slice

  • var_opex_fixed: fixed operational costs

  • var_capex_tot: aggregation of technology and CCS capex

  • var_capex_aux: auxiliary variable to calculate the fixed opex of existing technologies

  • var_opex_variable_tot: aggregation of technology and CCS opex variable, defined for each time slice

  • var_opex_fixed_tot: aggregation of technology and CCS opex fixed

  • var_tec_emissions_pos: positive emissions, defined per time slice

  • var_tec_emissions_neg: negative emissions, defined per time slice

If ccs is possible:

  • var_size_ccs: Size of CCS

  • var_input_ccs: input to the CCS component, defined for each CCS input carrier and time slice

  • var_output_ccs: output from the CCS component, defined for each CCS output carrier and time slice

  • var_capex_ccs: annualized investment of CCS

  • var_capex_aux_ccs: auxiliary variable to calculate the fixed opex of existing CCS

  • var_opex_variable_ccs: variable operation costs, defined for each time slice

  • var_opex_fixed_ccs: fixed operational costs

Constraint declarations

  • For new technologies, CAPEX, can be linear (for capex_model == 1), piecewise linear (for capex_model == 2) or linear with a fixed cost when the technology is installed (for capex_model == 3). The capex model can also be overwritten in the children technology classes (for capex_model == 4). Linear is defined as:

    \[capex_{aux} = size * capex_{unitannual}\]

    while linear with fixed installation costs is defined as. Note that capex_aux is zero if the technology is not installed:

    \[capex_{aux} = size * capex_{unitannual} + capex_{fixed}\]

    Existing technologies, i.e. existing = 1, can be decommissioned (decommission = 1) or not (decommission = 0). For technologies that cannot be decommissioned, the size is fixed to the size given in the technology data. For technologies that can be decommissioned, the size can be smaller or equal to the initial size. Reducing the size comes at the decommissioning costs specified in the economics of the technology. The fixed opex is calculated by determining the capex that the technology would have costed if newly build and then taking the respective opex_fixed share of this. This is done with the auxiliary variable capex_aux.

  • For existing technologies that can be decommissioned, the CAPEX equal to the decommissioning costs:

    \[capex = (size_{initial} - size) * decommissioningcost\]
  • Variable OPEX: variable opex is defined in terms of the input, with the exception of DAC_Adsorption, RES and CONV4, where it is defined per unit of output:

    \[opexvar_{t} = Input_{t, maincarrier} * opex_{var}\]
  • Fixed OPEX: defined as a fraction of annual CAPEX:

    \[opexfix = capex * opex_{fix}\]
  • Input aggregation: aggregates total input from technology and CCS. In case there is no CCS, input_ccs is zero:

    \[input_{t, car} + input_{CCS, t, car} = input_{tot, t, car}\]
  • Output aggregation: aggregates total output from technology and CCS. In case there is no CCS, output_ccs is zero:

    \[output_{t, car} + output_{CCS, t, car} = output_{tot, t, car}\]
  • Capex aggregation: aggregates capex of technology and CCS. In case there is no CCS, capex_ccs is zero:

    \[capex + capex_{CCS} = capex_{tot}\]
  • Opex variable aggregation: aggregates opex variable of technology and CCS. In case there is no CCS, var_opex_variable_ccs is zero:

    \[opex_{variable, t} + opex_{variable,CCS, t} = opex_{variable,tot, t}\]
  • Opex fixed aggregation: aggregates opex fixed of technology and CCS. In case there is no CCS, opex_fixed_ccs is zero:

    \[opex_{fixed} + opex_{fixed,CCS} = opex_{fixed,tot}\]
  • Emissions: depending if they are based on input or output and depending if emission factor is negative or positive

    \[emissions_{pos/neg,t} = output_{maincarrier, t} * emissionfactor_{pos}\]

If CCS is possible the following constraints apply:

  • Input carriers are given by:

\[input_{CCS, car} <= inputRatio_{carrier} * output_{CCS}/captureRate\]
\[input_{tot, car} = inputTec_{car} + input_{CCS, car}\]
  • CO2 captured output is constrained by:

\[output_{CCS} <= input(output)_{tec} * emissionFactor * captureRate\]
  • The total output are given by:

\[output_{tot, car} = outputTec_{car} + output_{CCS, car}\]
  • Emissions of the technology are:

\[emissions_{tec} = input(output)_{tec} * emissionFactor - output_{CCS}\]
  • CAPEX is given by

\[CAPEX_{CCS} = Size_{CCS} * UnitCost_{CCS} + FixCost_{CCS}\]
\[CAPEX_{tot} = CAPEX_{CCS} + CAPEX_{tec}\]
  • Fixed OPEX: defined as a fraction of annual CAPEX:

\[OPEXfix_{CCS} = CAPEX_{CCS} * opex_{CCS}\]
\[OPEX_{tot} = OPEX_{CCS} + OPEX_{tec}\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Construct the technology model with all required parameters, variable, sets,…

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits technology performance (bounds and coefficients).

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

scale_model(b_tec, model, config)

Scales technology model

Parameters:
  • b_tec – pyomo network block

  • model – pyomo model

  • config (dict) – config dict containing scaling factors

Returns:

pyomo model

write_results_tec_design(h5_group, model_block)

Function to report technology design

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

write_results_tec_operation(h5_group, model_block)

Function to report technology operation

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

Generic Technologies

class Res(tec_data: dict)

Renewable technology with capacity factor (has no input)

Resembles a renewable technology with no input. The capacity factors of the technology are determined for each individual technology type.

So far the following renewable technologies are possible:

  • Photovoltaic (based on irradiance in climate data and PV lib)

  • Wind turbines (based on wind speed and power curves provided)

Constraint declarations:

  • Output of technology. The output can be curtailed in three different ways. For curtailment == 0, there is no curtailment possible. For curtailment == 1, the curtailment is continuous. For curtailment == 2, the size needs to be an integer, and the technology can only be curtailed discretely, i.e. by turning full modules off. For curtailment == 0 (default), it holds:

\[Output_{t, car} = CapFactor_t * Size\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type RES (renewable technology)

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits technology performance

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

write_results_tec_design(h5_group, model_block)

Function to report technology design

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

write_results_tec_operation(h5_group, model_block)

Function to report technology operation

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

class Conv1(tec_data: dict)

Technology with full input an output substitution

This technology type resembles a technology with full input and output substitution, i.e. \(\sum(output) = f(\sum(inputs))\) Three different performance function fits are possible.

Constraint declarations:

  • Size constraints can be formulated on the input or output. For size_based_on == ‘input’ it holds:

    \[\sum(Input_{t, car}) \leq S\]

    For size_based_on == ‘output’ it holds:

    \[\sum(Output_{t, car}) \leq S\]
  • It is possible to limit the maximum input of a carrier. This needs to be specified in the technology JSON files. Then it holds:

    \[Input_{t, car} <= max_in_{car} * \sum(Input_{t, car})\]
  • performance_function_type == 1: Linear through origin. Note that if min_part_load is larger than 0, the technology cannot be turned off.

    \[\sum(Output_{t, car}) == {\alpha}_1 \sum(Input_{t, car})\]
    \[\min_part_load * S \leq {\alpha}_1 \sum(Input_{t, car})\]
  • performance_function_type == 2: Linear with minimal partload (makes big-m transformation required). If the technology is in on, it holds:

    \[\sum(Output_{t, car}) = {\alpha}_1 \sum(Input_{t, car}) + {\alpha}_2\]
    \[\sum(Input_{car}) \geq Input_{min} * S\]

    If the technology is off, input and output is set to 0:

    \[\sum(Output_{t, car}) = 0\]
    \[\sum(Input_{t, car}) = 0\]

    If the technology has a standby-power, the input of the standy-by power carrier is:

    \[Input_{t, standby-carrier} = standbypower * S\]
  • performance_function_type == 3: Piecewise linear performance function ( makes big-m transformation required). The same constraints as for performance_function_type == 2 with the exception that the performance function is defined piecewise for the respective number of pieces.

  • performance_function_type == 4:Piece-wise linear, minimal partload, includes constraints for slow (>1h) startup and shutdown trajectories. Based on Equations 9-11, 13 and 15 in Morales-España, G., Ramírez-Elizondo, L., & Hobbs, B. F. (2017). Hidden power system inflexibilities imposed by traditional unit commitment formulations. Applied Energy, 191, 223–238. https://doi.org/10.1016/J.APENERGY.2017.01.089

  • Additionally, ramping rates of the technology can be constraint.

    \[-rampingrate \leq \sum(Input_{t, car}) - \sum(Input_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type CONV1

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits conversion technology type 1

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

class Conv2(tec_data: dict)

Technology with full input substitution

This technology type resembles a technology with full input substitution, but different performance functions for the respective output carriers, i.e. \(output_{car} = f_{car}(\sum(inputs))\). Three different performance function fits are possible.

Constraint declarations:

  • Size constraints are formulated on the input.

    \[\sum(Input_{t, car}) \leq S\]
  • It is possible to limit the maximum input of a carrier. This needs to be specified in the technology JSON files. Then it holds:

    \[Input_{t, car} <= max_in_{car} * \sum(Input_{t, car})\]
  • performance_function_type == 1: Linear through origin, i.e.:

    \[Output_{t, car} == {\alpha}_{1, car} \sum(Input_{t, car})\]
    \[\min_part_load * S \leq {\alpha}_1 \sum(Input_{t, car})\]
  • performance_function_type == 2: Linear with minimal partload (makes big-m transformation required). If the technology is in on, it holds:

    \[Output_{t, car} = {\alpha}_{1, car} \sum(Input_{t, car}) + {\alpha}_{2, car}\]
    \[\sum(Input_{car}) \geq Input_{min} * S\]

    If the technology is off, input and output is set to 0:

    \[Output_{t, car} = 0\]
    \[\sum(Input_{t, car}) = 0\]

    If the technology has a standby-power, the input of the standy-by power carrier is:

    \[Input_{t, standby-carrier} = standbypower * S\]
  • performance_function_type == 3: Piecewise linear performance function ( makes big-m transformation required). The same constraints as for performance_function_type == 2 with the exception that the performance function is defined piecewise for the respective number of pieces.

  • performance_function_type == 4:Piece-wise linear, minimal partload, includes constraints for slow (>1h) startup and shutdown trajectories. Based on Equations 9-11, 13 and 15 in Morales-España, G., Ramírez-Elizondo, L., & Hobbs, B. F. (2017). Hidden power system inflexibilities imposed by traditional unit commitment formulations. Applied Energy, 191, 223–238. https://doi.org/10.1016/J.APENERGY.2017.01.089

  • Additionally, ramping rates of the technology can be constraint.

    \[-rampingrate \leq \sum(Input_{t, car}) - \sum(Input_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type CONV2

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits conversion technology type 2

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

class Conv3(tec_data: dict)

Technology with no input/output substitution

This technology type resembles a technology for which the output can be written as a function of the input, according to different performance functions that can be specified in the JSON files (performance_function_type). Four different performance function fits of the technology data (again specified in the JSON file) are possible, and for all the function is based on the input of the main carrier , i.e.,: \(output_{car} = f_{car}(input_{maincarrier})\). Note that the ratio between all input carriers is fixed.

Constraint declarations:

For all technologies modelled with CONV3 (regardless of performance function type): - Size constraints are formulated on the input.

\[Input_{t, maincarrier} \leq S\]
  • The ratios of inputs are fixed and given as:

    \[Input_{t, car} = {\phi}_{car} * Input_{t, maincarrier}\]

    If the technology is turned off, all inputs are set to zero.

  • performance_function_type == 1: Linear through origin. Note that if min_part_load is larger 0, the technology cannot be turned off.

    \[Output_{t, car} = {\alpha}_{1, car} Input_{t, maincarrier}\]
    \[\min_part_load * S \leq {\alpha}_1 Input_{t, maincarrier}\]
  • performance_function_type == 2: Linear with minimal partload. If the technology is in on, it holds:

    If the technology is in on, it holds:

    \[Output_{t, car} = {\alpha}_{1, car} Input_{t, maincarrier} + {\alpha}_{2, car}\]
    \[Input_{maincarrier} \geq Input_{min} * S\]
  • If the technology is off, input and output are set to 0:

    \[Output_{t, car} = 0\]
    \[Input_{t, maincarrier} = 0\]
  • performance_function_type == 3: Piecewise linear performance function ( makes big-m transformation required). The same constraints as for performance_function_type == 2 with the exception that the performance function is defined piecewise for the respective number of pieces.

  • performance_function_type == 4:Piece-wise linear, minimal partload, includes constraints for slow (>1h) startup and shutdown trajectories. Based on Equations 9-11, 13 and 15 in Morales-España, G., Ramírez-Elizondo, L., & Hobbs, B. F. (2017). Hidden power system inflexibilities imposed by traditional unit commitment formulations. Applied Energy, 191, 223–238. https://doi.org/10.1016/J.APENERGY.2017.01.089

  • Additionally, ramping rates of the technology can be constraint.

    \[-rampingrate \leq Input_{t, main-car} - Input_{t-1, car} \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type CONV3

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits conversion technology type 3

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

class Conv4(tec_data: dict)

Technology with no inputs

This technology type resembles a technology with fixed output ratios and no inputs, i.e., \(output_{car} \leq S\). This technology is useful for modelling a technology for which you do not care about the inputs, i.e., you do not wish to construct and solve an energy balance for the input carriers. Two different performance function fits are possible.

Constraint declarations:

For all performance function types, the following constraints hold:

  • Size constraints are formulated on the output.

    \[Output_{t, maincarrier} \leq S\]
  • The ratios of outputs are fixed and given as:

    \[Output_{t, car} = {\phi}_{car} * Output_{t, maincarrier}\]
  • performance_function_type == 1: No further constraints on the performance of the technology.

  • performance_function_type == 2: A minimum part load can be specified ( requiring a big-m transformation for the solving). The following constraints hold:

    When the technology is on:

    \[Output_{maincarrier} \geq Output_{min} * S\]

    When the technology is off, output is set to 0:

    \[Output_{t, car} = 0\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type CONV4

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits conversion technology type 4

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

class Stor(tec_data: dict)

Storage Technology

This model resembles a storage technology. Note that this technology only works for one carrier, and thus the carrier index is dropped in the below notation.

Variable declarations:

  • var_storage_level: Storage level in \(t\): \(E_t\)

  • var_capacity_charge: Charging capacity

  • var_capacity_discharge: Discharging capacity

Constraint declarations:

The following constants are used:

  • \({\eta}_{in}\): Charging efficiency

  • \({\eta}_{out}\): Discharging efficiency

  • \({\lambda_1}\): Self-Discharging coefficient (independent of environment)

  • \({\lambda_2(\Theta)}\): Self-Discharging coefficient (dependent on environment)

  • \(Input_{max}\): Maximal charging capacity

  • \(Output_{max}\): Maximal discharging capacity

  • Size constraint:

    \[E_{t} \leq S\]
  • Maximal charging and discharging:

    \[Input_{t} \leq Input_{max}\]
    \[Output_{t} \leq Output_{max}\]
  • Storage level calculation:

    \[E_{t} = E_{t-1} * (1 - \lambda_1) - \lambda_2(\Theta) * E_{t-1} + {\eta}_{in} * Input_{t} - 1 / {\eta}_{out} * Output_{t}\]
  • If allow_only_one_direction_precise == 1, then only input or output can be unequal to zero in each respective time step (otherwise, simultaneous charging and discharging can lead to unwanted ‘waste’ of energy/material).

  • If in Flexibility the power_energy_ratio == fixed, then the capacity of the charging and discharging power is fixed as a ratio of the energy capacity. Thus:

    \[Input_{max} = \gamma_{charging} * S\]
  • If in ‘Flexibility’ the “power_energy_ratio == flex” (flexible), then the capacity of the charging and discharging power is a variable in the optimization. In this case, the charging and discharging rates specified in the json file are the maximum installed capacities as a ratio of the energy capacity. The model will optimize the charging and discharging capacities, based on the incorporation of these components in the CAPEX function.

  • If an energy consumption for charging or dis-charging process is given, the respective carrier input is:

    \[Input_{t, car} = cons_{car, in} Input_{t}\]
    \[Input_{t, car} = cons_{car, out} Output_{t}\]
  • CAPEX is given by three contributions, the CAPEX of the charging capacity, the CAPEX of the discharging capacity, and the CAPEX of the energy capacity (i.e., the size of the storage).

    \[CAPEX_{chargeCapacity} = chargeCapacity * unitCost_{chargeCapacity}\]
    \[CAPEX_{dischargeCapacity} = dischargeCapacity * unitCost_{dischargeCapacity}\]
    \[CAPEX_{storSize} = storSize * unitCost_{storSize}\]
  • Additionally, ramping rates of the technology can be constraint (for input and output).

    \[-rampingrate \leq Input_{t, maincar} - Input_{t-1, maincar} \leq rampingrate\]
    \[-rampingrate \leq \sum(Output_{t, car}) - \sum(Output_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type STOR, resembling a storage technology

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits conversion technology type STOR and fills in the fitted parameters in a dict

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

write_results_tec_design(h5_group, model_block)

Function to report technology design

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

write_results_tec_operation(h5_group, model_block)

Function to report technology operation

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

Specific Technologies

Solid Sorbent Direct Air Capture

class DacAdsorption(tec_data: dict)

Direct Air Capture technology (adsorption)

The model resembles as Direct Air Capture technology with a modular setup. It has a heat and electricity input and CO2 as an output. The performance is based on data for a generic solid sorbent, as described in the article (see below). The performance data is fitted to the ambient temperature and humidity at the respective node.

The model is based on Wiegner et al. (2022). Optimal Design and Operation of Solid Sorbent Direct Air Capture Processes at Varying Ambient Conditions. Industrial and Engineering Chemistry Research, 2022, 12649–12667. https://doi.org/10.1021/acs.iecr.2c00681. It resembles operation configuration 1 without water spraying.

construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type DAC_adsorption

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits the technology performance

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

write_results_tec_operation(h5_group, model_block)

Function to report technology operation

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

Heat Pump

class HeatPump(tec_data: dict)

Heat pump

Resembles a heat pump Three different types of heat pumps are possible: air sourced ( ‘HeatPump_AirSourced’), ground sourced (‘HeatPump_GroundSourced’) and water sourced (‘HeatPump_WaterSourced’). Additionally, a heating curve is determined for heating for buildings. Then, the application needs to be set to either ‘floor_heating’ or ‘radiator_heating’ in the data file. Otherwise, the output temperature of the heat pump can also be set to a given temperature. The coefficient of performance at full load is calculated in the respective fitting function with the equations provided in Ruhnau, O., Hirth, L., & Praktiknjo, A. (2019). Time series of heat demand and heat pump efficiency for energy system modeling. Scientific Data, 6(1). https://doi.org/10.1038/s41597-019-0199-y

The part load behavior is modelled after equation (3) in Xu, Z., Li, H., Xu, W., Shao, S., Wang, Z., Gou, X., Zhao, M., & Li, J. (2022). Investigation on the efficiency degradation characterization of low ambient temperature air source heat pump under partial load operation. International Journal of Refrigeration, 133, 99–110. https://doi.org/10.1016/J.IJREFRIG.2021.10.002

Essentially, the equations for the heat pump model are the same as for generic conversion technology type 1 (with time-dependent performance parameter).

Ramping rates of the technology can be constraint.

\[-rampingrate \leq \sum(Input_{t, car}) - \sum(Input_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type HP (Heat Pump)

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Performs fitting for technology type HeatPump

Parameters:
  • tec_data – technology data

  • climate_data – climate data

Returns:

Gas Turbine

class GasTurbine(tec_data: dict)

Gas turbine

Resembles gas turbines of different sizes. Hydrogen and Natural Gas Turbines are possible at four different sizes, as indicated by the file names of the data. Performance data and the model is taken from Weimann, L., Ellerker, M., Kramer, G. J., & Gazzani, M. (2019). Modeling gas turbines in multi-energy systems: A linear model accounting for part-load operation, fuel, temperature, and sizing effects. International Conference on Applied Energy. https://doi.org/10.46855/energy-proceedings-5280

A small adaption is made: Natural gas turbines can co-fire hydrogen up to 5% of the energy content

Variable declarations:

  • Total fuel input in \(t\): \(Input_{tot, t}\)

  • Number of turbines on in \(t\): \(N_{on,t}\)

Constraint declarations:

The following constants are used:

  • \(Input_{min}\): Minimal input per turbine

  • \(Input_{max}\): Maximal input per turbine

  • \(in_{H2max}\): Maximal H2 admixture to fuel (only for natural gas turbines, default is 0.05)

  • \({\alpha}\): Performance parameter for electricity output

  • \({\beta}\): Performance parameter for electricity output

  • \({\epsilon}\): Performance parameter for heat output

  • \(f({\Theta})\): Ambient temperature correction factor

  • Input calculation (For hydrogen turbines, \(Input_{NG, t}\) is zero, and the second constraint is removed):

    \[Input_{H2, t} + Input_{NG, t} = Input_{tot, t}\]
    \[Input_{H2, t} \leq in_{H2max} Input_{tot, t}\]
  • Turbines on:

    \[N_{on, t} \leq S\]
  • If technology is on:

    \[Output_{el,t} = ({\alpha} Input_{tot, t} + {\beta} * N_{on, t}) *f({\Theta})\]
    \[Output_{th,t} = {\epsilon} Input_{tot, t} - Output_{el,t}\]
    \[Input_{min} * N_{on, t} \leq Input_{tot, t} \leq Input_{max} * N_{on, t}\]
  • If the technology is off, input and output is set to 0:

    \[\sum(Output_{t, car}) = 0\]
    \[\sum(Input_{t, car}) = 0\]
  • Additionally, ramping rates of the technology can be constraint.

    \[-rampingrate \leq \sum(Input_{t, car}) - \sum(Input_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for gas turbines

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Performs fitting for technology type GasTurbine

Parameters:
  • tec_data – technology data

  • climate_data – climate data

Returns:

write_results_tec_operation(h5_group, model_block)

Function to report results of technologies after optimization

Parameters:

b_tec – technology model block

Returns:

dict results: holds results

Hydro Open

class HydroOpen(tec_data: dict)

Open pumped hydro technology

Resembles a pumped hydro plant with additional natural inflows (defined in climate data). Note that this technology only works for one carrier, and thus the carrier index is dropped in the below notation.

Variable declarations:

  • Storage level in \(t\): \(E_t\)

  • Charging in \(t\): \(Input_{t}\)

  • Discharging in \(t\): \(Output_{t}\)

Constraint declarations:

The following constants are used:

  • \({\eta}_{in}\): Charging efficiency

  • \({\eta}_{out}\): Discharging efficiency

  • \({\lambda}\): Self-Discharging coefficient

  • \(Input_{max}\): Maximal charging capacity in one time-slice

  • \(Output_{max}\): Maximal discharging capacity in one time-slice

  • \(Natural_Inflow{t}\): Natural water inflow in time slice (can be negative, i.e. being an outflow)

  • Maximal charging and discharging:

    \[Input_{t} \leq Input_{max}\]
    \[Output_{t} \leq Output_{max}\]
  • Size constraint:

    \[E_{t} \leq S\]
  • Storage level calculation:

    \[E_{t} = E_{t-1} * (1 - \lambda) + {\eta}_{in} * Input_{t} - 1 / {\eta}_{out} * Output_{t} + Natural_Inflow_{t}\]
  • If allow_only_one_direction == 1, then only input or output can be unequal to zero in each respective time step (otherwise, simultanous charging and discharging can lead to unwanted ‘waste’ of energy/material).

  • Additionally, ramping rates of the technology can be constraint (for input and output).

    \[-rampingrate \leq Input_{t, maincar} - Input_{t-1, maincar} \leq rampingrate\]
    \[-rampingrate \leq \sum(Input_{t, car}) - \sum(Input_{t-1, car}) \leq rampingrate\]
construct_tech_model(b_tec, data: dict, set_t_full, set_t_clustered)

Adds constraints to technology blocks for tec_type Hydro_Open

Parameters:
  • b_tec – pyomo block with technology model

  • data (dict) – data containing model configuration

  • set_t_full – pyomo set containing timesteps

  • set_t_clustered – pyomo set containing clustered timesteps

Returns:

pyomo block with technology model

fit_technology_performance(climate_data: DataFrame, location: dict)

Fits technology performance

Parameters:
  • climate_data (pd.Dataframe) – dataframe containing climate data

  • location (dict) – dict containing location details

write_results_tec_operation(h5_group, model_block)

Function to report technology operation

Parameters:
  • model_block – pyomo network block

  • h5_group – h5 group to write to

Carbon Capture

Explanation of CCS & Sink