Skip to content

Add facade in oemof.solph #1193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 22 commits into
base: dev
Choose a base branch
from
Draft

Add facade in oemof.solph #1193

wants to merge 22 commits into from

Conversation

Bachibouzouk
Copy link
Contributor

  • What functionality does it implement?
    This is related to the discussion in Setting underlying structure to implement Facade #1169, after a discussion with @uvchik we decided it might be worth testing approach B. We will link the related PR in oemof.network
  • Where is it located?
    A new _facade.py file in oemof/solph/
  • How does the API look?
    This is tentatively described in the examples/facade/facade.py commited file

@Bachibouzouk
Copy link
Contributor Author

At the moment the code does not work, this is why I set the PR to draft

def add_subnode(self,*args):
"""Add a subnode to the subnetwork"""
for sub_component in args:
sub_component.label = self._sub_component_labelling(sub_component.label)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently cannot set label once it is set for renaming components in subnetwork

  • let labels be overwritten in oemof-solph
  • workaround with custom_properties "sub_label"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Labels are meant to be unique and constant identifiers at the level of oemof.network. Why do the labels have to be changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we wanted to label the components within a subnetwork in a specific way, but we found a solution, we do not change the labels, instead we use a method to label the subnetwork components right upon creation

feedin = Converter(
inputs={self.el_bus: Flow(variable_costs=self.feedin_tariff)},
outputs={internal_bus: Flow()},
label=self.sub_component_labelling("feedin_converter"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p-snft - here we label the subnetwork node using a Facade method. We think we need to have this naming convention to be able to bookkeep the nodes for postprocessing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our aim here is to manage to create a Facade class by tempering minimally with the existing code. This creation process will help the question raise and will prompt discussion about more elegant implementations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds similar to the way we did it in MTRESS:

class AbstractComponent:  # pretty much the MTRESS subnetwork

    (...)

    def create_solph_node(self, label: str, node_type: Callable, **kwargs):
        """Create a solph node and add it to the solph model."""
        _full_label = tuple(self.create_label(label))

        if label in self._solph_nodes:
            raise KeyError(
                f"Solph component named {_full_label} already exists"
            )

        _node = node_type(label=_full_label, **kwargs)

    def create_label(self, label: str) -> list[str]:
        """Return a unique label based on the identifier."""
        return self.identifier + [label]

    @property
    def identifier(self) -> list[str]:
        """Return identifier."""
        identifier = []
        highest_level = self
        while highest_level is not None:
            identifier.append(highest_level.name)
            highest_level = highest_level._nesting_element

        identifier.reverse()
        return identifier

(In reality split into AbstractComponent and NamedElement.)

Comment on lines +254 to +256
file_path = os.path.join(
helpers.extend_basic_path("lp_files"), "basic_example.lp"
)

Check warning

Code scanning / CodeQL

Unreachable code Warning

This statement is unreachable.
Comment on lines +196 to +198
file_path = os.path.join(
helpers.extend_basic_path("lp_files"), "basic_example.lp"
)

Check warning

Code scanning / CodeQL

Unreachable code Warning

This statement is unreachable.
@p-snft p-snft force-pushed the features/add-facades branch from 4a1b1f4 to ee1fd64 Compare June 30, 2025 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants