diff --git a/src/optimizer/optimizer.py b/src/optimizer/optimizer.py index fa7eeb17c..c1c375572 100644 --- a/src/optimizer/optimizer.py +++ b/src/optimizer/optimizer.py @@ -211,13 +211,19 @@ def _setup_variables(self): else: self.variables['z_c'][i] = None - # Binary variable to lock charging against discharging + # Binary variable to lock charging against discharging. A battery + # that cannot discharge (d_max=0) or cannot charge (c_max=0) needs no + # lock: the constraint pair is vacuous, and the binaries only add + # integrality work for the solver. self.variables['z_cd'] = {} for i, bat in enumerate(self.batteries): - self.variables['z_cd'][i] = [ - pulp.LpVariable(f"z_cd_{i}_{t}", cat='Binary') - for t in self.time_steps - ] + if bat.c_max > 0 and bat.d_max > 0: + self.variables['z_cd'][i] = [ + pulp.LpVariable(f"z_cd_{i}_{t}", cat='Binary') + for t in self.time_steps + ] + else: + self.variables['z_cd'][i] = None def _setup_target_function(self): """ @@ -504,14 +510,16 @@ def _add_battery_constraints(self): self.problem += (self.variables['d'][i][t] <= bat.d_max * self.time_series.dt[t] / 3600. * (1 - self.variables['y'][t])) - # lock charging against discharging - for t in self.time_steps: - # Discharge constraint - self.problem += (self.variables['d'][i][t] <= bat.d_max * self.time_series.dt[t] / 3600. - * self.variables['z_cd'][i][t]) - # Charge constraint - self.problem += (self.variables['c'][i][t] <= bat.c_max * self.time_series.dt[t] / 3600. - * (1 - self.variables['z_cd'][i][t])) + # lock charging against discharging (skipped when the battery + # cannot both charge and discharge: nothing to lock) + if self.variables['z_cd'][i] is not None: + for t in self.time_steps: + # Discharge constraint + self.problem += (self.variables['d'][i][t] <= bat.d_max * self.time_series.dt[t] / 3600. + * self.variables['z_cd'][i][t]) + # Charge constraint + self.problem += (self.variables['c'][i][t] <= bat.c_max * self.time_series.dt[t] / 3600. + * (1 - self.variables['z_cd'][i][t])) def solve(self) -> Dict: """ diff --git a/test_cases/013-grid-export-limit-hit.json b/test_cases/013-grid-export-limit-hit.json index 53863f505..4a3d34bcf 100644 --- a/test_cases/013-grid-export-limit-hit.json +++ b/test_cases/013-grid-export-limit-hit.json @@ -199,7 +199,7 @@ }, "expected_response": { "status": "Optimal", - "objective_value": 17.5372629588039, + "objective_value": 17.531374666979104, "limit_violations": { "grid_import_limit_exceeded": false, "grid_export_limit_hit": true