9#include <dpsim-models/DP/DP_Ph1_SVC.h>
18 setVirtualNodeNumber(2);
24 mViolationCounter =
mAttributes->create<Real>(
"ViolationCounter", 0);
27Bool DP::Ph1::SVC::ValueChanged() {
return mValueChange; }
32 mSubCompCreated =
true;
48 std::make_shared<DP::Ph1::Switch>(**
mName +
"_Lswitch",
mLogLevel);
49 mSubInductorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
60 std::make_shared<DP::Ph1::Switch>(**
mName +
"_Cswitch",
mLogLevel);
61 mSubCapacitorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
68 Real omega = 2. * PI * frequency;
70 Real LInit = 1e6 / omega;
71 Real CInit = 1e-6 / omega;
76 Complex LImpedance = {mSwitchROpen, omega * LInit};
77 Complex CImpedance = {mSwitchROpen, -1 / (omega * CInit)};
78 Complex impedance = LImpedance * CImpedance / (LImpedance + CImpedance);
80 (**mIntfVoltage)(0, 0) = initialSingleVoltage(0);
81 (**mIntfCurrent)(0, 0) = (**
mIntfVoltage)(0, 0) / impedance;
84 mPrevVoltage = (**mIntfVoltage)(0, 0).real();
85 **mVmeasPrev = mPrevVoltage;
88 SPDLOG_LOGGER_INFO(
mSLog,
"Using Mechanical Model");
91 SPDLOG_LOGGER_INFO(
mSLog,
92 "\n --- Parameters ---"
93 "\n Controller: T = {} K = {}"
94 "\n Reference Voltage {} [kV]"
95 "\n Qmax = {} [var] -> BN = {} [S]"
96 "\n Bmax = {} Bmin = {} [p.u.]"
102 (**mIntfVoltage)(0, 0) - LImpedance * (**
mIntfCurrent)(0, 0);
105 (**mIntfVoltage)(0, 0) - CImpedance * (**
mIntfCurrent)(0, 0);
112 mSubInductor->initializeFromNodesAndTerminals(frequency);
113 mSubInductorSwitch->initializeFromNodesAndTerminals(frequency);
115 mSubCapacitorSwitch->initializeFromNodesAndTerminals(frequency);
117 SPDLOG_LOGGER_INFO(
mSLog,
118 "\n--- Initialization from powerflow ---"
120 "\nVoltage across: {:s}"
122 "\nTerminal 0 voltage: {:s}"
123 "\n--- Initialization from powerflow finished ---",
124 impedance, Logger::phasorToString((**
mIntfVoltage)(0, 0)),
126 Logger::phasorToString(initialSingleVoltage(0)));
132 Attribute<Matrix>::Ptr leftVector) {
135 SPDLOG_LOGGER_INFO(
mSLog,
"\nTerminal 0 connected to {:s} = sim node {:d}",
139 mSubInductor->mnaInitialize(omega, timeStep, leftVector);
140 mRightVectorStamps.push_back(
141 &
mSubInductor->attributeTyped<Matrix>(
"right_vector")->get());
143 mSubInductorSwitch->mnaInitialize(omega, timeStep, leftVector);
144 mRighteVctorStamps.push_back(
145 &mSubInductorSwitch->attributeTyped<Matrix>(
"right_vector")->get());
148 mRightVectorStamps.push_back(
149 &
mSubCapacitor->attributeTyped<Matrix>(
"right_vector")->get());
151 mSubCapacitorSwitch->mnaInitialize(omega, timeStep, leftVector);
152 mRightVectorStamps.push_back(
153 &mSubCapacitorSwitch->attributeTyped<Matrix>(
"right_vector")->get());
157 SparseMatrixRow &systemMatrix) {
160 mSubCapacitorSwitch->mnaApplySystemMatrixStamp(systemMatrix);
161 mSubInductorSwitch->mnaApplySystemMatrixStamp(systemMatrix);
165 mSubInductor->mnaApplyRightSideVectorStamp(rightVector);
167 mSubCapacitorSwitch->mnaApplyRightSideVectorStamp(rightVector);
168 mSubInductorSwitch->mnaApplyRightSideVectorStamp(rightVector);
172 AttributeBase::List &prevStepDependencies,
173 AttributeBase::List &attributeDependencies,
174 AttributeBase::List &modifiedAttributes) {
177 prevStepDependencies, attributeDependencies, modifiedAttributes);
178 mSubInductorSwitch->mnaAddPreStepDependencies(
179 prevStepDependencies, attributeDependencies, modifiedAttributes);
181 prevStepDependencies, attributeDependencies, modifiedAttributes);
182 mSubCapacitorSwitch->mnaAddPreStepDependencies(
183 prevStepDependencies, attributeDependencies, modifiedAttributes);
191 mSubInductorSwitch->mnaPreStep(time, timeStepCount);
193 mSubCapacitorSwitch->mnaPreStep(time, timeStepCount);
197 if (time > 0.1 && !mDisconnect) {
199 mechanicalModelUpdateSusceptance(time);
203 checkProtection(time);
208 AttributeBase::List &prevStepDependencies,
209 AttributeBase::List &attributeDependencies,
210 AttributeBase::List &modifiedAttributes,
211 Attribute<Matrix>::Ptr &leftVector) {
213 mSubInductor->mnaAddPostStepDependencies(prevStepDependencies,
214 attributeDependencies,
215 modifiedAttributes, leftVector);
216 mSubInductorSwitch->mnaAddPostStepDependencies(
217 prevStepDependencies, attributeDependencies, modifiedAttributes,
219 mSubCapacitor->mnaAddPostStepDependencies(prevStepDependencies,
220 attributeDependencies,
221 modifiedAttributes, leftVector);
222 mSubCapacitorSwitch->mnaAddPostStepDependencies(
223 prevStepDependencies, attributeDependencies, modifiedAttributes,
227 attributeDependencies.push_back(leftVector);
233 mSubInductor->mnaPostStep(time, timeStepCount, leftVector);
234 mSubInductorSwitch->mnaPostStep(time, timeStepCount, leftVector);
236 mSubCapacitorSwitch->mnaPostStep(time, timeStepCount, leftVector);
241 mDeltaT = time - mPrevTimeStep;
242 mPrevTimeStep = time;
243 mValueChange =
false;
247 **mVpcc = Math::complexFromVectorElement(leftVector, matrixNodeIndex(0),
250 (**mIntfVoltage)(0, 0) =
251 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
255 (**mIntfCurrent)(0, 0) = 0;
256 (**mIntfCurrent)(0, 0) +=
mSubInductor->intfCurrent()(0, 0);
257 (**mIntfCurrent)(0, 0) +=
mSubCapacitor->intfCurrent()(0, 0);
260void DP::Ph1::SVC::checkProtection(Real time) {
264 Real Vpu = **mVmeasPrev / mNomVolt;
266 mProtCount1 = mProtCount1 + mDeltaT;
267 if (mProtCount1 > 0.1) {
274 mProtCount2 = mProtCount2 + mDeltaT;
275 if (mProtCount2 > 1) {
282 mProtCount3 = mProtCount3 + mDeltaT;
283 if (mProtCount3 > 5) {
291 SPDLOG_LOGGER_INFO(mSLog,
"Disconnect SVC because of overvoltage at {}",
293 mSubCapacitorSwitch->open();
294 mSubInductorSwitch->open();
299void DP::Ph1::SVC::updateSusceptance() {
302 Real Fac1 = mDeltaT / (2 * mTr);
303 Real Fac2 = mDeltaT * mKr / (2 * mTr);
305 Complex vintf = (**mIntfVoltage)(0, 0);
306 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
309 Real Fac3 = mDeltaT / (2 * mTm);
310 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
312 **mDeltaV = (Vmeas - mRefVolt) / mNomVolt;
313 Real deltaVPrev = (**mVmeasPrev - mRefVolt) / mNomVolt;
317 Real B = (1 / (1 + Fac1)) *
318 (Fac2 * (**mDeltaV + deltaVPrev) + (1 - Fac1) * **mBPrev);
325 }
else if (B < mBMin) {
335 Real omega = 2 * M_PI * mFrequencies(0, 0);
339 Real inductance = 1 / (omega * B * mBN);
341 if (Math::abs(1 - inductance / mLPrev) > 0.01) {
342 mInductiveMode =
true;
343 mSubInductor->updateInductance(inductance, mDeltaT);
352 Real capacitance = B * mBN / (-omega);
354 if (Math::abs(1 - capacitance / mCPrev) > 0.01) {
355 mInductiveMode =
false;
356 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
358 mCPrev = capacitance;
368 mBSetCounter = mBSetCounter + mDeltaT;
374 **mVmeasPrev = Vmeas;
378void DP::Ph1::SVC::mechanicalModelUpdateSusceptance(Real time) {
380 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
381 Real omega = 2 * M_PI * mFrequencies(0, 0);
384 Real Fac3 = mDeltaT / (2 * mTm);
385 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
388 Real deltaV = (mRefVolt - Vmeas) / mRefVolt;
390 if (Math::abs(deltaV) > mDeadband) {
391 if (**mViolationCounter > mMechSwitchDelay) {
393 if (deltaV > 0 && (mTapPos > mMinPos)) {
396 mTapPos = mTapPos - 1;
397 mTapPos = (mTapPos < mMinPos) ? mMinPos : mTapPos;
398 **mViolationCounter = 0;
399 SPDLOG_LOGGER_INFO(mSLog,
401 "\nDecreasing Tap. Reason: Undervoltage"
402 "\nNew Tap Position: {}",
404 }
else if (deltaV < 0 && (mTapPos < mMaxPos)) {
406 mTapPos = mTapPos + 1;
407 mTapPos = (mTapPos > mMaxPos) ? mMaxPos : mTapPos;
408 **mViolationCounter = 0;
409 SPDLOG_LOGGER_INFO(mSLog,
411 "\nIncreasing Tap. Reason: Overvoltag"
412 "\nNew Tap Position: {}",
416 if (**mViolationCounter == 0) {
420 mInductiveMode =
true;
421 Real inductance = 1 / ((mTapPos / mMaxPos) * mBN * omega);
422 SPDLOG_LOGGER_INFO(mSLog,
"New inductance: {}", inductance);
423 mSubInductor->updateInductance(inductance, mDeltaT);
426 }
else if (mTapPos < 0) {
428 mInductiveMode =
false;
429 Real capacitance = ((mTapPos / mMinPos) * mBN) / omega;
430 SPDLOG_LOGGER_INFO(mSLog,
"New capacitance: {}", capacitance);
431 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
435 }
else if (mTapPos = 0) {
437 SPDLOG_LOGGER_INFO(mSLog,
439 "Tap Position: 0. Open both elements",
441 mSubInductorSwitch->open();
442 mSubCapacitorSwitch->open();
447 **mViolationCounter = **mViolationCounter + mDeltaT;
451 **mViolationCounter = 0;
456 **mVmeasPrev = Vmeas;
459void DP::Ph1::SVC::setSwitchState() {
461 if (mInductiveMode) {
462 if (!mSubInductorSwitch->mnaIsClosed()) {
463 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Closed Inductor Switch");
464 mSubInductorSwitch->close();
466 if (mSubCapacitorSwitch->mnaIsClosed()) {
467 mSubCapacitorSwitch->open();
468 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Opened Capacitor Switch");
471 if (mSubInductorSwitch->mnaIsClosed()) {
472 mSubInductorSwitch->open();
473 SPDLOG_LOGGER_INFO(mSLog,
"Capacitive Mode: Openend Inductor Switch");
475 if (!mSubCapacitorSwitch->mnaIsClosed()) {
476 mSubCapacitorSwitch->close();
477 SPDLOG_LOGGER_INFO(mSLog,
"Capacitive Mode: Closed Capcitor Switch");
Real mBMax
Maximium susceptance [p.u.].
Real mBMin
Minimium susceptance [p.u.].
Real mRefVolt
Reference Voltage.
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override
Stamps system matrix.
void mnaCompPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
MNA post step operations.
void mnaCompUpdateCurrent(const Matrix &leftVector) override
Update interface current from MNA system results.
void createSubComponents() override
Constructs subcomponents; idempotent.
std::shared_ptr< DP::Ph1::Capacitor > mSubCapacitor
Internal capacitor.
void mnaCompUpdateVoltage(const Matrix &leftVector) override
Update interface voltage from MNA system results.
void mnaCompInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector) override
Initializes MNA specific variables.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
add MNA post step dependencies
std::shared_ptr< DP::Ph1::Inductor > mSubInductor
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
Stamps right side (source) vector.
void initializeFromNodesAndTerminals(Real frequency) override
Initializes states from power flow data.
void mnaCompPreStep(Real time, Int timeStepCount) override
MNA pre step operations.
void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
add MNA pre step dependencies
SVC(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and log level.
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
AttributeList::Ptr mAttributes
Attribute List.
MNASimPowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
Attribute< Matrix >::Ptr mRightVector
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
SimTerminal< Complex >::List mTerminals
SimNode< Complex >::Ptr node(UInt index)
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
SimNode< Complex >::List mVirtualNodes
void updateMatrixNodeIndices()
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.