-
-
Notifications
You must be signed in to change notification settings - Fork 350
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
Reactor.advance limits can be exceeded greatly #1453
Comments
@speth ... the problem for the surprising behavior is that |
Full code for this examplegas = ct.Solution('h2o2.yaml')
def integrate(limit=None):
P0 = 10 * ct.one_atm
T0 = 1100
X0 = 'H2:1.0, O2:0.5, AR:8.0'
gas.TPX = T0, P0, X0
r1 = ct.IdealGasReactor(gas)
net = ct.ReactorNet([r1])
ix = net.global_component_index('H2', 0)
r1.set_advance_limit('H2', limit)
tEnd = 0.01
tStep = 1e-3
nSteps = 0
states = ct.SolutionArray(gas, extra=['t', 'steps'])
t = tStep
yp = net.get_state()[ix]
steps_p = net.solver_stats['steps']
dy_max = 0
while t < tEnd:
steps = net.solver_stats['steps']
states.append(TPX=r1.thermo.TPX, t=net.time, steps=(steps-steps_p))
steps_p = steps
t_curr = net.advance(t)
y = net.get_state()[ix]
dy_max = max(dy_max, abs(y-yp))
yp = y
nSteps += 1
if t_curr >= t:
t += tStep
print(f'case: {limit=}, {dy_max=}, {nSteps=}')
return nSteps, states
n_baseline, states_baseline = integrate()
n_advance_coarse, states_coarse = integrate(0.01)
n_advance_fine, states_fine = integrate(0.001) While it does take a few more steps in the "coarse" case with the limit imposed, they're not really in the right place. And if you pick time steps that aren't aligned with the IDT, even if they are much smaller than the IDT, then the "fine" case also tends to struggle. For example, setting: tEnd = 0.01
tStep = 1.1e-4
nSteps = 0 Gives the results:
Here, you can see that the output is skipping over almost the entire ignition process despite a fair number of steps occurring before the event. I don't think it's necessary to implement backtracking to fix this. In all of these cases, CVODES is taking several hundred timesteps internally, within one call to |
Depending on the output times given to Reactor.advance, specified limits on the change in one or more state variables can be exceeded by a wide margin. See Cantera#1453
Depending on the output times given to Reactor.advance, specified limits on the change in one or more state variables can be exceeded by a wide margin. See #1453
Looking at the code again, the limits are checked every time there is a call into |
Problem description
Depending on the output times given to
Reactor.advance
, specified limits on the change in one or more state variables can be exceeded by a wide margin. In some cases, this seems to stem from the relevant variable having a near-zero derivative instantaneously, permitting a large interval to be passed on to the internaladvance
method, which then takes many time steps over which the variable changes by more than the expected amount. However, there are other cases where it seems like the instantaneous rate of change should predict the need for a shorter time step.I originally encountered this due to surprising failures for
TestReactor.test_advance_with_limits
in #1452, where it seems that the fact that test passes at all is kind of a fluke.Given the intention for this feature to be a robust way of getting nice output even for inexperienced users (see discussion in #628/#629), I think some improvement here is warranted.
Steps to reproduce
The following is based on
TestReactor.test_advance_with_limits
, with a few modifications.Behavior
As you can see, in the second case, the desired limit is exceeded by more than a factor of 10, and the output jumps over the ignition event entirely. Looking at
states_coarse.steps
, you can see that integrator takes over 2000 time steps between the second and third output points.With a finer limit, the behavior is better, but this isn't even a guaranteed path to success -- if
tStep
is increased to 0.2 s, then both values of the advance limit miss everything. Also, even here, there is a strange gap toward the end of the ignition event where the fuel mass fraction drops by quite a bit with no intervening output.System information
main
branch at 399e1cbThe text was updated successfully, but these errors were encountered: