9 #include <dpsim-models/DP/DP_Ph1_SVC.h>
15 mVpcc(mAttributes->create<Real>(
"Vpcc", 0)),
16 mVmeasPrev(mAttributes->create<Real>(
"Vmeas", 0)) {
18 setVirtualNodeNumber(2);
24 mViolationCounter =
mAttributes->create<Real>(
"ViolationCounter", 0);
27 Bool DP::Ph1::SVC::ValueChanged() {
return mValueChange; }
32 Real omega = 2. * PI * frequency;
34 Real LInit = 1e6 / omega;
35 Real CInit = 1e-6 / omega;
40 Complex LImpedance = {mSwitchROpen, omega * LInit};
41 Complex CImpedance = {mSwitchROpen, -1 / (omega * CInit)};
42 Complex impedance = LImpedance * CImpedance / (LImpedance + CImpedance);
44 (**mIntfVoltage)(0, 0) = initialSingleVoltage(0);
45 (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance;
48 mPrevVoltage = (**mIntfVoltage)(0, 0).real();
49 **mVmeasPrev = mPrevVoltage;
52 SPDLOG_LOGGER_INFO(mSLog,
"Using Mechanical Model");
55 SPDLOG_LOGGER_INFO(mSLog,
56 "\n --- Parameters ---"
57 "\n Controller: T = {} K = {}"
58 "\n Reference Voltage {} [kV]"
59 "\n Qmax = {} [var] -> BN = {} [S]"
60 "\n Bmax = {} Bmin = {} [p.u.]"
62 mTr, mKr, mRefVolt, mQN, mBN, mBMax, mBMin, **mBPrev);
66 (**mIntfVoltage)(0, 0) - LImpedance * (**mIntfCurrent)(0, 0);
67 mVirtualNodes[0]->setInitialVoltage(VLSwitch);
69 (**mIntfVoltage)(0, 0) - CImpedance * (**mIntfCurrent)(0, 0);
70 mVirtualNodes[1]->setInitialVoltage(VCSwitch);
75 std::make_shared<DP::Ph1::Inductor>(**mName +
"_ind", mLogLevel);
76 mSubInductor->setParameters(LInit);
77 mSubInductor->connect({SimNode::GND, mVirtualNodes[0]});
78 mSubInductor->initialize(mFrequencies);
79 mSubInductor->initializeFromNodesAndTerminals(frequency);
82 std::make_shared<DP::Ph1::Switch>(**mName +
"_Lswitch", mLogLevel);
83 mSubInductorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
84 mSubInductorSwitch->connect({mVirtualNodes[0], mTerminals[0]->node()});
85 mSubInductorSwitch->initialize(mFrequencies);
86 mSubInductorSwitch->initializeFromNodesAndTerminals(frequency);
90 std::make_shared<DP::Ph1::Capacitor>(**mName +
"_cap", mLogLevel);
91 mSubCapacitor->setParameters(CInit);
92 mSubCapacitor->connect({SimNode::GND, mVirtualNodes[1]});
93 mSubCapacitor->initialize(mFrequencies);
94 mSubCapacitor->initializeFromNodesAndTerminals(frequency);
97 std::make_shared<DP::Ph1::Switch>(**mName +
"_Cswitch", mLogLevel);
98 mSubCapacitorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
99 mSubCapacitorSwitch->connect({mVirtualNodes[1], mTerminals[0]->node()});
100 mSubCapacitorSwitch->initialize(mFrequencies);
101 mSubCapacitorSwitch->initializeFromNodesAndTerminals(frequency);
103 SPDLOG_LOGGER_INFO(mSLog,
104 "\n--- Initialization from powerflow ---"
106 "\nVoltage across: {:s}"
108 "\nTerminal 0 voltage: {:s}"
109 "\n--- Initialization from powerflow finished ---",
110 impedance, Logger::phasorToString((**mIntfVoltage)(0, 0)),
111 Logger::phasorToString((**mIntfCurrent)(0, 0)),
112 Logger::phasorToString(initialSingleVoltage(0)));
119 updateMatrixNodeIndices();
121 SPDLOG_LOGGER_INFO(mSLog,
"\nTerminal 0 connected to {:s} = sim node {:d}",
122 mTerminals[0]->node()->name(),
123 mTerminals[0]->node()->matrixNodeIndex());
125 mSubInductor->mnaInitialize(omega, timeStep, leftVector);
126 mRightVectorStamps.push_back(
127 &mSubInductor->attributeTyped<Matrix>(
"right_vector")->get());
129 mSubInductorSwitch->mnaInitialize(omega, timeStep, leftVector);
130 mRighteVctorStamps.push_back(
131 &mSubInductorSwitch->attributeTyped<Matrix>(
"right_vector")->get());
133 mSubCapacitor->mnaInitialize(omega, timeStep, leftVector);
134 mRightVectorStamps.push_back(
135 &mSubCapacitor->attributeTyped<Matrix>(
"right_vector")->get());
137 mSubCapacitorSwitch->mnaInitialize(omega, timeStep, leftVector);
138 mRightVectorStamps.push_back(
139 &mSubCapacitorSwitch->attributeTyped<Matrix>(
"right_vector")->get());
143 SparseMatrixRow &systemMatrix) {
144 mSubInductor->mnaApplySystemMatrixStamp(systemMatrix);
145 mSubCapacitor->mnaApplySystemMatrixStamp(systemMatrix);
146 mSubCapacitorSwitch->mnaApplySystemMatrixStamp(systemMatrix);
147 mSubInductorSwitch->mnaApplySystemMatrixStamp(systemMatrix);
151 mSubInductor->mnaApplyRightSideVectorStamp(rightVector);
152 mSubCapacitor->mnaApplyRightSideVectorStamp(rightVector);
153 mSubCapacitorSwitch->mnaApplyRightSideVectorStamp(rightVector);
154 mSubInductorSwitch->mnaApplyRightSideVectorStamp(rightVector);
158 AttributeBase::List &prevStepDependencies,
159 AttributeBase::List &attributeDependencies,
160 AttributeBase::List &modifiedAttributes) {
162 mSubInductor->mnaAddPreStepDependencies(
163 prevStepDependencies, attributeDependencies, modifiedAttributes);
164 mSubInductorSwitch->mnaAddPreStepDependencies(
165 prevStepDependencies, attributeDependencies, modifiedAttributes);
166 mSubCapacitor->mnaAddPreStepDependencies(
167 prevStepDependencies, attributeDependencies, modifiedAttributes);
168 mSubCapacitorSwitch->mnaAddPreStepDependencies(
169 prevStepDependencies, attributeDependencies, modifiedAttributes);
172 modifiedAttributes.push_back(mRightVector);
176 mSubInductor->mnaPreStep(time, timeStepCount);
177 mSubInductorSwitch->mnaPreStep(time, timeStepCount);
178 mSubCapacitor->mnaPreStep(time, timeStepCount);
179 mSubCapacitorSwitch->mnaPreStep(time, timeStepCount);
181 mnaCompApplyRightSideVectorStamp(**mRightVector);
183 if (time > 0.1 && !mDisconnect) {
185 mechanicalModelUpdateSusceptance(time);
189 checkProtection(time);
194 AttributeBase::List &prevStepDependencies,
195 AttributeBase::List &attributeDependencies,
196 AttributeBase::List &modifiedAttributes,
199 mSubInductor->mnaAddPostStepDependencies(prevStepDependencies,
200 attributeDependencies,
201 modifiedAttributes, leftVector);
202 mSubInductorSwitch->mnaAddPostStepDependencies(
203 prevStepDependencies, attributeDependencies, modifiedAttributes,
205 mSubCapacitor->mnaAddPostStepDependencies(prevStepDependencies,
206 attributeDependencies,
207 modifiedAttributes, leftVector);
208 mSubCapacitorSwitch->mnaAddPostStepDependencies(
209 prevStepDependencies, attributeDependencies, modifiedAttributes,
213 attributeDependencies.push_back(leftVector);
214 modifiedAttributes.push_back(mIntfVoltage);
215 modifiedAttributes.push_back(mIntfCurrent);
219 mSubInductor->mnaPostStep(time, timeStepCount, leftVector);
220 mSubInductorSwitch->mnaPostStep(time, timeStepCount, leftVector);
221 mSubCapacitor->mnaPostStep(time, timeStepCount, leftVector);
222 mSubCapacitorSwitch->mnaPostStep(time, timeStepCount, leftVector);
224 mnaCompUpdateVoltage(**mLeftVector);
225 mnaCompUpdateCurrent(**mLeftVector);
227 mDeltaT = time - mPrevTimeStep;
228 mPrevTimeStep = time;
229 mValueChange =
false;
233 **mVpcc = Math::complexFromVectorElement(leftVector, matrixNodeIndex(0),
236 (**mIntfVoltage)(0, 0) =
237 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
241 (**mIntfCurrent)(0, 0) = 0;
242 (**mIntfCurrent)(0, 0) += mSubInductor->intfCurrent()(0, 0);
243 (**mIntfCurrent)(0, 0) += mSubCapacitor->intfCurrent()(0, 0);
246 void DP::Ph1::SVC::checkProtection(Real time) {
250 Real Vpu = **mVmeasPrev / mNomVolt;
252 mProtCount1 = mProtCount1 + mDeltaT;
253 if (mProtCount1 > 0.1) {
260 mProtCount2 = mProtCount2 + mDeltaT;
261 if (mProtCount2 > 1) {
268 mProtCount3 = mProtCount3 + mDeltaT;
269 if (mProtCount3 > 5) {
277 SPDLOG_LOGGER_INFO(mSLog,
"Disconnect SVC because of overvoltage at {}",
279 mSubCapacitorSwitch->open();
280 mSubInductorSwitch->open();
285 void DP::Ph1::SVC::updateSusceptance() {
288 Real Fac1 = mDeltaT / (2 * mTr);
289 Real Fac2 = mDeltaT * mKr / (2 * mTr);
291 Complex vintf = (**mIntfVoltage)(0, 0);
292 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
295 Real Fac3 = mDeltaT / (2 * mTm);
296 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
298 **mDeltaV = (Vmeas - mRefVolt) / mNomVolt;
299 Real deltaVPrev = (**mVmeasPrev - mRefVolt) / mNomVolt;
303 Real B = (1 / (1 + Fac1)) *
304 (Fac2 * (**mDeltaV + deltaVPrev) + (1 - Fac1) * **mBPrev);
311 }
else if (B < mBMin) {
321 Real omega = 2 * M_PI * mFrequencies(0, 0);
325 Real inductance = 1 / (omega * B * mBN);
327 if (Math::abs(1 - inductance / mLPrev) > 0.01) {
328 mInductiveMode =
true;
329 mSubInductor->updateInductance(inductance, mDeltaT);
338 Real capacitance = B * mBN / (-omega);
340 if (Math::abs(1 - capacitance / mCPrev) > 0.01) {
341 mInductiveMode =
false;
342 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
344 mCPrev = capacitance;
354 mBSetCounter = mBSetCounter + mDeltaT;
360 **mVmeasPrev = Vmeas;
364 void DP::Ph1::SVC::mechanicalModelUpdateSusceptance(Real time) {
366 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
367 Real omega = 2 * M_PI * mFrequencies(0, 0);
370 Real Fac3 = mDeltaT / (2 * mTm);
371 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
374 Real deltaV = (mRefVolt - Vmeas) / mRefVolt;
376 if (Math::abs(deltaV) > mDeadband) {
377 if (**mViolationCounter > mMechSwitchDelay) {
379 if (deltaV > 0 && (mTapPos > mMinPos)) {
382 mTapPos = mTapPos - 1;
383 mTapPos = (mTapPos < mMinPos) ? mMinPos : mTapPos;
384 **mViolationCounter = 0;
385 SPDLOG_LOGGER_INFO(mSLog,
387 "\nDecreasing Tap. Reason: Undervoltage"
388 "\nNew Tap Position: {}",
390 }
else if (deltaV < 0 && (mTapPos < mMaxPos)) {
392 mTapPos = mTapPos + 1;
393 mTapPos = (mTapPos > mMaxPos) ? mMaxPos : mTapPos;
394 **mViolationCounter = 0;
395 SPDLOG_LOGGER_INFO(mSLog,
397 "\nIncreasing Tap. Reason: Overvoltag"
398 "\nNew Tap Position: {}",
402 if (**mViolationCounter == 0) {
406 mInductiveMode =
true;
407 Real inductance = 1 / ((mTapPos / mMaxPos) * mBN * omega);
408 SPDLOG_LOGGER_INFO(mSLog,
"New inductance: {}", inductance);
409 mSubInductor->updateInductance(inductance, mDeltaT);
412 }
else if (mTapPos < 0) {
414 mInductiveMode =
false;
415 Real capacitance = ((mTapPos / mMinPos) * mBN) / omega;
416 SPDLOG_LOGGER_INFO(mSLog,
"New capacitance: {}", capacitance);
417 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
421 }
else if (mTapPos = 0) {
423 SPDLOG_LOGGER_INFO(mSLog,
425 "Tap Position: 0. Open both elements",
427 mSubInductorSwitch->open();
428 mSubCapacitorSwitch->open();
433 **mViolationCounter = **mViolationCounter + mDeltaT;
437 **mViolationCounter = 0;
442 **mVmeasPrev = Vmeas;
445 void DP::Ph1::SVC::setSwitchState() {
447 if (mInductiveMode) {
448 if (!mSubInductorSwitch->mnaIsClosed()) {
449 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Closed Inductor Switch");
450 mSubInductorSwitch->close();
452 if (mSubCapacitorSwitch->mnaIsClosed()) {
453 mSubCapacitorSwitch->open();
454 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Opened Capacitor Switch");
457 if (mSubInductorSwitch->mnaIsClosed()) {
458 mSubInductorSwitch->open();
459 SPDLOG_LOGGER_INFO(mSLog,
"Capacitive Mode: Openend Inductor Switch");
461 if (!mSubCapacitorSwitch->mnaIsClosed()) {
462 mSubCapacitorSwitch->close();
463 SPDLOG_LOGGER_INFO(mSLog,
"Capacitive Mode: Closed Capcitor Switch");
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix)
Stamps system matrix.
void mnaCompUpdateVoltage(const Matrix &leftVector)
Update interface voltage from MNA system results.
void mnaCompUpdateCurrent(const Matrix &leftVector)
Update interface current from MNA system results.
void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector)
add MNA post step dependencies
void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes)
add MNA pre step dependencies
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector)
Stamps right side (source) vector.
void initializeFromNodesAndTerminals(Real frequency)
Initializes states from power flow data.
void mnaCompPreStep(Real time, Int timeStepCount)
MNA pre step operations.
void mnaCompPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector)
MNA post step operations.
SVC(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and log level.
void mnaCompInitialize(Real omega, Real timeStep, Attribute< Matrix >::Ptr leftVector)
Initializes MNA specific variables.
AttributeList::Ptr mAttributes
Attribute List.
Base class for all MNA components that are transmitting power.
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
Current through component.
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
Voltage between terminals.