Skip to content

Commit

Permalink
add load_profile stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
remi-l committed Feb 11, 2025
1 parent 40879a2 commit 327947a
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 35 deletions.
2 changes: 1 addition & 1 deletion NetworkEcartLEPlot.html

Large diffs are not rendered by default.

Binary file added grid_data_input_file_building_demo.xlsx
Binary file not shown.
221 changes: 190 additions & 31 deletions load_profile_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,36 +84,195 @@ def plot_profiles(individual_profiles: np.ndarray, aggregated_profile: list, noi



# if __name__ == "__main__":
# # Exemple d'utilisation
# hours = range(24)
# office_profile = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.5, 0.7, 0.8, 0.8, 0.8, 0.3, 0.3, 0.8, 0.8, 0.8, 0.7, 0.6, 0.2, 0.1, 0.1, 0.1]
# # Ajouter du bruit au profil agrégé
# noisy_office = add_noise_to_profile(office_profile, noise_std=0.05)
# # Générer les profils individuels pour 5 ordinateurs
# N = 10
# individual_profiles = generate_computer_profiles(N, noisy_office)
# # Afficher les profils
# #plot_profiles(individual_profiles, office_profile, noisy_office)

# HVAC_profile = [0.1, 0.1, 0.1, 0.5, 1, 1, 0.8, 0.7, 0.5, 0.3, 0.3, 0.3, 0.4, 0.7, 0.7, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
# noisy_HVAC = add_noise_to_profile(HVAC_profile, noise_std=0.05)

# EV_profile = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.9, 0.85, 0.8, 0.75, 0.7, 0.3, 0.25, 0.75, 0.7, 0.65, 0.6, 0.5, 0.2, 0.1, 0.1, 0.1]
# noisy_EV = add_noise_to_profile(EV_profile, noise_std=0.05)

# industrial_load_24h = [0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9]
# noisy_industrial_load_24h = add_noise_to_profile(industrial_load_24h, noise_std=0.05)

# industrial_load_12h = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0]
# noisy_industrial_load_12h = add_noise_to_profile(industrial_load_12h, noise_std=0.05)

# plt.figure()
# #plt.plot(hours,EV_profile,'g')
# #plt.plot(hours,noisy_HVAC,'r')
# #plt.plot(hours,noisy_office,'b')
# #plt.plot(hours,noisy_HVAC,'k')
# #plt.plot(hours,noisy_industrial_load_24h,'y')
# plt.plot(hours,noisy_industrial_load_12h,'c')
# plt.grid()
# plt.show()



import numpy as np
from datetime import datetime, timedelta, date as date_obj

def add_noise_to_profile(profile: list, noise_std: float = 0.05) -> np.ndarray:
"""
Ajoute du bruit gaussien à un profil de consommation.
"""
profile = np.array(profile)
noise = np.random.normal(0, noise_std, profile.shape)
noisy_profile = profile + noise
return np.clip(noisy_profile, 0, None)

def get_season(date: date_obj) -> str:
"""
Détermine la saison en fonction du mois de la date.
"""
month = date.month
if 3 <= month <= 5:
return 'spring'
elif 6 <= month <= 8:
return 'summer'
elif 9 <= month <= 11:
return 'autumn'
else:
return 'winter'

def get_day_type(date: date_obj, holidays: set) -> str:
"""
Détermine si la date est un jour de semaine, un week-end ou des vacances.
"""
if date in holidays:
return 'vacation'
elif date.weekday() >= 5:
return 'weekend'
else:
return 'workday'

def interpolate_profile(base_profile: list, time_step_min: int) -> np.ndarray:
"""
Interpole un profil de 24 heures à une résolution temporelle plus fine.
"""
hours = np.arange(24)
step_per_hour = 60 // time_step_min
x_new = np.linspace(0, 23, 24 * step_per_hour)
return np.interp(x_new, hours, base_profile)

def generate_load_profile(
num_days: int,
time_step_min: int = 60,
base_profiles: dict = None,
holidays: list = None,
noise_std: float = 0.05
) -> tuple:
"""
Génère un profil de charge électrique sur une période donnée.
Args:
num_days (int): Nombre de jours pour lesquels générer le profil.
time_step_min (int): Pas de temps en minutes (par défaut 60 minutes).
base_profiles (dict): Profils de base pour chaque saison et type de jour.
holidays (list): Liste des dates de vacances.
noise_std (float): Écart-type du bruit gaussien.
Returns:
tuple: (timestamps, load_values, timestamp_indices) où :
- timestamps est un tableau de datetime,
- load_values est un tableau de valeurs de charge,
- timestamp_indices est un tableau d'indices séquentiels.
"""
# Date de début fixée au 01/01/2018
start_date = date_obj(2018, 1, 1)
end_date = start_date + timedelta(days=num_days - 1)

dates = [start_date + timedelta(days=i) for i in range(num_days)]

timestamps = []
load_values = []
timestamp_indices = []
current_index = 0

if base_profiles is None:
# Profils de base par défaut (à personnaliser selon vos besoins)
office_profile = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.5, 0.7, 0.8, 0.8,
0.8, 0.3, 0.3, 0.8, 0.8, 0.8, 0.7, 0.6, 0.2, 0.1, 0.1, 0.1]
weekend_profile = [0.05] * 24
vacation_profile = [0.08] * 24

base_profiles = {
'winter': {'workday': office_profile, 'weekend': weekend_profile, 'vacation': vacation_profile},
'spring': {'workday': office_profile, 'weekend': weekend_profile, 'vacation': vacation_profile},
'summer': {'workday': office_profile, 'weekend': weekend_profile, 'vacation': vacation_profile},
'autumn': {'workday': office_profile, 'weekend': weekend_profile, 'vacation': vacation_profile}
}

holidays = set(holidays) if holidays else set()

for date in dates:
season = get_season(date)
day_type = get_day_type(date, holidays)

try:
base_profile = base_profiles[season][day_type]
except KeyError as e:
raise ValueError(f"Profil manquant pour {season} et {day_type}") from e

# Générer les timestamps pour la journée
steps_per_day = 24 * 60 // time_step_min
daily_timestamps = [
datetime(date.year, date.month, date.day, (i * time_step_min) // 60, (i * time_step_min) % 60)
for i in range(steps_per_day)
]

# Générer les valeurs de charge
if time_step_min == 60:
daily_load = add_noise_to_profile(base_profile, noise_std)
else:
interpolated = interpolate_profile(base_profile, time_step_min)
noise = np.random.normal(0, noise_std, interpolated.shape)
daily_load = np.clip(interpolated + noise, 0, None)

# Ajouter les timestamps, les valeurs de charge et les indices
timestamps.extend(daily_timestamps)
load_values.extend(daily_load)
timestamp_indices.extend(range(current_index, current_index + steps_per_day))
current_index += steps_per_day

return np.array(timestamps), np.array(load_values), np.array(timestamp_indices)

# Exemple d'utilisation
if __name__ == "__main__":
# Exemple d'utilisation
hours = range(24)
office_profile = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.5, 0.7, 0.8, 0.8, 0.8, 0.3, 0.3, 0.8, 0.8, 0.8, 0.7, 0.6, 0.2, 0.1, 0.1, 0.1]
# Ajouter du bruit au profil agrégé
noisy_office = add_noise_to_profile(office_profile, noise_std=0.05)
# Générer les profils individuels pour 5 ordinateurs
N = 10
individual_profiles = generate_computer_profiles(N, noisy_office)
# Afficher les profils
#plot_profiles(individual_profiles, office_profile, noisy_office)

HVAC_profile = [0.1, 0.1, 0.1, 0.5, 1, 1, 0.8, 0.7, 0.5, 0.3, 0.3, 0.3, 0.4, 0.7, 0.7, 0.5, 0.3, 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
noisy_HVAC = add_noise_to_profile(HVAC_profile, noise_std=0.05)

EV_profile = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.3, 0.9, 0.85, 0.8, 0.75, 0.7, 0.3, 0.25, 0.75, 0.7, 0.65, 0.6, 0.5, 0.2, 0.1, 0.1, 0.1]
noisy_EV = add_noise_to_profile(EV_profile, noise_std=0.05)

industrial_load_24h = [0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9]
noisy_industrial_load_24h = add_noise_to_profile(industrial_load_24h, noise_std=0.05)

industrial_load_12h = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0, 0, 0, 0]
noisy_industrial_load_12h = add_noise_to_profile(industrial_load_12h, noise_std=0.05)

plt.figure()
#plt.plot(hours,EV_profile,'g')
#plt.plot(hours,noisy_HVAC,'r')
#plt.plot(hours,noisy_office,'b')
#plt.plot(hours,noisy_HVAC,'k')
#plt.plot(hours,noisy_industrial_load_24h,'y')
plt.plot(hours,noisy_industrial_load_12h,'c')
plt.grid()
# Exemple de vacances
holidays = [date_obj(2018, 12, 25)] # Noël 2018

# Générer un profil pour 10 jours avec un pas de temps de 30 minutes
timestamps, load, indices = generate_load_profile(
num_days=1,
time_step_min=5,
holidays=holidays,
noise_std=0.05
)

# Affichage des 10 premiers éléments pour vérification
print("Timestamps:", timestamps[:10])
print("Load Values:", load[:10])
print("Timestamp Indices:", indices[:10])

# Affichage du profil généré
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 6))
plt.plot(indices, load, label='Profil de charge')
plt.xlabel('Temps')
plt.ylabel('Consommation normalisée')
plt.title('Profil de charge électrique sur 10 jours (pas de 30 minutes)')
plt.grid(True)
plt.legend()
plt.show()
4 changes: 2 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from worst_case_utilities import perform_comprehensive_sizing,validate_network_performance
from tqdm import tqdm

path = 'grid_data_input_file_building_demo.xlsx'
# path = 'grid_data_input_file_WIP_v1.xlsx'
#path = 'grid_data_input_file_building_demo.xlsx'
path = 'grid_data_input_file_WIP_v1.xlsx'
path_cable_catalogue = "cable_catalogue.xlsx"
path_converter_catalogue = "Converters_Library.xlsx"

Expand Down
2 changes: 1 addition & 1 deletion temp-plot.html

Large diffs are not rendered by default.

0 comments on commit 327947a

Please sign in to comment.