Python and Julia arrays indexing

Hello, I am trying to use a reaction solver package of Python called Cantera in Julia using PyCall. In the following code, I am trying to extract all reactions that contain “CO” and “CO2” in the reactant side and product side respectively. gas is a Python Object with gas.reactions() producing an array of Python Objects containing all the reactions. The reactants and products are defined as dictionaries and can be accessed for each reaction using .reactants and .products.
This is the code I wrote for the task at hand:

using PyCall
@pyimport cantera as ct
gas=ct.Solution("gri30.xml");
II = [i for (i,r) in enumerate(gas.reactions()) if "CO" in keys(r.reactants) && "CO2" in keys(r.products)]
for i in II
    print("\n")
    print(gas.reaction(i).equation)
end

Surprisingly, I get the following output:

HCO + O <=> CO + OH
CH2O + O2 <=> HCO + HO2
HCO + OH <=> CO + H2O
CH2O + HO2 <=> H2O2 + HCO

However, if I change the i inside the array II to i-1

II = [i-1 for (i,r) in enumerate(gas.reactions()) if "CO" in keys(r.reactants) && "CO2" in keys(r.products)]
for i in II
    print("\n")
    print(gas.reaction(i).equation)
end

it works perfectly well:

CO + O (+M) <=> CO2 (+M)
CO + O2 <=> CO2 + O
CO + OH <=> CO2 + H
CO + HO2 <=> CO2 + OH

Any insights on why such a thing happens? My initial guess was python arrays start with 0 while Julia arrays start with 1.

Yes. That is it.

5 Likes

@leandromartinez98 thank you for the link to the documentation. However, what I felt was invoking PyCall automatically accounts for this difference and I needn’t correct for it each time.

It does, but you are not accessing the element with getindex but rather through a function (i) and PyCall thus does not know to shift the index by 1 in this case.

Had you accessed an array with array[i], PyCall would handle it.

4 Likes

Just saw this discussion. I have been working on a native Julia package for combustion those days, called Arrhenius.jl at GitHub - DENG-MIT/Arrhenius.jl: Combustion Kinetic Modeling Software 2.0. I made the initial version within a couple of hours since it is built on top of Cantera’s mechanism interpreter! Part of the reason to make it is to avoid the pain of coupling between python and Julia … But the most important motivation is to have a native Julia code so that we can use Julia’s auto-differentiation packages.

I assume what you are looking for is the reaction source term since it is relatively simple to code governing equations. If that’s the case, definitely check out the package.

julia> a = PyObject([1,2,3])
PyObject array([1, 2, 3], dtype=int64)

julia> a[0]
3

julia> a[1]
1

julia> a[2]
2

julia> a[3]
3

julia> a[-1]
2

I’m confused by this half-julia half-python behavior, seems to be wrong in both worlds

3 Likes