3#include <dpsim/MNAStateSpaceContributor.h>
5#include <dpsim-models/EMT/EMT_Ph3_Capacitor.h>
6#include <dpsim-models/EMT/EMT_Ph3_Inductor.h>
7#include <dpsim-models/EMT/EMT_Ph3_Resistor.h>
8#include <dpsim-models/EMT/EMT_Ph3_TwoTerminalVTypeSSNComp.h>
9#include <dpsim-models/EMT/EMT_Ph3_TwoTerminalVTypeVariableSSNComp.h>
10#include <dpsim-models/EMT/EMT_Ph3_VoltageSource.h>
11#include <dpsim-models/EMT/EMT_VTypeSSNComp.h>
12#include <dpsim-models/SimPowerComp.h>
21using SimPowerCompReal = CPS::SimPowerComp<CPS::Real>;
25Matrix buildTwoTerminalInterfaceVoltageMapping(SimPowerCompReal &component,
27 Matrix K = Matrix::Zero(3, mnaVectorSize);
29 if (component.terminalNotGrounded(1)) {
30 for (UInt phase = 0; phase < 3; ++phase)
31 K(phase, component.matrixNodeIndex(1, phase)) = 1.0;
34 if (component.terminalNotGrounded(0)) {
35 for (UInt phase = 0; phase < 3; ++phase)
36 K(phase, component.matrixNodeIndex(0, phase)) = -1.0;
46void stampTwoTerminalCurrentInjectionMapping(
const Matrix &K, Matrix &CdMna,
48 const Matrix &outputMatrix) {
49 CdMna.block(0, stateOffset, CdMna.rows(), outputMatrix.cols()) +=
50 -K.transpose() * outputMatrix;
55 metadata.abcStateIndexTriples.push_back(
56 {stateOffset + 0, stateOffset + 1, stateOffset + 2});
59class EMTPh3InductorStateSpaceContributor final
62 explicit EMTPh3InductorStateSpaceContributor(
63 std::shared_ptr<EMT::Ph3::Inductor> component)
64 : mComponent(std::move(component)) {}
66 UInt getStateCount()
const override {
return 3; }
68 void stamp(Matrix &AdLocal, Matrix &BdMna, Matrix &CdMna, UInt stateOffset,
69 UInt mnaVectorSize)
const override {
70 const Matrix &conductance = mComponent->getMNAConductance();
73 buildTwoTerminalInterfaceVoltageMapping(*mComponent, mnaVectorSize);
79 AdLocal.block(stateOffset, stateOffset, 3, 3) += Matrix::Identity(3, 3);
81 BdMna.block(stateOffset, 0, 3, mnaVectorSize) += 2.0 * conductance * K;
83 stampTwoTerminalCurrentInjectionMapping(K, CdMna, stateOffset,
84 Matrix::Identity(3, 3));
87 void contributeMetadata(StateSpaceMetadata &metadata,
88 UInt stateOffset)
const override {
89 addThreePhaseAbcStateMetadata(metadata, stateOffset);
93 std::shared_ptr<EMT::Ph3::Inductor> mComponent;
96class EMTPh3CapacitorStateSpaceContributor final
99 explicit EMTPh3CapacitorStateSpaceContributor(
100 std::shared_ptr<EMT::Ph3::Capacitor> component)
101 : mComponent(std::move(component)) {}
103 UInt getStateCount()
const override {
return 3; }
105 void stamp(Matrix &AdLocal, Matrix &BdMna, Matrix &CdMna, UInt stateOffset,
106 UInt mnaVectorSize)
const override {
107 const Matrix &conductance = mComponent->getMNAConductance();
110 buildTwoTerminalInterfaceVoltageMapping(*mComponent, mnaVectorSize);
116 AdLocal.block(stateOffset, stateOffset, 3, 3) -= Matrix::Identity(3, 3);
118 BdMna.block(stateOffset, 0, 3, mnaVectorSize) -= 2.0 * conductance * K;
120 stampTwoTerminalCurrentInjectionMapping(K, CdMna, stateOffset,
121 Matrix::Identity(3, 3));
124 void contributeMetadata(StateSpaceMetadata &metadata,
125 UInt stateOffset)
const override {
126 addThreePhaseAbcStateMetadata(metadata, stateOffset);
130 std::shared_ptr<EMT::Ph3::Capacitor> mComponent;
133class EMTPh3TwoTerminalVTypeSSNStateSpaceContributor final
136 EMTPh3TwoTerminalVTypeSSNStateSpaceContributor(
137 std::shared_ptr<EMT::VTypeSSNComp> component, Bool isVariable)
138 : mComponent(std::move(component)), mIsVariable(isVariable) {}
140 UInt getStateCount()
const override {
return mComponent->getStateCount(); }
142 Bool isVariable()
const override {
return mIsVariable; }
144 void stamp(Matrix &AdLocal, Matrix &BdMna, Matrix &CdMna, UInt stateOffset,
145 UInt mnaVectorSize)
const override {
146 const UInt localStateCount = getStateCount();
148 const Matrix &discreteA = mComponent->getDiscreteA();
149 const Matrix &discreteB = mComponent->getDiscreteB();
150 const Matrix &outputC = mComponent->getC();
153 buildTwoTerminalInterfaceVoltageMapping(*mComponent, mnaVectorSize);
160 AdLocal.block(stateOffset, stateOffset, localStateCount, localStateCount) +=
163 const Matrix inputUpdate =
164 (discreteA + Matrix::Identity(localStateCount, localStateCount)) *
167 BdMna.block(stateOffset, 0, localStateCount, mnaVectorSize) +=
170 stampTwoTerminalCurrentInjectionMapping(K, CdMna, stateOffset, outputC);
173 void contributeMetadata(StateSpaceMetadata &metadata,
174 UInt stateOffset)
const override {
175 const UInt localStateCount = getStateCount();
177 for (
auto abcBlock : mComponent->getLocalAbcStateIndexTriples()) {
178 for (
auto &idx : abcBlock) {
179 if (idx >= localStateCount) {
180 throw std::runtime_error(
181 "SSN component returned an invalid abc state index.");
187 metadata.abcStateIndexTriples.push_back(abcBlock);
192 std::shared_ptr<EMT::VTypeSSNComp> mComponent;
193 Bool mIsVariable =
false;
198MNAStateSpaceContributor::Ptr
199MNAStateSpaceContributorFactory::create(
const MNAInterface::Ptr &component) {
204 std::dynamic_pointer_cast<EMT::Ph3::Inductor>(component)) {
205 return std::make_shared<EMTPh3InductorStateSpaceContributor>(inductor);
209 std::dynamic_pointer_cast<EMT::Ph3::Capacitor>(component)) {
210 return std::make_shared<EMTPh3CapacitorStateSpaceContributor>(capacitor);
213 if (
auto variableSsn =
214 std::dynamic_pointer_cast<EMT::Ph3::TwoTerminalVTypeVariableSSNComp>(
216 return std::make_shared<EMTPh3TwoTerminalVTypeSSNStateSpaceContributor>(
220 if (
auto ssn = std::dynamic_pointer_cast<EMT::Ph3::TwoTerminalVTypeSSNComp>(
222 return std::make_shared<EMTPh3TwoTerminalVTypeSSNStateSpaceContributor>(
226 if (std::dynamic_pointer_cast<EMT::Ph3::Resistor>(component))
229 if (std::dynamic_pointer_cast<EMT::Ph3::VoltageSource>(component))
232 throw std::invalid_argument(
233 "Unsupported component in MNA state-space extraction.");
236MNAStateSpaceContributor::List MNAStateSpaceContributorFactory::createList(
237 const MNAInterface::List &components) {
238 MNAStateSpaceContributor::List contributors;
240 for (
const auto &component : components) {
241 auto contributor = create(component);
243 contributors.push_back(contributor);