Skip to content

Commit

Permalink
improve dtmin and unstable detection
Browse files Browse the repository at this point in the history
  • Loading branch information
oscardssmith committed May 16, 2024
1 parent 2df59ce commit 429c570
Showing 1 changed file with 41 additions and 26 deletions.
67 changes: 41 additions & 26 deletions src/integrator_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -584,53 +584,68 @@ function check_error(integrator::DEIntegrator)
if integrator.sol.retcode (ReturnCode.Success, ReturnCode.Default)
return integrator.sol.retcode
end
opts = integrator.opts
verbose = opts.verbose

Check warning on line 588 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L587-L588

Added lines #L587 - L588 were not covered by tests
# 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#L597-L598

Added lines #L597 - L598 were 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 sucessfully taking such a small timestep is to hit a tstop exactly

Check warning on line 606 in src/integrator_interface.jl

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"sucessfully" should be "successfully".
# We also exit if the ODE is unstable (by default this is the same as nonfinite u)
# but only consider the ODE unstable if the error is somewhat controlled
# (to prevent from bailing out as unstable when we just took way too big a step)
if !opts.force_dtmin && opts.adaptive
if abs(integrator.dt) <= abs(opts.dtmin) &&

Check warning on line 611 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L610-L611

Added lines #L610 - L611 were not covered by tests
(((hasproperty(integrator, :opts) && hasproperty(opts, :tstops)) ?
integrator.t + integrator.dt < integrator.tdir * first(opts.tstops) :
true) || (hasproperty(integrator, :accept_step) && !integrator.accept_step))
if verbose
if isdefined(integrator, :EEst)
EEst = ", and step error estimate = $(integrator.EEst)"

Check warning on line 617 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L615-L617

Added lines #L615 - L617 were not covered by tests
else
EEst = ""

Check warning on line 619 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L619

Added line #L619 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 621 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L621

Added line #L621 was not covered by tests
end
return ReturnCode.DtLessThanMin
elseif abs(integrator.dt) <= abs(eps(integrator.t)) &&

Check warning on line 624 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L623-L624

Added lines #L623 - L624 were not covered by tests
hasproperty(integrator, :accept_step) && !integrator.accept_step
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
@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.")
return ReturnCode.Unstable

Check warning on line 634 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L634

Added line #L634 was not covered by tests
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
end
bigtol = max(opts.reltol, opts.abstol)
if isdefined(integrator, :EEst) && integrator.EEst * bigtol < .1
if opts.unstable_check(integrator.dt, integrator.u, integrator.p,

Check warning on line 639 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L637-L639

Added lines #L637 - L639 were not covered by tests
integrator.t)
if verbose

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
@warn("Instability detected. Aborting")
end
return ReturnCode.Unstable
end
end
if last_step_failed(integrator)
if integrator.opts.verbose
if verbose

Check warning on line 648 in src/integrator_interface.jl

View check run for this annotation

Codecov / codecov/patch

src/integrator_interface.jl#L648

Added line #L648 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

0 comments on commit 429c570

Please sign in to comment.