DPsim
Loading...
Searching...
No Matches
DecouplingIdealTransformer_EMT_Ph1.cpp
1// SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University
2// SPDX-License-Identifier: MPL-2.0
3
4#include "dpsim-models/Definitions.h"
5#include "dpsim-models/TopologicalNode.h"
6#include <dpsim-models/Signal/DecouplingIdealTransformer_EMT_Ph1.h>
7
8using namespace CPS;
9using namespace CPS::EMT::Ph1;
10using namespace CPS::Signal;
11
12DecouplingIdealTransformer_EMT_Ph1::DecouplingIdealTransformer_EMT_Ph1(
13 String name, Logger::Level logLevel)
14 : SimSignalComp(name, name, logLevel),
15 mStates(mAttributes->create<Matrix>("states")),
16 mSourceVoltageIntfVoltage(mAttributes->create<Real>("v_intf")),
17 mSourceVoltageIntfCurrent(mAttributes->create<Real>("i_intf")),
18 mSrcVoltageRef(mAttributes->create<Real>("v_ref")),
19 mSrcCurrentRef(mAttributes->create<Real>("i_ref")) {
20
21 mRes1 = Resistor::make(name + "_r1", logLevel);
22 mRes2 = Resistor::make(name + "_r2", logLevel);
23 mVoltageSrc = VoltageSource::make(name + "_v", logLevel);
24 mCurrentSrc = CurrentSource::make(name + "_i", logLevel);
25
26 mSrcVoltage = mVoltageSrc->mVoltageRef;
27 mSrcCurrent = mCurrentSrc->mCurrentRef;
28}
29
30void DecouplingIdealTransformer_EMT_Ph1::setParameters(
31 SimNode<Real>::Ptr node1, SimNode<Real>::Ptr node2, Real delay,
32 Matrix voltageSrcIntfCurr, Real current1Extrap0, CouplingMethod method) {
33
34 mNode1 = node1;
35 mNode2 = node2;
36 mVirtualNode = SimNode<Real>::make(name() + "_virtual", PhaseType::Single);
37
38 mDelay = delay;
39 mCouplingMethod = method;
40
41 if (mCouplingMethod == CouplingMethod::EXTRAPOLATION_LINEAR) {
42 mExtrapolationDegree = 1;
43 }
44
45 mRes1->setParameters(mInternalSeriesResistance);
46 mRes1->connect({node1, mVirtualNode});
47 mRes2->setParameters(mInternalParallelResistance);
48 mRes2->connect({node2, SimNode<Real>::GND});
49 mVoltageSrc->setParameters(0);
50 mVoltageSrcIntfCurr = voltageSrcIntfCurr;
51 mCurrent1Extrap0 = current1Extrap0;
52 mVoltageSrc->connect({SimNode<Real>::GND, mVirtualNode});
53 mCurrentSrc->setParameters(0);
54 mCurrentSrc->connect({SimNode<Real>::GND, node2});
55}
56
57void DecouplingIdealTransformer_EMT_Ph1::initialize(Real omega, Real timeStep) {
58 if (mDelay <= 0) {
59 mDelay = 0;
60 mBufSize = 1;
61 mAlpha = 1;
62 } else {
63 mBufSize = static_cast<UInt>(ceil(mDelay / timeStep));
64 mAlpha = 1 - (mBufSize - mDelay / timeStep);
65 }
66 SPDLOG_LOGGER_INFO(mSLog, "bufsize {} alpha {}", mBufSize, mAlpha);
67
68 mVoltageSrc->setIntfCurrent(mVoltageSrcIntfCurr);
69 Complex cur1 = mVoltageSrc->mIntfCurrent->get()(0);
70 Complex volt2 = mNode2->initialSingleVoltage() * RMS3PH_TO_PEAK1PH;
71
72 mVirtualNode->setInitialVoltage(mNode1->initialSingleVoltage() -
73 mInternalSeriesResistance * cur1);
74
75 SPDLOG_LOGGER_INFO(mSLog, "initial current: i_1 {}", cur1);
76 SPDLOG_LOGGER_INFO(mSLog, "initial voltage: v_2 {}", volt2);
77
78 **mSrcVoltageRef = volt2.real();
79 **mSrcCurrentRef = cur1.real();
80 mVoltageSrc->setParameters(**mSrcVoltageRef);
81 mCurrentSrc->setParameters(**mSrcCurrentRef);
82
83 Matrix mSourceCurrentIntfVoltage(1, 1);
84 mSourceCurrentIntfVoltage(0, 0) = volt2.real();
85 mCurrentSrc->setIntfVoltage(mSourceCurrentIntfVoltage);
86
87 mVoltageSrc->setIntfVoltage(mSourceCurrentIntfVoltage);
88 mVoltageSrc->setIntfCurrent(mVoltageSrcIntfCurr);
89
90 **mSourceVoltageIntfVoltage = volt2.real();
91 **mSourceVoltageIntfCurrent = mVoltageSrc->intfCurrent()(0, 0);
92
93 // Resize ring buffers and initialize
94 mCur1.resize(mBufSize, cur1.real());
95 mVol2.resize(mBufSize, volt2.real());
96
97 SPDLOG_LOGGER_INFO(mSLog, "Verify initial current: i_1 {}",
98 mCurrentSrc->intfCurrent()(0, 0));
99 SPDLOG_LOGGER_INFO(mSLog, "Verify initial voltage: v_2 {}",
100 mVoltageSrc->intfVoltage()(0, 0));
101
102 mCur1Extrap.resize(mExtrapolationDegree + 1, 0);
103 mCur1Extrap[0] = mCurrent1Extrap0;
104 if (mExtrapolationDegree > 0) {
105 mCur1Extrap[1] = mVoltageSrcIntfCurr(0, 0);
106 }
107 mVol2Extrap.resize(mExtrapolationDegree + 1, volt2.real());
108}
109
110Real DecouplingIdealTransformer_EMT_Ph1::interpolate(std::vector<Real> &data) {
111 Real c1 = data[mBufIdx];
112 Real c2 = mBufIdx == mBufSize - 1 ? data[0] : data[mBufIdx + 1];
113 return mAlpha * c1 + (1 - mAlpha) * c2;
114}
115
116Real DecouplingIdealTransformer_EMT_Ph1::extrapolate(std::vector<Real> &data) {
117 if (mCouplingMethod == CouplingMethod::EXTRAPOLATION_LINEAR) {
118 Real c1 = data[mMacroBufIdx];
119 Real c2 =
120 mMacroBufIdx == mExtrapolationDegree ? data[0] : data[mMacroBufIdx + 1];
121 Real delayFraction =
122 (mDelay * (mBufIdx + 1)) / static_cast<float>(mBufSize);
123 Real tEval = mDelay + delayFraction;
124 return ((c2 - c1) / mDelay) * tEval + c1;
125 } else {
126 return data[mMacroBufIdx];
127 }
128}
129
130void DecouplingIdealTransformer_EMT_Ph1::step(Real time, Int timeStepCount) {
131 Real volt1, cur2;
132 if (mCouplingMethod == CouplingMethod::DELAY) {
133 volt1 = interpolate(mVol2);
134 cur2 = interpolate(mCur1);
135 } else {
136 volt1 = extrapolate(mVol2Extrap);
137 cur2 = extrapolate(mCur1Extrap);
138 }
139
140 // Update voltage and current
141 **mSrcVoltageRef = volt1;
142 **mSrcCurrentRef = cur2;
143 **mSourceVoltageIntfVoltage = mVoltageSrc->intfVoltage()(0, 0);
144 **mSourceVoltageIntfCurrent = mVoltageSrc->intfCurrent()(0, 0);
145
146 mSrcVoltage->set(**mSrcVoltageRef);
147 mSrcCurrent->set(**mSrcCurrentRef);
148}
149
150void DecouplingIdealTransformer_EMT_Ph1::PreStep::execute(Real time,
151 Int timeStepCount) {
152 mITM.step(time, timeStepCount);
153}
154
155void DecouplingIdealTransformer_EMT_Ph1::postStep() {
156 // Update ringbuffers with new values
157 mCur1[mBufIdx] = mVoltageSrc->intfCurrent()(0, 0);
158 mVol2[mBufIdx] = -mCurrentSrc->intfVoltage()(0, 0);
159
160 mBufIdx++;
161 if (mBufIdx == mBufSize) {
162 mCur1Extrap[mMacroBufIdx] = mCur1[mBufIdx - 1];
163 mVol2Extrap[mMacroBufIdx] = mVol2[mBufIdx - 1];
164 mMacroBufIdx++;
165 if (mMacroBufIdx == mExtrapolationDegree + 1) {
166 mMacroBufIdx = 0;
167 }
168 mBufIdx = 0;
169 }
170}
171
172void DecouplingIdealTransformer_EMT_Ph1::PostStep::execute(Real time,
173 Int timeStepCount) {
174 mITM.postStep();
175}
176
177Task::List DecouplingIdealTransformer_EMT_Ph1::getTasks() {
178 return Task::List(
179 {std::make_shared<PreStep>(*this), std::make_shared<PostStep>(*this)});
180}
181
182IdentifiedObject::List DecouplingIdealTransformer_EMT_Ph1::getComponents() {
183 return IdentifiedObject::List({mRes1, mRes2, mVoltageSrc, mCurrentSrc});
184}
185
186TopologicalNode::Ptr DecouplingIdealTransformer_EMT_Ph1::getVirtualNode() {
187 return mVirtualNode;
188}
Logger::Log mSLog
Component logger.