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

improve dtmin and unstable detection #693

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 39 additions & 28 deletions src/integrator_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -584,53 +584,64 @@
if integrator.sol.retcode ∉ (ReturnCode.Success, ReturnCode.Default)
return integrator.sol.retcode
end
opts = integrator.opts
verbose = opts.verbose
# This implementation is intended to be used for ODEIntegrator and
# SDEIntegrator.
if isnan(integrator.dt)
if integrator.opts.verbose
if verbose

Check warning on line 592 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L592

Added line #L592 was not covered by tests
@warn("NaN dt detected. Likely a NaN value in the state, parameters, or derivative value caused this outcome.")
end
return ReturnCode.DtNaN
end
if integrator.iter > integrator.opts.maxiters
if integrator.opts.verbose
if integrator.iter > opts.maxiters
if verbose

Check warning on line 598 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L598

Added line #L598 was not covered by tests
@warn("Interrupted. Larger maxiters is needed. If you are using an integrator for non-stiff ODEs or an automatic switching algorithm (the default), you may want to consider using a method for stiff equations. See the solver pages for more details (e.g. https://docs.sciml.ai/DiffEqDocs/stable/solvers/ode_solve/#Stiff-Problems).")
end
return ReturnCode.MaxIters
end

# The last part:
# If you are close to the end, don't exit: let the user hit the end!
# However, if we try that and the step fails, exit instead of infinite loop
if !integrator.opts.force_dtmin && integrator.opts.adaptive &&
abs(integrator.dt) <= abs(integrator.opts.dtmin) &&
(((hasproperty(integrator, :opts) && hasproperty(integrator.opts, :tstops)) ?
integrator.t + integrator.dt < integrator.tdir * first(integrator.opts.tstops) :
true) || (hasproperty(integrator, :accept_step) && !integrator.accept_step))
if integrator.opts.verbose
if isdefined(integrator, :EEst)
EEst = ", and step error estimate = $(integrator.EEst)"
else
EEst = ""
# Bail out if we take a step with dt less than the minimum value (which may be time dependent)
# except if we are successfully taking such a small timestep is to hit a tstop exactly
# We also exit if the ODE is unstable according to a user chosen callback
# but only if we accepted the step to prevent from bailing out as unstable
# when we just took way too big a step)
step_accepted = !hasproperty(integrator, :accept_step) || integrator.accept_step
if !opts.force_dtmin && opts.adaptive
if abs(integrator.dt) <= abs(opts.dtmin) &&
(!step_accepted || (hasproperty(opts, :tstops) ?
integrator.t + integrator.dt < integrator.tdir * first(opts.tstops) :
true))
if verbose
if isdefined(integrator, :EEst)
EEst = ", and step error estimate = $(integrator.EEst)"

Check warning on line 618 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L616-L618

Added lines #L616 - L618 were not covered by tests
else
EEst = ""

Check warning on line 620 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L620

Added line #L620 was not covered by tests
end
@warn("dt($(integrator.dt)) <= dtmin($(opts.dtmin)) at t=$(integrator.t)$EEst. Aborting. There is either an error in your model specification or the true solution is unstable.")

Check warning on line 622 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L622

Added line #L622 was not covered by tests
end
@warn("dt($(integrator.dt)) <= dtmin($(integrator.opts.dtmin)) at t=$(integrator.t)$EEst. Aborting. There is either an error in your model specification or the true solution is unstable.")
end
return ReturnCode.DtLessThanMin
end
if integrator.opts.unstable_check(integrator.dt, integrator.u, integrator.p,
integrator.t)
bigtol = max(integrator.opts.reltol, integrator.opts.abstol)
# only declare instability if the dt is very small
# or we have at least one digit of accuracy in the solution
if integrator.dt<eps(integrator.t) || isdefined(integrator, :EEst) && integrator.EEst * bigtol < .1
if integrator.opts.verbose
@warn("Instability detected. Aborting")
return ReturnCode.DtLessThanMin

Check warning on line 624 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L624

Added line #L624 was not covered by tests
elseif !step_accepted && integrator.t isa AbstractFloat && abs(integrator.dt) <= abs(eps(integrator.t))
if verbose
if isdefined(integrator, :EEst)
EEst = ", and step error estimate = $(integrator.EEst)"

Check warning on line 628 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L626-L628

Added lines #L626 - L628 were not covered by tests
else
EEst = ""

Check warning on line 630 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L630

Added line #L630 was not covered by tests
end
@warn("dt($(integrator.dt)) <= eps(t)($(integrator.t)) $EEst. Aborting. There is either an error in your model specification or the true solution is unstable (or the true solution can not be represented in the precision of $(eltype(integrator.u))).")

Check warning on line 632 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L632

Added line #L632 was not covered by tests
end
return ReturnCode.Unstable
end
end
if step_accepted && opts.unstable_check(integrator.dt, integrator.u, integrator.p, integrator.t)
if verbose
@warn("Instability detected. Aborting")

Check warning on line 639 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L638-L639

Added lines #L638 - L639 were not covered by tests
end
return ReturnCode.Unstable

Check warning on line 641 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L641

Added line #L641 was not covered by tests
end
if last_step_failed(integrator)
if integrator.opts.verbose
if verbose

Check warning on line 644 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L644

Added line #L644 was not covered by tests
@warn("Newton steps could not converge and algorithm is not adaptive. Use a lower dt.")
end
return ReturnCode.ConvergenceFailure
Expand Down
Loading