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
69c26264
Commit
69c26264
authored
Oct 29, 2020
by
Jan Dinkelbach
Committed by
Markus Mirz
Nov 21, 2020
Browse files
refactor dp1ph network injection using vs subcomp and add validation example
parent
c585237a
Changes
6
Hide whitespace changes
Inline
Side-by-side
Examples/Cxx/CMakeLists.txt
View file @
69c26264
...
...
@@ -8,7 +8,7 @@ endif()
# targets
set
(
CIRCUIT_SOURCES
# D
ynamic phasor
examples
# D
P
examples
Circuits/DP_VS_RL1.cpp
Circuits/DP_Circuits.cpp
Circuits/DP_Basics_DP_Sims.cpp
...
...
@@ -16,10 +16,12 @@ set(CIRCUIT_SOURCES
Circuits/DP_DecouplingLine.cpp
Circuits/DP_Diakoptics.cpp
Circuits/DP_VSI.cpp
# DP examples with PF initialization
Circuits/DP_Slack_PiLine_PQLoad_with_PF_Init.cpp
Circuits/DP_Slack_PiLine_VSI_with_PF_Init.cpp
Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.cpp
Circuits/EMT_Slack
_PiLine_VSI_with_PF_Init
.cpp
# Combined EMT and DP examples
Circuits/EMT_
DP_
Slack.cpp
Circuits/EMT_DP_VS_RLC_Circuits.cpp
# Powerflow examples
...
...
Examples/Cxx/Circuits/EMT_DP_Slack.cpp
0 → 100644
View file @
69c26264
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
* DPsim
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <DPsim.h>
using
namespace
DPsim
;
using
namespace
CPS
::
DP
;
void
simElements
()
{
Real
timeStep
=
0.00005
;
Real
finalTime
=
1
;
String
simName
=
"DP_Slack_Elements"
;
Logger
::
setLogDir
(
"logs/"
+
simName
);
// Nodes
auto
n1
=
SimNode
::
make
(
"n1"
);
// Components
auto
vs
=
Ph1
::
VoltageSource
::
make
(
"v_1"
);
vs
->
setParameters
(
CPS
::
Math
::
polar
(
100000
,
0
));
auto
load
=
Ph1
::
Resistor
::
make
(
"R_load"
);
load
->
setParameters
(
10000
);
// Topology
vs
->
connect
({
SimNode
::
GND
,
n1
});
load
->
connect
({
n1
,
SimNode
::
GND
});
auto
sys
=
SystemTopology
(
50
,
SystemNodeList
{
n1
},
SystemComponentList
{
vs
,
load
});
// Logging
auto
logger
=
DataLogger
::
make
(
simName
);
logger
->
addAttribute
(
"v1"
,
n1
->
attribute
(
"v"
));
logger
->
addAttribute
(
"i1"
,
vs
->
attribute
(
"i_intf"
));
Simulation
sim
(
simName
);
sim
.
setSystem
(
sys
);
sim
.
setTimeStep
(
timeStep
);
sim
.
setFinalTime
(
finalTime
);
sim
.
addLogger
(
logger
);
sim
.
run
();
}
void
simComponent
()
{
Real
timeStep
=
0.00005
;
Real
finalTime
=
1
;
String
simName
=
"DP_Slack_Component"
;
Logger
::
setLogDir
(
"logs/"
+
simName
);
// Nodes
auto
n1
=
SimNode
::
make
(
"n1"
);
// Components
auto
sl
=
Ph1
::
NetworkInjection
::
make
(
"v_1"
);
sl
->
setParameters
(
CPS
::
Math
::
polar
(
100000
,
0
));
auto
load
=
Ph1
::
Resistor
::
make
(
"R_load"
);
load
->
setParameters
(
10000
);
// Topology
sl
->
connect
({
n1
});
load
->
connect
({
n1
,
SimNode
::
GND
});
auto
sys
=
SystemTopology
(
50
,
SystemNodeList
{
n1
},
SystemComponentList
{
sl
,
load
});
// Logging
auto
logger
=
DataLogger
::
make
(
simName
);
logger
->
addAttribute
(
"v1"
,
n1
->
attribute
(
"v"
));
logger
->
addAttribute
(
"i1"
,
sl
->
attribute
(
"i_intf"
));
Simulation
sim
(
simName
);
sim
.
setSystem
(
sys
);
sim
.
setTimeStep
(
timeStep
);
sim
.
setFinalTime
(
finalTime
);
sim
.
addLogger
(
logger
);
sim
.
run
();
}
int
main
(
int
argc
,
char
*
argv
[])
{
simElements
();
simComponent
();
}
\ No newline at end of file
Examples/Notebooks/Components/Slack.ipynb
0 → 100644
View file @
69c26264
%% Cell type:markdown id: tags:
# Slack Tests
%% Cell type:code id: tags:
```
python
import
villas.dataprocessing.readtools
as
rt
from
villas.dataprocessing.timeseries
import
TimeSeries
as
ts
import
matplotlib.pyplot
as
plt
import
numpy
as
np
#%matplotlib widget
```
%% Cell type:markdown id: tags:
## DP Slack with voltage source element
%% Cell type:code id: tags:
```
python
%%
bash
TOP
=
$
{
TOP
:
-
$
(
git
rev
-
parse
--
show
-
toplevel
)}
PATH
=
$
{
TOP
}
/
build
/
Examples
/
Cxx
EMT_DP_Slack
```
%% Cell type:code id: tags:
```
python
work_dir
=
'logs/DP_Slack_Elements/'
log_name
=
'DP_Slack_Elements'
print
(
work_dir
+
log_name
+
'.csv'
)
slack_elements
=
rt
.
read_timeseries_dpsim
(
work_dir
+
log_name
+
'.csv'
)
slack_elements_dp_shifted
=
ts
.
frequency_shift_list
(
slack_elements
,
50
)
```
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_elements_dp_shifted
[
'v1_shift'
].
time
,
slack_elements_dp_shifted
[
'v1_shift'
].
values
,
label
=
'v1_shift'
)
plt
.
legend
()
```
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_elements_dp_shifted
[
'i1_shift'
].
time
,
slack_elements_dp_shifted
[
'i1_shift'
].
values
,
label
=
'i1_shift'
)
plt
.
legend
()
```
%% Cell type:markdown id: tags:
## DP Slack composite model
%% Cell type:code id: tags:
```
python
work_dir
=
'logs/DP_Slack_Component/'
log_name
=
'DP_Slack_Component'
print
(
work_dir
+
log_name
+
'.csv'
)
slack_component
=
rt
.
read_timeseries_dpsim
(
work_dir
+
log_name
+
'.csv'
)
slack_component_dp_shifted
=
ts
.
frequency_shift_list
(
slack_component
,
50
)
```
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_component_dp_shifted
[
'v1_shift'
].
time
,
slack_component_dp_shifted
[
'v1_shift'
].
values
,
label
=
'v1_shift'
)
plt
.
legend
()
```
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_component_dp_shifted
[
'i1_shift'
].
time
,
slack_component_dp_shifted
[
'i1_shift'
].
values
,
label
=
'i1_shift'
)
plt
.
legend
()
```
%% Cell type:markdown id: tags:
## Error for DP Slack
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_elements_dp_shifted
[
'v1_shift'
].
time
,
slack_elements_dp_shifted
[
'v1_shift'
].
values
-
slack_component_dp_shifted
[
'v1_shift'
].
values
,
label
=
'v1_shift_error'
)
plt
.
legend
()
```
%% Cell type:code id: tags:
```
python
plt
.
figure
()
plt
.
plot
(
slack_elements_dp_shifted
[
'i1_shift'
].
time
,
slack_elements_dp_shifted
[
'i1_shift'
].
values
-
slack_component_dp_shifted
[
'i1_shift'
].
values
,
label
=
'i1_shift_error'
)
plt
.
legend
()
```
%% Cell type:markdown id: tags:
## Assertion for DP Slack
%% Cell type:code id: tags:
```
python
errors_dp_shifted
=
[]
for
name
in
[
'v1_shift'
,
'i1_shift'
]:
errors_dp_shifted
.
append
(
np
.
absolute
(
slack_elements_dp_shifted
[
name
].
values
-
slack_component_dp_shifted
[
name
].
values
).
max
())
print
(
name
+
': '
+
str
(
errors_dp_shifted
[
-
1
]))
assert
np
.
max
(
errors_dp_shifted
)
<
1e-3
```
Source/MNASolver.cpp
View file @
69c26264
...
...
@@ -249,6 +249,9 @@ void MnaSolver<VarType>::initializeSystemWithPrecomputedMatrices() {
}
// Initialize source vector for debugging
// CAUTION: this does not always deliver proper source vector initialization
// as not full pre-step is executed (not involving necessary electrical or signal
// subcomp updates before right vector calculation)
for
(
auto
comp
:
mMNAComponents
)
{
comp
->
mnaApplyRightSideVectorStamp
(
mRightSideVector
);
auto
idObj
=
std
::
dynamic_pointer_cast
<
IdentifiedObject
>
(
comp
);
...
...
models/Include/cps/DP/DP_Ph1_NetworkInjection.h
View file @
69c26264
...
...
@@ -11,30 +11,28 @@
#include <cps/SimPowerComp.h>
#include <cps/Solver/MNAInterface.h>
#include <cps/Solver/DAEInterface.h>
#include <cps/DP/DP_Ph1_VoltageSource.h>
namespace
CPS
{
namespace
DP
{
namespace
Ph1
{
/// \brief
Ideal Voltage source
model
/// \brief
Network injection
model
///
/// This model uses modified nodal analysis to represent an ideal voltage source.
/// For a voltage source between nodes j and k, a new variable
/// (current across the voltage source) is added to the left side vector
/// as unkown and it is taken into account for the equation of node j as
/// positve and for the equation of node k as negative. Moreover
/// a new equation ej - ek = V is added to the problem.
/// This model represents network injections by an ideal voltage source.
class
NetworkInjection
:
public
SimPowerComp
<
Complex
>
,
public
MNAInterface
,
public
DAEInterface
,
public
SharedFactory
<
NetworkInjection
>
{
private:
///
void
updateVoltage
(
Real
time
);
///
Attribute
<
Complex
>::
Ptr
mVoltageRef
;
///
Attribute
<
Real
>::
Ptr
mSrcFreq
;
// ### Electrical Subcomponents ###
/// Voltage source
std
::
shared_ptr
<
DP
::
Ph1
::
VoltageSource
>
mSubVoltageSource
;
// #### solver ####
/// Vector to collect subcomponent right vector stamps
std
::
vector
<
const
Matrix
*>
mRightVectorStamps
;
public:
/// Defines UID, name, component parameters and logging level
NetworkInjection
(
String
uid
,
String
name
,
Logger
::
Level
loglevel
=
Logger
::
Level
::
off
);
...
...
@@ -50,78 +48,52 @@ namespace Ph1 {
// #### General ####
/// Initializes component from power flow data
void
initializeFromNodesAndTerminals
(
Real
frequency
);
///
void
setSourceValue
(
Complex
voltage
);
///
/// Setter for reference voltage parameters
void
setParameters
(
Complex
voltageRef
,
Real
srcFreq
=
-
1
);
// #### MNA Section ####
/// Initializes internal variables of the component
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
);
void
mnaApplySystemMatrixStampHarm
(
Matrix
&
systemMatrix
,
Int
freqIdx
);
/// Stamps right side (source) vector
void
mnaApplyRightSideVectorStamp
(
Matrix
&
rightVector
);
void
mnaApplyRightSideVectorStampHarm
(
Matrix
&
rightVector
);
/// Returns current through the component
void
mnaUpdateCurrent
(
const
Matrix
&
leftVector
);
/// Updates voltage across component
void
mnaUpdateVoltage
(
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
);
class
MnaPreStep
:
public
Task
{
class
MnaPreStep
:
public
CPS
::
Task
{
public:
MnaPreStep
(
NetworkInjection
&
NetworkInjection
)
:
Task
(
NetworkInjection
.
mName
+
".MnaPreStep"
),
mNetworkInjection
(
NetworkInjection
)
{
mAttributeDependencies
.
push_back
(
NetworkInjection
.
attribute
(
"V_ref"
));
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"right_vector"
));
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"v_intf"
));
MnaPreStep
(
NetworkInjection
&
networkInjection
)
:
Task
(
networkInjection
.
mName
+
".MnaPreStep"
),
mNetworkInjection
(
networkInjection
)
{
mNetworkInjection
.
mnaAddPreStepDependencies
(
mPrevStepDependencies
,
mAttributeDependencies
,
mModifiedAttributes
);
}
void
execute
(
Real
time
,
Int
timeStepCount
);
private:
NetworkInjection
&
mNetworkInjection
;
};
void
execute
(
Real
time
,
Int
timeStepCount
)
{
mNetworkInjection
.
mnaPreStep
(
time
,
timeStepCount
);
};
class
MnaPostStep
:
public
Task
{
public:
MnaPostStep
(
NetworkInjection
&
NetworkInjection
,
Attribute
<
Matrix
>::
Ptr
leftVector
)
:
Task
(
NetworkInjection
.
mName
+
".MnaPostStep"
),
mNetworkInjection
(
NetworkInjection
),
mLeftVector
(
leftVector
)
{
mAttributeDependencies
.
push_back
(
mLeftVector
);
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"i_intf"
));
}
void
execute
(
Real
time
,
Int
timeStepCount
);
private:
NetworkInjection
&
mNetworkInjection
;
Attribute
<
Matrix
>::
Ptr
mLeftVector
;
};
class
MnaP
re
Step
Harm
:
public
CPS
::
Task
{
class
MnaP
ost
Step
:
public
CPS
::
Task
{
public:
MnaPreStepHarm
(
NetworkInjection
&
NetworkInjection
)
:
Task
(
NetworkInjection
.
mName
+
".MnaPreStepHarm"
),
mNetworkInjection
(
NetworkInjection
)
{
mAttributeDependencies
.
push_back
(
NetworkInjection
.
attribute
(
"V_ref"
));
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"right_vector"
));
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"v_intf"
));
MnaPostStep
(
NetworkInjection
&
networkInjection
,
Attribute
<
Matrix
>::
Ptr
leftVector
)
:
Task
(
networkInjection
.
mName
+
".MnaPostStep"
),
mNetworkInjection
(
networkInjection
),
mLeftVector
(
leftVector
)
{
mNetworkInjection
.
mnaAddPostStepDependencies
(
mPrevStepDependencies
,
mAttributeDependencies
,
mModifiedAttributes
,
mLeftVector
);
}
void
execute
(
Real
time
,
Int
timeStepCount
);
private:
NetworkInjection
&
mNetworkInjection
;
};
void
execute
(
Real
time
,
Int
timeStepCount
)
{
mNetworkInjection
.
mnaPostStep
(
time
,
timeStepCount
,
mLeftVector
);
};
class
MnaPostStepHarm
:
public
CPS
::
Task
{
public:
MnaPostStepHarm
(
NetworkInjection
&
NetworkInjection
,
std
::
vector
<
Attribute
<
Matrix
>::
Ptr
>
leftVectors
)
:
Task
(
NetworkInjection
.
mName
+
".MnaPostStepHarm"
),
mNetworkInjection
(
NetworkInjection
),
mLeftVectors
(
leftVectors
)
{
for
(
UInt
i
=
0
;
i
<
mLeftVectors
.
size
();
i
++
)
mAttributeDependencies
.
push_back
(
mLeftVectors
[
i
]);
mModifiedAttributes
.
push_back
(
mNetworkInjection
.
attribute
(
"i_intf"
));
}
void
execute
(
Real
time
,
Int
timeStepCount
);
private:
NetworkInjection
&
mNetworkInjection
;
std
::
vector
<
Attribute
<
Matrix
>::
Ptr
>
mLeftVector
s
;
Attribute
<
Matrix
>::
Ptr
mLeftVector
;
};
// #### DAE Section ####
...
...
models/Source/DP/DP_Ph1_NetworkInjection.cpp
View file @
69c26264
...
...
@@ -12,13 +12,22 @@ using namespace CPS;
DP
::
Ph1
::
NetworkInjection
::
NetworkInjection
(
String
uid
,
String
name
,
Logger
::
Level
logLevel
)
:
SimPowerComp
<
Complex
>
(
uid
,
name
,
logLevel
)
{
setVirtualNodeNumber
(
1
);
setVirtualNodeNumber
(
0
);
setTerminalNumber
(
1
);
mSLog
->
info
(
"Create {} {}"
,
this
->
type
(),
name
);
mIntfVoltage
=
MatrixComp
::
Zero
(
1
,
1
);
mIntfCurrent
=
MatrixComp
::
Zero
(
1
,
1
);
addAttribute
<
Complex
>
(
"V_ref"
,
Flags
::
read
|
Flags
::
write
);
addAttribute
<
Real
>
(
"f_src"
,
Flags
::
read
|
Flags
::
write
);
// Create electrical sub components
mSubVoltageSource
=
std
::
make_shared
<
DP
::
Ph1
::
VoltageSource
>
(
mName
+
"_vs"
,
mLogLevel
);
mSubComponents
.
push_back
(
mSubVoltageSource
);
mSLog
->
info
(
"Electrical subcomponents: "
);
for
(
auto
subcomp
:
mSubComponents
)
mSLog
->
info
(
"- {}"
,
subcomp
->
name
());
addAttributeRef
<
Complex
>
(
"V_ref"
,
mSubVoltageSource
->
attribute
<
Complex
>
(
"V_ref"
),
Flags
::
read
|
Flags
::
write
);
addAttributeRef
<
Real
>
(
"f_src"
,
mSubVoltageSource
->
attribute
<
Real
>
(
"f_src"
),
Flags
::
read
|
Flags
::
write
);
}
SimPowerComp
<
Complex
>::
Ptr
DP
::
Ph1
::
NetworkInjection
::
clone
(
String
name
)
{
...
...
@@ -28,25 +37,26 @@ SimPowerComp<Complex>::Ptr DP::Ph1::NetworkInjection::clone(String name) {
}
void
DP
::
Ph1
::
NetworkInjection
::
setParameters
(
Complex
voltageRef
,
Real
srcFreq
)
{
attribute
<
Complex
>
(
"V_ref"
)
->
set
(
voltageRef
);
attribute
<
Real
>
(
"f_src"
)
->
set
(
srcFreq
);
mParametersSet
=
true
;
mSubVoltageSource
->
attribute
<
Complex
>
(
"V_ref"
)
->
set
(
voltageRef
);
mSubVoltageSource
->
attribute
<
Real
>
(
"f_src"
)
->
set
(
srcFreq
);
mSLog
->
info
(
"
\n
Voltage Ref={:s} [V]"
"
\n
Frequency={:s} [Hz]"
,
Logger
::
phasorToString
(
voltageRef
),
Logger
::
realToString
(
srcFreq
));
}
void
DP
::
Ph1
::
NetworkInjection
::
initializeFromNodesAndTerminals
(
Real
frequency
)
{
mVoltageRef
=
attribute
<
Complex
>
(
"V_ref"
);
mSrcFreq
=
attribute
<
Real
>
(
"f_src"
);
if
(
mVoltageRef
->
get
()
==
Complex
(
0
,
0
))
//mVoltageRef->set(Complex(std::abs(initialSingleVoltage(0).real()), std::abs(initialSingleVoltage(0).imag())));
mVoltageRef
->
set
(
initialSingleVoltage
(
0
));
mSLog
->
info
(
"
\n
--- Initialization from node voltages ---"
"
\n
Voltage across: {:e}<{:e}"
"
\n
Terminal 0 voltage: {:e}<{:e}"
"
\n
--- Initialization from node voltages ---"
,
std
::
abs
(
mVoltageRef
->
get
()),
std
::
arg
(
mVoltageRef
->
get
()),
std
::
abs
(
initialSingleVoltage
(
0
)),
std
::
arg
(
initialSingleVoltage
(
0
)));
// Connect electrical subcomponents
mSubVoltageSource
->
connect
({
SimNode
::
GND
,
node
(
0
)
});
// Initialize electrical subcomponents
for
(
auto
subcomp
:
mSubComponents
)
{
subcomp
->
initialize
(
mFrequencies
);
subcomp
->
initializeFromNodesAndTerminals
(
frequency
);
}
}
// #### MNA functions ####
...
...
@@ -55,90 +65,83 @@ void DP::Ph1::NetworkInjection::mnaInitialize(Real omega, Real timeStep, Attribu
MNAInterface
::
mnaInitialize
(
omega
,
timeStep
);
updateMatrixNodeIndices
();
mIntfVoltage
(
0
,
0
)
=
mVoltageRef
->
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
);
}
// initialize electrical subcomponents
for
(
auto
subcomp
:
mSubComponents
)
if
(
auto
mnasubcomp
=
std
::
dynamic_pointer_cast
<
MNAInterface
>
(
subcomp
))
mnasubcomp
->
mnaInitialize
(
omega
,
timeStep
,
leftVector
);
void
DP
::
Ph1
::
NetworkInjection
::
mnaInitializeHarm
(
Real
omega
,
Real
timeStep
,
std
::
vector
<
Attribute
<
Matrix
>::
Ptr
>
leftVectors
)
{
MNAInterface
::
mnaInitialize
(
omega
,
timeStep
);
updateMatrixNodeIndices
();
// collect right side vectors of subcomponents
mRightVectorStamps
.
push_back
(
&
mSubVoltageSource
->
attribute
<
Matrix
>
(
"right_vector"
)
->
get
());
mIntfVoltage
(
0
,
0
)
=
mVoltageRef
->
get
();
// collect tasks
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPreStep
>
(
*
this
));
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPostStep
>
(
*
this
,
leftVector
));
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPreStepHarm
>
(
*
this
));
mMnaTasks
.
push_back
(
std
::
make_shared
<
MnaPostStepHarm
>
(
*
this
,
leftVectors
));
mRightVector
=
Matrix
::
Zero
(
leftVectors
[
0
]
->
get
().
rows
(),
mNumFreqs
);
mRightVector
=
Matrix
::
Zero
(
leftVector
->
get
().
rows
(),
1
);
}
void
DP
::
Ph1
::
NetworkInjection
::
mnaApplySystemMatrixStamp
(
Matrix
&
systemMatrix
)
{
for
(
UInt
freq
=
0
;
freq
<
mNumFreqs
;
freq
++
)
{
Math
::
setMatrixElement
(
systemMatrix
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
matrixNodeIndex
(
0
),
Complex
(
1
,
0
),
mNumFreqs
,
freq
);
Math
::
setMatrixElement
(
systemMatrix
,
matrixNodeIndex
(
0
),
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
Complex
(
1
,
0
),
mNumFreqs
,
freq
);
mSLog
->
info
(
"-- Stamp frequency {:d} ---"
,
freq
);
mSLog
->
info
(
"Add {:f} to system at ({:d},{:d})"
,
1.
,
matrixNodeIndex
(
0
),
mVirtualNodes
[
0
]
->
matrixNodeIndex
());
mSLog
->
info
(
"Add {:f} to system at ({:d},{:d})"
,
1.
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
matrixNodeIndex
(
0
));
}
}
void
DP
::
Ph1
::
NetworkInjection
::
mnaApplySystemMatrixStampHarm
(
Matrix
&
systemMatrix
,
Int
freqIdx
)
{
Math
::
setMatrixElement
(
systemMatrix
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
matrixNodeIndex
(
0
),
Complex
(
1
,
0
));
Math
::
setMatrixElement
(
systemMatrix
,
matrixNodeIndex
(
0
),
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
Complex
(
1
,
0
));
mSLog
->
info
(
"-- Stamp frequency {:d} ---"
,
freqIdx
);
mSLog
->
info
(
"Add {:f} to system at ({:d},{:d})"
,
1.
,
matrixNodeIndex
(
0
),
mVirtualNodes
[
0
]
->
matrixNodeIndex
());
mSLog
->
info
(
"Add {:f} to system at ({:d},{:d})"
,
1.
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
matrixNodeIndex
(
0
));
for
(
auto
subcomp
:
mSubComponents
)
if
(
auto
mnasubcomp
=
std
::
dynamic_pointer_cast
<
MNAInterface
>
(
subcomp
))
mnasubcomp
->
mnaApplySystemMatrixStamp
(
systemMatrix
);
}
void
DP
::
Ph1
::
NetworkInjection
::
mnaApplyRightSideVectorStamp
(
Matrix
&
rightVector
)
{
// TODO: Is this correct with two nodes not gnd?
Math
::
setVectorElement
(
rightVector
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
mIntfVoltage
(
0
,
0
),
mNumFreqs
);
SPDLOG_LOGGER_DEBUG
(
mSLog
,
"Add {:s} to source vector at {:d}"
,
Logger
::
complexToString
(
mIntfVoltage
(
0
,
0
)),
mVirtualNodes
[
0
]
->
matrixNodeIndex
());
}
rightVector
.
setZero
();
for
(
auto
stamp
:
mRightVectorStamps
)
rightVector
+=
*
stamp
;
void
DP
::
Ph1
::
NetworkInjection
::
mnaApplyRightSideVectorStampHarm
(
Matrix
&
rightVector
)
{
for
(
UInt
freq
=
0
;
freq
<
mNumFreqs
;
freq
++
)
{
// TODO: Is this correct with two nodes not gnd?
Math
::
setVectorElement
(
rightVector
,
mVirtualNodes
[
0
]
->
matrixNodeIndex
(),
mIntfVoltage
(
0
,
freq
),
1
,
0
,
freq
);
SPDLOG_LOGGER_DEBUG
(
mSLog
,
"Add {:s} to source vector at {:d}"
,
Logger
::
complexToString
(
mIntfVoltage
(
0
,
freq
)),
mVirtualNodes
[
0
]
->
matrixNodeIndex
());
}
mSLog
->
info
(
"Right Side Vector: {:s}"
,
Logger
::
matrixToString
(
rightVector
));
}
void
DP
::
Ph1
::
NetworkInjection
::
updateVoltage
(
Real
time
)
{
if
(
mSrcFreq
->
get
()
<
0
)
{
mIntfVoltage
(
0
,
0
)
=
mVoltageRef
->
get
();
}
else
{
mIntfVoltage
(
0
,
0
)
=
Complex
(
Math
::
abs
(
mVoltageRef
->
get
())
*
cos
(
time
*
2.
*
PI
*
mSrcFreq
->
get
()
+
Math
::
phase
(
mVoltageRef
->
get
())),
Math
::
abs
(
mVoltageRef
->
get
())
*
sin
(
time
*
2.
*
PI
*
mSrcFreq
->
get
()
+
Math
::
phase
(
mVoltageRef
->
get
())
));
}
void
DP
::
Ph1
::
NetworkInjection
::
mnaAddPreStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
)
{
// add pre-step dependencies of subcomponents
for
(
auto
subcomp
:
mSubComponents
)
if
(
auto
mnasubcomp
=
std
::
dynamic_pointer_cast
<
MNAInterface
>
(
subcomp
))
mnasubcomp
->
mnaAddPreStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
);
// add pre-step dependencies of component itself
prevStepDependencies
.
push_back
(
attribute
(
"i_intf"
));
prevStepDependencies
.
push_back
(
attribute
(
"v_intf"
));
modifiedAttributes
.
push_back
(
attribute
(
"right_vector"
));
}
void
DP
::
Ph1
::
NetworkInjection
::
MnaPreStep
::
execute
(
Real
time
,
Int
timeStepCount
)
{
mNetworkInjection
.
updateVoltage
(
time
);
mNetworkInjection
.
mnaApplyRightSideVectorStamp
(
mNetworkInjection
.
mRightVector
);
void
DP
::
Ph1
::
NetworkInjection
::
mnaPreStep
(
Real
time
,
Int
timeStepCount
)
{
// pre-step of subcomponents
for
(
auto
subcomp
:
mSubComponents
)
if
(
auto
mnasubcomp
=
std
::
dynamic_pointer_cast
<
MNAInterface
>
(
subcomp
))
mnasubcomp
->
mnaPreStep
(
time
,
timeStepCount
);
// pre-step of component itself
mnaApplyRightSideVectorStamp
(
mRightVector
);
}
void
DP
::
Ph1
::
NetworkInjection
::
MnaPreStepHarm
::
execute
(
Real
time
,
Int
timeStepCount
)
{
mNetworkInjection
.
updateVoltage
(
time
);
mNetworkInjection
.
mnaApplyRightSideVectorStampHarm
(
mNetworkInjection
.
mRightVector
);
void
DP
::
Ph1
::
NetworkInjection
::
mnaAddPostStepDependencies
(
AttributeBase
::
List
&
prevStepDependencies
,
AttributeBase
::
List
&
attributeDependencies
,
AttributeBase
::
List
&
modifiedAttributes
,
Attribute
<
Matrix
>::
Ptr
&
leftVector
)
{
// add post-step dependencies of subcomponents
for
(
auto
subcomp
:
mSubComponents
)
if
(
auto
mnasubcomp
=
std
::
dynamic_pointer_cast
<
MNAInterface
>
(
subcomp
))
mnasubcomp
->
mnaAddPostStepDependencies
(
prevStepDependencies
,
attributeDependencies
,
modifiedAttributes
,
leftVector
);
// add post-step dependencies of component itself
attributeDependencies
.
push_back
(
leftVector
);
modifiedAttributes
.
push_back
(
attribute
(
"v_intf"
));