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
9940a47e
Commit
9940a47e
authored
Sep 06, 2017
by
Georg Martin Reinke
Browse files
add Python functionality as new command-line option
Former-commit-id:
7d7a684a
parent
6425cf64
Changes
1
Hide whitespace changes
Inline
Side-by-side
Source/DPsimMain.cpp
View file @
9940a47e
...
...
@@ -17,6 +17,7 @@ void usage() {
<<
" -i/--interface OBJ_NAME: prefix for the names of the shmem objects used for communication (default: /dpsim)"
<<
std
::
endl
<<
" -n/--node NODE_ID: RDF id of the node where the interfacing voltage/current source should be placed"
<<
std
::
endl
<<
" -r/--realtime: enable realtime simulation "
<<
std
::
endl
<<
" -p/--python: provide an interactive python shell for simulation control"
<<
std
::
endl
<<
" -s/--split INDEX: index of this instance for distributed simulation (0 or 1)"
<<
std
::
endl
<<
" -t/--timestep TIMESTEP: simulation timestep in seconds (default: 1e-3)"
<<
std
::
endl
;
}
...
...
@@ -44,15 +45,26 @@ enum SimState {
static
pthread_t
simThread
;
struct
SimContext
{
Simulation
*
sim
;
Logger
*
log
,
*
llog
,
*
rlog
;
Simulation
&
sim
;
Logger
&
log
,
&
llog
,
&
rlog
;
pthread_cond_t
cond
;
pthread_mutex_t
mut
;
std
::
atomic_int
stop
,
numStep
;
SimState
state
;
SimContext
(
Simulation
&
,
Logger
&
,
Logger
&
,
Logger
&
);
};
static
SimContext
globalCtx
;
SimContext
::
SimContext
(
Simulation
&
sim
,
Logger
&
log
,
Logger
&
llog
,
Logger
&
rlog
)
:
sim
(
sim
),
log
(
log
),
llog
(
llog
),
rlog
(
rlog
)
{
pthread_mutex_init
(
&
this
->
mut
,
nullptr
);
pthread_cond_init
(
&
this
->
cond
,
nullptr
);
this
->
stop
=
0
;
this
->
numStep
=
0
;
this
->
state
=
StateStopped
;
}
static
SimContext
*
globalCtx
;
static
void
*
simThreadFunction
(
void
*
arg
)
{
bool
running
=
true
;
...
...
@@ -60,9 +72,9 @@ static void* simThreadFunction(void* arg) {
ctx
->
numStep
=
0
;
while
(
running
)
{
running
=
ctx
->
sim
->
step
(
*
ctx
->
log
,
*
ctx
->
llog
,
*
ctx
->
rlog
);
running
=
ctx
->
sim
.
step
(
ctx
->
log
,
ctx
->
llog
,
ctx
->
rlog
);
ctx
->
numStep
++
;
ctx
->
sim
->
increaseByTimeStep
();
ctx
->
sim
.
increaseByTimeStep
();
if
(
ctx
->
stop
)
{
pthread_mutex_lock
(
&
ctx
->
mut
);
ctx
->
state
=
StatePaused
;
...
...
@@ -79,83 +91,73 @@ static void* simThreadFunction(void* arg) {
return
nullptr
;
}
void
initContext
(
SimContext
*
ctx
)
{
// TODO: pass parameters like frequency, timestep to this function, or read them from the command line
ctx
->
log
=
new
Logger
();
ctx
->
llog
=
new
Logger
(
"lvector-python.log"
);
ctx
->
rlog
=
new
Logger
(
"rvector-python.log"
);
ctx
->
sim
=
new
Simulation
(
components
,
2
*
PI
*
50
,
1e-3
,
100
,
*
globalCtx
.
log
);
pthread_mutex_init
(
&
ctx
->
mut
,
nullptr
);
pthread_cond_init
(
&
ctx
->
cond
,
nullptr
);
}
static
PyObject
*
pythonStart
(
PyObject
*
self
,
PyObject
*
args
)
{
pthread_mutex_lock
(
&
globalCtx
.
mut
);
if
(
globalCtx
.
state
!=
StateStopped
)
{
pthread_mutex_lock
(
&
globalCtx
->
mut
);
if
(
globalCtx
->
state
!=
StateStopped
)
{
PyErr_SetString
(
PyExc_SystemError
,
"Simulation already started"
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
return
nullptr
;
}
globalCtx
.
stop
=
0
;
globalCtx
.
state
=
StateRunning
;
pthread_create
(
&
simThread
,
nullptr
,
simThreadFunction
,
&
globalCtx
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
globalCtx
->
stop
=
0
;
globalCtx
->
state
=
StateRunning
;
pthread_create
(
&
simThread
,
nullptr
,
simThreadFunction
,
globalCtx
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
pythonStep
(
PyObject
*
self
,
PyObject
*
args
)
{
pthread_mutex_lock
(
&
globalCtx
.
mut
);
int
oldStep
=
globalCtx
.
numStep
;
if
(
globalCtx
.
state
==
StateStopped
)
{
globalCtx
.
state
=
StateRunning
;
globalCtx
.
stop
=
1
;
pthread_create
(
&
simThread
,
nullptr
,
simThreadFunction
,
&
globalCtx
);
}
else
if
(
globalCtx
.
state
==
StatePaused
)
{
globalCtx
.
stop
=
1
;
pthread_cond_signal
(
&
globalCtx
.
cond
);
pthread_mutex_lock
(
&
globalCtx
->
mut
);
int
oldStep
=
globalCtx
->
numStep
;
if
(
globalCtx
->
state
==
StateStopped
)
{
globalCtx
->
state
=
StateRunning
;
globalCtx
->
stop
=
1
;
pthread_create
(
&
simThread
,
nullptr
,
simThreadFunction
,
globalCtx
);
}
else
if
(
globalCtx
->
state
==
StatePaused
)
{
globalCtx
->
stop
=
1
;
pthread_cond_signal
(
&
globalCtx
->
cond
);
}
else
{
PyErr_SetString
(
PyExc_SystemError
,
"Simulation currently running"
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
return
nullptr
;
}
while
(
globalCtx
.
numStep
==
oldStep
)
pthread_cond_wait
(
&
globalCtx
.
cond
,
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
while
(
globalCtx
->
numStep
==
oldStep
)
pthread_cond_wait
(
&
globalCtx
->
cond
,
&
globalCtx
->
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
pythonPause
(
PyObject
*
self
,
PyObject
*
args
)
{
pthread_mutex_lock
(
&
globalCtx
.
mut
);
if
(
globalCtx
.
state
!=
StateRunning
)
{
pthread_mutex_lock
(
&
globalCtx
->
mut
);
if
(
globalCtx
->
state
!=
StateRunning
)
{
PyErr_SetString
(
PyExc_SystemError
,
"Simulation not currently running"
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
return
nullptr
;
}
globalCtx
.
stop
=
1
;
pthread_cond_signal
(
&
globalCtx
.
cond
);
while
(
globalCtx
.
state
==
StateRunning
)
pthread_cond_wait
(
&
globalCtx
.
cond
,
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
globalCtx
->
stop
=
1
;
pthread_cond_signal
(
&
globalCtx
->
cond
);
while
(
globalCtx
->
state
==
StateRunning
)
pthread_cond_wait
(
&
globalCtx
->
cond
,
&
globalCtx
->
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
Py_INCREF
(
Py_None
);
return
Py_None
;
}
static
PyObject
*
pythonWait
(
PyObject
*
self
,
PyObject
*
args
)
{
pthread_mutex_lock
(
&
globalCtx
.
mut
);
if
(
globalCtx
.
state
==
StateStopped
)
{
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
pthread_mutex_lock
(
&
globalCtx
->
mut
);
if
(
globalCtx
->
state
==
StateStopped
)
{
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
Py_INCREF
(
Py_None
);
return
Py_None
;
}
else
if
(
globalCtx
.
state
==
StatePaused
)
{
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
}
else
if
(
globalCtx
->
state
==
StatePaused
)
{
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
PyErr_SetString
(
PyExc_SystemError
,
"Simulation currently paused"
);
return
nullptr
;
}
while
(
globalCtx
.
state
==
StateRunning
)
pthread_cond_wait
(
&
globalCtx
.
cond
,
&
globalCtx
.
mut
);
pthread_mutex_unlock
(
&
globalCtx
.
mut
);
while
(
globalCtx
->
state
==
StateRunning
)
pthread_cond_wait
(
&
globalCtx
->
cond
,
&
globalCtx
->
mut
);
pthread_mutex_unlock
(
&
globalCtx
->
mut
);
Py_INCREF
(
Py_None
);
return
Py_None
;
}
...
...
@@ -177,9 +179,21 @@ static PyObject* PyInit_dpsim(void) {
return
PyModule_Create
(
&
dpsimModule
);
}
int
doPythonLoop
(
SimContext
*
sim
)
{
PyImport_AppendInittab
(
"dpsim"
,
&
PyInit_dpsim
);
Py_Initialize
();
while
(
std
::
cin
.
good
()
&&
Py_IsInitialized
())
{
std
::
cout
<<
"> "
;
std
::
string
line
;
std
::
getline
(
std
::
cin
,
line
);
PyRun_SimpleString
(
line
.
c_str
());
}
}
// TODO: that many platform-dependent ifdefs inside main are kind of ugly
int
cimMain
(
int
argc
,
const
char
*
argv
[])
{
bool
rt
=
false
;
bool
rt
=
false
,
python
=
false
;
int
i
,
split
=
-
1
;
Real
frequency
=
2
*
PI
*
50
,
timestep
=
0.001
,
duration
=
0.3
;
std
::
string
interfaceBase
=
"/dpsim"
;
...
...
@@ -191,34 +205,28 @@ int cimMain(int argc, const char* argv[]) {
// Parse arguments
for
(
i
=
1
;
i
<
argc
;
i
++
)
{
if
(
!
strcmp
(
argv
[
i
],
"-f"
)
||
!
strcmp
(
argv
[
i
],
"--frequency"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -f/--frequency; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
if
(
!
parseFloat
(
argv
[
++
i
],
&
frequency
)
||
frequency
<=
0
)
{
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for system frequency"
<<
std
::
endl
;
return
1
;
}
frequency
*=
2
*
PI
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-t"
)
||
!
strcmp
(
argv
[
i
],
"--timestep"
))
{
if
(
!
strcmp
(
argv
[
i
],
"-d"
)
||
!
strcmp
(
argv
[
i
],
"--duration"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -
t
/--
timestep
; see 'DPsim --help' for usage"
<<
std
::
endl
;
std
::
cerr
<<
"Missing argument for -
d
/--
duration
; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
if
(
!
parseFloat
(
argv
[
++
i
],
&
timestep
)
||
timestep
<=
0
)
{
std
::
cerr
<<
"Invali
e
d setting "
<<
argv
[
i
]
<<
" for the
timestep
"
<<
std
::
endl
;
if
(
!
parseFloat
(
argv
[
++
i
],
&
duration
)
||
duration
<=
0
)
{
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for the
duration
"
<<
std
::
endl
;
return
1
;
}
}
else
if
(
!
strcmp
(
argv
[
i
],
"-
d
"
)
||
!
strcmp
(
argv
[
i
],
"--
duration
"
))
{
}
else
if
(
!
strcmp
(
argv
[
i
],
"-
f
"
)
||
!
strcmp
(
argv
[
i
],
"--
frequency
"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -
d
/--
duration
; see 'DPsim --help' for usage"
<<
std
::
endl
;
std
::
cerr
<<
"Missing argument for -
f
/--
frequency
; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
if
(
!
parseFloat
(
argv
[
++
i
],
&
duration
)
||
duration
<=
0
)
{
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for
the duration
"
<<
std
::
endl
;
if
(
!
parseFloat
(
argv
[
++
i
],
&
frequency
)
||
frequency
<=
0
)
{
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for
system frequency
"
<<
std
::
endl
;
return
1
;
}
frequency
*=
2
*
PI
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
||
!
strcmp
(
argv
[
i
],
"--help"
))
{
usage
();
return
0
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-i"
)
||
!
strcmp
(
argv
[
i
],
"--interface"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -i/--interface; see 'DPsim --help' for usage"
<<
std
::
endl
;
...
...
@@ -229,6 +237,16 @@ int cimMain(int argc, const char* argv[]) {
return
1
;
}
interfaceBase
=
std
::
string
(
argv
[
i
]);
}
else
if
(
!
strcmp
(
argv
[
i
],
"-n"
)
||
!
strcmp
(
argv
[
i
],
"--node"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -n/--node; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
splitNode
=
std
::
string
(
argv
[
++
i
]);
}
else
if
(
!
strcmp
(
argv
[
i
],
"-p"
)
||
!
strcmp
(
argv
[
i
],
"--python"
))
{
python
=
true
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-r"
)
||
!
strcmp
(
argv
[
i
],
"--realtime"
))
{
rt
=
true
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-s"
)
||
!
strcmp
(
argv
[
i
],
"--split"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -s/--split; see 'DPsim --help' for usage"
<<
std
::
endl
;
...
...
@@ -238,17 +256,15 @@ int cimMain(int argc, const char* argv[]) {
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for the split index"
<<
std
::
endl
;
return
1
;
}
}
else
if
(
!
strcmp
(
argv
[
i
],
"-
n
"
)
||
!
strcmp
(
argv
[
i
],
"--
node
"
))
{
}
else
if
(
!
strcmp
(
argv
[
i
],
"-
t
"
)
||
!
strcmp
(
argv
[
i
],
"--
timestep
"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -n/--node; see 'DPsim --help' for usage"
<<
std
::
endl
;
std
::
cerr
<<
"Missing argument for -t/--timestep; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
if
(
!
parseFloat
(
argv
[
++
i
],
&
timestep
)
||
timestep
<=
0
)
{
std
::
cerr
<<
"Invalied setting "
<<
argv
[
i
]
<<
" for the timestep"
<<
std
::
endl
;
return
1
;
}
splitNode
=
std
::
string
(
argv
[
++
i
]);
}
else
if
(
!
strcmp
(
argv
[
i
],
"-r"
)
||
!
strcmp
(
argv
[
i
],
"--realtime"
))
{
rt
=
true
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
||
!
strcmp
(
argv
[
i
],
"--help"
))
{
usage
();
return
0
;
}
else
if
(
argv
[
i
][
0
]
==
'-'
)
{
std
::
cerr
<<
"Unknown option "
<<
argv
[
i
]
<<
" ; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
...
...
@@ -270,6 +286,10 @@ int cimMain(int argc, const char* argv[]) {
return
1
;
}
#endif
if
(
python
&&
(
split
>=
0
||
splitNode
.
length
()
!=
0
||
rt
))
{
std
::
cerr
<<
"Realtime and distributed simulation currently not supported in combination with Python"
<<
std
::
endl
;
return
1
;
}
// Parse CIM files
CIMReader
reader
(
frequency
);
...
...
@@ -320,42 +340,32 @@ int cimMain(int argc, const char* argv[]) {
// Do the actual simulation
Logger
log
(
logName
),
llog
(
llogName
),
rlog
(
rlogName
);
Simulation
sim
(
components
,
frequency
,
timestep
,
duration
,
log
);
if
(
python
)
{
globalCtx
=
new
SimContext
(
sim
,
log
,
llog
,
rlog
);
doPythonLoop
(
globalCtx
);
}
else
{
#ifdef __linux__
if
(
intf
)
sim
.
addExternalInterface
(
intf
);
if
(
intf
)
sim
.
addExternalInterface
(
intf
);
if
(
rt
)
{
sim
.
runRT
(
RTTimerFD
,
true
,
log
,
llog
,
rlog
);
}
else
{
while
(
sim
.
step
(
log
,
llog
,
rlog
))
sim
.
increaseByTimeStep
();
}
if
(
rt
)
{
sim
.
runRT
(
RTTimerFD
,
true
,
log
,
llog
,
rlog
);
}
else
{
while
(
sim
.
step
(
log
,
llog
,
rlog
))
sim
.
increaseByTimeStep
();
}
if
(
intf
)
delete
intf
;
if
(
intf
)
delete
intf
;
#else
while
(
sim
.
step
(
log
,
llog
,
rlog
))
sim
.
increaseByTimeStep
();
while
(
sim
.
step
(
log
,
llog
,
rlog
))
sim
.
increaseByTimeStep
();
#endif
return
0
;
}
int
pythonMain
(
int
argc
,
const
char
*
argv
[])
{
PyImport_AppendInittab
(
"dpsim"
,
&
PyInit_dpsim
);
Py_Initialize
();
components
.
push_back
(
new
VoltSourceRes
(
"V_in"
,
1
,
0
,
10
,
1
,
1
));
components
.
push_back
(
new
LinearResistor
(
"R_load"
,
1
,
0
,
100
));
initContext
(
&
globalCtx
);
while
(
std
::
cin
.
good
()
&&
Py_IsInitialized
())
{
std
::
cout
<<
"> "
;
std
::
string
line
;
std
::
getline
(
std
::
cin
,
line
);
PyRun_SimpleString
(
line
.
c_str
());
}
return
0
;
}
int
main
(
int
argc
,
const
char
*
argv
[])
{
return
python
Main
(
argc
,
argv
);
return
cim
Main
(
argc
,
argv
);
}
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