diff --git a/LoadProfile.py b/Utilities/LoadProfile.py similarity index 53% rename from LoadProfile.py rename to Utilities/LoadProfile.py index 8476637..4518635 100644 --- a/LoadProfile.py +++ b/Utilities/LoadProfile.py @@ -1,5 +1,6 @@ import numpy as np -from Utilities.Time import generate_timestrings, index_peak_times +from Utilities.Time import generate_timestrings, index_peak_times, index_operating_hours +from scipy.optimize import root_scalar def get_no_of_peaks(peak_bounds): @@ -24,6 +25,23 @@ def generate_peak_info(c, dt): return peak_times, peak_durations +def generate_out_of_hours_consumption_ratio(c): + # Generate a random ratio for out-of-hours consumption + ratio = np.random.uniform( + c["site_info"]["out_of_hours_consumption"]["min"], + c["site_info"]["out_of_hours_consumption"]["max"], + ) + return ratio + + +def generate_realistic_profile(site, peak_indices, out_of_hours_ratio): + pass + + +def objective(x): + pass + + def get_load_profile(c, dt, batch_start_time, batch_process_duration): # Generate load profile for each site @@ -36,10 +54,19 @@ def get_load_profile(c, dt, batch_start_time, batch_process_duration): # generate timeseries from start to end time start_time = batch_start_time end_time = start_time + batch_process_duration - timestamps = np.arange(start_time, end_time, dt) + timestamps = np.arange(start_time, end_time + 1, dt) + operating_hours_indices = index_operating_hours( + timestamps, c["site_info"]["operating hours"] + ) - # Generate peak times and durations - peak_times, peak_durations = generate_peak_info(c, dt) + # loop through each site in the configuration + for site in c["site_info"]["sites"]: + # Generate peak times and durations + peak_times, peak_durations = generate_peak_info(c, dt) - # Generate peak times and durations - peak_indices = index_peak_times(timestamps, peak_times, peak_durations) + # Generate peak times and durations + peak_indices = index_peak_times(timestamps, peak_times, peak_durations) + + # Generate out-of-hours consumption ratio + # The % of energy used outside of the operating hours + out_of_hours_ratio = generate_out_of_hours_consumption_ratio(c) diff --git a/Utilities/Time.py b/Utilities/Time.py index 751de52..a368cf4 100644 --- a/Utilities/Time.py +++ b/Utilities/Time.py @@ -4,9 +4,12 @@ import numpy as np import matplotlib.pyplot as pl -def get_current_time(): +def get_start_time(): """Returns the current time in seconds since the epoch.""" - return time.time() + current_date = datetime.now() + # set to 00:00 + current_date = current_date.replace(hour=0, minute=0, second=0, microsecond=0) + return int(current_date.timestamp()) def generate_timestrings(start_time_str, end_time_str, dt): @@ -40,15 +43,34 @@ def index_peak_times(timestamps, peak_times, peak_durations): ) peak_start = int(full_datetime.timestamp()) peak_end = peak_start + duration * 60 # duration in minutes to seconds - peak_timestamps = np.arange(peak_start, peak_end, dt, dtype=int) + peak_timestamps = np.arange(peak_start, peak_end + 1, dt, dtype=int) - common, indices_ts, _ = np.intersect1d( - timestamps, peak_timestamps, return_indices=True - ) - peak_indices[indices_ts] = peak_occurence_no + indices = np.where(np.isin(timestamps, peak_timestamps))[0] + peak_indices[indices] = peak_occurence_no peak_occurence_no += 1 - pl.plot(peak_indices, label="Peak Indices") - pl.show() + return peak_indices - return processed_times + +def index_operating_hours(timestamps, operating_hours): + """Indexes the operating hours in the timestamps.""" + # operating_hours is a dictionary with "start" and "end" keys in HH:MM format + + operating_indices = np.zeros(len(timestamps), dtype=int) + start_time = datetime.strptime(operating_hours["start"], "%H:%M") + end_time = datetime.strptime(operating_hours["end"], "%H:%M") + + # get date from timestamp variable + start_date = datetime.fromtimestamp(timestamps[0]).date() + start_datetime = datetime.combine(start_date, start_time.time()) + end_datetime = datetime.combine(start_date, end_time.time()) + + # convert to seconds since epoch + start_time = int(start_datetime.timestamp()) + end_time = int(end_datetime.timestamp()) + + for i, ts in enumerate(timestamps): + if start_time <= ts <= end_time: + operating_indices[i] = 1 # mark as operating hour + + return operating_indices diff --git a/YAMLs/site_info.yaml b/YAMLs/site_info.yaml index 7eca9fc..bf748d5 100644 --- a/YAMLs/site_info.yaml +++ b/YAMLs/site_info.yaml @@ -32,3 +32,6 @@ peak_duration: unit: minutes min: 1 max: 4 +out_of_hours_consumption: + min: 0.05 + max: 0.15 diff --git a/main.py b/main.py index f546732..e8641cc 100644 --- a/main.py +++ b/main.py @@ -1,13 +1,13 @@ import yaml -from Utilities.Time import get_current_time -from LoadProfile import get_load_profile +from Utilities.Time import get_start_time +from Utilities.LoadProfile import get_load_profile # read config file c = yaml.safe_load(open("YAMLs/config.yml")) ## simulation time setup # get current time -c["sim_start_time"] = get_current_time() +c["sim_start_time"] = get_start_time() # get time step in minutes, then convert to seconds dt = c["sim_time"]["time_step_minutes"] * 60 # compute end time based on duration in days diff --git a/requirements.txt b/requirements.txt index 07ac851..791c1fd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,16 @@ +contourpy==1.3.2 +cycler==0.12.1 +fonttools==4.58.5 +kiwisolver==1.4.8 +matplotlib==3.10.3 numpy==2.3.1 +packaging==25.0 pandas==2.3.1 +pillow==11.3.0 +pyparsing==3.2.3 python-dateutil==2.9.0.post0 pytz==2025.2 +PyYAML==6.0.2 +scipy==1.16.0 six==1.17.0 tzdata==2025.2