Jon Olav Vik wrote:
> Dear Cythoneers,
>
Hi again! I'll be brief, suspecting that it's better with a quick answer
now than putting it off until I don't remember getting back. Please get
back with any obstacles that this doesn't solve.
> Subtasks include:
> * Installing Sundials from [2] (Done; test programs run successfully.
> Also, Pysundials uses the same Sundials installation.)
> * (Optional: Experienced Cythoneers might perhaps find it informative
> to see how Pysundials wraps things; in that case, install from [1]
> (and watch out for the CPATH gotcha mentioned on that page))
> * Telling Cython where to find cvode.h, nvector.h, sundials.h (see [11])
>
I suspect the problem here is including "cvode", "nvector" etc. directly
in include_path. Instead you should likely do
cdef extern from "cvode/....h":
...
and in setup.py simly have include_paths=[".../include"] rather than
[".../include/cvode", ".../include/nvector", ...]. (This is how
libraries are usually set up anyway.)
> * Importing anything from Sundials (see [12]). Currently "python
> setup.py build_ext --inplace" complains about not finding nvector.h
> [13]
> * Allocating an NVector with Sundials (see [3, 7]).
>
Note that the call seems to allocate the ydot NVector for you (whether
you still need to allocate other NVector's I didn't bother to check now;
but it is likely straightforward).
The challenge here though is about function pointers.
Basically you need to define
cdef extern from ...:
ctypedef double realtype
ctypedef struct N_Vector:
...more or less copy definition from nvector header files...
ctypedef int (*CVRhsFn)(realtype t, N_Vector y, N_Vector ydot, void
*user_data)
int CVodeInit(void* mem, CVRhsFn f, realtype t0, N_Vector y0)
Note that here CVRhsFn is a /type/, it is a pointer to a function, and
CVodeInit is a function which takes such a pointer (a "callback"). So
you'd do
cdef int your_rhs(realtype t, N_Vector y, N_vector ydot, void* user_data):
...
CVodeInit(..., your_rhs, t0, y0)
and now Sundials will know that your_rhs should be called.
Furthermore, user_data is for your use, for passing additional
parameters to your_rhs. It can e.g. be a Python object (or Cython cdef
class object) storing values your_rhs needs, as long as you cast it:
cdef class MyRhsProperties:
...
cdef MyRhsProperties props = ...
some_solve_function_taking_user_data(..., <void*>props, ...)
cdef int your_rhs(realtype t, N_Vector y, N_vector ydot, void* user_data):
cdef MyRhsProperties props = <MyRhsProperties>user_data
...
Further refining this we get a typical pattern in these situations:
cdef class SundialsRhs:
cdef int step(realtype t, N_vector y, N_vector ydot):
...
cdef int your_rhs(realtype t, N_Vector y, N_vector ydot, void* user_data):
(<MyRhsProperties>user_data).step(t, y, ydot)
def foosolve(..., SundialsRhs rhs):
some_solve_function_taking_user_data(..., <void*>rhs, ...)
which (for a small virtual dispatch penalty) allows you to subclass
SundialsRhs to provide the callback function.
> * Handle the NVector from Python: exchange data with a Numpy array,
> and pass the NVector to a C or Cython function.
>
Can you find the definition of NVector and paste it in an email if you
don't succeed here? Having to fetch Sundials just to provide hints is a
bit inconvenient...
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev