DPsim
Loading...
Searching...
No Matches
DP_Ph3_PiLine.cpp
1/* Author: Christoph Wirtz <christoph.wirtz@fgh-ma.de>
2 * SPDX-FileCopyrightText: 2025 FGH e.V.
3 * SPDX-License-Identifier: MPL-2.0
4 */
5
6#include <dpsim-models/DP/DP_Ph3_PiLine.h>
7
8using namespace CPS;
9
10DP::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel)
11 : Base::Ph3::PiLine(mAttributes),
12 CompositePowerComp<Complex>(uid, name, true, true, logLevel) {
13 mPhaseType = PhaseType::ABC;
14 setVirtualNodeNumber(1);
15 setTerminalNumber(2);
16
17 SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name);
18 **mIntfVoltage = MatrixComp::Zero(3, 1);
19 **mIntfCurrent = MatrixComp::Zero(3, 1);
20}
21
23SimPowerComp<Complex>::Ptr DP::Ph3::PiLine::clone(String name) {
24 auto copy = PiLine::make(name, mLogLevel);
25 copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap,
27 return copy;
28}
29
32 return;
33 mSubCompCreated = true;
34
35 // By default there is always a small conductance to ground to
36 // avoid problems with floating nodes.
37 Matrix defaultParallelCond = Matrix::Zero(3, 3);
38 defaultParallelCond << 1e-6, 0, 0, 0, 1e-6, 0, 0, 0, 1e-6;
40 ((**mParallelCond)(0, 0) > 0) ? **mParallelCond : defaultParallelCond;
41
42 // Create series sub components
44 std::make_shared<DP::Ph3::Resistor>(**mName + "_res", mLogLevel);
45 mSubSeriesResistor->setParameters(**mSeriesRes);
46 mSubSeriesResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]});
48 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
49 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false);
50
52 std::make_shared<DP::Ph3::Inductor>(**mName + "_ind", mLogLevel);
53 mSubSeriesInductor->setParameters(**mSeriesInd);
54 mSubSeriesInductor->connect({mVirtualNodes[0], mTerminals[1]->node()});
56 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
57 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
58
59 // Create parallel sub components
61 std::make_shared<DP::Ph3::Resistor>(**mName + "_con0", mLogLevel);
62 mSubParallelResistor0->setParameters(2. * (**mParallelCond).inverse());
63 mSubParallelResistor0->connect(
64 SimNode::List{SimNode::GND, mTerminals[0]->node()});
66 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
67 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false);
68
70 std::make_shared<DP::Ph3::Resistor>(**mName + "_con1", mLogLevel);
71 mSubParallelResistor1->setParameters(2. * (**mParallelCond).inverse());
72 mSubParallelResistor1->connect(
73 SimNode::List{SimNode::GND, mTerminals[1]->node()});
75 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
76 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false);
77
78 if ((**mParallelCap)(0, 0) > 0) {
79 mSubParallelCapacitor0 =
80 std::make_shared<DP::Ph3::Capacitor>(**mName + "_cap0", mLogLevel);
81 mSubParallelCapacitor0->setParameters(**mParallelCap / 2.);
82 mSubParallelCapacitor0->connect(
83 SimNode::List{SimNode::GND, mTerminals[0]->node()});
84 addMNASubComponent(mSubParallelCapacitor0,
85 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
86 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
87
89 std::make_shared<DP::Ph3::Capacitor>(**mName + "_cap1", mLogLevel);
90 mSubParallelCapacitor1->setParameters(**mParallelCap / 2.);
92 SimNode::List{SimNode::GND, mTerminals[1]->node()});
94 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
95 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
96 }
97}
98
100 // Static calculation
101 Real omega = 2. * PI * frequency;
102 MatrixComp impedance = MatrixComp::Zero(3, 3);
103 impedance << Complex((**mSeriesRes)(0, 0), omega * (**mSeriesInd)(0, 0)),
104 Complex((**mSeriesRes)(0, 1), omega * (**mSeriesInd)(0, 1)),
105 Complex((**mSeriesRes)(0, 2), omega * (**mSeriesInd)(0, 2)),
106 Complex((**mSeriesRes)(1, 0), omega * (**mSeriesInd)(1, 0)),
107 Complex((**mSeriesRes)(1, 1), omega * (**mSeriesInd)(1, 1)),
108 Complex((**mSeriesRes)(1, 2), omega * (**mSeriesInd)(1, 2)),
109 Complex((**mSeriesRes)(2, 0), omega * (**mSeriesInd)(2, 0)),
110 Complex((**mSeriesRes)(2, 1), omega * (**mSeriesInd)(2, 1)),
111 Complex((**mSeriesRes)(2, 2), omega * (**mSeriesInd)(2, 2));
112 MatrixComp vInitABC = MatrixComp::Zero(3, 1);
113 vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(1) -
114 RMS3PH_TO_PEAK1PH * initialSingleVoltage(0);
115 vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B;
116 vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C;
117 MatrixComp iInit = impedance.inverse() * vInitABC;
118 **mIntfCurrent = iInit;
119 **mIntfVoltage = vInitABC;
120
121 // Initialization of virtual node
122 // Initial voltage of phase B,C is set after A
123 MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1);
124 vInitTerm0(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(0);
125 vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B;
126 vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C;
127
128 mVirtualNodes[0]->setInitialVoltage(PEAK1PH_TO_RMS3PH *
129 (vInitTerm0 + **mSeriesRes * iInit));
130
131 SPDLOG_LOGGER_INFO(
132 mSLog,
133 "\n--- Initialization from powerflow ---"
134 "\nVoltage across: {:s}"
135 "\nCurrent: {:s}"
136 "\nTerminal 0 voltage: {:s}"
137 "\nTerminal 1 voltage: {:s}"
138 "\nVirtual Node 1 voltage: {:s}"
139 "\n--- Initialization from powerflow finished ---",
140 Logger::matrixCompToString(**mIntfVoltage),
141 Logger::matrixCompToString(**mIntfCurrent),
142 Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)),
143 Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)),
144 Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage()));
145}
146
148 AttributeBase::List &prevStepDependencies,
149 AttributeBase::List &attributeDependencies,
150 AttributeBase::List &modifiedAttributes) {
151 // add pre-step dependencies of component itself
152 prevStepDependencies.push_back(mIntfCurrent);
153 prevStepDependencies.push_back(mIntfVoltage);
154 modifiedAttributes.push_back(mRightVector);
155}
156
157void DP::Ph3::PiLine::mnaParentPreStep(Real time, Int timeStepCount) {
158 // pre-step of component itself
160}
161
162void DP::Ph3::PiLine::mnaParentAddPostStepDependencies(
163 AttributeBase::List &prevStepDependencies,
164 AttributeBase::List &attributeDependencies,
165 AttributeBase::List &modifiedAttributes,
166 Attribute<Matrix>::Ptr &leftVector) {
167 // add post-step dependencies of component itself
168 attributeDependencies.push_back(leftVector);
169 modifiedAttributes.push_back(mIntfVoltage);
170 modifiedAttributes.push_back(mIntfCurrent);
171}
172
173void DP::Ph3::PiLine::mnaParentPostStep(Real time, Int timeStepCount,
174 Attribute<Matrix>::Ptr &leftVector) {
175 // post-step of component itself
176 this->mnaUpdateVoltage(**leftVector);
177 this->mnaUpdateCurrent(**leftVector);
178}
179
180void DP::Ph3::PiLine::mnaCompUpdateVoltage(const Matrix &leftVector) {
181 // v1 - v0
182 **mIntfVoltage = MatrixComp::Zero(3, 1);
183 if (terminalNotGrounded(1)) {
184 (**mIntfVoltage)(0, 0) =
185 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 0));
186 (**mIntfVoltage)(1, 0) =
187 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 1));
188 (**mIntfVoltage)(2, 0) =
189 Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 2));
190 }
191 if (terminalNotGrounded(0)) {
192 (**mIntfVoltage)(0, 0) =
193 (**mIntfVoltage)(0, 0) -
194 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 0));
195 (**mIntfVoltage)(1, 0) =
196 (**mIntfVoltage)(1, 0) -
197 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 1));
198 (**mIntfVoltage)(2, 0) =
199 (**mIntfVoltage)(2, 0) -
200 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 2));
201 }
202}
203
204void DP::Ph3::PiLine::mnaCompUpdateCurrent(const Matrix &leftVector) {
205 **mIntfCurrent = mSubSeriesInductor->intfCurrent();
206}
207
208// #### Tear Methods ####
209MNAInterface::List DP::Ph3::PiLine::mnaTearGroundComponents() {
210 MNAInterface::List gndComponents;
211
212 gndComponents.push_back(mSubParallelResistor0);
213 gndComponents.push_back(mSubParallelResistor1);
214
215 if ((**mParallelCap)(0, 0) > 0) {
216 gndComponents.push_back(mSubParallelCapacitor0);
217 gndComponents.push_back(mSubParallelCapacitor1);
218 }
219
220 return gndComponents;
221}
222
223void DP::Ph3::PiLine::mnaTearInitialize(Real omega, Real timeStep) {
224 mSubSeriesResistor->mnaTearSetIdx(mTearIdx);
225 mSubSeriesResistor->mnaTearInitialize(omega, timeStep);
226 mSubSeriesInductor->mnaTearSetIdx(mTearIdx);
227 mSubSeriesInductor->mnaTearInitialize(omega, timeStep);
228}
229
230void DP::Ph3::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {
231 mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix);
232 mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix);
233}
234
235void DP::Ph3::PiLine::mnaTearApplyVoltageStamp(Matrix &voltageVector) {
236 mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector);
237}
238
239void DP::Ph3::PiLine::mnaTearPostStep(MatrixComp voltage, MatrixComp current) {
240 mSubSeriesInductor->mnaTearPostStep(voltage - (**mSeriesRes * current),
241 current);
242 (**mIntfCurrent) = mSubSeriesInductor->intfCurrent();
243}
const Attribute< Matrix >::Ptr mParallelCond
Conductance in parallel to the line [S].
const Attribute< Matrix >::Ptr mSeriesRes
Resistance along the line [ohms].
const Attribute< Matrix >::Ptr mSeriesInd
Inductance along the line [H].
const Attribute< Matrix >::Ptr mParallelCap
Capacitance in parallel to the line [F].
void addMNASubComponent(typename SimPowerComp< Complex >::Ptr subc, MNA_SUBCOMP_TASK_ORDER preStepOrder, MNA_SUBCOMP_TASK_ORDER postStepOrder, Bool contributeToRightVector)
CompositePowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre and post step operations.
std::shared_ptr< Resistor > mSubSeriesResistor
Series Resistor submodel.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Updates internal current variable of the component.
PiLine(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and logging level.
std::shared_ptr< Capacitor > mSubParallelCapacitor1
Parallel capacitor submodel at Terminal 1.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Updates internal voltage variable of the component.
SimPowerComp< Complex >::Ptr clone(String copySuffix) override
DEPRECATED: Remove method.
std::shared_ptr< Inductor > mSubSeriesInductor
std::shared_ptr< Resistor > mSubParallelResistor0
Parallel Resistor submodel at Terminal 0.
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
add MNA pre and post step dependencies
void initializeParentFromNodesAndTerminals(Real frequency) override
Derives values from power flow data and pushes them to subcomponents.
void createSubComponents() override
Constructs and registers MNA subcomponents; idempotent.
std::shared_ptr< Resistor > mSubParallelResistor1
Parallel resistor submodel at Terminal 1.
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
String type()
Get component type (cross-platform)
AttributeList::Ptr mAttributes
Attribute List.
Attribute< Matrix >::Ptr mRightVector
void mnaApplyRightSideVectorStamp(Matrix &rightVector) final
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
SimTerminal< Complex >::List mTerminals
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
SimNode< Complex >::List mVirtualNodes
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.