Repository navigation
Add Subsystem and Partition Interfaces for PowerElectronics #560
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
Open
+1,734
−7
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
ee0b1b1
Add BusPartitionInterface to define partition boundaries
abdourahmanbarry ca6fe44
Add SubsystemModel for partition evaluation
abdourahmanbarry c315040
Add HIRES test for SubsystemModel
abdourahmanbarry ac8769e
Add protected access to SystemModelPowerElectronics
abdourahmanbarry 6c76011
Change external data vector to use GridKit vectors
abdourahmanbarry a67eef2
Updated SystemModelPowerElectronics.hpp
abdourahmanbarry 3d36c47
Update README.md for Hires problem
abdourahmanbarry 35af962
Minor update
abdourahmanbarry 239fbdd
Apply pre-commit fixes
abdourahmanbarry 4b4c8b6
Address leak in test
abdourahmanbarry 50c8f26
Change neg1 to INVALID_INDEX
abdourahmanbarry ac21a74
Simplified SubsystemModel code
abdourahmanbarry e37d476
Update BusPartitionInterface constructor and documentation
abdourahmanbarry ed86caa
Update test case
abdourahmanbarry daba0ee
Bug fix
abdourahmanbarry ceb7c5c
Update SubsystemModel
abdourahmanbarry bc769a9
Add BusLinePartitionInterface
abdourahmanbarry 88043c4
Update CMake
abdourahmanbarry ccfaa9f
Forward time updates to enclosed component in BusPartitionInterface
abdourahmanbarry 3de0eba
Update SubsystemModel
abdourahmanbarry 768622f
Remove cloned component and move connection index initialization to c…
abdourahmanbarry b023eb3
Remove Hires Test problem
abdourahmanbarry 39f879c
Add partition PowerElectronics Test problem
abdourahmanbarry 73869f1
Update CMake file in tests
abdourahmanbarry 489655c
Remove BusPartitionInterface as requested during code review
abdourahmanbarry 3c0aa34
change "counter" to "index"
abdourahmanbarry 4a1235e
Set f_ext_data_ to zero
abdourahmanbarry b6581b6
Updated SystemModels
abdourahmanbarry 4f1fa56
Update Interfaces
abdourahmanbarry cde9d74
Update tests
abdourahmanbarry c96a613
Apply pre-commit fixes
abdourahmanbarry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
213 changes: 213 additions & 0 deletions
213
GridKit/Model/PowerElectronics/PartitionInterface/BusLinePartitionInterface.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,213 @@ | ||
|
|
||
| #include "BusLinePartitionInterface.hpp" | ||
|
|
||
| #include <cstddef> | ||
| #include <format> | ||
|
|
||
| #include <GridKit/Model/PowerElectronics/Bus/MicrogridBus.hpp> | ||
| #include <GridKit/Model/PowerElectronics/ExternalConnection.hpp> | ||
| #include <GridKit/Model/PowerElectronics/MicrogridLine/MicrogridLine.hpp> | ||
|
|
||
| namespace GridKit | ||
| { | ||
|
|
||
| namespace PowerElectronics | ||
| { | ||
|
|
||
| /** | ||
| * @brief Construct a partition interface between a bus and a line. | ||
| * | ||
| * The interface consists of four external connections: two bus variables | ||
| * and two line current variables. During partitioning, these connections | ||
| * are mapped to the appropriate subsystem storage. | ||
| * | ||
| * The line currents contribute to the bus residual equations, with signs | ||
| * determined by the orientation of the line relative to the bus. | ||
| * | ||
| * @pre The bus and line connection indices have been allocated. | ||
| * | ||
| * @param bus Bus associated with the partition interface. | ||
| * @param component Line component across the partition boundary. | ||
| * @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) | ||
| { | ||
| if (dynamic_cast<MicrogridBus<ScalarT, IdxT>*>(bus) == nullptr) | ||
| { | ||
| throw std::invalid_argument("BusLinePartitionInterface: Requires a MicrogridBus."); | ||
| } | ||
|
|
||
| if (dynamic_cast<MicrogridLine<ScalarT, IdxT>*>(component) == nullptr) | ||
| { | ||
| throw std::invalid_argument("BusLinePartitionInterface: Requires a MicrogridLine."); | ||
| } | ||
|
|
||
| if (!bus->isAllocated() or !component->isAllocated()) | ||
| { | ||
| throw std::invalid_argument("BusLinePartitionInterface: Malformed network. Ensure components are allocated before partitioning."); | ||
| } | ||
|
|
||
| size_ = 4; | ||
| n_intern_ = 0; | ||
| n_extern_ = 4; | ||
| idc_ = id; | ||
| extern_indices_ = {0, 1, 2, 3}; | ||
| nnz_ = 2; | ||
|
|
||
| // Global indices associated with the local bus. | ||
| auto bus_idx_i = bus->getNodeConnection(0).idx_; | ||
| auto bus_idx_j = bus->getNodeConnection(1).idx_; | ||
|
|
||
| const bool is_left_connection = bus_idx_i == component->getNodeConnection(1) && bus_idx_j == component->getNodeConnection(2); | ||
| const bool is_right_connection = bus_idx_i == component->getNodeConnection(3) && bus_idx_j == component->getNodeConnection(4); | ||
|
|
||
| if (is_left_connection == is_right_connection) | ||
| { | ||
| throw std::invalid_argument( | ||
| std::format( | ||
| "Invalid partition interface detected. Bus(ID={}), Component(ID={}). " | ||
| "Malformed topology or no partitionable connection was found.", | ||
| bus->busID(), | ||
| component->getIDcomponent())); | ||
| } | ||
|
|
||
| sign_ = is_left_connection ? -1.0 : 1.0; | ||
| connection_indices_.resize(static_cast<size_t>(size_)); | ||
|
|
||
| connection_indices_[0] = component->getNodeConnection(is_left_connection ? 1 : 3); | ||
| connection_indices_[1] = component->getNodeConnection(is_left_connection ? 2 : 4); | ||
| connection_indices_[2] = component->getNodeConnection(5); | ||
| connection_indices_[3] = component->getNodeConnection(6); | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::allocate() | ||
| { | ||
| Component<ScalarT, IdxT>::allocate(); | ||
|
|
||
| this->setConnectionNodes(0, connection_indices_[0]); | ||
| this->setConnectionNodes(1, connection_indices_[1]); | ||
| this->setConnectionNodes(2, connection_indices_[2]); | ||
| this->setConnectionNodes(3, connection_indices_[3]); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::setAbsoluteTolerance(RealT abs_tol) | ||
| { | ||
| abs_tol_.setToConst(static_cast<ScalarT>(abs_tol)); | ||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Initialize the partition interface. | ||
| * | ||
| * @return 0 on success. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::initialize() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Identify differential variables | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::tagDifferentiable() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Evaluates the internal residual. | ||
| * | ||
| * All variables are external from the interface's point of view, so there | ||
| * are no internal residual contributions to evaluate. | ||
| * | ||
| * @return 0 on success. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateInternalResidual() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Evaluate the line contribution to the external bus residual. | ||
| * | ||
| * Adds the two line current residual contributions to the corresponding | ||
| * bus residual equations. The sign of each contribution is determined by | ||
| * whether the bus is connected to the left or right end of the line, | ||
| * consistent with the line current orientation. | ||
| * | ||
| * @return 0 on success. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateExternalResidual() | ||
| { | ||
| *f_ext_[0] += sign_ * *y_ext_[2]; | ||
| *f_ext_[1] += sign_ * *y_ext_[3]; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Evaluate the Jacobian contributions associated with the bus. | ||
| * | ||
| * Evaluates the Jacobian of the entries whose residual rows correspond | ||
| * to variables belonging to the connected bus. | ||
| * | ||
| * @note Some of these entries may not be required to form the Jacobian of the | ||
| * subsystem, but may be useful for parallel Jacobian assembly. | ||
| * | ||
| * @return 0 on success. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateJacobian() | ||
| { | ||
| this->zeroJacMatrix(); | ||
|
|
||
| // Jacobian entries corresponding to the two transferred line contributions. | ||
| std::vector<IdxT> rtemp{0, 1}; | ||
| std::vector<IdxT> ctemp{2, 3}; | ||
| std::vector<RealT> valtemp{sign_, sign_}; | ||
|
|
||
| this->setJacValues(rtemp, ctemp, valtemp); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateIntegrand() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::initializeAdjoint() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateAdjointResidual() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| template <class ScalarT, typename IdxT> | ||
| int BusLinePartitionInterface<ScalarT, IdxT>::evaluateAdjointIntegrand() | ||
| { | ||
| return 0; | ||
| } | ||
|
|
||
| // Available template instantiations | ||
| template class BusLinePartitionInterface<double, long int>; | ||
| template class BusLinePartitionInterface<double, size_t>; | ||
| template class BusLinePartitionInterface<DependencyTracking::Variable, long int>; | ||
| template class BusLinePartitionInterface<DependencyTracking::Variable, size_t>; | ||
| } // namespace PowerElectronics | ||
| } // namespace GridKit | ||
109 changes: 109 additions & 0 deletions
109
GridKit/Model/PowerElectronics/PartitionInterface/BusLinePartitionInterface.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /** | ||
| * @file BusLinePartitionInterface.hpp | ||
| * @author Abdourahman Barry (abdourahman@vt.edu) | ||
| * | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <GridKit/Model/PowerElectronics/Component.hpp> | ||
| #include <GridKit/Model/PowerElectronics/NodeBase.hpp> | ||
| #include <GridKit/Model/PowerElectronics/PartitionInterface/PartitionInterface.hpp> | ||
|
|
||
| namespace GridKit | ||
| { | ||
| namespace PowerElectronics | ||
| { | ||
| /** | ||
| * @brief Partition interface between a bus and a line. | ||
| * | ||
| * The BusLinePartitionInterface provides a mechanism for a partition to access | ||
| * the current injection it requires from a line located in a neighboring | ||
| * partition, without evaluating the line within the local partition. | ||
| * | ||
| * The interface tracks four variables associated with the bus-line connection. | ||
| * The first two variables belong to the bus participating in the partition | ||
| * boundary, while the last two belong to the line connected to that bus. All | ||
| * four variables are treated as external variables by the interface. | ||
| * | ||
| * During partitioning, the interface is added to the partition containing the | ||
| * bus. Since the first two interface variables belong to components within the | ||
| * partition, the subsystem maps them to its local variables. The last two | ||
| * variables belong to the line in the neighboring partition and are therefore | ||
| * identified by the subsystem as external variables. | ||
| * | ||
| * During subsystem evaluation, the interface uses these external line variables | ||
| * to provide the corresponding current injection to the bus equations. The | ||
| * current contribution is added to or subtracted from the bus residual according | ||
| * to which end of the line is connected to the bus. | ||
| * | ||
| * @tparam ScalarT Scalar type used for state and residual values. | ||
| * @tparam IdxT Index type used for component and variable indices. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| class BusLinePartitionInterface : public PartitionInterface<ScalarT, IdxT> | ||
| { | ||
|
|
||
| using component_type = Component<ScalarT, IdxT>; | ||
| using node_type = typename PowerElectronics::NodeBase<ScalarT, IdxT>; | ||
| using RealT = typename Component<ScalarT, IdxT>::RealT; | ||
|
|
||
| using Component<ScalarT, IdxT>::size_; | ||
| using Component<ScalarT, IdxT>::nnz_; | ||
| using Component<ScalarT, IdxT>::time_; | ||
| using Component<ScalarT, IdxT>::alpha_; | ||
| using Component<ScalarT, IdxT>::y_ext_; | ||
| using Component<ScalarT, IdxT>::y_int_; | ||
| using Component<ScalarT, IdxT>::yp_ext_; | ||
| using Component<ScalarT, IdxT>::yp_int_; | ||
| using Component<ScalarT, IdxT>::tag_; | ||
| using Component<ScalarT, IdxT>::abs_tol_; | ||
| using Component<ScalarT, IdxT>::f_ext_; | ||
| using Component<ScalarT, IdxT>::f_int_; | ||
| using Component<ScalarT, IdxT>::g_; | ||
| using Component<ScalarT, IdxT>::yB_; | ||
| using Component<ScalarT, IdxT>::ypB_; | ||
| using Component<ScalarT, IdxT>::fB_; | ||
| using Component<ScalarT, IdxT>::gB_; | ||
| using Component<ScalarT, IdxT>::param_; | ||
| using Component<ScalarT, IdxT>::idc_; | ||
|
|
||
| using Component<ScalarT, IdxT>::extern_indices_; | ||
| using Component<ScalarT, IdxT>::n_extern_; | ||
| using Component<ScalarT, IdxT>::n_intern_; | ||
| using Component<ScalarT, IdxT>::connection_nodes_; | ||
|
|
||
| public: | ||
| BusLinePartitionInterface(node_type* bus, component_type* component, IdxT id); | ||
| ~BusLinePartitionInterface() override = default; | ||
|
|
||
| int allocate() final; | ||
| int initialize() final; | ||
| int tagDifferentiable() final; | ||
| int setAbsoluteTolerance(RealT) final; | ||
| int evaluateInternalResidual() final; | ||
| int evaluateExternalResidual() final; | ||
| int evaluateJacobian() final; | ||
| int evaluateIntegrand() final; | ||
|
|
||
| int initializeAdjoint() final; | ||
| int evaluateAdjointResidual() final; | ||
| // int evaluateAdjointJacobian(); | ||
|
superwhiskers marked this conversation as resolved.
Resolved
|
||
| int evaluateAdjointIntegrand() final; | ||
|
|
||
| private: | ||
| /** | ||
| * @brief Global connection indices for the bus voltages and line currents | ||
| * across the partition boundary. | ||
| */ | ||
| std::vector<IdxT> connection_indices_; | ||
|
|
||
| /** | ||
| * @brief Sign of the line current contribution to the bus residual. | ||
| * | ||
| * -1 for the left end of the line and +1 for the right end. | ||
| */ | ||
| RealT sign_; | ||
| }; | ||
| } // namespace PowerElectronics | ||
| } // namespace GridKit | ||
9 changes: 9 additions & 0 deletions
9
GridKit/Model/PowerElectronics/PartitionInterface/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| gridkit_add_library( | ||
| power_elec_bus_line_interface | ||
| SOURCES BusLinePartitionInterface.cpp | ||
| HEADERS BusLinePartitionInterface.hpp PartitionInterface.hpp | ||
| LINK_LIBRARIES | ||
| PUBLIC | ||
| GridKit::dense_vector | ||
| GridKit::utilities_logger | ||
| GridKit::power_elec_microline) |
32 changes: 32 additions & 0 deletions
32
GridKit/Model/PowerElectronics/PartitionInterface/PartitionInterface.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
|
|
||
|
|
||
| #pragma once | ||
|
|
||
| #include <GridKit/AutomaticDifferentiation/DependencyTracking/Variable.hpp> | ||
| #include <GridKit/Model/Evaluator.hpp> | ||
| #include <GridKit/Model/PowerElectronics/Component.hpp> | ||
|
|
||
| namespace GridKit | ||
| { | ||
| namespace PowerElectronics | ||
| { | ||
|
|
||
| /*! | ||
| * @brief Base class for partition interface components. | ||
| * | ||
| * A partition interface is simply a component that is designed to aid in | ||
| * marking partition boundary to facilitate partion evaluation and | ||
| * Jacobian assembly. All partition interface that will be implemented | ||
| * in the future should inherit from this class and all common features | ||
| * should be factored here. | ||
| */ | ||
| template <class ScalarT, typename IdxT> | ||
| class PartitionInterface : public Component<ScalarT, IdxT> | ||
| { | ||
| public: | ||
| PartitionInterface() = default; | ||
|
|
||
| ~PartitionInterface() = default; | ||
| }; | ||
| } // namespace PowerElectronics | ||
| } // namespace GridKit |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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 keepBusLinePartitionInterfacefor now and only introduceBusPartitionInterfaceif/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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the
BusLinePartitionInterfaceis specific to the connection between a bus and a line, removingBusPartitionInterfacemeans 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
BusPartitionInterfaceand theHirestest 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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
Hiresis not specific toPowerElectronics, I recommend a custom evaluator with the partitions in the unit test, similar to what's being done in #614. A PR withHirestesting the (higer-order) co-simulation methods is welcome.