Skip to content

Commit

Permalink
Merge pull request #153 from RAMP-project/fix/duty_cycle_selection
Browse files Browse the repository at this point in the history
Fix duty cycle selection
  • Loading branch information
Bachibouzouk authored Jun 6, 2024
2 parents 0922874 + 2ea6532 commit fce9fc9
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 87 deletions.
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
) 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

0 comments on commit fce9fc9

Please sign in to comment.