DPsim
Loading...
Searching...
No Matches
DP_Ph1_Inverter.cpp
1/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2 * EONERC, RWTH Aachen University
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7 *********************************************************************************/
8
9#include <cmath>
10#include <dpsim-models/DP/DP_Ph1_Inverter.h>
11#include <dpsim-models/MathUtils.h>
12
13using namespace CPS;
14using namespace std;
15
16DP::Ph1::Inverter::Inverter(String uid, String name, Logger::Level logLevel)
17 : MNASimPowerComp<Complex>(uid, name, true, true, logLevel) {
18 setTerminalNumber(1);
19 setVirtualNodeNumber(1);
20 **mIntfVoltage = MatrixComp::Zero(1, 1);
21 **mIntfCurrent = MatrixComp::Zero(1, 1);
22}
23
24void DP::Ph1::Inverter::setParameters(const std::vector<Int> &carrierHarms,
25 const std::vector<Int> &modulHarms,
26 Real inputVoltage, Real ratio,
27 Real phase) {
28 mCarHarms = carrierHarms;
29 mModHarms = modulHarms;
30 mVin = inputVoltage;
31 mModIdx = ratio;
32 mPhaseMod = phase;
33
34 mParametersSet = true;
35}
36
38
39void DP::Ph1::Inverter::generateFrequencies() {
40 for (Int m = 2; m <= mMaxCarrierHarm; m = m + 2) {
41 mCarHarms.push_back(m);
42 SPDLOG_LOGGER_INFO(mSLog, "Add carrier harmonic {0}", m);
43 }
44 for (Int n = -mMaxModulHarm; n <= mMaxModulHarm; n = n + 2) {
45 mModHarms.push_back(n);
46 SPDLOG_LOGGER_INFO(mSLog, "Add modulation harmonic {0}", n);
47 }
48}
49
50void DP::Ph1::Inverter::initialize(Matrix frequencies) {
52
53 SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization ---");
54
55 // Check that both lists have the same length
56 mCarHarNum = static_cast<UInt>(mCarHarms.size());
57 mModHarNum = static_cast<UInt>(mModHarms.size());
58 if (mCarHarNum != mModHarNum) {
59 throw std::invalid_argument(
60 "Number of carrier and modulation harmonics must be equal.");
61 }
62 mHarNum = mCarHarNum;
63
64 mPhasorMags = Matrix::Zero(mHarNum, 1);
65 mPhasorPhases = Matrix::Zero(mHarNum, 1);
66 mPhasorFreqs = Matrix::Zero(mHarNum, 1);
67
68 for (UInt h = 0; h < mHarNum; h++) {
71 }
72
73 // Precompute factorials
74 for (Int f = 0; f <= mMaxBesselSumIdx; f++) {
75 mFactorials.push_back(factorial(f));
76 }
77
78 for (UInt h = 0; h < mHarNum; h++) {
79 for (Int f = 0; f <= mMaxBesselSumIdx; f++)
80 mMultInvFactorials[f + mModHarms[h]] = multInvFactorial(f + mModHarms[h]);
81 }
82
83 SPDLOG_LOGGER_INFO(mSLog,
84 "\nFrequencies: \n{}"
85 "\nPhases: \n{}"
86 "\n--- End of initialization ---",
88}
89
90void DP::Ph1::Inverter::calculatePhasors() {
91 // Compute fundamental content of grid frequency
92 mVfund = mModIdx * mVin;
93 (**mIntfVoltage)(0, 0) = Complex(0, mVfund * -1);
94
95 // Compute sideband harmonics for even multiplies of carrier frequency m
96 // and odd reference signal multiplies n
97 for (UInt h = 0; h < mHarNum; h++) {
98 Real Jn = besselFirstKind_n_opt(mModHarms[h], mMaxBesselSumIdx,
99 mCarHarms[h] * mModIdx * PI / 2.);
100 //mPhasorMags(h, 0) = (4.*mVin/PI) * (Jn/mCarHarms[h]) * cos(mCarHarms[h] * PI/2.);
101 //(**mIntfVoltage)(0, h+1) = mPhasorMags(h, 0) * -1i;
102 (**mIntfVoltage)(0, h + 1) =
103 Complex(0, -1 * (4. * mVin / PI) * (Jn / mCarHarms[h]) *
104 cos(mCarHarms[h] * PI / 2.));
105 }
106
107 SPDLOG_LOGGER_DEBUG(mSLog,
108 "\n--- Phasor calculation ---"
109 "\n{}"
110 "\n{}"
111 "\n--- Phasor calculation end ---",
112 mPhasorMags, **mIntfVoltage);
113}
114
115// #### MNA functions ####
116
117void DP::Ph1::Inverter::mnaCompInitialize(Real omega, Real timeStep,
118 Attribute<Matrix>::Ptr leftVector) {
120 calculatePhasors();
121}
122
123void DP::Ph1::Inverter::mnaCompInitializeHarm(
124 Real omega, Real timeStep,
125 std::vector<Attribute<Matrix>::Ptr> leftVectors) {
126 updateMatrixNodeIndices();
127
128 mMnaTasks.push_back(std::make_shared<MnaPreStepHarm>(*this));
129 mMnaTasks.push_back(std::make_shared<MnaPostStepHarm>(*this, leftVectors));
130 **mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs);
131
132 calculatePhasors();
133}
134
136 SparseMatrixRow &systemMatrix) {
137 SPDLOG_LOGGER_INFO(mSLog, "--- Stamping into system matrix ---");
138
139 for (UInt freq = 0; freq < mNumFreqs; freq++) {
140 SPDLOG_LOGGER_INFO(mSLog, "Stamp frequency {:d}", freq);
141 if (terminalNotGrounded(0)) {
142 Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(),
143 matrixNodeIndex(0), Complex(1, 0), mNumFreqs,
144 freq);
145 Math::setMatrixElement(systemMatrix, matrixNodeIndex(0),
146 mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0),
147 mNumFreqs, freq);
148 }
149
150 if (terminalNotGrounded(0)) {
151 SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1.,
152 mVirtualNodes[0]->matrixNodeIndex(),
153 matrixNodeIndex(0));
154 SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1.,
155 matrixNodeIndex(0),
156 mVirtualNodes[0]->matrixNodeIndex());
157 }
158 }
159 SPDLOG_LOGGER_INFO(mSLog, "--- Stamping into system matrix end ---");
160}
161
162void DP::Ph1::Inverter::mnaCompApplySystemMatrixStampHarm(
163 SparseMatrixRow &systemMatrix, Int freqIdx) {
164 SPDLOG_LOGGER_INFO(mSLog, "Stamp frequency {:d}", freqIdx);
165 if (terminalNotGrounded(0)) {
166 Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(),
167 matrixNodeIndex(0), Complex(1, 0));
168 Math::setMatrixElement(systemMatrix, matrixNodeIndex(0),
169 mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0));
170 }
171
172 if (terminalNotGrounded(0)) {
173 SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1.,
174 mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0));
175 SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1.,
176 matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex());
177 }
178}
179
181 SPDLOG_LOGGER_DEBUG(mSLog, "Stamp harmonics into source vector");
182 for (UInt freq = 0; freq < mNumFreqs; freq++) {
183 if (terminalNotGrounded(0)) {
184 Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(),
185 (**mIntfVoltage)(0, freq), mNumFreqs, freq);
186
187 SPDLOG_LOGGER_DEBUG(mSLog,
188 "Add {:s} to source vector at {:d}, harmonic {:d}",
189 Logger::complexToString((**mIntfVoltage)(0, freq)),
190 mVirtualNodes[0]->matrixNodeIndex(), freq);
191 }
192 }
193}
194
195void DP::Ph1::Inverter::mnaCompApplyRightSideVectorStampHarm(
196 Matrix &rightVector) {
197 SPDLOG_LOGGER_DEBUG(mSLog, "Stamp harmonics into source vector");
198 for (UInt freq = 0; freq < mNumFreqs; freq++) {
199 if (terminalNotGrounded(0)) {
200 Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(),
201 (**mIntfVoltage)(0, freq), 1, 0, freq);
202 }
203 }
204}
205
206void DP::Ph1::Inverter::mnaCompApplyRightSideVectorStampHarm(
207 Matrix &rightVector, Int freq) {
208 Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(),
209 (**mIntfVoltage)(0, freq));
210}
211
213 AttributeBase::List &prevStepDependencies,
214 AttributeBase::List &attributeDependencies,
215 AttributeBase::List &modifiedAttributes) {
216 modifiedAttributes.push_back(mRightVector);
217 modifiedAttributes.push_back(mIntfVoltage);
218}
219
220void DP::Ph1::Inverter::mnaCompPreStep(Real time, Int timeStepCount) {
221 calculatePhasors();
222 mnaCompApplyRightSideVectorStamp(**mRightVector);
223}
224
225void DP::Ph1::Inverter::MnaPreStepHarm::execute(Real time, Int timeStepCount) {
226 mInverter.calculatePhasors();
227 mInverter.mnaCompApplyRightSideVectorStampHarm(**mInverter.mRightVector);
228}
229
231 AttributeBase::List &prevStepDependencies,
232 AttributeBase::List &attributeDependencies,
233 AttributeBase::List &modifiedAttributes,
234 Attribute<Matrix>::Ptr &leftVector) {
235 attributeDependencies.push_back(leftVector);
236 modifiedAttributes.push_back(mIntfCurrent);
237}
238
239void DP::Ph1::Inverter::mnaCompPostStep(Real time, Int timeStepCount,
240 Attribute<Matrix>::Ptr &leftVector) {}
241
242void DP::Ph1::Inverter::MnaPostStepHarm::execute(Real time, Int timeStepCount) {
243
244}
245
246// #### Math functions ####
247
249Real DP::Ph1::Inverter::besselFirstKind_n(Int n, Int k_max, Real x) const {
250 Real Jn = 0;
251 for (Int k = 0; k <= k_max; ++k) {
252 Real Jn_k = pow(-1, k) / (double)factorial(k) * multInvFactorial(k + n) *
253 pow(x / 2., 2. * k + n);
254 Jn = Jn + Jn_k;
255 }
256 return Jn;
257}
258
260Real DP::Ph1::Inverter::besselFirstKind_n_opt(Int n, Int k_max, Real x) {
261 Real Jn = 0;
262 for (Int k = 0; k <= k_max; ++k) {
263 Real Jn_k = pow(-1, k) / mFactorials[k] * mMultInvFactorials[k + n] *
264 pow(x / 2., 2. * k + n);
265 Jn = Jn + Jn_k;
266 }
267 return Jn;
268}
269
270long long DP::Ph1::Inverter::factorial(Int n) const {
271 return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
272}
273
274Real DP::Ph1::Inverter::multInvFactorial(Int n) const {
275 if (n < 0)
276 return 0;
277 else
278 return 1. / (double)factorial(n);
279}
280
281Real DP::Ph1::Inverter::multInvIntGamma(Real n) const {
282 if (n <= 0)
283 return 0;
284 else
285 return 1. / std::tgamma(n);
286}
std::vector< Int > mModHarms
Vector of modulation signal harmonics.
void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Add MNA pre step dependencies.
Real mFreqMod
system frequency (should be updated every step)
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
UInt mHarNum
Number of harmonics.
Matrix mPhasorPhases
Vector of phasor phases.
Real mPhaseCar
Carrier phase.
void initialize(Matrix frequencies) override
Initialize components with correct network frequencies.
Real besselFirstKind_n(Int n, Int k_max, Real x) const
Bessel function.
Real besselFirstKind_n_opt(Int n, Int k_max, Real x)
Bessel function using look up tables for factorials.
Inverter(String name, String uid, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and logging level.
Real mFreqCar
switching frequency (constant)
Matrix mPhasorMags
Vector of phasor magnitudes.
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
Stamps right side (source) vector.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes Component variables according to power flow data stored in Nodes.
Int mMaxBesselSumIdx
Maximum upper limit for Bessel function 1st kind summation.
Real mPhaseMod
Modulation phase.
std::vector< Int > mCarHarms
Vector of carrier signal harmonics.
Matrix mPhasorFreqs
Vector of phasor frequencies.
void mnaCompInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes internal variables of the component.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Add MNA post step dependencies.
String uid()
Returns unique id.
MNASimPowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
Attribute< Matrix >::Ptr mRightVector
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
virtual void initialize(Matrix frequencies)
Initialize components with correct network frequencies.
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
SimNode< Complex >::List mVirtualNodes
Logger::Log mSLog
Component logger.