Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Appliance_growth_example_final.xlsx
Binary file not shown.
118 changes: 118 additions & 0 deletions RAMP_New_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 1 10:28:55 2024

@author: nilsl
"""

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from openpyxl import load_workbook
from ramp import UseCase, User
import time
import datetime

start = time.time()



workbook = load_workbook(filename="example_excel_usecase_filled_final.xlsx")
workbook.save(filename="example_excel_usecase_filled_new_final.xlsx")

use_case = UseCase() # creating a new UseCase instance

use_case.load("example_excel_usecase_filled_new_final.xlsx")

#dictionary for the user and appliance limits
user_lim = {}
user_lim['household_low'] = 15
user_lim['household_low_growth'] = 15
user_lim['household_med'] = 15
user_lim['household_med_growth'] = 15
user_lim['household_high'] = 7
user_lim['household_high_growth'] = 7
user_lim['IGA'] = 3
user_lim['Church'] = 2
user_lim['PL'] = 1
app_lim = {}
app_lim['light'] = 8
app_lim['radio'] = 2
app_lim['tv'] = 1
app_lim['decoder'] = 1
app_lim['dvd'] = 1
app_lim['charger'] = 3
app_lim['woofer'] = 1
app_lim['freezer'] = 1
app_lim['speaker'] = 1
app_lim['light_fresh'] = 8
app_lim['radio_fresh'] = 2
app_lim['tv_fresh'] = 1
app_lim['decoder_fresh'] = 1
app_lim['dvd_fresh'] = 1
app_lim['charger_fresh'] = 4
app_lim['woofer_fresh'] = 1
app_lim['freezer_fresh'] = 1
app_lim['speaker_fresh'] = 1
app_lim['laptop_fresh'] = 1

app_lim['Appliance_1'] = 2
app_lim['Appliance_2'] = 2
app_lim['Appliance_3'] = 2
app_lim['Appliance_4'] = 2
app_lim['Appliance_5'] = 5



Load_ECOS = np.mean(np.load("Load_ECOS.npy").reshape((24,60)),axis = 1)

n_days = 30
date_start = "2024-01-01"
use_case.date_start = date_start
use_case.initialize(num_days=n_days, force=True)
n_years = 5
profile = use_case.generate_daily_load_profiles(flat=True, num_years = n_years, num_app_lim=app_lim, num_user_lim=user_lim, load_growth='yes')





if n_years == 1:
Load = profile.reshape((n_days,60*24))
Load_mean_day = np.mean(Load, axis = 0).reshape((24,60))
Load_RAMP = np.mean(Load_mean_day, axis = 1)
plt.plot(Load_RAMP)
plt.show()

else:
Load = profile.iloc[:].to_numpy()
Load_mean_day = np.zeros((n_years,1440))
for n in range(n_years):
Load_year_n = np.transpose(Load[:,n])
Load_year_n_reshape = Load_year_n.reshape((n_days,1440))
Load_mean_day[n,:] = np.mean(Load_year_n_reshape, axis = 0)

Load_plot = np.mean(Load_mean_day.reshape((n_years,24,60)),axis=2)
fig, ax = plt.subplots()
time_axis = [datetime.datetime(2024, 1, 1, 8) + datetime.timedelta(hours=i) for i in range(24)] # 08:00 to 08:00 next day
tick_times = [time_axis[0] + datetime.timedelta(hours=i) for i in range(0, 24, 2)]
plot_legend = []
for n2 in range(n_years):
plt.plot(time_axis,Load_plot[n2,:], label = str(n2))
plot_legend.append("Year" + str(n2))
plt.xticks(fontsize = 11)
plt.yticks(fontsize = 11)

ax.set_xticks(tick_times)
ax.set_xticklabels([dt.strftime('%H:%M') for dt in tick_times], rotation=45)
plt.legend(plot_legend, fontsize = 12)
plt.xlabel("Time [Hour]", fontsize = 13)
plt.ylabel("Electrical Demand [kW]", fontsize = 13)
plt.tight_layout()
plt.show()






106 changes: 91 additions & 15 deletions ramp/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ def __init__(
if self.random_seed:
random.seed(self.random_seed)


@property
def date_start(self):
"""Start date of the daily profiles generated by the UseCase instance"""
Expand Down Expand Up @@ -386,8 +387,9 @@ def calc_peak_time_range(self, peak_enlarge=None):
# The peak_time is randomly enlarged based on the calibration parameter peak_enlarge
return np.arange(peak_time - rand_peak_enlarge, peak_time + rand_peak_enlarge)

"""Added a new input here: num_years"""
def generate_daily_load_profiles(
self, days=None, flat=True, cases=None, verbose=False
self, days=None, flat=True, cases=None, verbose=False, num_years = 1, num_user_lim = None, num_app_lim = None, load_growth = 'no'
):
"""
Iterate over the days and generate a daily profile for each of the days
Expand All @@ -407,14 +409,77 @@ def generate_daily_load_profiles(
-------
daily_profiles: numpy array
"""
if cases is not None:
if num_years > 1:
if load_growth == 'yes': #add new appliances if the promotion year has come
app_gr_df = pd.read_excel("Appliance_growth_example_final.xlsx")
results = {}
for case in cases:
profiles = self.generate_daily_load_profiles(days=days, flat=True)
results[f"case {case}"] = pd.Series(
original_user_info = {}
new_user_info = {}
for y in range(num_years):
#print("Year ",y)
#print("Number of days: ", self.days)
for user in self.users: #for each user category
#increase the number of users in the user category based on the uniform distribution for all users
if user.num_users < num_user_lim[user.user_name]:
#print("The old number of users: ",user.user_name, user.num_users)
user_increase = int(np.heaviside(y,0)*round(random.uniform(0,1))) # heaviside function is used to make sure that no increases are made in year 0
if user.num_users + user_increase > num_user_lim[user.user_name]:
user_increase = num_user_lim[user.user_name] - user.num_users
user.num_users = random.choice([user.num_users,user.num_users,user.num_users+user_increase])
#print("The new number of users:", user.num_users,"\nUser Increase:", user_increase)
#if user.num_users == num_user_lim[user.user_name]:
# print("Maximum number of users reached")

for app in user.App_list:
if app.number < num_app_lim[app.name]:
#print("The old number of apps: ",app.name, app.number)
app_increase = int(np.heaviside(y,0)*round(random.uniform(0,1)))
if app.number + app_increase > num_app_lim[app.name]:
app_increase = num_app_lim[app.name] - app.number
app.number = random.choice([app.number,app.number,app.number+app_increase])
#print("The new number of apps: ",app.number,"\nApp increase: ",app_increase)
#if app.number == num_app_lim[app.name]:
#print("Max number of appliances reached")
for user in self.users:
for n_gr in range(app_gr_df.shape[0]):
if app_gr_df.loc[n_gr,'growth_name'] == user.user_name and app_gr_df.loc[n_gr,'growth_year'] == y: #check which appliances have to be adjusted in numbers
user_new = User(user.user_name + "_growth", user.num_users, user.user_preference) #define a new user instance
self.add_user(user_new)
user_new.add_appliance(
number=int(app_gr_df.loc[n_gr,'number']),
power=float(app_gr_df.loc[n_gr,'power']),
num_windows=int(app_gr_df.loc[n_gr,'num_windows']),
func_time=int(app_gr_df.loc[n_gr,'func_time']),
time_fraction_random_variability=float(app_gr_df.loc[n_gr,'time_fraction_random_variability']),
func_cycle=int(app_gr_df.loc[n_gr,'func_cycle']),
#fixed=app_prom_df.loc[n_prom,'fixed'],
#flat=app_prom_df.loc[n_prom,'flat'],
name=app_gr_df.loc[n_gr,'name'],
occasional_use=float(app_gr_df.loc[n_gr,'occasional_use']),
window_1 = np.array([app_gr_df.loc[n_gr,'window_1_start'],app_gr_df.loc[n_gr,'window_1_end']],dtype=np.intc),
window_2 = np.array([app_gr_df.loc[n_gr,'window_2_start'],app_gr_df.loc[n_gr,'window_2_end']],dtype=np.intc),
window_3 = np.array([app_gr_df.loc[n_gr,'window_3_start'],app_gr_df.loc[n_gr,'window_3_end']],dtype=np.intc),
random_var_w = float(app_gr_df.loc[n_gr,'random_var_w'])
)
#Uncomment to have two sets of users to compare the original users with the final ones
# =============================================================================
# if y == 0:
# for user in self.users:
# original_user_info[user.user_name] = user.num_users
# elif y == num_years-1:
# for user in self.users:
# new_user_info[user.user_name] = user.num_users
# print(user.App_list)
# print(original_user_info)
# print(new_user_info)
# =============================================================================
self.save("multiyear output year " + str(y)) # just for checking the use_case. Can be commented out
profiles = self.generate_daily_load_profiles(days=days, flat=True, num_years = 1)
results[f"y {y}"] = pd.Series(
index=self.datetimeindex, data=profiles
)
answer = Plot(pd.concat(results, axis=1))

answer = pd.concat(results, axis=1)
else:
if self.days is None:
if days is not None:
Expand Down Expand Up @@ -613,30 +678,30 @@ def load(self, filename: str) -> None:

# assign windows arguments
for k in WINDOWS_PARAMETERS:
if "window" in k:
w_start = row.get(k + "_start", np.NaN)
w_end = row.get(k + "_end", np.NaN)
if "window" in k:
w_start = row.get(k + "_start", np.nan)
w_end = row.get(k + "_end", np.nan)
if not np.isnan(w_start) and not np.isnan(w_end):
appliance_parameters[k] = np.array(
[w_start, w_end], dtype=np.intc
)
else:
val = row.get(k, np.NaN)
val = row.get(k, np.nan)
if not np.isnan(val):
appliance_parameters[k] = val

# assign duty cycles arguments
for duty_cycle_params in DUTY_CYCLE_PARAMETERS:
for k in duty_cycle_params:
if "cw" in k:
cw_start = row.get(k + "_start", np.NaN)
cw_end = row.get(k + "_end", np.NaN)
cw_start = row.get(k + "_start", np.nan)
cw_end = row.get(k + "_end", np.nan)
if not np.isnan(cw_start) and not np.isnan(cw_end):
appliance_parameters[k] = np.array(
[cw_start, cw_end], dtype=np.intc
)
else:
val = row.get(k, np.NaN)
val = row.get(k, np.nan)
if not np.isnan(val):
appliance_parameters[k] = val

Expand Down Expand Up @@ -667,7 +732,8 @@ def __init__(
# TODO check type of Usecase
self.usecase = usecase
self.user_name = user_name
self.num_users = num_users
"""Changed self.num_users = num_users to self._num_users = num_users"""
self._num_users = num_users
self.user_preference = user_preference
self.rand_daily_pref = 0
self.load = None
Expand Down Expand Up @@ -822,6 +888,16 @@ def num_days(self):
if self.usecase.is_initialized is True:
answer = self.usecase.num_days
return answer

"""Added a new propery with a setter: num_users"""
@property
def num_users(self):
return self._num_users

@num_users.setter
def num_users(self, new_num_users):
self._num_users = new_num_users


def save(self, filename: str = None) -> Union[pd.DataFrame, None]:
"""Saves/returns the model database including all appliances as a single pd.DataFrame or excel file.
Expand Down Expand Up @@ -1046,7 +1122,7 @@ def generate_aggregated_load_profile(
"""

self.load = np.zeros(1440) # initialise empty load for User instance
for _ in range(self.num_users):
for _ in range(self._num_users):
# iterates for every single user within a User class.
self.load = self.load + self.generate_single_load_profile(
prof_i, peak_time_range, day_type
Expand Down