DPsim
Loading...
Searching...
No Matches
MNAStateSpaceExtractor.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University
2// SPDX-License-Identifier: MPL-2.0
3
6
7#include <stdexcept>
8#include <string>
9
10namespace DPsim {
11
13 const CPS::MNAInterface::List &components, UInt mnaVectorSize,
14 Real timeStep) {
15 reset();
16
17 if (timeStep <= 0.0)
18 throw std::invalid_argument(
19 "MNAStateSpaceExtractor requires a positive time step.");
20
21 mMnaVectorSize = mnaVectorSize;
22 mTimeStep = timeStep;
23
24 const auto contributors =
26
27 UInt nextStateOffset = 0;
28
29 for (const auto &contributor : contributors) {
30 const UInt localStateCount = contributor->getStateCount();
31
32 ContributorEntry entry;
33 entry.contributor = contributor;
34 entry.stateOffset = nextStateOffset;
35 mContributorEntries.push_back(entry);
36
37 nextStateOffset += localStateCount;
38
39 if (contributor->contributesToUpdatedMatrices())
40 mHasUpdatedContributors = true;
41
42 const auto dependencies = contributor->getAttributeDependencies();
43 mAttributeDependencies.insert(mAttributeDependencies.end(),
44 dependencies.begin(), dependencies.end());
45 }
46
47 mStateCount = nextStateOffset;
48
49 allocateMatrices();
50 collectMetadata();
51
52 stampConstantMatrices();
53 restampUpdatedMatrices();
54 rebuildCombinedMatrices();
55
56 mStateMatrixValid = false;
57 mInitialized = true;
58}
59
60void MNAStateSpaceExtractor::reset() {
61 mInitialized = false;
62
63 mMnaVectorSize = 0;
64 mStateCount = 0;
65 mTimeStep = 0.0;
66
67 mHasUpdatedContributors = false;
68 mStateMatrixValid = false;
69 mMetadata = StateSpaceMetadata{};
70 mLastExtractionTime = 0.0;
71 mHasExtractionTime = false;
72
73 mContributorEntries.clear();
74 mAttributeDependencies.clear();
75
76 mAdLocalConstant.resize(0, 0);
77 mBdMnaConstant.resize(0, 0);
78 mCdMnaConstant.resize(0, 0);
79
80 mAdLocalUpdated.resize(0, 0);
81 mBdMnaUpdated.resize(0, 0);
82 mCdMnaUpdated.resize(0, 0);
83
84 mAdLocal.resize(0, 0);
85 mBdMna.resize(0, 0);
86 mCdMna.resize(0, 0);
87
88 mAd.resize(0, 0);
89}
90
92 Bool variableModelChanged,
93 Bool systemMatrixChanged, Real time) {
94 if (!mInitialized)
95 throw std::logic_error(
96 "MNAStateSpaceExtractor::extract() called before initialize().");
97
98 mLastExtractionTime = time;
99 mHasExtractionTime = true;
100
101 if (mStateCount == 0) {
102 mStateMatrixValid = true;
103 return;
104 }
105
106 Bool updatedMatricesChanged = variableModelChanged;
107
108 if (!updatedMatricesChanged) {
109 for (const auto &entry : mContributorEntries) {
110 if (entry.contributor->contributesToUpdatedMatrices() &&
111 entry.contributor->requiresUpdate()) {
112 updatedMatricesChanged = true;
113 break;
114 }
115 }
116 }
117
118 if (updatedMatricesChanged && mHasUpdatedContributors) {
119 restampUpdatedMatrices();
120 rebuildCombinedMatrices();
121 mStateMatrixValid = false;
122 }
123
124 if (systemMatrixChanged)
125 mStateMatrixValid = false;
126
127 if (!mStateMatrixValid)
128 computeStateMatrix(linearSolver);
129}
130
131void MNAStateSpaceExtractor::allocateMatrices() {
132 mAdLocalConstant = Matrix::Zero(mStateCount, mStateCount);
133 mBdMnaConstant = Matrix::Zero(mStateCount, mMnaVectorSize);
134 mCdMnaConstant = Matrix::Zero(mMnaVectorSize, mStateCount);
135
136 mAdLocalUpdated = Matrix::Zero(mStateCount, mStateCount);
137 mBdMnaUpdated = Matrix::Zero(mStateCount, mMnaVectorSize);
138 mCdMnaUpdated = Matrix::Zero(mMnaVectorSize, mStateCount);
139
140 mAdLocal = Matrix::Zero(mStateCount, mStateCount);
141 mBdMna = Matrix::Zero(mStateCount, mMnaVectorSize);
142 mCdMna = Matrix::Zero(mMnaVectorSize, mStateCount);
143
144 mAd = Matrix::Zero(mStateCount, mStateCount);
145}
146
147void MNAStateSpaceExtractor::collectMetadata() {
148 mMetadata = StateSpaceMetadata{};
149 mMetadata.stateNames.resize(mStateCount);
150
151 for (const auto &entry : mContributorEntries) {
152 entry.contributor->contributeMetadata(mMetadata, entry.stateOffset);
153 }
154
155 for (UInt idx = 0; idx < mStateCount; ++idx) {
156 if (mMetadata.stateNames[idx].empty())
157 mMetadata.stateNames[idx] = "x" + std::to_string(idx);
158 }
159
160 for (const auto &abcBlock : mMetadata.abcStateBlocks) {
161 if (abcBlock.name.empty()) {
162 throw std::runtime_error(
163 "MNAStateSpaceExtractor: abc metadata block has an empty name.");
164 }
165
166 for (const auto idx : abcBlock.indices) {
167 if (idx >= mStateCount) {
168 throw std::runtime_error(
169 "MNAStateSpaceExtractor: abc metadata index is outside the "
170 "extracted state vector.");
171 }
172 }
173 }
174}
175
176void MNAStateSpaceExtractor::stampConstantMatrices() {
177 mAdLocalConstant.setZero();
178 mBdMnaConstant.setZero();
179 mCdMnaConstant.setZero();
180
181 for (const auto &entry : mContributorEntries) {
182 if (!entry.contributor->contributesToUpdatedMatrices()) {
183 entry.contributor->stamp(mAdLocalConstant, mBdMnaConstant, mCdMnaConstant,
184 entry.stateOffset, mMnaVectorSize);
185 }
186 }
187}
188
189void MNAStateSpaceExtractor::restampUpdatedMatrices() {
190 mAdLocalUpdated.setZero();
191 mBdMnaUpdated.setZero();
192 mCdMnaUpdated.setZero();
193
194 for (const auto &entry : mContributorEntries) {
195 if (entry.contributor->contributesToUpdatedMatrices()) {
196 entry.contributor->stamp(mAdLocalUpdated, mBdMnaUpdated, mCdMnaUpdated,
197 entry.stateOffset, mMnaVectorSize);
198 }
199 }
200}
201
202void MNAStateSpaceExtractor::rebuildCombinedMatrices() {
203 mAdLocal = mAdLocalConstant + mAdLocalUpdated;
204 mBdMna = mBdMnaConstant + mBdMnaUpdated;
205 mCdMna = mCdMnaConstant + mCdMnaUpdated;
206}
207
208void MNAStateSpaceExtractor::computeStateMatrix(
209 DirectLinearSolver &linearSolver) {
210 // DirectLinearSolver::solve takes a non-const Matrix&, so use a local copy.
211 Matrix rhs = mCdMna;
212 const Matrix mnaToStateSolution = linearSolver.solve(rhs);
213
214 if (mnaToStateSolution.rows() != mMnaVectorSize ||
215 mnaToStateSolution.cols() != mStateCount) {
216 throw std::runtime_error(
217 "MNAStateSpaceExtractor: linear solver returned unexpected "
218 "dimensions.");
219 }
220
221 mAd = mAdLocal + mBdMna * mnaToStateSolution;
222
223 mStateMatrixValid = true;
224}
225
226} // namespace DPsim
std::vector< Ptr > List
static MNAStateSpaceContributor::List createList(const CPS::MNAInterface::List &components)
void initialize(const CPS::MNAInterface::List &components, UInt mnaVectorSize, Real timeStep)
void extract(DirectLinearSolver &linearSolver, Bool variableModelChanged, Bool systemMatrixChanged, Real time)
CPS::Real Real
Definition Definitions.h:18
CPS::Matrix Matrix
Definition Definitions.h:24
CPS::Bool Bool
Definition Definitions.h:21
CPS::UInt UInt
Definition Definitions.h:23
std::vector< String > stateNames
Names of extracted states in native extracted-state order.