v0.0.5 code

This commit is contained in:
Hanzhang Ma 2024-05-10 23:57:58 +02:00
parent ebebd2d481
commit 060fa5bff1
6 changed files with 70547 additions and 35277 deletions

View File

@ -35,6 +35,8 @@ class EnergySystem:
# 如果ESS也不足以满足需求再从电网获取 - 当ESS中的存储电量也不足以补充时再从电网购买剩余所需电量。
def simulate(self, data, time_interval):
total_benefit = 0
total_netto_benefit = 0
total_gen = 0
for index, row in data.iterrows():
time = row['time']
sunlight_intensity = row['sunlight']
@ -109,9 +111,11 @@ class EnergySystem:
# 工厂需求量-总能量
# unmet_demand = max(0, factory_demand * time_interval - total_energy)
# benefit = (total_energy - unmet_demand) * electricity_price
total_gen += saved_energy
benefit = (saved_energy) * electricity_price
cost = net_grid * electricity_price
# print(f"time:{time} benefit: {benefit}, cost: {cost}")
total_netto_benefit += benefit
total_benefit += benefit - cost
# # spring
week_start = self.season_start
@ -137,4 +141,4 @@ class EnergySystem:
# self.winter_week_gen.append(generated_pv_power)
# self.winter_week_soc.append(self.ess.storage / self.ess.capacity)
return total_benefit
return (total_benefit, total_netto_benefit, total_gen)

View File

@ -17,12 +17,12 @@
"pv_capacities":{
"begin": 0,
"end": 50000,
"groups": 5
"groups": 11
},
"ess_capacities":{
"begin": 0,
"end": 100000,
"groups": 10
"groups": 11
},
"time_interval":{
"numerator": 15,
@ -31,7 +31,8 @@
"annotated": {
"unmet_prob": false,
"benefit": false,
"cost": false
"cost": false,
"roi": false
},
"figure_size":{
"height": 9,
@ -40,6 +41,7 @@
"plot_title":{
"unmet_prob": "Coverage Rate of Factory Electrical Demands",
"cost": "Costs of Microgrid system [m-EUR]",
"benefit": "Financial Profit Based on Py & Ess Configuration (k-EUR / year)"
"benefit": "Financial Profit Based on Py & Ess Configuration (k-EUR / year)",
"roi": "ROI"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@
"source": [
"import json\n",
"\n",
"print(\"Version 0.0.4\")\n",
"print(\"Version 0.0.5\")\n",
"\n",
"with open('config.json', 'r') as f:\n",
" js_data = json.load(f)\n",
@ -61,6 +61,7 @@
" \n",
"\n",
"time_interval = js_data[\"time_interval\"][\"numerator\"] / js_data[\"time_interval\"][\"denominator\"]\n",
"print(time_interval)\n",
"\n",
"pv_loss = js_data[\"pv\"][\"loss\"]\n",
"pv_cost_per_kW = js_data[\"pv\"][\"cost_per_kW\"]\n",
@ -85,10 +86,13 @@
"annot_unmet = js_data[\"annotated\"][\"unmet_prob\"]\n",
"annot_benefit = js_data[\"annotated\"][\"benefit\"]\n",
"annot_cost = js_data[\"annotated\"][\"cost\"]\n",
"annot_roi = js_data[\"annotated\"][\"roi\"]\n",
"\n",
"title_unmet = js_data[\"plot_title\"][\"unmet_prob\"]\n",
"title_cost = js_data[\"plot_title\"][\"cost\"]\n",
"title_benefit = js_data[\"plot_title\"][\"benefit\"]\n",
"title_roi = js_data[\"plot_title\"][\"roi\"]\n",
"\n",
"\n",
"figure_size = (js_data[\"figure_size\"][\"length\"], js_data[\"figure_size\"][\"height\"])\n",
"\n",
@ -181,6 +185,59 @@
" plt.savefig(filename)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def draw_roi(costs, results, filename, title_roi, days=365, annot_roi=False, figure_size=(10, 10)):\n",
" costs = costs.astype(float)\n",
" costs = costs / 365 \n",
" costs = costs * days\n",
"\n",
" df = results\n",
" df = costs / df\n",
" if 0 in df.index and 0 in df.columns:\n",
" df.loc[0,0] = 100\n",
" df[df > 80] = 100\n",
" print(df)\n",
"\n",
" df = df.astype(float)\n",
" df.index = df.index / 1000\n",
" df.index = df.index.map(int)\n",
" df.columns = df.columns / 1000\n",
" df.columns = df.columns.map(int)\n",
" min_value = df.min().min()\n",
" max_value = df.max().max()\n",
" print(max_value)\n",
" max_scale = max(abs(min_value), abs(max_value))\n",
"\n",
" df[df.columns[-1] + 1] = df.iloc[:, -1] \n",
" new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns)\n",
" for i in df.columns:\n",
" new_Data[i] = df[i].iloc[-1]\n",
" df = pd.concat([df, new_Data])\n",
"\n",
" X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))\n",
"\n",
" def fmt(x,pos):\n",
" return '{:.0f}'.format(x)\n",
"\n",
" cmap = sns.color_palette(\"Greys\", as_cmap=True)\n",
" plt.figure(figsize=figure_size)\n",
" ax = sns.heatmap(df, fmt=\".1f\", cmap=cmap, vmin=0, vmax=100, annot=annot_benefit)\n",
" CS = ax.contour(X, Y, df, colors='black', alpha=0.5)\n",
" ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))\n",
" plt.title(title_roi)\n",
" plt.gca().invert_yaxis()\n",
" plt.xlim(0, df.shape[1] - 1)\n",
" plt.ylim(0, df.shape[0] - 1)\n",
" plt.xlabel('ESS Capacity (MWh)')\n",
" plt.ylabel('PV Capacity (MW)')\n",
" plt.savefig(filename)"
]
},
{
"cell_type": "code",
"execution_count": null,
@ -253,8 +310,8 @@
" ax = sns.heatmap(df, fmt=\".00%\", cmap=cmap, vmin=0, vmax=1, annot=annot_unmet)\n",
"\n",
" cbar = ax.collections[0].colorbar\n",
" cbar.set_ticks([0, 0.25, 0.5, 0.75, 1])\n",
" cbar.set_ticklabels(['0%', '25%', '50%', '75%', '100%'])\n",
" cbar.set_ticks([0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1])\n",
" cbar.set_ticklabels(['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%'])\n",
" cbar.ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'{x:.0%}'))\n",
" X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))\n",
"\n",
@ -289,7 +346,7 @@
"metadata": {},
"outputs": [],
"source": [
"def generate_data(pv_capacity, pv_cost_per_kW, pv_lifetime, pv_loss, ess_capacity, ess_cost_per_kW, ess_lifetime, ess_loss, grid_capacity, grid_loss, sell_price,time_interval, data, days):\n",
"def generate_data(pv_capacity, pv_cost_per_kW, pv_lifetime, pv_loss, ess_capacity, ess_cost_per_kW, ess_lifetime, ess_loss, grid_capacity, grid_loss, sell_price, time_interval, data, days):\n",
" pv = pv_config(capacity=pv_capacity, \n",
" cost_per_kW=pv_cost_per_kW,\n",
" lifetime=pv_lifetime, \n",
@ -306,11 +363,11 @@
" energySystem = EnergySystem(pv_type=pv, \n",
" ess_type=ess, \n",
" grid_type= grid)\n",
" benefit = energySystem.simulate(data, time_interval)\n",
" (benefit, netto_benefit, gen_energy) = energySystem.simulate(data, time_interval)\n",
" results = cal_profit(energySystem, benefit, days)\n",
" overload_cnt = energySystem.overload_cnt\n",
" costs = energySystem.ess.capacity * energySystem.ess.cost_per_kW + energySystem.pv.capacity * energySystem.pv.cost_per_kW\n",
" return (results, overload_cnt, costs)\n"
" return (results, overload_cnt, costs, netto_benefit, gen_energy, energySystem.generated)\n"
]
},
{
@ -322,26 +379,38 @@
"months_results = []\n",
"months_costs = []\n",
"months_overload = []\n",
"months_nettos = []\n",
"months_gen_energy = []\n",
"months_gen_energy2 = []\n",
"for index, month_data in enumerate(months_data):\n",
" results = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" gen_energies = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" gen_energies2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
" for pv_capacity in pv_capacities:\n",
" for ess_capacity in ess_capacities:\n",
" (result, overload, cost) = generate_data(pv_capacity=pv_capacity,pv_cost_per_kW=pv_cost_per_kW, pv_lifetime=pv_lifetime, pv_loss=pv_loss, ess_capacity=ess_capacity, ess_cost_per_kW=ess_cost_per_kW, ess_lifetime=ess_lifetime, ess_loss=ess_loss, grid_capacity=grid_capacity, grid_loss=grid_loss, sell_price=sell_price, time_interval=time_interval, data=month_data, days=months_days[index])\n",
" (result, overload, cost, netto, gen_energy, gen_energy2) = generate_data(pv_capacity=pv_capacity,pv_cost_per_kW=pv_cost_per_kW, pv_lifetime=pv_lifetime, pv_loss=pv_loss, ess_capacity=ess_capacity, ess_cost_per_kW=ess_cost_per_kW, ess_lifetime=ess_lifetime, ess_loss=ess_loss, grid_capacity=grid_capacity, grid_loss=grid_loss, sell_price=sell_price, time_interval=time_interval, data=month_data, days=months_days[index])\n",
" results.loc[pv_capacity,ess_capacity] = result\n",
" overload_cnt.loc[pv_capacity,ess_capacity] = overload\n",
" costs.loc[pv_capacity,ess_capacity] = cost\n",
" nettos.loc[pv_capacity,ess_capacity] = netto\n",
" gen_energies.loc[pv_capacity, ess_capacity] = gen_energy\n",
" gen_energies2.loc[pv_capacity, ess_capacity] = gen_energy2\n",
" months_results.append(results)\n",
" months_costs.append(costs)\n",
" months_overload.append(overload_cnt)\n",
" months_nettos.append(nettos)\n",
" months_gen_energy.append(gen_energies)\n",
" months_gen_energy2.append(gen_energies2)\n",
" draw_results(results=results, \n",
" filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-{index}-benefit.png',\n",
" filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-benefit.png',\n",
" title_benefit=title_benefit,\n",
" annot_benefit=annot_benefit,\n",
" figure_size=figure_size)\n",
" draw_overload(overload_cnt=overload_cnt, \n",
" filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-{index}-unmet.png',\n",
" filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-unmet.png',\n",
" title_unmet=title_unmet,\n",
" annot_unmet=annot_unmet,\n",
" figure_size=figure_size,\n",
@ -351,6 +420,11 @@
"annual_result = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"annual_costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"annual_overload = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"annual_nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"annual_gen = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"annual_gen2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n",
"\n",
"\n",
"\n",
"# get the yearly results\n",
"for pv_capacity in pv_capacities:\n",
@ -358,13 +432,22 @@
" results = 0\n",
" costs = 0\n",
" overload_cnt = 0\n",
" nettos = 0\n",
" gen = 0\n",
" gen2 = 0\n",
" for index, month_data in enumerate(months_data):\n",
" results += months_results[index].loc[pv_capacity,ess_capacity]\n",
" costs += months_costs[index].loc[pv_capacity,ess_capacity]\n",
" overload_cnt += months_overload[index].loc[pv_capacity, ess_capacity]\n",
" nettos += months_nettos[index].loc[pv_capacity, ess_capacity]\n",
" gen += months_gen_energy[index].loc[pv_capacity, ess_capacity]\n",
" gen2 += months_gen_energy[index].loc[pv_capacity, ess_capacity]\n",
" annual_result.loc[pv_capacity, ess_capacity] = results\n",
" annual_costs.loc[pv_capacity, ess_capacity] = costs\n",
" annual_overload.loc[pv_capacity, ess_capacity] = overload_cnt\n",
" annual_nettos.loc[pv_capacity, ess_capacity] = nettos\n",
" annual_gen.loc[pv_capacity, ess_capacity] = gen\n",
" annual_gen2.loc[pv_capacity, ess_capacity] = gen2\n",
"\n",
"draw_cost(costs=annual_costs,\n",
" filename='plots/annual_cost.png',\n",
@ -403,9 +486,27 @@
"if not os.path.isdir('data'):\n",
" os.makedirs('data')\n",
"\n",
"save_data(results, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results')\n",
"save_data(costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs')\n",
"save_data(overload_cnt, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt')"
"save_data(annual_result, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results')\n",
"save_data(annual_costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs')\n",
"save_data(annual_overload, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"draw_results(annual_result, 'plots/test.png', 'test', False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"draw_roi(annual_costs, annual_nettos, 'plots/annual_roi.png', title_roi, 365, annot_benefit, figure_size)\n"
]
}
],

524
main.py
View File

@ -1,12 +1,21 @@
#!/usr/bin/env python
# coding: utf-8
# In[14]:
# In[ ]:
import os
import glob
import shutil
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.ticker import FuncFormatter
import numpy as np
import pandas as pd
import os
import seaborn as sns
import json
from matplotlib.colors import LinearSegmentedColormap
def clear_folder_make_ess_pv(folder_path):
if os.path.isdir(folder_path):
@ -19,7 +28,7 @@ folder_path = 'plots'
clear_folder_make_ess_pv(folder_path)
# In[15]:
# In[ ]:
import matplotlib.pyplot as plt
@ -30,18 +39,21 @@ from EnergySystem import EnergySystem
from config import pv_config, grid_config, ess_config
# In[16]:
# In[ ]:
import json
print("Version 0.0.2")
print("Version 0.0.5")
with open('config.json', 'r') as f:
js_data = json.load(f)
data = pd.read_csv('combined_data.csv')
time_interval = js_data["time_interval"]["numerator"] / js_data["time_interval"]["denominator"]
print(time_interval)
pv_loss = js_data["pv"]["loss"]
pv_cost_per_kW = js_data["pv"]["cost_per_kW"]
@ -66,22 +78,45 @@ ess_groups = js_data["ess_capacities"]["groups"]
annot_unmet = js_data["annotated"]["unmet_prob"]
annot_benefit = js_data["annotated"]["benefit"]
annot_cost = js_data["annotated"]["cost"]
annot_roi = js_data["annotated"]["roi"]
title_unmet = js_data["plot_title"]["unmet_prob"]
title_cost = js_data["plot_title"]["cost"]
title_benefit = js_data["plot_title"]["benefit"]
title_roi = js_data["plot_title"]["roi"]
figure_size = (js_data["figure_size"]["length"], js_data["figure_size"]["height"])
data = pd.read_csv('combined_data.csv')
granularity = js_data["time_interval"]["numerator"]
months_days = [31,28,31,30,31,30,31,31,30,31,30,31]
def get_month_coe(num, granularity):
return 60 / granularity * 24 * months_days[num]
months_index = [get_month_coe(num, granularity) for num in range(12)]
months_data = []
for i in range(1,12):
months_index[i] += months_index[i-1]
for i in range(12):
start = 0 if i == 0 else months_index[i-1]
end = months_index[i]
months_data.append(data.iloc[int(start):int(end)])
pv_capacities = np.linspace(pv_begin, pv_end, pv_groups)
ess_capacities = np.linspace(ess_begin, ess_end, ess_groups)
results = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
affords = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# results = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# affords = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# In[17]:
# In[ ]:
hour_demand = []
@ -97,21 +132,192 @@ plt.savefig('plots/demand.png')
plt.close()
# In[18]:
# In[ ]:
def cal_profit(es: EnergySystem, saved_money):
profit = saved_money - es.ess.get_cost_per_year() - es.pv.get_cost_per_year()
def draw_results(results, filename, title_benefit, annot_benefit=False, figure_size=(10, 10)):
df=results
df = df.astype(float)
df.index = df.index / 1000
df.index = df.index.map(int)
df.columns = df.columns / 1000
df.columns = df.columns.map(int)
min_value = df.min().min()
max_value = df.max().max()
max_scale = max(abs(min_value/1000), abs(max_value/1000))
df[df.columns[-1] + 1] = df.iloc[:, -1]
new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns)
for i in df.columns:
new_Data[i] = df[i].iloc[-1]
df = pd.concat([df, new_Data])
X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))
def fmt(x,pos):
return '{:.0f}'.format(x/1000)
cmap = sns.color_palette("coolwarm", as_cmap=True)
plt.figure(figsize=figure_size)
ax = sns.heatmap(df/1000, fmt=".1f", cmap=cmap, vmin=-max_scale, vmax=max_scale, annot=annot_benefit)
CS = ax.contour(X, Y, df, colors='black', alpha=0.5)
ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))
plt.title(title_benefit)
plt.gca().invert_yaxis()
plt.xlim(0, df.shape[1] - 1)
plt.ylim(0, df.shape[0] - 1)
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig(filename)
# In[ ]:
def draw_roi(costs, results, filename, title_roi, days=365, annot_roi=False, figure_size=(10, 10)):
costs = costs.astype(float)
costs = costs / 365
costs = costs * days
df = results
df = costs / df
if 0 in df.index and 0 in df.columns:
df.loc[0,0] = 100
df[df > 80] = 100
print(df)
df = df.astype(float)
df.index = df.index / 1000
df.index = df.index.map(int)
df.columns = df.columns / 1000
df.columns = df.columns.map(int)
min_value = df.min().min()
max_value = df.max().max()
print(max_value)
max_scale = max(abs(min_value), abs(max_value))
df[df.columns[-1] + 1] = df.iloc[:, -1]
new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns)
for i in df.columns:
new_Data[i] = df[i].iloc[-1]
df = pd.concat([df, new_Data])
X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))
def fmt(x,pos):
return '{:.0f}'.format(x)
cmap = sns.color_palette("Greys", as_cmap=True)
plt.figure(figsize=figure_size)
ax = sns.heatmap(df, fmt=".1f", cmap=cmap, vmin=0, vmax=100, annot=annot_benefit)
CS = ax.contour(X, Y, df, colors='black', alpha=0.5)
ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))
plt.title(title_roi)
plt.gca().invert_yaxis()
plt.xlim(0, df.shape[1] - 1)
plt.ylim(0, df.shape[0] - 1)
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig(filename)
# In[ ]:
def draw_cost(costs, filename, title_cost, annot_cost=False, figure_size=(10, 10)):
df = costs
df = df.astype(int)
df.index = df.index / 1000
df.index = df.index.map(int)
df.columns = df.columns / 1000
df.columns = df.columns.map(int)
df[df.columns[-1] + 1] = df.iloc[:, -1]
new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns)
for i in df.columns:
new_Data[i] = df[i].iloc[-1]
df = pd.concat([df, new_Data])
X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))
def fmt(x, pos):
return '{:.0f}'.format(x / 1000000)
plt.figure(figsize=figure_size)
ax = sns.heatmap(df/1000000, fmt=".1f", cmap='viridis', annot=annot_cost)
CS = ax.contour(X, Y, df, colors='black', alpha=0.5)
ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))
plt.title(title_cost)
plt.gca().invert_yaxis()
plt.xlim(0, df.shape[1] - 1)
plt.ylim(0, df.shape[0] - 1)
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig(filename)
# In[ ]:
def draw_overload(overload_cnt, filename, title_unmet, annot_unmet=False, figure_size=(10, 10), days=365, granularity=15):
df = overload_cnt
print(days, granularity)
coef = 60 / granularity * days * 24
print(coef)
print(df)
df = ( coef - df) / coef
print(df)
df = df.astype(float)
df.index = df.index / 1000
df.index = df.index.map(int)
df.columns = df.columns / 1000
df.columns = df.columns.map(int)
df[df.columns[-1] + 1] = df.iloc[:, -1]
new_Data = pd.DataFrame(index=[df.index[-1] + 1], columns=df.columns)
for i in df.columns:
new_Data[i] = df[i].iloc[-1]
# print(new_Data)
df = pd.concat([df, new_Data])
plt.figure(figsize=figure_size)
cmap = LinearSegmentedColormap.from_list("", ["white", "blue"])
ax = sns.heatmap(df, fmt=".00%", cmap=cmap, vmin=0, vmax=1, annot=annot_unmet)
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1])
cbar.set_ticklabels(['0%', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%', '100%'])
cbar.ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'{x:.0%}'))
X, Y = np.meshgrid(np.arange(df.shape[1]), np.arange(df.shape[0]))
def fmt(x, pos):
return '{:.0f}%'.format(x * 100)
CS = ax.contour(X, Y, df, colors='black', alpha=0.5)
ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))
plt.xlim(0, df.shape[1] - 1)
plt.ylim(0, df.shape[0] - 1)
plt.title(title_unmet)
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig(filename)
# In[ ]:
def cal_profit(es: EnergySystem, saved_money, days):
profit = saved_money - es.ess.get_cost_per_year() / 365 * days - es.pv.get_cost_per_year() / 365 * days
return profit
# In[24]:
# In[ ]:
for ess_capacity in ess_capacities:
print(f"ess_capacity:{ess_capacity}")
for pv_capacity in pv_capacities:
print(f"pv_capacity:{pv_capacity}")
def generate_data(pv_capacity, pv_cost_per_kW, pv_lifetime, pv_loss, ess_capacity, ess_cost_per_kW, ess_lifetime, ess_loss, grid_capacity, grid_loss, sell_price, time_interval, data, days):
pv = pv_config(capacity=pv_capacity,
cost_per_kW=pv_cost_per_kW,
lifetime=pv_lifetime,
@ -128,133 +334,107 @@ for ess_capacity in ess_capacities:
energySystem = EnergySystem(pv_type=pv,
ess_type=ess,
grid_type= grid)
benefit = energySystem.simulate(data, time_interval)
results.loc[pv_capacity,ess_capacity] = cal_profit(energySystem, benefit)
affords.loc[pv_capacity,ess_capacity] = energySystem.afford
overload_cnt.loc[pv_capacity,ess_capacity] = energySystem.overload_cnt
costs.loc[pv_capacity,ess_capacity] = energySystem.ess.capacity * energySystem.ess.cost_per_kW + energySystem.pv.capacity * energySystem.pv.cost_per_kW
pv_generated = energySystem.day_generated
ess_generated = energySystem.hour_stored
ess_generated_2 = energySystem.hour_stored_2
plt.figure(figsize=(10,8));
plt.plot(ess_generated)
plt.xlabel('day #')
plt.ylabel('SoC %')
plt.title(f'14:00 ESS SoC \n PV cap:{pv_capacity}, ESS cap:{ess_capacity}')
plt.savefig(f'plots/ess/1400-{pv_capacity}-{ess_capacity}.png')
plt.close()
plt.figure(figsize=(10,8));
plt.plot(ess_generated_2)
plt.xlabel('day #')
plt.ylabel('SoC%')
plt.title(f'08:00 ESS SoC \n PV cap:{pv_capacity}, ESS cap:{ess_capacity}')
plt.savefig(f'plots/ess/0800-{pv_capacity}-{ess_capacity}.png')
plt.close()
# print(energySystem.unmet)
# spring_week_start = energySystem.season_start
# spring_week_end = spring_week_start + energySystem.week_length
# summer_week_start = energySystem.season_start + 1 * energySystem.season_step
# summer_week_end = summer_week_start + energySystem.week_length
# autumn_week_start = energySystem.season_start + 2 * energySystem.season_step
# autumn_week_end = autumn_week_start + energySystem.week_length
# winter_week_start = energySystem.season_start + 3 * energySystem.season_step
# winter_week_end = winter_week_start+ energySystem.week_length
# spring_consume_data = []
# summer_consume_data = []
# autumn_consume_data = []
# winter_consume_data = []
# for index, row in data.iterrows():
# if index in range(spring_week_start, spring_week_end):
# spring_consume_data.append(row['demand'])
# elif index in range(summer_week_start, summer_week_end):
# summer_consume_data.append(row['demand'])
# elif index in range(autumn_week_start, autumn_week_end):
# autumn_consume_data.append(row['demand'])
# elif index in range(winter_week_start, winter_week_end):
# winter_consume_data.append(row['demand'])
# spring_week_time = list(range(spring_week_start, spring_week_end))
# summer_week_time = list(range(summer_week_start, summer_week_end))
# autumn_week_time = list(range(autumn_week_start, autumn_week_end))
# winter_week_time = list(range(winter_week_start, winter_week_end))
# spring_pv_generated = energySystem.spring_week_gen
# summer_pv_generated = energySystem.summer_week_gen
# autumn_pv_generated = energySystem.autumn_week_gen
# winter_pv_generated = energySystem.winter_week_gen
# spring_soc = energySystem.spring_week_soc
# summer_soc = energySystem.summer_week_soc
# autumn_soc = energySystem.autumn_week_soc
# winter_soc = energySystem.winter_week_soc
(benefit, netto_benefit, gen_energy) = energySystem.simulate(data, time_interval)
results = cal_profit(energySystem, benefit, days)
overload_cnt = energySystem.overload_cnt
costs = energySystem.ess.capacity * energySystem.ess.cost_per_kW + energySystem.pv.capacity * energySystem.pv.cost_per_kW
return (results, overload_cnt, costs, netto_benefit, gen_energy, energySystem.generated)
# fig, ax1 = plt.subplots()
# plt.plot(spring_week_time, spring_pv_generated, label = 'pv generation')
# plt.plot(spring_week_time, spring_consume_data, label = 'factory consume')
# plt.ylabel('Power / kW')
# plt.xlabel('15 min #')
# plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW spring week generate condition')
# plt.legend()
# plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-spring.png')
# plt.close()
# plt.plot(summer_week_time, summer_pv_generated, label = 'pv generation')
# plt.plot(summer_week_time, summer_consume_data, label = 'factory consume')
# plt.ylabel('Power / kW')
# plt.xlabel('15 min #')
# plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW summer week generate condition')
# plt.legend()
# plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-summer.png')
# plt.close()
# plt.plot(autumn_week_time, autumn_pv_generated, label = 'pv generation')
# plt.plot(autumn_week_time, autumn_consume_data, label = 'factory consume')
# plt.ylabel('Power / kW')
# plt.xlabel('15 min #')
# plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW autumn week generate condition')
# plt.legend()
# plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-autumn.png')
# plt.close()
# plt.plot(winter_week_time, winter_pv_generated, label = 'pv generation')
# plt.plot(winter_week_time, winter_consume_data, label = 'factory consume')
# plt.ylabel('Power / kW')
# plt.xlabel('15 min #')
# plt.title(f'ess: {energySystem.ess.capacity/1000 } MWh pv: {energySystem.pv.capacity/1000 } MW winter week generate condition')
# plt.legend()
# plt.savefig(f'plots/{energySystem.ess.capacity}-{energySystem.pv.capacity}-winter.png')
# plt.close()
# plt.figure();
# plt.plot(pv_generated)
# plt.xlabel('day #')
# plt.ylabel('Electricity kWh')
# plt.title(f'PV generated pv cap:{pv_capacity}, ess cap:{ess_capacity}')
# plt.savefig(f'plots/pv/{pv_capacity}-{ess_capacity}.png')
# plt.close()
# In[ ]:
# plt.show()
months_results = []
months_costs = []
months_overload = []
months_nettos = []
months_gen_energy = []
months_gen_energy2 = []
for index, month_data in enumerate(months_data):
results = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
overload_cnt = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
gen_energies = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
gen_energies2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
for pv_capacity in pv_capacities:
for ess_capacity in ess_capacities:
(result, overload, cost, netto, gen_energy, gen_energy2) = generate_data(pv_capacity=pv_capacity,pv_cost_per_kW=pv_cost_per_kW, pv_lifetime=pv_lifetime, pv_loss=pv_loss, ess_capacity=ess_capacity, ess_cost_per_kW=ess_cost_per_kW, ess_lifetime=ess_lifetime, ess_loss=ess_loss, grid_capacity=grid_capacity, grid_loss=grid_loss, sell_price=sell_price, time_interval=time_interval, data=month_data, days=months_days[index])
results.loc[pv_capacity,ess_capacity] = result
overload_cnt.loc[pv_capacity,ess_capacity] = overload
costs.loc[pv_capacity,ess_capacity] = cost
nettos.loc[pv_capacity,ess_capacity] = netto
gen_energies.loc[pv_capacity, ess_capacity] = gen_energy
gen_energies2.loc[pv_capacity, ess_capacity] = gen_energy2
months_results.append(results)
months_costs.append(costs)
months_overload.append(overload_cnt)
months_nettos.append(nettos)
months_gen_energy.append(gen_energies)
months_gen_energy2.append(gen_energies2)
draw_results(results=results,
filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-benefit.png',
title_benefit=title_benefit,
annot_benefit=annot_benefit,
figure_size=figure_size)
draw_overload(overload_cnt=overload_cnt,
filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-month-{index+1}-unmet.png',
title_unmet=title_unmet,
annot_unmet=annot_unmet,
figure_size=figure_size,
days=months_days[index],
granularity=granularity)
annual_result = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
annual_costs = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
annual_overload = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
annual_nettos = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
annual_gen = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
annual_gen2 = pd.DataFrame(index=pv_capacities, columns= ess_capacities)
# get the yearly results
for pv_capacity in pv_capacities:
for ess_capacity in ess_capacities:
results = 0
costs = 0
overload_cnt = 0
nettos = 0
gen = 0
gen2 = 0
for index, month_data in enumerate(months_data):
results += months_results[index].loc[pv_capacity,ess_capacity]
costs += months_costs[index].loc[pv_capacity,ess_capacity]
overload_cnt += months_overload[index].loc[pv_capacity, ess_capacity]
nettos += months_nettos[index].loc[pv_capacity, ess_capacity]
gen += months_gen_energy[index].loc[pv_capacity, ess_capacity]
gen2 += months_gen_energy[index].loc[pv_capacity, ess_capacity]
annual_result.loc[pv_capacity, ess_capacity] = results
annual_costs.loc[pv_capacity, ess_capacity] = costs
annual_overload.loc[pv_capacity, ess_capacity] = overload_cnt
annual_nettos.loc[pv_capacity, ess_capacity] = nettos
annual_gen.loc[pv_capacity, ess_capacity] = gen
annual_gen2.loc[pv_capacity, ess_capacity] = gen2
# results = results.astype(float)
draw_cost(costs=annual_costs,
filename='plots/annual_cost.png',
title_cost=title_cost,
annot_cost=annot_cost,
figure_size=figure_size)
draw_results(results=annual_result,
filename='plots/annual_benefit.png',
title_benefit=title_benefit,
annot_benefit=annot_benefit,
figure_size=figure_size)
draw_overload(overload_cnt=annual_overload,
filename='plots/annual_unmet.png',
title_unmet=title_unmet,
annot_unmet=annot_unmet,
figure_size=figure_size)
# pv = pv_config(capacity=100000,cost_per_kW=200,lifetime=25,loss=0.95)
# ess = ess_config(capacity=100000,cost_per_kW=300,lifetime=25,loss=0.95,charge_power=100000,discharge_power=100000)
# grid = grid_config(price_schedule=price_schedule, capacity=5000, grid_loss=0.95, sell_price=0.4)
# grid = grid_config(capacity=50000, grid_loss=0.95, sell_price=0.4)
# print(benefit)
# In[20]:
# In[ ]:
def save_data(data, filename):
@ -262,83 +442,25 @@ def save_data(data, filename):
data.to_json(filename + '.json')
# In[21]:
# In[ ]:
import matplotlib.ticker as ticker
if not os.path.isdir('data'):
os.makedirs('data')
save_data(results, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results')
save_data(costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs')
save_data(overload_cnt, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt')
df=results
df = df.astype(float)
df.index = df.index / 1000
df.columns = df.columns / 1000
min_value = df.min().min()
max_value = df.max().max()
max_scale = max(abs(min_value/1000), abs(max_value/1000))
plt.figure(figsize=figure_size)
cmap = sns.color_palette("coolwarm", as_cmap=True)
ax = sns.heatmap(df/1000, fmt=".1f", cmap=cmap, vmin=-max_scale, vmax=max_scale, annot=annot_benefit)
# ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))
plt.title(title_benefit)
plt.gca().invert_yaxis()
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig('plots/benefit.png')
save_data(annual_result, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-results')
save_data(annual_costs, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-costs')
save_data(annual_overload, f'data/{pv_begin}-{pv_end}-{pv_groups}-{ess_begin}-{ess_end}-{ess_groups}-overload_cnt')
# In[22]:
# In[ ]:
df = costs
df = df.astype(int)
df.index = df.index / 1000
df.columns = df.columns / 1000
plt.figure(figsize=figure_size)
sns.heatmap(df/1000000, fmt=".1f", cmap='viridis', annot=annot_cost)
plt.title(title_cost)
plt.gca().invert_yaxis()
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig('plots/costs.png')
# pv = pv_config(capacity=100000,cost_per_kW=200,lifetime=25,loss=0.95)
# ess = ess_config(capacity=100000,cost_per_kW=300,lifetime=25,loss=0.95,charge_power=100000,discharge_power=100000)
# grid = grid_config(price_schedule=price_schedule, capacity=5000, grid_loss=0.95, sell_price=0.4)
# grid = grid_config(capacity=50000, grid_loss=0.95, sell_price=0.4)
draw_results(annual_result, 'plots/test.png', 'test', False)
# print(benefit)
# In[ ]:
# In[23]:
from matplotlib.colors import LinearSegmentedColormap
df = overload_cnt
df = df.astype(int)
df.index = df.index / 1000
df.columns = df.columns / 1000
min_value = df.min().min()
max_value = df.max().max()
max_scale = max(abs(min_value/1000), abs(max_value/1000))
plt.figure(figsize=figure_size)
cmap = LinearSegmentedColormap.from_list("", ["white", "blue"])
ax = sns.heatmap(df/(4*24*365), fmt=".00%", cmap=cmap, vmin=0, vmax=1, annot=annot_unmet)
cbar = ax.collections[0].colorbar
cbar.set_ticks([0, 0.25, 0.5, 0.75, 1])
cbar.set_ticklabels(['0%', '25%', '50%', '75%', '100%'])
cbar.ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, pos: f'{x:.0%}'))
plt.title(title_unmet)
plt.gca().invert_yaxis()
plt.xlabel('ESS Capacity (MWh)')
plt.ylabel('PV Capacity (MW)')
plt.savefig('plots/unmet.png')
draw_roi(annual_costs, annual_nettos, 'plots/annual_roi.png', title_roi, 365, annot_benefit, figure_size)