Skip to content

Commit

Permalink
Fix references between built backend components (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
brynpickering committed Jan 26, 2024
1 parent 52bb659 commit f903741
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 15 deletions.
27 changes: 20 additions & 7 deletions src/calliope/backend/backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def _add_component(
equations = parsed_component.parse_equations(self.valid_component_names)
if not equations:
component_da = component_setter(
parsed_component.drop_dims_not_in_foreach(top_level_where)
parsed_component.drop_dims_not_in_foreach(top_level_where), references
)
else:
component_da = (
Expand Down Expand Up @@ -835,15 +835,28 @@ def _find_all_references(self, initial_references: set) -> set:
references.update(self._find_all_references(new_refs))
return references

def _rebuild_reference(self, reference: str) -> None:
"""Delete and rebuild an optimisation problem component.
def _rebuild_references(self, references: set[str]) -> None:
"""Delete and rebuild optimisation problem components.
Args:
references (str): name of optimisation problem component.
references (set[str]): names of optimisation problem components.
"""
obj_type = self._dataset[reference].attrs["obj_type"]
self.delete_component(reference, obj_type)
getattr(self, "add_" + obj_type.removesuffix("s"))(name=reference)
ordered_components = [
"parameters",
"variables",
"global_expressions",
"constraints",
"objectives",
]
for component in ordered_components:
refs = [
ref
for ref in references
if self._dataset[ref].attrs["obj_type"] == component
]
for ref in refs:
self.delete_component(ref, component)
getattr(self, "add_" + component.removesuffix("s"))(name=ref)


class ShadowPrices:
Expand Down
2 changes: 1 addition & 1 deletion src/calliope/backend/latex_backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def add_variable(
) -> None:
domain_dict = {"real": r"\mathbb{R}\;", "integer": r"\mathbb{Z}\;"}

def _variable_setter(where: xr.DataArray) -> xr.DataArray:
def _variable_setter(where: xr.DataArray, references: set) -> xr.DataArray:
return where.where(where)

if variable_dict is None:
Expand Down
16 changes: 9 additions & 7 deletions src/calliope/backend/pyomo_backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,14 @@ def add_variable(
if variable_dict is None:
variable_dict = self.inputs.attrs["math"]["variables"][name]

def _variable_setter(where):
def _variable_setter(where, references):
domain_type = domain_dict[variable_dict.get("domain", "real")]

bounds = variable_dict["bounds"]
return self._apply_func(
self._to_pyomo_variable,
where,
self._get_capacity_bound(variable_dict["bounds"]["max"], name=name),
self._get_capacity_bound(variable_dict["bounds"]["min"], name=name),
self._get_capacity_bound(bounds["max"], name, references),
self._get_capacity_bound(bounds["min"], name, references),
name=name,
domain_type=domain_type,
)
Expand Down Expand Up @@ -394,8 +394,7 @@ def update_parameter(
new_values,
default=self.inputs.attrs["defaults"].get(name, np.nan),
)
for ref in refs_to_update:
self._rebuild_reference(ref)
self._rebuild_references(refs_to_update)
return None

if missing_dims_in_new_vals:
Expand Down Expand Up @@ -464,7 +463,9 @@ def unfix_variable(self, name: str, where: Optional[xr.DataArray] = None) -> Non
variable_da = variable_da.where(where.fillna(0))
self._apply_func(self._unfix_pyomo_variable, variable_da)

def _get_capacity_bound(self, bound: Any, name: str) -> xr.DataArray:
def _get_capacity_bound(
self, bound: Any, name: str, references: set
) -> xr.DataArray:
"""
Generate array for the upper/lower bound of a decision variable.
Any NaN values will be replaced by None, which Pyomo will correctly interpret as there being no bound to apply.
Expand All @@ -484,6 +485,7 @@ def _get_capacity_bound(self, bound: Any, name: str) -> xr.DataArray:
f"Applying bound according to the {bound} parameter values.",
)
bound_array = self.get_parameter(bound)
references.add(bound)
else:
bound_array = xr.DataArray(bound)

Expand Down

0 comments on commit f903741

Please sign in to comment.