9#include "dpsim-models/MathUtils.h"
10#include <Eigen/src/Core/Array.h>
11#include <dpsim-models/Signal/DecouplingLineEMT_Ph3.h>
14using namespace CPS::EMT::Ph3;
15using namespace CPS::Signal;
17DecouplingLineEMT_Ph3::DecouplingLineEMT_Ph3(String name,
18 Logger::Level logLevel)
20 mStates(mAttributes->create<Matrix>(
"states")),
21 mSrcCur1Ref(mAttributes->create<Matrix>(
"i_src1", Matrix::Zero(3, 1))),
22 mSrcCur2Ref(mAttributes->create<Matrix>(
"i_src2", Matrix::Zero(3, 1))) {
24 mRes1 = EMT::Ph3::Resistor::make(name +
"_r1", logLevel);
25 mRes2 = EMT::Ph3::Resistor::make(name +
"_r2", logLevel);
26 mSrc1 = ControlledCurrentSource::make(name +
"_i1", logLevel);
27 mSrc2 = ControlledCurrentSource::make(name +
"_i2", logLevel);
30void DecouplingLineEMT_Ph3::setParameters(SimNode<Real>::Ptr node1,
31 SimNode<Real>::Ptr node2,
32 Matrix resistance, Matrix inductance,
35 mResistance = resistance;
36 mInductance = inductance;
37 mCapacitance = capacitance;
41 mSurgeImpedance = (inductance * capacitance.inverse()).array().sqrt();
42 mDelay = (inductance.array() * capacitance.array()).sqrt().maxCoeff();
43 SPDLOG_LOGGER_INFO(
mSLog,
"surge impedance: {}", mSurgeImpedance);
44 SPDLOG_LOGGER_INFO(
mSLog,
"delay: {}", mDelay);
47 mSurgeImpedance(0, 0) + mResistance(0, 0) / 4));
48 mRes1->connect({SimNode<Real>::GND, node1});
50 mSurgeImpedance(0, 0) + mResistance(0, 0) / 4));
53 mRes2->connect({SimNode<Real>::GND, node2});
54 mSrc1->setParameters(Matrix::Zero(3, 1));
55 mSrc1->connect({node1, SimNode<Real>::GND});
56 mSrc2->setParameters(Matrix::Zero(3, 1));
57 mSrc2->connect({node2, SimNode<Real>::GND});
59 mSrcCur1 = mSrc1->mCurrentRef;
60 mSrcCur2 = mSrc2->mCurrentRef;
63void DecouplingLineEMT_Ph3::initialize(Real omega, Real timeStep) {
64 if (mDelay < timeStep)
65 throw SystemError(
"Timestep too large for decoupling");
67 mBufSize =
static_cast<UInt
>(ceil(mDelay / timeStep));
68 mAlpha = 1 - (mBufSize - mDelay / timeStep);
69 SPDLOG_LOGGER_INFO(
mSLog,
"bufsize {} alpha {}", mBufSize, mAlpha);
72 MatrixComp volt1 = -mNode1->initialVoltage();
73 MatrixComp volt2 = -mNode2->initialVoltage();
75 MatrixComp initAdmittance =
76 (mResistance + Complex(0, omega) * mInductance).inverse() +
77 Complex(0, omega) * mCapacitance / 2;
79 initAdmittance * volt1 -
80 (mResistance + Complex(0, omega) * mInductance).inverse() * volt2;
82 initAdmittance * volt2 -
83 (mResistance + Complex(0, omega) * mInductance).inverse() * volt1;
85 SPDLOG_LOGGER_INFO(
mSLog,
"initial voltages: v_k {} v_m {}", volt1, volt2);
86 SPDLOG_LOGGER_INFO(
mSLog,
"initial currents: i_km {} i_mk {}", cur1, cur2);
89 mVolt1 = volt1.real().transpose().replicate(mBufSize, 1);
90 mVolt2 = volt2.real().transpose().replicate(mBufSize, 1);
91 mCur1 = cur1.real().transpose().replicate(mBufSize, 1);
92 mCur2 = cur2.real().transpose().replicate(mBufSize, 1);
95Matrix DecouplingLineEMT_Ph3::interpolate(Matrix &data) {
97 Matrix c1 = data.row(mBufIdx);
98 Matrix c2 = mBufIdx == mBufSize - 1 ? data.row(0) : data.row(mBufIdx + 1);
99 return (mAlpha * c1 + (1 - mAlpha) * c2).transpose();
102void DecouplingLineEMT_Ph3::step(Real time, Int timeStepCount) {
103 Matrix volt1 = interpolate(mVolt1);
104 Matrix volt2 = interpolate(mVolt2);
105 Matrix cur1 = interpolate(mCur1);
106 Matrix cur2 = interpolate(mCur2);
107 Matrix denom = (mSurgeImpedance + (mResistance / 4)) *
108 (mSurgeImpedance + (mResistance / 4));
110 if (timeStepCount == 0) {
113 cur1 - (mSurgeImpedance + mResistance / 4).inverse() * volt1;
115 cur2 - (mSurgeImpedance + mResistance / 4).inverse() * volt2;
118 **mSrcCur1Ref = -mSurgeImpedance * denom.inverse() *
119 (volt2 + (mSurgeImpedance - mResistance / 4) * cur2) -
120 mResistance / 4 * denom.inverse() *
121 (volt1 + (mSurgeImpedance - mResistance / 4) * cur1);
122 **mSrcCur2Ref = -mSurgeImpedance * denom.inverse() *
123 (volt1 + (mSurgeImpedance - mResistance / 4) * cur1) -
124 mResistance / 4 * denom.inverse() *
125 (volt2 + (mSurgeImpedance - mResistance / 4) * cur2);
127 mSrcCur1->set(**mSrcCur1Ref);
128 mSrcCur2->set(**mSrcCur2Ref);
131void DecouplingLineEMT_Ph3::PreStep::execute(Real time, Int timeStepCount) {
132 mLine.step(time, timeStepCount);
135void DecouplingLineEMT_Ph3::postStep() {
137 mVolt1.row(mBufIdx) = -mRes1->intfVoltage().transpose();
138 mVolt2.row(mBufIdx) = -mRes2->intfVoltage().transpose();
140 -mRes1->intfCurrent().transpose() + mSrcCur1->get().real().transpose();
142 -mRes2->intfCurrent().transpose() + mSrcCur2->get().real().transpose();
145 if (mBufIdx == mBufSize)
149void DecouplingLineEMT_Ph3::PostStep::execute(Real time, Int timeStepCount) {
153Task::List DecouplingLineEMT_Ph3::getTasks() {
155 {std::make_shared<PreStep>(*
this), std::make_shared<PostStep>(*
this)});
158IdentifiedObject::List DecouplingLineEMT_Ph3::getLineComponents() {
159 return IdentifiedObject::List({mRes1, mRes2, mSrc1, mSrc2});
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
Logger::Log mSLog
Component logger.