Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue281 slp creation #282

Merged
merged 4 commits into from
Jul 13, 2020
Merged
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
29 changes: 16 additions & 13 deletions pycity_base/classes/demand/domestic_hot_water.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,28 @@ def __init__(self,
filename = os.path.join(src_path, 'inputs', 'standard_load_profile', 'dhw_annex42.csv')
DomesticHotWater.a42 = np.loadtxt(filename,
skiprows=1, delimiter="\t")
# Adjust time resolution. Annex 42 data is sampled at 900 sec.
if timeDis != 900:
res = []
changeResol = cr.changeResolution
for i in range(3):
res.append(changeResol(DomesticHotWater.a42[:,i],
oldResolution=900,
newResolution=timeDis,
method="mean"))
DomesticHotWater.a42 = np.transpose(np.array(res))
DomesticHotWater.loaded_profile = True

# Adjust time resolution. Annex 42 data is sampled at 900 sec.
if timeDis != 900:
res = []
changeResol = cr.changeResolution
for i in range(3):
res.append(changeResol(DomesticHotWater.a42[:, i],
oldResolution=900,
newResolution=timeDis,
method="mean"))
a42 = np.transpose(np.array(res))
else:
a42 = DomesticHotWater.a42

# Compute tap water profile (based on average daily consumption)
if daily_consumption <= 150:
tapProfile = self.a42[:, 0] * daily_consumption / 100
tapProfile = a42[:,0] * daily_consumption / 100
elif daily_consumption <= 250 and daily_consumption > 150:
tapProfile = self.a42[:, 1] * daily_consumption / 200
tapProfile = a42[:,1] * daily_consumption / 200
elif daily_consumption > 250:
tapProfile = self.a42[:, 2] * daily_consumption / 300
tapProfile = a42[:,2] * daily_consumption / 300

# Compute equivalent heat demand in Watt
cWater = 4180 # J/kgK
Expand Down
3 changes: 1 addition & 2 deletions pycity_base/classes/demand/electrical_demand.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ def __init__(self,
filename = os.path.join(src_path, 'inputs',
'standard_load_profile',
'slp_electrical.xlsx')
ElectricalDemand.slp = slp_el.load(filename,
time_discretization=environment.timer.time_discretization)
ElectricalDemand.slp = slp_el.load(filename)
ElectricalDemand.loaded_slp = True

loadcurve = slp_el.get_demand(annual_demand,
Expand Down
3 changes: 1 addition & 2 deletions pycity_base/classes/demand/space_heating.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@ def __init__(self, environment, method=0, loadcurve=[],
f_hour = os.path.join(folder, 'slp_thermal_hourly_factors.xlsx')
f_prof = os.path.join(folder, 'slp_thermal_profile_factors.xlsx')
f_week = os.path.join(folder, 'slp_thermal_week_day_factors.xlsx')
SpaceHeating.slp_hour = slp_th.load_hourly_factors(f_hour,
timeDis)
SpaceHeating.slp_hour = slp_th.load_hourly_factors(f_hour)
SpaceHeating.slp_prof = slp_th.load_profile_factors(f_prof)
SpaceHeating.slp_week = slp_th.load_week_day_factors(f_week)

Expand Down
17 changes: 9 additions & 8 deletions pycity_base/functions/slp_electrical.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import pycity_base.functions.change_resolution as cr


def load(filename, time_discretization=900):
def load(filename):
# Open the workbook and get the sheet with all profiles
book = xlrd.open_workbook(filename)
sheet = book.sheet_by_name("Profiles")
Expand All @@ -27,13 +27,6 @@ def load(filename, time_discretization=900):
# Get the corresponding values
values = [sheet.cell_value(r, c) for r in range(2, sheet.nrows)]

# Adjust sampling time
if time_discretization != 900:
changeResol = cr.changeResolution
values = changeResol(values, 900, time_discretization, "sum")
# Use scaling method "sum", because the values are given
# in kWh for each 15 minutes

# Store the results
profiles[key] = np.array(values)

Expand All @@ -43,6 +36,14 @@ def load(filename, time_discretization=900):

def get_demand(annual_demand, profile, time_discretization):
scaling = 4000 / 1000000 * annual_demand / time_discretization * 900

# Adjust sampling time
if time_discretization != 900:
changeResol = cr.changeResolution
profile = changeResol(profile, 900, time_discretization, "sum")
# Use scaling method "sum", because the values are given
# in kWh for each 15 minutes

return scaling * profile


Expand Down
21 changes: 13 additions & 8 deletions pycity_base/functions/slp_thermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def calculate(temperature, initial_day, profiles, weekly_factors,
Parameters
----------
temperature : array-like
Full year temperature profile with hourly discretization.
Full year temperature profile.
initial_day : integer
- 0 : Monday
- 1 : Tuesday
Expand Down Expand Up @@ -67,9 +67,19 @@ def calculate(temperature, initial_day, profiles, weekly_factors,
Total yearly demand in kWh
"""
# Compute average daily temperatures. [1], page 17, section 3.5.2
timesteps_day = len(hourly_factors[list(hourly_factors.keys())[0]])
timesteps_day, r = divmod(len(temperature), 365)
if r != 0:
raise ValueError("`temperature` array could not be split into days")

t_average = _average_temperature(temperature, timesteps_day)

time_discretization = 86400 / timesteps_day
if time_discretization != 3600:
hourly_factors = {
k: cr.changeResolution(values, 3600, time_discretization, "sum")
for k, values in hourly_factors.items()
}

# Compute h-factors. [1], page 38
theta_0 = 40 # [1], page 38
A = profiles[0]
Expand All @@ -90,7 +100,6 @@ def calculate(temperature, initial_day, profiles, weekly_factors,
result = _daily_profiles(t_average, KW, h, F, hourly_factors, initial_day)

# Transform to W instead of kWh
time_discretization = 86400 / timesteps_day
return result * 1000 * 3600 / time_discretization


Expand Down Expand Up @@ -183,8 +192,7 @@ def load_week_day_factors(filename):
# Return results
return profiles


def load_hourly_factors(filename, time_discretization=3600):
def load_hourly_factors(filename):
"""
"""
# Initialization
Expand All @@ -202,9 +210,6 @@ def load_hourly_factors(filename, time_discretization=3600):
# Read values
values = [sheet.cell_value(d*11+t+1, hour+1)
for hour in range(24)]
if time_discretization != 3600:
values = cr.changeResolution(values, 3600,
time_discretization, "sum")
temp_factors[d, temperature_range[t]] = np.array(values)

# Store values
Expand Down
5 changes: 3 additions & 2 deletions pycity_base/test/pycity_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import pycity_base.classes.city_district as citydist


@pytest.fixture(scope='module')
def create_environment(timestep=900):
@pytest.fixture(scope='module', params=[900])
def create_environment(request):
"""
Fixture to create environment object for PyCity (scope='module')

Expand All @@ -32,6 +32,7 @@ def create_environment(timestep=900):
-------
create_environment : environment object
"""
timestep = request.param
timer = pycity_base.classes.timer.Timer(time_discretization=timestep,
timesteps_total=365 * 24 * 4,
initial_day=1)
Expand Down
65 changes: 65 additions & 0 deletions pycity_base/test/test_dhw.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,68 @@ def test_method3(self, create_environment):
method=1,
daily_consumption=daily_consumption,
supply_temperature=supply_temperature)

def test_multiple_resolutions(self, create_environment, create_occupancy):

timer = create_environment.timer
occupancy_profile = create_occupancy.occupancy
tFlow = 60
supplyTemperature = 25
dailyConsumption = 50

# Generate electrical demand object
dhw_1 = dhw.DomesticHotWater(create_environment,
t_flow=tFlow,
thermal=True,
method=1,
daily_consumption=dailyConsumption,
supply_temperature=supplyTemperature)

timer.time_discretization = int(timer.time_discretization/2)
dhw_2 = dhw.DomesticHotWater(create_environment,
t_flow=tFlow,
thermal=True,
method=1,
daily_consumption=dailyConsumption,
supply_temperature=supplyTemperature)

# Thermal power in W (per 15 minute timestep)
load_1 = dhw_1.get_power(currentValues=False, returnTemperature=False)
# Thermal power in W (per 7.5 minute timestep)
load_2 = dhw_2.get_power(currentValues=False, returnTemperature=False)

assert len(load_2) == len(load_1) * 2

assert np.allclose(load_2[::2], load_1)
assert np.isclose(np.mean(load_2), np.mean(load_1))


def test_multiple_resolutions_stochastical(self, create_environment, create_occupancy):
timer = create_environment.timer
occupancy_profile = create_occupancy.occupancy

# Generate electrical demand object
dhw_1 = dhw.DomesticHotWater(create_environment,
t_flow=60,
thermal=True,
method=2,
supply_temperature=20,
occupancy=occupancy_profile)

timer.time_discretization = int(timer.time_discretization / 2)

dhw_2 = dhw.DomesticHotWater(create_environment,
t_flow=60,
thermal=True,
method=2,
supply_temperature=20,
occupancy=occupancy_profile)

# Thermal power in W (per 15 minute timestep)
load_1 = dhw_1.get_power(currentValues=False, returnTemperature=False)
# Thermal power in W (per 7.5 minute timestep)
load_2 = dhw_2.get_power(currentValues=False, returnTemperature=False)

assert len(load_2) == len(load_1) * 2

assert np.isclose(np.mean(load_2), np.mean(load_1), rtol=0.1)
22 changes: 22 additions & 0 deletions pycity_base/test/test_electrical_demand.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,25 @@ def test_method3(self, create_environment, create_occupancy):
print(el_en_demand_value)

assert ann_demand - el_en_demand_value <= 0.001 * ann_demand

def test_multiple_resolutions(self, create_environment):
timer = create_environment.timer
# Generate electrical demand object
el_demand_object_1 = ed.ElectricalDemand(create_environment,
method=1,
profile_type="H0",
annual_demand=3000)

timer.time_discretization = int(timer.time_discretization/2)
el_demand_object_2 = ed.ElectricalDemand(create_environment,
method=1,
profile_type="H0",
annual_demand=3000)

# Get space heating load curve (in W) per timestep
load_1 = el_demand_object_1.get_power(currentValues=False)
load_2 = el_demand_object_2.get_power(currentValues=False)

assert len(load_2) == len(load_1) * 2
rescaled_load_2 = np.mean(load_2.reshape(-1, 2), axis=1)
assert np.allclose(rescaled_load_2, load_1)
28 changes: 28 additions & 0 deletions pycity_base/test/test_spaceheating.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pycity_base.classes.demand.space_heating as sh
from pycity_base.test.pycity_fixtures import create_environment

create_environment2 = create_environment

class TestSpaceHeating(object):

Expand Down Expand Up @@ -61,3 +62,30 @@ def test_method3(self, create_environment): # Modelica profile

# Check if sum of energy demand values is (almost) equal to input
assert abs(np.sum(th_energy_demand_curve) - 150 * 100) <= 0.001 * 150 * 100


@pytest.mark.parametrize("create_environment2", [(3600)], indirect=["create_environment2"])
def test_multiple_resolutions(self, create_environment, create_environment2):

# Generate space heating object
assert create_environment2.timer.time_discretization == 3600
assert create_environment.timer.time_discretization == 900
sh_1 = sh.SpaceHeating(create_environment2,
method=1,
living_area=100,
specific_demand=150)

sh_2 = sh.SpaceHeating(create_environment,
method=1,
living_area=100,
specific_demand=150)

# Get space heating load curve (in W) per timestep
load_1 = sh_1.get_power(currentValues=False)
load_2 = sh_2.get_power(currentValues=False)

assert len(load_1) == 24*365
assert len(load_2) == 24*4*365

rescaled_load_2 = np.mean(load_2.reshape(-1, 4), axis=1)
assert np.isclose(rescaled_load_2.sum(), load_1.sum())