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
84b4a698
Commit
84b4a698
authored
Sep 15, 2017
by
Georg Martin Reinke
Browse files
support loading components from CIM in Python; remove unneeded command-line args
parent
8e767e65
Changes
5
Hide whitespace changes
Inline
Side-by-side
Source/DPsimMain.cpp
View file @
84b4a698
...
...
@@ -7,6 +7,7 @@
#include
<thread>
#include
"CIMReader.h"
#include
"PyComponent.h"
#include
"PySimulation.h"
#include
"Simulation.h"
#include
"ShmemInterface.h"
...
...
@@ -16,15 +17,11 @@ using namespace DPsim;
void
usage
()
{
std
::
cerr
<<
"usage: DPsolver [OPTIONS] CIM_FILE..."
<<
std
::
endl
<<
"Possible options:"
<<
std
::
endl
<<
" -d/--duration DURATION: simulation duration in seconds (default: 0.3)"
<<
std
::
endl
<<
" -f/--frequency FREQUENCY: system frequency in Hz (default: 50)"
<<
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
<<
" -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
;
<<
" -s/--split INDEX: index of this instance for distributed simulation (0 or 1)"
<<
std
::
endl
;
}
bool
parseFloat
(
const
char
*
s
,
double
*
d
)
{
...
...
@@ -39,14 +36,21 @@ bool parseInt(const char *s, int *i) {
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
,
NULL
,
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
;
...
...
@@ -56,6 +60,8 @@ static PyObject* PyInit_dpsim(void) {
Py_INCREF
(
&
PySimulationType
);
PyModule_AddObject
(
m
,
"Simulation"
,
(
PyObject
*
)
&
PySimulationType
);
Py_INCREF
(
&
PyComponentType
);
PyModule_AddObject
(
m
,
"Component"
,
(
PyObject
*
)
&
PyComponentType
);
return
m
;
}
...
...
@@ -73,9 +79,8 @@ void doPythonLoop() {
// TODO: that many platform-dependent ifdefs inside main are kind of ugly
int
cimMain
(
int
argc
,
const
char
*
argv
[])
{
bool
rt
=
false
,
python
=
false
;
bool
rt
=
false
;
int
i
,
split
=
-
1
;
Real
frequency
=
2
*
PI
*
50
,
timestep
=
0.001
,
duration
=
0.3
;
std
::
string
interfaceBase
=
"/dpsim"
;
std
::
string
splitNode
=
""
;
std
::
string
outName
,
inName
,
logName
(
"log.txt"
),
llogName
(
"lvector.csv"
),
rlogName
(
"rvector.csv"
);
...
...
@@ -85,26 +90,7 @@ int cimMain(int argc, const char* argv[]) {
// Parse arguments
for
(
i
=
1
;
i
<
argc
;
i
++
)
{
if
(
!
strcmp
(
argv
[
i
],
"-d"
)
||
!
strcmp
(
argv
[
i
],
"--duration"
))
{
if
(
i
==
argc
-
1
)
{
std
::
cerr
<<
"Missing argument for -d/--duration; 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
;
return
1
;
}
}
else
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
],
"-h"
)
||
!
strcmp
(
argv
[
i
],
"--help"
))
{
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
||
!
strcmp
(
argv
[
i
],
"--help"
))
{
usage
();
return
0
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-i"
)
||
!
strcmp
(
argv
[
i
],
"--interface"
))
{
...
...
@@ -123,8 +109,6 @@ int cimMain(int argc, const char* argv[]) {
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"
))
{
...
...
@@ -136,15 +120,6 @@ 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
],
"-t"
)
||
!
strcmp
(
argv
[
i
],
"--timestep"
))
{
if
(
i
==
argc
-
1
)
{
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
;
}
}
else
if
(
argv
[
i
][
0
]
==
'-'
)
{
std
::
cerr
<<
"Unknown option "
<<
argv
[
i
]
<<
" ; see 'DPsim --help' for usage"
<<
std
::
endl
;
return
1
;
...
...
@@ -153,10 +128,7 @@ int cimMain(int argc, const char* argv[]) {
break
;
}
}
if
(
i
==
argc
)
{
std
::
cerr
<<
"No input files given (see DPsim --help for usage)"
<<
std
::
endl
;
return
1
;
}
// TODO: treat remaining arguments as initial python scripts
#ifndef __linux__
if
(
split
>=
0
||
splitNode
.
length
()
!=
0
)
{
std
::
cerr
<<
"Distributed simulation not supported on this platform"
<<
std
::
endl
;
...
...
@@ -166,22 +138,13 @@ int cimMain(int argc, const char* argv[]) {
return
1
;
}
#endif
if
(
python
&&
(
split
>=
0
||
splitNode
.
length
()
!=
0
||
rt
)
)
{
if
(
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
);
for
(;
i
<
argc
;
i
++
)
{
if
(
!
reader
.
addFile
(
argv
[
i
]))
{
std
::
cerr
<<
"Failed to read file "
<<
argv
[
i
]
<<
std
::
endl
;
return
1
;
}
}
reader
.
parseFiles
();
components
=
reader
.
getComponents
();
// 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) {
...
...
@@ -216,14 +179,11 @@ int cimMain(int argc, const char* argv[]) {
}
}
#endif
// Do the actual simulation
Logger
log
(
logName
),
llog
(
llogName
),
rlog
(
rlogName
);
Simulation
sim
(
components
,
frequency
,
timestep
,
duration
,
log
);
*/
if
(
python
)
{
doPythonLoop
();
}
else
{
doPythonLoop
();
/*
#ifdef __linux__
if (intf)
sim.addExternalInterface(intf);
...
...
@@ -237,11 +197,8 @@ int cimMain(int argc, const char* argv[]) {
if (intf)
delete intf;
#else
while
(
sim
.
step
(
log
,
llog
,
rlog
))
sim
.
increaseByTimeStep
();
#endif
}
*/
return
0
;
}
...
...
Source/PyComponent.cpp
0 → 100644
View file @
84b4a698
#include
"PyComponent.h"
#include
"CIMReader.h"
using
namespace
DPsim
;
PyTypeObject
DPsim
::
PyComponentType
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"dpsim.Component"
,
/* tp_name */
sizeof
(
PyComponent
),
/* tp_basicsize */
0
,
/* tp_itemsize */
(
destructor
)
PyComponent
::
dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_reserved */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
,
/* tp_flags */
"A component in a simulation."
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
0
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
PyComponent
::
newfunc
,
/* tp_new */
};
PyObject
*
PyComponent
::
newfunc
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
PyComponent
*
self
=
(
PyComponent
*
)
type
->
tp_alloc
(
type
,
0
);
if
(
self
)
self
->
comp
=
nullptr
;
return
(
PyObject
*
)
self
;
}
void
PyComponent
::
dealloc
(
PyComponent
*
self
)
{
if
(
self
->
comp
)
delete
self
->
comp
;
Py_TYPE
(
self
)
->
tp_free
((
PyObject
*
)
self
);
}
bool
DPsim
::
compsFromPython
(
PyObject
*
list
,
std
::
vector
<
BaseComponent
*>&
comps
)
{
if
(
!
PyList_Check
(
list
))
return
false
;
for
(
int
i
=
0
;
i
<
PyList_Size
(
list
);
i
++
)
{
PyObject
*
obj
=
PyList_GetItem
(
list
,
i
);
if
(
!
PyObject_TypeCheck
(
obj
,
&
PyComponentType
))
{
comps
.
clear
();
return
false
;
}
PyComponent
*
pyComp
=
(
PyComponent
*
)
obj
;
comps
.
push_back
(
pyComp
->
comp
);
}
return
true
;
}
PyObject
*
DPsim
::
pyLoadCim
(
PyObject
*
self
,
PyObject
*
args
)
{
double
frequency
=
50
;
PyObject
*
list
;
PyBytesObject
*
filename
;
CIMReader
*
reader
;
if
(
PyArg_ParseTuple
(
args
,
"O&|d"
,
PyUnicode_FSConverter
,
&
filename
,
&
frequency
))
{
reader
=
new
CIMReader
(
2
*
PI
*
frequency
);
reader
->
addFile
(
PyBytes_AsString
((
PyObject
*
)
filename
));
Py_DECREF
(
filename
);
}
else
if
(
PyArg_ParseTuple
(
args
,
"O|d"
,
&
list
,
&
frequency
))
{
PyErr_Clear
();
if
(
!
PyList_Check
(
list
))
{
PyErr_SetString
(
PyExc_TypeError
,
"First argument must be filename or list of filenames"
);
return
nullptr
;
}
reader
=
new
CIMReader
(
2
*
PI
*
frequency
);
for
(
int
i
=
0
;
i
<
PyList_Size
(
list
);
i
++
)
{
if
(
!
PyUnicode_FSConverter
(
PyList_GetItem
(
list
,
i
),
&
filename
))
{
delete
reader
;
PyErr_SetString
(
PyExc_TypeError
,
"First argument must be filename or list of filenames"
);
return
nullptr
;
}
reader
->
addFile
(
PyBytes_AsString
((
PyObject
*
)
filename
));
Py_DECREF
(
filename
);
}
}
else
{
PyErr_SetString
(
PyExc_TypeError
,
"First argument must be filename or list of filenames"
);
return
nullptr
;
}
reader
->
parseFiles
();
std
::
vector
<
BaseComponent
*>
comps
=
reader
->
getComponents
();
list
=
PyList_New
(
comps
.
size
());
for
(
int
i
=
0
;
i
<
comps
.
size
();
i
++
)
{
// corresponds to "pyComp = dpsim.Component()" in Python
PyObject
*
emptyTuple
=
PyTuple_New
(
0
);
PyComponent
*
pyComp
=
(
PyComponent
*
)
PyObject_CallObject
((
PyObject
*
)
&
PyComponentType
,
emptyTuple
);
Py_DECREF
(
emptyTuple
);
if
(
!
pyComp
)
{
Py_DECREF
(
list
);
delete
reader
;
return
nullptr
;
}
/*
PyComponent* pyComp = PyObject_New(PyComponent, &PyComponentType);
PyObject_Init((PyObject*) pyComp, &PyComponentType);
*/
pyComp
->
comp
=
comps
[
i
];
PyList_SET_ITEM
(
list
,
i
,
(
PyObject
*
)
pyComp
);
}
delete
reader
;
return
list
;
}
Source/PyComponent.h
0 → 100644
View file @
84b4a698
#ifndef PYCOMPONENT_H
#define PYCOMPONENT_H
#include
<Python.h>
#include
<vector>
#include
"Components/BaseComponent.h"
namespace
DPsim
{
struct
PyComponent
{
PyObject_HEAD
BaseComponent
*
comp
;
static
PyObject
*
newfunc
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
);
static
void
dealloc
(
PyComponent
*
);
};
extern
PyTypeObject
PyComponentType
;
bool
compsFromPython
(
PyObject
*
list
,
std
::
vector
<
BaseComponent
*>&
comps
);
PyObject
*
pyLoadCim
(
PyObject
*
self
,
PyObject
*
args
);
};
#endif
Source/PySimulation.cpp
View file @
84b4a698
#include
"PySimulation.h"
#include
"PyComponent.h"
#include
<cfloat>
#include
<iostream>
using
namespace
DPsim
;
std
::
vector
<
BaseComponent
*>
DPsim
::
components
;
static
PyMethodDef
PySimulation_methods
[]
=
{
{
"lvector"
,
PySimulation
::
lvector
,
METH_NOARGS
,
"Returns the left-side vector from the last step."
},
{
"start"
,
PySimulation
::
start
,
METH_NOARGS
,
"Start the simulation, or resume if it is paused."
},
{
"step"
,
PySimulation
::
step
,
METH_NOARGS
,
"Perform a single simulation step."
},
{
"stop"
,
PySimulation
::
stop
,
METH_NOARGS
,
"Cancel the running simulation."
},
{
"pause"
,
PySimulation
::
pause
,
METH_NOARGS
,
"Pause the already running simulation."
},
{
"wait"
,
PySimulation
::
wait
,
METH_NOARGS
,
"Wait for the simulation to finish."
},
{
NULL
,
NULL
,
0
,
NULL
}
};
PyTypeObject
DPsim
::
PySimulationType
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"dpsim.Simulation"
,
/* tp_name */
sizeof
(
PySimulation
),
/* tp_basicsize */
0
,
/* tp_itemsize */
(
destructor
)
PySimulation
::
dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_reserved */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
,
/* tp_flags */
"A single simulation."
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
PySimulation_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
(
initproc
)
PySimulation
::
init
,
/* tp_init */
0
,
/* tp_alloc */
PySimulation
::
newfunc
,
/* tp_new */
};
void
PySimulation
::
simThreadFunction
(
PySimulation
*
pySim
)
{
bool
notDone
=
true
;
...
...
@@ -46,18 +97,23 @@ PyObject* PySimulation::newfunc(PyTypeObject* type, PyObject *args, PyObject *kw
}
int
PySimulation
::
init
(
PySimulation
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
{
static
char
*
kwlist
[]
=
{
"frequency"
,
"timestep"
,
"duration"
,
"log"
,
NULL
};
static
char
*
kwlist
[]
=
{
"components"
,
"frequency"
,
"timestep"
,
"duration"
,
"log"
,
NULL
};
double
frequency
=
50
,
timestep
=
1e-3
,
duration
=
DBL_MAX
;
const
char
*
log
=
nullptr
;
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"|ddds"
,
kwlist
,
&
frequency
,
&
timestep
,
&
duration
,
&
log
))
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|ddds"
,
kwlist
,
&
self
->
pyComps
,
&
frequency
,
&
timestep
,
&
duration
,
&
log
))
return
-
1
;
if
(
!
compsFromPython
(
self
->
pyComps
,
self
->
comps
))
{
PyErr_SetString
(
PyExc_TypeError
,
"Invalid components argument (must by list of dpsim.Component)"
);
return
-
1
;
}
Py_INCREF
(
self
->
pyComps
);
if
(
log
)
self
->
log
=
new
Logger
(
log
);
else
self
->
log
=
new
Logger
();
self
->
sim
=
new
Simulation
(
component
s
,
2
*
PI
*
frequency
,
timestep
,
duration
,
*
self
->
log
);
self
->
sim
=
new
Simulation
(
self
->
comp
s
,
2
*
PI
*
frequency
,
timestep
,
duration
,
*
self
->
log
);
return
0
;
};
...
...
@@ -69,12 +125,20 @@ void PySimulation::dealloc(PySimulation* self) {
self
->
simThread
->
join
();
delete
self
->
simThread
;
}
if
(
self
->
sim
)
delete
self
->
sim
;
if
(
self
->
log
)
delete
self
->
log
;
delete
self
->
mut
;
delete
self
->
cond
;
// Since this is not a C++ destructor which would automatically call the
// destructor of its members, we have to manually call the destructor of
// the component vector here to free the associated memory.
self
->
comps
.
~
vector
<
BaseComponent
*>
();
Py_XDECREF
(
self
->
pyComps
);
Py_TYPE
(
self
)
->
tp_free
((
PyObject
*
)
self
);
}
...
...
Source/PySimulation.h
View file @
84b4a698
...
...
@@ -32,6 +32,9 @@ namespace DPsim {
std
::
atomic_int
sigPause
,
numStep
;
std
::
thread
*
simThread
;
SimState
state
;
PyObject
*
pyComps
;
// Components as a (Python) list of PyComponents
std
::
vector
<
BaseComponent
*>
comps
;
// Function executed by the simulation thread
static
void
simThreadFunction
(
PySimulation
*
pySim
);
...
...
@@ -53,58 +56,6 @@ namespace DPsim {
static
PyObject
*
wait
(
PyObject
*
self
,
PyObject
*
args
);
};
static
PyMethodDef
PySimulation_methods
[]
=
{
{
"lvector"
,
PySimulation
::
lvector
,
METH_NOARGS
,
"Returns the left-side vector from the last step."
},
{
"start"
,
PySimulation
::
start
,
METH_NOARGS
,
"Start the simulation, or resume if it is paused."
},
{
"step"
,
PySimulation
::
step
,
METH_NOARGS
,
"Perform a single simulation step."
},
{
"stop"
,
PySimulation
::
stop
,
METH_NOARGS
,
"Cancel the running simulation."
},
{
"pause"
,
PySimulation
::
pause
,
METH_NOARGS
,
"Pause the already running simulation."
},
{
"wait"
,
PySimulation
::
wait
,
METH_NOARGS
,
"Wait for the simulation to finish."
},
{
NULL
,
NULL
,
0
,
NULL
}
};
static
PyTypeObject
PySimulationType
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"dpsim.Simulation"
,
/* tp_name */
sizeof
(
PySimulation
),
/* tp_basicsize */
0
,
/* tp_itemsize */
(
destructor
)
PySimulation
::
dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_reserved */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
0
,
/* tp_call */
0
,
/* tp_str */
0
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
,
/* tp_flags */
"A single simulation."
,
/* tp_doc */
0
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
PySimulation_methods
,
/* tp_methods */
0
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
(
initproc
)
PySimulation
::
init
,
/* tp_init */
0
,
/* tp_alloc */
PySimulation
::
newfunc
,
/* tp_new */
};
extern
std
::
vector
<
BaseComponent
*>
components
;
extern
PyTypeObject
PySimulationType
;
};
#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