diff --git a/Project.toml b/Project.toml index 1d5970bbd..671a8f809 100644 --- a/Project.toml +++ b/Project.toml @@ -27,6 +27,7 @@ RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" RuntimeGeneratedFunctions = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" +SciMLLogging = "a6db7da4-7206-11f0-1eab-35f2a5dbe1d1" SciMLOperators = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" SciMLPublic = "431bcebd-1456-4ced-9d72-93c2757fff0b" SciMLStructures = "53ae85a6-f571-4167-b2af-e1d143709226" @@ -113,6 +114,7 @@ RecursiveArrayTools = "3.35" Reexport = "1" ReverseDiff = "1" RuntimeGeneratedFunctions = "0.5.12" +SciMLLogging = "1.3.1" SciMLOperators = "1.3" SciMLPublic = "1.0.0" SciMLStructures = "1.1" diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index 92b149941..425e1bcb7 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -48,6 +48,8 @@ import SciMLOperators: using SciMLPublic: @public +using SciMLLogging: @SciMLMessage + function __solve end function __init end diff --git a/src/integrator_interface.jl b/src/integrator_interface.jl index 9ba669d56..55a546521 100644 --- a/src/integrator_interface.jl +++ b/src/integrator_interface.jl @@ -612,15 +612,22 @@ function check_error(integrator::DEIntegrator) verbose = opts.verbose # This implementation is intended to be used for ODEIntegrator and # SDEIntegrator. + if isnan(integrator.dt) - if verbose - @warn("NaN dt detected. Likely a NaN value in the state, parameters, or derivative value caused this outcome.") + if verbose isa Bool + @warn "NaN dt detected. Likely a NaN value in the state, parameters, or derivative value caused this outcome." + else + @SciMLMessage("NaN dt detected. Likely a NaN value in the state, parameters, or derivative value caused this outcome.", verbose, :dt_NaN) end return ReturnCode.DtNaN end if integrator.iter > opts.maxiters - if verbose - @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).") + if verbose isa Bool + @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)." + else + @SciMLMessage("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).", + verbose, + :max_iters) end return ReturnCode.MaxIters end @@ -637,38 +644,60 @@ function check_error(integrator::DEIntegrator) (!step_accepted || (hasproperty(opts, :tstops) ? integrator.t + integrator.dt < integrator.tdir * first(opts.tstops) : true)) - if verbose + if verbose isa Bool if isdefined(integrator, :EEst) EEst = ", and step error estimate = $(integrator.EEst)" else EEst = "" 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.") + @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." + else + @SciMLMessage(verbose, :dt_min_unstable) do + if isdefined(integrator, :EEst) + EEst = ", and step error estimate = $(integrator.EEst)" + else + EEst = "" + end + "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." + end end return ReturnCode.DtLessThanMin elseif !step_accepted && integrator.t isa AbstractFloat && abs(integrator.dt) <= abs(eps(integrator.t)) - if verbose + if verbose isa Bool if isdefined(integrator, :EEst) EEst = ", and step error estimate = $(integrator.EEst)" else EEst = "" end - @warn("At t=$(integrator.t), dt was forced below floating point epsilon $(integrator.dt)$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))).") + @warn "At t=$(integrator.t), dt was forced below floating point epsilon $(integrator.dt)$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)))." + else + @SciMLMessage(verbose, :dt_epsilon) do + if isdefined(integrator, :EEst) + EEst = ", and step error estimate = $(integrator.EEst)" + else + EEst = "" + end + "At t=$(integrator.t), dt was forced below floating point epsilon $(integrator.dt)$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)))." + end 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") + if verbose isa Bool + @warn "Instability detected. Aborting" + else + @SciMLMessage("Instability detected. Aborting", verbose, :instability) end return ReturnCode.Unstable end if last_step_failed(integrator) - if verbose - @warn("Newton steps could not converge and algorithm is not adaptive. Use a lower dt.") + if verbose isa Bool + @warn "Newton steps could not converge and algorithm is not adaptive. Use a lower dt." + else + @SciMLMessage("Newton steps could not converge and algorithm is not adaptive. Use a lower dt.", verbose, :newton_convergence) end return ReturnCode.ConvergenceFailure end