Just for the records, I managed to interface my system equations coded in multiple .H and .C files with PyDSTool C-based integrators, e.g. Radau and Dopri.

My issues were raising from the fact that my code consists of multiple source .C files which in turn required also linking to several .H files as well as several other shared libraries installed in my system, e.g. GSL (as libgsl.so and libgslcblas.so). Because in the current version, it is not possible to pass to the compiler of Radau and Dopri these system shared libraries, nor it is possible to specify which C standard, it is necessary to modify some of the core PyDSTool routines before compilation.

The few steps to follow to guarantee that your C-coded system could be integrated successfully by Radau or Dopri integrators are:

  • Make sure that your code is merely in C, that is you can only have .H and .C files. C++ code will not compile (or maybe it can, but the workaround is likely to be a headache... see my previous post).
  • Say your code is in C99 standard and that it requires linking to GSL whose path for this latter is in /usr/lib64. Then you need to edit mixins.py under PyDSTool/Generator. In particular open this file and go to line 180 (as of PyDSTool 0.90.2) and edit extra_compile_args by adding flags -std=c99, -L/usr/lib64, -lgsl, -lgslcblas, i.e.

    extra_compile_args=utils.extra_arch_arg(["-std=c99", "-w", "-Wno-return-type", "-Wall", "-L/usr/lib64","-lm", "-lgsl", "-lgslcblas"]) + self.cflags,
    
  • Finally first instantiate the generator and then compile it separately by:

    DSargs = ...
    DSargs['nobuild'] = True
    DS = dst.Generator.Dopri_ODEsystem(DSargs) # or DS = dst.Generator.Radau_ODEsystem(DSargs)
    # Specify `.H` files to include that are called by your C code
    DS.makeLibSource(include =  ['mylib_1.h','mylib_2.h',...])
    # Compile including the different source files, specified by their full path
    # as well as the directories to include to search for header files
    DS.compileLib(libsources = ['/home/me/model_1/eqs.c','/usr/me/c_code/extra_eqs.c',...],
                                 libdirs = ['/home/me/model_1','/usr/me/c_code',...])
    

If you get some errors, to help you debugging, look at the build.log file automatically generated in the target radau_tmp or dopri83_tmp directories.

Also recall that, as emphasized on the tutorials, you need to delete the *_tmp target directory and recompile every time that you modify your C routines. The additional step of restarting the Python kernel, may become unnecessary if you work for example in PyCharm.

 

Last edit: Maurizio De Pitta' 2016-09-22