DPsim
DP_Ph3_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_Ph3_Inductor.h>
10 
11 using namespace CPS;
12 
13 DP::Ph3::Inductor::Inductor(String uid, String name, Logger::Level logLevel)
14  : MNASimPowerComp<Complex>(uid, name, true, true, logLevel),
15  Base::Ph3::Inductor(mAttributes) {
16  mPhaseType = PhaseType::ABC;
17  setTerminalNumber(2);
18  mEquivCurrent = MatrixComp::Zero(3, 1);
19  **mIntfVoltage = MatrixComp::Zero(3, 1);
20  **mIntfCurrent = MatrixComp::Zero(3, 1);
21 }
22 
24  auto copy = Inductor::make(name, mLogLevel);
25  copy->setParameters(**mInductance);
26  return copy;
27 }
28 
30 
31  Real omega = 2 * PI * frequency;
32 
33  MatrixComp reactance = MatrixComp::Zero(3, 3);
34  reactance << Complex(0, omega * (**mInductance)(0, 0)),
35  Complex(0, omega * (**mInductance)(0, 1)),
36  Complex(0, omega * (**mInductance)(0, 2)),
37  Complex(0, omega * (**mInductance)(1, 0)),
38  Complex(0, omega * (**mInductance)(1, 1)),
39  Complex(0, omega * (**mInductance)(1, 2)),
40  Complex(0, omega * (**mInductance)(2, 0)),
41  Complex(0, omega * (**mInductance)(2, 1)),
42  Complex(0, omega * (**mInductance)(2, 2));
43  MatrixComp susceptance = reactance.inverse();
44  // IntfVoltage initialization for each phase
45  (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0);
46  Real voltMag = Math::abs((**mIntfVoltage)(0, 0));
47  Real voltPhase = Math::phase((**mIntfVoltage)(0, 0));
48  (**mIntfVoltage)(1, 0) = Complex(voltMag * cos(voltPhase - 2. / 3. * M_PI),
49  voltMag * sin(voltPhase - 2. / 3. * M_PI));
50  (**mIntfVoltage)(2, 0) = Complex(voltMag * cos(voltPhase + 2. / 3. * M_PI),
51  voltMag * sin(voltPhase + 2. / 3. * M_PI));
52 
53  **mIntfCurrent = susceptance * **mIntfVoltage;
54 
55  //TODO
56  SPDLOG_LOGGER_INFO(mSLog, "--- Initialize according to power flow ---");
57  // << "in phase A: " << std::endl
58  // << "Voltage across: " << std::abs((**mIntfVoltage)(0,0))
59  // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl
60  // << "Current: " << std::abs((**mIntfCurrent)(0,0))
61  // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl
62  // << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0))
63  // << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl
64  // << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1))
65  // << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl
66  // << "--- Power flow initialization finished ---" << std::endl;
67 }
68 
69 void DP::Ph3::Inductor::initVars(Real omega, Real timeStep) {
70  Matrix a = timeStep / 2. * (**mInductance).inverse();
71  Real b = timeStep * omega / 2.;
72 
73  Matrix equivCondReal = a / (1. + b * b);
74  Matrix equivCondImag = -a * b / (Real(1.) + b * b);
75  mEquivCond = MatrixComp::Zero(3, 3);
76  mEquivCond << Complex(equivCondReal(0, 0), equivCondImag(0, 0)),
77  Complex(equivCondReal(0, 1), equivCondImag(0, 1)),
78  Complex(equivCondReal(0, 2), equivCondImag(0, 2)),
79  Complex(equivCondReal(1, 0), equivCondImag(1, 0)),
80  Complex(equivCondReal(1, 1), equivCondImag(1, 1)),
81  Complex(equivCondReal(1, 2), equivCondImag(1, 2)),
82  Complex(equivCondReal(2, 0), equivCondImag(2, 0)),
83  Complex(equivCondReal(2, 1), equivCondImag(2, 1)),
84  Complex(equivCondReal(2, 2), equivCondImag(2, 2));
85 
86  Real preCurrFracReal = (1. - b * b) / (1. + b * b);
87  Real preCurrFracImag = (-2. * b) / (1. + b * b);
88  mPrevCurrFac = Complex(preCurrFracReal, preCurrFracImag);
89 
90  // TODO: check if this is correct or if it should be only computed before the step
91  mEquivCurrent = mEquivCond * **mIntfVoltage + mPrevCurrFac * **mIntfCurrent;
92  // no need to update this now
93  //**mIntfCurrent = mEquivCond.cwiseProduct(**mIntfVoltage) + mEquivCurrent;
94 }
95 
96 void DP::Ph3::Inductor::mnaCompInitialize(Real omega, Real timeStep,
97  Attribute<Matrix>::Ptr leftVector) {
98  updateMatrixNodeIndices();
99  initVars(omega, timeStep);
100 
101  SPDLOG_LOGGER_INFO(mSLog, "Initial voltage {}",
102  Math::abs((**mIntfVoltage)(0, 0)));
103  // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl
104  // << "Initial current " << Math::abs((**mIntfCurrent)(0,0))
105  // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl;
106 }
107 
109  SparseMatrixRow &systemMatrix) {
110  MNAStampUtils::stampAdmittanceMatrix(
111  mEquivCond, systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1),
112  terminalNotGrounded(0), terminalNotGrounded(1), mSLog);
113 }
114 
116 
117  // Calculate equivalent current source for next time step
118  mEquivCurrent = mEquivCond * **mIntfVoltage + mPrevCurrFac * **mIntfCurrent;
119 
120  if (terminalNotGrounded(0)) {
121  Math::setVectorElement(rightVector, matrixNodeIndex(0, 0),
122  mEquivCurrent(0, 0));
123  Math::setVectorElement(rightVector, matrixNodeIndex(0, 1),
124  mEquivCurrent(1, 0));
125  Math::setVectorElement(rightVector, matrixNodeIndex(0, 2),
126  mEquivCurrent(2, 0));
127  }
128  if (terminalNotGrounded(1)) {
129  Math::setVectorElement(rightVector, matrixNodeIndex(1, 0),
130  -mEquivCurrent(0, 0));
131  Math::setVectorElement(rightVector, matrixNodeIndex(1, 1),
132  -mEquivCurrent(1, 0));
133  Math::setVectorElement(rightVector, matrixNodeIndex(1, 2),
134  -mEquivCurrent(2, 0));
135  }
136 }
137 
139  AttributeBase::List &prevStepDependencies,
140  AttributeBase::List &attributeDependencies,
141  AttributeBase::List &modifiedAttributes) {
142  // actually depends on L, but then we'd have to modify the system matrix anyway
143  modifiedAttributes.push_back(mRightVector);
144  prevStepDependencies.push_back(mIntfVoltage);
145  prevStepDependencies.push_back(mIntfCurrent);
146 }
147 
148 void DP::Ph3::Inductor::mnaCompPreStep(Real time, Int timeStepCount) {
149  mnaCompApplyRightSideVectorStamp(**mRightVector);
150 }
151 
153  AttributeBase::List &prevStepDependencies,
154  AttributeBase::List &attributeDependencies,
155  AttributeBase::List &modifiedAttributes,
156  Attribute<Matrix>::Ptr &leftVector) {
157  attributeDependencies.push_back(leftVector);
158  modifiedAttributes.push_back(mIntfVoltage);
159  modifiedAttributes.push_back(mIntfCurrent);
160 }
161 
162 void DP::Ph3::Inductor::mnaCompPostStep(Real time, Int timeStepCount,
163  Attribute<Matrix>::Ptr &leftVector) {
164  mnaCompUpdateVoltage(**leftVector);
165  mnaCompUpdateCurrent(**leftVector);
166 }
167 
168 void DP::Ph3::Inductor::mnaCompUpdateVoltage(const Matrix &leftVector) {
169  // v1 - v0
170  **mIntfVoltage = Matrix::Zero(3, 1);
171  if (terminalNotGrounded(1)) {
172  (**mIntfVoltage)(0, 0) =
173  Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 0));
174  (**mIntfVoltage)(1, 0) =
175  Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 1));
176  (**mIntfVoltage)(2, 0) =
177  Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 2));
178  }
179  if (terminalNotGrounded(0)) {
180  (**mIntfVoltage)(0, 0) =
181  (**mIntfVoltage)(0, 0) -
182  Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 0));
183  (**mIntfVoltage)(1, 0) =
184  (**mIntfVoltage)(1, 0) -
185  Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 1));
186  (**mIntfVoltage)(2, 0) =
187  (**mIntfVoltage)(2, 0) -
188  Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 2));
189  }
190 }
191 
192 void DP::Ph3::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) {
193  **mIntfCurrent = mEquivCond * **mIntfVoltage + mEquivCurrent;
194 }
195 
196 void DP::Ph3::Inductor::mnaTearInitialize(Real omega, Real timeStep) {
197  initVars(omega, timeStep);
198 }
199 
200 void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {
201  /*
202  Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, mEquivCond.cwiseInverse()(0,0));
203  */
204 }
205 
206 void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) {
207  /*
208  mEquivCurrent = mEquivCond * (**mIntfVoltage)(0,0) + mPrevCurrFac * (**mIntfCurrent)(0,0);
209  Math::addToVectorElement(voltageVector, mTearIdx, mEquivCurrent .cwiseProduct( mEquivCond.cwiseInverse()));
210  */
211 }
212 
213 void DP::Ph3::Inductor::mnaTearPostStep(Complex voltage, Complex current) {
214  /*
215  **mIntfVoltage = voltage;
216  **mIntfCurrent = mEquivCond * voltage + mEquivCurrent;
217  */
218 }
void mnaCompInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes internal variables of the component.
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
MatrixComp mEquivCurrent
DC equivalent current source [A].
void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
Add MNA pre step dependencies.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Update interface voltage from MNA system result.
Inductor(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name, component parameters and logging level.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Update interface current from MNA system result.
SimPowerComp< Complex >::Ptr clone(String name) override
Returns a modified copy of the component with the given suffix added to the name and without.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
Add MNA post step dependencies.
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
Stamps right side (source) vector.
Base class for all MNA components that are transmitting power.
Base class for all components that are transmitting power.
Definition: SimPowerComp.h:17
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
Current through component.
Definition: SimPowerComp.h:47
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
Voltage between terminals.
Definition: SimPowerComp.h:45