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 return mEquivCond(0, 0);
38}
39
41
42 Real omega = 2. * PI * frequency;
43 Complex impedance = {0, omega * **mInductance};
44 (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0);
45 (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance;
46
47 SPDLOG_LOGGER_INFO(mSLog,
48 "\nInductance [H]: {:s}"
49 "\nImpedance [Ohm]: {:s}",
50 Logger::realToString(**mInductance),
51 Logger::complexToString(impedance));
52 SPDLOG_LOGGER_INFO(mSLog,
53 "\n--- Initialization from powerflow ---"
54 "\nVoltage across: {:s}"
55 "\nCurrent: {:s}"
56 "\nTerminal 0 voltage: {:s}"
57 "\nTerminal 1 voltage: {:s}"
58 "\n--- Initialization from powerflow finished ---",
59 Logger::phasorToString((**mIntfVoltage)(0, 0)),
60 Logger::phasorToString((**mIntfCurrent)(0, 0)),
61 Logger::phasorToString(initialSingleVoltage(0)),
62 Logger::phasorToString(initialSingleVoltage(1)));
63}
64
65// #### MNA functions ####
66
67void DP::Ph1::Inductor::initVars(Real timeStep) {
68 for (UInt freq = 0; freq < mNumFreqs; freq++) {
69 Real a = timeStep / (2. * **mInductance);
70 Real b = timeStep * 2. * PI * mFrequencies(freq, 0) / 2.;
71
72 Real equivCondReal = a / (1. + b * b);
73 Real equivCondImag = -a * b / (1. + b * b);
74 mEquivCond(freq, 0) = {equivCondReal, equivCondImag};
75 Real preCurrFracReal = (1. - b * b) / (1. + b * b);
76 Real preCurrFracImag = (-2. * b) / (1. + b * b);
77 mPrevCurrFac(freq, 0) = {preCurrFracReal, preCurrFracImag};
78
79 // In steady-state, these variables should not change
80 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
81 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
82 (**mIntfCurrent)(0, freq) =
83 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
84 mEquivCurrent(freq, 0);
85 }
86}
87
88void DP::Ph1::Inductor::mnaCompInitialize(Real omega, Real timeStep,
89 Attribute<Matrix>::Ptr leftVector) {
91 initVars(timeStep);
92
93 SPDLOG_LOGGER_INFO(mSLog,
94 "\n--- MNA initialization ---"
95 "\nInitial voltage {:s}"
96 "\nInitial current {:s}"
97 "\nEquiv. current {:s}"
98 "\n--- MNA initialization finished ---",
99 Logger::phasorToString((**mIntfVoltage)(0, 0)),
100 Logger::phasorToString((**mIntfCurrent)(0, 0)),
101 Logger::complexToString(mEquivCurrent(0, 0)));
102}
103
104void DP::Ph1::Inductor::mnaCompInitializeHarm(
105 Real omega, Real timeStep,
106 std::vector<Attribute<Matrix>::Ptr> leftVectors) {
107 updateMatrixNodeIndices();
108
109 initVars(timeStep);
110
111 mMnaTasks.push_back(std::make_shared<MnaPreStepHarm>(*this));
112 mMnaTasks.push_back(std::make_shared<MnaPostStepHarm>(*this, leftVectors));
113 **mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs);
114}
115
117 SparseMatrixRow &systemMatrix) {
118 for (UInt freq = 0; freq < mNumFreqs; freq++) {
119 MNAStampUtils::stampAdmittance(
120 mEquivCond(freq, 0), systemMatrix, matrixNodeIndex(0),
121 matrixNodeIndex(1), terminalNotGrounded(0), terminalNotGrounded(1),
122 mSLog, mNumFreqs, freq);
123 }
124}
125
126void DP::Ph1::Inductor::mnaCompApplySystemMatrixStampHarm(
127 SparseMatrixRow &systemMatrix, Int freqIdx) {
128 MNAStampUtils::stampAdmittance(mEquivCond(freqIdx, 0), systemMatrix,
129 matrixNodeIndex(0), matrixNodeIndex(1),
130 terminalNotGrounded(0), terminalNotGrounded(1),
131 mSLog);
132}
133
135 for (UInt freq = 0; freq < mNumFreqs; freq++) {
136 // Calculate equivalent current source for next time step
137 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
138 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
139
140 if (terminalNotGrounded(0))
141 Math::setVectorElement(rightVector, matrixNodeIndex(0),
142 mEquivCurrent(freq, 0), mNumFreqs, freq);
143 if (terminalNotGrounded(1))
144 Math::setVectorElement(rightVector, matrixNodeIndex(1),
145 -mEquivCurrent(freq, 0), mNumFreqs, freq);
146
147 SPDLOG_LOGGER_DEBUG(mSLog, "MNA EquivCurrent {:s}",
148 Logger::complexToString(mEquivCurrent(freq, 0)));
149 if (terminalNotGrounded(0))
150 SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
151 Logger::complexToString(mEquivCurrent(freq, 0)),
152 matrixNodeIndex(0));
153 if (terminalNotGrounded(1))
154 SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
155 Logger::complexToString(-mEquivCurrent(freq, 0)),
156 matrixNodeIndex(1));
157 }
158}
159
160void DP::Ph1::Inductor::mnaCompApplyRightSideVectorStampHarm(
161 Matrix &rightVector) {
162 for (UInt freq = 0; freq < mNumFreqs; freq++) {
163 // Calculate equivalent current source for next time step
164 mEquivCurrent(freq, 0) = mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
165 mPrevCurrFac(freq, 0) * (**mIntfCurrent)(0, freq);
166
167 if (terminalNotGrounded(0))
168 Math::setVectorElement(rightVector, matrixNodeIndex(0),
169 mEquivCurrent(freq, 0), 1, 0, freq);
170 if (terminalNotGrounded(1))
171 Math::setVectorElement(rightVector, matrixNodeIndex(1),
172 -mEquivCurrent(freq, 0), 1, 0, freq);
173 }
174}
175
177 AttributeBase::List &prevStepDependencies,
178 AttributeBase::List &attributeDependencies,
179 AttributeBase::List &modifiedAttributes) {
180 // actually depends on L, but then we'd have to modify the system matrix anyway
181 prevStepDependencies.push_back(mIntfVoltage);
182 prevStepDependencies.push_back(mIntfCurrent);
183 modifiedAttributes.push_back(mRightVector);
184}
185
186void DP::Ph1::Inductor::mnaCompPreStep(Real time, Int timeStepCount) {
188}
189
191 AttributeBase::List &prevStepDependencies,
192 AttributeBase::List &attributeDependencies,
193 AttributeBase::List &modifiedAttributes,
194 Attribute<Matrix>::Ptr &leftVector) {
195 attributeDependencies.push_back(leftVector);
196 modifiedAttributes.push_back(mIntfVoltage);
197 modifiedAttributes.push_back(mIntfCurrent);
198}
199
200void DP::Ph1::Inductor::mnaCompPostStep(Real time, Int timeStepCount,
201 Attribute<Matrix>::Ptr &leftVector) {
202 this->mnaUpdateVoltage(**leftVector);
203 this->mnaUpdateCurrent(**leftVector);
204}
205
206void DP::Ph1::Inductor::MnaPreStepHarm::execute(Real time, Int timeStepCount) {
207 mInductor.mnaCompApplyRightSideVectorStampHarm(**mInductor.mRightVector);
208}
209
210void DP::Ph1::Inductor::MnaPostStepHarm::execute(Real time, Int timeStepCount) {
211 for (UInt freq = 0; freq < mInductor.mNumFreqs; freq++)
212 mInductor.mnaCompUpdateVoltageHarm(**mLeftVectors[freq], freq);
213 mInductor.mnaCompUpdateCurrentHarm();
214}
215
216void DP::Ph1::Inductor::mnaCompUpdateVoltage(const Matrix &leftVector) {
217 // v1 - v0
218 for (UInt freq = 0; freq < mNumFreqs; freq++) {
219 (**mIntfVoltage)(0, freq) = 0;
220 if (terminalNotGrounded(1))
221 (**mIntfVoltage)(0, freq) = Math::complexFromVectorElement(
222 leftVector, matrixNodeIndex(1), mNumFreqs, freq);
223 if (terminalNotGrounded(0))
224 (**mIntfVoltage)(0, freq) =
225 (**mIntfVoltage)(0, freq) -
226 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0),
227 mNumFreqs, freq);
228
229 SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}",
230 Logger::phasorToString((**mIntfVoltage)(0, freq)));
231 }
232}
233
234void DP::Ph1::Inductor::mnaCompUpdateVoltageHarm(const Matrix &leftVector,
235 Int freqIdx) {
236 // v1 - v0
237 (**mIntfVoltage)(0, freqIdx) = 0;
238 if (terminalNotGrounded(1))
239 (**mIntfVoltage)(0, freqIdx) =
240 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1));
241 if (terminalNotGrounded(0))
242 (**mIntfVoltage)(0, freqIdx) =
243 (**mIntfVoltage)(0, freqIdx) -
244 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
245
246 SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}",
247 Logger::phasorToString((**mIntfVoltage)(0, freqIdx)));
248}
249
250void DP::Ph1::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) {
251 for (UInt freq = 0; freq < mNumFreqs; freq++) {
252 (**mIntfCurrent)(0, freq) =
253 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
254 mEquivCurrent(freq, 0);
255 SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}",
256 Logger::phasorToString((**mIntfCurrent)(0, freq)));
257 }
258}
259
260void DP::Ph1::Inductor::mnaCompUpdateCurrentHarm() {
261 for (UInt freq = 0; freq < mNumFreqs; freq++) {
262 (**mIntfCurrent)(0, freq) =
263 mEquivCond(freq, 0) * (**mIntfVoltage)(0, freq) +
264 mEquivCurrent(freq, 0);
265 SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}",
266 Logger::phasorToString((**mIntfCurrent)(0, freq)));
267 }
268}
269
270// #### Tear Methods ####
271void DP::Ph1::Inductor::mnaTearInitialize(Real omega, Real timeStep) {
272 initVars(timeStep);
273}
274
275void DP::Ph1::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {
276 Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx,
277 1. / mEquivCond(0, 0));
278}
279
280void DP::Ph1::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) {
281 mEquivCurrent(0, 0) = mEquivCond(0, 0) * (**mIntfVoltage)(0, 0) +
282 mPrevCurrFac(0, 0) * (**mIntfCurrent)(0, 0);
283 Math::addToVectorElement(voltageVector, mTearIdx,
284 mEquivCurrent(0, 0) / mEquivCond(0, 0));
285}
286
287void DP::Ph1::Inductor::mnaTearPostStep(Complex voltage, Complex current) {
288 (**mIntfVoltage)(0, 0) = voltage;
289 (**mIntfCurrent)(0, 0) = mEquivCond(0, 0) * voltage + mEquivCurrent(0, 0);
290}
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.
Complex getMNAConductance() const
Return single-frequency MNA companion conductance.
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.