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
5e7f1315
Commit
5e7f1315
authored
Sep 20, 2017
by
Georg Martin Reinke
Browse files
build DPsim as a Python module
parent
ad4b3f2d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Source/CMakeLists.txt
View file @
5e7f1315
cmake_minimum_required
(
VERSION 3.0
)
project
(
DPsim
)
# needed so CIMParser and arabica (which are first compiled into static libs)
# can be included in the .so
set
(
CMAKE_CXX_FLAGS
"-fPIC"
)
# library configuration etc.
if
(
IS_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
/../Libraries/eigen
)
set
(
EIGEN3_INCLUDE_DIR ../Libraries/eigen
)
...
...
@@ -11,32 +15,19 @@ endif()
find_package
(
PythonLibs
)
if
(
WIN32
)
set
(
MODNAME
"dpsim.dll"
)
set
(
ARABICA_XML_BACKEND USE_MSXML
)
else
()
set
(
MODNAME
"dpsim.so"
)
set
(
LIBS
"-lrt -lvillas-ext"
)
endif
()
include_directories
(
${
EIGEN3_INCLUDE_DIR
}
${
PYTHON_INCLUDE_DIRS
}
)
add_subdirectory
(
CIM-XML-Parser
)
# static library target for everything but main (otherwise, CMake compiles all
# object files again for each test)
file
(
GLOB SOURCES *.cpp Components/*.cpp Examples/*.cpp
)
set
(
SOURCES_NOMAIN
${
SOURCES
}
)
file
(
GLOB MAIN_FULLPATH DPsimMain.cpp
)
list
(
REMOVE_ITEM SOURCES_NOMAIN
${
MAIN_FULLPATH
}
)
add_library
(
DPsim STATIC
${
SOURCES_NOMAIN
}
)
target_link_libraries
(
DPsim CIMParser
)
# actual executable
add_executable
(
DPSolver
${
MAIN_FULLPATH
}
)
target_link_libraries
(
DPSolver DPsim CIMParser pthread
${
PYTHON_LIBRARIES
}
${
LIBS
}
)
file
(
GLOB SOURCES *.cpp Components/*.cpp
)
add_library
(
dpsim SHARED
${
SOURCES
}
)
target_link_libraries
(
dpsim CIMParser pthread
${
PYTHON_LIBRARIES
}
${
LIBS
}
)
execute_process
(
COMMAND python -c
"import sysconfig; print(sysconfig.get_path('platlib'), end='')"
OUTPUT_VARIABLE PYTHON_PKGPATH
)
install
(
FILES build/libdpsim.so DESTINATION
${
PYTHON_PKGPATH
}
RENAME
${
MODNAME
}
)
# tests
file
(
GLOB TESTS Tests/*.cpp
)
foreach
(
TEST
${
TESTS
}
)
string
(
REGEX MATCH
"[^/]*$"
TEST_SHORT
${
TEST
}
)
string
(
REPLACE
".cpp"
""
TEST_BIN
${
TEST_SHORT
}
)
add_executable
(
${
TEST_BIN
}
${
TEST
}
)
target_link_libraries
(
${
TEST_BIN
}
DPsim CIMParser
${
LIBS
}
)
endforeach
()
Source/DPsimMain.cpp
deleted
100644 → 0
View file @
ad4b3f2d
#include <Python.h>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
#include "CIMReader.h"
#include "PyComponent.h"
#include "PySimulation.h"
#include "Simulation.h"
#include "ShmemInterface.h"
using
namespace
DPsim
;
void
usage
()
{
std
::
cerr
<<
"usage: DPsolver [OPTIONS] [PYTHON_FILE...]"
<<
std
::
endl
<<
"Possible options:"
<<
std
::
endl
<<
" -b/--batch: don't show an interactive prompt after reading files"
<<
std
::
endl
<<
" -h/--help: show this help and exit"
<<
std
::
endl
<<
" -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
<<
" -s/--split INDEX: index of this instance for distributed simulation (0 or 1)"
<<
std
::
endl
<<
"Remaining arguments are treated as Python files and executed in order."
<<
std
::
endl
;
}
bool
parseFloat
(
const
char
*
s
,
double
*
d
)
{
char
*
end
;
*
d
=
std
::
strtod
(
s
,
&
end
);
return
(
end
!=
s
&&
!*
end
);
}
bool
parseInt
(
const
char
*
s
,
int
*
i
)
{
char
*
end
;
*
i
=
strtol
(
s
,
&
end
,
0
);
return
(
end
!=
s
&&
!*
end
);
}
static
PyMethodDef
pyModuleMethods
[]
=
{
{
"load_cim"
,
pyLoadCim
,
METH_VARARGS
,
"Load a network from CIM file(s)."
},
{
0
}
};
static
PyModuleDef
dpsimModule
=
{
PyModuleDef_HEAD_INIT
,
"dpsim"
,
NULL
,
-
1
,
pyModuleMethods
,
NULL
,
NULL
,
NULL
,
NULL
};
static
PyObject
*
PyInit_dpsim
(
void
)
{
PyObject
*
m
;
if
(
PyType_Ready
(
&
PyComponentType
)
<
0
)
return
nullptr
;
if
(
PyType_Ready
(
&
PySimulationType
)
<
0
)
return
nullptr
;
m
=
PyModule_Create
(
&
dpsimModule
);
if
(
!
m
)
return
nullptr
;
Py_INCREF
(
&
PySimulationType
);
PyModule_AddObject
(
m
,
"Simulation"
,
(
PyObject
*
)
&
PySimulationType
);
Py_INCREF
(
&
PyComponentType
);
PyModule_AddObject
(
m
,
"Component"
,
(
PyObject
*
)
&
PyComponentType
);
return
m
;
}
// TODO: that many platform-dependent ifdefs inside main are kind of ugly
int
cimMain
(
int
argc
,
const
char
*
argv
[])
{
bool
rt
=
false
,
batch
=
false
;
int
i
,
split
=
-
1
;
std
::
string
interfaceBase
=
"/dpsim"
;
std
::
string
splitNode
=
""
;
std
::
string
outName
,
inName
,
logName
(
"log.txt"
),
llogName
(
"lvector.csv"
),
rlogName
(
"rvector.csv"
);
#ifdef __linux__
ShmemInterface
*
intf
=
nullptr
;
#endif
// Parse arguments
for
(
i
=
1
;
i
<
argc
;
i
++
)
{
if
(
!
strcmp
(
argv
[
i
],
"-b"
)
||
!
strcmp
(
argv
[
i
],
"--batch"
))
{
batch
=
true
;
}
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
;
return
1
;
}
if
(
argv
[
++
i
][
0
]
!=
'/'
)
{
std
::
cerr
<<
"Shmem interface object name must start with a '/'"
<<
std
::
endl
;
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
],
"-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
;
return
1
;
}
if
(
!
parseInt
(
argv
[
++
i
],
&
split
)
||
split
<
0
||
split
>
1
)
{
std
::
cerr
<<
"Invalid setting "
<<
argv
[
i
]
<<
" for the split index"
<<
std
::
endl
;
return
1
;
}
}
else
if
(
argv
[
i
][
0
]
==
'-'
)
{
std
::
cerr
<<
"Unknown option "
<<
argv
[
i
]
<<
" ; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
}
else
{
// remaining arguments treated as input files
break
;
}
}
#ifndef __linux__
if
(
split
>=
0
||
splitNode
.
length
()
!=
0
)
{
std
::
cerr
<<
"Distributed simulation not supported on this platform"
<<
std
::
endl
;
return
1
;
}
else
if
(
rt
)
{
std
::
cerr
<<
"Realtime simulation not supported on this platform"
<<
std
::
endl
;
return
1
;
}
#endif
if
(
split
>=
0
||
splitNode
.
length
()
!=
0
||
rt
)
{
std
::
cerr
<<
"Realtime and distributed simulation currently not supported in combination with Python"
<<
std
::
endl
;
return
1
;
}
// TODO: RT / shmem interface with python
/*
#ifdef __linux__
// TODO: this is a simple, pretty much fixed setup. Make this more flexible / configurable
if (split >= 0) {
int node = reader.mapTopologicalNode(splitNode);
if (node < 0) {
std::cerr << "Invalid / missing split node" << std::endl;
return 1;
}
if (split == 0) {
outName = interfaceBase + ".0.out";
inName = interfaceBase + ".0.in";
intf = new ShmemInterface(outName.c_str(), inName.c_str());
ExternalVoltageSource *evs = new ExternalVoltageSource("v_int", node, 0, 0, 0, reader.getNumVoltageSources()+1);
intf->registerVoltageSource(evs, 0, 1);
intf->registerExportedCurrent(evs, 0, 1);
components.push_back(evs);
// TODO make log names configurable
logName = "cim0.log";
llogName = "lvector-cim0.csv";
rlogName = "rvector-cim0.csv";
} else {
outName = interfaceBase + ".1.out";
inName = interfaceBase + ".1.in";
intf = new ShmemInterface(outName.c_str(), inName.c_str());
ExternalCurrentSource *ecs = new ExternalCurrentSource("i_int", node, 0, 0, 0);
intf->registerCurrentSource(ecs, 0, 1);
intf->registerExportedVoltage(node, 0, 0, 1);
components.push_back(ecs);
logName = "cim1.log";
llogName = "lvector-cim1.csv";
rlogName = "rvector-cim1.csv";
}
}
#endif
*/
PyImport_AppendInittab
(
"dpsim"
,
&
PyInit_dpsim
);
Py_Initialize
();
for
(;
i
<
argc
;
i
++
)
{
FILE
*
f
=
fopen
(
argv
[
i
],
"r"
);
if
(
!
f
)
{
std
::
cerr
<<
"Failed to open "
;
std
::
perror
(
argv
[
i
]);
return
1
;
}
PyRun_SimpleFile
(
f
,
argv
[
i
]);
fclose
(
f
);
}
if
(
!
batch
)
{
while
(
std
::
cin
.
good
()
&&
Py_IsInitialized
())
{
std
::
cout
<<
"> "
;
std
::
string
line
;
std
::
getline
(
std
::
cin
,
line
);
PyRun_SimpleString
(
line
.
c_str
());
}
}
/*
#ifdef __linux__
if (intf)
sim.addExternalInterface(intf);
if (rt) {
sim.runRT(RTTimerFD, true, log, llog, rlog);
} else {
while (sim.step(log, llog, rlog))
sim.increaseByTimeStep();
}
if (intf)
delete intf;
#endif
*/
return
0
;
}
int
main
(
int
argc
,
const
char
*
argv
[])
{
return
cimMain
(
argc
,
argv
);
}
Source/PyModule.cpp
0 → 100644
View file @
5e7f1315
#include <Python.h>
#include "PyComponent.h"
#include "PyModule.h"
#include "PySimulation.h"
using
namespace
DPsim
;
PyMethodDef
DPsim
::
pyModuleMethods
[]
=
{
{
"load_cim"
,
pyLoadCim
,
METH_VARARGS
,
"Load a network from CIM file(s)."
},
{
0
}
};
PyModuleDef
DPsim
::
dpsimModule
=
{
PyModuleDef_HEAD_INIT
,
"dpsim"
,
NULL
,
-
1
,
pyModuleMethods
,
NULL
,
NULL
,
NULL
,
NULL
};
extern
"C"
{
PyObject
*
PyInit_dpsim
(
void
)
{
PyObject
*
m
;
if
(
PyType_Ready
(
&
PyComponentType
)
<
0
)
return
nullptr
;
if
(
PyType_Ready
(
&
PySimulationType
)
<
0
)
return
nullptr
;
m
=
PyModule_Create
(
&
dpsimModule
);
if
(
!
m
)
return
nullptr
;
Py_INCREF
(
&
PySimulationType
);
PyModule_AddObject
(
m
,
"Simulation"
,
(
PyObject
*
)
&
PySimulationType
);
Py_INCREF
(
&
PyComponentType
);
PyModule_AddObject
(
m
,
"Component"
,
(
PyObject
*
)
&
PyComponentType
);
return
m
;
}
};
Source/PyModule.h
0 → 100644
View file @
5e7f1315
#ifndef PYMODULE_H
#define PYMODULE_H
#include <Python.h>
namespace
DPsim
{
extern
PyMethodDef
pyModuleMethods
[];
extern
PyModuleDef
dpsimModule
;
};
// Has to be declared as extern C and without a namespace, because the linker
// otherwise mangles the name so the Python interpreter can't find this function.
extern
"C"
{
extern
PyObject
*
PyInit_dpsim
(
void
);
};
#endif
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