4#include <dpsim/DirectLinearSolver.h>
5#include <dpsim/MNAStateSpaceExtractor.h>
11void MNAStateSpaceExtractor::initialize(
12 const CPS::MNAInterface::List &components, UInt mnaVectorSize,
17 throw std::invalid_argument(
18 "MNAStateSpaceExtractor requires a positive time step.");
20 mMnaVectorSize = mnaVectorSize;
23 const auto contributors =
24 MNAStateSpaceContributorFactory::createList(components);
26 UInt nextStateOffset = 0;
28 for (
const auto &contributor : contributors) {
29 const UInt localStateCount = contributor->getStateCount();
31 ContributorEntry entry;
32 entry.contributor = contributor;
33 entry.stateOffset = nextStateOffset;
34 mContributorEntries.push_back(entry);
36 nextStateOffset += localStateCount;
38 if (contributor->isVariable())
39 mHasVariableContributors =
true;
42 mStateCount = nextStateOffset;
47 stampStaticMatrices();
48 restampVariableMatrices();
49 rebuildCombinedMatrices();
51 mStateMatrixValid =
false;
55void MNAStateSpaceExtractor::reset() {
62 mHasVariableContributors =
false;
63 mStateMatrixValid =
false;
64 mMetadata = StateSpaceMetadata{};
65 mLastExtractionTime = 0.0;
66 mHasExtractionTime =
false;
68 mContributorEntries.clear();
70 mAdLocalStatic.resize(0, 0);
71 mBdMnaStatic.resize(0, 0);
72 mCdMnaStatic.resize(0, 0);
74 mAdLocalVariable.resize(0, 0);
75 mBdMnaVariable.resize(0, 0);
76 mCdMnaVariable.resize(0, 0);
78 mAdLocal.resize(0, 0);
86 Bool variableModelChanged,
87 Bool systemMatrixChanged, Real time) {
89 throw std::logic_error(
90 "MNAStateSpaceExtractor::extract() called before initialize().");
92 mLastExtractionTime = time;
93 mHasExtractionTime =
true;
95 if (mStateCount == 0) {
96 mStateMatrixValid =
true;
100 if (variableModelChanged && mHasVariableContributors) {
101 restampVariableMatrices();
102 rebuildCombinedMatrices();
103 mStateMatrixValid =
false;
106 if (systemMatrixChanged)
107 mStateMatrixValid =
false;
109 if (!mStateMatrixValid)
110 computeStateMatrix(linearSolver);
113void MNAStateSpaceExtractor::allocateMatrices() {
114 mAdLocalStatic = Matrix::Zero(mStateCount, mStateCount);
115 mBdMnaStatic = Matrix::Zero(mStateCount, mMnaVectorSize);
116 mCdMnaStatic = Matrix::Zero(mMnaVectorSize, mStateCount);
118 mAdLocalVariable = Matrix::Zero(mStateCount, mStateCount);
119 mBdMnaVariable = Matrix::Zero(mStateCount, mMnaVectorSize);
120 mCdMnaVariable = Matrix::Zero(mMnaVectorSize, mStateCount);
122 mAdLocal = Matrix::Zero(mStateCount, mStateCount);
123 mBdMna = Matrix::Zero(mStateCount, mMnaVectorSize);
124 mCdMna = Matrix::Zero(mMnaVectorSize, mStateCount);
126 mAd = Matrix::Zero(mStateCount, mStateCount);
129void MNAStateSpaceExtractor::collectMetadata() {
130 mMetadata = StateSpaceMetadata{};
132 for (
const auto &entry : mContributorEntries) {
133 entry.contributor->contributeMetadata(mMetadata, entry.stateOffset);
136 for (
const auto &abcBlock : mMetadata.abcStateIndexTriples) {
137 for (
const auto idx : abcBlock) {
138 if (idx >= mStateCount) {
139 throw std::runtime_error(
140 "MNAStateSpaceExtractor: abc metadata index is outside the "
141 "extracted state vector.");
147void MNAStateSpaceExtractor::stampStaticMatrices() {
148 mAdLocalStatic.setZero();
149 mBdMnaStatic.setZero();
150 mCdMnaStatic.setZero();
152 for (
const auto &entry : mContributorEntries) {
153 if (!entry.contributor->isVariable()) {
154 entry.contributor->stamp(mAdLocalStatic, mBdMnaStatic, mCdMnaStatic,
155 entry.stateOffset, mMnaVectorSize);
160void MNAStateSpaceExtractor::restampVariableMatrices() {
161 mAdLocalVariable.setZero();
162 mBdMnaVariable.setZero();
163 mCdMnaVariable.setZero();
165 for (
const auto &entry : mContributorEntries) {
166 if (entry.contributor->isVariable()) {
167 entry.contributor->stamp(mAdLocalVariable, mBdMnaVariable, mCdMnaVariable,
168 entry.stateOffset, mMnaVectorSize);
173void MNAStateSpaceExtractor::rebuildCombinedMatrices() {
174 mAdLocal = mAdLocalStatic + mAdLocalVariable;
175 mBdMna = mBdMnaStatic + mBdMnaVariable;
176 mCdMna = mCdMnaStatic + mCdMnaVariable;
179void MNAStateSpaceExtractor::computeStateMatrix(
183 const Matrix mnaToStateSolution = linearSolver.solve(rhs);
185 if (mnaToStateSolution.rows() != mMnaVectorSize ||
186 mnaToStateSolution.cols() != mStateCount) {
187 throw std::runtime_error(
188 "MNAStateSpaceExtractor: linear solver returned unexpected "
192 mAd = mAdLocal + mBdMna * mnaToStateSolution;
194 mStateMatrixValid =
true;