4#include <dpsim/DirectLinearSolver.h>
5#include <dpsim/MNAStateSpaceExtractor.h>
12void MNAStateSpaceExtractor::initialize(
13 const CPS::MNAInterface::List &components, UInt mnaVectorSize,
18 throw std::invalid_argument(
19 "MNAStateSpaceExtractor requires a positive time step.");
21 mMnaVectorSize = mnaVectorSize;
24 const auto contributors =
25 MNAStateSpaceContributorFactory::createList(components);
27 UInt nextStateOffset = 0;
29 for (
const auto &contributor : contributors) {
30 const UInt localStateCount = contributor->getStateCount();
32 ContributorEntry entry;
33 entry.contributor = contributor;
34 entry.stateOffset = nextStateOffset;
35 mContributorEntries.push_back(entry);
37 nextStateOffset += localStateCount;
39 if (contributor->isVariable())
40 mHasVariableContributors =
true;
43 mStateCount = nextStateOffset;
48 stampStaticMatrices();
49 restampVariableMatrices();
50 rebuildCombinedMatrices();
52 mStateMatrixValid =
false;
56void MNAStateSpaceExtractor::reset() {
63 mHasVariableContributors =
false;
64 mStateMatrixValid =
false;
65 mMetadata = StateSpaceMetadata{};
66 mLastExtractionTime = 0.0;
67 mHasExtractionTime =
false;
69 mContributorEntries.clear();
71 mAdLocalStatic.resize(0, 0);
72 mBdMnaStatic.resize(0, 0);
73 mCdMnaStatic.resize(0, 0);
75 mAdLocalVariable.resize(0, 0);
76 mBdMnaVariable.resize(0, 0);
77 mCdMnaVariable.resize(0, 0);
79 mAdLocal.resize(0, 0);
87 Bool variableModelChanged,
88 Bool systemMatrixChanged, Real time) {
90 throw std::logic_error(
91 "MNAStateSpaceExtractor::extract() called before initialize().");
93 mLastExtractionTime = time;
94 mHasExtractionTime =
true;
96 if (mStateCount == 0) {
97 mStateMatrixValid =
true;
101 if (variableModelChanged && mHasVariableContributors) {
102 restampVariableMatrices();
103 rebuildCombinedMatrices();
104 mStateMatrixValid =
false;
107 if (systemMatrixChanged)
108 mStateMatrixValid =
false;
110 if (!mStateMatrixValid)
111 computeStateMatrix(linearSolver);
114void MNAStateSpaceExtractor::allocateMatrices() {
115 mAdLocalStatic = Matrix::Zero(mStateCount, mStateCount);
116 mBdMnaStatic = Matrix::Zero(mStateCount, mMnaVectorSize);
117 mCdMnaStatic = Matrix::Zero(mMnaVectorSize, mStateCount);
119 mAdLocalVariable = Matrix::Zero(mStateCount, mStateCount);
120 mBdMnaVariable = Matrix::Zero(mStateCount, mMnaVectorSize);
121 mCdMnaVariable = Matrix::Zero(mMnaVectorSize, mStateCount);
123 mAdLocal = Matrix::Zero(mStateCount, mStateCount);
124 mBdMna = Matrix::Zero(mStateCount, mMnaVectorSize);
125 mCdMna = Matrix::Zero(mMnaVectorSize, mStateCount);
127 mAd = Matrix::Zero(mStateCount, mStateCount);
130void MNAStateSpaceExtractor::collectMetadata() {
131 mMetadata = StateSpaceMetadata{};
132 mMetadata.stateNames.resize(mStateCount);
134 for (
const auto &entry : mContributorEntries) {
135 entry.contributor->contributeMetadata(mMetadata, entry.stateOffset);
138 for (UInt idx = 0; idx < mStateCount; ++idx) {
139 if (mMetadata.stateNames[idx].empty())
140 mMetadata.stateNames[idx] =
"x" + std::to_string(idx);
143 for (
const auto &abcBlock : mMetadata.abcStateBlocks) {
144 if (abcBlock.name.empty()) {
145 throw std::runtime_error(
146 "MNAStateSpaceExtractor: abc metadata block has an empty name.");
149 for (
const auto idx : abcBlock.indices) {
150 if (idx >= mStateCount) {
151 throw std::runtime_error(
152 "MNAStateSpaceExtractor: abc metadata index is outside the "
153 "extracted state vector.");
159void MNAStateSpaceExtractor::stampStaticMatrices() {
160 mAdLocalStatic.setZero();
161 mBdMnaStatic.setZero();
162 mCdMnaStatic.setZero();
164 for (
const auto &entry : mContributorEntries) {
165 if (!entry.contributor->isVariable()) {
166 entry.contributor->stamp(mAdLocalStatic, mBdMnaStatic, mCdMnaStatic,
167 entry.stateOffset, mMnaVectorSize);
172void MNAStateSpaceExtractor::restampVariableMatrices() {
173 mAdLocalVariable.setZero();
174 mBdMnaVariable.setZero();
175 mCdMnaVariable.setZero();
177 for (
const auto &entry : mContributorEntries) {
178 if (entry.contributor->isVariable()) {
179 entry.contributor->stamp(mAdLocalVariable, mBdMnaVariable, mCdMnaVariable,
180 entry.stateOffset, mMnaVectorSize);
185void MNAStateSpaceExtractor::rebuildCombinedMatrices() {
186 mAdLocal = mAdLocalStatic + mAdLocalVariable;
187 mBdMna = mBdMnaStatic + mBdMnaVariable;
188 mCdMna = mCdMnaStatic + mCdMnaVariable;
191void MNAStateSpaceExtractor::computeStateMatrix(
195 const Matrix mnaToStateSolution = linearSolver.solve(rhs);
197 if (mnaToStateSolution.rows() != mMnaVectorSize ||
198 mnaToStateSolution.cols() != mStateCount) {
199 throw std::runtime_error(
200 "MNAStateSpaceExtractor: linear solver returned unexpected "
204 mAd = mAdLocal + mBdMna * mnaToStateSolution;
206 mStateMatrixValid =
true;