DPsim
Loading...
Searching...
No Matches
DecouplingLineEMT_Ph3.cpp
Go to the documentation of this file.
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
10#include <Eigen/src/Core/Array.h>
12
13using namespace CPS;
14using namespace CPS::EMT::Ph3;
15using namespace CPS::Signal;
16
18 Logger::Level logLevel)
19 : SimSignalComp(name, name, 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))) {
23
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);
28}
29
32 Matrix resistance, Matrix inductance,
33 Matrix capacitance) {
34
35 mResistance = resistance;
36 mInductance = inductance;
37 mCapacitance = capacitance;
38 mNode1 = node1;
39 mNode2 = node2;
40
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);
45
47 mSurgeImpedance(0, 0) + mResistance(0, 0) / 4));
48 mRes1->connect({SimNode<Real>::GND, node1});
50 mSurgeImpedance(0, 0) + mResistance(0, 0) / 4));
51 /*Notice that, as opposed to the DecouplingLine Ph1, this resistor is connected from GND to node2,
52 since currently the Ph3 resistor has the opposite sign convention for voltage and current, compared to the Ph1 countepart.*/
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});
58
59 mSrcCur1 = mSrc1->mCurrentRef;
60 mSrcCur2 = mSrc2->mCurrentRef;
61}
62
64 if (mDelay < timeStep)
65 throw SystemError("Timestep too large for decoupling");
66
67 mBufSize = static_cast<UInt>(ceil(mDelay / timeStep));
68 mAlpha = 1 - (mBufSize - mDelay / timeStep);
69 SPDLOG_LOGGER_INFO(mSLog, "bufsize {} alpha {}", mBufSize, mAlpha);
70
71 // Initialization based on static PI-line model
72 MatrixComp volt1 = -mNode1->initialVoltage();
73 MatrixComp volt2 = -mNode2->initialVoltage();
74
75 MatrixComp initAdmittance =
76 (mResistance + Complex(0, omega) * mInductance).inverse() +
77 Complex(0, omega) * mCapacitance / 2;
78 MatrixComp cur1 =
79 initAdmittance * volt1 -
80 (mResistance + Complex(0, omega) * mInductance).inverse() * volt2;
81 MatrixComp cur2 =
82 initAdmittance * volt2 -
83 (mResistance + Complex(0, omega) * mInductance).inverse() * volt1;
84
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);
87
88 // Resize ring buffers and initialize
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);
93}
94
96 // linear interpolation of the nearest values
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();
100}
101
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)) *
109
110 if (timeStepCount == 0) {
111 // initialization
112 **mSrcCur1Ref =
113 cur1 - (mSurgeImpedance + mResistance / 4).inverse() * volt1;
114 **mSrcCur2Ref =
115 cur2 - (mSurgeImpedance + mResistance / 4).inverse() * volt2;
116 } else {
117 // Update currents
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);
126 }
127 mSrcCur1->set(**mSrcCur1Ref);
128 mSrcCur2->set(**mSrcCur2Ref);
129}
130
132 mLine.step(time, timeStepCount);
133}
134
136 // Update ringbuffers with new values
137 mVolt1.row(mBufIdx) = -mRes1->intfVoltage().transpose();
138 mVolt2.row(mBufIdx) = -mRes2->intfVoltage().transpose();
139 mCur1.row(mBufIdx) =
140 -mRes1->intfCurrent().transpose() + mSrcCur1->get().real().transpose();
141 mCur2.row(mBufIdx) =
142 -mRes2->intfCurrent().transpose() + mSrcCur2->get().real().transpose();
143
144 mBufIdx++;
145 if (mBufIdx == mBufSize)
146 mBufIdx = 0;
147}
148
150 mLine.postStep();
151}
152
154 return Task::List(
155 {std::make_shared<PreStep>(*this), std::make_shared<PostStep>(*this)});
156}
157
std::vector< Ptr > List
AttributeList::Ptr mAttributes
Attribute List.
spdlog::level::level_enum Level
Definition Logger.h:33
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
void execute(Real time, Int timeStepCount)
std::shared_ptr< EMT::Ph3::ControlledCurrentSource > mSrc2
void setParameters(SimNode< Real >::Ptr node1, SimNode< Real >::Ptr node2, Matrix resistance, Matrix inductance, Matrix capacitance)
void initialize(Real omega, Real timeStep)
void step(Real time, Int timeStepCount)
std::shared_ptr< EMT::Ph3::Resistor > mRes1
std::shared_ptr< EMT::Ph3::ControlledCurrentSource > mSrc1
const Attribute< Matrix >::Ptr mSrcCur2Ref
std::shared_ptr< EMT::SimNode > mNode2
std::shared_ptr< EMT::SimNode > mNode1
std::shared_ptr< EMT::Ph3::Resistor > mRes2
DecouplingLineEMT_Ph3(String name, Logger::Level logLevel=Logger::Level::info)
const Attribute< Matrix >::Ptr mSrcCur1Ref
const Attribute< Matrix >::Ptr mStates
FIXME: workaround for dependency analysis as long as the states aren't attributes.
std::shared_ptr< SimNode< VarType > > Ptr
Definition SimNode.h:32
static Ptr GND
Definition SimNode.h:35
SimSignalComp(String uid, String name, Logger::Level logLevel=Logger::Level::off)
std::vector< Ptr > List
Definition Task.h:28
Logger::Log mSLog
Component logger.
static std::shared_ptr< Resistor > make(Args &&...args)
Definition PtrFactory.h:19
struct dps_magma_data data
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
Dense matrix for real numbers.
Definition Definitions.h:81
std::string String
Definition Definitions.h:65
double Real
Definition Definitions.h:62
int Int
Definition Definitions.h:61
std::complex< Real > Complex
Definition Definitions.h:63
Eigen::Matrix< Complex, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > MatrixComp
Dense matrix for complex numbers.
Definition Definitions.h:84
unsigned int UInt
Definition Definitions.h:60