"""Functions related to load profiles
"""
import numpy as np
[docs]class LoadProfileStock(object):
"""Collection of load shapes in a list
Arguments
----------
name : string
Load profile stock name
"""
def __init__(self, name):
self.name = name
self.load_profiles = {}
self.dict_tuple_keys = {}
self.stock_enduses = set([])
[docs] def add_lp(
self,
unique_identifier,
technologies,
enduses,
shape_yd,
shape_y_dh,
model_yeardays,
sectors,
shape_yh=False
):
"""Add load profile to stock
Arguments
---------
unique_identifier : str
Name (unique identifier)
technologies : list
Technologies for which the profile applies
enduses : list
Enduses for which the profile applies
shape_y_dh : array
shape_yh : array
Shape yh (from year to hour)
sectors : list, default=False
Sectors for which the profile applies
"""
self.load_profiles[unique_identifier] = LoadProfile(
enduses,
unique_identifier,
shape_yh,
shape_yd,
shape_y_dh,
model_yeardays)
# Generate lookup dictionary with triple key
self.dict_tuple_keys = generate_key_lu_dict(
self.dict_tuple_keys,
unique_identifier,
enduses,
sectors,
technologies)
# Update enduses in stock
self.stock_enduses = get_stock_enduses(self.load_profiles)
[docs] def get_lp(self, enduse, sector, technology, shape):
"""Get shape for a certain technology, enduse and sector
Arguments
----------
enduse : str
Enduse
sector : str
Sector
technology : str
technology
shape : str
Type of shape which is to be read out from 'load_profiles'
Return
------
Load profile attribute
"""
# Get key from lookup dict
position_in_dict = self.dict_tuple_keys[(enduse, sector, technology)]
# Get correct object
load_profile_obj = self.load_profiles[position_in_dict]
return getattr(load_profile_obj, shape)
[docs]def generate_key_lu_dict(
dict_tuple_keys,
unique_identifier,
enduses,
sectors,
technologies
):
"""Generate look_up keys to position in 'load_profiles'
Arguments
----------
dict_tuple_keys : dict
Already existing lu keys
unique_identifier : string
Unique identifier of load shape object
enduses : list
List with enduses
sectors : list
List with sectors
technologies : list
List with technologies
Returns
-------
dict_tuple_keys : str
Lookup position in dict
"""
for enduse in enduses:
for sector in sectors:
for technology in technologies:
dict_tuple_keys[(enduse, sector, technology)] = unique_identifier
return dict_tuple_keys
[docs]def get_stock_enduses(load_profiles):
"""Update the list of the object with all
enduses for which load profies are provided
Arguments
---------
load_profiles : dict
All load profiles of load profile stock
Returns
------
all_enduses : list
All enduses in stock
"""
all_enduses = set([])
for profile_obj in load_profiles.values():
for enduse in profile_obj.enduses:
all_enduses.add(enduse)
return list(all_enduses)
[docs]class LoadProfile(object):
"""Load profile container to store differengt shapes
Arguments
----------
enduses : list
Enduses assigned to load profile
unique_identifier : string
Unique identifer for LoadProfile object
shape_y_dh : array
Shape of every day in a year (sum = 365)
shape_yh : array
Shape yh (from year to hour)
Standard value is average daily amount
shape_peak_dh : array
Shape (dh), shape of a day for every hour
"""
def __init__(
self,
enduses,
unique_identifier,
shape_yh,
shape_yd,
shape_y_dh,
model_yeardays
):
"""Constructor
"""
self.unique_identifier = unique_identifier
self.enduses = enduses
if isinstance(shape_yh, bool):
self.shape_yh = calc_yh(
shape_yd,
shape_y_dh,
model_yeardays)
else:
self.shape_yh = shape_yh
[docs]def abs_to_rel(absolute_array):
"""Convert absolute numbers in an array to relative
Arguments
----------
absolute_array : array
Contains absolute numbers in it
Returns
-------
relative_array : array
Contains relative numbers
Note
----
- If the total sum is zero, return an array with zeros
"""
sum_array = float(np.sum(absolute_array))
if sum_array != 0.0:
relative_array = absolute_array / sum_array
relative_array[np.isnan(relative_array)] = 0
return relative_array
else:
return absolute_array
[docs]def calk_peak_h_dh(fuel_peak_dh):
"""Ger peak hour in peak day
Arguments
----------
fuel_peak_dh : array
Fuel of peak day for every fueltype
Return
------
peak_fueltype_h : array
Fuel for maximum hour in peak day per fueltype
"""
# Get maximum value per row (maximum fuel hour per fueltype)
peak_fueltype_h = np.max(fuel_peak_dh, axis=1)
return peak_fueltype_h
[docs]def calk_peak_h_dh_single_fueltype(fuel_peak_dh):
"""Ger peak hour in peak day
Arguments
----------
fuel_peak_dh : array
Fuel of peak day for every fueltype
Return
------
peak_fueltype_h : array
Fuel for maximum hour in peak day per fueltype
"""
# Get maximum value per row (maximum fuel hour per fueltype)
peak_fueltype_h = np.max(fuel_peak_dh, axis=0)
return peak_fueltype_h
[docs]def calc_av_lp(demand_yh, seasons, model_yeardays_daytype):
"""Calculate average load profile for daytype and season
for fuel of a fueltype
Result
------
demand_yh : array
Energy demand for every day of a single fueltype
seasons: dict
Seasons and their yeardays
model_yeardays_daytype : dict
Yearday type of every year
av_loadprofiles : dict
season, daytype
Returns
-------
av_season_daytypes : dict
Averaged lp
season_daytypes : dict
Not averaged lp
"""
season_daytypes = {
'spring': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'summer': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'autumn': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'winter': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")}}
av_season_daytypes = {
'spring': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'summer': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'autumn': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")},
'winter': {
'workday': np.zeros((0, 24), dtype="float"),
'holiday': np.zeros((0, 24), dtype="float")}}
for yearday, daytype_yearday in enumerate(model_yeardays_daytype):
# Season
if yearday in seasons['spring']:
season = 'spring'
elif yearday in seasons['summer']:
season = 'summer'
elif yearday in seasons['autumn']:
season = 'autumn'
else:
season = 'winter'
# Add data as row to array
new_data_dh = demand_yh[yearday]
existing_array = season_daytypes[season][daytype_yearday]
# Add to dict
season_daytypes[season][daytype_yearday] = np.vstack([existing_array, new_data_dh])
# -----------------------------
# Calculate average of all dict
# -----------------------------
# Calculate average over every hour in a day
for season, daytypes_data in season_daytypes.items():
for daytype, daytpe_data in daytypes_data.items():
av_season_daytypes[season][daytype] = np.average(daytpe_data, axis=0)
return av_season_daytypes, season_daytypes
[docs]def calc_yh(shape_yd, shape_y_dh, model_yeardays):
"""Calculate the shape based on yh and y_dh shape
Arguments
---------
shape_yd : array
Shape with fuel amount for every day (365)
shape_y_dh : array
Shape for every day (365, 24), total sum = 365
model_yeardays : array
Modelled yeardays
Returns
-------
shape_yh : array
Shape for every hour in a year (total sum == 1)
"""
shape_yh = shape_yd[:, np.newaxis] * shape_y_dh[model_yeardays]
return shape_yh