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; }
43 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
46 std::make_shared<DP::Ph1::Switch>(**
mName +
"_Lswitch",
mLogLevel);
47 mSubInductorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
50 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
51 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
false);
58 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
true);
61 std::make_shared<DP::Ph1::Switch>(**
mName +
"_Cswitch",
mLogLevel);
62 mSubCapacitorSwitch->setParameters(mSwitchROpen, mSwitchRClosed,
false);
65 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
66 MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
false);
71 Real omega = 2. * PI * frequency;
73 Real LInit = 1e6 / omega;
74 Real CInit = 1e-6 / omega;
79 Complex LImpedance = {mSwitchROpen, omega * LInit};
80 Complex CImpedance = {mSwitchROpen, -1 / (omega * CInit)};
81 Complex impedance = LImpedance * CImpedance / (LImpedance + CImpedance);
83 (**mIntfVoltage)(0, 0) = initialSingleVoltage(0);
84 (**mIntfCurrent)(0, 0) = (**
mIntfVoltage)(0, 0) / impedance;
87 mPrevVoltage = (**mIntfVoltage)(0, 0).real();
88 **mVmeasPrev = mPrevVoltage;
91 SPDLOG_LOGGER_INFO(
mSLog,
"Using Mechanical Model");
94 SPDLOG_LOGGER_INFO(
mSLog,
95 "\n --- Parameters ---"
96 "\n Controller: T = {} K = {}"
97 "\n Reference Voltage {} [kV]"
98 "\n Qmax = {} [var] -> BN = {} [S]"
99 "\n Bmax = {} Bmin = {} [p.u.]"
105 (**mIntfVoltage)(0, 0) - LImpedance * (**
mIntfCurrent)(0, 0);
108 (**mIntfVoltage)(0, 0) - CImpedance * (**
mIntfCurrent)(0, 0);
114 SPDLOG_LOGGER_INFO(
mSLog,
115 "\n--- Initialization from powerflow ---"
117 "\nVoltage across: {:s}"
119 "\nTerminal 0 voltage: {:s}"
120 "\n--- Initialization from powerflow finished ---",
121 impedance, Logger::phasorToString((**
mIntfVoltage)(0, 0)),
123 Logger::phasorToString(initialSingleVoltage(0)));
129 AttributeBase::List &prevStepDependencies,
130 AttributeBase::List &attributeDependencies,
131 AttributeBase::List &modifiedAttributes) {
138 if (time > 0.1 && !mDisconnect) {
140 mechanicalModelUpdateSusceptance(time);
144 checkProtection(time);
149 AttributeBase::List &prevStepDependencies,
150 AttributeBase::List &attributeDependencies,
151 AttributeBase::List &modifiedAttributes,
152 Attribute<Matrix>::Ptr &leftVector) {
153 attributeDependencies.push_back(leftVector);
159 Attribute<Matrix>::Ptr &leftVector) {
163 mDeltaT = time - mPrevTimeStep;
164 mPrevTimeStep = time;
165 mValueChange =
false;
169 **mVpcc = Math::complexFromVectorElement(leftVector, matrixNodeIndex(0),
172 (**mIntfVoltage)(0, 0) =
173 Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
177 (**mIntfCurrent)(0, 0) = 0;
178 (**mIntfCurrent)(0, 0) +=
mSubInductor->intfCurrent()(0, 0);
179 (**mIntfCurrent)(0, 0) +=
mSubCapacitor->intfCurrent()(0, 0);
182void DP::Ph1::SVC::checkProtection(Real time) {
186 Real Vpu = **mVmeasPrev / mNomVolt;
188 mProtCount1 = mProtCount1 + mDeltaT;
189 if (mProtCount1 > 0.1) {
196 mProtCount2 = mProtCount2 + mDeltaT;
197 if (mProtCount2 > 1) {
204 mProtCount3 = mProtCount3 + mDeltaT;
205 if (mProtCount3 > 5) {
213 SPDLOG_LOGGER_INFO(mSLog,
"Disconnect SVC because of overvoltage at {}",
215 mSubCapacitorSwitch->open();
216 mSubInductorSwitch->open();
221void DP::Ph1::SVC::updateSusceptance() {
224 Real Fac1 = mDeltaT / (2 * mTr);
225 Real Fac2 = mDeltaT * mKr / (2 * mTr);
227 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
230 Real Fac3 = mDeltaT / (2 * mTm);
231 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
233 **mDeltaV = (Vmeas - mRefVolt) / mNomVolt;
234 Real deltaVPrev = (**mVmeasPrev - mRefVolt) / mNomVolt;
237 Real B = (1 / (1 + Fac1)) *
238 (Fac2 * (**mDeltaV + deltaVPrev) + (1 - Fac1) * **mBPrev);
243 }
else if (B < mBMin) {
249 Real omega = 2 * M_PI * mFrequencies(0, 0);
253 Real inductance = 1 / (omega * B * mBN);
255 if (Math::abs(1 - inductance / mLPrev) > 0.01) {
256 mInductiveMode =
true;
257 mSubInductor->updateInductance(inductance, mDeltaT);
265 Real capacitance = B * mBN / (-omega);
267 if (Math::abs(1 - capacitance / mCPrev) > 0.01) {
268 mInductiveMode =
false;
269 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
270 mCPrev = capacitance;
280 mBSetCounter = mBSetCounter + mDeltaT;
286 **mVmeasPrev = Vmeas;
290void DP::Ph1::SVC::mechanicalModelUpdateSusceptance(Real time) {
292 Real V = Math::abs((**mIntfVoltage)(0, 0).real());
293 Real omega = 2 * M_PI * mFrequencies(0, 0);
296 Real Fac3 = mDeltaT / (2 * mTm);
297 Real Vmeas = (1 / (1 + Fac3)) * (V + mPrevVoltage - **mVmeasPrev);
300 Real deltaV = (mRefVolt - Vmeas) / mRefVolt;
302 if (Math::abs(deltaV) > mDeadband) {
303 if (**mViolationCounter > mMechSwitchDelay) {
305 if (deltaV > 0 && (mTapPos > mMinPos)) {
308 mTapPos = mTapPos - 1;
309 mTapPos = (mTapPos < mMinPos) ? mMinPos : mTapPos;
310 **mViolationCounter = 0;
311 SPDLOG_LOGGER_INFO(mSLog,
313 "\nDecreasing Tap. Reason: Undervoltage"
314 "\nNew Tap Position: {}",
316 }
else if (deltaV < 0 && (mTapPos < mMaxPos)) {
318 mTapPos = mTapPos + 1;
319 mTapPos = (mTapPos > mMaxPos) ? mMaxPos : mTapPos;
320 **mViolationCounter = 0;
321 SPDLOG_LOGGER_INFO(mSLog,
323 "\nIncreasing Tap. Reason: Overvoltag"
324 "\nNew Tap Position: {}",
328 if (**mViolationCounter == 0) {
332 mInductiveMode =
true;
333 Real inductance = 1 / ((mTapPos / mMaxPos) * mBN * omega);
334 SPDLOG_LOGGER_INFO(mSLog,
"New inductance: {}", inductance);
335 mSubInductor->updateInductance(inductance, mDeltaT);
338 }
else if (mTapPos < 0) {
340 mInductiveMode =
false;
341 Real capacitance = ((mTapPos / mMinPos) * mBN) / omega;
342 SPDLOG_LOGGER_INFO(mSLog,
"New capacitance: {}", capacitance);
343 mSubCapacitor->updateCapacitance(capacitance, mDeltaT);
347 }
else if (mTapPos = 0) {
349 SPDLOG_LOGGER_INFO(mSLog,
351 "Tap Position: 0. Open both elements",
353 mSubInductorSwitch->open();
354 mSubCapacitorSwitch->open();
359 **mViolationCounter = **mViolationCounter + mDeltaT;
363 **mViolationCounter = 0;
368 **mVmeasPrev = Vmeas;
371void DP::Ph1::SVC::setSwitchState() {
373 if (mInductiveMode) {
374 if (!mSubInductorSwitch->mnaIsClosed()) {
375 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Closed Inductor Switch");
376 mSubInductorSwitch->close();
378 if (mSubCapacitorSwitch->mnaIsClosed()) {
379 mSubCapacitorSwitch->open();
380 SPDLOG_LOGGER_INFO(mSLog,
"Inductive Mode: Opened Capacitor Switch");
383 if (mSubInductorSwitch->mnaIsClosed()) {
384 mSubInductorSwitch->open();
385 SPDLOG_LOGGER_INFO(mSLog,
"Capacitive Mode: Openend Inductor Switch");
387 if (!mSubCapacitorSwitch->mnaIsClosed()) {
388 mSubCapacitorSwitch->close();
389 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 addMNASubComponent(typename SimPowerComp< Complex >::Ptr subc, MNA_SUBCOMP_TASK_ORDER preStepOrder, MNA_SUBCOMP_TASK_ORDER postStepOrder, Bool contributeToRightVector)
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override
CompositePowerComp(String uid, String name, Bool hasPreStep, Bool hasPostStep, Logger::Level logLevel)
void initializeParentFromNodesAndTerminals(Real frequency) override
Initializes states from power flow data (parent-specific part).
void mnaParentPostStep(Real time, Int timeStepCount, Attribute< Matrix >::Ptr &leftVector) override
MNA post step operations (parent-specific)
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.
std::shared_ptr< DP::Ph1::Inductor > mSubInductor
Internal inductor.
void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute< Matrix >::Ptr &leftVector) override
add MNA post step dependencies (parent-specific)
void mnaParentPreStep(Real time, Int timeStepCount) override
MNA pre step operations (parent-specific)
SVC(String uid, String name, Logger::Level logLevel=Logger::Level::off)
Defines UID, name and log level.
void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override
add MNA pre step dependencies (parent-specific)
const Attribute< String >::Ptr mName
Human readable name.
String uid()
Returns unique id.
AttributeList::Ptr mAttributes
Attribute List.
Attribute< Matrix >::Ptr mRightVector
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
SimTerminal< Complex >::List mTerminals
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
SimNode< Complex >::List mVirtualNodes
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.