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
a8db6305
Commit
a8db6305
authored
Dec 19, 2019
by
Jan Dinkelbach
Committed by
Markus Mirz
Jan 31, 2020
Browse files
sp1ph: update syngen model
parent
a8434448
Changes
5
Hide whitespace changes
Inline
Side-by-side
Dependencies/libcps/Include/cps/SP/SP_Ph1_SynchronGenerator.h
View file @
a8db6305
...
...
@@ -23,9 +23,6 @@
#include
<cps/PowerComponent.h>
#include
<cps/Solver/PFSolverInterfaceBus.h>
#include
<cps/SP/SP_Ph1_PVNode.h>
#include
<cps/SP/SP_Ph1_PQNode.h>
#include
<cps/SP/SP_Ph1_VDNode.h>
namespace
CPS
{
...
...
@@ -33,32 +30,52 @@ namespace CPS {
namespace
SP
{
namespace
Ph1
{
class
SynchronGenerator
:
public
PowerComponent
<
Complex
>
,
public
SharedFactory
<
SynchronGenerator
>
,
public
PFSolverInterfaceBus
{
private:
Real
mRatedU
;
Real
mRatedS
;
class
SynchronGenerator
:
public
PowerComponent
<
Complex
>
,
public
SharedFactory
<
SynchronGenerator
>
,
public
PFSolverInterfaceBus
{
private:
/// Rate apparent power [VA]
Real
mRatedApparentPower
;
/// Rated voltage [V]
Real
mRatedVoltage
;
public:
using
PowerComponent
<
Complex
>::
PowerComponent
;
/// Active power set point of the machine [W]
Real
mSetPointActivePower
;
/// Voltage set point of the machine [V]
Real
mSetPointVoltage
;
/// Maximum reactive power [VAr]
Real
mMaximumReactivePower
;
/// Defines UID, name, component parameters and logging level
SynchronGenerator
(
String
uid
,
String
name
,
PowerflowBusType
powerflowBusType
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
);
/// Base apparent power[VA]
Real
mBaseApparentPower
;
/// Base omega [1/s]
Real
mBaseOmega
;
/// Base voltage [V]
Real
mBaseVoltage
;
/// Active power set point of the machine [pu]
Real
mSetPointActivePowerPerUnit
;
/// Voltage set point of the machine [pu]
Real
mSetPointVoltagePerUnit
;
SynchronGenerator
(
String
uid
,
String
name
,
Real
power
,
Real
voltageSetPoint
,
PowerflowBusType
powerflowBusType
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
);
SynchronGenerator
(
String
uid
,
String
name
,
Real
power
,
Real
maxQ
,
Real
voltageSetPoint
,
Real
ratedU
,
Real
ratedS
,
PowerflowBusType
powerflowBusType
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
);
public:
/// Defines UID, name and logging level
SynchronGenerator
(
String
uid
,
String
name
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
);
/// Defines name and logging level
SynchronGenerator
(
String
name
,
Logger
::
Level
logLevel
=
Logger
::
Level
::
off
)
:
SynchronGenerator
(
name
,
name
,
logLevel
)
{
}
/// Setter for synchronous generator parameters
void
setParameters
(
Real
ratedApparentPower
,
Real
ratedVoltage
,
Real
setPointActivePower
,
Real
setPointVoltage
,
Real
maximumReactivePower
,
PowerflowBusType
powerflowBusType
);
// #### Powerflow section ####
// #### Powerflow section ####
/// Set base voltage
void
setBaseVoltage
(
Real
baseVoltage
);
/// Initializes component from power flow data
void
calculatePerUnitParameters
(
Real
baseApparentPower
,
Real
baseOmega
);
/// Modify powerflow bus type
void
modifyPowerFlowBusType
(
PowerflowBusType
powerflowBusType
)
override
;
};
};
}
}
}
Dependencies/libcps/Source/CIM/Reader.cpp
View file @
a8db6305
...
...
@@ -314,6 +314,19 @@ Component::Ptr Reader::mapEnergyConsumer(EnergyConsumer* consumer) {
}
else
if
(
mDomain
==
Domain
::
SP
)
{
auto
load
=
std
::
make_shared
<
SP
::
Ph1
::
Load
>
(
consumer
->
mRID
,
consumer
->
name
,
mComponentLogLevel
);
// TODO: Use EnergyConsumer.P and EnergyConsumer.Q if available, overwrite if existent SvPowerFlow data
/*
Real p = 0;
Real q = 0;
if (consumer->p.value){
p = unitValue(consumer->p.value,UnitMultiplier::M);
}
if (consumer->q.value){
q = unitValue(consumer->q.value,UnitMultiplier::M);
}*/
// P and Q values will be set according to SvPowerFlow data
load
->
setParameters
(
0
,
0
,
0
);
load
->
modifyPowerFlowBusType
(
PowerflowBusType
::
PQ
);
// for powerflow solver set as PQ component as default
return
load
;
...
...
@@ -551,28 +564,39 @@ Component::Ptr Reader::mapSynchronousMachine(SynchronousMachine* machine) {
for
(
auto
syncGen
:
genUnit
->
RotatingMachine
)
{
if
(
syncGen
->
mRID
==
machine
->
mRID
){
try
{
mSLog
->
info
(
" InitialP={}"
,
(
float
)
genUnit
->
initialP
.
value
);
//mSLog->info("InitialP {}", genUnit->initialP.value);
}
catch
(
ReadingUninitializedField
*
e
){
genUnit
->
initialP
.
value
=
0
;
std
::
cerr
<<
"Uninitalized InitialP for GeneratingUnit "
<<
genUnit
->
name
<<
".Setting default value of "
<<
genUnit
->
initialP
.
value
<<
std
::
endl
;
}
try
{
mSLog
->
info
(
" maxQ={}"
,
(
float
)
machine
->
maxQ
.
value
);
}
catch
(
ReadingUninitializedField
*
e
){
machine
->
maxQ
.
value
=
1e12
;
std
::
cerr
<<
"Uninitalized maxQ for GeneratingUnit "
<<
genUnit
->
name
<<
".Setting default value of "
<<
machine
->
maxQ
.
value
<<
std
::
endl
;
}
return
std
::
make_shared
<
SP
::
Ph1
::
SynchronGenerator
>
(
machine
->
mRID
,
machine
->
name
,
unitValue
(
genUnit
->
initialP
.
value
,
UnitMultiplier
::
M
),
unitValue
(
machine
->
maxQ
.
value
,
UnitMultiplier
::
M
),
unitValue
(
machine
->
RegulatingControl
->
targetValue
.
value
,
UnitMultiplier
::
k
),
unitValue
(
machine
->
ratedU
.
value
,
UnitMultiplier
::
k
),
unitValue
(
machine
->
ratedS
.
value
,
UnitMultiplier
::
M
),
PowerflowBusType
::
PV
,
mComponentLogLevel
);
// Check whether relevant input data are set, otherwise set default values
Real
setPointActivePower
=
0
;
Real
setPointVoltage
=
0
;
Real
maximumReactivePower
=
1e12
;
try
{
setPointActivePower
=
unitValue
(
genUnit
->
initialP
.
value
,
UnitMultiplier
::
M
);
mSLog
->
info
(
" setPointActivePower={}"
,
setPointActivePower
);
}
catch
(
ReadingUninitializedField
*
e
){
std
::
cerr
<<
"Uninitalized setPointActivePower for GeneratingUnit "
<<
machine
->
name
<<
". Using default value of "
<<
setPointActivePower
<<
std
::
endl
;
}
if
(
machine
->
RegulatingControl
)
{
setPointVoltage
=
unitValue
(
machine
->
RegulatingControl
->
targetValue
.
value
,
UnitMultiplier
::
k
);
mSLog
->
info
(
" setPointVoltage={}"
,
setPointVoltage
);
}
else
{
std
::
cerr
<<
"Uninitalized setPointVoltage for GeneratingUnit "
<<
machine
->
name
<<
". Using default value of "
<<
setPointVoltage
<<
std
::
endl
;
}
try
{
maximumReactivePower
=
unitValue
(
machine
->
maxQ
.
value
,
UnitMultiplier
::
M
);
mSLog
->
info
(
" maximumReactivePower={}"
,
maximumReactivePower
);
}
catch
(
ReadingUninitializedField
*
e
){
std
::
cerr
<<
"Uninitalized maximumReactivePower for GeneratingUnit "
<<
machine
->
name
<<
". Using default value of "
<<
maximumReactivePower
<<
std
::
endl
;
}
auto
gen
=
std
::
make_shared
<
SP
::
Ph1
::
SynchronGenerator
>
(
machine
->
mRID
,
machine
->
name
,
mComponentLogLevel
);
gen
->
setParameters
(
unitValue
(
machine
->
ratedS
.
value
,
UnitMultiplier
::
M
),
unitValue
(
machine
->
ratedU
.
value
,
UnitMultiplier
::
k
),
setPointActivePower
,
setPointVoltage
,
maximumReactivePower
,
PowerflowBusType
::
PV
);
gen
->
setBaseVoltage
(
unitValue
(
machine
->
ratedU
.
value
,
UnitMultiplier
::
k
));
return
gen
;
}
}
...
...
@@ -580,7 +604,7 @@ Component::Ptr Reader::mapSynchronousMachine(SynchronousMachine* machine) {
}
mSLog
->
info
(
"no corresponding initial power for {}"
,
machine
->
name
);
return
std
::
make_shared
<
SP
::
Ph1
::
SynchronGenerator
>
(
machine
->
mRID
,
machine
->
name
,
PowerflowBusType
::
PV
,
mComponentLogLevel
);
return
std
::
make_shared
<
SP
::
Ph1
::
SynchronGenerator
>
(
machine
->
mRID
,
machine
->
name
,
mComponentLogLevel
);
}
else
{
return
std
::
make_shared
<
DP
::
Ph1
::
SynchronGeneratorIdeal
>
(
machine
->
mRID
,
machine
->
name
,
mComponentLogLevel
);
...
...
Dependencies/libcps/Source/SP/SP_Ph1_SynchronGenerator.cpp
View file @
a8db6305
...
...
@@ -23,64 +23,69 @@
using
namespace
CPS
;
SP
::
Ph1
::
SynchronGenerator
::
SynchronGenerator
(
String
uid
,
String
name
,
PowerflowBusType
powerflowBusType
,
Logger
::
Level
logLevel
)
:
PowerComponent
<
Complex
>
(
uid
,
name
,
logLevel
)
{
SP
::
Ph1
::
SynchronGenerator
::
SynchronGenerator
(
String
uid
,
String
name
,
Logger
::
Level
logLevel
)
:
PowerComponent
<
Complex
>
(
uid
,
name
,
logLevel
)
{
setTerminalNumber
(
1
);
mPowerflowBusType
=
powerflowBusType
;
mSLog
->
info
(
"Create {} of type {}"
,
name
,
this
->
type
());
mSLog
->
flush
();
setTerminalNumber
(
1
);
addAttribute
<
Real
>
(
"P_set"
,
&
mSetPointActivePower
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"V_set"
,
&
mSetPointVoltage
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"P_set_pu"
,
&
mSetPointActivePowerPerUnit
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"V_set_pu"
,
&
mSetPointVoltagePerUnit
,
Flags
::
read
|
Flags
::
write
);
};
SP
::
Ph1
::
SynchronGenerator
::
SynchronGenerator
(
String
uid
,
String
name
,
Real
power
,
Real
maxQ
,
Real
vSetPoint
,
Real
ratedU
,
Real
ratedS
,
PowerflowBusType
powerflowBusType
,
Logger
::
Level
logLevel
)
:
SynchronGenerator
(
uid
,
name
,
powerflowBusType
,
logLevel
){
mRatedS
=
ratedS
;
mRatedU
=
ratedU
;
void
SP
::
Ph1
::
SynchronGenerator
::
setParameters
(
Real
ratedApparentPower
,
Real
ratedVoltage
,
Real
setPointActivePower
,
Real
setPointVoltage
,
Real
maximumReactivePower
,
PowerflowBusType
powerflowBusType
)
{
mRatedApparentPower
=
ratedApparentPower
;
mRatedVoltage
=
ratedVoltage
;
mSetPointActivePower
=
setPointActivePower
;
mSetPointVoltage
=
setPointVoltage
;
mMaximumReactivePower
=
maximumReactivePower
;
mPowerflowBusType
=
powerflowBusType
;
switch
(
powerflowBusType
)
{
case
CPS
::
PowerflowBusType
::
PV
:
mSLog
->
info
(
"Create PVNode as member of {}."
,
name
);
mPV
=
std
::
make_shared
<
PVNode
>
(
uid
,
name
,
power
,
vSetPoint
,
maxQ
,
ratedU
,
ratedS
,
logLevel
);
mSLog
->
info
(
"Power={} [W] Voltage={} [pu]"
,
power
,
vSetPoint
/
ratedU
);
break
;
case
CPS
::
PowerflowBusType
::
PQ
:
mSLog
->
info
(
"Setting Synchronous Generator as PQNode is currently not supported."
);
break
;
case
CPS
::
PowerflowBusType
::
VD
:
mSLog
->
info
(
"Create VDNode as member of {}."
,
name
);
mVD
=
std
::
make_shared
<
VDNode
>
(
uid
,
name
,
vSetPoint
/
ratedU
,
logLevel
);
mSLog
->
info
(
"Power={} [W] Voltage={} [pu]"
,
power
,
vSetPoint
);
break
;
default:
throw
std
::
invalid_argument
(
" Invalid power flow bus type "
);
break
;
}
};
mSLog
->
info
(
"Rated Apparent Power={} [VA] Rated Voltage={} [V]"
,
mRatedApparentPower
,
mRatedVoltage
);
mSLog
->
info
(
"Active Power Set Point={} [W] Voltage Set Point={} [V]"
,
mSetPointActivePower
,
mSetPointVoltage
);
mSLog
->
info
(
"Maximum Reactive Power={} [VAr]"
,
mMaximumReactivePower
);
mSLog
->
flush
();
}
// #### Powerflow section ####
void
SP
::
Ph1
::
SynchronGenerator
::
setBaseVoltage
(
Real
baseVoltage
)
{
mBaseVoltage
=
baseVoltage
;
}
void
SP
::
Ph1
::
SynchronGenerator
::
modifyPowerFlowBusType
(
PowerflowBusType
powerflowBusType
)
{
void
SP
::
Ph1
::
SynchronGenerator
::
calculatePerUnitParameters
(
Real
baseApparentPower
,
Real
baseOmega
)
{
mSLog
->
info
(
"#### Calculate Per Unit Parameters for {}"
,
mName
);
mBaseApparentPower
=
baseApparentPower
;
mBaseOmega
=
baseOmega
;
mSLog
->
info
(
"Base Power={} [VA] Base Omega={} [1/s]"
,
mBaseApparentPower
,
mBaseOmega
);
mPowerflowBusType
=
powerflowBusType
;
mSetPointActivePowerPerUnit
=
mSetPointActivePower
/
mBaseApparentPower
;
mSetPointVoltagePerUnit
=
mSetPointVoltage
/
mBaseVoltage
;
mSLog
->
info
(
"Active Power Set Point={} [pu] Voltage Set Point={} [pu]"
,
mSetPointActivePowerPerUnit
,
mSetPointVoltagePerUnit
);
mSLog
->
flush
();
}
void
SP
::
Ph1
::
SynchronGenerator
::
modifyPowerFlowBusType
(
PowerflowBusType
powerflowBusType
)
{
switch
(
powerflowBusType
)
{
case
CPS
::
PowerflowBusType
::
PV
:
mPowerflowBusType
=
powerflowBusType
;
break
;
case
CPS
::
PowerflowBusType
::
PQ
:
mSLog
->
info
(
"
Setting Synchronous Generator as PQNode is currently not supported."
);
throw
std
::
invalid_argument
(
"Setting Synchronous Generator as PQNode is currently not supported."
);
break
;
case
CPS
::
PowerflowBusType
::
VD
:
m
VD
=
std
::
make_shared
<
VDNode
>
(
mUID
,
mName
,
mPV
->
attribute
<
Real
>
(
"V_set_pu"
)
->
get
(),
mLogLevel
)
;
m
PowerflowBusType
=
powerflowBusType
;
break
;
case
CPS
::
PowerflowBusType
::
None
:
break
;
break
;
default:
throw
std
::
invalid_argument
(
" Invalid power flow bus type "
);
break
;
}
}
Source/PFSolver.cpp
View file @
a8db6305
...
...
@@ -90,6 +90,9 @@ void PFSolver::initializeComponents(){
for
(
auto
load
:
mLoads
)
{
load
->
calculatePerUnitParameters
(
mBaseApparentPower
,
mSystem
.
mSystemOmega
);
}
for
(
auto
gen
:
mSynchronGenerators
)
{
gen
->
calculatePerUnitParameters
(
mBaseApparentPower
,
mSystem
.
mSystemOmega
);
}
}
...
...
@@ -97,8 +100,8 @@ void PFSolver::setBaseApparentPower() {
Real
maxPower
=
0.
;
if
(
!
mSynchronGenerators
.
empty
())
{
for
(
auto
gen
:
mSynchronGenerators
)
if
(
std
::
abs
(
gen
->
mPV
->
attribute
<
Real
>
(
"P_set"
)
->
get
())
>
maxPower
)
maxPower
=
std
::
abs
(
gen
->
mPV
->
attribute
<
Real
>
(
"P_set"
)
->
get
());
if
(
std
::
abs
(
gen
->
attribute
<
Real
>
(
"P_set"
)
->
get
())
>
maxPower
)
maxPower
=
std
::
abs
(
gen
->
attribute
<
Real
>
(
"P_set"
)
->
get
());
}
else
if
(
!
mTransformers
.
empty
())
{
for
(
auto
trafo
:
mTransformers
)
...
...
Source/PFSolverPowerPolar.cpp
View file @
a8db6305
...
...
@@ -31,6 +31,17 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, bool keep_last_solut
resize_sol
(
mSystem
.
mNodes
.
size
());
resize_complex_sol
(
mSystem
.
mNodes
.
size
());
// update all components for the new time
for
(
auto
comp
:
mSystem
.
mComponents
)
{
if
(
std
::
shared_ptr
<
CPS
::
SP
::
Ph1
::
Load
>
load
=
std
::
dynamic_pointer_cast
<
CPS
::
SP
::
Ph1
::
Load
>
(
comp
))
{
if
(
load
->
use_profile
)
{
load
->
updatePQ
(
time
);
load
->
calculatePerUnitParameters
(
mBaseApparentPower
,
mSystem
.
mSystemOmega
);
}
}
}
// set initial solution for the new time
for
(
auto
pq
:
mPQBuses
)
{
if
(
!
keep_last_solution
)
{
sol_V
(
pq
->
simNode
())
=
1.0
;
...
...
@@ -38,16 +49,11 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, bool keep_last_solut
sol_V_complex
(
pq
->
simNode
())
=
CPS
::
Complex
(
sol_V
[
pq
->
simNode
()],
sol_D
[
pq
->
simNode
()]);
}
for
(
auto
comp
:
mSystem
.
mComponentsAtNode
[
pq
])
{
if
(
std
::
shared_ptr
<
CPS
::
SP
::
Ph1
::
Load
>
load
=
std
::
dynamic_pointer_cast
<
CPS
::
SP
::
Ph1
::
Load
>
(
comp
))
{
if
(
load
->
use_profile
)
{
load
->
updatePQ
(
time
);
load
->
calculatePerUnitParameters
(
mBaseApparentPower
,
mSystem
.
mSystemOmega
);
}
sol_P
(
pq
->
simNode
())
-=
load
->
attribute
<
CPS
::
Real
>
(
"P_pu"
)
->
get
();
sol_Q
(
pq
->
simNode
())
-=
load
->
attribute
<
CPS
::
Real
>
(
"Q_pu"
)
->
get
();
sol_S_complex
(
pq
->
simNode
())
=
CPS
::
Complex
(
sol_P
[
pq
->
simNode
()],
sol_Q
[
pq
->
simNode
()]);
}
if
(
std
::
shared_ptr
<
CPS
::
SP
::
Ph1
::
Load
>
load
=
std
::
dynamic_pointer_cast
<
CPS
::
SP
::
Ph1
::
Load
>
(
comp
))
{
sol_P
(
pq
->
simNode
())
-=
load
->
attribute
<
CPS
::
Real
>
(
"P_pu"
)
->
get
();
sol_Q
(
pq
->
simNode
())
-=
load
->
attribute
<
CPS
::
Real
>
(
"Q_pu"
)
->
get
();
}
sol_S_complex
(
pq
->
simNode
())
=
CPS
::
Complex
(
sol_P
[
pq
->
simNode
()],
sol_Q
[
pq
->
simNode
()]);
}
}
...
...
@@ -58,8 +64,8 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, bool keep_last_solut
}
for
(
auto
comp
:
mSystem
.
mComponentsAtNode
[
pv
])
{
if
(
std
::
shared_ptr
<
CPS
::
SP
::
Ph1
::
SynchronGenerator
>
gen
=
std
::
dynamic_pointer_cast
<
CPS
::
SP
::
Ph1
::
SynchronGenerator
>
(
comp
))
{
sol_P
(
pv
->
simNode
())
+=
gen
->
mPV
->
attribute
<
CPS
::
Real
>
(
"P_set"
)
->
get
()
/
mBaseApparentPower
;
sol_V
(
pv
->
simNode
())
=
gen
->
mPV
->
attribute
<
CPS
::
Real
>
(
"V_set_pu"
)
->
get
();
sol_P
(
pv
->
simNode
())
+=
gen
->
attribute
<
CPS
::
Real
>
(
"P_set
_pu
"
)
->
get
();
sol_V
(
pv
->
simNode
())
=
gen
->
attribute
<
CPS
::
Real
>
(
"V_set_pu"
)
->
get
();
}
else
if
(
std
::
shared_ptr
<
CPS
::
SP
::
Ph1
::
Load
>
load
=
std
::
dynamic_pointer_cast
<
CPS
::
SP
::
Ph1
::
Load
>
(
comp
))
{
sol_P
(
pv
->
simNode
())
-=
load
->
attribute
<
CPS
::
Real
>
(
"P_pu"
)
->
get
();
...
...
@@ -87,7 +93,7 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, bool keep_last_solut
for
(
auto
gen
:
mSynchronGenerators
)
{
if
(
gen
->
node
(
0
)
->
simNode
()
==
vd
->
simNode
())
sol_V
(
vd
->
simNode
())
=
gen
->
mVD
->
attribute
<
CPS
::
Real
>
(
"V_set_pu"
)
->
get
();
sol_V
(
vd
->
simNode
())
=
gen
->
attribute
<
CPS
::
Real
>
(
"V_set_pu"
)
->
get
();
}
}
...
...
Jan Dinkelbach
@jan.dinkelbach
mentioned in commit
19fd4d89
·
Feb 13, 2020
mentioned in commit
19fd4d89
mentioned in commit 19fd4d89fcf7cdf33003f56fdf28fca96e6f8aab
Toggle commit list
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment