Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
ACS
Public
Power System Simulation and Optimization
DPsim
DPsim
Commits
76f03d97
Commit
76f03d97
authored
Oct 12, 2020
by
Markus Mirz
Browse files
add SVC DP component
parent
9158d8a2
Changes
4
Hide whitespace changes
Inline
Side-by-side
models/Include/cps/Base/Base_Ph1_SVC.h
0 → 100644
View file @
76f03d97
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/
#pragma once
#include <cps/Definitions.h>
namespace
CPS
{
namespace
Base
{
namespace
Ph1
{
/// Static VAR compensator (SVC)
class
SVC
{
protected:
/// Inductance [H]
Real
mInductance
;
/// Maximium susceptance [p.u.]
Real
mBMax
;
/// Minimium susceptance [p.u.]
Real
mBMin
;
/// rated B [S]
Real
mBN
;
/// maximum Q
Real
mQN
;
/// Time Constant
Real
mTr
;
/// Gain
Real
mKr
;
/// Reference Voltage
Real
mRefVolt
;
/// Nominal Voltage
Real
mNomVolt
;
// Time step values
Real
mPrevTimeStep
=
0
;
Real
mDeltaT
;
// param for mechanical model
Bool
mMechMode
=
false
;
Real
mViolationCounter
=
0
;
Real
mDeadband
;
Real
mMechSwitchDelay
;
Real
mTapPos
;
Real
mMaxPos
;
Real
mMinPos
;
// save for numerical integration
Real
mPrevVoltage
;
Real
mDeltaV
=
0
;
Real
mBPrev
;
public:
/// Sets model specific parameters
void
setParameters
(
Real
Bmax
,
Real
Bmin
,
Real
QN
,
Real
nomVolt
,
Real
RefVolt
=
0
)
{
// initial inductance very high 10^6 [Ohm] @ 50 Hz
mInductance
=
3183.1
;
mBMax
=
Bmax
;
mBMin
=
Bmin
;
//mBMax = 1;
//mBMin = Bmin;
mQN
=
QN
;
mBN
=
QN
/
(
nomVolt
*
nomVolt
);
mNomVolt
=
nomVolt
;
mRefVolt
=
(
RefVolt
>
0
)
?
RefVolt
:
mNomVolt
;
}
void
setControllerParameters
(
Real
T
,
Real
K
)
{
// Pt1 controller
mTr
=
T
;
mKr
=
K
;
}
void
setMechModelParameter
(
Real
deadband
,
Real
switchDelay
,
Real
maxPos
,
Real
minPos
,
Real
nomVolt
,
Real
RefVolt
,
Real
BN
,
Real
initPos
=
0
)
{
mMechMode
=
true
;
// initial inductance very high 10^6 [Ohm] @ 50 Hz
mInductance
=
3183.1
;
mDeadband
=
deadband
;
mMechSwitchDelay
=
switchDelay
;
mMaxPos
=
maxPos
;
mMinPos
=
minPos
;
mTapPos
=
initPos
;
mNomVolt
=
nomVolt
;
mRefVolt
=
(
RefVolt
>
0
)
?
RefVolt
:
mNomVolt
;
mBN
=
BN
;
mBMax
=
mBN
;
mBMin
=
mMinPos
*
mBN
;
mQN
=
mBN
*
nomVolt
*
nomVolt
;
}
};
}
}
}
\ No newline at end of file
models/Include/cps/Components.h
View file @
76f03d97
...
...
@@ -52,6 +52,7 @@
#include <cps/DP/DP_Ph1_Inverter.h>
#include <cps/DP/DP_Ph1_NetworkInjection.h>
#include <cps/DP/DP_Ph1_AvVoltageSourceInverterDQ.h>
#include <cps/DP/DP_Ph1_SVC.h>
#include <cps/DP/DP_Ph3_ControlledVoltageSource.h>
#include <cps/DP/DP_Ph3_Capacitor.h>
...
...
models/Include/cps/DP/DP_Ph1_SVC.h
0 → 100644
View file @
76f03d97
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/
#pragma once
#include <cps/Solver/MNAInterface.h>
#include <cps/Solver/MNAVariableElementInterface.h>
#include <cps/Base/Base_Ph1_SVC.h>
#include <cps/DP/DP_Ph1_Capacitor.h>
#include <cps/DP/DP_Ph1_Inductor.h>
#include <cps/DP/DP_Ph1_Switch.h>
namespace
CPS
{
namespace
DP
{
namespace
Ph1
{
/// \brief SVC
///
/// SVC represented by an Inductor
/// The inductor is represented by a DC equivalent circuit which corresponds to
/// one iteration of the trapezoidal integration method.
/// The equivalent DC circuit is a resistance in parallel with a current source.
/// The resistance is constant for a defined time step and system
/// frequency and the current source changes for each iteration.
class
SVC
:
public
Base
::
Ph1
::
SVC
,
public
MNAVariableElementInterface
,
public
SimPowerComp
<
Complex
>
,
public
SharedFactory
<
SVC
>
{
protected:
/// ### internal components
/// Internal inductor
std
::
shared_ptr
<
DP
::
Ph1
::
Inductor
>
mSubInductor
;
std
::
shared_ptr
<
DP
::
Ph1
::
Switch
>
mSubInductorProtectionSwitch
;
/// Internal capacitor
std
::
shared_ptr
<
DP
::
Ph1
::
Capacitor
>
mSubCapacitor
;
std
::
shared_ptr
<
DP
::
Ph1
::
Switch
>
mSubCapacitorProtectionSwitch
;
Bool
mValueChange
=
false
;
Bool
mInductiveMode
=
false
;
// has state changed? (allow this only once)
// could be redundant with internal status of switch element (mnaIsClosed)
Real
mSwitchStateChange
=
false
;
Real
mSwitchROpen
=
1e9
;
Real
mSwitchRClosed
=
1e-9
;
Real
mCounter
=
0
;
Real
mBSetCounter
=
0
;
Real
mVpcc
=
0
;
// values of PT1 for measurement of voltage at PCC
Real
mTm
=
0.01
;
Real
mKm
=
1
;
Real
mVmeasPrev
=
0
;
Real
mLPrev
;
Real
mCPrev
;
// variables for protection
Real
mProtCount1
=
0
;
Real
mProtCount2
=
0
;
Real
mProtCount3
=
0
;
Bool
mDisconnect
=
false
;
public:
/// Defines UID, name and log level
SVC
(
String
uid
,
String
name
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
);
/// Defines name and log level
SVC
(
String
name
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
)
:
SVC
(
name
,
name
,
logLevel
)
{
}
// #### General ####
/// Initializes states from power flow data
void
initializeFromPowerflow
(
Real
frequency
);
// #### MNA section ####
/// Initializes MNA specific variables
void
mnaInitialize
(
Real
omega
,
Real
timeStep
,
Attribute
<
Matrix
>::
Ptr
leftVector
);
//void mnaInitializeHarm(Real omega, Real timeStep, std::vector<Attribute<Matrix>::Ptr> leftVectors);
/// Stamps system matrix
void
mnaApplySystemMatrixStamp
(
Matrix
&
systemMatrix
);
/// Stamps right side (source) vector
void
mnaApplyRightSideVectorStamp
(
Matrix
&
rightVector
);
/// Update interface voltage from MNA system results
void
mnaUpdateVoltage
(
const
Matrix
&
leftVector
);
/// Update interface current from MNA system results
void
mnaUpdateCurrent
(
const
Matrix
&
leftVector
);
/// MNA pre step operations
void
mnaPreStep
(
Real
time
,
Int
timeStepCount
);
/// MNA post step operations
void
mnaPostStep
(
Real
time
,
Int
timeStepCount
,
Attribute
<
Matrix
>::
Ptr
&
leftVector
);
/// add MNA pre step dependencies
void
mnaAddPreStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
);
/// add MNA post step dependencies
void
mnaAddPostStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
,
Attribute
<
Matrix
>::
Ptr
&
leftVector
);
// #### Tearing methods ####
Bool
ValueChanged
()
{
return
mValueChange
;
};
void
setSwitchState
();
void
updateSusceptance
();
void
mechanicalModelUpdateSusceptance
(
Real
time
);
// check protection function
void
checkProtection
(
Real
time
);
class
MnaPreStep
:
public
Task
{
public:
MnaPreStep
(
SVC
&
svc
)
:
Task
(
svc
.
mName
+
".MnaPreStep"
),
mSVC
(
svc
)
{
mSVC
.
mnaAddPreStepDependencies
(
mPrevStepDependencies
,
mAttributeDependencies
,
mModifiedAttributes
);
}
void
execute
(
Real
time
,
Int
timeStepCount
)
{
mSVC
.
mnaPreStep
(
time
,
timeStepCount
);
}
private:
SVC
&
mSVC
;
};
class
MnaPostStep
:
public
Task
{
public:
MnaPostStep
(
SVC
&
svc
,
Attribute
<
Matrix
>::
Ptr
leftVector
)
:
Task
(
svc
.
mName
+
".MnaPostStep"
),
mSVC
(
svc
),
mLeftVector
(
leftVector
)
{
mSVC
.
mnaAddPostStepDependencies
(
mPrevStepDependencies
,
mAttributeDependencies
,
mModifiedAttributes
,
mLeftVector
);
}
void
execute
(
Real
time
,
Int
timeStepCount
)
{
mSVC
.
mnaPostStep
(
time
,
timeStepCount
,
mLeftVector
);
}
private:
SVC
&
mSVC
;
Attribute
<
Matrix
>::
Ptr
mLeftVector
;
};
};
}
}
}
models/Source/DP/DP_Ph1_SVC.cpp
0 → 100644
View file @
76f03d97
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/
#include <cps/DP/DP_Ph1_SVC.h>
using
namespace
CPS
;
DP
::
Ph1
::
SVC
::
SVC
(
String
uid
,
String
name
,
Logger
::
Level
logLevel
)
:
SimPowerComp
<
Complex
>
(
uid
,
name
,
logLevel
)
{
setTerminalNumber
(
1
);
setVirtualNodeNumber
(
2
);
mIntfVoltage
=
MatrixComp
::
Zero
(
1
,
1
);
mIntfCurrent
=
MatrixComp
::
Zero
(
1
,
1
);
addAttribute
<
Real
>
(
"B"
,
&
mBPrev
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"DeltaV"
,
&
mDeltaV
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"Vpcc"
,
&
mVpcc
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"Vmeas"
,
&
mVmeasPrev
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"ViolationCounter"
,
&
mViolationCounter
,
Flags
::
read
|
Flags
::
write
);
}
void
DP
::
Ph1
::
SVC
::
initializeFromPowerflow
(
Real
frequency
)
{
// initial state is both switches are open
Real
omega
=
2.
*
PI
*
frequency
;
// init L and C with small/high values (both have high impedance)
Real
LInit
=
1e6
/
omega
;
Real
CInit
=
1e-6
/
omega
;
mLPrev
=
LInit
;
mCPrev
=
CInit
;
// impedances of both branches
Complex
LImpedance
=
{
mSwitchROpen
,
omega
*
LInit
};
Complex
CImpedance
=
{
mSwitchROpen
,
-
1
/
(
omega
*
CInit
)
};
Complex
impedance
=
LImpedance
*
CImpedance
/
(
LImpedance
+
CImpedance
);
mIntfVoltage
(
0
,
0
)
=
initialSingleVoltage
(
0
);
mIntfCurrent
(
0
,
0
)
=
mIntfVoltage
(
0
,
0
)
/
impedance
;
mBPrev
=
0
;
mPrevVoltage
=
mIntfVoltage
(
0
,
0
).
real
();
mVmeasPrev
=
mPrevVoltage
;
if
(
mMechMode
)
{
mSLog
->
info
(
"Using Mechanical Model"
);
}
mSLog
->
info
(
"
\n
--- Parameters ---"
"
\n
Controller: T = {} K = {}"
"
\n
Reference Voltage {} [kV]"
"
\n
Qmax = {} [var] -> BN = {} [S]"
"
\n
Bmax = {} Bmin = {} [p.u.]"
"
\n
Initial B: {}"
,
mTr
,
mKr
,
mRefVolt
,
mQN
,
mBN
,
mBMax
,
mBMin
,
mBPrev
);
// set voltages at virtual nodes
Complex
VLSwitch
=
mIntfVoltage
(
0
,
0
)
-
LImpedance
*
mIntfCurrent
(
0
,
0
);
mVirtualNodes
[
0
]
->
setInitialVoltage
(
VLSwitch
);
Complex
VCSwitch
=
mIntfVoltage
(
0
,
0
)
-
CImpedance
*
mIntfCurrent
(
0
,
0
);
mVirtualNodes
[
1
]
->
setInitialVoltage
(
VCSwitch
);
// create elements
// Inductor with Switch
mSubInductor
=
std
::
make_shared
<
DP
::
Ph1
::
Inductor
>
(
mName
+
"_ind"
,
mLogLevel
);
mSubInductor
->
setParameters
(
LInit
);
mSubInductor
->
connect
({
SimNode
::
GND
,
mVirtualNodes
[
0
]
});
mSubInductor
->
initialize
(
mFrequencies
);
mSubInductor
->
initializeFromPowerflow
(
frequency
);
mSubInductorSwitch
=
std
::
make_shared
<
DP
::
Ph1
::
Switch
>
(
mName
+
"_Lswitch"
,
mLogLevel
);
mSubInductorSwitch
->
setParameters
(
mSwitchROpen
,
mSwitchRClosed
,
false
);
mSubInductorSwitch
->
connect
({
mVirtualNodes
[
0
],
mTerminals
[
0
]
->
node
()
});
mSubInductorSwitch
->
initialize
(
mFrequencies
);
mSubInductorSwitch
->
initializeFromPowerflow
(
frequency
);
// Capacitor with Switch
mSubCapacitor
=
std
::
make_shared
<
DP
::
Ph1
::
Capacitor
>
(
mName
+
"_cap"
,
mLogLevel
);
mSubCapacitor
->
setParameters
(
CInit
);
mSubCapacitor
->
connect
({
SimNode
::
GND
,
mVirtualNodes
[
1
]
});
mSubCapacitor
->
initialize
(
mFrequencies
);
mSubCapacitor
->
initializeFromPowerflow
(
frequency
);
mSubCapacitorSwitch
=
std
::
make_shared
<
DP
::
Ph1
::
Switch
>
(
mName
+
"_Cswitch"
,
mLogLevel
);
mSubCapacitorSwitch
->
setParameters
(
mSwitchROpen
,
mSwitchRClosed
,
false
);
mSubCapacitorSwitch
->
connect
({
mVirtualNodes
[
1
],
mTerminals
[
0
]
->
node
()
});
mSubCapacitorSwitch
->
initialize
(
mFrequencies
);
mSubCapacitorSwitch
->
initializeFromPowerflow
(
frequency
);
mSLog
->
info
(
"
\n
--- Initialization from powerflow ---"
"
\n
Impedance: {}"
"
\n
Voltage across: {:s}"
"
\n
Current: {:s}"
"
\n
Terminal 0 voltage: {:s}"
"
\n
--- Initialization from powerflow finished ---"
,
impedance
,
Logger
::
phasorToString
(
mIntfVoltage
(
0
,
0
)),
Logger
::
phasorToString
(
mIntfCurrent
(
0
,
0
)),
Logger
::
phasorToString
(
initialSingleVoltage
(
0
)));
}
// #### MNA functions ####
void
DP
::
Ph1
::
SVC
::
mnaInitialize
(
Real
omega
,
Real
timeStep
,
Attribute
<
Matrix
>::
Ptr
leftVector
)
{
MNAInterface
::
mnaInitialize
(
omega
,
timeStep
);
updateMatrixNodeIndices
();
mSLog
->
info
(
"
\n
Terminal 0 connected to {:s} = sim node {:d}"
,
mTerminals
[
0
]
->
node
()
->
name
(),
mTerminals
[
0
]
->
node
()
->
matrixNodeIndex
());
mSubInductor
->
mnaInitialize
(
omega
,
timeStep
,
leftVector
);
mRightVectorStamps
.
push_back
(
&
mSubInductor
->
attribute
<
Matrix
>
(
"right_vector"
)
->
get
());
mSubInductorSwitch
->
mnaInitialize
(
omega
,
timeStep
,
leftVector
);
mRighteVctorStamps
.
push_back
(
&
mSubInductorSwitch
->
attribute
<
Matrix
>
(
"right_vector"
)
->
get
());
mSubCapacitor
->
mnaInitialize
(
omega
,
timeStep
,
leftVector
);
mRightVectorStamps
.
push_back
(
&
mSubCapacitor
->
attribute
<
Matrix
>
(
"right_vector"
)
->
get
());
mSubCapacitorSwitch
->
mnaInitialize
(
omega
,
timeStep
,
leftVector
);
mRightVectorStamps
.
push_back
(
&
mSubCapacitorSwitch
->
attribute
<
Matrix
>
(
"right_vector"
)
->
get
());
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPreStep
>
(
*
this
));
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPostStep
>
(
*
this
,
leftVector
));
mRightVector
=
Matrix
::
Zero
(
leftVector
->
get
().
rows
(),
1
);
}
void
DP
::
Ph1
::
SVC
::
mnaApplySystemMatrixStamp
(
Matrix
&
systemMatrix
)
{
mSubInductor
->
mnaApplySystemMatrixStamp
(
systemMatrix
);
mSubCapacitor
->
mnaApplySystemMatrixStamp
(
systemMatrix
);
mSubCapacitorSwitch
->
mnaApplySystemMatrixStamp
(
systemMatrix
);
mSubInductorSwitch
->
mnaApplySystemMatrixStamp
(
systemMatrix
);
}
void
DP
::
Ph1
::
SVC
::
mnaApplyRightSideVectorStamp
(
Matrix
&
rightVector
)
{
mSubInductor
->
mnaApplyRightSideVectorStamp
(
rightVector
);
mSubCapacitor
->
mnaApplyRightSideVectorStamp
(
rightVector
);
mSubCapacitorSwitch
->
mnaApplyRightSideVectorStamp
(
rightVector
);
mSubInductorSwitch
->
mnaApplyRightSideVectorStamp
(
rightVector
);
}
void
DP
::
Ph1
::
SVC
::
mnaAddPreStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
)
{
// add pre-step dependencies of subcomponents
mSubInductor
->
mnaAddPreStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
);
mSubInductorSwitch
->
mnaAddPreStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
);
mSubCapacitor
->
mnaAddPreStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
);
mSubCapacitorSwitch
->
mnaAddPreStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
);
// add pre-step dependencies of component itself
modifiedAttributes
.
push_back
(
this
->
attribute
(
"right_vector"
));
}
void
DP
::
Ph1
::
SVC
::
mnaPreStep
(
Real
time
,
Int
timeStepCount
)
{
mSubInductor
->
mnaPreStep
(
time
,
timeStepCount
);
mSubInductorSwitch
->
mnaPreStep
(
time
,
timeStepCount
);
mSubCapacitor
->
mnaPreStep
(
time
,
timeStepCount
);
mSubCapacitorSwitch
->
mnaPreStep
(
time
,
timeStepCount
);
mnaApplyRightSideVectorStamp
(
mRightVector
);
if
(
time
>
0.1
&&
!
mDisconnect
)
{
if
(
mMechMode
)
{
mechanicalModelUpdateSusceptance
(
time
);
}
else
{
updateSusceptance
();
}
checkProtection
(
time
);
}
}
void
DP
::
Ph1
::
SVC
::
mnaAddPostStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
,
Attribute
<
Matrix
>::
Ptr
&
leftVector
)
{
// add post-step dependencies of subcomponents
mSubInductor
->
mnaAddPostStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
,
leftVector
);
mSubInductorSwitch
->
mnaAddPostStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
,
leftVector
);
mSubCapacitor
->
mnaAddPostStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
,
leftVector
);
mSubCapacitorSwitch
->
mnaAddPostStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
,
leftVector
);
// add post-step dependencies of component itself
attributeDependencies
.
push_back
(
leftVector
);
modifiedAttributes
.
push_back
(
attribute
(
"v_intf"
));
modifiedAttributes
.
push_back
(
attribute
(
"i_intf"
));
}
void
DP
::
Ph1
::
SVC
::
mnaPostStep
(
Real
time
,
Int
timeStepCount
)
{
mSubInductor
->
mnaPostStep
(
time
,
timeStepCount
,
leftVector
);
mSubInductorSwitch
->
mnaPostStep
(
time
,
timeStepCount
,
leftVector
);
mSubCapacitor
->
mnaPostStep
(
time
,
timeStepCount
,
leftVector
);
mSubCapacitorSwitch
->
mnaPostStep
(
time
,
timeStepCount
,
leftVector
);
mnaUpdateVoltage
(
*
mLeftVector
);
mnaUpdateCurrent
(
*
mLeftVector
);
mDeltaT
=
time
-
mPrevTimeStep
;
mPrevTimeStep
=
time
;
mValueChange
=
false
;
}
void
DP
::
Ph1
::
SVC
::
mnaUpdateVoltage
(
const
Matrix
&
leftVector
)
{
mVpcc
=
Math
::
complexFromVectorElement
(
leftVector
,
matrixNodeIndex
(
0
),
mNumFreqs
,
0
).
real
();
mIntfVoltage
(
0
,
0
)
=
Math
::
complexFromVectorElement
(
leftVector
,
matrixNodeIndex
(
0
));
}
void
DP
::
Ph1
::
SVC
::
mnaUpdateCurrent
(
const
Matrix
&
leftVector
)
{
mIntfCurrent
(
0
,
0
)
=
0
;
mIntfCurrent
(
0
,
0
)
+=
mSubInductor
->
intfCurrent
()(
0
,
0
);
mIntfCurrent
(
0
,
0
)
+=
mSubCapacitor
->
intfCurrent
()(
0
,
0
);
}
void
DP
::
Ph1
::
SVC
::
checkProtection
(
Real
time
)
{
// check states for violation of protection values
// get inverse protection curve value (time delay value)
Real
Vpu
=
mVmeasPrev
/
mNomVolt
;
if
(
Vpu
>
1.4
)
{
mProtCount1
=
mProtCount1
+
mDeltaT
;
if
(
mProtCount1
>
0.1
)
{
mDisconnect
=
true
;
}
}
else
{
mProtCount1
=
0
;
}
if
(
Vpu
>
1.25
)
{
mProtCount2
=
mProtCount2
+
mDeltaT
;
if
(
mProtCount2
>
1
)
{
mDisconnect
=
true
;
}
}
else
{
mProtCount2
=
0
;
}
if
(
Vpu
>
1.15
)
{
mProtCount3
=
mProtCount3
+
mDeltaT
;
if
(
mProtCount3
>
5
)
{
mDisconnect
=
true
;
}
}
else
{
mProtCount3
=
0
;
}
if
(
mDisconnect
)
{
mSLog
->
info
(
"Disconnect SVC because of overvoltage at {}"
,
time
);
mSubCapacitorSwitch
->
open
();
mSubInductorSwitch
->
open
();
mValueChange
=
true
;
}
}
void
DP
::
Ph1
::
SVC
::
updateSusceptance
()
{
// calculate new B value
// summarize some constants
Real
Fac1
=
mDeltaT
/
(
2
*
mTr
);
Real
Fac2
=
mDeltaT
*
mKr
/
(
2
*
mTr
);
Complex
vintf
=
mIntfVoltage
(
0
,
0
);
Real
V
=
Math
::
abs
(
mIntfVoltage
(
0
,
0
).
real
());
// Pt1 with trapez rule for voltage measurement
Real
Fac3
=
mDeltaT
/
(
2
*
mTm
);
Real
Vmeas
=
(
1
/
(
1
+
Fac3
))
*
(
V
+
mPrevVoltage
-
mVmeasPrev
);
mDeltaV
=
(
Vmeas
-
mRefVolt
)
/
mNomVolt
;
Real
deltaVPrev
=
(
mVmeasPrev
-
mRefVolt
)
/
mNomVolt
;
// calc new B with trapezoidal rule
//Real B = (1/(1+Fac1)) * (Fac2 * (mDeltaV + deltaVPrev) + (1-Fac1) * mBPrev);
Real
B
=
(
1
/
(
1
+
Fac1
))
*
(
Fac2
*
(
mDeltaV
+
deltaVPrev
)
+
(
1
-
Fac1
)
*
mBPrev
);
//mSLog->info("New B value: percent={}, absolute={}", 100 * B, B * mBN);
// check bounds
if
(
B
>
mBMax
)
{
B
=
mBMax
;
//mSLog->debug("New B value exceeds Bmax");
}
else
if
(
B
<
mBMin
)
{
B
=
mBMin
;
//mSLog->debug("New B value exceeds Bmin");
}
// set new B if it has a new value and difference is big enough
if
(
B
!=
mBPrev
)
{
//if (B != mBPrev && mBSetCounter > 0.001){
//mValueChange = true;
//mBSetCounter = 0;
Real
omega
=
2
*
M_PI
*
mFrequencies
(
0
,
0
);
if
(
B
>
0
)
{
// model inductive behaviour (decrease voltage)
Real
inductance
=
1
/
(
omega
*
B
*
mBN
);
//check if change in reactance is sufficient to trigger a change
if
(
Math
::
abs
(
1
-
inductance
/
mLPrev
)
>
0.01
)
{
mInductiveMode
=
true
;
mSubInductor
->
updateInductance
(
inductance
,
mDeltaT
);
//mSLog->debug("Inductive Mode: New Inductance: L = {} [H]", inductance);
mLPrev
=
inductance
;
mValueChange
=
true
;
mBSetCounter
=
0
;
}
}
else
{
// model capacitive behaviour (increase voltage)
Real
capacitance
=
B
*
mBN
/
(
-
omega
);
//check if change in reactance is sufficient to trigger a change
if
(
Math
::
abs
(
1
-
capacitance
/
mCPrev
)
>
0.01
)
{
mInductiveMode
=
false
;
mSubCapacitor
->
updateCapacitance
(
capacitance
,
mDeltaT
);
//mSLog->debug("Capacitive Mode: New Capacitance: C = {} [F]", capacitance);
mCPrev
=
capacitance
;
mValueChange
=
true
;
mBSetCounter
=
0
;
}
}
// update inductance model
setSwitchState
();
}
else
{
mBSetCounter
=
mBSetCounter
+
mDeltaT
;
}
// save values
mBPrev
=
B
;
mPrevVoltage
=
V
;
mVmeasPrev
=
Vmeas
;
}
// model SVC with a mechanical component and discrete
void
DP
::
Ph1
::
SVC
::
mechanicalModelUpdateSusceptance
(
Real
time
)
{
// current voltage
Real
V
=
Math
::
abs
(
mIntfVoltage
(
0
,
0
).
real
());
Real
omega
=
2
*
M_PI
*
mFrequencies
(
0
,
0
);
// Pt1 with trapez rule for voltage measurement
Real
Fac3
=
mDeltaT
/
(
2
*
mTm
);
Real
Vmeas
=
(
1
/
(
1
+
Fac3
))
*
(
V
+
mPrevVoltage
-
mVmeasPrev
);
// V diff in pu
Real
deltaV
=
(
mRefVolt
-
Vmeas
)
/
mRefVolt
;
if
(
Math
::
abs
(
deltaV
)
>
mDeadband
)
{
if
(
mViolationCounter
>
mMechSwitchDelay
)
{
// change suszeptance one step