-
-
Notifications
You must be signed in to change notification settings - Fork 222
Verbosity System [Very Rough Draft] #2688
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
Conversation
end | ||
|
||
|
||
mutable struct ODEErrorControlVerbosity |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are only two uses of the verbose
keyword in OrdinaryDiffEq so I had to make some up for demo purposes. In reality these will all be options that toggle error messages related to error control.
I also want to add a macro for this so that we can automatically get the correct line number, file, and module using |
Switched to using a macro, now you can just write @SciMLMessage(integrator.opts.verbose, :thing1, :error_control) do
"u₁ is $u₁"
end or @SciMLMessage("This is a logging message", integrator.opts.verbose, :thing3, :numerical) and it will automatically get the correct file name, line, and module. May need to think about hygiene more though. |
if integrator.opts.verbose && isnan(d₁) | ||
@warn("First function call produced NaNs. Exiting. Double check that none of the initial conditions, parameters, or timespan values are NaN.") | ||
if isnan(d₁) | ||
@SciMLMessage("First function call produced NaNs. Exiting. Double check that none of the initial conditions, parameters, or timespan values are NaN.", integrator.opts.verbose, :thing5, :numerical) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a numerical issue. It's an error or control flow one
@@ -154,6 +154,14 @@ | |||
|
|||
u₁ = zero(u0) # required by DEDataArray | |||
|
|||
@SciMLMessage(integrator.opts.verbose, :thing1, :error_control) do | |||
"u₁ is $u₁" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make much sense to track
@@ -175,6 +183,21 @@ | |||
# Avoids AD issues | |||
length(u0) > 0 && f₀ == f₁ && return tdir * max(dtmin, 100dt₀) | |||
|
|||
@SciMLMessage(integrator.opts.verbose, :thing3, :performance) do | |||
if length(u0) > 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The specific messages here are more for demonstration purposes, I made some up to show that the macro works, this one demonstrates that you can write a do-block involving the outside variables and the result will be put in the log.
If it makes sense to do it this way, most of this stuff should be moved to SciMLBase and then we can start writing error messages using the macro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The verbosity system looks right. I think we can start the move of the interface to SciMLBase
@@ -41,7 +41,7 @@ mutable struct DEOptions{absType, relType, QT, tType, Controller, F1, F2, F3, F4 | |||
callback::F4 | |||
isoutofdomain::F5 | |||
unstable_check::F7 | |||
verbose::Bool | |||
verbose |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type stability
This is a very early rough draft of the verbosity system described in SciML/SciMLBase.jl#962.
It closely follows what was written there. I wanted to put this here as a demo of what this could look like, but likely the final definitions etc. will be located in SciMLBase.
The basic idea is that there's an
ODEVerbosity
type, which has fieldserror_control
,performance
, andnumerical
, which areODEErrorControlVerbosity
,ODEPerformanceVerbosity
, andODENumericalVerbosity
.ODEVerbosity
also has a Bool type parameter, that just represents a toggle determining whether there will be any log messages that are emitted. The reason it's a type parameter is so that the code that creates the error messages can be statically determined to not run. I'm not sure it's necessary for that to work yet though.ODEErrorControlVerbosity
etc. holds fields that will toggle individual log messages. The "types" of each field will determine what log message level is emitted, there's also an option to emit no log message. The verbosity levels are defined as a Moshi.jl ADT, which provides namespacing for the Verbosity types, and exhaustive pattern matching. This can be changed pretty easily, but it matches the namespacing of enums in the issue linked.The
ODEVerbosity
is held in theDEOptions
object in the integrator. The verbosity object is callable, with two different methods. One is(verbose::ODEVerbosity)(message, option, group, values...)
, which emitsmessage
, at the level set byoption
.group
represent which of error control, performance, or numerical this message falls under, and will be included in the metadata for the log message and can be used for filtering.(verbose::ODEVerbosity)(f::Function, option, values...)
will run the function and use the return value as the log message, and facilitate the do block syntax and allow for things like:so that the message can involve calculated information. If the ODEVerbosity type parameter is false, calling the verbosity object goes to an empty function. Also, if the toggle in the ODEVerbosity is
Verbosity.None()
the function does not get run.I kept the "choosing what is printed and at what level" separate from "choosing where each level goes", which can be handled by the logger. We can provide an
ODELogger
function that's just creates a composition of loggers from LoggingExtras with some convenient options for toggling REPL printing and printing to files. We might want to add awith_logger
somewhere and have alogger
keyword argument, but that does make stacktraces and using the debugger a lot more annoying, so maybe iflogger
is nothing it bypasses thewith_logger
.We can define a helper function that just constructs a composition of loggers from LoggingExtras. In order to make this really easy for users we might want to make this a keyword argument that passes to a
with_logger
, so we could just do something likesolve(prob, verbose = ODEVerbosity(Verbosity.Default()), logger = ODELogger(info_file = "info.txt", info_repl = false))
for example.I think by using specific combinations of ODEVerbosity settings and custom loggers