Question about subclassing ReactorNet

47 views
Skip to first unread message

Cory Kinney

unread,
Jul 4, 2024, 2:20:03 PMJul 4
to Cantera Users' Group
Hello,

I had previously written a simple tool for autoignition simulations using Cantera, but now I'm cleaning it up and adding some functionality so that it can go on PyPI. Originally, the tool only allowed users to run simulations by specifying an end time for the simulation. Now, I'd like to allow the users to be able to simply advance the simulation to steady state rather than specifying an end time. I was going to reimplement the advance to steady state function in my autoignition simulation class, which seems to be the approach that PyMARS took, but copying the functionality and redefining it, along with all of the required tolerance parameters, seems a bit clunky and not elegant.

Then, I realized that all I actually want is to record the state of the reactor at every time step for later reference and for calculating the ignition delay time. So the thought of subclassing ReactorNet and overriding the step behavior occurred to me and I decided to try it out:
import cantera as ct
class AutoignitionSimulation(ct.ReactorNet):
   
    def __init__(self, reactor: ct.Reactor):
        self.reactor = reactor
        super().__init__([self.reactor])
        self.states = ct.SolutionArray(reactor.thermo, extra=["t"])

    def step(self):
        super().step()
        self.states.append(self.reactor.thermo.state, t=self.time)

    def ignition_delay_time():
        ...


Adding the following code below to test it:
from matplotlib import pyplot as plt

gas = ct.Solution("gri30.yaml")
gas.TPX = 1000, 10e5, "H2: 0.1, O2: 0.05, Ar: 0.85"
sim = AutoignitionSimulation(ct.Reactor(gas))
sim.advance_to_steady_state()

plt.plot(sim.states.t, sim.states.T)
plt.show()

The result is a plot stopping right after ignition. This is exactly the behavior I wanted, not having to redefine advance methods but simply tracking state for later analysis, with only a few lines of code changes thanks to inheritance.

Now my question is mostly directed to the Cantera authors, if they are able to answer, but is there any potentially unexpected drawbacks of this approach? Is it reasonable to expect that this probably won't be affected by future updates to Cantera?

Ray Speth

unread,
Jul 7, 2024, 5:41:01 PMJul 7
to Cantera Users' Group

Hi Cory,

I don’t see any significant drawbacks to this approach. The interface of the ReactorNet constructor has been stable since Cantera 2.0, and the step method hasn’t changed since Cantera 2.3 (where an optional argument was removed). And given how fundamental these classes and methods are, any change would come with a round of warnings first.

The one larger change that would affect this is that I would like to eventually replace the advance_to_steady_state solver with a different algorithm based on the steady-state solver used for 1D flames. This is some work that was started quite a while back (PR #1021) but is currently stalled. If and when that is completed, getting the steady-state solution for a reactor network will not involve calls into Python, so overriding the Python step method won’t have any effect. But even when that happens, there will be a release with the existing advance_to_steady_state method in place with a deprecation warning.

Regards,
Ray

Cory Kinney

unread,
Jul 8, 2024, 11:07:32 AMJul 8
to Cantera Users' Group
Hi Ray,

Thanks for the response. I was surprised that overriding  step in the Python interface worked, but now I understand given the current implementation of advance_to_steady_state.  It sounds like the current approach should work for the foreseeable future. I know that extensible reactors were recently added, but I suppose there probably wouldn't be enough utility outside my specific use case to justify an extensible reactor network to truly future-proof it. What I would really be interested in developing, for both my current application and other projects, is a ReactorNet that automatically tracks the state of each reactor in a SolutionArraywith a convenient interface. I wouldn't be able to implement that in Python, I would have to do it in C++, but is that something that would be generally useful for others or too specific just for convenience sake?

Cory

Ray Speth

unread,
Jul 8, 2024, 11:59:54 AMJul 8
to Cantera Users' Group

Hi Cory,

There may not be a strong use case for bringing the full ExtensibleXyz capability to ReactorNet, but it might be useful for this scenario and some debugging use cases to add optional Python callback functions to ReactorNet, similar to the set_time_step_callback and set_steady_callback methods that are available in the 1D solver.

I think adding functionality to automatically build SolutionArray objects for each reactor is a great idea. The possibility of doing this from the C++ side opened up thank’s to Ingmar’s work bringing the SolutionArray class to C++ in Cantera 3.0 — the original implementation I had made was Python only. Please consider writing that up as an item in the Enhancements repository.

Regards,
Ray

Ingmar Schoegl

unread,
Jul 9, 2024, 2:35:07 AM (13 days ago) Jul 9
to Cantera Users' Group
Hi Cory - I saw your enhancement request about the automatically saving to SolutionArray. While it was one motivation for me to port SolutionArray to C++, I never got around implementing it (in many cases, the clunky Python workaround was simple enough). Overall, I don't think that this is too specific of a use case (if done right, it's actually quite broad); I'd be happy to provide pointers if you'd like to take this on!
-ingmar-

Reply all
Reply to author
Forward
0 new messages