102 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import numpy as np
 | |
| import yaml
 | |
| from Utilities.Time import get_start_time
 | |
| from Utilities.LoadProfile import get_load_profiles
 | |
| from Utilities.BESS import initialise_SoC, initial_site_assignment, discharge_bess
 | |
| import matplotlib.pyplot as pl
 | |
| import pandas as pd
 | |
| from concurrent.futures import ThreadPoolExecutor
 | |
| 
 | |
| # read config file
 | |
| c = yaml.safe_load(open("YAMLs/config.yml"))
 | |
| 
 | |
| # read BESS data
 | |
| bess_data = yaml.safe_load(open(c["paths"]["bess"]))
 | |
| 
 | |
| ## simulation time setup
 | |
| # 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
 | |
| duration = c["sim_time"]["duration_days"] * 24 * 60 * 60
 | |
| c["sim_end_time"] = c["sim_start_time"] + duration
 | |
| timestamps = np.arange(c["sim_start_time"], c["sim_end_time"] + 1, dt)
 | |
| 
 | |
| # batch process hours in seconds
 | |
| c["sim_time"]["batch_process_seconds"] = c["sim_time"]["batch_process_hours"] * 60 * 60
 | |
| 
 | |
| # load site info
 | |
| c["site_info"] = yaml.safe_load(open(c["paths"]["site_info"]))
 | |
| 
 | |
| 
 | |
| def generate_and_cache_profiles(c, dt):
 | |
|     """Generates load profiles for all sites and caches them."""
 | |
|     return get_load_profiles(
 | |
|         c, dt, c["sim_start_time"], c["sim_time"]["batch_process_seconds"]
 | |
|     )
 | |
| 
 | |
| 
 | |
| # initialise BESS
 | |
| bess_data = initialise_SoC(bess_data)
 | |
| bess_data = initial_site_assignment(c, bess_data)
 | |
| # bess SoC dataframe
 | |
| bess_soc = pd.DataFrame(columns=[unit["name"] for unit in bess_data["units"]])
 | |
| 
 | |
| # get initial load profiles
 | |
| cumulative_load_profiles = get_load_profiles(
 | |
|     c, dt, c["sim_start_time"], c["sim_time"]["batch_process_seconds"]
 | |
| )
 | |
| 
 | |
| # async function is running
 | |
| is_running_in_async = False
 | |
| 
 | |
| # loop through
 | |
| with ThreadPoolExecutor() as executor:
 | |
|     for i in range(0, len(timestamps)):
 | |
|         # start generating load profiles 200 seconds before data required
 | |
|         if len(cumulative_load_profiles) <= len(timestamps):
 | |
|             if is_running_in_async is False:
 | |
|                 # generate load profiles
 | |
|                 future = executor.submit(generate_and_cache_profiles, c, dt)
 | |
|                 is_running_in_async = True
 | |
|         else:
 | |
|             is_running_in_async = False
 | |
| 
 | |
|         # discharge BESS for each site
 | |
|         for site in c["site_info"]["sites"]:
 | |
|             site_name = site["name"]
 | |
|             discharge_power = cumulative_load_profiles[site_name].iloc[i]
 | |
|             bess_data = discharge_bess(bess_data, site_name, dt, discharge_power)
 | |
|         temp_soc = [unit["SoC"] for unit in bess_data["units"]]
 | |
| 
 | |
|         # append SoC to dataframe
 | |
|         bess_soc = pd.concat(
 | |
|             [
 | |
|                 bess_soc,
 | |
|                 pd.DataFrame(
 | |
|                     [temp_soc], columns=bess_soc.columns, index=[timestamps[i]]
 | |
|                 ),
 | |
|             ],
 | |
|             axis=0,
 | |
|         )
 | |
| 
 | |
|         # add to cumulative load profiles
 | |
|         # check if future exists and is done
 | |
|         if is_running_in_async:
 | |
|             if future.done():
 | |
|                 load_profiles = future.result()
 | |
|                 cumulative_load_profiles = pd.concat(
 | |
|                     [
 | |
|                         cumulative_load_profiles,
 | |
|                         load_profiles,
 | |
|                     ],
 | |
|                     axis=0,
 | |
|                 )
 | |
|                 print(len(cumulative_load_profiles), "load profiles generated")
 | |
|                 is_running_in_async = False
 | |
| 
 | |
| pl.plot(bess_soc.index, bess_soc.values, label="BESS SoC", alpha=0.5)
 | |
| pl.show()
 | |
| pl.xlabel("Time (s since epoch)")
 |