This repository contains the code and data files for the article "Peer-to-Peer (P2P) Electricity Markets for Low Voltage Networks" by Diana Vieira Fernandes, Nicolas Christin, and Soummya Kar.
Paper submitted and accepted to the 15th IEEE International Conference on Smart Grid Communications (SmartGridComm 2024).
pip install sklearn
Scikit-learn documentation: "2.3.2. K-means" - https://scikit-learn.org/stable/modules/clustering.html#k-means
https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#
pip install pandapower
L. Thurner, A. Scheidler, F. Schäfer et al, pandapower - an Open Source Python Tool for Convenient Modeling, Analysis and Optimization of Electric Power Systems, in IEEE Transactions on Power Systems, vol. 33, no. 6, pp. 6510-6521, Nov. 2018.
pip install gurobipy
Gurobi Optimization Inc., Gurobi Optimizer, 2024 (https://www.gurobi.com)
Typical load profiles (households, commercial)
NREL: https://www.nrel.gov/buildings/end-use-load-profiles.html
Demand: (End Use Load Profiles for the U.S. Building Stock) https://data.openei.org/submissions/4520 (PA, ISO, PJM aggregate TS) National Renewable Energy Laboratory (NREL). (2021). End-Use Load Profiles for the U.S. Building Stock [data set]. Retrieved from https://dx.doi.org/10.25984/1876417.
Supply | Generation
Solar https://globalsolaratlas.info/map (assuming 3kWp)
Other:
NREL Solar Integration Data and Tools
-
CIGRE low voltage radial distribution network (44 bus system)
-
Synthetic Voltage Control LV Networks ''Village'' (80 bus system)
The double auction mechanism is used to incorporate real-world constraints on both the demand and supply sides, whereas
- Buy orders:
$D = { (d_1, p^d_1, q^d_1), \ldots, (d_n, d^b_n, d^b_n) }$ where each tuple represents a buy order with identifier$d_i$ , a willing-to-pay price$p^d_i$ , and a desired quantity$q^d_i$ . - Sell orders:
$S = { (s_1, p^s_1, q^s_1), \ldots, (s_m, p^s_m, q^s_m) }$ where each tuple represents a sell order with identifier$s_i$ , an asking price$p^s_i$ , and an available quantity$q^s_i$ .
The quantities on each are adjusted at each bus
The matching process is described in the Algorithm "Matching_algo".
-
D = set of buy orders
$(d_1, p^d_1, q^d_1), ..., (d_n, p^d_n, q^d_n)$ -
S = set of sell orders
$(s_1, p^s_1, q^s_1), ..., (s_m, p^s_m, q^s_m)$ -
T = empty set (to store matches)
-
Sort D by increasing
$p^d$ (price offered by buyers) -
Sort S by decreasing
$p^s$ (price offered by sellers)
Matching Loop:
-
For each buy order
$(d_i, p^d_i, q^d_i) \in D$ :- If
$q^d_i$ (quantity demanded by buyer) is already 0, skip to the next buy order. - For each sell order
$(s_i,p^s_i,q^s_i) \in S$ :- Check if
$q^s_i$ (quantity offered by seller) is positive and$p^d_i$ (buyer's price) is greater than or equal to$p^s_i$ (seller's price).- If conditions met:
- Calculate traded quantity
$q_t$ as the minimum of$q^d_i and q^s_i$ . - Create a trade tuple
$t = (s_i, d_i, q_{t})$ . - Add
$t$ to the set of matches$T$ . - Update remaining quantities:
-
$q^d_i$ is reduced by$q_{t}$ . -
$q^s_i$ is reduced by$q_{t}$ . - If
$q^d_i$ becomes 0 after the trade, the buyer is satisfied, so move to the next buy order.
-
- Calculate traded quantity
- If conditions met:
- Check if
- If
-
Calculate the total matched quantity
$Q_{Total}$ by summing$q_{t}$ for all trades in$T$ .
A trade
def match_orders(net):
"""
Function to match buy and sell orders for each hour block.
Parameters:
net (dict): Network state containing load and generation data.
Returns:
tuple: Two lists containing matches for buyers and sellers.
"""
def update_network_for_hour(hour, nets):
"""
Function to update the network for a specific hour.
Parameters:
hour (int): The hour for which the network needs to be updated.
nets (list): A list containing network data for each hour.
Returns:
net (dict): Updated network state for the specified hour.
"""
def correct_baseline(network):
"""
Function to correct the baseline (Power Flow for all nodes in the grid and P2P) to get the network state without P2P effect.
Parameters:
network (dict): The current network state.
Returns:
corrected_network (dict): Network state after correcting for P2P effects.
"""
def run_optimization(net, B, adj_matrix, matches_hour):
"""
Function to run optimization for a specific hour.
Parameters:
net (object): Network state for the specific hour.
B (matrix): Susceptance matrix.
adj_matrix (matrix): Adjacency matrix of the network.
matches_hour (list): Matches for the hour from the previous matching function.
Returns:
results: The optimization results for the given hour.
"""
A. Demand and supply simulation 09_23.ipynb here
- Description: Simulates demand and supply patterns (using K-means clustering) for solar, residential, and commercial profiles.
B. Single_timestep_LP_DC_aprox_210724.ipynb here
- Description: Contains a single timestep Linear Programming (LP) DC approximation for testing purposes.
C. P2P_24_hour_block_LP_DC_aprox_21072024.ipynb here
- Description: Handles the optimization process for a 24-hour block using the LP DC approximation method.
- R (ggplot2) plots: here