{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "import glob\n", "import shutil\n", "import matplotlib.pyplot as plt\n", "import matplotlib.ticker as ticker\n", "from matplotlib.ticker import FuncFormatter\n", "import numpy as np\n", "import pandas as pd\n", "import os\n", "import seaborn as sns\n", "import json\n", "from matplotlib.colors import LinearSegmentedColormap\n", "\n", "def clear_folder_make_ess_pv(folder_path):\n", " if os.path.isdir(folder_path):\n", " shutil.rmtree(folder_path)\n", " os.makedirs(folder_path)\n", " os.makedirs(os.path.join(folder_path,'ess'))\n", " os.makedirs(os.path.join(folder_path,'pv'))\n", "\n", "folder_path = 'plots'\n", "clear_folder_make_ess_pv(folder_path)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "import numpy as np\n", "import pandas as pd\n", "from EnergySystem import EnergySystem\n", "from config import pv_config, grid_config, ess_config\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", "print(\"Version 0.0.4\")\n", "\n", "with open('config.json', 'r') as f:\n", " js_data = json.load(f)\n", "\n", "\n", " \n", "\n", "time_interval = js_data[\"time_interval\"][\"numerator\"] / js_data[\"time_interval\"][\"denominator\"]\n", "\n", "pv_loss = js_data[\"pv\"][\"loss\"]\n", "pv_cost_per_kW = js_data[\"pv\"][\"cost_per_kW\"]\n", "pv_lifetime = js_data[\"pv\"][\"lifetime\"]\n", "\n", "ess_loss = js_data[\"ess\"][\"loss\"]\n", "ess_cost_per_kW = js_data[\"ess\"][\"cost_per_kW\"]\n", "ess_lifetime = js_data[\"ess\"][\"lifetime\"]\n", "\n", "grid_loss = js_data[\"grid\"][\"loss\"]\n", "sell_price = js_data[\"grid\"][\"sell_price\"] #kWh\n", "grid_capacity = js_data[\"grid\"][\"capacity\"] #kWh\n", "\n", "pv_begin = js_data[\"pv_capacities\"][\"begin\"]\n", "pv_end = js_data[\"pv_capacities\"][\"end\"]\n", "pv_groups = js_data[\"pv_capacities\"][\"groups\"]\n", "\n", "ess_begin = js_data[\"ess_capacities\"][\"begin\"]\n", "ess_end = js_data[\"ess_capacities\"][\"end\"]\n", "ess_groups = js_data[\"ess_capacities\"][\"groups\"]\n", "\n", "annot_unmet = js_data[\"annotated\"][\"unmet_prob\"]\n", "annot_benefit = js_data[\"annotated\"][\"benefit\"]\n", "annot_cost = js_data[\"annotated\"][\"cost\"]\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", "\n", "figure_size = (js_data[\"figure_size\"][\"length\"], js_data[\"figure_size\"][\"height\"])\n", "\n", "data = pd.read_csv('combined_data.csv')\n", "\n", "granularity = js_data[\"time_interval\"][\"numerator\"]\n", "\n", "months_days = [31,28,31,30,31,30,31,31,30,31,30,31]\n", "def get_month_coe(num, granularity):\n", " return 60 / granularity * 24 * months_days[num]\n", "\n", "months_index = [get_month_coe(num, granularity) for num in range(12)]\n", "months_data = []\n", "for i in range(1,12):\n", " months_index[i] += months_index[i-1]\n", "for i in range(12):\n", " start = 0 if i == 0 else months_index[i-1]\n", " end = months_index[i]\n", " months_data.append(data.iloc[int(start):int(end)])\n", " \n", "\n", "\n", "\n", "pv_capacities = np.linspace(pv_begin, pv_end, pv_groups)\n", "ess_capacities = np.linspace(ess_begin, ess_end, ess_groups)\n", "# results = pd.DataFrame(index=pv_capacities, columns= ess_capacities)\n", "# affords = 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" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "hour_demand = []\n", "for index, row in data.iterrows():\n", " time = row['time']\n", " demand = row['demand']\n", " if time.endswith('00'):\n", " hour_demand.append(demand)\n", "plt.figure(figsize=(10,8))\n", "plt.plot(hour_demand)\n", "plt.ylabel('Demand Power / kW')\n", "plt.savefig('plots/demand.png')\n", "plt.close()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def draw_results(results, filename, title_benefit, annot_benefit=False, figure_size=(10, 10)):\n", " df=results\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", " max_scale = max(abs(min_value/1000), abs(max_value/1000))\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/1000)\n", "\n", " cmap = sns.color_palette(\"coolwarm\", as_cmap=True)\n", " plt.figure(figsize=figure_size)\n", " ax = sns.heatmap(df/1000, fmt=\".1f\", cmap=cmap, vmin=-max_scale, vmax=max_scale, 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_benefit)\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, "metadata": {}, "outputs": [], "source": [ "def draw_cost(costs, filename, title_cost, annot_cost=False, figure_size=(10, 10)):\n", " df = costs\n", " df = df.astype(int)\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", "\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", " 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 / 1000000)\n", "\n", " plt.figure(figsize=figure_size)\n", " ax = sns.heatmap(df/1000000, fmt=\".1f\", cmap='viridis', annot=annot_cost)\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_cost)\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, "metadata": {}, "outputs": [], "source": [ "def draw_overload(overload_cnt, filename, title_unmet, annot_unmet=False, figure_size=(10, 10), days=365, granularity=15):\n", " df = overload_cnt\n", " print(days, granularity)\n", " coef = 60 / granularity * days * 24\n", " print(coef)\n", " print(df)\n", " df = ( coef - df) / coef\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", "\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", " # print(new_Data)\n", " df = pd.concat([df, new_Data])\n", "\n", "\n", " plt.figure(figsize=figure_size)\n", " cmap = LinearSegmentedColormap.from_list(\"\", [\"white\", \"blue\"])\n", " 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.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", " def fmt(x, pos):\n", " return '{:.0f}%'.format(x * 100)\n", " CS = ax.contour(X, Y, df, colors='black', alpha=0.5)\n", "\n", " ax.clabel(CS, inline=True, fontsize=10, fmt=FuncFormatter(fmt))\n", "\n", " plt.xlim(0, df.shape[1] - 1)\n", " plt.ylim(0, df.shape[0] - 1)\n", " plt.title(title_unmet)\n", " plt.xlabel('ESS Capacity (MWh)')\n", " plt.ylabel('PV Capacity (MW)')\n", " plt.savefig(filename)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def cal_profit(es: EnergySystem, saved_money, days):\n", " profit = saved_money - es.ess.get_cost_per_year() / 365 * days - es.pv.get_cost_per_year() / 365 * days\n", " return profit" ] }, { "cell_type": "code", "execution_count": null, "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", " pv = pv_config(capacity=pv_capacity, \n", " cost_per_kW=pv_cost_per_kW,\n", " lifetime=pv_lifetime, \n", " loss=pv_loss)\n", " ess = ess_config(capacity=ess_capacity, \n", " cost_per_kW=ess_cost_per_kW, \n", " lifetime=ess_lifetime, \n", " loss=ess_loss,\n", " charge_power=ess_capacity,\n", " discharge_power=ess_capacity)\n", " grid = grid_config(capacity=grid_capacity, \n", " grid_loss=grid_loss,\n", " sell_price= sell_price)\n", " energySystem = EnergySystem(pv_type=pv, \n", " ess_type=ess, \n", " grid_type= grid)\n", " benefit = 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" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "months_results = []\n", "months_costs = []\n", "months_overload = []\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", " 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", " 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", " months_results.append(results)\n", " months_costs.append(costs)\n", " months_overload.append(overload_cnt)\n", " draw_results(results=results, \n", " filename=f'plots/pv-{pv_capacity}-ess-{ess_capacity}-{index}-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", " title_unmet=title_unmet,\n", " annot_unmet=annot_unmet,\n", " figure_size=figure_size,\n", " days=months_days[index],\n", " granularity=granularity)\n", "\n", "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", "\n", "# get the yearly results\n", "for pv_capacity in pv_capacities:\n", " for ess_capacity in ess_capacities:\n", " results = 0\n", " costs = 0\n", " overload_cnt = 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", " 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", "\n", "draw_cost(costs=annual_costs,\n", " filename='plots/annual_cost.png',\n", " title_cost=title_cost,\n", " annot_cost=annot_cost,\n", " figure_size=figure_size)\n", "draw_results(results=annual_result,\n", " filename='plots/annual_benefit.png',\n", " title_benefit=title_benefit,\n", " annot_benefit=annot_benefit,\n", " figure_size=figure_size)\n", "draw_overload(overload_cnt=annual_overload,\n", " filename='plots/annual_unmet.png',\n", " title_unmet=title_unmet,\n", " annot_unmet=annot_unmet,\n", " figure_size=figure_size)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def save_data(data, filename):\n", " data.to_csv(filename+'.csv')\n", " data.to_json(filename + '.json')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "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')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 2 }