Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Julia support for Cantera #81

Open
RSuryaNarayan opened this issue Feb 21, 2021 · 11 comments
Open

Julia support for Cantera #81

RSuryaNarayan opened this issue Feb 21, 2021 · 11 comments
Labels
feature-request New feature request

Comments

@RSuryaNarayan
Copy link

Motivation
With Julia being increasingly turned towards by the scientific computing community, Cantera's support to Julia shall be a valuable feature addition. Two such paths exist to extend Cantera's support to Julia:
Possible solutions

  • A complete re-implementation based on the Cantera interpreter like Arrhenius.jl
  • Some additions to the source code to make the existing version of Cantera "callable" in Julia.
    A possible example of the second method would be to use the PyCall feature of Julia to make the Python implementation of Cantera available in the Julia environment:
    using PyCall; pyimport('cantera')
    Note that before this can take action, one needs PyCall added using Pkg.add("PyCall") and configure the working environment to include python using ENV["PYTHON"] = "location of the python.exe". Some skepticism exists that such an implementation would be unstable. A better implementation of such a feature would be to use the C++ implementation of cantera directly using Julia ccall()and create an executable.

References-Cantera user's group discussions

  1. https://groups.google.com/g/cantera-users/c/AkjunMzAkJs
  2. https://groups.google.com/g/cantera-users/c/WGi-PTq9Wgg/m/M5LTO-1HAwAJ
@jiweiqi
Copy link

jiweiqi commented Feb 21, 2021

I would suggest we explore both of those two approaches.

On one hand, there seem to be some needs for machine learning research that are not easy to realize by extends Canetra. But this needs more careful discussions.

On the other hand, there are very successful examples of building a wrapper for C++ packages in Julia. See Sundials.jl for Sundials. This might be categorized as different solutions to PyCall or cccall, as discussed in #39

@speth
Copy link
Member

speth commented Feb 21, 2021

The Sundials.jl package uses ccall, as you can see in cvode.jl.

For Cantera, we could wrap the Cantera C interface using ccall, or interact directly with the C++ interface using something like Cxx.jl or CxxWrap.jl. Wrapping the C++ interface directly would be more like what we do for the Python module, and would probably make it easier to translate data structures like the AnyMap class across language boundaries.

@jiweiqi
Copy link

jiweiqi commented Feb 21, 2021

I just invited Chris to see if he could share some suggestions on the choice of ccall .vs. C++ wrapper.

@ischoegl
Copy link
Member

I believe a hybrid option would be to use Cantera's existing framework to handle loading of mechanisms etc. and expose essential reaction parameters to Julia (not too dissimilar of what ReacTorch does in a targeted way). Conversely, it should be possible to write reaction equations in Julia and call them from the C++ framework (which may incur some overhead, but would be quite useful for testing). Another route would be to leverage existing projects, e.g. ReactionMechanismSimulator.jl or others.

@ChrisRackauckas
Copy link

The latest results from ReactionMechanismSimulator.jl show some really nice speedups, so for the most part I plan on spending my time there. But for how to wrap, Sundials.jl uses Clang.jl to automatically generate a full wrapper of the sundials C API, which then gets a Julia wrapper into the DifferentialEquations.jl interface, but can also be used directly if one wished. Cxx.jl and CxxWrap.jl get you to a similar place, but IMO are a bit harder to maintain. But with Clang.jl you cannot make good use of templates, while with Cxx.jl you can JIT compile templated calls (hence the C++ REPL it provides). I like working with Clang.jl because then there's a direct Julia-side equivalent to all structs making the memory matching easy (to me), but YMMV.

@jiweiqi
Copy link

jiweiqi commented Feb 21, 2021

For a hybrid option, using Cantera's interpreter is a very mature way and it is something that we can decide inside Cantera communities. Both ReacTorch and Arrhenius.jl are trying to work in this style.

One thing that I am not sure about is whether there is already API in Cantera's C/Python API that one can access every kinetic parameter. For instance, for now, ReacTorch has to interpret from the YAML files directly for parts of parameters. But I believe there are already APIs existing but I didn't know back at that time.

For the equations, more specifically, computing reaction source term, I believe we certainly should build a wrapper to do that. As Chris mentioned, we could have some nice speedups with DifferentialEquations.jl. But I guess that speed up is based on better Jacobian computation with auto-differentiation. Nevertheless, this is something we should do within Canetra's community as we did for Matlab to facilitate Julia users.

Regarding the efforts of re-implementing the equations for computing reaction source terms in native Julia code, I am not sure whether it should be a part of Cantera or a standalone package since it does equivalent functionality as of Cantera.

@ischoegl
Copy link
Member

ischoegl commented Feb 21, 2021

One thing that I am not sure about is whether there is already API in Cantera's C/Python API that one can access every kinetic parameter. For instance, for now, ReacTorch has to interpret from the YAML files directly for parts of parameters. But I believe there are already APIs existing but I didn't know back at that time.

Most parameters should be available for Python via the cython interface, and adding ones that may not be exposed at the moment is relatively straightforward. The C API (clib) is less developed, but it may not be needed if Julia accesses C++ directly. On cython/clib I can provide pointers if you know what is missing.

@jiweiqi
Copy link

jiweiqi commented Feb 21, 2021

Thanks @ischoegl , I did try to use the wrapper to access that information. I had some difficulties in using ccall since I haven't written c/c++ code for many years. For me, I would like to join the efforts after someone sets up the environment. I mean figure out what package to use, how to set up the environment for development etc.

For the current time being, the development of ReacTorch and Arrhenius.jl are focusing on doing minimal value products to show combustion communities that those PINN and neural ODE stuff are exciting (which is indeed not easy to convince ... based on my experience). By saying exciting, I mean doing things fundamentally new that we can not do with a conventional method. The current mechanism interpreter is sufficient for those algorithms development. But in the long run, I expect that it can rely more on Canetra's interpreter.

@jiweiqi
Copy link

jiweiqi commented Mar 20, 2021

Share some of my recent experience on this topic.

Regarding calling Cantera via PyCall: I think this is a pretty convenient approach if the integration doesn't add much overhead, and we don't need auto-differentiation across the solver. For example, in the package of Arrhenius.jl, it is fairly easy to make a zero-D reactor, although might not robust as Cantera was given the limited time period. But for one-dimensional flame, one has to implement the switching between newton iterations and time-stepping, adaptive grid, etc. Then, it is a good idea to call Cantera to do the calculation of one-d flame. Also, solving one-d flame is usually time-consuming, such that the communication is neglectable. Furthermore, for a steady solution of one-D flame, the sensitivity computation can be easily done offline in Julia by reading the results from Cantera.

looking forward, it will be certainly great to have something like Cantera's Matlab toolbox.

@jiweiqi
Copy link

jiweiqi commented May 5, 2021

For reference, below are some example codes calling Cantera in Julia.
https://github.com/DENG-MIT/Arrhenius_Flame_1D/blob/4e88cd98dc6de9b573ee4754a197d3b29d52345d/src/ct_flame_1d.jl#L5-L37

It is pretty convenient if the goal is not to using Julia's AD eco-system

@Naikless
Copy link

Naikless commented Apr 26, 2022

Just out of interest: In a package I am writing, I am currently using the approach suggested above where I access cantera‘s python interface via PyCall to obtain thermodynamic and kinetic data or calculate equilibriums. Any ODEs are solved using OrdinaryDiffEq.jl.

This works quite conveniently, even though it adds a little extra organizational effort in managing the package’s dependencies (ensure python is installed, choose a compatible cantera version…)

But what I am more interested in are the implications regarding performance. I call some cantera routines via pycall inside my ODE function calls and wonder how much of a bottleneck this actually is. Does anyone have a feeling if trying to switch to a pure Julia implementation using e.g. Arrhenius.jl or trying to access cantera‘s c++ interface directly would significantly improve performance here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request New feature request
Projects
None yet
Development

No branches or pull requests

6 participants