From b37e7e08d3002183ae28158509d9b2df9eb394b1 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 9 Oct 2022 11:17:39 +0200 Subject: [PATCH 1/6] Log warning instead of raising UnknownForecastException, and assume zero power values for missing values Signed-off-by: F.N. Claessen --- flexmeasures/data/models/planning/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flexmeasures/data/models/planning/utils.py b/flexmeasures/data/models/planning/utils.py index 23a9c347e..1ce404d51 100644 --- a/flexmeasures/data/models/planning/utils.py +++ b/flexmeasures/data/models/planning/utils.py @@ -150,11 +150,13 @@ def get_power_values( one_deterministic_belief_per_event=True, ) # consumption is negative, production is positive df = simplify_index(bdf) + df = df.reindex(initialize_index(query_window[0], query_window[1], resolution)) nan_values = df.isnull().values if nan_values.any() or df.empty: - raise UnknownForecastException( - f"Forecasts unknown for planning window. (sensor {sensor.id})" + current_app.logger.warning( + f"Assuming zero power values for (partially) unknown power values for planning window. (sensor {sensor.id})" ) + df = df.fillna(0) return -df.values From 14b8c7a836c16ce4332a0e7be49670684acfd330 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 9 Oct 2022 11:18:34 +0200 Subject: [PATCH 2/6] Scheduler takes into account attribute consumption_is_positive Signed-off-by: F.N. Claessen --- flexmeasures/data/models/planning/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/flexmeasures/data/models/planning/utils.py b/flexmeasures/data/models/planning/utils.py index 1ce404d51..90bf279d8 100644 --- a/flexmeasures/data/models/planning/utils.py +++ b/flexmeasures/data/models/planning/utils.py @@ -157,6 +157,10 @@ def get_power_values( f"Assuming zero power values for (partially) unknown power values for planning window. (sensor {sensor.id})" ) df = df.fillna(0) + if sensor.get_attribute( + "consumption_is_positive", False + ): # FlexMeasures default is to store consumption as negative power values + return df.values return -df.values From 94749fa38e52cebaca28619fddb74df5e9eac6f7 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 9 Oct 2022 11:34:15 +0200 Subject: [PATCH 3/6] Stop wrapping DataFrame representations in logging Signed-off-by: F.N. Claessen --- flexmeasures/utils/config_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flexmeasures/utils/config_utils.py b/flexmeasures/utils/config_utils.py index bc7cb5fbe..519203d77 100644 --- a/flexmeasures/utils/config_utils.py +++ b/flexmeasures/utils/config_utils.py @@ -8,6 +8,7 @@ from flask import Flask from inflection import camelize +import pandas as pd from flexmeasures.utils.config_defaults import ( Config as DefaultConfig, @@ -45,6 +46,7 @@ def configure_logging(): """Configure and register logging""" + pd.options.display.expand_frame_repr = False # Don't wrap DataFrame representations loggingDictConfig(flexmeasures_logging_config) From 7320432ae45a18a00121b837a48142d8bb1d42cd Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Fri, 21 Oct 2022 10:35:07 +0200 Subject: [PATCH 4/6] Deal with empty SoC targets Signed-off-by: F.N. Claessen --- flexmeasures/data/models/planning/battery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flexmeasures/data/models/planning/battery.py b/flexmeasures/data/models/planning/battery.py index d6e3380e0..ce5f56d1a 100644 --- a/flexmeasures/data/models/planning/battery.py +++ b/flexmeasures/data/models/planning/battery.py @@ -127,7 +127,7 @@ def schedule_battery( beliefs_before=belief_time, sensor=inflexible_sensor, ) - if soc_targets is not None: + if soc_targets is not None and not soc_targets.empty: device_constraints[0]["equals"] = soc_targets.shift( -1, freq=resolution ).values * (timedelta(hours=1) / resolution) - soc_at_start * ( From 0e6c81429a8ea94e0994e77fb1210e4698352d11 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Fri, 21 Oct 2022 10:36:53 +0200 Subject: [PATCH 5/6] Let sign of battery derivative constraints depend on sensor attribute, similar to Charge Points Signed-off-by: F.N. Claessen --- flexmeasures/data/models/planning/battery.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/flexmeasures/data/models/planning/battery.py b/flexmeasures/data/models/planning/battery.py index ce5f56d1a..7aa2e288b 100644 --- a/flexmeasures/data/models/planning/battery.py +++ b/flexmeasures/data/models/planning/battery.py @@ -141,10 +141,16 @@ def schedule_battery( device_constraints[0]["max"] = (soc_max - soc_at_start) * ( timedelta(hours=1) / resolution ) - device_constraints[0]["derivative min"] = ( - sensor.get_attribute("capacity_in_mw") * -1 - ) - device_constraints[0]["derivative max"] = sensor.get_attribute("capacity_in_mw") + if sensor.get_attribute("is_strictly_non_positive"): + device_constraints[0]["derivative min"] = 0 + else: + device_constraints[0]["derivative min"] = ( + sensor.get_attribute("capacity_in_mw") * -1 + ) + if sensor.get_attribute("is_strictly_non_negative"): + device_constraints[0]["derivative max"] = 0 + else: + device_constraints[0]["derivative max"] = sensor.get_attribute("capacity_in_mw") # Apply round-trip efficiency evenly to charging and discharging device_constraints[0]["derivative down efficiency"] = roundtrip_efficiency**0.5 From dc7f2b2cbef910baa98a77ce73c9dc363336d4e3 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Sun, 9 Oct 2022 11:11:40 +0200 Subject: [PATCH 6/6] Remove obsolete import Signed-off-by: F.N. Claessen --- flexmeasures/data/models/planning/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/flexmeasures/data/models/planning/utils.py b/flexmeasures/data/models/planning/utils.py index 90bf279d8..e7e3f1b36 100644 --- a/flexmeasures/data/models/planning/utils.py +++ b/flexmeasures/data/models/planning/utils.py @@ -9,7 +9,6 @@ from flexmeasures.data.models.time_series import Sensor, TimedBelief from flexmeasures.data.models.planning.exceptions import ( - UnknownForecastException, UnknownMarketException, UnknownPricesException, )