18 throw std::invalid_argument(
19 "MNAStateSpaceExtractor requires a positive time step.");
21 mMnaVectorSize = mnaVectorSize;
24 const auto contributors =
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->contributesToUpdatedMatrices())
40 mHasUpdatedContributors =
true;
42 const auto dependencies = contributor->getAttributeDependencies();
43 mAttributeDependencies.insert(mAttributeDependencies.end(),
44 dependencies.begin(), dependencies.end());
47 mStateCount = nextStateOffset;
52 stampConstantMatrices();
53 restampUpdatedMatrices();
54 rebuildCombinedMatrices();
56 mStateMatrixValid =
false;
60void MNAStateSpaceExtractor::reset() {
67 mHasUpdatedContributors =
false;
68 mStateMatrixValid =
false;
70 mLastExtractionTime = 0.0;
71 mHasExtractionTime =
false;
73 mContributorEntries.clear();
74 mAttributeDependencies.clear();
76 mAdLocalConstant.resize(0, 0);
77 mBdMnaConstant.resize(0, 0);
78 mCdMnaConstant.resize(0, 0);
80 mAdLocalUpdated.resize(0, 0);
81 mBdMnaUpdated.resize(0, 0);
82 mCdMnaUpdated.resize(0, 0);
84 mAdLocal.resize(0, 0);
92 Bool variableModelChanged,
93 Bool systemMatrixChanged,
Real time) {
95 throw std::logic_error(
96 "MNAStateSpaceExtractor::extract() called before initialize().");
98 mLastExtractionTime = time;
99 mHasExtractionTime =
true;
101 if (mStateCount == 0) {
102 mStateMatrixValid =
true;
106 Bool updatedMatricesChanged = variableModelChanged;
108 if (!updatedMatricesChanged) {
109 for (
const auto &entry : mContributorEntries) {
110 if (entry.contributor->contributesToUpdatedMatrices() &&
111 entry.contributor->requiresUpdate()) {
112 updatedMatricesChanged =
true;
118 if (updatedMatricesChanged && mHasUpdatedContributors) {
119 restampUpdatedMatrices();
120 rebuildCombinedMatrices();
121 mStateMatrixValid =
false;
124 if (systemMatrixChanged)
125 mStateMatrixValid =
false;
127 if (!mStateMatrixValid)
128 computeStateMatrix(linearSolver);
131void MNAStateSpaceExtractor::allocateMatrices() {
132 mAdLocalConstant = Matrix::Zero(mStateCount, mStateCount);
133 mBdMnaConstant = Matrix::Zero(mStateCount, mMnaVectorSize);
134 mCdMnaConstant = Matrix::Zero(mMnaVectorSize, mStateCount);
136 mAdLocalUpdated = Matrix::Zero(mStateCount, mStateCount);
137 mBdMnaUpdated = Matrix::Zero(mStateCount, mMnaVectorSize);
138 mCdMnaUpdated = Matrix::Zero(mMnaVectorSize, mStateCount);
140 mAdLocal = Matrix::Zero(mStateCount, mStateCount);
141 mBdMna = Matrix::Zero(mStateCount, mMnaVectorSize);
142 mCdMna = Matrix::Zero(mMnaVectorSize, mStateCount);
144 mAd = Matrix::Zero(mStateCount, mStateCount);
147void MNAStateSpaceExtractor::collectMetadata() {
148 mMetadata = StateSpaceMetadata{};
151 for (
const auto &entry : mContributorEntries) {
152 entry.contributor->contributeMetadata(mMetadata, entry.stateOffset);
155 for (
UInt idx = 0; idx < mStateCount; ++idx) {
156 if (mMetadata.stateNames[idx].empty())
157 mMetadata.stateNames[idx] =
"x" + std::to_string(idx);
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.");
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.");
176void MNAStateSpaceExtractor::stampConstantMatrices() {
177 mAdLocalConstant.setZero();
178 mBdMnaConstant.setZero();
179 mCdMnaConstant.setZero();
181 for (
const auto &entry : mContributorEntries) {
182 if (!entry.contributor->contributesToUpdatedMatrices()) {
183 entry.contributor->stamp(mAdLocalConstant, mBdMnaConstant, mCdMnaConstant,
184 entry.stateOffset, mMnaVectorSize);
189void MNAStateSpaceExtractor::restampUpdatedMatrices() {
190 mAdLocalUpdated.setZero();
191 mBdMnaUpdated.setZero();
192 mCdMnaUpdated.setZero();
194 for (
const auto &entry : mContributorEntries) {
195 if (entry.contributor->contributesToUpdatedMatrices()) {
196 entry.contributor->stamp(mAdLocalUpdated, mBdMnaUpdated, mCdMnaUpdated,
197 entry.stateOffset, mMnaVectorSize);
202void MNAStateSpaceExtractor::rebuildCombinedMatrices() {
203 mAdLocal = mAdLocalConstant + mAdLocalUpdated;
204 mBdMna = mBdMnaConstant + mBdMnaUpdated;
205 mCdMna = mCdMnaConstant + mCdMnaUpdated;
208void MNAStateSpaceExtractor::computeStateMatrix(
212 const Matrix mnaToStateSolution = linearSolver.solve(rhs);
214 if (mnaToStateSolution.rows() != mMnaVectorSize ||
215 mnaToStateSolution.cols() != mStateCount) {
216 throw std::runtime_error(
217 "MNAStateSpaceExtractor: linear solver returned unexpected "
221 mAd = mAdLocal + mBdMna * mnaToStateSolution;
223 mStateMatrixValid =
true;
static MNAStateSpaceContributor::List createList(const CPS::MNAInterface::List &components)