From 0f692fb4bb3760d11739abd843b0e261ada84bf6 Mon Sep 17 00:00:00 2001 From: Julian Brendel Date: Tue, 13 Apr 2021 09:57:01 +0200 Subject: [PATCH 1/4] add assertion error if flows in and out of battery are detected --- smooth/components/component_battery.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/smooth/components/component_battery.py b/smooth/components/component_battery.py index 912c89d..3f00ba6 100644 --- a/smooth/components/component_battery.py +++ b/smooth/components/component_battery.py @@ -252,6 +252,27 @@ def add_to_oemof_model(self, busses, model): model.add(battery) return battery + def update_flows(self, results, comp_name=None): + """Updates the flows of a component for each time step. + + :param results: The oemof results for the given time step + :type results: object + :param comp_name: The name of the component - while components can generate more + than one oemof model, they sometimes need to give a custom name, defaults to None + :type comp_name: str, optional + :return: updated flow values for each flow in the 'flows' dict + """ + # Update flows as defined in mother class + Component.update_flows(self, results, self.name) + # Check if there are flows in and out, if so trigger an AssertionError + non_zero_flows = 0 + for flows_key in self.flows: + if self.flows[flows_key][self.sim_params.i_interval] != 0: + non_zero_flows += 1 + assert non_zero_flows <= 1, \ + 'There are flows in and out of the Battery \'' + self.name \ + + '\', please reevaluate your settings (e.g. variable artificial costs).' + def update_states(self, results): """Updates the states of the battery component for each time step From 209cbf32eb10f2af11660cea45ff1e3589051755 Mon Sep 17 00:00:00 2001 From: Julian Brendel Date: Tue, 13 Apr 2021 14:36:37 +0200 Subject: [PATCH 2/4] rework error message for cycle flows of battery --- smooth/components/component_battery.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/smooth/components/component_battery.py b/smooth/components/component_battery.py index 3f00ba6..d7c8a12 100644 --- a/smooth/components/component_battery.py +++ b/smooth/components/component_battery.py @@ -261,17 +261,27 @@ def update_flows(self, results, comp_name=None): than one oemof model, they sometimes need to give a custom name, defaults to None :type comp_name: str, optional :return: updated flow values for each flow in the 'flows' dict + :raises: ValueError when input parameters result in flows in and out + of the battery at the same time """ # Update flows as defined in mother class Component.update_flows(self, results, self.name) # Check if there are flows in and out, if so trigger an AssertionError non_zero_flows = 0 - for flows_key in self.flows: - if self.flows[flows_key][self.sim_params.i_interval] != 0: + for flows in self.flows.values(): + if flows[self.sim_params.i_interval] != 0: non_zero_flows += 1 - assert non_zero_flows <= 1, \ - 'There are flows in and out of the Battery \'' + self.name \ - + '\', please reevaluate your settings (e.g. variable artificial costs).' + if non_zero_flows > 1: + if (self.vac_in < 0) & \ + self.vac_out < \ + -self.vac_in * self.efficiency_charge * self.efficiency_discharge: + raise ValueError('There are flows in and out of the Battery \'' + self.name + + '\', if the Battery is incetivised to be charged using negative ' + 'vac_in, the vac_out have to be higher than the value of vac_in,' + ' multiplied with the internal losses') + else: + raise ValueError('There are flows in and out of the Battery \'' + self.name + + '\', please reevaluate your settings') def update_states(self, results): """Updates the states of the battery component for each time step From d3e79048d7142905731752e653d9842b6286dd3f Mon Sep 17 00:00:00 2001 From: Julian Brendel Date: Thu, 22 Apr 2021 14:56:24 +0200 Subject: [PATCH 3/4] make flow ckeck external function --- smooth/components/component_battery.py | 41 +++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/smooth/components/component_battery.py b/smooth/components/component_battery.py index d7c8a12..afa6c36 100644 --- a/smooth/components/component_battery.py +++ b/smooth/components/component_battery.py @@ -261,27 +261,10 @@ def update_flows(self, results, comp_name=None): than one oemof model, they sometimes need to give a custom name, defaults to None :type comp_name: str, optional :return: updated flow values for each flow in the 'flows' dict - :raises: ValueError when input parameters result in flows in and out - of the battery at the same time """ # Update flows as defined in mother class Component.update_flows(self, results, self.name) - # Check if there are flows in and out, if so trigger an AssertionError - non_zero_flows = 0 - for flows in self.flows.values(): - if flows[self.sim_params.i_interval] != 0: - non_zero_flows += 1 - if non_zero_flows > 1: - if (self.vac_in < 0) & \ - self.vac_out < \ - -self.vac_in * self.efficiency_charge * self.efficiency_discharge: - raise ValueError('There are flows in and out of the Battery \'' + self.name + - '\', if the Battery is incetivised to be charged using negative ' - 'vac_in, the vac_out have to be higher than the value of vac_in,' - ' multiplied with the internal losses') - else: - raise ValueError('There are flows in and out of the Battery \'' + self.name + - '\', please reevaluate your settings') + self.check_flows() def update_states(self, results): """Updates the states of the battery component for each time step @@ -302,3 +285,25 @@ def update_states(self, results): # Check if this result is the state of charge. self.soc = df_storage[i_result][0] / self.battery_capacity self.states["soc"][self.sim_params.i_interval] = self.soc + + def check_flows(self): + """ + :raises: ValueError when input parameters result in flows in and out + of the battery at the same time + """ + # Check if there are flows in and out, if so trigger an AssertionError + non_zero_flows = 0 + for flows in self.flows.values(): + if flows[self.sim_params.i_interval] != 0: + non_zero_flows += 1 + if non_zero_flows > 1: + if (self.vac_in < 0) & \ + self.vac_out < \ + -self.vac_in * self.efficiency_charge * self.efficiency_discharge: + raise ValueError('There are flows in and out of the Battery \'' + self.name + + '\', if the Battery is incetivised to be charged using negative ' + 'vac_in, the vac_out have to be higher than the value of vac_in,' + ' multiplied with the internal losses') + else: + raise ValueError('There are flows in and out of the Battery \'' + self.name + + '\', please reevaluate your settings') From da8e041d7098b2b4f8b7752c92b8dc76616dc30b Mon Sep 17 00:00:00 2001 From: Julian Brendel Date: Wed, 28 Apr 2021 13:16:37 +0200 Subject: [PATCH 4/4] restructure Error messages for cycle flows --- smooth/components/component_battery.py | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/smooth/components/component_battery.py b/smooth/components/component_battery.py index afa6c36..f0d08e5 100644 --- a/smooth/components/component_battery.py +++ b/smooth/components/component_battery.py @@ -253,16 +253,14 @@ def add_to_oemof_model(self, busses, model): return battery def update_flows(self, results, comp_name=None): - """Updates the flows of a component for each time step. + """Update flow values for each flow in the 'flows' dict of results :param results: The oemof results for the given time step :type results: object :param comp_name: The name of the component - while components can generate more than one oemof model, they sometimes need to give a custom name, defaults to None :type comp_name: str, optional - :return: updated flow values for each flow in the 'flows' dict """ - # Update flows as defined in mother class Component.update_flows(self, results, self.name) self.check_flows() @@ -287,23 +285,25 @@ def update_states(self, results): self.states["soc"][self.sim_params.i_interval] = self.soc def check_flows(self): + """ Checks if there are flows in and out of the battery and if so triggers an AssertionError + + :raises: ValueError if flows in and out of the battery at the same time are detected """ - :raises: ValueError when input parameters result in flows in and out - of the battery at the same time - """ - # Check if there are flows in and out, if so trigger an AssertionError - non_zero_flows = 0 - for flows in self.flows.values(): - if flows[self.sim_params.i_interval] != 0: - non_zero_flows += 1 + # get current time index + time_idx = self.sim_params.i_interval + # get number of current non-zero flows + non_zero_flows = sum([1 if flow[time_idx] else 0 for flow in self.flows.values()]) if non_zero_flows > 1: - if (self.vac_in < 0) & \ - self.vac_out < \ - -self.vac_in * self.efficiency_charge * self.efficiency_discharge: + # more than one non-zero flow detected + # compute vac_out_threshold: the minimum vac_out required to prevent circular flows + vac_out_threshold = -self.vac_in / (self.efficiency_charge * self.efficiency_discharge) + if self.vac_in < 0 and self.vac_out < vac_out_threshold: + # vac_in/vac_out invalid: charging and discharging at the same time is incentivized raise ValueError('There are flows in and out of the Battery \'' + self.name + - '\', if the Battery is incetivised to be charged using negative ' - 'vac_in, the vac_out have to be higher than the value of vac_in,' - ' multiplied with the internal losses') + '\'. If the Battery is incetivised to be charged using negative ' + 'vac_in, vac_out has to be chosen higher than: ' + '-vac_in / (efficiency_charge * efficiency_discharge)') else: + # something different went wrong. Does this even happen? raise ValueError('There are flows in and out of the Battery \'' + self.name + - '\', please reevaluate your settings') + '\'. Please reevaluate your settings')