DPsim
Loading...
Searching...
No Matches
DP_Ph1_Inductor.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 <dpsim-models/DP/DP_Ph1_Inductor.h>
10
11using namespace CPS;
12
13DP::Ph1::Inductor::Inductor(String uid, String name, Logger::Level logLevel)
14 : MNASimPowerComp<Complex>(uid, name, true, true, logLevel),
15 Base::Ph1::Inductor(mAttributes) {
16 mEquivCurrent = {0, 0};
17 **mIntfVoltage = MatrixComp::Zero(1, 1);
18 **mIntfCurrent = MatrixComp::Zero(1, 1);
19 setTerminalNumber(2);
20}
21
22SimPowerComp<Complex>::Ptr DP::Ph1::Inductor::clone(String name) {
23 auto copy = Inductor::make(name, mLogLevel);
24 copy->setParameters(**mInductance);
25 return copy;
26}
27
28void DP::Ph1::Inductor::initialize(Matrix frequencies) {
30
31 mEquivCurrent = MatrixComp::Zero(mNumFreqs, 1);
32 mEquivCond = MatrixComp::Zero(mNumFreqs, 1);
33 mPrevCurrFac = MatrixComp::Zero(mNumFreqs, 1);
34}
35
37
38 Real omega = 2. * PI * frequency;
39 Complex impedance = {0, omega * **mInductance};
40 (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0);
41 (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance;
42
43 SPDLOG_LOGGER_INFO(mSLog,
44 "\nInductance [H]: {:s}"
45 "\nImpedance [Ohm]: {:s}",
46 Logger::realToString(**mInductance),
47 Logger::complexToString(impedance));
48 SPDLOG_LOGGER_INFO(mSLog,
49 "\n--- Initialization from powerflow ---"
50 "\nVoltage across: {:s}"
51 "\nCurrent: {:s}"
52 "\nTerminal 0 voltage: {:s}"
53 "\nTerminal 1 voltage: {:s}"
54 "\n--- Initialization from powerflow finished ---",
55 Logger::phasorToString((**mIntfVoltage)(0, 0)),
56 Logger::phasorToString((**mIntfCurrent)(0, 0)),
57 Logger::phasorToString(initialSingleVoltage(0)),
58 Logger::phasorToString(initialSingleVoltage(1)));
59}
60
61// #### MNA functions ####
62
63void DP::Ph1::Inductor::initVars(Real timeStep) {
64 for (UInt freq = 0; freq < mNumFreqs; freq++) {
65 Real a = timeStep / (2. * **mInductance);
66 Real b = timeStep * 2. * PI * mFrequencies(freq, 0) / 2.;
67
68 Real equivCondReal = a / (1. + b * b);
69 Real equivCondImag = -a * b / (1. + b * b);
70 mEquivCond(freq, 0) = {equivCondReal, equivCondImag};
71 Real preCurrFracReal = (1. - b * b) / (1. + b * b);
72 Real preCurrFracImag = (-2. * b) / (1. + b * b);
73 mPrevCurrFac(freq, 0) = {preCurrFracReal, preCurrFracImag};
74
75 // In steady-state, these variables should not change
76 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
77 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
78 (**mIntfCurrent)(0, freq) =
79 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
80 mEquivCurrent(freq, 0);
81 }
82}
83
84void DP::Ph1::Inductor::mnaCompInitialize(Real omega, Real timeStep,
85 Attribute<Matrix>::Ptr leftVector) {
87 initVars(timeStep);
88
89 SPDLOG_LOGGER_INFO(mSLog,
90 "\n--- MNA initialization ---"
91 "\nInitial voltage {:s}"
92 "\nInitial current {:s}"
93 "\nEquiv. current {:s}"
94 "\n--- MNA initialization finished ---",
95 Logger::phasorToString((**mIntfVoltage)(0, 0)),
96 Logger::phasorToString((**mIntfCurrent)(0, 0)),
97 Logger::complexToString(mEquivCurrent(0, 0)));
98}
99
100void DP::Ph1::Inductor::mnaCompInitializeHarm(
101 Real omega, Real timeStep,
102 std::vector<Attribute<Matrix>::Ptr> leftVectors) {
103 updateMatrixNodeIndices();
104
105 initVars(timeStep);
106
107 mMnaTasks.push_back(std::make_shared<MnaPreStepHarm>(*this));
108 mMnaTasks.push_back(std::make_shared<MnaPostStepHarm>(*this, leftVectors));
109 **mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs);
110}
111
113 SparseMatrixRow &systemMatrix) {
114 for (UInt freq = 0; freq < mNumFreqs; freq++) {
115 MNAStampUtils::stampAdmittance(
116 mEquivCond(freq, 0), systemMatrix, matrixNodeIndex(0),
117 matrixNodeIndex(1), terminalNotGrounded(0), terminalNotGrounded(1),
118 mSLog, mNumFreqs, freq);
119 }
120}
121
122void DP::Ph1::Inductor::mnaCompApplySystemMatrixStampHarm(
123 SparseMatrixRow &systemMatrix, Int freqIdx) {
124 MNAStampUtils::stampAdmittance(mEquivCond(freqIdx, 0), systemMatrix,
125 matrixNodeIndex(0), matrixNodeIndex(1),
126 terminalNotGrounded(0), terminalNotGrounded(1),
127 mSLog);
128}
129
131 for (UInt freq = 0; freq < mNumFreqs; freq++) {
132 // Calculate equivalent current source for next time step
133 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
134 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
135
136 if (terminalNotGrounded(0))
137 Math::setVectorElement(rightVector, matrixNodeIndex(0),
138 mEquivCurrent(freq, 0), mNumFreqs, freq);
139 if (terminalNotGrounded(1))
140 Math::setVectorElement(rightVector, matrixNodeIndex(1),
141 -mEquivCurrent(freq, 0), mNumFreqs, freq);
142
143 SPDLOG_LOGGER_DEBUG(mSLog, "MNA EquivCurrent {:s}",
144 Logger::complexToString(mEquivCurrent(freq, 0)));
145 if (terminalNotGrounded(0))
146 SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
147 Logger::complexToString(mEquivCurrent(freq, 0)),
148 matrixNodeIndex(0));
149 if (terminalNotGrounded(1))
150 SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
151 Logger::complexToString(-mEquivCurrent(freq, 0)),
152 matrixNodeIndex(1));
153 }
154}
155
156void DP::Ph1::Inductor::mnaCompApplyRightSideVectorStampHarm(
157 Matrix &rightVector) {
158 for (UInt freq = 0; freq < mNumFreqs; freq++) {
159 // Calculate equivalent current source for next time step
160 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
161 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
162
163 if (terminalNotGrounded(0))
164 Math::setVectorElement(rightVector, matrixNodeIndex(0),
165 mEquivCurrent(freq, 0), 1, 0, freq);
166 if (terminalNotGrounded(1))
167 Math::setVectorElement(rightVector, matrixNodeIndex(1),
168 -mEquivCurrent(freq, 0), 1, 0, freq);
169 }
170}
171
173 AttributeBase::List &prevStepDependencies,
174 AttributeBase::List &attributeDependencies,
175 AttributeBase::List &modifiedAttributes) {
176 // actually depends on L, but then we'd have to modify the system matrix anyway
177 prevStepDependencies.push_back(mIntfVoltage);
178 prevStepDependencies.push_back(mIntfCurrent);
179 modifiedAttributes.push_back(mRightVector);
180}
181
182void DP::Ph1::Inductor::mnaCompPreStep(Real time, Int timeStepCount) {
184}
185
187 AttributeBase::List &prevStepDependencies,
188 AttributeBase::List &attributeDependencies,
189 AttributeBase::List &modifiedAttributes,
190 Attribute<Matrix>::Ptr &leftVector) {
191 attributeDependencies.push_back(leftVector);
192 modifiedAttributes.push_back(mIntfVoltage);
193 modifiedAttributes.push_back(mIntfCurrent);
194}
195
196void DP::Ph1::Inductor::mnaCompPostStep(Real time, Int timeStepCount,
197 Attribute<Matrix>::Ptr &leftVector) {
198 this->mnaUpdateVoltage(**leftVector);
199 this->mnaUpdateCurrent(**leftVector);
200}
201
202void DP::Ph1::Inductor::MnaPreStepHarm::execute(Real time, Int timeStepCount) {
203 mInductor.mnaCompApplyRightSideVectorStampHarm(**mInductor.mRightVector);
204}
205
206void DP::Ph1::Inductor::MnaPostStepHarm::execute(Real time, Int timeStepCount) {
207 for (UInt freq = 0; freq < mInductor.mNumFreqs; freq++)
208 mInductor.mnaCompUpdateVoltageHarm(**mLeftVectors[freq], freq);
209 mInductor.mnaCompUpdateCurrentHarm();
210}
211
212void DP::Ph1::Inductor::mnaCompUpdateVoltage(const Matrix &leftVector) {
213 // v1 - v0
214 for (UInt freq = 0; freq < mNumFreqs; freq++) {
215 (**mIntfVoltage)(0, freq) = 0;
216 if (terminalNotGrounded(1))
217 (**mIntfVoltage)(0, freq) = Math::complexFromVectorElement(
218 leftVector, matrixNodeIndex(1), mNumFreqs, freq);
219 if (terminalNotGrounded(0))
220 (**mIntfVoltage)(0, freq) =
221 (**mIntfVoltage)(0, freq) -
222 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0),
223 mNumFreqs, freq);
224
225 SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}",
226 Logger::phasorToString((**mIntfVoltage)(0, freq)));
227 }
228}
229
230void DP::Ph1::Inductor::mnaCompUpdateVoltageHarm(const Matrix &leftVector,
231 Int freqIdx) {
232 // v1 - v0
233 (**mIntfVoltage)(0, freqIdx) = 0;
234 if (terminalNotGrounded(1))
235 (**mIntfVoltage)(0, freqIdx) =
236 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1));
237 if (terminalNotGrounded(0))
238 (**mIntfVoltage)(0, freqIdx) =
239 (**mIntfVoltage)(0, freqIdx) -
240 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
241
242 SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}",
243 Logger::phasorToString((**mIntfVoltage)(0, freqIdx)));
244}
245
246void DP::Ph1::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) {
247 for (UInt freq = 0; freq < mNumFreqs; freq++) {
248 (**mIntfCurrent)(0, freq) =
249 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
250 mEquivCurrent(freq, 0);
251 SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}",
252 Logger::phasorToString((**mIntfCurrent)(0, freq)));
253 }
254}
255
256void DP::Ph1::Inductor::mnaCompUpdateCurrentHarm() {
257 for (UInt freq = 0; freq < mNumFreqs; freq++) {
258 (**mIntfCurrent)(0, freq) =
259 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
260 mEquivCurrent(freq, 0);
261 SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}",
262 Logger::phasorToString((**mIntfCurrent)(0, freq)));
263 }
264}
265
266// #### Tear Methods ####
267void DP::Ph1::Inductor::mnaTearInitialize(Real omega, Real timeStep) {
268 initVars(timeStep);
269}
270
271void DP::Ph1::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {
272 Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx,
273 1. / mEquivCond(0, 0));
274}
275
276void DP::Ph1::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) {
277 mEquivCurrent(0, 0) = mEquivCond(0, 0) * (**mIntfVoltage)(0, 0) +
278 mPrevCurrFac(0, 0) * (**mIntfCurrent)(0, 0);
279 Math::addToVectorElement(voltageVector, mTearIdx,
280 mEquivCurrent(0, 0) / mEquivCond(0, 0));
281}
282
283void DP::Ph1::Inductor::mnaTearPostStep(Complex voltage, Complex current) {
284 (**mIntfVoltage)(0, 0) = voltage;
285 (**mIntfCurrent)(0, 0) = mEquivCond(0, 0) * voltage + mEquivCurrent(0, 0);
286}
const CPS::Attribute< Real >::Ptr mInductance
Inductance [H].
MatrixComp mEquivCond
Equivalent conductance for harmonics [S].
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Update interface current from MNA system results.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Add MNA post step dependencies.
SimPowerComp< Complex >::Ptr clone(String name) override
Return new instance with the same parameters.
MatrixComp mEquivCurrent
DC equivalent current source for harmonics [A].
void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Add MNA pre step dependencies.
void mnaCompInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes MNA specific variables.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Update interface voltage from MNA system results.
void mnaCompPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
MNA post step operations.
MatrixComp mPrevCurrFac
Coefficient in front of previous current value for harmonics.
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
Stamps right side (source) vector.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes states from power flow data.
void initialize(Matrix frequencies) override
Initializes state variables considering the number of frequencies.
void mnaCompPreStep(Real time, Int timeStepCount) override
MNA pre step operations.
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
Inductor(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and log level.
String uid()
Returns unique id.
AttributeList::Ptr mAttributes
Attribute List.
void mnaUpdateCurrent(const Matrix &leftVector) final
void mnaUpdateVoltage(const Matrix &leftVector) final
MNASimPowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
Attribute< Matrix >::Ptr mRightVector
void mnaApplyRightSideVectorStamp(Matrix &rightVector) final
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
virtual void initialize(Matrix frequencies)
Initialize components with correct network frequencies.
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.