From 84978dbe5037de07bc86a009d0debde943dac73e Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 10:27:14 -0400 Subject: [PATCH 1/8] add linear verbosity stuff --- src/verbosity.jl | 250 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/verbosity.jl diff --git a/src/verbosity.jl b/src/verbosity.jl new file mode 100644 index 000000000..bf706f589 --- /dev/null +++ b/src/verbosity.jl @@ -0,0 +1,250 @@ +@data Verbosity begin + None + Info + Warn + Error + Level(Int) + Edge + All + Default +end + +# Linear Verbosity + +linear_defaults = Dict( + :default_lu_fallback => Verbosity.Warn() +:using_iterative_solvers => Verbosity.Warn() +) +mutable struct LinearErrorControlVerbosity + default_lu_fallback::Verbosity.Type + + function LinearErrorControlVerbosity(; + default_lu_fallback = linear_defaults[:default_lu_fallback]) + new(default_lu_fallback) + end +end + +function LinearErrorControlVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearErrorControlVerbosity(fill( + Verbosity.None(), length(fieldnames(LinearErrorControlVerbosity)))...) + + Verbosity.Info() => LinearErrorControlVerbosity(fill( + Verbosity.Info(), length(fieldnames(LinearErrorControlVerbosity)))...) + + Verbosity.Warn() => LinearErrorControlVerbosity(fill( + Verbosity.Warn(), length(fieldnames(LinearErrorControlVerbosity)))...) + + Verbosity.Error() => LinearErrorControlVerbosity(fill( + Verbosity.Error(), length(fieldnames(LinearErrorControlVerbosity)))...) + + Verbosity.Default() => LinearErrorControlVerbosity() + + Verbosity.Edge() => LinearErrorControlVerbosity() + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct LinearPerformanceVerbosity + no_right_preconditioning::Verbosity.Type + function LinearPerformanceVerbosity(; + no_right_preconditioning = linear_defaults[:no_right_preconditioning]) + new(no_right_preconditioning) + end +end + +function LinearPerformanceVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearPerformanceVerbosity(fill( + Verbosity.None(), length(fieldnames(LinearPerformanceVerbosity)))...) + + Verbosity.Info() => LinearPerformanceVerbosity(fill( + Verbosity.Info(), length(fieldnames(LinearPerformanceVerbosity)))...) + + Verbosity.Warn() => LinearPerformanceVerbosity(fill( + Verbosity.Warn(), length(fieldnames(LinearPerformanceVerbosity)))...) + + Verbosity.Error() => LinearPerformanceVerbosity(fill( + Verbosity.Error(), length(fieldnames(LinearPerformanceVerbosity)))...) + + Verbosity.Default() => LinearPerformanceVerbosity() + + Verbosity.Edge() => LinearPerformanceVerbosity() + + _ => @error "Not a valid choice for verbosity." + end +end + +mutable struct LinearNumericalVerbosity + using_IterativeSolvers::Verbosity.Type + IterativeSolvers_iterations::Verbosity.Type + KrylovKit_verbosity::Verbosity.Type + + function LinearNumericalVerbosity(; + using_IterativeSolvers = linear_defaults[:using_IterativeSolvers], + IterativeSolvers_iterations = linear_defaults[:IterativeSolvers_iterations], + KrylovKit_verbosity = linear_defaults[:KrylovKit_verbosity]) + new(using_IterativeSolvers, IterativeSolvers_iterations, KrylovKit_verbosity) + end +end + +function LinearNumericalVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => LinearNumericalVerbosity(fill( + Verbosity.None(), length(fieldnames(LinearNumericalVerbosity)))...) + + Verbosity.Info() => LinearNumericalVerbosity(fill( + Verbosity.Info(), length(fieldnames(LinearNumericalVerbosity)))...) + + Verbosity.Warn() => LinearNumericalVerbosity(fill( + Verbosity.Warn(), length(fieldnames(LinearNumericalVerbosity)))...) + + Verbosity.Error() => LinearNumericalVerbosity(fill( + Verbosity.Error(), length(fieldnames(LinearNumericalVerbosity)))...) + + Verbosity.Default() => LinearNumericalVerbosity() + + Verbosity.Edge() => LinearNumericalVerbosity() + + _ => @error "Not a valid choice for verbosity." + end +end + +struct LinearVerbosity{T} <: AbstractVerbositySpecifier{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() => LinearVerbosity{true}( + LinearErrorControlVerbosity(Verbosity.Info()), + LinearPerformanceVerbosity(Verbosity.Info()), + LinearNumericalVerbosity(Verbosity.Info()) + ) + + _ => @error "Not a valid choice for verbosity." + end +end + +function LinearVerbosity(; + error_control = Verbosity.Default(), performance = Verbosity.Default(), + numerical = Verbosity.Default(), kwargs...) + if error_control isa Verbosity.Type + error_control_verbosity = LinearErrorControlVerbosity(error_control) + else + error_control_verbosity = error_control + end + + if performance isa Verbosity.Type + performance_verbosity = LinearPerformanceVerbosity(performance) + else + performance_verbosity = performance + end + + if numerical isa Verbosity.Type + numerical_verbosity = LinearNumericalVerbosity(numerical) + else + numerical_verbosity = numerical + end + + if !isempty(kwargs) + for (key, value) in pairs(kwargs) + if hasfield(LinearErrorControlVerbosity, key) + setproperty!(error_control_verbosity, key, value) + elseif hasfield(LinearPerformanceVerbosity, key) + setproperty!(performance_verbosity, key, value) + elseif hasfield(LinearNumericalVerbosity, key) + setproperty!(numerical_verbosity, key, value) + else + error("$key is not a recognized verbosity toggle.") + end + end + end + + LinearVerbosity{true}(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::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::V, + option, group, file, line, _module) where {V <: AbstractVerbositySpecifier{true}} + 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)), $option, $group, $file, $line, $_module)) +end + From 72bf843ce522739d4d91bf0ded46f1680e5b66cb Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 11:15:20 -0400 Subject: [PATCH 2/8] add to SciMLBase --- src/SciMLBase.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index 18a3fb695..d56bed6ee 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -763,6 +763,8 @@ include("integrator_interface.jl") include("remake.jl") include("callbacks.jl") +include("verbosity.jl") + include("adapt.jl") include("deprecated.jl") From 8d4ff8a12857c7c404c33c116a97b3ecedce05fd Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 11:15:33 -0400 Subject: [PATCH 3/8] add defaults --- src/verbosity.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index bf706f589..c47c1208a 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -11,10 +11,14 @@ end # Linear Verbosity -linear_defaults = Dict( - :default_lu_fallback => Verbosity.Warn() -:using_iterative_solvers => Verbosity.Warn() -) +# linear_defaults = Dict( +# :default_lu_fallback => Verbosity.Warn() +# :no_right_preconditioning => Verbosity.Warn() +# :using_iterative_solvers => Verbosity.Warn() +# :using_IterativeSolvers => Verbosity.Warn() +# :IterativeSolvers_iterations => Verbosity.Warn() +# :KrylovKit_verbosity => Verbosity.Warn() +# ) mutable struct LinearErrorControlVerbosity default_lu_fallback::Verbosity.Type From f69d5d3aa1298c05cbf2dfaa407d8658bbfecd97 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 11:16:39 -0400 Subject: [PATCH 4/8] add AbstractVerbositySpecifier --- src/SciMLBase.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/SciMLBase.jl b/src/SciMLBase.jl index d56bed6ee..42bbb2927 100644 --- a/src/SciMLBase.jl +++ b/src/SciMLBase.jl @@ -641,6 +641,13 @@ abstract type AbstractAliasSpecifier end """ $(TYPEDEF) +Base for types which specify which log messages are emitted at what level. +""" +abstract type AbstractVerbositySpecifier{T} end + +""" +$(TYPEDEF) + Internal. Used for signifying the AD context comes from a ChainRules.jl definition. """ struct ChainRulesOriginator <: ADOriginator end From 91a421b0f63a3d80505078f3862bc45252264e17 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 11:32:28 -0400 Subject: [PATCH 5/8] move to inner constructors so they can use new --- src/verbosity.jl | 105 +++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index c47c1208a..d8dfae4d6 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -11,14 +11,14 @@ end # Linear Verbosity -# linear_defaults = Dict( -# :default_lu_fallback => Verbosity.Warn() -# :no_right_preconditioning => Verbosity.Warn() -# :using_iterative_solvers => Verbosity.Warn() -# :using_IterativeSolvers => Verbosity.Warn() -# :IterativeSolvers_iterations => Verbosity.Warn() -# :KrylovKit_verbosity => Verbosity.Warn() -# ) +linear_defaults = Dict( + :default_lu_fallback => Verbosity.Warn(), + :no_right_preconditioning => Verbosity.Warn(), + :using_iterative_solvers => Verbosity.Warn(), + :using_IterativeSolvers => Verbosity.Warn(), + :IterativeSolvers_iterations => Verbosity.Warn(), + :KrylovKit_verbosity => Verbosity.Warn() +) mutable struct LinearErrorControlVerbosity default_lu_fallback::Verbosity.Type @@ -26,58 +26,61 @@ mutable struct LinearErrorControlVerbosity default_lu_fallback = linear_defaults[:default_lu_fallback]) new(default_lu_fallback) end -end -function LinearErrorControlVerbosity(verbose::Verbosity.Type) - @match verbose begin - Verbosity.None() => LinearErrorControlVerbosity(fill( - Verbosity.None(), length(fieldnames(LinearErrorControlVerbosity)))...) + function LinearErrorControlVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => new(fill( + Verbosity.None(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Info() => LinearErrorControlVerbosity(fill( - Verbosity.Info(), length(fieldnames(LinearErrorControlVerbosity)))...) + Verbosity.Info() => new(fill( + Verbosity.Info(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Warn() => LinearErrorControlVerbosity(fill( - Verbosity.Warn(), length(fieldnames(LinearErrorControlVerbosity)))...) + Verbosity.Warn() => new(fill( + Verbosity.Warn(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Error() => LinearErrorControlVerbosity(fill( - Verbosity.Error(), length(fieldnames(LinearErrorControlVerbosity)))...) + Verbosity.Error() => new(fill( + Verbosity.Error(), length(fieldnames(LinearErrorControlVerbosity)))...) - Verbosity.Default() => LinearErrorControlVerbosity() + Verbosity.Default() => LinearErrorControlVerbosity() - Verbosity.Edge() => LinearErrorControlVerbosity() + Verbosity.Edge() => LinearErrorControlVerbosity() - _ => @error "Not a valid choice for verbosity." + _ => @error "Not a valid choice for verbosity." + end end end + mutable struct LinearPerformanceVerbosity no_right_preconditioning::Verbosity.Type + function LinearPerformanceVerbosity(; no_right_preconditioning = linear_defaults[:no_right_preconditioning]) new(no_right_preconditioning) end -end -function LinearPerformanceVerbosity(verbose::Verbosity.Type) - @match verbose begin - Verbosity.None() => LinearPerformanceVerbosity(fill( - Verbosity.None(), length(fieldnames(LinearPerformanceVerbosity)))...) + function LinearPerformanceVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => new(fill( + Verbosity.None(), length(fieldnames(LinearPerformanceVerbosity)))...) - Verbosity.Info() => LinearPerformanceVerbosity(fill( - Verbosity.Info(), length(fieldnames(LinearPerformanceVerbosity)))...) + Verbosity.Info() => new(fill( + Verbosity.Info(), length(fieldnames(LinearPerformanceVerbosity)))...) - Verbosity.Warn() => LinearPerformanceVerbosity(fill( - Verbosity.Warn(), length(fieldnames(LinearPerformanceVerbosity)))...) + Verbosity.Warn() => new(fill( + Verbosity.Warn(), length(fieldnames(LinearPerformanceVerbosity)))...) - Verbosity.Error() => LinearPerformanceVerbosity(fill( - Verbosity.Error(), length(fieldnames(LinearPerformanceVerbosity)))...) + Verbosity.Error() => new(fill( + Verbosity.Error(), length(fieldnames(LinearPerformanceVerbosity)))...) - Verbosity.Default() => LinearPerformanceVerbosity() + Verbosity.Default() => LinearPerformanceVerbosity() - Verbosity.Edge() => LinearPerformanceVerbosity() + Verbosity.Edge() => LinearPerformanceVerbosity() - _ => @error "Not a valid choice for verbosity." + _ => @error "Not a valid choice for verbosity." + end end + end mutable struct LinearNumericalVerbosity @@ -91,30 +94,32 @@ mutable struct LinearNumericalVerbosity KrylovKit_verbosity = linear_defaults[:KrylovKit_verbosity]) new(using_IterativeSolvers, IterativeSolvers_iterations, KrylovKit_verbosity) end -end -function LinearNumericalVerbosity(verbose::Verbosity.Type) - @match verbose begin - Verbosity.None() => LinearNumericalVerbosity(fill( - Verbosity.None(), length(fieldnames(LinearNumericalVerbosity)))...) + function LinearNumericalVerbosity(verbose::Verbosity.Type) + @match verbose begin + Verbosity.None() => new(fill( + Verbosity.None(), length(fieldnames(LinearNumericalVerbosity)))...) - Verbosity.Info() => LinearNumericalVerbosity(fill( - Verbosity.Info(), length(fieldnames(LinearNumericalVerbosity)))...) + Verbosity.Info() => new(fill( + Verbosity.Info(), length(fieldnames(LinearNumericalVerbosity)))...) - Verbosity.Warn() => LinearNumericalVerbosity(fill( - Verbosity.Warn(), length(fieldnames(LinearNumericalVerbosity)))...) + Verbosity.Warn() => new(fill( + Verbosity.Warn(), length(fieldnames(LinearNumericalVerbosity)))...) - Verbosity.Error() => LinearNumericalVerbosity(fill( - Verbosity.Error(), length(fieldnames(LinearNumericalVerbosity)))...) + Verbosity.Error() => new(fill( + Verbosity.Error(), length(fieldnames(LinearNumericalVerbosity)))...) - Verbosity.Default() => LinearNumericalVerbosity() + Verbosity.Default() => LinearNumericalVerbosity() - Verbosity.Edge() => LinearNumericalVerbosity() + Verbosity.Edge() => LinearNumericalVerbosity() - _ => @error "Not a valid choice for verbosity." + _ => @error "Not a valid choice for verbosity." + end end end + + struct LinearVerbosity{T} <: AbstractVerbositySpecifier{T} error_control::LinearErrorControlVerbosity performance::LinearPerformanceVerbosity From 3373aaf3072aaf097819b90dca9f88ee860246db Mon Sep 17 00:00:00 2001 From: jClugstor Date: Thu, 5 Jun 2025 11:48:03 -0400 Subject: [PATCH 6/8] update error message --- src/verbosity.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index d8dfae4d6..6a4646948 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -145,7 +145,7 @@ function LinearVerbosity(verbose::Verbosity.Type) LinearNumericalVerbosity(Verbosity.Info()) ) - _ => @error "Not a valid choice for verbosity." + _ => @error "Not a valid choice for LinearVerbosity. Available choices are `Default`, `None`, and `All`." end end From 233818cead204b7dce5eb78a697f412a7c9e4955 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Fri, 6 Jun 2025 11:56:20 -0400 Subject: [PATCH 7/8] add group to macro, add simple logger --- src/verbosity.jl | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index 6a4646948..c609080bc 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -219,7 +219,7 @@ function emit_message(message::String, verbose::V, level = message_level(verbose, option, group) if !isnothing(level) - Base.@logmsg level message _file=file _line=line _module=_module + Base.@logmsg level message _file=file _line=line _module=_module _group = group end end @@ -257,3 +257,39 @@ macro SciMLMessage(f_or_message, verb, option, group) $(esc(f_or_message)), $(esc(verb)), $option, $group, $file, $line, $_module)) end +function SciMLLogger(; info_repl = true, warn_repl = true, error_repl = true, + info_file = nothing, warn_file = nothing, error_file = nothing) + info_sink = isnothing(info_file) ? NullLogger() : FileLogger(info_file) + warn_sink = isnothing(warn_file) ? NullLogger() : FileLogger(warn_file) + error_sink = isnothing(error_file) ? NullLogger() : FileLogger(error_file) + + repl_filter = EarlyFilteredLogger(current_logger()) do log + if log.level == Logging.Info && info_repl + return true + end + + if log.level == Logging.Warn && warn_repl + return true + end + + if log.level == Logging.Error && error_repl + return true + end + + return false + end + + info_filter = EarlyFilteredLogger(info_sink) do log + log.level == Logging.Info + end + + warn_filter = EarlyFilteredLogger(warn_sink) do log + log.level == Logging.Warn + end + + error_filter = EarlyFilteredLogger(error_sink) do log + log.level == Logging.Error + end + + TeeLogger(repl_filter, info_filter, warn_filter, error_filter) +end From c2b2ad820fcbd426229c8c972e66febdad9f1084 Mon Sep 17 00:00:00 2001 From: jClugstor Date: Wed, 11 Jun 2025 13:16:44 -0400 Subject: [PATCH 8/8] add KrylovJL verbosity setting --- src/verbosity.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/verbosity.jl b/src/verbosity.jl index c609080bc..d1f05c049 100644 --- a/src/verbosity.jl +++ b/src/verbosity.jl @@ -17,7 +17,8 @@ linear_defaults = Dict( :using_iterative_solvers => Verbosity.Warn(), :using_IterativeSolvers => Verbosity.Warn(), :IterativeSolvers_iterations => Verbosity.Warn(), - :KrylovKit_verbosity => Verbosity.Warn() + :KrylovKit_verbosity => Verbosity.Warn(), + :KrylovJL_verbosity => Verbosity.None() ) mutable struct LinearErrorControlVerbosity default_lu_fallback::Verbosity.Type @@ -87,12 +88,14 @@ mutable struct LinearNumericalVerbosity using_IterativeSolvers::Verbosity.Type IterativeSolvers_iterations::Verbosity.Type KrylovKit_verbosity::Verbosity.Type + KrylovJL_verbosity::Verbosity.Type function LinearNumericalVerbosity(; using_IterativeSolvers = linear_defaults[:using_IterativeSolvers], IterativeSolvers_iterations = linear_defaults[:IterativeSolvers_iterations], - KrylovKit_verbosity = linear_defaults[:KrylovKit_verbosity]) - new(using_IterativeSolvers, IterativeSolvers_iterations, KrylovKit_verbosity) + KrylovKit_verbosity = linear_defaults[:KrylovKit_verbosity], + KrylovJL_verbosity = linear_defaults[:KrylovJL_verbosity]) + new(using_IterativeSolvers, IterativeSolvers_iterations, KrylovKit_verbosity, KrylovJL_verbosity) end function LinearNumericalVerbosity(verbose::Verbosity.Type)