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

Fix duty cycle selection #153

Merged
merged 7 commits into from
Jun 6, 2024
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
55 changes: 35 additions & 20 deletions ramp/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
random_choice,
read_input_file,
within_peak_time_window,
range_within_window,
)
from ramp.post_process.post_process import Plot

Expand Down Expand Up @@ -699,6 +700,8 @@ def _add_appliance_instance(self, appliances):
f"You are trying to add an object of type {type(app)} as an appliance to the user {self.user_name}"
)
if app not in self.App_list:
if app.name == "":
app.name = f"appliance_{len(self.App_list) + 1}"
self.App_list.append(app)

def add_appliance(self, *args, **kwargs):
Expand Down Expand Up @@ -1865,35 +1868,47 @@ def rand_switch_on_window(self, rand_time: int):
if (
self.fixed_cycle > 0
): # evaluates if the app has some duty cycles to be considered
evaluate = np.round(np.mean(indexes)) if indexes.size > 0 else 0
indexes_low = indexes[0]
indexes_high = indexes[-1]
# selects the proper duty cycle
if (
self.cw11[0] <= evaluate < self.cw11[1]
or self.cw12[0] <= evaluate < self.cw12[1]
):
if range_within_window(
indexes_low, indexes_high, self.cw11
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FLomb - in the intermediate commit 510c164 the upper bound is included. In order to compare the two you can locally do git checkout 510c1647237365ada7e3c2f10995301cf46e1e1a and git checkout fix/duty_cycle_selection to come back to the tip of the branch

) or range_within_window(indexes_low, indexes_high, self.cw12):
self.current_duty_cycle_id = 1
duty_cycle_duration = len(self.random_cycle1)
elif (
self.cw21[0] <= evaluate < self.cw21[1]
or self.cw22[0] <= evaluate < self.cw22[1]
):
elif range_within_window(
indexes_low, indexes_high, self.cw21
) or range_within_window(indexes_low, indexes_high, self.cw22):
self.current_duty_cycle_id = 2
duty_cycle_duration = len(self.random_cycle2)
elif (
self.cw31[0] <= evaluate < self.cw31[1]
or self.cw32[0] <= evaluate < self.cw32[1]
):
elif range_within_window(
indexes_low, indexes_high, self.cw31
) or range_within_window(indexes_low, indexes_high, self.cw32):
self.current_duty_cycle_id = 3
duty_cycle_duration = len(self.random_cycle3)
else:
print(
f"The app {self.name} has duty cycle option on, however the switch on event fell outside the provided duty cycle windows"
# previously duty_cycle3 was always considered as default if neither duty_cycle1 nor duty_cycle2
# got selected. If the switch on window does not fall within any duty cycle we do not assign it
# to duty_cycle3 by default, rather we pick another switch on event and we notify the user we
# did so. That way, in case this warning is shown too often, it can indicate to the user there
# is some peculiar behavior for this appliance
warnings.warn(
f"The app {self.name} has duty cycle option on (with {self.fixed_cycle} cycle(s)). However, the switch on window [{switch_on}, {switch_on + len(indexes)}] fell outside the provided duty cycle windows: "
+ "cw11 "
+ str(self.cw11)
+ ", cw12 "
+ str(self.cw12)
+ ", cw21 "
+ str(self.cw21)
+ ", cw22 "
+ str(self.cw22)
+ ", cw31 "
+ str(self.cw31)
+ ", cw32 "
+ str(self.cw32)
+ ". Picking another random switch on event. You probably see this warning because your window of use is the same as the duty cycle window and the random variability of the windows of use is greater than zero. If you see this warning only once, no need to worry, this is inherent to stochasticity."
)
# TODO previously duty_cycle3 was always considered as default if the evaluate proxy did neither
# get selected by duty_cycle1 nor duty_cycle2, for default is kept but not silently anymore in
# order to see wheather this is an issue or not
self.current_duty_cycle_id = 3
duty_cycle_duration = len(self.random_cycle3)
return self.rand_switch_on_window(rand_time)

if (
indexes.size > duty_cycle_duration
Expand Down
14 changes: 14 additions & 0 deletions ramp/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,20 @@ def duty_cycle(var, t1, p1, t2, p2):
)


def range_within_window(range_low, range_high, window):
"""Compare a range with a window to see if there is an overlap

The two cases where there is no overlap between two windows are when the
range boundaries are both lower than the lowest window value or both
higher than the highest window value

"""
return not (
(range_low < window[0] and range_high < window[0])
or (range_low > window[1] and range_high > window[1])
)


def random_choice(var, t1, p1, t2, p2):
"""Chooses one of two duty cycles randomly

Expand Down
117 changes: 63 additions & 54 deletions ramp/example/input_file_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,45 +55,50 @@
func_cycle=60,
fixed="yes",
flat="yes",
name="indoor_bulb",
)
Ch_indoor_bulb.windows(window_1=[1200, 1440], window_2=[0, 0], random_var_w=0.1)

Ch_outdoor_bulb = Church.add_appliance(7, 26, 1, 150, 0.2, 60, "yes", flat="yes")
Ch_outdoor_bulb = Church.add_appliance(
7, 26, 1, 150, 0.2, 60, "yes", flat="yes", name="outdoor_bulb"
)
Ch_outdoor_bulb.windows([1200, 1440], [0, 0], 0.1)

Ch_speaker = Church.add_appliance(1, 100, 1, 150, 0.2, 60)
Ch_speaker = Church.add_appliance(1, 100, 1, 150, 0.2, 60, name="speaker")
Ch_speaker.windows([1200, 1350], [0, 0], 0.1)

# Public lighting
Pub_lights = Public_lighting.add_appliance(12, 40, 2, 310, 0.1, 300, "yes", flat="yes")
Pub_lights = Public_lighting.add_appliance(
12, 40, 2, 310, 0.1, 300, "yes", flat="yes", name="lights"
)
Pub_lights.windows([0, 336], [1110, 1440], 0.2)

Pub_lights_2 = Public_lighting.add_appliance(
25, 150, 2, 310, 0.1, 300, "yes", flat="yes"
25, 150, 2, 310, 0.1, 300, "yes", flat="yes", name="lights2"
)
Pub_lights_2.windows([0, 336], [1110, 1440], 0.2)


# High-Income
HI_indoor_bulb = HI.add_appliance(6, 7, 2, 120, 0.2, 10)
HI_indoor_bulb = HI.add_appliance(6, 7, 2, 120, 0.2, 10, name="indoor_bulb")
HI_indoor_bulb.windows([1170, 1440], [0, 30], 0.35)

HI_outdoor_bulb = HI.add_appliance(2, 13, 2, 600, 0.2, 10)
HI_outdoor_bulb = HI.add_appliance(2, 13, 2, 600, 0.2, 10, name="outdoor_bulb")
HI_outdoor_bulb.windows([0, 330], [1170, 1440], 0.35)

HI_TV = HI.add_appliance(2, 60, 3, 180, 0.1, 5)
HI_TV = HI.add_appliance(2, 60, 3, 180, 0.1, 5, name="TV")
HI_TV.windows([720, 900], [1170, 1440], 0.35, [0, 60])

HI_DVD = HI.add_appliance(1, 8, 3, 60, 0.1, 5)
HI_DVD = HI.add_appliance(1, 8, 3, 60, 0.1, 5, name="DVD")
HI_DVD.windows([720, 900], [1170, 1440], 0.35, [0, 60])

HI_Antenna = HI.add_appliance(1, 8, 3, 120, 0.1, 5)
HI_Antenna = HI.add_appliance(1, 8, 3, 120, 0.1, 5, name="antenna")
HI_Antenna.windows([720, 900], [1170, 1440], 0.35, [0, 60])

HI_Phone_charger = HI.add_appliance(5, 2, 2, 300, 0.2, 5)
HI_Phone_charger = HI.add_appliance(5, 2, 2, 300, 0.2, 5, name="phone_charger")
HI_Phone_charger.windows([1110, 1440], [0, 30], 0.35)

HI_Freezer = HI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3)
HI_Freezer = HI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3, name="freezer")
HI_Freezer.windows([0, 1440], [0, 0])
HI_Freezer.specific_cycle_1(200, 20, 5, 10)
HI_Freezer.specific_cycle_2(200, 15, 5, 15)
Expand All @@ -102,7 +107,7 @@
[480, 1200], [0, 0], [300, 479], [0, 0], [0, 299], [1201, 1440]
)

HI_Freezer2 = HI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3)
HI_Freezer2 = HI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3, name="freezer2")
HI_Freezer2.windows([0, 1440], [0, 0])
HI_Freezer2.specific_cycle_1(200, 20, 5, 10)
HI_Freezer2.specific_cycle_2(200, 15, 5, 15)
Expand All @@ -111,32 +116,32 @@
[480, 1200], [0, 0], [300, 479], [0, 0], [0, 299], [1201, 1440]
)

HI_Mixer = HI.add_appliance(1, 50, 3, 30, 0.1, 1, occasional_use=0.33)
HI_Mixer = HI.add_appliance(1, 50, 3, 30, 0.1, 1, occasional_use=0.33, name="mixer")
HI_Mixer.windows([420, 480], [660, 750], 0.35, [1140, 1200])

# Higher-Middle Income
HMI_indoor_bulb = HMI.add_appliance(5, 7, 2, 120, 0.2, 10)
HMI_indoor_bulb = HMI.add_appliance(5, 7, 2, 120, 0.2, 10, name="indoor_bulb")
HMI_indoor_bulb.windows([1170, 1440], [0, 30], 0.35)

HMI_outdoor_bulb = HMI.add_appliance(2, 13, 2, 600, 0.2, 10)
HMI_outdoor_bulb = HMI.add_appliance(2, 13, 2, 600, 0.2, 10, name="outdoor_bulb")
HMI_outdoor_bulb.windows([0, 330], [1170, 1440], 0.35)

HMI_TV = HMI.add_appliance(1, 60, 2, 120, 0.1, 5)
HMI_TV = HMI.add_appliance(1, 60, 2, 120, 0.1, 5, name="TV")
HMI_TV.windows([1170, 1440], [0, 60], 0.35)

HMI_DVD = HMI.add_appliance(1, 8, 2, 40, 0.1, 5)
HMI_DVD = HMI.add_appliance(1, 8, 2, 40, 0.1, 5, name="DVD")
HMI_DVD.windows([1170, 1440], [0, 60], 0.35)

HMI_Antenna = HMI.add_appliance(1, 8, 2, 80, 0.1, 5)
HMI_Antenna = HMI.add_appliance(1, 8, 2, 80, 0.1, 5, name="antenna")
HMI_Antenna.windows([1170, 1440], [0, 60], 0.35)

HMI_Radio = HMI.add_appliance(1, 36, 2, 60, 0.1, 5)
HMI_Radio = HMI.add_appliance(1, 36, 2, 60, 0.1, 5, name="radio")
HMI_Radio.windows([390, 450], [1140, 1260], 0.35)

HMI_Phone_charger = HMI.add_appliance(4, 2, 2, 300, 0.2, 5)
HMI_Phone_charger = HMI.add_appliance(4, 2, 2, 300, 0.2, 5, name="phone_charger")
HMI_Phone_charger.windows([1110, 1440], [0, 30], 0.35)

HMI_Freezer = HMI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3)
HMI_Freezer = HMI.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3, name="freezer")
HMI_Freezer.windows([0, 1440], [0, 0])
HMI_Freezer.specific_cycle_1(200, 20, 5, 10)
HMI_Freezer.specific_cycle_2(200, 15, 5, 15)
Expand All @@ -145,61 +150,61 @@
[480, 1200], [0, 0], [300, 479], [0, 0], [0, 299], [1201, 1440]
)

HMI_Mixer = HMI.add_appliance(1, 50, 3, 30, 0.1, 1, occasional_use=0.33)
HMI_Mixer = HMI.add_appliance(1, 50, 3, 30, 0.1, 1, occasional_use=0.33, name="mixer")
HMI_Mixer.windows([420, 450], [660, 750], 0.35, [1020, 1170])

# Lower-Midlle Income
LMI_indoor_bulb = LMI.add_appliance(3, 7, 2, 120, 0.2, 10)
LMI_indoor_bulb = LMI.add_appliance(3, 7, 2, 120, 0.2, 10, name="indoor_bulb")
LMI_indoor_bulb.windows([1170, 1440], [0, 30], 0.35)

LMI_outdoor_bulb = LMI.add_appliance(2, 13, 2, 600, 0.2, 10)
LMI_outdoor_bulb = LMI.add_appliance(2, 13, 2, 600, 0.2, 10, name="outdoor_bulb")
LMI_outdoor_bulb.windows([0, 330], [1170, 1440], 0.35)

LMI_TV = LMI.add_appliance(1, 60, 3, 90, 0.1, 5)
LMI_TV = LMI.add_appliance(1, 60, 3, 90, 0.1, 5, name="TV")
LMI_TV.windows([450, 660], [720, 840], 0.35, [1170, 1440])

LMI_DVD = LMI.add_appliance(1, 8, 3, 30, 0.1, 5)
LMI_DVD = LMI.add_appliance(1, 8, 3, 30, 0.1, 5, name="DVD")
LMI_DVD.windows([450, 660], [720, 840], 0.35, [1170, 1440])

LMI_Antenna = LMI.add_appliance(1, 8, 3, 60, 0.1, 5)
LMI_Antenna = LMI.add_appliance(1, 8, 3, 60, 0.1, 5, name="antenna")
LMI_Antenna.windows([450, 660], [720, 840], 0.35, [1170, 1440])

LMI_Phone_charger = LMI.add_appliance(4, 2, 1, 300, 0.2, 5)
LMI_Phone_charger = LMI.add_appliance(4, 2, 1, 300, 0.2, 5, name="phone_charger")
LMI_Phone_charger.windows([1020, 1440], [0, 0], 0.35)

LMI_Mixer = LMI.add_appliance(1, 50, 2, 30, 0.1, 1, occasional_use=0.33)
LMI_Mixer = LMI.add_appliance(1, 50, 2, 30, 0.1, 1, occasional_use=0.33, name="mixer")
LMI_Mixer.windows([660, 750], [1110, 1200], 0.35)

# Low Income
LI_indoor_bulb = LI.add_appliance(2, 7, 2, 120, 0.2, 10)
LI_indoor_bulb = LI.add_appliance(2, 7, 2, 120, 0.2, 10, name="indoor_bulb")
LI_indoor_bulb.windows([1170, 1440], [0, 30], 0.35)

LI_outdoor_bulb = LI.add_appliance(1, 13, 2, 600, 0.2, 10)
LI_outdoor_bulb = LI.add_appliance(1, 13, 2, 600, 0.2, 10, name="outdoor_bulb")
LI_outdoor_bulb.windows([0, 330], [1170, 1440], 0.35)

LI_TV = LI.add_appliance(1, 60, 3, 90, 0.1, 5)
LI_TV = LI.add_appliance(1, 60, 3, 90, 0.1, 5, name="TV")
LI_TV.windows([750, 840], [1170, 1440], 0.35, [0, 30])

LI_DVD = LI.add_appliance(1, 8, 3, 30, 0.1, 5)
LI_DVD = LI.add_appliance(1, 8, 3, 30, 0.1, 5, name="DVD")
LI_DVD.windows([750, 840], [1170, 1440], 0.35, [0, 30])

LI_Antenna = LI.add_appliance(1, 8, 3, 60, 0.1, 5)
LI_Antenna = LI.add_appliance(1, 8, 3, 60, 0.1, 5, name="antenna")
LI_Antenna.windows([750, 840], [1170, 1440], 0.35, [0, 30])

LI_Phone_charger = LI.add_appliance(2, 2, 1, 300, 0.2, 5)
LI_Phone_charger = LI.add_appliance(2, 2, 1, 300, 0.2, 5, name="phone_charger")
LI_Phone_charger.windows([1080, 1440], [0, 0], 0.35)

# Hospital
Ho_indoor_bulb = Hospital.add_appliance(12, 7, 2, 690, 0.2, 10)
Ho_indoor_bulb = Hospital.add_appliance(12, 7, 2, 690, 0.2, 10, name="indoor_bulb")
Ho_indoor_bulb.windows([480, 720], [870, 1440], 0.35)

Ho_outdoor_bulb = Hospital.add_appliance(1, 13, 2, 690, 0.2, 10)
Ho_outdoor_bulb = Hospital.add_appliance(1, 13, 2, 690, 0.2, 10, name="outdoor_bulb")
Ho_outdoor_bulb.windows([0, 330], [1050, 1440], 0.35)

Ho_Phone_charger = Hospital.add_appliance(8, 2, 2, 300, 0.2, 5)
Ho_Phone_charger = Hospital.add_appliance(8, 2, 2, 300, 0.2, 5, name="phone_charger")
Ho_Phone_charger.windows([480, 720], [900, 1440], 0.35)

Ho_Fridge = Hospital.add_appliance(1, 150, 1, 1440, 0, 30, "yes", 3)
Ho_Fridge = Hospital.add_appliance(1, 150, 1, 1440, 0, 30, "yes", 3, name="fridge")
Ho_Fridge.windows([0, 1440], [0, 0])
Ho_Fridge.specific_cycle_1(150, 20, 5, 10)
Ho_Fridge.specific_cycle_2(150, 15, 5, 15)
Expand All @@ -208,47 +213,49 @@
[580, 1200], [0, 0], [420, 579], [0, 0], [0, 419], [1201, 1440]
)

Ho_Fridge2 = Hospital.add_appliance(1, 150, 1, 1440, 0, 30, "yes", 3)
Ho_Fridge2 = Hospital.add_appliance(1, 150, 1, 1440, 0, 30, "yes", 3, name="fridge2")
Ho_Fridge2.windows([0, 1440], [0, 0])
Ho_Fridge2.specific_cycle_1(150, 20, 5, 10)
Ho_Fridge2.specific_cycle_2(150, 15, 5, 15)
Ho_Fridge2.specific_cycle_3(150, 10, 5, 20)
Ho_Fridge2.cycle_behaviour(
[580, 1200], [0, 0], [420, 579], [0, 0], [0, 299], [1201, 1440]
[580, 1200], [0, 0], [420, 579], [0, 0], [0, 419], [1201, 1440]
)

Ho_Fridge3 = Hospital.add_appliance(1, 150, 1, 1440, 0.1, 30, "yes", 3)
Ho_Fridge3 = Hospital.add_appliance(1, 150, 1, 1440, 0.1, 30, "yes", 3, name="fridge3")
Ho_Fridge3.windows([0, 1440], [0, 0])
Ho_Fridge3.specific_cycle_1(150, 20, 5, 10)
Ho_Fridge3.specific_cycle_2(150, 15, 5, 15)
Ho_Fridge3.specific_cycle_3(150, 10, 5, 20)
Ho_Fridge3.cycle_behaviour(
[580, 1200], [0, 0], [420, 479], [0, 0], [0, 419], [1201, 1440]
[580, 1200], [0, 0], [420, 579], [0, 0], [0, 419], [1201, 1440]
)

Ho_PC = Hospital.add_appliance(2, 50, 2, 300, 0.1, 10)
Ho_PC = Hospital.add_appliance(2, 50, 2, 300, 0.1, 10, name="PC")
Ho_PC.windows([480, 720], [1050, 1440], 0.35)

Ho_Mixer = Hospital.add_appliance(1, 50, 2, 60, 0.1, 1, occasional_use=0.33)
Ho_Mixer = Hospital.add_appliance(
1, 50, 2, 60, 0.1, 1, occasional_use=0.33, name="mixer"
)
Ho_Mixer.windows([480, 720], [1050, 1440], 0.35)

# School
S_indoor_bulb = School.add_appliance(8, 7, 1, 60, 0.2, 10)
S_indoor_bulb = School.add_appliance(8, 7, 1, 60, 0.2, 10, name="indoor_bulb")
S_indoor_bulb.windows([1020, 1080], [0, 0], 0.35)

S_outdoor_bulb = School.add_appliance(6, 13, 1, 60, 0.2, 10)
S_outdoor_bulb = School.add_appliance(6, 13, 1, 60, 0.2, 10, name="outdoor_bulb")
S_outdoor_bulb.windows([1020, 1080], [0, 0], 0.35)

S_Phone_charger = School.add_appliance(5, 2, 2, 180, 0.2, 5)
S_Phone_charger = School.add_appliance(5, 2, 2, 180, 0.2, 5, name="phone_charger")
S_Phone_charger.windows([510, 750], [810, 1080], 0.35)

S_PC = School.add_appliance(18, 50, 2, 210, 0.1, 10)
S_PC = School.add_appliance(18, 50, 2, 210, 0.1, 10, name="PC")
S_PC.windows([510, 750], [810, 1080], 0.35)

S_Printer = School.add_appliance(1, 20, 2, 30, 0.1, 5)
S_Printer = School.add_appliance(1, 20, 2, 30, 0.1, 5, name="printer")
S_Printer.windows([510, 750], [810, 1080], 0.35)

S_Freezer = School.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3)
S_Freezer = School.add_appliance(1, 200, 1, 1440, 0, 30, "yes", 3, name="freezer")
S_Freezer.windows([0, 1440])
S_Freezer.specific_cycle_1(200, 20, 5, 10)
S_Freezer.specific_cycle_2(200, 15, 5, 15)
Expand All @@ -257,13 +264,15 @@
[580, 1200], [0, 0], [510, 579], [0, 0], [0, 509], [1201, 1440]
)

S_TV = School.add_appliance(1, 60, 2, 120, 0.1, 5, occasional_use=0.5)
S_TV = School.add_appliance(1, 60, 2, 120, 0.1, 5, occasional_use=0.5, name="TV")
S_TV.windows([510, 750], [810, 1080], 0.35)

S_DVD = School.add_appliance(1, 8, 2, 120, 0.1, 5, occasional_use=0.5)
S_DVD = School.add_appliance(1, 8, 2, 120, 0.1, 5, occasional_use=0.5, name="DVD")
S_DVD.windows([510, 750], [810, 1080], 0.35)

S_Stereo = School.add_appliance(1, 150, 2, 90, 0.1, 5, occasional_use=0.33)
S_Stereo = School.add_appliance(
1, 150, 2, 90, 0.1, 5, occasional_use=0.33, name="stereo"
)
S_Stereo.windows([510, 750], [810, 1080], 0.35)

if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions ramp/example/input_file_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
time_fraction_random_variability=0.1,
func_cycle=3,
thermal_p_var=0.2,
name="shower",
)
HH_shower.windows(window_1=[390, 540], window_2=[1080, 1200], random_var_w=0.2)

Expand Down
Loading