From 7a6256afcde759b2d0e2a64494efb134e0d20f55 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Tue, 25 Mar 2025 15:56:34 -0400 Subject: [PATCH 1/9] add AbstractVerbositySpecifier --- src/SciMLBase.jl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index 18a3fb695..d70e43dab 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -633,14 +633,21 @@ abstract type ADOriginator end """ $(TYPEDEF) -Used to specify which variables can be aliased in a solve. -Every concrete AbstractAliasSpecifier should have at least the fields `alias_p` and `alias_f`. +Base for types that specify which variables can be aliased in a solve. +Every concrete AbstractAliasSpecifier should have at least the fields `alias_p` and `alias_f`. """ abstract type AbstractAliasSpecifier end """ $(TYPEDEF) +Base for types which specify what will be printed during a solve. +""" +abstract type AbstractVerbositySpecifier end + +""" +$(TYPEDEF) + Internal. Used for signifying the AD context comes from a ChainRules.jl definition. """ struct ChainRulesOriginator <: ADOriginator end From cc957bb6a6d3d9219f5f585c9fa2eecf3872c2aa Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 8 May 2025 12:14:26 -0400 Subject: [PATCH 2/9] add verbosity stuff --- docs/src/interfaces/Verbosity.md | 9 + src/SciMLBase.jl | 6 +- src/verbosity.jl | 460 +++++++++++++++++++++++++++++++ 3 files changed, 473 insertions(+), 2 deletions(-) create mode 100644 docs/src/interfaces/Verbosity.md create mode 100644 src/verbosity.jl diff --git a/docs/src/interfaces/Verbosity.md b/docs/src/interfaces/Verbosity.md new file mode 100644 index 000000000..fb97c928b --- /dev/null +++ b/docs/src/interfaces/Verbosity.md @@ -0,0 +1,9 @@ +# SciML Verbosity +The SciML verbosity system is designed to make it easy for users to specify what messages are logged, and at what level they are logged at, during the solution process. + +At the highest level are the `AbstractVerbositySpecifier` subtypes, e.g. `ODEVerbosity`, `LinearVerbosity`, and so on. These hold `group` objects that group the error messages into three broad categories. The first is error control, which contains options related to solver error control and adaptivity algorithms, such as convergence issues and correctness guarantees (e.g. `dt < dtmin) + +At the lowest level are the `option` settings. These correspond to either individual messages or groups of messages in + +## Verbosity Types + diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index d70e43dab..ac89986ab 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -641,9 +641,9 @@ abstract type AbstractAliasSpecifier end """ $(TYPEDEF) -Base for types which specify what will be printed during a solve. +Base for types which specify which log messages are emitted at what level. """ -abstract type AbstractVerbositySpecifier end +abstract type AbstractVerbositySpecifier{T} end """ $(TYPEDEF) @@ -770,6 +770,8 @@ include("integrator_interface.jl") include("remake.jl") include("callbacks.jl") +include("verbosity.jl") + include("adapt.jl") include("deprecated.jl") diff --git a/src/verbosity.jl b/src/verbosity.jl new file mode 100644 index 000000000..976faad68 --- /dev/null +++ b/src/verbosity.jl @@ -0,0 +1,460 @@ +@data Verbosity begin + None + Edge + Info + Warn + Error + All + Default + Level(Int) +end + + +function message_level(verbose::AbstractVerbositySpecifier{true}, option, group) + group = getproperty(verbose, group) + opt_level = getproperty(group, option) + + @match opt_level begin + Verbosity.None() => nothing + Verbosity.Info() => Logging.Info + Verbosity.Warn() => Logging.Warn + Verbosity.Error() => Logging.Error + Verbosity.Level(i) => Logging.LogLevel(i) + end +end + +function emit_message( + f::Function, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) + level = message_level(verbose, option, group) + + if !isnothing(level) + message = f() + Base.@logmsg level message _file=file _line=line _module=_module + end +end + +function emit_message(message::String, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) + level = message_level(verbose, option, group) + + if !isnothing(level) + Base.@logmsg level message _file=file _line=line _module=_module + end +end + +function emit_message(f, verbose::AbstractVerbositySpecifier{false}, option, group, file, line, _module) +end + +@doc doc""" +A macro that emits a log message based on the log level specified in the `option` and `group` of the `AbstractVerbositySpecifier` supplied. + +`f_or_message` may be a message String, or a 0-argument function that returns a String. + +## Usage +To emit a simple string, `@SciMLMessage("message", verbosity, :option, :group)` will emit a log message with the LogLevel specified in `verbosity`, at the appropriate `option` and `group`. + +`@SciMLMessage` can also be used to emit a log message coming from the evaluation of a 0-argument function. This function is resolved in the environment of the macro call. +Therefore it can use variables from the surrounding evironment. This may be useful if the log message writer wishes to carry out some calculations using existing variables +and use them. + +```julia +x = 10 +y = 20 + +@SciMLMessage(verbosity, :option, :group) do + z = x + y + "Message is: x + y = \$z" +end +``` +""" +macro SciMLMessage(f_or_message, verb, option, group) + line = __source__.line + file = string(__source__.file) + _module = __module__ + return :(emit_message($(esc(f_or_message)), $(esc(verb)), $toggle, $group, $file, $line, $_module)) +end + + +# Linear Verbosity + +mutable struct LinearErrorControlVerbosity + +end + +function LinearErrorControlVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearErrorControlVerbosity(fill(Verbosity.None(), nfields(LinearErrorControlVerbosity))...) + + Verbosity.Warn() => LinearErrorControlVerbosity(fill(Verbosity.Warn(), nfields(LinearErrorControlVerbosity))...) + + Verbosity.Error() => LinearErrorControlVerbosity(fill(Verbosity.Error(), nfields(LinearErrorControlVerbosity))...) + + Verbosity.Default() => LinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => LinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct LinearPerformanceVerbosity + + @add_kwonly function LinearPerformanceVerbosity() + new() + end +end + + + +function LinearPerformanceVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearPerformanceVerbosity(fill( + Verbosity.None(), nfields(LinearPerformanceVerbosity))...) + + Verbosity.Warn() => LinearPerformanceVerbosity(fill( + Verbosity.Warn(), nfields(LinearPerformanceVerbosity))...) + + Verbosity.Error() => LinearPerformanceVerbosity(fill( + Verbosity.Error(), nfields(LinearPerformanceVerbosity))...) + + Verbosity.Default() => LinearPerformanceVerbosity( + Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => LinearPerformanceVerbosity(Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct LinearNumericalVerbosity + @add_kwonly function LinearNumericalVerbosity() + LinearNumericalVerbosity() + end + +end + + +function LinearNumericalVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearNumericalVerbosity(fill( + Verbosity.None(), nfields(LinearNumericalVerbosity))...) + + Verbosity.Warn() => LinearNumericalVerbosity(fill( + Verbosity.Warn(), nfields(LinearNumericalVerbosity))...) + + Verbosity.Error() => LinearNumericalVerbosity(fill( + Verbosity.Error(), nfields(LinearNumericalVerbosity))...) + + Verbosity.Default() => LinearNumericalVerbosity( + Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => LinearNumericalVerbosity(Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +struct LinearVerbosity{T} + error_control::LinearErrorControlVerbosity + performance::LinearPerformanceVerbosity + numerical::LinearNumericalVerbosity +end + +function LinearVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.Default() => LinearVerbosity{true}( + LinearErrorControlVerbosity(Verbosity.Default()), + LinearPerformanceVerbosity(Verbosity.Default()), + LinearNumericalVerbosity(Verbosity.Default()) + ) + + Verbosity.None() => LinearVerbosity{false}( + LinearErrorControlVerbosity(Verbosity.None()), + LinearPerformanceVerbosity(Verbosity.None()), + LinearNumericalVerbosity(Verbosity.None())) + + Verbosity.All() => ODEVerbosity{true}( + LinearErrorControlVerbosity(Verbosity.All()), + LinearPerformanceVerbosity(Verbosity.All()), + LinearNumericalVerbosity(Verbosity.All()) + ) + + _ => @error "Not a valid choice for verbosity." + end +end + +# Nonlinear Verbosity + +mutable struct NonlinearErrorControlVerbosity + @add_kwonly function NonlinearErrorControlVerbosity() + NonlinearErrorControlVerbosity() + end +end + + + +function NonlinearErrorControlVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => NonlinearErrorControlVerbosity(fill( + Verbosity.None(), nfields(NonlinearErrorControlVerbosity))...) + + Verbosity.Warn() => NonlinearErrorControlVerbosity(fill( + Verbosity.Warn(), nfields(NonlinearErrorControlVerbosity))...) + + Verbosity.Error() => NonlinearNumericalVerbosity(fill( + Verbosity.Error(), nfields(NonlinearErrorControlVerbosity))...) + + Verbosity.Default() => NonlinearErrorControlVerbosity( + Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => NonlinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct NonlinearPerformanceVerbosity + @add_kwonly function NonlinearPerformanceVerbosity() + NonlinearPerformanceVerbosity() + end + +end + + +function NonlinearPerformanceVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => NonlinearPerformanceVerbosity(fill( + Verbosity.None(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Warn() => NonlinPerformanceVerbosity(fill( + Verbosity.Warn(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Error() => NonlinearPerformanceVerbosity(fill( + Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Default() => NonlinearPerformanceVerbosity( + Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => NonlinearPerformanceVerbosity( + Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + + +mutable struct NonlinearNumericalVerbosity + @add_kwonly function NonlinearNumericalVerbosity() + NonlinearNumericalVerbosity() + end +end + +function NonlinearNumericalVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => NonlinearNumericalVerbosity(fill( + Verbosity.None(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Warn() => NonlinearNumericalVerbosity(fill( + Verbosity.Warn(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Error() => NonlinearNumericalVerbosity(fill( + Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) + + Verbosity.Default() => NonlinearNumericalVerbosity( + Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => NonlinearNumericalVerbosity( + Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +struct NonlinearVerbosity{T} + linear_verbosity::LinearVerbosity + + error_control::NonlinearErrorControlVerbosity + performance::NonlinearPerformanceVerbosity + numerical::NonlinearNumericalVerbosity +end + +function NonlinearVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.Default() => NonlinearVerbosity{true}( + LinearVerbosity(Verbosity.Default()), + NonlinearErrorControlVerbosity(Verbosity.Default()), + NonlinearPerformanceVerbosity(Verbosity.Default()), + NonlinearNumericalVerbosity(Verbosity.Default()) + ) + + Verbosity.None() => NonlinearVerbosity{false}( + LinearVerbosity(Verbosity.None()), + NonlinearErrorControlVerbosity(Verbosity.None()), + NonlinearPerformanceVerbosity(Verbosity.None()), + NonlinearNumericalVerbosity(Verbosity.None())) + + Verbosity.All() => ODEVerbosity{true}( + LinearVerbosity(Verbosity.All()), + NonlinearErrorControlVerbosity(Verbosity.All()), + NonlinearPerformanceVerbosity(Verbosity.All()), + NonlinearNumericalVerbosity(Verbosity.All()) + ) + + _ => @error "Not a valid choice for verbosity." + end +end + +# ODE Verbosity + +mutable struct ODEErrorControlVerbosity + dt_NaN::Verbosity.Type + init_NaN::Verbosity.Type + + @add_kwonly function ODEErrorControlVerbosity(dt_NaN, init_NaN) + ODEErrorControlVerbosity(dt_NaN, init_NaN) + end +end + + + +function ODEErrorControlVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => ODEErrorControlVerbosity(fill( + Verbosity.None(), nfields(ODEErrorControlVerbosity))...) + + Verbosity.Warn() => ODEErrorControlVerbosity(fill( + Verbosity.Warn(), nfields(ODEErrorControlVerbosity))...) + + Verbosity.Error() => ODEErrorControlVerbosity(fill( + Verbosity.Error(), nfields(ODEErrorControlVerbosity))...) + + Verbosity.Default() => ODEErrorControlVerbosity(Verbosity.Info(), Verbosity.Error()) + + Verbosity.Edge() => ODEErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct ODEPerformanceVerbosity + @add_kwonly function ODEPerformanceVerbosity(dt_NaN, init_NaN) + ODEPerformanceVerbosity(dt_NaN, init_NaN) + end +end + + + +function ODEPerformanceVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => ODEPerformanceVerbosity(fill( + Verbosity.None(), nfields(ODEPerformanceVerbosity))...) + + Verbosity.Warn() => ODEPerformanceVerbosity(fill( + Verbosity.Warn(), nfields(ODEPerformanceVerbosity))...) + + Verbosity.Error() => ODEPerformanceVerbosity(fill( + Verbosity.Error(), nfields(ODEPerformanceVerbosity))...) + + Verbosity.Default() => ODEPerformanceVerbosity(Verbosity.Warn(), Verbosity.Error()) + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct ODENumericalVerbosity + @add_kwonly function ODENumericalVerbosity(dt_NaN, init_NaN) + ODEErrorControlVerbosity(dt_NaN, init_NaN) + end +end + + + +function ODENumericalVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => ODENumericalVerbosity(fill( + Verbosity.None(), nfields(ODENumericalVerbosity))...) + + Verbosity.Warn() => ODENumericalVerbosity(fill( + Verbosity.Warn(), nfields(ODENumericalVerbosity))...) + + Verbosity.Error() => ODENumericalVerbosity(fill( + Verbosity.Error(), nfields(ODENumericalVerbosity))...) + + Verbosity.Default() => ODENumericalVerbosity(Verbosity.Warn(), Verbosity.Error()) + + _ => @error "Not a valid choice for verbosity." + end +end + +struct ODEVerbosity{T} + nonlinear_verbosity::NonlinearVerbosity + linear_verbosity::LinearVerbosity + + error_control::ODEErrorControlVerbosity + performance::ODEPerformanceVerbosity + numerical::ODENumericalVerbosity +end + +function ODEVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.Default() => ODEVerbosity{true}( + LinearVerbosity(Verbosity.Default()), + NonlinearVerbosity(Verbosity.Default()), + ODEErrorControlVerbosity(Verbosity.Default()), + ODEPerformanceVerbosity(Verbosity.Default()), + ODENumericalVerbosity(Verbosity.Default()) + ) + + Verbosity.None() => ODEVerbosity{false}( + LinearVerbosity(Verbosity.None()), + NonlinearVerbosity(Verbosity.None()), + ODEErrorControlVerbosity(Verbosity.None()), + ODEPerformanceVerbosity(Verbosity.None()), + ODENumericalVerbosity(Verbosity.None()) + ) + + Verbosity.All() => ODEVerbosity{true}( + LinearVerbosity(Verbosity.All()), + NonlinearVerbosity(Verbosity.All()), + ODEErrorControlVerbosity(Verbosity.All()), + ODEPerformanceVerbosity(Verbosity.All()), + ODENumericalVerbosity(Verbosity.All()) + ) + + _ => @error "Not a valid choice for verbosity." + end +end + +function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbosity.Default(), numerical = Verbosity.Default(), linear_verbosity = Verbosity.Default(), nonlinear_verbosity = Verbosity.Default()) + + if error_control isa Verbosity.Type + error_control_verbosity = ODEErrorControlVerbosity(error_control) + else + error_control_verbosity = error_control + end + + if performance isa Verbosity.Type + performance_verbosity = ODEPerformanceVerbosity(performance) + else + performance_verbosity = performance + end + + if numerical isa Verbosity.Type + numerical_verbosity = ODENumericalVerbosity(numerical) + else + numerical_verbosity = numerical + end + + if linear_verbosity isa Verbosity.Type + linear = LinearVerbosity(linear_verbosity) + else + linear = linear_verbosity + end + + if nonlinear_verbosity isa Verbosity.Type + nonlinear = NonlinearVerbosity(nonlinear_verbosity) + else + nonlinear = nonlinear_verbosity + end + + ODEVerbosity(nonlinear, linear, error_control_verbosity, performance_verbosity, numerical_verbosity) +end From a584633979bb305ef175e449f142550be9447197 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Fri, 9 May 2025 12:17:15 -0400 Subject: [PATCH 3/9] rearrange --- src/verbosity.jl | 182 +++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 92 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index 976faad68..6d8d199ca 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -1,79 +1,15 @@ @data Verbosity begin None - Edge Info Warn Error + Level(Int) + Edge All Default - Level(Int) -end - - -function message_level(verbose::AbstractVerbositySpecifier{true}, option, group) - group = getproperty(verbose, group) - opt_level = getproperty(group, option) - - @match opt_level begin - Verbosity.None() => nothing - Verbosity.Info() => Logging.Info - Verbosity.Warn() => Logging.Warn - Verbosity.Error() => Logging.Error - Verbosity.Level(i) => Logging.LogLevel(i) - end -end - -function emit_message( - f::Function, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) - level = message_level(verbose, option, group) - if !isnothing(level) - message = f() - Base.@logmsg level message _file=file _line=line _module=_module - end end -function emit_message(message::String, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) - level = message_level(verbose, option, group) - - if !isnothing(level) - Base.@logmsg level message _file=file _line=line _module=_module - end -end - -function emit_message(f, verbose::AbstractVerbositySpecifier{false}, option, group, file, line, _module) -end - -@doc doc""" -A macro that emits a log message based on the log level specified in the `option` and `group` of the `AbstractVerbositySpecifier` supplied. - -`f_or_message` may be a message String, or a 0-argument function that returns a String. - -## Usage -To emit a simple string, `@SciMLMessage("message", verbosity, :option, :group)` will emit a log message with the LogLevel specified in `verbosity`, at the appropriate `option` and `group`. - -`@SciMLMessage` can also be used to emit a log message coming from the evaluation of a 0-argument function. This function is resolved in the environment of the macro call. -Therefore it can use variables from the surrounding evironment. This may be useful if the log message writer wishes to carry out some calculations using existing variables -and use them. - -```julia -x = 10 -y = 20 - -@SciMLMessage(verbosity, :option, :group) do - z = x + y - "Message is: x + y = \$z" -end -``` -""" -macro SciMLMessage(f_or_message, verb, option, group) - line = __source__.line - file = string(__source__.file) - _module = __module__ - return :(emit_message($(esc(f_or_message)), $(esc(verb)), $toggle, $group, $file, $line, $_module)) -end - - # Linear Verbosity mutable struct LinearErrorControlVerbosity @@ -88,9 +24,9 @@ function LinearErrorControlVerbosity(verbose::Verbosity.Type) Verbosity.Error() => LinearErrorControlVerbosity(fill(Verbosity.Error(), nfields(LinearErrorControlVerbosity))...) - Verbosity.Default() => LinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => LinearErrorControlVerbosity() - Verbosity.Edge() => LinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => LinearErrorControlVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -116,10 +52,9 @@ function LinearPerformanceVerbosity(verbose::Verbosity.Type) Verbosity.Error() => LinearPerformanceVerbosity(fill( Verbosity.Error(), nfields(LinearPerformanceVerbosity))...) - Verbosity.Default() => LinearPerformanceVerbosity( - Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => LinearPerformanceVerbosity() - Verbosity.Edge() => LinearPerformanceVerbosity(Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => LinearPerformanceVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -144,10 +79,9 @@ function LinearNumericalVerbosity(verbose::Verbosity.Type) Verbosity.Error() => LinearNumericalVerbosity(fill( Verbosity.Error(), nfields(LinearNumericalVerbosity))...) - Verbosity.Default() => LinearNumericalVerbosity( - Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => LinearNumericalVerbosity() - Verbosity.Edge() => LinearNumericalVerbosity(Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => LinearNumericalVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -203,10 +137,9 @@ function NonlinearErrorControlVerbosity(verbose::Verbosity.Type) Verbosity.Error() => NonlinearNumericalVerbosity(fill( Verbosity.Error(), nfields(NonlinearErrorControlVerbosity))...) - Verbosity.Default() => NonlinearErrorControlVerbosity( - Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => NonlinearErrorControlVerbosity() - Verbosity.Edge() => NonlinearErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => NonlinearErrorControlVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -214,7 +147,7 @@ end mutable struct NonlinearPerformanceVerbosity @add_kwonly function NonlinearPerformanceVerbosity() - NonlinearPerformanceVerbosity() + new() end end @@ -231,11 +164,9 @@ function NonlinearPerformanceVerbosity(verbose::Verbosity.Type) Verbosity.Error() => NonlinearPerformanceVerbosity(fill( Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) - Verbosity.Default() => NonlinearPerformanceVerbosity( - Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => NonlinearPerformanceVerbosity() - Verbosity.Edge() => NonlinearPerformanceVerbosity( - Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => NonlinearPerformanceVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -244,7 +175,7 @@ end mutable struct NonlinearNumericalVerbosity @add_kwonly function NonlinearNumericalVerbosity() - NonlinearNumericalVerbosity() + new() end end @@ -259,11 +190,9 @@ function NonlinearNumericalVerbosity(verbose::Verbosity.Type) Verbosity.Error() => NonlinearNumericalVerbosity(fill( Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) - Verbosity.Default() => NonlinearNumericalVerbosity( - Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => NonlinearNumericalVerbosity() - Verbosity.Edge() => NonlinearNumericalVerbosity( - Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => NonlinearNumericalVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -310,7 +239,7 @@ mutable struct ODEErrorControlVerbosity init_NaN::Verbosity.Type @add_kwonly function ODEErrorControlVerbosity(dt_NaN, init_NaN) - ODEErrorControlVerbosity(dt_NaN, init_NaN) + new(dt_NaN, init_NaN) end end @@ -337,7 +266,7 @@ end mutable struct ODEPerformanceVerbosity @add_kwonly function ODEPerformanceVerbosity(dt_NaN, init_NaN) - ODEPerformanceVerbosity(dt_NaN, init_NaN) + new(dt_NaN, init_NaN) end end @@ -354,7 +283,7 @@ function ODEPerformanceVerbosity(verbose::Verbosity.Type) Verbosity.Error() => ODEPerformanceVerbosity(fill( Verbosity.Error(), nfields(ODEPerformanceVerbosity))...) - Verbosity.Default() => ODEPerformanceVerbosity(Verbosity.Warn(), Verbosity.Error()) + Verbosity.Default() => ODEPerformanceVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -362,7 +291,7 @@ end mutable struct ODENumericalVerbosity @add_kwonly function ODENumericalVerbosity(dt_NaN, init_NaN) - ODEErrorControlVerbosity(dt_NaN, init_NaN) + new(dt_NaN, init_NaN) end end @@ -379,7 +308,7 @@ function ODENumericalVerbosity(verbose::Verbosity.Type) Verbosity.Error() => ODENumericalVerbosity(fill( Verbosity.Error(), nfields(ODENumericalVerbosity))...) - Verbosity.Default() => ODENumericalVerbosity(Verbosity.Warn(), Verbosity.Error()) + Verbosity.Default() => ODENumericalVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -458,3 +387,72 @@ function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbo ODEVerbosity(nonlinear, linear, error_control_verbosity, performance_verbosity, numerical_verbosity) end + + +# Utilities + +function message_level(verbose::AbstractVerbositySpecifier{true}, option, group) + group = getproperty(verbose, group) + opt_level = getproperty(group, option) + + @match opt_level begin + Verbosity.None() => nothing + Verbosity.Info() => Logging.Info + Verbosity.Warn() => Logging.Warn + Verbosity.Error() => Logging.Error + Verbosity.Level(i) => Logging.LogLevel(i) + end +end + +function emit_message( + f::Function, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) + level = message_level(verbose, option, group) + + if !isnothing(level) + message = f() + Base.@logmsg level message _file=file _line=line _module=_module + end +end + +function emit_message(message::String, verbose::AbstractVerbositySpecifier{true}, + option, group, file, line, _module) + level = message_level(verbose, option, group) + + if !isnothing(level) + Base.@logmsg level message _file=file _line=line _module=_module + end +end + +function emit_message( + f, verbose::AbstractVerbositySpecifier{false}, option, group, file, line, _module) +end + +@doc doc""" +A macro that emits a log message based on the log level specified in the `option` and `group` of the `AbstractVerbositySpecifier` supplied. + +`f_or_message` may be a message String, or a 0-argument function that returns a String. + +## Usage +To emit a simple string, `@SciMLMessage("message", verbosity, :option, :group)` will emit a log message with the LogLevel specified in `verbosity`, at the appropriate `option` and `group`. + +`@SciMLMessage` can also be used to emit a log message coming from the evaluation of a 0-argument function. This function is resolved in the environment of the macro call. +Therefore it can use variables from the surrounding environment. This may be useful if the log message writer wishes to carry out some calculations using existing variables +and use them in the log message. + +```julia +x = 10 +y = 20 + +@SciMLMessage(verbosity, :option, :group) do + z = x + y + "Message is: x + y = \$z" +end +``` +""" +macro SciMLMessage(f_or_message, verb, option, group) + line = __source__.line + file = string(__source__.file) + _module = __module__ + return :(emit_message( + $(esc(f_or_message)), $(esc(verb)), $toggle, $group, $file, $line, $_module)) +end \ No newline at end of file From 418fe1ae6623d68034a6f8dfae387f2fe0d70fc6 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Fri, 9 May 2025 12:17:28 -0400 Subject: [PATCH 4/9] more writing --- docs/src/interfaces/Verbosity.md | 56 +++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/docs/src/interfaces/Verbosity.md b/docs/src/interfaces/Verbosity.md index fb97c928b..785e53d45 100644 --- a/docs/src/interfaces/Verbosity.md +++ b/docs/src/interfaces/Verbosity.md @@ -1,9 +1,57 @@ # SciML Verbosity -The SciML verbosity system is designed to make it easy for users to specify what messages are logged, and at what level they are logged at, during the solution process. +The SciML verbosity system is designed to make it easy for users to specify what messages are logged and at what level they are logged at during the solution process. -At the highest level are the `AbstractVerbositySpecifier` subtypes, e.g. `ODEVerbosity`, `LinearVerbosity`, and so on. These hold `group` objects that group the error messages into three broad categories. The first is error control, which contains options related to solver error control and adaptivity algorithms, such as convergence issues and correctness guarantees (e.g. `dt < dtmin) +At the highest level are the `AbstractVerbositySpecifier` subtypes, e.g. `ODEVerbosity`, `LinearVerbosity`, and so on. These hold "group" objects that group the error messages into three broad categories. The first is error control, which contains options related to solver error control and adaptivity algorithms, such as convergence issues and correctness guarantees (e.g. `dt < dtmin`). The numerical group holds options pertaining to performance issues, such as large condition numbers and detection of potential floating point issues. Finally the performance group has options related to potential performance issues. For example, mismatched input/output types in out of place functions, and other known performance traps. An example of a group object would be `ODEPerformanceVerbosity`. -At the lowest level are the `option` settings. These correspond to either individual messages or groups of messages in +At the lowest level are the `option` settings. These correspond to either individual messages or groups of messages relating to a specific issue or piece of information. For example, the `dt_NaN` option in the `ODEErrorControl` group sets the level of a log message that states that the adaptive timestepping algorithm set `dt` to `NaN`. -## Verbosity Types +The system is also hierarchical in the sense that for example `ODEVerbosity` also contains a `NonlinearVerbosity` and a `LinearVerbosity`, because an ODE solve might use NonlinearSolve and LinearSolve. Note that `NonlinearVerbosity` also has a `LinearVerbosity`, because NonlinearSolve also can use LinearSolve. The `LinearVerbosity` in the `ODEVerbosity` handles any calls to LinearSolve that are not inside of a call to NonlinearSolve. + +# Base Verbosity Types +The base verbosity specifiers are [Moshi.jl](https://rogerluo.dev/Moshi.jl/) algebraic data types. These allow for pattern matching and gives a namespace `Verbosity` to access the types with. +There are five of these types that are used for the lowest level option toggles: + +- `None`: indicates that this message should not be logged. +- `Info`: indicates that this message should be logged with a log level of `Info` +- `Warn`: indicates that this message should be logged with a log level of `Warn` +- `Error`: indicates that this message should be logged with a log level of `Error` +- `Level`: indicates that this message should be logged with a custom log level held by the `Level` type, e.g. `Verbosity.Level(4)` corresponds to `Logging.LogLevel(4)` + +Three of these types are only meant to be used for higher level constructors of the verbosity types: + +- `Edge`: messages in this group or verbosity specifier are only logged when they relate to edge cases +- `All`: All messages in this group or verbosity specifier are logged +- `Default`: only the default messages of this group or verbosity specifier are logged. + +# Constructors + +The constructors for the verbosity specifiers are designed to be flexible. For example, they can takes some of the base verbosity types described above: + +```julia +ODEVerbosity(Verbosity.None()) #logs nothing +ODEVerbosity(Verbosity.All()) #logs everything +ODEVerbosity(Verbosity.Default()) #logs somethings +``` + +They also have keyword argument constructors that can take base verbosity types and automatically construct the correct group object, while also taking a group object for a different +group: + +```julia +# Doesn't print out any error_control information, warns if there is an `init_dt` issue, errors if there is a `dt_NaN` issue, uses Verbosity.Default() for ODENumericalVerbosity +ODEVerbosity(error_control = Verbosity.None(), performance = ODEPerformanceVerbosity(init_dt = Verbosity.Warn(), dt_NaN = Verbosity.Error())) +``` + +Similarly, all of the group objects have equally flexible constructors, but take different base verbosity types. + +```julia +ODENumericalVerbosity(Verbosity.None()) #logs nothing +ODENumericalVerbosity(Verbosity.Warn()) #everything is logged as a warning +``` + +# SciMLMessage Macro +```@docs +SciMLBase.SciMLMessage +``` + +# Verbosity API From e50e408701304fb1ba9ede66fecf24caacc2a0b7 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Fri, 9 May 2025 15:14:05 -0400 Subject: [PATCH 5/9] fix stuff --- docs/src/interfaces/Verbosity.md | 2 + src/verbosity.jl | 135 ++++++++++++++++++------------- 2 files changed, 83 insertions(+), 54 deletions(-) diff --git a/docs/src/interfaces/Verbosity.md b/docs/src/interfaces/Verbosity.md index 785e53d45..219806d6d 100644 --- a/docs/src/interfaces/Verbosity.md +++ b/docs/src/interfaces/Verbosity.md @@ -46,6 +46,8 @@ Similarly, all of the group objects have equally flexible constructors, but take ```julia ODENumericalVerbosity(Verbosity.None()) #logs nothing ODENumericalVerbosity(Verbosity.Warn()) #everything is logged as a warning + +ODEErrorControlVerbosity(init_dt = Verbosity.Warn(), dt_NaN = Verbosity.Error()) ``` # SciMLMessage Macro diff --git a/src/verbosity.jl b/src/verbosity.jl index 6d8d199ca..d380bfc6f 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -18,11 +18,13 @@ end function LinearErrorControlVerbosity(verbose::Verbosity.Type) @match verbose begin - Verbosity.None() => LinearErrorControlVerbosity(fill(Verbosity.None(), nfields(LinearErrorControlVerbosity))...) + Verbosity.None() => LinearErrorControlVerbosity(fill(Verbosity.None(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Warn() => LinearErrorControlVerbosity(fill(Verbosity.Warn(), nfields(LinearErrorControlVerbosity))...) + Verbosity.Info() => LinearErrorControlVerbosity(fill(Verbosity.Info(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Error() => LinearErrorControlVerbosity(fill(Verbosity.Error(), nfields(LinearErrorControlVerbosity))...) + Verbosity.Warn() => LinearErrorControlVerbosity(fill(Verbosity.Warn(), length(fieldnames(LinearErrorControlVerbosity)))...) + + Verbosity.Error() => LinearErrorControlVerbosity(fill(Verbosity.Error(), length(fieldnames(LinearErrorControlVerbosity)))...) Verbosity.Default() => LinearErrorControlVerbosity() @@ -44,13 +46,16 @@ end function LinearPerformanceVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => LinearPerformanceVerbosity(fill( - Verbosity.None(), nfields(LinearPerformanceVerbosity))...) + Verbosity.None(), length(fieldnames(LinearPerformanceVerbosity)))...) + + Verbosity.Info() => LinearPerformanceVerbosity(fill( + Verbosity.Info(), length(fieldnames(LinearPerformanceVerbosity)))...) Verbosity.Warn() => LinearPerformanceVerbosity(fill( - Verbosity.Warn(), nfields(LinearPerformanceVerbosity))...) + Verbosity.Warn(), length(fieldnames(LinearPerformanceVerbosity)))...) Verbosity.Error() => LinearPerformanceVerbosity(fill( - Verbosity.Error(), nfields(LinearPerformanceVerbosity))...) + Verbosity.Error(), length(fieldnames(LinearPerformanceVerbosity)))...) Verbosity.Default() => LinearPerformanceVerbosity() @@ -62,7 +67,7 @@ end mutable struct LinearNumericalVerbosity @add_kwonly function LinearNumericalVerbosity() - LinearNumericalVerbosity() + new() end end @@ -71,13 +76,16 @@ end function LinearNumericalVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => LinearNumericalVerbosity(fill( - Verbosity.None(), nfields(LinearNumericalVerbosity))...) + Verbosity.None(), length(fieldnames(LinearNumericalVerbosity)))...) + + Verbosity.Info() => LinearNumericalVerbosity(fill( + Verbosity.Info(), length(fieldnames(LinearNumericalVerbosity)))...) Verbosity.Warn() => LinearNumericalVerbosity(fill( - Verbosity.Warn(), nfields(LinearNumericalVerbosity))...) + Verbosity.Warn(), length(fieldnames(LinearNumericalVerbosity)))...) Verbosity.Error() => LinearNumericalVerbosity(fill( - Verbosity.Error(), nfields(LinearNumericalVerbosity))...) + Verbosity.Error(), length(fieldnames(LinearNumericalVerbosity)))...) Verbosity.Default() => LinearNumericalVerbosity() @@ -87,7 +95,7 @@ function LinearNumericalVerbosity(verbose::Verbosity.Type) end end -struct LinearVerbosity{T} +struct LinearVerbosity{T} <: AbstractVerbositySpecifier{T} error_control::LinearErrorControlVerbosity performance::LinearPerformanceVerbosity numerical::LinearNumericalVerbosity @@ -106,10 +114,10 @@ function LinearVerbosity(verbose::Verbosity.Type) LinearPerformanceVerbosity(Verbosity.None()), LinearNumericalVerbosity(Verbosity.None())) - Verbosity.All() => ODEVerbosity{true}( - LinearErrorControlVerbosity(Verbosity.All()), - LinearPerformanceVerbosity(Verbosity.All()), - LinearNumericalVerbosity(Verbosity.All()) + Verbosity.All() => LinearVerbosity{true}( + LinearErrorControlVerbosity(Verbosity.Info()), + LinearPerformanceVerbosity(Verbosity.Info()), + LinearNumericalVerbosity(Verbosity.Info()) ) _ => @error "Not a valid choice for verbosity." @@ -120,7 +128,7 @@ end mutable struct NonlinearErrorControlVerbosity @add_kwonly function NonlinearErrorControlVerbosity() - NonlinearErrorControlVerbosity() + new() end end @@ -129,13 +137,16 @@ end function NonlinearErrorControlVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => NonlinearErrorControlVerbosity(fill( - Verbosity.None(), nfields(NonlinearErrorControlVerbosity))...) + Verbosity.None(), length(fieldnames(NonlinearErrorControlVerbosity)))...) + + Verbosity.Info() => NonlinearErrorControlVerbosity(fill( + Verbosity.Info(), length(fieldnames(NonlinearErrorControlVerbosity)))...) Verbosity.Warn() => NonlinearErrorControlVerbosity(fill( - Verbosity.Warn(), nfields(NonlinearErrorControlVerbosity))...) + Verbosity.Warn(), length(fieldnames(NonlinearErrorControlVerbosity)))...) Verbosity.Error() => NonlinearNumericalVerbosity(fill( - Verbosity.Error(), nfields(NonlinearErrorControlVerbosity))...) + Verbosity.Error(), length(fieldnames(NonlinearErrorControlVerbosity)))...) Verbosity.Default() => NonlinearErrorControlVerbosity() @@ -156,13 +167,16 @@ end function NonlinearPerformanceVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => NonlinearPerformanceVerbosity(fill( - Verbosity.None(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.None(), length(fieldnames(NonlinearPerformanceVerbosity)))...) + + Verbosity.Info() => NonlinearPerformanceVerbosity(fill( + Verbosity.Info(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Warn() => NonlinPerformanceVerbosity(fill( - Verbosity.Warn(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.Warn(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Error() => NonlinearPerformanceVerbosity(fill( - Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.Error(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Default() => NonlinearPerformanceVerbosity() @@ -182,13 +196,16 @@ end function NonlinearNumericalVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => NonlinearNumericalVerbosity(fill( - Verbosity.None(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.None(), length(fieldnames(NonlinearPerformanceVerbosity)))...) + + Verbosity.Info() => NonlinearNumericalVerbosity(fill( + Verbosity.Info(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Warn() => NonlinearNumericalVerbosity(fill( - Verbosity.Warn(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.Warn(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Error() => NonlinearNumericalVerbosity(fill( - Verbosity.Error(), nfields(NonlinearPerformanceVerbosity))...) + Verbosity.Error(), length(fieldnames(NonlinearPerformanceVerbosity)))...) Verbosity.Default() => NonlinearNumericalVerbosity() @@ -198,7 +215,7 @@ function NonlinearNumericalVerbosity(verbose::Verbosity.Type) end end -struct NonlinearVerbosity{T} +struct NonlinearVerbosity{T} <: AbstractVerbositySpecifier{T} linear_verbosity::LinearVerbosity error_control::NonlinearErrorControlVerbosity @@ -221,11 +238,11 @@ function NonlinearVerbosity(verbose::Verbosity.Type) NonlinearPerformanceVerbosity(Verbosity.None()), NonlinearNumericalVerbosity(Verbosity.None())) - Verbosity.All() => ODEVerbosity{true}( + Verbosity.All() => NonlinearVerbosity{true}( LinearVerbosity(Verbosity.All()), - NonlinearErrorControlVerbosity(Verbosity.All()), - NonlinearPerformanceVerbosity(Verbosity.All()), - NonlinearNumericalVerbosity(Verbosity.All()) + NonlinearErrorControlVerbosity(Verbosity.Info()), + NonlinearPerformanceVerbosity(Verbosity.Info()), + NonlinearNumericalVerbosity(Verbosity.Info()) ) _ => @error "Not a valid choice for verbosity." @@ -248,13 +265,16 @@ end function ODEErrorControlVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => ODEErrorControlVerbosity(fill( - Verbosity.None(), nfields(ODEErrorControlVerbosity))...) + Verbosity.None(), length(fieldnames(ODEErrorControlVerbosity)))...) + + Verbosity.Info() => ODEErrorControlVerbosity(fill( + Verbosity.Info(), length(fieldnames(ODEErrorControlVerbosity)))...) Verbosity.Warn() => ODEErrorControlVerbosity(fill( - Verbosity.Warn(), nfields(ODEErrorControlVerbosity))...) + Verbosity.Warn(), length(fieldnames(ODEErrorControlVerbosity)))...) Verbosity.Error() => ODEErrorControlVerbosity(fill( - Verbosity.Error(), nfields(ODEErrorControlVerbosity))...) + Verbosity.Error(), length(fieldnames(ODEErrorControlVerbosity)))...) Verbosity.Default() => ODEErrorControlVerbosity(Verbosity.Info(), Verbosity.Error()) @@ -265,8 +285,8 @@ function ODEErrorControlVerbosity(verbose::Verbosity.Type) end mutable struct ODEPerformanceVerbosity - @add_kwonly function ODEPerformanceVerbosity(dt_NaN, init_NaN) - new(dt_NaN, init_NaN) + @add_kwonly function ODEPerformanceVerbosity() + new() end end @@ -275,13 +295,16 @@ end function ODEPerformanceVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => ODEPerformanceVerbosity(fill( - Verbosity.None(), nfields(ODEPerformanceVerbosity))...) + Verbosity.None(), length(fieldnames(ODEPerformanceVerbosity)))...) + + Verbosity.Info() => ODEPerformanceVerbosity(fill( + Verbosity.Info(), length(fieldnames(ODEPerformanceVerbosity)))...) Verbosity.Warn() => ODEPerformanceVerbosity(fill( - Verbosity.Warn(), nfields(ODEPerformanceVerbosity))...) + Verbosity.Warn(), length(fieldnames(ODEPerformanceVerbosity)))...) Verbosity.Error() => ODEPerformanceVerbosity(fill( - Verbosity.Error(), nfields(ODEPerformanceVerbosity))...) + Verbosity.Error(), length(fieldnames(ODEPerformanceVerbosity)))...) Verbosity.Default() => ODEPerformanceVerbosity() @@ -290,8 +313,8 @@ function ODEPerformanceVerbosity(verbose::Verbosity.Type) end mutable struct ODENumericalVerbosity - @add_kwonly function ODENumericalVerbosity(dt_NaN, init_NaN) - new(dt_NaN, init_NaN) + @add_kwonly function ODENumericalVerbosity() + new() end end @@ -300,13 +323,16 @@ end function ODENumericalVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => ODENumericalVerbosity(fill( - Verbosity.None(), nfields(ODENumericalVerbosity))...) + Verbosity.None(), length(fieldnames(ODENumericalVerbosity)))...) + + Verbosity.Info() => ODENumericalVerbosity(fill( + Verbosity.None(), length(fieldnames(ODENumericalVerbosity)))...) Verbosity.Warn() => ODENumericalVerbosity(fill( - Verbosity.Warn(), nfields(ODENumericalVerbosity))...) + Verbosity.Warn(), length(fieldnames(ODENumericalVerbosity)))...) Verbosity.Error() => ODENumericalVerbosity(fill( - Verbosity.Error(), nfields(ODENumericalVerbosity))...) + Verbosity.Error(), length(fieldnames(ODENumericalVerbosity)))...) Verbosity.Default() => ODENumericalVerbosity() @@ -314,9 +340,9 @@ function ODENumericalVerbosity(verbose::Verbosity.Type) end end -struct ODEVerbosity{T} - nonlinear_verbosity::NonlinearVerbosity +struct ODEVerbosity{T} <: AbstractVerbositySpecifier{T} linear_verbosity::LinearVerbosity + nonlinear_verbosity::NonlinearVerbosity error_control::ODEErrorControlVerbosity performance::ODEPerformanceVerbosity @@ -344,9 +370,9 @@ function ODEVerbosity(verbose::Verbosity.Type) Verbosity.All() => ODEVerbosity{true}( LinearVerbosity(Verbosity.All()), NonlinearVerbosity(Verbosity.All()), - ODEErrorControlVerbosity(Verbosity.All()), - ODEPerformanceVerbosity(Verbosity.All()), - ODENumericalVerbosity(Verbosity.All()) + ODEErrorControlVerbosity(Verbosity.Info()), + ODEPerformanceVerbosity(Verbosity.Info()), + ODENumericalVerbosity(Verbosity.Info()) ) _ => @error "Not a valid choice for verbosity." @@ -385,7 +411,7 @@ function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbo nonlinear = nonlinear_verbosity end - ODEVerbosity(nonlinear, linear, error_control_verbosity, performance_verbosity, numerical_verbosity) + ODEVerbosity{true}(linear, nonlinear, error_control_verbosity, performance_verbosity, numerical_verbosity) end @@ -405,17 +431,18 @@ function message_level(verbose::AbstractVerbositySpecifier{true}, option, group) end function emit_message( - f::Function, verbose::AbstractVerbositySpecifier{true}, option, group, file, line, _module) - level = message_level(verbose, option, group) + f::Function, verbose::V, option, group, file, line, _module) where {V<:AbstractVerbositySpecifier{true}} + level = message_level( + verbose, option, group) if !isnothing(level) message = f() Base.@logmsg level message _file=file _line=line _module=_module end end -function emit_message(message::String, verbose::AbstractVerbositySpecifier{true}, - option, group, file, line, _module) +function emit_message(message::String, verbose::V, + option, group, file, line, _module) where {V<:AbstractVerbositySpecifier{true}} level = message_level(verbose, option, group) if !isnothing(level) @@ -454,5 +481,5 @@ macro SciMLMessage(f_or_message, verb, option, group) file = string(__source__.file) _module = __module__ return :(emit_message( - $(esc(f_or_message)), $(esc(verb)), $toggle, $group, $file, $line, $_module)) + $(esc(f_or_message)), $(esc(verb)), $option, $group, $file, $line, $_module)) end \ No newline at end of file From 59c725d285c54bc9dc671b75f86963906cfbde0a Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 22 May 2025 13:50:59 -0400 Subject: [PATCH 6/9] add alg_switch --- src/verbosity.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index d380bfc6f..132c1f07b 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -285,8 +285,10 @@ function ODEErrorControlVerbosity(verbose::Verbosity.Type) end mutable struct ODEPerformanceVerbosity + alg_switch + @add_kwonly function ODEPerformanceVerbosity() - new() + new(alg_switch) end end From 614bc89acc5c35d716a5f044262e223127ce5101 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 22 May 2025 14:38:54 -0400 Subject: [PATCH 7/9] add autoalg switching --- src/verbosity.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index 132c1f07b..bf61a38cc 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -287,7 +287,7 @@ end mutable struct ODEPerformanceVerbosity alg_switch - @add_kwonly function ODEPerformanceVerbosity() + @add_kwonly function ODEPerformanceVerbosity(alg_switch) new(alg_switch) end end @@ -308,7 +308,7 @@ function ODEPerformanceVerbosity(verbose::Verbosity.Type) Verbosity.Error() => ODEPerformanceVerbosity(fill( Verbosity.Error(), length(fieldnames(ODEPerformanceVerbosity)))...) - Verbosity.Default() => ODEPerformanceVerbosity() + Verbosity.Default() => ODEPerformanceVerbosity(alg_switch = Verbosity.None()) _ => @error "Not a valid choice for verbosity." end From a1c1e93fec3af2a5ea2136f46f9f99b22f16cb37 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Tue, 27 May 2025 12:44:27 -0400 Subject: [PATCH 8/9] add ability for ODEVerbosity constructor to take more kwargs --- src/verbosity.jl | 58 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index bf61a38cc..324c62024 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -7,9 +7,21 @@ Edge All Default - end +# Defaults + +defaults = + Dict( + :dt_NaN => Verbosity.Warn(), + :init_NaN => Verbosity.Warn(), + :rosenbrock_no_differential_states => Verbosity.Warn(), + :dense_output_saveat => Verbosity.Warn(), + :alg_switch => Verbosity.Warn(), + :mismatched_input_output_type => Verbosity.Warn() + ) + + # Linear Verbosity mutable struct LinearErrorControlVerbosity @@ -35,7 +47,6 @@ function LinearErrorControlVerbosity(verbose::Verbosity.Type) end mutable struct LinearPerformanceVerbosity - @add_kwonly function LinearPerformanceVerbosity() new() end @@ -132,8 +143,6 @@ mutable struct NonlinearErrorControlVerbosity end end - - function NonlinearErrorControlVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => NonlinearErrorControlVerbosity(fill( @@ -254,9 +263,12 @@ end mutable struct ODEErrorControlVerbosity dt_NaN::Verbosity.Type init_NaN::Verbosity.Type + rosenbrock_no_differential_states::Verbosity.Type + dense_output_saveat::Verbosity.Type - @add_kwonly function ODEErrorControlVerbosity(dt_NaN, init_NaN) - new(dt_NaN, init_NaN) + function ODEErrorControlVerbosity(dt_NaN = defaults[:dt_NaN], init_NaN = defaults[:init_NaN], + rosenbrock_no_differential_states = defaults[:rosenbrock_no_differential_states], dense_output_saveat = defaults[:dense_output_saveat]) + new(dt_NaN, init_NaN, rosenbrock_no_differential_states, dense_output_saveat) end end @@ -276,24 +288,23 @@ function ODEErrorControlVerbosity(verbose::Verbosity.Type) Verbosity.Error() => ODEErrorControlVerbosity(fill( Verbosity.Error(), length(fieldnames(ODEErrorControlVerbosity)))...) - Verbosity.Default() => ODEErrorControlVerbosity(Verbosity.Info(), Verbosity.Error()) + Verbosity.Default() => ODEErrorControlVerbosity() - Verbosity.Edge() => ODEErrorControlVerbosity(Verbosity.Info(), Verbosity.Warn()) + Verbosity.Edge() => ODEErrorControlVerbosity() _ => @error "Not a valid choice for verbosity." end end mutable struct ODEPerformanceVerbosity - alg_switch + alg_switch::Verbosity.Type + mismatched_input_output_type::Verbosity.Type - @add_kwonly function ODEPerformanceVerbosity(alg_switch) - new(alg_switch) + function ODEPerformanceVerbosity(;alg_switch = defaults[:alg_switch], mismatched_input_output_type = defaults[:mismatched_input_output_type]) + new(alg_switch, mismatched_input_output_type) end end - - function ODEPerformanceVerbosity(verbose::Verbosity.Type) @match verbose begin Verbosity.None() => ODEPerformanceVerbosity(fill( @@ -308,7 +319,7 @@ function ODEPerformanceVerbosity(verbose::Verbosity.Type) Verbosity.Error() => ODEPerformanceVerbosity(fill( Verbosity.Error(), length(fieldnames(ODEPerformanceVerbosity)))...) - Verbosity.Default() => ODEPerformanceVerbosity(alg_switch = Verbosity.None()) + Verbosity.Default() => ODEPerformanceVerbosity() _ => @error "Not a valid choice for verbosity." end @@ -381,7 +392,7 @@ function ODEVerbosity(verbose::Verbosity.Type) end end -function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbosity.Default(), numerical = Verbosity.Default(), linear_verbosity = Verbosity.Default(), nonlinear_verbosity = Verbosity.Default()) +function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbosity.Default(), numerical = Verbosity.Default(), linear_verbosity = Verbosity.Default(), nonlinear_verbosity = Verbosity.Default(), kwargs...) if error_control isa Verbosity.Type error_control_verbosity = ODEErrorControlVerbosity(error_control) @@ -413,6 +424,20 @@ function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbo nonlinear = nonlinear_verbosity end + if !isempty(kwargs) + for (key, value) in pairs(kwargs) + if hasfield(ODEErrorControlVerbosity, key) + setproperty!(error_control_verbosity, key, value) + elseif hasfield(ODEPerformanceVerbosity, key) + setproperty!(performance_verbosity, key, value) + elseif hasfield(ODENumericalVerbosity, key) + setproperty!(numerical_verbosity, key, value) + else + error("$key is not a recognized verbosity toggle.") + end + end + end + ODEVerbosity{true}(linear, nonlinear, error_control_verbosity, performance_verbosity, numerical_verbosity) end @@ -484,4 +509,5 @@ macro SciMLMessage(f_or_message, verb, option, group) _module = __module__ return :(emit_message( $(esc(f_or_message)), $(esc(verb)), $option, $group, $file, $line, $_module)) -end \ No newline at end of file +end + From cf008d7a8b1309950625979f70256a8f26073264 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Tue, 27 May 2025 13:19:24 -0400 Subject: [PATCH 9/9] allow NamedTuples for Nonlinear and Linear verbosity --- src/verbosity.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index 324c62024..55bbaee40 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -77,7 +77,7 @@ function LinearPerformanceVerbosity(verbose::Verbosity.Type) end mutable struct LinearNumericalVerbosity - @add_kwonly function LinearNumericalVerbosity() + function LinearNumericalVerbosity() new() end @@ -138,7 +138,7 @@ end # Nonlinear Verbosity mutable struct NonlinearErrorControlVerbosity - @add_kwonly function NonlinearErrorControlVerbosity() + function NonlinearErrorControlVerbosity() new() end end @@ -166,7 +166,7 @@ function NonlinearErrorControlVerbosity(verbose::Verbosity.Type) end mutable struct NonlinearPerformanceVerbosity - @add_kwonly function NonlinearPerformanceVerbosity() + function NonlinearPerformanceVerbosity() new() end @@ -197,7 +197,7 @@ end mutable struct NonlinearNumericalVerbosity - @add_kwonly function NonlinearNumericalVerbosity() + function NonlinearNumericalVerbosity() new() end end @@ -414,12 +414,16 @@ function ODEVerbosity(; error_control = Verbosity.Default(), performance = Verbo if linear_verbosity isa Verbosity.Type linear = LinearVerbosity(linear_verbosity) + elseif linear_verbosity isa NamedTuple + linear = LinearVerbosity(linear) else linear = linear_verbosity end if nonlinear_verbosity isa Verbosity.Type nonlinear = NonlinearVerbosity(nonlinear_verbosity) + elseif nonlinear_verbosity isa NamedTuple + nonlinear = NonlinearVerbosity(nonlinear_verbosity) else nonlinear = nonlinear_verbosity end