Skip to content

Add Subsystem and Partition Interfaces for PowerElectronics - #560

Open
abdourahmanbarry wants to merge 31 commits into
developfrom
abdou/subsystem_model
Open

abdourahmanbarry wants to merge 31 commits into
developfrom
abdou/subsystem_model

Conversation

@abdourahmanbarry

Copy link
Copy Markdown
Collaborator

Description

In this PR, we implement SubsystemModel for partitioned Power Electronics simulation. The implementation provides the infrastructure required to partition Power Electronics networks, and to evaluate subsystem residuals and Jacobians independently.

This is the third of four stacked pull requests that split PR #492 into simpler, more manageable chunks.

Proposed changes

We added a SubsystemModel class to represent an individual partition and a BusPartitionInterface component to mark partition boundaries. Together, these enable us to partition larger networks for co-simulation and parallel function evaluation.

Checklist

  • All tests pass.
  • Code compiles cleanly with flags -Wall -Wpedantic -Wconversion -Wextra.
  • The new code follows GridKit™ style guidelines.
  • There are unit tests for the new code.
  • The new code is documented.
  • The feature branch is rebased with respect to the target branch.
  • The CHANGELOG.md has been updated to reflect the changes. If this is a minor PR that is part of a larger fix already included in the file, state so.

@superwhiskers superwhiskers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

just an architectural question

Comment on lines +27 to +50
/**
* @brief Represents a subset of a PowerElectronicsModel that can be evaluated
* independently.
*
* A SubsystemModel contains a collection of existing GridKit components and
* nodes taken from a larger system. Variables owned by those components and
* nodes become internal variables of the subsystem. Variables needed by those
* components but owned outside the subsystem become external coupling
* variables.
*
* Components normally store connection indices in the global system indexing.
* During subsystem allocation, these indices are temporarily replaced with a
* contiguous local subsystem indexing so that the subsystem can be evaluated
* like an independent PowerElectronicsModel.
*
* External coupling values must be supplied before residual or Jacobian
* evaluation, either directly through the external-data vectors or through a
* forcing function.
*
* @todo Find a better name for this class and its base class.
*
* @tparam ScalarT Scalar type used by the model.
* @tparam IdxT Index type used for variable and connection indices.
*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

so, my main question here is why do we need this notion of distinct "systems" and "subsystems" present in the codebase?

when first learning about system partitioning stuff in gridkit, it seemed more natural to me to instead allow the system itself to be a component that can be used in another system. the "non-owning" nature of SubsystemModel as implemented here seems like it could be more naturally captured by a SystemModelRef or some similar type that encapsulates the notion of "referencing" a system model or something like that (perhaps to match the bus partition interface thing for components---SystemModelInterface).

what was the motivation behind this design choice? it seems more natural to build up from smaller components than to break apart.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good question. There are several reasons for doing it this way.

First, when we partition a system, each subsystem is smaller than the original system, so we can no longer directly use the global indices of the components when evaluating the subsystem. We therefore need to map the global system indices to the corresponding local subsystem indices. This mapping is not needed when evaluating the monolithic system, but it is something we must do before we can evaluate partitions independently.

Second, there is an important difference in how the two models are used. PowerElectronicsModel is designed to construct and own a network. We add components and nodes to it to build up the system. SubsystemModel expects to receive part of an already existing network. It is not trying to construct another network or own those components. If we combine everything into a single class, the same class would need logic for both constructing a network(not need when you are absorbing a part of an already existing network) and representing a partition of an existing network, in addition to handling local/global index mappings and internal/external variables management. I think keeping those responsibilities separate makes the design easier to understand. In addition, the SubsystemModel is still a System model because it inherits and reuses a lot of code from the System Model.

I agree with you that, ideally, we would want a System Model that can be treated as a component, and can be nested hierarchically to arbitrary depth. This was actually one of our design considerations. However, we agreed that supporting that design properly would require a substantial amount time, but we do not have much time left under the scope of the AGM project.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

i think that we should open an issue regarding "componentized" system models to replace the partitioning implementation approach implemented in this pull request if doing so right now is too difficult

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot 2026-09-04 140924

We are already heading down that direction with this implementation. It might need couple of cycles to get there. This is a good starting point I think. I have attached a snapshot of a design document I shared with Slaven couple of months ago. It needs to be update, but this section talks about doing exactly what you are thinking.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This chart is more applicable to multimethod implementation rather than co-simulations. You can indeed use SystmModel in cosimulation framework, where all system components would be connected through signal ports. But to @superwhiskers point, SystemModel could (and probably should) behave as a component.

Base automatically changed from abdou/clone to develop September 8, 2026 17:51
@nkoukpaizan
nkoukpaizan force-pushed the abdou/subsystem_model branch from 1ad85a7 to e23c7ba Compare September 8, 2026 17:51

@nkoukpaizan nkoukpaizan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few specific comments.

This seems to work, but I find the logic of the BusPartitionInterface constructor and SubsystemModel index maps hard to follow. I would like to get inputs from @alexander-novo on those implementations.

I'll take another look after the initial comments have been addressed.

Comment on lines +24 to +25
template <class ScalarT, typename IdxT>
class HiresComponent1 : public CircuitComponent<ScalarT, IdxT>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Will need to update the namespaces after #576

@abdourahmanbarry

abdourahmanbarry commented Sep 19, 2026 •

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan @alexander-novo @superwhiskers I have updated the code to incorporate the suggestions and improved the documentation to make the implementation easier to follow. Let me know what you think.

@superwhiskers superwhiskers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

just one minor comment

@abdourahmanbarry

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan I have added the partition interface that we discussed last time. It is simpler (and hopefully more efficient), but it only supports partitioning between a MicrogridBus and a MicrogridLine. I believe this covers the most common use cases for partitioning in cosim for PowerElectronics. I still advice we keep the other partition interface for partitioning test problems that are not necessarily PowerElectronics such as the Hires test problem.

CC: @pelesh @alexander-novo @superwhiskers

@superwhiskers superwhiskers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

looks good. all of these are nitpicks. SubsystemModelWithHires passes just fine on my machine.

@nkoukpaizan nkoukpaizan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I like the BusLinePartitionInterface. Please see my related comments and other comments below.

* @param id Unique identifier for the partition interface.
*/
template <class ScalarT, typename IdxT>
BusLinePartitionInterface<ScalarT, IdxT>::BusLinePartitionInterface(node_type* bus, component_type* component, IdxT id)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yes, this is much simpler and easier to understand than BusPartitionInterface. I recommend adding a unit test for this approach or updating the existing test. My preference would be to only keep BusLinePartitionInterface for now and only introduce BusPartitionInterface if/when the need arises.

Also, I believe we don't need clone() in this approach. We can directly compute and store the relevant indices and signs in the constructor.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Since the BusLinePartitionInterface is specific to the connection between a bus and a line, removing BusPartitionInterface means the Hires Test problem can no longer be partitioned as in the current design, since it does not contain a line.

I plan to keep the BusPartitionInterface and the Hires test problem in a separate branch for order testing of my cosims methods, without any plans of merging to develop. For now I have removed the Hires test and added a new Power Electronics test to validate the partitioning implementation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since Hires is not specific to PowerElectronics, I recommend a custom evaluator with the partitions in the unit test, similar to what's being done in #614. A PR with Hires testing the (higer-order) co-simulation methods is welcome.

Comment on lines +17 to +20
/**
* @todo Move all PowerElectronics models into the PowerElectronics namespace
* for consistency.
*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We merged the namespace fix. Rebasing would help (and reduce the conflicts with develop).

@abdourahmanbarry abdourahmanbarry Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is now rebased with respect to develop. You can have a look again if you have time.

@read-the-docs-community

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants