Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ RecursiveFactorization = "0.2.26"
Reexport = "1.2.2"
SafeTestsets = "0.1"
SciMLBase = "2.128"
SciMLLogging = "1.3.1"
SciMLLogging = "1.7"
SciMLOperators = "1.13"
Setfield = "1.1.1"
SparseArrays = "1.10"
Expand Down
3 changes: 2 additions & 1 deletion src/LinearSolve.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ using SciMLBase: SciMLBase, LinearAliasSpecifier, AbstractSciMLOperator,
using SciMLOperators: SciMLOperators, AbstractSciMLOperator, IdentityOperator,
MatrixOperator,
has_ldiv!, issquare, has_concretization
using SciMLLogging: SciMLLogging, @SciMLMessage, verbosity_to_int, AbstractVerbositySpecifier, AbstractMessageLevel, AbstractVerbosityPreset,
using SciMLLogging: SciMLLogging, @SciMLMessage, verbosity_to_int,
AbstractVerbositySpecifier, AbstractMessageLevel, AbstractVerbosityPreset,
Silent, InfoLevel, WarnLevel, CustomLevel, None, Minimal, Standard, Detailed, All
using Setfield: @set, @set!
using DocStringExtensions: DocStringExtensions
Expand Down
356 changes: 136 additions & 220 deletions src/verbosity.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,127 @@
"""
SciMLLogging.@verbosity_specifier LinearVerbosity begin
toggles = (
:default_lu_fallback,
:no_right_preconditioning,
:using_IterativeSolvers,
:IterativeSolvers_iterations,
:KrylovKit_verbosity,
:KrylovJL_verbosity,
:HYPRE_verbosity,
:pardiso_verbosity,
:blas_errors,
:blas_invalid_args,
:blas_info,
:blas_success,
:condition_number,
:convergence_failure,
:solver_failure,
:max_iters
)

presets = (
None = (
default_lu_fallback = Silent(),
no_right_preconditioning = Silent(),
using_IterativeSolvers = Silent(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = Silent(),
KrylovJL_verbosity = Silent(),
HYPRE_verbosity = Silent(),
pardiso_verbosity = Silent(),
blas_errors = Silent(),
blas_invalid_args = Silent(),
blas_info = Silent(),
blas_success = Silent(),
condition_number = Silent(),
convergence_failure = Silent(),
solver_failure = Silent(),
max_iters = Silent()
),
Minimal = (
default_lu_fallback = Silent(),
no_right_preconditioning = Silent(),
using_IterativeSolvers = Silent(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = Silent(),
KrylovJL_verbosity = Silent(),
HYPRE_verbosity = Silent(),
pardiso_verbosity = Silent(),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = Silent(),
blas_success = Silent(),
condition_number = Silent(),
convergence_failure = Silent(),
solver_failure = Silent(),
max_iters = Silent()
),
Standard = (
default_lu_fallback = Silent(),
no_right_preconditioning = Silent(),
using_IterativeSolvers = Silent(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = CustomLevel(1),
KrylovJL_verbosity = Silent(),
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = Silent(),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = Silent(),
blas_success = Silent(),
condition_number = Silent(),
convergence_failure = WarnLevel(),
solver_failure = WarnLevel(),
max_iters = WarnLevel()
),
Detailed = (
default_lu_fallback = WarnLevel(),
no_right_preconditioning = InfoLevel(),
using_IterativeSolvers = InfoLevel(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = CustomLevel(2),
KrylovJL_verbosity = CustomLevel(1),
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = CustomLevel(1),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = InfoLevel(),
blas_success = InfoLevel(),
condition_number = Silent(),
convergence_failure = WarnLevel(),
solver_failure = WarnLevel(),
max_iters = WarnLevel()
),
All = (
default_lu_fallback = WarnLevel(),
no_right_preconditioning = InfoLevel(),
using_IterativeSolvers = InfoLevel(),
IterativeSolvers_iterations = InfoLevel(),
KrylovKit_verbosity = CustomLevel(3),
KrylovJL_verbosity = CustomLevel(1),
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = CustomLevel(1),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = InfoLevel(),
blas_success = InfoLevel(),
condition_number = InfoLevel(),
convergence_failure = WarnLevel(),
solver_failure = WarnLevel(),
max_iters = WarnLevel()
)
)

groups = (
error_control = (:default_lu_fallback, :blas_errors, :blas_invalid_args),
performance = (:no_right_preconditioning,),
numerical = (:using_IterativeSolvers, :IterativeSolvers_iterations,
:KrylovKit_verbosity, :KrylovJL_verbosity, :HYPRE_verbosity,
:pardiso_verbosity, :blas_info, :blas_success, :condition_number,
:convergence_failure, :solver_failure, :max_iters)
)
end

@doc """
LinearVerbosity <: AbstractVerbositySpecifier

Verbosity configuration for LinearSolve.jl solvers, providing fine-grained control over
Expand Down Expand Up @@ -68,225 +191,15 @@ verbose = LinearVerbosity(
blas_errors = SciMLLogging.ErrorLevel() # Override specific field
)
```
"""
LinearSolve.@concrete struct LinearVerbosity <:
AbstractVerbositySpecifier
# Error control
default_lu_fallback
# Performance
no_right_preconditioning
# Numerical
using_IterativeSolvers
IterativeSolvers_iterations
KrylovKit_verbosity
KrylovJL_verbosity
HYPRE_verbosity
pardiso_verbosity
blas_errors
blas_invalid_args
blas_info
blas_success
condition_number
convergence_failure
solver_failure
max_iters
end

function LinearVerbosity(;
error_control = nothing, performance = nothing, numerical = nothing, kwargs...)
# Fast path for default construction (type-stable)
if error_control === nothing && performance === nothing &&
numerical === nothing && isempty(kwargs)
return LinearVerbosity(
Silent(),
Silent(),
Silent(),
Silent(),
CustomLevel(1), # WARN_LEVEL in KrylovKit.jl
Silent(),
InfoLevel(),
Silent(),
WarnLevel(),
WarnLevel(),
Silent(),
Silent(),
Silent(),
WarnLevel(),
WarnLevel(),
WarnLevel())
end

# Validate group arguments
if error_control !== nothing && !(error_control isa AbstractMessageLevel)
throw(ArgumentError("error_control must be a SciMLLogging.AbstractMessageLevel, got $(typeof(error_control))"))
end
if performance !== nothing && !(performance isa AbstractMessageLevel)
throw(ArgumentError("performance must be a SciMLLogging.AbstractMessageLevel, got $(typeof(performance))"))
end
if numerical !== nothing && !(numerical isa AbstractMessageLevel)
throw(ArgumentError("numerical must be a SciMLLogging.AbstractMessageLevel, got $(typeof(numerical))"))
end

# Validate individual kwargs
for (key, value) in kwargs
if !(key in error_control_options || key in performance_options ||
key in numerical_options)
throw(ArgumentError("Unknown verbosity option: $key. Valid options are: $(tuple(error_control_options..., performance_options..., numerical_options...))"))
end
if !(value isa AbstractMessageLevel)
throw(ArgumentError("$key must be a SciMLLogging.AbstractMessageLevel, got $(typeof(value))"))
end
end

# Build arguments using NamedTuple for type stability
default_args = (
default_lu_fallback = Silent(),
no_right_preconditioning = Silent(),
using_IterativeSolvers = Silent(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = CustomLevel(1), # WARN_LEVEL in KrylovKit.jl
KrylovJL_verbosity = Silent(),
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = Silent(),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = Silent(),
blas_success = Silent(),
condition_number=Silent(),
convergence_failure=WarnLevel(),
solver_failure=WarnLevel(),
max_iters=WarnLevel()
)

# Apply group-level settings
final_args = if error_control !== nothing || performance !== nothing ||
numerical !== nothing
NamedTuple{keys(default_args)}(
_resolve_arg_value(
key, default_args[key], error_control, performance, numerical)
for key in keys(default_args)
)
else
default_args
end

# Apply individual overrides
if !isempty(kwargs)
final_args = merge(final_args, NamedTuple(kwargs))
end

LinearVerbosity(values(final_args)...)
end

# Constructor for verbosity presets following the hierarchical levels:
# None < Minimal < Standard < Detailed < All
# Each level includes all messages from levels below it plus additional ones
function LinearVerbosity(verbose::AbstractVerbosityPreset)
if verbose isa Minimal
# Minimal: Only fatal errors and critical warnings (BLAS errors/invalid args)
LinearVerbosity(
default_lu_fallback = Silent(),
no_right_preconditioning = Silent(),
using_IterativeSolvers = Silent(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = Silent(),
KrylovJL_verbosity = Silent(),
HYPRE_verbosity = Silent(),
pardiso_verbosity = Silent(),
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = Silent(),
blas_success = Silent(),
condition_number = Silent(),
convergence_failure = Silent(),
solver_failure = Silent(),
max_iters = Silent()
)
elseif verbose isa Standard
# Standard: Everything from Minimal + non-fatal warnings
LinearVerbosity()
elseif verbose isa Detailed
# Detailed: Everything from Standard + debugging/solver behavior
LinearVerbosity(
default_lu_fallback = WarnLevel(),
no_right_preconditioning = InfoLevel(),
using_IterativeSolvers = InfoLevel(),
IterativeSolvers_iterations = Silent(),
KrylovKit_verbosity = CustomLevel(2), # STARTSTOP_LEVEL in KrylovKit.jl
KrylovJL_verbosity = CustomLevel(1), # verbose = true in Krylov.jl
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = CustomLevel(1), # verbose = true in Pardiso.jl
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = InfoLevel(),
blas_success = InfoLevel(),
condition_number = Silent(),
convergence_failure = WarnLevel(),
solver_failure = WarnLevel(),
max_iters = WarnLevel()
)
elseif verbose isa All
# All: Maximum verbosity - every possible logging message at InfoLevel
LinearVerbosity(
default_lu_fallback = WarnLevel(),
no_right_preconditioning = InfoLevel(),
using_IterativeSolvers = InfoLevel(),
IterativeSolvers_iterations = InfoLevel(),
KrylovKit_verbosity = CustomLevel(3), # EACHITERATION_LEVEL in KrylovKit.jl
KrylovJL_verbosity = CustomLevel(1),
HYPRE_verbosity = InfoLevel(),
pardiso_verbosity = CustomLevel(1), # verbsoe = true in Pardiso.jl
blas_errors = WarnLevel(),
blas_invalid_args = WarnLevel(),
blas_info = InfoLevel(),
blas_success = InfoLevel(),
condition_number = InfoLevel(),
convergence_failure = WarnLevel(),
solver_failure = WarnLevel(),
max_iters = WarnLevel()
)
end
end
""" LinearVerbosity

@inline function LinearVerbosity(verbose::None)
LinearVerbosity(
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent(),
Silent())
end

# Helper function to resolve argument values based on group membership
@inline function _resolve_arg_value(key::Symbol, default_val, error_control, performance, numerical)
if key in error_control_options && error_control !== nothing
return error_control
elseif key in performance_options && performance !== nothing
return performance
elseif key in numerical_options && numerical !== nothing
return numerical
else
return default_val
end
end

# Group classifications
# Group classifications (for backwards compatibility)
const error_control_options = (:default_lu_fallback, :blas_errors, :blas_invalid_args)
const performance_options = (:no_right_preconditioning,)
const numerical_options = (:using_IterativeSolvers, :IterativeSolvers_iterations,
:KrylovKit_verbosity, :KrylovJL_verbosity, :HYPRE_verbosity, :pardiso_verbosity,
:blas_info, :blas_success, :condition_number, :convergence_failure, :solver_failure, :max_iters)
:KrylovKit_verbosity, :KrylovJL_verbosity, :HYPRE_verbosity,
:pardiso_verbosity, :blas_info, :blas_success, :condition_number,
:convergence_failure, :solver_failure, :max_iters)

function option_group(option::Symbol)
if option in error_control_options
Expand All @@ -303,12 +216,15 @@ end
# Get all options in a group
function group_options(verbosity::LinearVerbosity, group::Symbol)
if group === :error_control
return NamedTuple{error_control_options}(getproperty(verbosity, opt) for opt in error_control_options)
return NamedTuple{error_control_options}(getproperty(verbosity, opt)
for opt in error_control_options)
elseif group === :performance
return NamedTuple{performance_options}(getproperty(verbosity, opt) for opt in performance_options)
return NamedTuple{performance_options}(getproperty(verbosity, opt)
for opt in performance_options)
elseif group === :numerical
return NamedTuple{numerical_options}(getproperty(verbosity, opt) for opt in numerical_options)
return NamedTuple{numerical_options}(getproperty(verbosity, opt)
for opt in numerical_options)
else
error("Unknown group: $group")
end
end
end
Loading
Loading