soc predictor wip
This commit is contained in:
parent
62cf35c727
commit
1b29cfdea8
@ -26,5 +26,19 @@ def discharge_bess(bess, site_name, dt, discharge_power):
|
|||||||
if unit["site"] == site_name:
|
if unit["site"] == site_name:
|
||||||
new_soc = unit["SoC"] - (dt * discharge_energy) / unit["capacity_kWh"]
|
new_soc = unit["SoC"] - (dt * discharge_energy) / unit["capacity_kWh"]
|
||||||
new_soc = 0 if new_soc < 0 else new_soc
|
new_soc = 0 if new_soc < 0 else new_soc
|
||||||
|
else:
|
||||||
|
new_soc = unit["SoC"]
|
||||||
|
|
||||||
|
# update SoC
|
||||||
bess["units"][index]["SoC"] = new_soc
|
bess["units"][index]["SoC"] = new_soc
|
||||||
return bess
|
return bess
|
||||||
|
|
||||||
|
|
||||||
|
def predict_swap_time(bess_soc_for_cycle):
|
||||||
|
"""Predict the swap time for each BESS unit based on its SoC history."""
|
||||||
|
swap_times = {}
|
||||||
|
for unit_name, df in bess_soc_for_cycle.items():
|
||||||
|
# Find the timestamp when SoC reaches 0
|
||||||
|
swap_time = df[df["SoC"] == 0]["Timestamp"].min()
|
||||||
|
swap_times[unit_name] = swap_time
|
||||||
|
return swap_times
|
||||||
|
|||||||
@ -14,3 +14,9 @@ units:
|
|||||||
- name: MBESS 5
|
- name: MBESS 5
|
||||||
capacity_kWh: 2096
|
capacity_kWh: 2096
|
||||||
c-rate: 0.5
|
c-rate: 0.5
|
||||||
|
- name: MBESS 6
|
||||||
|
capacity_kWh: 2096
|
||||||
|
c-rate: 0.5
|
||||||
|
buffer:
|
||||||
|
unit: percentage of buffer
|
||||||
|
min: 0.1
|
||||||
|
|||||||
48
main.py
48
main.py
@ -2,11 +2,17 @@ import numpy as np
|
|||||||
import yaml
|
import yaml
|
||||||
from Utilities.Time import get_start_time
|
from Utilities.Time import get_start_time
|
||||||
from Utilities.LoadProfile import get_load_profiles
|
from Utilities.LoadProfile import get_load_profiles
|
||||||
from Utilities.BESS import initialise_SoC, initial_site_assignment, discharge_bess
|
from Utilities.BESS import (
|
||||||
|
initialise_SoC,
|
||||||
|
initial_site_assignment,
|
||||||
|
discharge_bess,
|
||||||
|
predict_swap_time,
|
||||||
|
)
|
||||||
import matplotlib.pyplot as pl
|
import matplotlib.pyplot as pl
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
|
|
||||||
# read config file
|
# read config file
|
||||||
c = yaml.safe_load(open("YAMLs/config.yml"))
|
c = yaml.safe_load(open("YAMLs/config.yml"))
|
||||||
|
|
||||||
@ -41,7 +47,13 @@ def generate_and_cache_profiles(c, dt):
|
|||||||
bess_data = initialise_SoC(bess_data)
|
bess_data = initialise_SoC(bess_data)
|
||||||
bess_data = initial_site_assignment(c, bess_data)
|
bess_data = initial_site_assignment(c, bess_data)
|
||||||
# bess SoC dataframe
|
# bess SoC dataframe
|
||||||
bess_soc = pd.DataFrame(columns=[unit["name"] for unit in bess_data["units"]])
|
bess_soc_since_start = pd.DataFrame(
|
||||||
|
columns=[unit["name"] for unit in bess_data["units"]]
|
||||||
|
)
|
||||||
|
# bess SoC dictionary, meant to track SoC progress over each cycle.
|
||||||
|
# resets after each charging cycle. This is for predicting swap times.
|
||||||
|
init_df = pd.DataFrame(columns=["Timestamp", "SoC"])
|
||||||
|
bess_soc_for_cycle = {unit["name"]: init_df for unit in bess_data["units"]}
|
||||||
|
|
||||||
# get initial load profiles
|
# get initial load profiles
|
||||||
cumulative_load_profiles = get_load_profiles(
|
cumulative_load_profiles = get_load_profiles(
|
||||||
@ -71,16 +83,38 @@ with ThreadPoolExecutor() as executor:
|
|||||||
temp_soc = [unit["SoC"] for unit in bess_data["units"]]
|
temp_soc = [unit["SoC"] for unit in bess_data["units"]]
|
||||||
|
|
||||||
# append SoC to dataframe
|
# append SoC to dataframe
|
||||||
bess_soc = pd.concat(
|
bess_soc_since_start = pd.concat(
|
||||||
[
|
[
|
||||||
bess_soc,
|
bess_soc_since_start,
|
||||||
pd.DataFrame(
|
pd.DataFrame(
|
||||||
[temp_soc], columns=bess_soc.columns, index=[timestamps[i]]
|
[temp_soc],
|
||||||
|
columns=bess_soc_since_start.columns,
|
||||||
|
index=[timestamps[i]],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
axis=0,
|
axis=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# assign SoC for cycle
|
||||||
|
for unit in bess_data["units"]:
|
||||||
|
unit_name = unit["name"]
|
||||||
|
# reset df if SoC is 0. Start a new cycle
|
||||||
|
if unit["SoC"] == 0:
|
||||||
|
bess_soc_for_cycle[unit_name] = init_df
|
||||||
|
bess_soc_for_cycle[unit_name] = pd.concat(
|
||||||
|
[
|
||||||
|
bess_soc_for_cycle[unit_name],
|
||||||
|
pd.DataFrame(
|
||||||
|
[[timestamps[i], unit["SoC"]]],
|
||||||
|
columns=["Timestamp", "SoC"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
axis=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
# predict swap times
|
||||||
|
swap_times = predict_swap_time(bess_soc_for_cycle)
|
||||||
|
|
||||||
# add to cumulative load profiles
|
# add to cumulative load profiles
|
||||||
# check if future exists and is done
|
# check if future exists and is done
|
||||||
if is_running_in_async:
|
if is_running_in_async:
|
||||||
@ -96,6 +130,6 @@ with ThreadPoolExecutor() as executor:
|
|||||||
print(len(cumulative_load_profiles), "load profiles generated")
|
print(len(cumulative_load_profiles), "load profiles generated")
|
||||||
is_running_in_async = False
|
is_running_in_async = False
|
||||||
|
|
||||||
pl.plot(bess_soc.index, bess_soc.values, label="BESS SoC", alpha=0.5)
|
pl.plot(cumulative_load_profiles)
|
||||||
pl.show()
|
pl.show()
|
||||||
pl.xlabel("Time (s since epoch)")
|
pl.plot(bess_soc_since_start)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user