111 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import numpy as np
 | |
| from Utilities.Time import generate_timestrings, index_peak_times, index_operating_hours
 | |
| from scipy.optimize import root_scalar
 | |
| import pandas as pd
 | |
| 
 | |
| 
 | |
| def get_no_of_peaks(peak_bounds):
 | |
|     peak_occurences = np.random.randint(peak_bounds["min"], peak_bounds["max"], 1)
 | |
|     return peak_occurences
 | |
| 
 | |
| 
 | |
| def generate_peak_info(c, dt):
 | |
|     no_of_peaks = get_no_of_peaks(c["site_info"]["no_of_peaks"])
 | |
|     operating_hours = generate_timestrings(
 | |
|         c["site_info"]["operating hours"]["start"],
 | |
|         c["site_info"]["operating hours"]["end"],
 | |
|         dt,
 | |
|     )
 | |
|     peak_times = np.random.choice(operating_hours, no_of_peaks, replace=False)
 | |
|     peak_durations = np.random.randint(
 | |
|         c["site_info"]["peak_duration"]["min"],
 | |
|         c["site_info"]["peak_duration"]["max"],
 | |
|         no_of_peaks,
 | |
|     )
 | |
| 
 | |
|     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 recompute_load_profile(
 | |
|     load_profile,
 | |
|     offset,
 | |
| ):
 | |
| 
 | |
|     # apply offset to the load profile
 | |
|     load_profile += offset
 | |
| 
 | |
|     return load_profile
 | |
| 
 | |
| 
 | |
| def get_load_profile(c, dt, batch_start_time, batch_process_duration):
 | |
|     # Generate load profile for each site
 | |
| 
 | |
|     # c is the configuration dictionary
 | |
|     # dt is the time step in seconds
 | |
|     # batch_start_time is the start time for the batch process in seconds since the epoch
 | |
|     # batch_process_duration is the duration of the batch process in seconds
 | |
| 
 | |
|     # start with indexing all the peak occurences
 | |
|     # generate timeseries from start to end time
 | |
|     start_time = batch_start_time
 | |
|     end_time = start_time + batch_process_duration
 | |
|     batch_process_duration_hours = batch_process_duration / 3600  # convert to hours
 | |
|     timestamps = np.arange(start_time, end_time + 1, dt)
 | |
|     idx_operating_hours = index_operating_hours(
 | |
|         timestamps, c["site_info"]["operating hours"]
 | |
|     )
 | |
|     no_of_operating_hours = np.sum(idx_operating_hours > 0)
 | |
| 
 | |
|     # loop through each site in the configuration
 | |
|     for site in c["site_info"]["sites"]:
 | |
|         # Initialise the load profile
 | |
|         load_profile = np.zeros(len(timestamps))
 | |
| 
 | |
|         # generate noise to make the profile more realistic
 | |
|         noise = np.random.normal(
 | |
|             1 - c["noise"]["range"], 1 + c["noise"]["range"], len(timestamps)
 | |
|         )
 | |
|         # Generate peak times and durations
 | |
|         peak_times, peak_durations = generate_peak_info(c, dt)
 | |
| 
 | |
|         # Generate peak times and durations
 | |
|         idx_peak = 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)
 | |
| 
 | |
|         # start by computing average consumption during operating hours
 | |
|         # and outside of operating hours
 | |
|         operating_hour_consumption = site["daily_consumption_kWh"] * (
 | |
|             1 - out_of_hours_ratio
 | |
|         )
 | |
|         out_of_hours_consumption = site["daily_consumption_kWh"] * out_of_hours_ratio
 | |
| 
 | |
|         avg_operating_hour_consumption = (
 | |
|             operating_hour_consumption / no_of_operating_hours
 | |
|         )
 | |
|         avg_out_of_hours_consumption = out_of_hours_consumption / (
 | |
|             batch_process_duration_hours - no_of_operating_hours
 | |
|         )
 | |
| 
 | |
|         # assign base load profile
 | |
|         load_profile[idx_operating_hours > 0] = avg_operating_hour_consumption
 | |
|         load_profile[idx_operating_hours == 0] = avg_out_of_hours_consumption
 | |
| 
 | |
|         # apply peak loads
 | |
|         for i in range(1, np.max(idx_peak) + 1):
 | |
|             load_profile[idx_peak == i] = site["maximum_demand_kW"]
 | |
| 
 | |
|         # apply noise to the load profile, including max demand
 | |
|         load_profile = load_profile * noise
 |