from railgun import SimObject, relpath
class LinearODE(SimObject):
"""
Solve D-dimensional linear ordinary differential equations
Equation::
dX/dt(t) = A X(t)
X: D-dimensional vector
A: DxD matrix
"""
_clibname_ = 'liblode.so' # name of shared library
_clibdir_ = relpath('.', __file__) # library directory
_cmembers_ = [ # declaring members of struct
'num_d', # num_* as size of array (no need to write `int`)
'num_s = 10000', # setting default value
'double dt = 0.001',
'double a[d][d]', # num_d x num_d array
'double x[s][d]', # num_s x num_d array
]
_cfuncs_ = [ # declaring functions to load
"x run(s< s_end=num_s)"
# argument `s_end` has index `s` type and default is `num_s`
# '<' means it is upper bound of the index so the range is [1, num_s]
# this function returns member x
]
lode = LinearODE(num_d=2) # set num_d
lode.x[0] = [1, 0] # access c-member "VAR" via lode.VAR
lode.a = [[0, 1], [-1, 0]]
x1 = lode.run().copy()
lode.setv(a_0_0=-0.5) # set lode.a[i][j]=v via lode.set(a_'i'_'j'=v)
x2 = lode.run().copy()
import pylab
for (i, x) in enumerate([x1, x2]):
pylab.subplot(2, 2, 1 + i)
pylab.plot(x[:,0])
pylab.plot(x[:,1])
pylab.subplot(2, 2, 3 + i)
pylab.plot(x[:,0], x[:,1])
pylab.show()
typedef struct linearode_{
int num_d, num_s;
double dt;
double **a;
double **x;
} LinearODE;
int LinearODE_run(LinearODE *self, int s_end)
{
int s, d1, d2;
for (s = 1; s < s_end; ++s){
for (d1 = 0; d1 < self->num_d; ++d1){
self->x[s][d1] = self->x[s-1][d1];
for (d2 = 0; d2 < self->num_d; ++d2){
self->x[s][d1] += self->dt * self->a[d1][d2] * self->x[s-1][d2];
}
}
}
return 0;
}
from railgun import SimObject, relpath
class LinearOrdinaryDifferentialEquation(SimObject): # != LinearODE
"""
Solve D-dimensional linear ordinary differential equations
Equation::
dX/dt(t) = A X(t)
X: D-dimensional vector
A: DxD matrix
"""
_clibname_ = 'liblode.so' # name of shared library
_clibdir_ = relpath('.', __file__) # library directory
_cstructname_ = 'LinearODE' # specify the C struct name
_cmembers_ = [ # declaring members of struct
'num_d', # num_* as size of array (no need to write `int`)
'num_s = 10000', # setting default value
'double dt = 0.001',
'double a[d][d]', # num_d x num_d array
'double x[s][d]', # num_s x num_d array
]
_cfuncs_ = [ # declaring functions to load
"x run(s< s_end=num_s)"
# argument `s_end` has index `s` type and default is `num_s`
# '<' means it is upper bound of the index so the range is [1, num_s]
# this function returns member x
]
lode = LinearOrdinaryDifferentialEquation(num_d=2) # set num_d
lode.x[0] = [1, 0] # access c-member "VAR" via lode.VAR
lode.a = [[0, 1], [-1, 0]]
x1 = lode.run().copy()
lode.setv(a_0_0=-0.5) # set lode.a[i][j]=v via lode.set(a_'i'_'j'=v)
x2 = lode.run().copy()
import pylab
for (i, x) in enumerate([x1, x2]):
pylab.subplot(2, 2, 1 + i)
pylab.plot(x[:,0])
pylab.plot(x[:,1])
pylab.subplot(2, 2, 3 + i)
pylab.plot(x[:,0], x[:,1])
pylab.show()
What is the difference from the normal version? (... just three lines!):
--- lode_cstructname.py 2011-04-17 15:39:05.942934998 +0900
+++ lode.py 2011-04-16 21:53:58.707407999 +0900
@@ -1,6 +1,6 @@
from railgun import SimObject, relpath
-class LinearOrdinaryDifferentialEquation(SimObject): # != LinearODE
+class LinearODE(SimObject):
"""
Solve D-dimensional linear ordinary differential equations
@@ -14,7 +14,6 @@
_clibname_ = 'liblode.so' # name of shared library
_clibdir_ = relpath('.', __file__) # library directory
- _cstructname_ = 'LinearODE' # specify the C struct name
_cmembers_ = [ # declaring members of struct
'num_d', # num_* as size of array (no need to write `int`)
'num_s = 10000', # setting default value
@@ -30,7 +29,7 @@
]
-lode = LinearOrdinaryDifferentialEquation(num_d=2) # set num_d
+lode = LinearODE(num_d=2) # set num_d
lode.x[0] = [1, 0] # access c-member "VAR" via lode.VAR
lode.a = [[0, 1], [-1, 0]]
x1 = lode.run().copy()
How to omit the name of the struct in the C functions.
Please notice that _cfuncprefix_ = '' is added to omit the name of the struct name.
from railgun import SimObject, relpath
class LinearODE(SimObject):
"""
Solve D-dimensional linear ordinary differential equations
Equation::
dX/dt(t) = A X(t)
X: D-dimensional vector
A: DxD matrix
"""
_clibname_ = 'liblode_cfuncprefix.so' # name of shared library
_clibdir_ = relpath('.', __file__) # library directory
_cfuncprefix_ = '' # no prefix for C functions!
_cmembers_ = [ # declaring members of struct
'num_d', # num_* as size of array (no need to write `int`)
'num_s = 10000', # setting default value
'double dt = 0.001',
'double a[d][d]', # num_d x num_d array
'double x[s][d]', # num_s x num_d array
]
_cfuncs_ = [ # declaring functions to load
"x run(s< s_end=num_s)"
# argument `s_end` has index `s` type and default is `num_s`
# '<' means it is upper bound of the index so the range is [1, num_s]
# this function returns member x
]
lode = LinearODE(num_d=2) # set num_d
lode.x[0] = [1, 0] # access c-member "VAR" via lode.VAR
lode.a = [[0, 1], [-1, 0]]
x1 = lode.run().copy()
lode.setv(a_0_0=-0.5) # set lode.a[i][j]=v via lode.set(a_'i'_'j'=v)
x2 = lode.run().copy()
import pylab
for (i, x) in enumerate([x1, x2]):
pylab.subplot(2, 2, 1 + i)
pylab.plot(x[:,0])
pylab.plot(x[:,1])
pylab.subplot(2, 2, 3 + i)
pylab.plot(x[:,0], x[:,1])
pylab.show()
The function is simply run without the prefix now.
typedef struct linearode_{
int num_d, num_s;
double dt;
double **a;
double **x;
} LinearODE;
int run(LinearODE *self, int s_end)
{
int s, d1, d2;
for (s = 1; s < s_end; ++s){
for (d1 = 0; d1 < self->num_d; ++d1){
self->x[s][d1] = self->x[s-1][d1];
for (d2 = 0; d2 < self->num_d; ++d2){
self->x[s][d1] += self->dt * self->a[d1][d2] * self->x[s-1][d2];
}
}
}
return 0;
}