def preventBessOverload(currentInput: DataMessage, previousOutput: ResultsMessage, newOutput: ResultsMessage, minBuyingPrice, maxBuyingPrice, MIN_ENERGY_FOR_BATTERY): Pbess = currentInput.current_load - currentInput.solar_production if Pbess > BATTERY_MAX_OUTPUT_POWER: if previousOutput.load_three == True: newOutput.load_three = False if currentInput.current_load * 0.7 > BATTERY_MAX_OUTPUT_POWER: newOutput.load_two = False # Case when battery is empty elif currentInput.bessSOC == 0: if currentInput.grid_status == False: turn_off_loads(newOutput) newOutput.power_reference = 0.0 availablePower = currentInput.solar_production * (-1.0) if currentInput.solar_production >= currentInput.current_load * 0.2: newOutput.load_one = True availablePower = currentInput.solar_production - currentInput.current_load * 0.2 if currentInput.solar_production >= currentInput.current_load * 0.7: newOutput.load_two = True availablePower = currentInput.solar_production - currentInput.current_load * 0.7 newOutput.power_reference = availablePower * (-1.0) else: turn_off_loads(newOutput) newOutput.power_reference = 0.0 availablePower = currentInput.solar_production if currentInput.solar_production >= currentInput.current_load * 0.2: newOutput.load_one = True availablePower = currentInput.solar_production - currentInput.current_load * 0.2 if currentInput.solar_production >= currentInput.current_load * 0.7: newOutput.load_two = True availablePower = currentInput.solar_production - currentInput.current_load * 0.7 if currentInput.solar_production >= currentInput.current_load: newOutput.load_three = True availablePower = currentInput.solar_production - currentInput.current_load newOutput.power_reference = availablePower * (-1.0) # Case when battery is full elif currentInput.bessSOC == 1: newOutput.pv_mode = PVMode.OFF handleRegularScenarios(currentInput, previousOutput, newOutput, minBuyingPrice, maxBuyingPrice, MIN_ENERGY_FOR_BATTERY) if newOutput.power_reference < 0.0: newOutput.power_reference = 0.0
def worker(msg: DataMessage) -> ResultsMessage: """TODO: This function should be implemented by contestants.""" # Details about DataMessage and ResultsMessage objects can be found in /utils/utils.py if len(lastPowerDown) == 0: lastPowerDown.append(-1000) MIN_ENERGY_FOR_BATTERY = MINIMAL_BATTERY_POWER_FOR_LOAD_1 if msg.grid_status == False: lastPowerDown[0] = msg.id else: if msg.id - lastPowerDown[0] < PERIOD_WITHOUT_POWER_DOWN: MIN_ENERGY_FOR_BATTERY = 0.11 if len(minBuyingCosts) == 0: minBuyingCosts.append(msg.buying_price) maxBuyingCosts.append(msg.buying_price) sellingCosts.append(msg.selling_price) else: if minBuyingCosts[0] > msg.buying_price: minBuyingCosts[0] = msg.buying_price if maxBuyingCosts[0] < msg.buying_price: maxBuyingCosts[0] = msg.buying_price if sellingCosts[0] < msg.selling_price: sellingCosts[0] = msg.selling_price # Save received status from framework saveReceivedStatus(msg, listOfReceivedStatuses) # set default output message witch should be changed batteryUsing = 0.0 newOutput = ResultsMessage(msg, True, True, True, batteryUsing, PVMode.ON) shutdownLoadIfPowerIsExpensive(listOfReceivedStatuses[0], newOutput) defaultOutputStatus = ResultsMessage( msg, True, True, True, 0.0, PVMode.ON) if len(listOfSentStatuses) == 0 else listOfSentStatuses[0] # Prevent battery overload if msg.bessOverload: preventBessOverload(listOfReceivedStatuses[0], defaultOutputStatus, newOutput, minBuyingCosts[0], maxBuyingCosts[0], MIN_ENERGY_FOR_BATTERY) else: handleRegularScenarios(listOfReceivedStatuses[0], defaultOutputStatus, newOutput, minBuyingCosts[0], maxBuyingCosts[0], MIN_ENERGY_FOR_BATTERY) saveSentStatus(newOutput, listOfSentStatuses) if msg.id - lastPowerDown[ 0] > PERIOD_WITHOUT_POWER_DOWN and msg.bessSOC * 10.0 < MINIMAL_BATTERY_POWER_FOR_LOAD_1: newOutput.power_reference = -6.0 return newOutput
def get_physics_metrics(d: DataMessage, r: ResultsMessage, spent_time=0) \ -> Tuple[float, float, float, float, float, float, float, bool, float]: global overload_cnt global penal_l1_cnt global penal_l2_cnt BESS_MAX_POWER = 5 BESS_CAPACITY = 20 penal = 0.0 if r.power_reference > BESS_MAX_POWER: r.power_reference = BESS_MAX_POWER elif r.power_reference < -BESS_MAX_POWER: r.power_reference = -BESS_MAX_POWER if not r.load_one: if penal_l1_cnt == 0: penal += PENAL_L1_INIT + PENAL_L1_CONT penal_l1_cnt += 1 else: penal += PENAL_L1_CONT else: penal_l1_cnt = 0 if not r.load_two: if penal_l2_cnt == 0: penal += PENAL_L2_INIT + PENAL_L2_CONT penal_l2_cnt += 1 else: penal += PENAL_L2_CONT else: penal_l2_cnt = 0 if not r.load_three: penal += PENAL_L3_CONT if d.grid_status: if (d.bessSOC == 0 and r.power_reference > 0) \ or (d.bessSOC == 1 and r.power_reference < 0): r.power_reference = 0 r_load = real_load(int(r.load_one), int(r.load_two), int(r.load_three), d.current_load) mg = main_grid(True, r_load, r.power_reference, d.solar_production, r.pv_mode) # we sell if mg < 0: bess_sell = abs(mg) * d.selling_price / CFG.sampleRate consumption = 0.0 else: consumption = mg * d.buying_price / CFG.sampleRate bess_sell = 0 current_power = r.power_reference soc_bess = d.bessSOC - r.power_reference / (CFG.sampleRate * BESS_CAPACITY) overload = False elif not d.grid_status: r_load = real_load(int(r.load_one), int(r.load_two), int(r.load_three), d.current_load) current_power = main_grid(False, r_load, r.power_reference, d.solar_production, r.pv_mode) soc_bess = d.bessSOC - current_power / (CFG.sampleRate * BESS_CAPACITY) if abs(current_power) > BESS_MAX_POWER or (soc_bess >= 1 and current_power < 0) \ or (soc_bess <= 0 and current_power > 0): overload = True overload_cnt += 1 else: overload = False overload_cnt = 0 if overload_cnt > 1: penal = PENAL_L1_INIT + PENAL_L1_CONT + PENAL_L2_INIT + PENAL_L2_CONT + PENAL_L3_CONT current_power = 0 r.load_one = False r.load_two = False r.load_three = False r.pv_mode = PVMode.OFF overload = False overload_cnt = 0 soc_bess = d.bessSOC r_load = 0 consumption = 0 mg = 0 bess_sell = 0 if 0 > soc_bess: soc_bess = 0 if soc_bess > 1: soc_bess = 1 TARGET_1MS_PRICE = 100 # targeted daily price for 1ms avg spent time performance_mark = (spent_time * 1000) * (24 / (TARGET_1MS_PRICE * CFG.sampleRate)) em = energy_mark(consumption, bess_sell) pv_power = d.solar_production if r.pv_mode == PVMode.ON else 0 return em, performance_mark, mg, penal, r_load, pv_power, soc_bess, \ overload, current_power
def handleRegularScenarios(currentInput:DataMessage, previousOutput:ResultsMessage, newOutput:ResultsMessage, minBuyingPrice, maxBuyingPrice, MIN_ENERGY_FOR_BATTERY): if currentInput.grid_status == False: if currentInput.bessSOC * 10 + currentInput.solar_production <= MINIMAL_BATTERY_POWER_FOR_LOAD_1: newOutput.load_two = False newOutput.load_three = False elif currentInput.bessSOC * 10 + currentInput.solar_production <= MINIMAL_BATTERY_POWER_FOR_LOAD_1_AND_LOAD_2: newOutput.load_three = False if currentInput.solar_production + BATTERY_MAX_OUTPUT_POWER < currentInput.current_load: newOutput.load_three = False if currentInput.solar_production + BATTERY_MAX_OUTPUT_POWER < currentInput.current_load * 0.7: newOutput.load_two = False if currentInput.solar_production + BATTERY_MAX_OUTPUT_POWER < currentInput.current_load * 0.2: newOutput.load_one = False else: extraEnergy = currentInput.solar_production - predictFutureConsumption(newOutput.load_two, newOutput.load_three, currentInput.current_load) if extraEnergy > 0: if currentInput.bessSOC * 10.0 <= 9.9: # Charge battery newOutput.power_reference = extraEnergy * (-1.0) elif currentInput.selling_price > 0: newOutput.power_reference = 0.0 else: newOutput.power_reference = 0.0 if newOutput.load_two == False and newOutput.load_three == False: if extraEnergy + 6 > currentInput.current_load * 0.8: newOutput.load_two = True newOutput.load_three = True if extraEnergy >= currentInput.current_load * 0.8: newOutput.power_reference = 0.0 elif currentInput.buying_price == maxBuyingPrice: newOutput.power_reference = currentInput.current_load * 0.8 - extraEnergy else: newOutput.load_two = False newOutput.load_three = False elif newOutput.load_two == False: if extraEnergy + 6 > currentInput.current_load * 0.5: newOutput.load_two = True if extraEnergy >= currentInput.current_load * 0.5: newOutput.power_reference = 0.0 elif currentInput.buying_price == maxBuyingPrice: newOutput.power_reference = currentInput.current_load * 0.5 - extraEnergy else: newOutput.load_two = False elif newOutput.load_three == False: if extraEnergy + 6 > currentInput.current_load * 0.3: newOutput.load_three = True if extraEnergy >= currentInput.current_load * 0.3: newOutput.power_reference = 0.0 elif currentInput.buying_price == maxBuyingPrice: newOutput.power_reference = currentInput.current_load * 0.3 - extraEnergy else: newOutput.load_three = False else: if currentInput.buying_price == minBuyingPrice and currentInput.bessSOC * 10.0 < 9.88: newOutput.power_reference = -6.0 elif currentInput.bessSOC * 10.0 > MIN_ENERGY_FOR_BATTERY: if currentInput.buying_price == maxBuyingPrice: newOutput.power_reference = extraEnergy * (-1.0) else: newOutput.power_reference = 0.0