kernel¶
This module defines kernel functions for shipp.
The functions defined in this module are used to solve the dispatch optimization problem with scipy.optimize.linprog or with a rule-based approach. They build the matrices describing the linear optimization from scratch. For complex problems, the use of the functions in kernel_pyomo is prefered.
- Functions:
build_lp_obj_npv: Build objective vector for NPV maximization.
build_lp_cst_sparse: Build sparse constraints for a LP.
solve_lp_sparse: Build and solve a LP for NPV maximization.
os_rule_based: Build the operation schedule with a rule-based EMS
financial_metrics: Calculate financial metrics for a given hybrid power plant
Module Contents¶
Functions¶
Build the objective function vector for NPV maximization for the LP formulation. |
|
Build the objective function vector for revenues maximization for the LP formulation. |
|
Build the sparse constraints for the LP formulation of the dispatch optimization problem. |
|
Build and solve the integrated dispatch optimization problem, formulated as a linear program. |
|
Build the operation schedule following a rule-based control. |
|
Calculate financial metrics for a given hybrid power plant |
Data¶
API¶
- kernel.TOL = 0.0001¶
- kernel.DEFAULT_ALPHA_OBJ = None¶
- kernel.BIG_M = 100¶
- kernel.build_lp_obj_npv(price: numpy.ndarray, n: int, stor1_p_cost: float, stor1_e_cost: float, stor2_p_cost: float, stor2_e_cost: float, discount_rate: float, n_year: int, options: dict = None) numpy.ndarray¶
Build the objective function vector for NPV maximization for the LP formulation.
This function returns an objective vector corresponding to the maximization of Net Present Value (NPV):
f(x) = - factor*price*(power - alpha*curtailed_power) + stor1_e_cost*stor1_e_cap + stor1_p_cost*stor1_p_cap + stor2_e_cost*stor2_e_cap + stor2_p_cost*stor2_p_cap
where factor = sum_n=1^(n_year) (1+discount_rate)**(-n). The objective function vector corresponds to the following design variables:
- Formulation lp:
Power from storage 1 in charge, shape-(n,)
Power from storage 1 in discharge, shape-(n,)
Power from storage 2 in charge, shape-(n,)
Power from storage 2 in discharge, shape-(n,)
Curtailed power, shape-(n,)
State of charge (energy) of storage 1, shape-(n+1,)
State of charge (energy) of storage 2, shape-(n+1,)
Power capacity of storage 1, shape-(1,)
Energy capacity of storage 1, shape-(1,)
Power capacity of storage 2, shape-(1,)
Energy capacity of storage 2, shape-(1,)
The number of design variables is n_x = 7*n+6
Formulation milp:
- Same as the lp formulation with the addition of:
Integer variables for storage 1, shape-(n,)
Integer variables for storage 2, shape-(n,)
The number of design variables is n_x = 9*n+6
- Formulation lp_alt:
Power from storage 1, shape-(n,)
Power from storage 2, shape-(n,)
Curtailed power, shape-(n,)
State of charge (energy) of storage 1, shape-(n+1,)
State of charge (energy) of storage 2, shape-(n+1,)
Power capacity of storage 1, shape-(1,)
Energy capacity of storage 1, shape-(1,)
Power capacity of storage 2, shape-(1,)
Energy capacity of storage 2, shape-(1,)
The number of design variables is n_x = 5*n+6
- Parameters:
price (np.array) – An array of electricity price to calculate the revenue [currency/MWh]
n (int) – the number of time steps [-]
stor1_p_cost (float) – cost of storage 1 per power capacity [currency/MW]
stor1_e_cost (float) – cost of storage 1 per energy capacity [currency/MWh]
stor2_p_cost (float) – cost of storage 2 per power capacity [currency/MW]
stor2_e_cost (float) – cost of storage 2 per energy capacity [currency/MWh]
discount_rate (float) – discount rate to calculate the NPV [-]
n_year (int) – number of years of operation of the project [-]
options (dict) –
list of options for the problem formulation
formulation (str): Problem formulation for the storage model. Allowed values are ‘lp’, ‘lp_alt’, ‘milp’. Default is lp_alt.
alpha_obj (float): penalty factor for the curtailed power in the objective function proportional to the price. Default is (1+1e-6)
beta_obj (float): penalty factor for the curtailed power in the objective function. Default is 0
epsilon (float): penalty factor to avoid simultaneous charge and discharge for the lp formulation. Default is 1e-3.
- Returns:
A shape-(n_x,) array representing the objective function of the linear program [-]
- Return type:
np.ndarray
- Raises:
AssertionError – if the length of the price is below n, if any input is not finite
- kernel.build_lp_obj_revenues(price: numpy.ndarray, n: int, options: dict = None) numpy.ndarray¶
Build the objective function vector for revenues maximization for the LP formulation.
This function returns an objective vector corresponding to revenue maximization
f(x) = -price*(power - alpha*curtailed_power)
The objective function vector corresponds to the following design variables:
- Formulation lp:
Power from storage 1 in charge, shape-(n,)
Power from storage 1 in discharge, shape-(n,)
Power from storage 2 in charge, shape-(n,)
Power from storage 2 in discharge, shape-(n,)
Curtailed power, shape-(n,)
State of charge (energy) of storage 1, shape-(n+1,)
State of charge (energy) of storage 2, shape-(n+1,)
Power capacity of storage 1, shape-(1,)
Energy capacity of storage 1, shape-(1,)
Power capacity of storage 2, shape-(1,)
Energy capacity of storage 2, shape-(1,)
The number of design variables is n_x = 7*n+6
Formulation milp:
- Same as the lp formulation with the addition of:
Integer variables for storage 1, shape-(n,)
Integer variables for storage 2, shape-(n,)
The number of design variables is n_x = 9*n+6
- Formulation lp_alt:
Power from storage 1, shape-(n,)
Power from storage 2, shape-(n,)
Curtailed power, shape-(n,)
State of charge (energy) of storage 1, shape-(n+1,)
State of charge (energy) of storage 2, shape-(n+1,)
Power capacity of storage 1, shape-(1,)
Energy capacity of storage 1, shape-(1,)
Power capacity of storage 2, shape-(1,)
Energy capacity of storage 2, shape-(1,)
The number of design variables is n_x = 5*n+6
- Parameters:
price (np.array) – An array of electricity price to calculate the revenue [currency/MWh]
n (int) – the number of time steps [-]
options (dict) –
list of options for the problem formulation
formulation (str): Problem formulation for the storage model. Allowed values are ‘lp’, ‘lp_alt’, ‘milp’. Default is lp_alt.
alpha_obj (float): penalty factor for the curtailed power in the objective function proportional to the price. Default is (1+1e-6)
beta_obj (float): penalty factor for the curtailed power in the objective function. Default is 0
epsilon (float): penalty factor to avoid simultaneous charge and discharge for the lp formulation. Default is 1e-3.
- Returns:
A shape-(n_x,) array representing the objective function of the linear program [-]
- Return type:
np.ndarray
- Raises:
AssertionError – if the length of the price is below n, if any input is not finite
- kernel.build_lp_cst_sparse(power: numpy.ndarray, dt: float, p_min, p_max: float, n: int, stor1: shipp.components.Storage, stor2: shipp.components.Storage, stor1_p_cap_max: float = -1.0, stor2_p_cap_max: float = -1.0, stor1_e_cap_max: float = -1.0, stor2_e_cap_max: float = -1.0, options: dict = None) tuple[scipy.sparse.coo_matrix, numpy.ndarray, scipy.sparse.coo_matrix, numpy.ndarray, numpy.ndarray, numpy.ndarray]¶
Build the sparse constraints for the LP formulation of the dispatch optimization problem.
Function to build the matrices and vectors for the constraints of the dispatch optimization problem, considering two different storage systems, and as a linear program. A sparse format is used to represent the matrices.
The constraints are made of equality and inequality constraints such that:
mat_eq * x = vec_eq
mat_ineq * x <= vec_ineq
bounds_lower <= x <= bounds_upper
With n the number of time steps, the problem is made of:
n_x = 5*n+6 design variables (lp_alt formulation) or 7*n+6 (lp formulation) or 10*n+6 (milp formulation)
n_eq = 0 equality constraints (lp_alt formulation) or 2*n (lp and milp formulation)
n_ineq = 15*n+6 inequality constraints (lp_alt formulation) or 6+11*n (lp formulation) or 6+17*n (milp formulation)
The design variables for the linear problem are:
Power from storage 1, shape-(n,) (lp_alt formulation) or Power from storage 1 in charge, shape-(n,) and discharge, shape-(n,) (lp and milp formulation)
Power from storage 2, shape-(n,) (lp_alt formulation) or Power from storage 2 in charge, shape-(n,) and discharge, shape-(n,) (lp and milp formulation)
Curtailed power, shape-(n,)
State of charge (energy) of storage 1, shape-(n+1,)
State of charge (energy) of storage 2, shape-(n+1,)
Power capacity of storage 1, shape-(1,)
Energy capacity of storage 1, shape-(1,)
Power capacity of storage 2, shape-(1,)
Energy capacity of storage 2, shape-(1,)
Integer variables for storage 1, shape-(n,1) (milp formulation)
Integer variables for storage 2, shape-(n,1) (milp formulation)
The equality constraints for the problem are:
Constraint to enforce the value of the first stored energy of storage 1 is equal to the last (size 1)
Constraint to enforce the value of the first stored energy of storage 2 is equal to the last (size 1)
(lp formulation only) Constraint to enforce the storage model for Storage 1 (size n)
(lp formulation only) Constraint to enforce the storage model for Storage 2 (size n)
The inequality constraints for the problem are:
Constraints on the minimum and maximum combined power from production and storage assets (size 2*n)
(lp_alt formulation only) Constraints on the stored energy of storage 1 (size 2*n)
(lp_alt formulation only) Constraints on the stored energy of storage 2 (size 2*n)
(lp_alt formulation only) Constraints on the maximmum and minimum power to and from storage 1 (size 2*n)
(lp_alt formulation only) Constraints on the maximmum and minimum power to and from storage 2 (size 2*n)
(lp formulation only) Constraints on the maximmum charge and discharge power for storage 1 (size 2*n)
(lp formulation only) Constraints on the maximmum charge and discharge power for storage 2 (size 2*n)
Constraints on the minimum and maximum stored energy in storage 1 (size 2*(n+1))
Constraints on the minimum and maximum stored energy in storage 2 (size 2*(n+1))
(milp formulation only) Constraint to enforce distinct charge and discharge in storage 1 (size 2*n)
(milp formulation only) Constraint to enforce distinct charge and discharge in storage 2 (size 2*n)
(milp formulation only) Constraint to enforce distinct curtailment and discharge in storage 1 (size n)
(milp formulation only) Constraint to enforce distinct curtailment and discharge in storage 1 (size n)
Constraint on the maximum combined storage power (size n)
- Parameters:
power (np.ndarray) – A shape-(n,) array for the power production from renewables [MW].
dt (float) – time step [s].
p_min (float or np.ndarray) – A float or shape-(n,) array for the minimum required power production [MW].
p_max (float) – maximum power production [MW]
n (int) – number of time steps [-].
stor1 (Storage) – object representing Storage 1 [-].
stor2 (Storage) – object representing Storage 2 [-].
stor1_p_cap_max (float) – maximum power capacity for storage 1 [MW]. Default to -1.0 when there is no limit in power rate.
stor2_p_cap_max (float) – maximum power capacity for storage 2 [MW]. Default to -1.0 when there is no limit in power rate.
stor1_e_cap_max (float) – maximum energy capacity for storage 1 [MWh]. Default to -1.0 when there is no limit.
stor2_e_cap_max (float) – maximum energy capacity for storage 2 [MWh]. Default to -1.0 when there is no limit.
options (dict) –
list of options for the problem formulation
fixed_cap (bool): True if the storage capacity is fixed during the optimization. Default is False.
formulation (str): Problem formulation for the storage model. Allowed values are ‘lp’, ‘lp_alt’, ‘milp’. Default is lp_alt.
- Returns:
[mat_eq, vec_ec, mat_ineq, vec_ineq, bounds_lower, bounds_upper] matrices and vectors representing the inequality, equality and bound constraints of the problem.
- Return type:
tuple[sps.coo_matrix, np.ndarray, sps.coo_matrix, np.ndarray, np.ndarray, np.ndarray]
- Raises:
ValueError – if argument p_min is not a float or a list of floats
AssertionError – if any argument is not finite and if the argument power has a length lower than n
- kernel.solve_lp_sparse(price_ts: shipp.timeseries.TimeSeries, prod1: shipp.components.Production, prod2: shipp.components.Production, stor1: shipp.components.Storage, stor2: shipp.components.Storage, discount_rate: float, n_year: int, p_min, p_max: float, n: int, options: dict = None) shipp.components.OpSchedule¶
Build and solve the integrated dispatch optimization problem, formulated as a linear program.
This function builds and solves the hybrid sizing and operation problem as a linear program. The objective is to minimize the Net Present Value of the plant. The optimization problem finds the optimal energy and power capacity of two storage systems and their optimal dispatch. In this function, the power production inputs are represented by two Production objects (e.g. one for wind and one for solar PV).
- Parameters:
price_ts (TimeSeries) – Time series of the price of electricity on the day-ahead market [currency/MWh].
prod1 (Production) – Object representing the power production of the first production asset.
prod2 (Production) – Object representing the power production of the second production asset.
stor1 (Storage) – Object describing storage 1.
stor2 (Storage) – Object describing storage 2.
discount_rate (float) – Discount rate for the NPV calculation [-].
n_year (int) – Number of years for the NPV calculation [-].
p_min (float or np.ndarray) – Minimum power requirement (e.g. baseload) [MW].
p_max (float) – Maximum power requirement [MW].
n (int) – Number of time steps to consider in the optimization.
options (dict) –
list of options for the problem formulation
formulation (str): Problem formulation for the storage model. Allowed values are ‘lp’, ‘lp_alt’, ‘milp’. Default is lp_alt.
fixed_cap (bool): True if the storage capacity is fixed during the optimization. Default is False.
alpha_obj (float): penalty factor for the curtailed power in the objective function proportional to the price. Default is (1+1e-6)
beta_obj (float): penalty factor for the curtailed power in the objective function. Default is 0
epsilon (float): penalty factor to avoid simultaneous charge and discharge for the lp formulation. Default is 1e-3.
- Returns:
Object describing the optimal operational schedule and optimal storage capacities.
- Return type:
- Raises:
AssertionError – if the time step of the power and price time series do not match, if the length of the power in the Production objects is below n.
RuntimeError – if the optimization algorithm fails to solve the problem.
- kernel.os_rule_based(price_ts: shipp.timeseries.TimeSeries, prod1: shipp.components.Production, prod2: shipp.components.Production, stor1: shipp.components.Storage, stor2: shipp.components.Storage, discount_rate: float, n_year: int, p_min, p_rule: float, price_min: float, n: int, e_start: float = 0) shipp.components.OpSchedule¶
Build the operation schedule following a rule-based control.
This function builds the operation schedule for a hybrid power plant following a rule-based approach. The objective of the controller is to satisfy a baseload power represented by p_min. The control rules are as follow:
if the power produced is above a given value (p_rule), the storage systems are charged.
if the power produced is below p_rule but above the baseload, and if the price is above a threshold (price_min), the storage systems should sell power
if the power output is below the required baseload, power is delivered from the storage systems.
This implementation is based on the work by Jasper Kreeft for the sizing of the Baseload Power Hub.
- Parameters:
price_ts (TimeSeries) – Time series of the price of electricity on theday-ahead market [currency/MWh].
prod1 (Production) – Object describing the first production asset.
prod2 (Production) – Object describing the second production asset.
stor1 (Storage) – Object describing storage 1.
stor2 (Storage) – Object describing storage 2.
discount_rate (float) – Discount rate for the NPV calculation [-].
n_year (int) – Number of years for the NPV calculation [-].
p_min (float or np.ndarray) – Minimum power requirement [MW].
p_rule (float) – Power above which the storage should charge [MW].
price_min (float) – Price above which the storage should discharge [currency]
n (int) – Number of time steps to consider simulation.
- Returns:
Object describing the operational schedule.
- Return type:
- Raises:
AssertionError – if the time step of the power and price time series do not match.
- kernel.financial_metrics(production_list: list[shipp.components.Production], storage_list: list[shipp.components.Storage], production_p: list[shipp.timeseries.TimeSeries], storage_p: list[shipp.timeseries.TimeSeries], p_max_hpp: float, p_cost_shared: float, price: shipp.timeseries.TimeSeries, m: int, discount_rate: float, added_price: float = 0) kernel.financial_metrics.tuple[float, float, float, float, list[float]]¶
Calculate financial metrics for a given hybrid power plant
Five metrics are calculated: LCOE, NPV, IRR, Total CAPEX, and the vector of cashflow during the project.
- Parameters:
production_list (list[Production]) – List of power generation components (wind farm, solar PV, etc.)
storage_list (list[Storage]) – List of storage system components
production_p (list[TimeSeries]) – List of power production time series, corresponding to the components in production_list
storage_p (list[TimeSeries]) – List of storage power time series, corresponding to the components in storage_list
p_max_hpp (float) – Grid connection capacity of the hybrid power plant (MW)
p_cost_shared (float) – Shared CAPEX of the hybrid power plant (e.g., balance of plant), proportional to the grid connection capacity (Currency/MW)
price (TimeSeries) – Time series of electricity price to calculate the revenue (currency/MWh)
m (int) – number of years of operation of the project (-))
discount_rate (float) – discount rate for the calculation of discounted cashflows (-)
added_price (float, optional) – Value of electricity price added to the price timeseries, similar to a subsidy premium (currency/MWh).
- Returns:
[lcoe, npv, irr, capex_tot, cashflow]
- Return type:
tuple[float, float, float, float, list[float]]
- Raises:
AssertionError – if any argument is of incorrect type, if the length of production or storage objects does not match the list of power timeseries, if the time increment is inconsistent.