Skip to content

Use verbosity system #622

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

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c3a0e1b
add imports for SciMLMessage
jClugstor Jun 4, 2025
5346fed
make verbose be a LinearVerbosity
jClugstor Jun 4, 2025
8655b97
use SciMLMessage for fallback to QR factorization
jClugstor Jun 4, 2025
782b160
use SciMLMessage
jClugstor Jun 4, 2025
3d7621e
replace verbose::Bool with verbose::LinearVerbosity
jClugstor Jun 4, 2025
1e8e3fe
make default verbose a LInearVerbosity
jClugstor Jun 10, 2025
5f23b7e
make KrylovKit verbosity work
jClugstor Jun 10, 2025
3805f0f
make sure krylov verbosity works
jClugstor Jun 11, 2025
c50837b
using more stuff
jClugstor Jun 11, 2025
4600d2c
add verbosity types
jClugstor Jul 7, 2025
e516c6a
add SciMLVerbosity as dep
jClugstor Jul 8, 2025
319e831
use SciMLVerbosity not SciMLBase
jClugstor Jul 8, 2025
fa33bd2
replace
jClugstor Jul 9, 2025
d63010f
imports
jClugstor Jul 14, 2025
a379e16
use LinearVerbosity for verbose
jClugstor Jul 20, 2025
151ef6c
allow for bool verbose for backwards compatibility
jClugstor Jul 20, 2025
4727bdd
add documentation
jClugstor Jul 20, 2025
d3e7c5a
fix imports and exports
jClugstor Jul 20, 2025
a54fe6b
add usings
jClugstor Jul 20, 2025
a43b84c
add compat, fix types
jClugstor Jul 20, 2025
a232f0c
make sure verbosity works for HYPRE
jClugstor Jul 21, 2025
6a0e285
add simple tests for verbosity
jClugstor Jul 21, 2025
b904183
fix verbosity tests
jClugstor Jul 21, 2025
a6236de
correct import
jClugstor Jul 21, 2025
5b77980
these don't really need to be mutable
jClugstor Jul 25, 2025
11c9229
if verbose isa verbosity type, construct a LinearVerbosity from it
jClugstor Jul 25, 2025
1ddc6e6
fix doc string
jClugstor Jul 25, 2025
591a8e8
they actually do need to be mutable
jClugstor Jul 25, 2025
9d7892c
update compat
jClugstor Jul 25, 2025
09e38a7
make use of new SciMLVerbosity stuff
jClugstor Jul 25, 2025
7453094
import SciMLMessage
jClugstor Jul 27, 2025
30f7cac
get rid of unused import
jClugstor Jul 27, 2025
f2cc43c
fix pardiso verbosity
jClugstor Jul 27, 2025
e2534ae
actually fix pardiso verbosity
jClugstor Jul 27, 2025
1053de8
format things related to verbosity
jClugstor Jul 28, 2025
07d9b17
DualCache init verbose should be LinearVerbosity as well
jClugstor Jul 28, 2025
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: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
SciMLOperators = "c0aeaf25-5076-4817-a8d5-81caf7dfa961"
SciMLVerbosity = "a05b3ec9-34a1-438a-b0a1-c0adb433119f"
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
Expand Down Expand Up @@ -109,6 +110,7 @@ Reexport = "1"
SafeTestsets = "0.1"
SciMLBase = "2.70"
SciMLOperators = "0.3.7, 0.4, 1"
SciMLVerbosity = "1.2.0"
Setfield = "1"
SparseArrays = "1.10"
Sparspak = "0.3.6"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/advanced/developing.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct MyLUFactorization{P} <: LinearSolve.SciMLLinearSolveAlgorithm end

function LinearSolve.init_cacheval(
alg::MyLUFactorization, A, b, u, Pl, Pr, maxiters::Int, abstol, reltol,
verbose::Bool, assump::LinearSolve.OperatorAssumptions)
verbose::LinearVerbosity, assump::LinearSolve.OperatorAssumptions)
lu!(convert(AbstractMatrix, A))
end

Expand Down
103 changes: 102 additions & 1 deletion docs/src/basics/common_solver_opts.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ The following are the options these algorithms take, along with their defaults.
`A` and `b` can be written to and changed by the solver algorithm. When fields are `nothing`
the default behavior is used, which is to default to `true` when the algorithm is known
not to modify the matrices, and false otherwise.
- `verbose`: Whether to print extra information. Defaults to `false`.
- `assumptions`: Sets the assumptions of the operator in order to effect the default
choice algorithm. See the [Operator Assumptions page for more details](@ref assumptions).

Expand All @@ -26,3 +25,105 @@ solve completely. Error controls only apply to iterative solvers.
- `maxiters`: The number of iterations allowed. Defaults to `length(prob.b)`
- `Pl,Pr`: The left and right preconditioners, respectively. For more information,
see [the Preconditioners page](@ref prec).

## Verbosity Controls

The verbosity system in LinearSolve.jl provides fine-grained control over the diagnostic messages, warnings, and errors that are displayed during the solution of linear systems.

The verbosity system is organized hierarchically into three main categories:

1. Error Control - Messages related to fallbacks and error handling
2. Performance - Messages related to performance considerations
3. Numerical - Messages related to numerical solvers and iterations

Each category can be configured independently, and individual settings can be adjusted to suit your needs.

### Verbosity Levels

The following verbosity levels are available:

#### Individual Settings

These settings are meant for individual settings within a category. These can also be used to set all of the individual settings in a group to the same value.

- Verbosity.None() - Suppress all messages
- Verbosity.Info() - Show message as log message at info level
- Verbosity.Warn() - Show warnings (default for most settings)
- Verbosity.Error() - Throw errors instead of warnings
- Verbosity.Level(n) - Show messages with a log level setting of n

#### Group Settings

These settings are meant for controlling a group of settings.

- Verbosity.Default() - Use the default settings
- Verbosity.All() - Show all possible messages

### Basic Usage

#### Global Verbosity Control

```julia
using LinearSolve

# Suppress all messages
verbose = LinearVerbosity(Verbosity.None())
prob = LinearProblem(A, b)
sol = solve(prob; verbose = verbose)

# Show all messages
verbose = LinearVerbosity(Verbosity.All())
sol = solve(prob; verbose = verbose)

# Use default settings
verbose = LinearVerbosity(Verbosity.Default())
sol = solve(prob; verbose = verbose)
```

#### Group Level Control

```julia
# Customize by category
verbose = LinearVerbosity(
error_control = Verbosity.Warn(), # Show warnings for error control related issues
performance = Verbosity.None(), # Suppress performance messages
numerical = Verbosity.Info() # Show all numerical related log messages at info level
)

sol = solve(prob; verbose = verbose)
```

#### Fine-grained Control

The constructor for `LinearVerbosity` allows you to set verbosity for each specific message toggle, giving you fine-grained control.
The verbosity settings for the toggles are automatically passed to the group objects.

```julia
# Set specific message types
verbose = LinearVerbosity(
default_lu_fallback = Verbosity.Info(), # Show info when LU fallback is used
KrylovJL_verbosity = Verbosity.Warn(), # Show warnings from KrylovJL
no_right_preconditioning = Verbosity.None(), # Suppress right preconditioning messages
KrylovKit_verbosity = Verbosity.Level(KrylovKit.WARN_LEVEL) # Set KrylovKit verbosity level using KrylovKit's own verbosity levels
)

sol = solve(prob; verbose = verbose)

```

#### Verbosity Levels

##### Error Control Settings

- default_lu_fallback: Controls messages when falling back to LU factorization (default: Warn)

##### Performance Settings

- no_right_preconditioning: Controls messages when right preconditioning is not used (default: Warn)

##### Numerical Settings

- using_IterativeSolvers: Controls messages when using the IterativeSolvers.jl package (default: Warn)
- IterativeSolvers_iterations: Controls messages about iteration counts from IterativeSolvers.jl (default: Warn)
- KrylovKit_verbosity: Controls messages from the KrylovKit.jl package (default: Warn)
- KrylovJL_verbosity: Controls verbosity of the KrylovJL.jl package (default: None)
6 changes: 3 additions & 3 deletions ext/LinearSolveBandedMatricesExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ for alg in (:SVDFactorization, :MKLLUFactorization, :DiagonalFactorization,
:AppleAccelerateLUFactorization, :CholeskyFactorization)
@eval begin
function init_cacheval(::$(alg), ::BandedMatrix, b, u, Pl, Pr, maxiters::Int,
abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions)
abstol, reltol, verbose::LinearVerbosity, assumptions::OperatorAssumptions)
return nothing
end
end
end

function init_cacheval(::LUFactorization, A::BandedMatrix{T}, b, u, Pl, Pr, maxiters::Int,
abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions) where {T}
abstol, reltol, verbose::LinearVerbosity, assumptions::OperatorAssumptions) where {T}
(T <: BigFloat) && return qr(similar(A, 0, 0))
return lu(similar(A, 0, 0))
end
Expand All @@ -61,7 +61,7 @@ for alg in (:SVDFactorization, :MKLLUFactorization, :DiagonalFactorization,
:AppleAccelerateLUFactorization, :QRFactorization, :LUFactorization)
@eval begin
function init_cacheval(::$(alg), ::Symmetric{<:Number, <:BandedMatrix}, b, u, Pl,
Pr, maxiters::Int, abstol, reltol, verbose::Bool,
Pr, maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
return nothing
end
Expand Down
11 changes: 7 additions & 4 deletions ext/LinearSolveCUDAExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,29 @@ function SciMLBase.solve!(cache::LinearSolve.LinearCache, alg::CudaOffloadFactor
end

function LinearSolve.init_cacheval(alg::CudaOffloadFactorization, A, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
qr(CUDA.CuArray(A))
end

function LinearSolve.init_cacheval(
::SparspakFactorization, A::CUDA.CUSPARSE.CuSparseMatrixCSR, b, u,
Pl, Pr, maxiters::Int, abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions)
Pl, Pr, maxiters::Int, abstol, reltol,
verbose::LinearVerbosity, assumptions::OperatorAssumptions)
nothing
end

function LinearSolve.init_cacheval(
::KLUFactorization, A::CUDA.CUSPARSE.CuSparseMatrixCSR, b, u,
Pl, Pr, maxiters::Int, abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions)
Pl, Pr, maxiters::Int, abstol, reltol,
verbose::LinearVerbosity, assumptions::OperatorAssumptions)
nothing
end

function LinearSolve.init_cacheval(
::UMFPACKFactorization, A::CUDA.CUSPARSE.CuSparseMatrixCSR, b, u,
Pl, Pr, maxiters::Int, abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions)
Pl, Pr, maxiters::Int, abstol, reltol,
verbose::LinearVerbosity, assumptions::OperatorAssumptions)
nothing
end

Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveFastAlmostBandedMatricesExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ for alg in (:SVDFactorization, :MKLLUFactorization, :DiagonalFactorization,
:AppleAccelerateLUFactorization, :CholeskyFactorization, :LUFactorization)
@eval begin
function init_cacheval(::$(alg), ::AlmostBandedMatrix, b, u, Pl, Pr, maxiters::Int,
abstol, reltol, verbose::Bool, assumptions::OperatorAssumptions)
abstol, reltol, verbose::LinearVerbosity, assumptions::OperatorAssumptions)
return nothing
end
end
Expand Down
10 changes: 5 additions & 5 deletions ext/LinearSolveFastLapackInterfaceExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct WorkspaceAndFactors{W, F}
end

function LinearSolve.init_cacheval(::FastLUFactorization, A, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
ws = LUWs(A)
return WorkspaceAndFactors(
Expand All @@ -36,26 +36,26 @@ end

function LinearSolve.init_cacheval(
alg::FastQRFactorization{NoPivot}, A::AbstractMatrix, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
ws = QRWYWs(A; blocksize = alg.blocksize)
return WorkspaceAndFactors(ws,
LinearSolve.ArrayInterface.qr_instance(convert(AbstractMatrix, A)))
end
function LinearSolve.init_cacheval(
::FastQRFactorization{ColumnNorm}, A::AbstractMatrix, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
ws = QRpWs(A)
return WorkspaceAndFactors(ws,
LinearSolve.ArrayInterface.qr_instance(convert(AbstractMatrix, A)))
end

function LinearSolve.init_cacheval(alg::FastQRFactorization, A, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
return init_cacheval(alg, convert(AbstractMatrix, A), b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
end

Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveForwardDiffExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function SciMLBase.init(
abstol = LinearSolve.default_tol(real(eltype(prob.b))),
reltol = LinearSolve.default_tol(real(eltype(prob.b))),
maxiters::Int = length(prob.b),
verbose::Bool = false,
verbose = LinearVerbosity(),
Pl = nothing,
Pr = nothing,
assumptions = OperatorAssumptions(issquare(prob.A)),
Expand Down
12 changes: 8 additions & 4 deletions ext/LinearSolveHYPREExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ using HYPRE.LibHYPRE: HYPRE_Complex
using HYPRE: HYPRE, HYPREMatrix, HYPRESolver, HYPREVector
using LinearSolve: HYPREAlgorithm, LinearCache, LinearProblem, LinearSolve,
OperatorAssumptions, default_tol, init_cacheval, __issquare,
__conditioning, LinearSolveAdjoint
__conditioning, LinearSolveAdjoint, LinearVerbosity
using SciMLBase: LinearProblem, LinearAliasSpecifier, SciMLBase
using SciMLVerbosity: @match, Verbosity, verbosity_to_int
using UnPack: @unpack
using Setfield: @set!

Expand All @@ -22,7 +23,7 @@ end

function LinearSolve.init_cacheval(alg::HYPREAlgorithm, A, b, u, Pl, Pr, maxiters::Int,
abstol, reltol,
verbose::Bool, assumptions::OperatorAssumptions)
verbose::LinearVerbosity, assumptions::OperatorAssumptions)
return HYPRECache(nothing, nothing, nothing, nothing, true, true, true)
end

Expand Down Expand Up @@ -64,7 +65,7 @@ function SciMLBase.init(prob::LinearProblem, alg::HYPREAlgorithm,
eltype(prob.A)),
# TODO: Implement length() for HYPREVector in HYPRE.jl?
maxiters::Int = prob.b isa HYPREVector ? 1000 : length(prob.b),
verbose::Bool = false,
verbose = LinearVerbosity(),
Pl = LinearAlgebra.I,
Pr = LinearAlgebra.I,
assumptions = OperatorAssumptions(),
Expand Down Expand Up @@ -159,10 +160,13 @@ function create_solver(alg::HYPREAlgorithm, cache::LinearCache)
solver = create_solver(alg.solver, comm)

# Construct solver options

verbose = verbosity_to_int(cache.verbose.numerical.HYPRE_verbosity)

solver_options = (;
AbsoluteTol = cache.abstol,
MaxIter = cache.maxiters,
PrintLevel = Int(cache.verbose),
PrintLevel = verbose,
Tol = cache.reltol)

# Preconditioner (uses Pl even though it might not be a *left* preconditioner just *a*
Expand Down
19 changes: 12 additions & 7 deletions ext/LinearSolveIterativeSolversExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module LinearSolveIterativeSolversExt
using LinearSolve, LinearAlgebra
using LinearSolve: LinearCache, DEFAULT_PRECS
import LinearSolve: IterativeSolversJL
using SciMLVerbosity: @SciMLMessage, Verbosity

using IterativeSolvers

Expand Down Expand Up @@ -47,7 +48,7 @@ LinearSolve.default_alias_b(::IterativeSolversJL, ::Any, ::Any) = true
function LinearSolve.init_cacheval(alg::IterativeSolversJL, A, b, u, Pl, Pr, maxiters::Int,
abstol,
reltol,
verbose::Bool, assumptions::OperatorAssumptions)
verbose::LinearVerbosity, assumptions::OperatorAssumptions)
restart = (alg.gmres_restart == 0) ? min(20, size(A, 1)) : alg.gmres_restart
s = :idrs_s in keys(alg.kwargs) ? alg.kwargs.idrs_s : 4 # shadow space

Expand All @@ -56,23 +57,26 @@ function LinearSolve.init_cacheval(alg::IterativeSolversJL, A, b, u, Pl, Pr, max

iterable = if alg.generate_iterator === IterativeSolvers.cg_iterator!
!LinearSolve._isidentity_struct(Pr) &&
@warn "$(alg.generate_iterator) doesn't support right preconditioning"
@SciMLMessage("$(alg.generate_iterator) doesn't support right preconditioning",
verbose, :no_right_preconditioning, :performance)
alg.generate_iterator(u, A, b, Pl;
kwargs...)
elseif alg.generate_iterator === IterativeSolvers.gmres_iterable!
alg.generate_iterator(u, A, b; Pl = Pl, Pr = Pr, restart = restart,
kwargs...)
elseif alg.generate_iterator === IterativeSolvers.idrs_iterable!
!!LinearSolve._isidentity_struct(Pr) &&
@warn "$(alg.generate_iterator) doesn't support right preconditioning"
@SciMLMessage("$(alg.generate_iterator) doesn't support right preconditioning",
verbose, :no_right_preconditioning, :performance)
history = IterativeSolvers.ConvergenceHistory(partial = true)
history[:abstol] = abstol
history[:reltol] = reltol
IterativeSolvers.idrs_iterable!(history, u, A, b, s, Pl, abstol, reltol, maxiters;
alg.kwargs...)
elseif alg.generate_iterator === IterativeSolvers.bicgstabl_iterator!
!!LinearSolve._isidentity_struct(Pr) &&
@warn "$(alg.generate_iterator) doesn't support right preconditioning"
@SciMLMessage("$(alg.generate_iterator) doesn't support right preconditioning",
verbose, :no_right_preconditioning, :performance)
alg.generate_iterator(u, A, b, alg.args...; Pl = Pl,
abstol = abstol, reltol = reltol,
max_mv_products = maxiters * 2,
Expand Down Expand Up @@ -103,14 +107,15 @@ function SciMLBase.solve!(cache::LinearCache, alg::IterativeSolversJL; kwargs...
end
purge_history!(cache.cacheval, cache.u, cache.b)

cache.verbose && println("Using IterativeSolvers.$(alg.generate_iterator)")
@SciMLMessage("Using IterativeSolvers.$(alg.generate_iterator)",
cache.verbose, :using_IterativeSolvers, :numerical)
i = 0
for iter in enumerate(cache.cacheval)
i += 1
cache.verbose && println("Iter: $(iter[1]), residual: $(iter[2])")
@SciMLMessage("Iter: $(iter[1]), residual: $(iter[2])",
cache.verbose, :IterativeSolvers_iterations, :numerical)
# TODO inject callbacks KSP into solve! cb!(cache.cacheval)
end
cache.verbose && println()

resid = cache.cacheval isa IterativeSolvers.IDRSIterable ? cache.cacheval.R :
cache.cacheval.residual
Expand Down
3 changes: 2 additions & 1 deletion ext/LinearSolveKrylovKitExt.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module LinearSolveKrylovKitExt

using LinearSolve, KrylovKit, LinearAlgebra
using SciMLVerbosity: @match, Verbosity, verbosity_to_int
using LinearSolve: LinearCache, DEFAULT_PRECS

function LinearSolve.KrylovKitJL(args...;
Expand All @@ -25,7 +26,7 @@ function SciMLBase.solve!(cache::LinearCache, alg::KrylovKitJL; kwargs...)
atol = float(cache.abstol)
rtol = float(cache.reltol)
maxiter = cache.maxiters
verbosity = cache.verbose ? 1 : 0
verbosity = verbosity_to_int(cache.verbose.numerical.KrylovKit_verbosity)
krylovdim = (alg.gmres_restart == 0) ? min(20, size(cache.A, 1)) : alg.gmres_restart

kwargs = (atol = atol, rtol = rtol, maxiter = maxiter, verbosity = verbosity,
Expand Down
2 changes: 1 addition & 1 deletion ext/LinearSolveMetalExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ default_alias_A(::MetalLUFactorization, ::Any, ::Any) = false
default_alias_b(::MetalLUFactorization, ::Any, ::Any) = false

function LinearSolve.init_cacheval(alg::MetalLUFactorization, A, b, u, Pl, Pr,
maxiters::Int, abstol, reltol, verbose::Bool,
maxiters::Int, abstol, reltol, verbose::LinearVerbosity,
assumptions::OperatorAssumptions)
ArrayInterface.lu_instance(convert(AbstractMatrix, A))
end
Expand Down
Loading
Loading