Linear Ordinary Differential Equation

Python code

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()

C code

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;
}

Using SimObject._cstructname_

Python code

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()

Using SimObject._cfuncprefix_

How to omit the name of the struct in the C functions.

Python code

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()

C code

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;
}