DPsim
Loading...
Searching...
No Matches
StateSpaceModalAnalysis.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 <Eigen/Eigenvalues>
5#include <dpsim/StateSpaceModalAnalysis.h>
6#include <stdexcept>
7
8namespace DPsim {
9
10StateSpaceModalAnalysis::StateSpaceModalAnalysis(
11 const MNAStateSpaceExtractor &extractor)
12 : mExtractor(extractor) {}
13
15 if (!mExtractor.isInitialized())
16 throw std::logic_error("StateSpaceModalAnalysis requires an initialized "
17 "MNAStateSpaceExtractor.");
18
19 const Matrix &Ad = mExtractor.getDiscreteStateMatrix();
20
21 if (Ad.rows() == 0) {
22 mDiscreteEigenvalues.resize(0);
23 mContinuousEigenvalues.resize(0);
24 return;
25 }
26
27 Eigen::EigenSolver<Matrix> eigenSolver(Ad, false);
28
29 if (eigenSolver.info() != Eigen::Success)
30 throw std::runtime_error(
31 "StateSpaceModalAnalysis: eigenvalue computation failed.");
32
33 mDiscreteEigenvalues = eigenSolver.eigenvalues();
34
35 mContinuousEigenvalues.resize(mDiscreteEigenvalues.rows());
36
37 for (Eigen::Index idx = 0; idx < mDiscreteEigenvalues.rows(); ++idx)
38 mContinuousEigenvalues(idx) =
39 mapDiscreteToContinuous(mDiscreteEigenvalues(idx));
40}
41
42CPS::Complex
43StateSpaceModalAnalysis::mapDiscreteToContinuous(const CPS::Complex &z) const {
44 const CPS::Complex one(1.0, 0.0);
45 const CPS::Complex denominator = z + one;
46
47 if (std::abs(denominator) <= DOUBLE_EPSILON)
48 return CPS::Complex(std::numeric_limits<Real>::infinity(), 0.0);
49
50 return (2.0 / mExtractor.getTimeStep()) * (z - one) / denominator;
51}
52
53} // namespace DPsim
void update()
Update modal quantities from the current extracted state matrix.