DPsim
Loading...
Searching...
No Matches
MNAStateSpaceExtractor.cpp
1// SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University
2// SPDX-License-Identifier: MPL-2.0
3
4#include <dpsim/DirectLinearSolver.h>
5#include <dpsim/MNAStateSpaceExtractor.h>
6
7#include <stdexcept>
8
9namespace DPsim {
10
11void MNAStateSpaceExtractor::initialize(
12 const CPS::MNAInterface::List &components, UInt mnaVectorSize,
13 Real timeStep) {
14 reset();
15
16 if (timeStep <= 0.0)
17 throw std::invalid_argument(
18 "MNAStateSpaceExtractor requires a positive time step.");
19
20 mMnaVectorSize = mnaVectorSize;
21 mTimeStep = timeStep;
22
23 const auto contributors =
24 MNAStateSpaceContributorFactory::createList(components);
25
26 UInt nextStateOffset = 0;
27
28 for (const auto &contributor : contributors) {
29 const UInt localStateCount = contributor->getStateCount();
30
31 ContributorEntry entry;
32 entry.contributor = contributor;
33 entry.stateOffset = nextStateOffset;
34 mContributorEntries.push_back(entry);
35
36 nextStateOffset += localStateCount;
37
38 if (contributor->isVariable())
39 mHasVariableContributors = true;
40 }
41
42 mStateCount = nextStateOffset;
43
44 allocateMatrices();
45
46 stampStaticMatrices();
47 restampVariableMatrices();
48 rebuildCombinedMatrices();
49
50 mStateMatrixValid = false;
51 mInitialized = true;
52}
53
54void MNAStateSpaceExtractor::reset() {
55 mInitialized = false;
56
57 mMnaVectorSize = 0;
58 mStateCount = 0;
59 mTimeStep = 0.0;
60
61 mHasVariableContributors = false;
62 mStateMatrixValid = false;
63
64 mContributorEntries.clear();
65
66 mAdLocalStatic.resize(0, 0);
67 mBdMnaStatic.resize(0, 0);
68 mCdMnaStatic.resize(0, 0);
69
70 mAdLocalVariable.resize(0, 0);
71 mBdMnaVariable.resize(0, 0);
72 mCdMnaVariable.resize(0, 0);
73
74 mAdLocal.resize(0, 0);
75 mBdMna.resize(0, 0);
76 mCdMna.resize(0, 0);
77
78 mAd.resize(0, 0);
79}
80
81void MNAStateSpaceExtractor::extract(DirectLinearSolver &linearSolver,
82 Bool variableModelChanged,
83 Bool systemMatrixChanged) {
84 if (!mInitialized)
85 throw std::logic_error(
86 "MNAStateSpaceExtractor::extract() called before initialize().");
87
88 if (mStateCount == 0) {
89 mStateMatrixValid = true;
90 return;
91 }
92
93 if (variableModelChanged && mHasVariableContributors) {
94 restampVariableMatrices();
95 rebuildCombinedMatrices();
96 mStateMatrixValid = false;
97 }
98
99 if (systemMatrixChanged)
100 mStateMatrixValid = false;
101
102 if (!mStateMatrixValid)
103 computeStateMatrix(linearSolver);
104}
105
106void MNAStateSpaceExtractor::allocateMatrices() {
107 mAdLocalStatic = Matrix::Zero(mStateCount, mStateCount);
108 mBdMnaStatic = Matrix::Zero(mStateCount, mMnaVectorSize);
109 mCdMnaStatic = Matrix::Zero(mMnaVectorSize, mStateCount);
110
111 mAdLocalVariable = Matrix::Zero(mStateCount, mStateCount);
112 mBdMnaVariable = Matrix::Zero(mStateCount, mMnaVectorSize);
113 mCdMnaVariable = Matrix::Zero(mMnaVectorSize, mStateCount);
114
115 mAdLocal = Matrix::Zero(mStateCount, mStateCount);
116 mBdMna = Matrix::Zero(mStateCount, mMnaVectorSize);
117 mCdMna = Matrix::Zero(mMnaVectorSize, mStateCount);
118
119 mAd = Matrix::Zero(mStateCount, mStateCount);
120}
121
122void MNAStateSpaceExtractor::stampStaticMatrices() {
123 mAdLocalStatic.setZero();
124 mBdMnaStatic.setZero();
125 mCdMnaStatic.setZero();
126
127 for (const auto &entry : mContributorEntries) {
128 if (!entry.contributor->isVariable()) {
129 entry.contributor->stamp(mAdLocalStatic, mBdMnaStatic, mCdMnaStatic,
130 entry.stateOffset, mMnaVectorSize);
131 }
132 }
133}
134
135void MNAStateSpaceExtractor::restampVariableMatrices() {
136 mAdLocalVariable.setZero();
137 mBdMnaVariable.setZero();
138 mCdMnaVariable.setZero();
139
140 for (const auto &entry : mContributorEntries) {
141 if (entry.contributor->isVariable()) {
142 entry.contributor->stamp(mAdLocalVariable, mBdMnaVariable, mCdMnaVariable,
143 entry.stateOffset, mMnaVectorSize);
144 }
145 }
146}
147
148void MNAStateSpaceExtractor::rebuildCombinedMatrices() {
149 mAdLocal = mAdLocalStatic + mAdLocalVariable;
150 mBdMna = mBdMnaStatic + mBdMnaVariable;
151 mCdMna = mCdMnaStatic + mCdMnaVariable;
152}
153
154void MNAStateSpaceExtractor::computeStateMatrix(
155 DirectLinearSolver &linearSolver) {
156 // DirectLinearSolver::solve takes a non-const Matrix&, so use a local copy.
157 Matrix rhs = mCdMna;
158 const Matrix mnaToStateSolution = linearSolver.solve(rhs);
159
160 if (mnaToStateSolution.rows() != mMnaVectorSize ||
161 mnaToStateSolution.cols() != mStateCount) {
162 throw std::runtime_error(
163 "MNAStateSpaceExtractor: linear solver returned unexpected "
164 "dimensions.");
165 }
166
167 mAd = mAdLocal + mBdMna * mnaToStateSolution;
168
169 mStateMatrixValid = true;
170}
171
172} // namespace DPsim