Skip to content

Commit fb0fece

Browse files
committed
Add a new file krylov_show.jl
1 parent 720850c commit fb0fece

File tree

6 files changed

+306
-305
lines changed

6 files changed

+306
-305
lines changed

src/Krylov.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ include("block_krylov_utils.jl")
1212
include("block_krylov_processes.jl")
1313
include("block_krylov_workspaces.jl")
1414

15+
include("krylov_show.jl")
16+
1517
include("block_minres.jl")
1618
include("block_gmres.jl")
1719

src/block_krylov_workspaces.jl

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -127,100 +127,3 @@ function BlockGmresWorkspace(A, B; memory::Integer = 5)
127127
SV = matrix_to_vector(SM)
128128
BlockGmresWorkspace(m, n, p, SV, SM; memory)
129129
end
130-
131-
for (KS, fun, nsol, nA, nAt, warm_start) in [
132-
(:BlockMinresWorkspace, :block_minres!, 1, 1, 0, true)
133-
(:BlockGmresWorkspace , :block_gmres! , 1, 1, 0, true)
134-
]
135-
@eval begin
136-
krylov_elapsed_time(workspace :: $KS) = workspace.stats.timer
137-
size(workspace :: $KS) = workspace.m, workspace.n
138-
nrhs(workspace :: $KS) = workspace.p
139-
statistics(workspace :: $KS) = workspace.stats
140-
niterations(workspace :: $KS) = workspace.stats.niter
141-
Aprod(workspace :: $KS) = $nA * workspace.stats.niter
142-
Atprod(workspace :: $KS) = $nAt * workspace.stats.niter
143-
nsolution(workspace :: $KS) = $nsol
144-
if $nsol == 1
145-
solution(workspace :: $KS) = workspace.X
146-
solution(workspace :: $KS, p :: Integer) = (p == 1) ? solution(workspace) : error("solution(workspace) has only one output.")
147-
results(workspace :: $KS) = (workspace.X, workspace.stats)
148-
end
149-
issolved(workspace :: $KS) = workspace.stats.solved
150-
if $warm_start
151-
function warm_start!(workspace :: $KS, X0)
152-
n2, p2 = size(X0)
153-
SM = typeof(workspace.X)
154-
(workspace.n == n2 && workspace.p == p2) || error("X0 should have size ($n, $p)")
155-
allocate_if(true, workspace, :ΔX, SM, workspace.n, workspace.p)
156-
copyto!(workspace.ΔX, X0)
157-
workspace.warm_start = true
158-
return workspace
159-
end
160-
end
161-
end
162-
end
163-
164-
function ksizeof(attribute)
165-
if isa(attribute, Vector{<:AbstractVector}) && !isempty(attribute)
166-
# A vector of vectors is a vector of pointers in Julia.
167-
# All vectors inside a vector have the same size in Krylov.jl
168-
size_attribute = sizeof(attribute) + length(attribute) * ksizeof(attribute[1])
169-
else
170-
size_attribute = sizeof(attribute)
171-
end
172-
return size_attribute
173-
end
174-
175-
function sizeof(stats_workspace :: Union{KrylovStats, KrylovWorkspace, BlockKrylovWorkspace})
176-
type = typeof(stats_workspace)
177-
nfields = fieldcount(type)
178-
storage = 0
179-
for i = 1:nfields
180-
field_i = getfield(stats_workspace, i)
181-
size_i = ksizeof(field_i)
182-
storage += size_i
183-
end
184-
return storage
185-
end
186-
187-
"""
188-
show(io, workspace; show_stats=true)
189-
190-
Statistics of `workspace` are displayed if `show_stats` is set to true.
191-
"""
192-
function show(io :: IO, workspace :: Union{KrylovWorkspace{T,FC,S}, BlockKrylovWorkspace{T,FC,S}}; show_stats :: Bool=true) where {T <: AbstractFloat, FC <: FloatOrComplex{T}, S <: AbstractVector{FC}}
193-
type_workspace = typeof(workspace)
194-
name_workspace = string(type_workspace.name.name)
195-
name_stats = string(typeof(workspace.stats).name.name)
196-
nbytes = sizeof(workspace)
197-
storage = format_bytes(nbytes)
198-
architecture = S <: Vector ? "CPU" : "GPU"
199-
l1 = max(length(name_workspace), length(string(FC)) + 11) # length("Precision: ") = 11
200-
nchar = type_workspace <: Union{CgLanczosShiftWorkspace, FomWorkspace, DiomWorkspace, DqgmresWorkspace, GmresWorkspace, FgmresWorkspace, GpmrWorkspace, BlockGmresWorkspace} ? 8 : 0 # length("Vector{}") = 8
201-
l2 = max(ndigits(workspace.m) + 7, length(architecture) + 14, length(string(S)) + nchar) # length("nrows: ") = 7 and length("Architecture: ") = 14
202-
l2 = max(l2, length(name_stats) + 2 + length(string(T))) # length("{}") = 2
203-
l3 = max(ndigits(workspace.n) + 7, length(storage) + 9) # length("Storage: ") = 9 and length("cols: ") = 7
204-
format = Printf.Format("│%$(l1)s│%$(l2)s│%$(l3)s│\n")
205-
format2 = Printf.Format("│%$(l1+1)s│%$(l2)s│%$(l3)s│\n")
206-
@printf(io, "┌%s┬%s┬%s┐\n", ""^l1, ""^l2, ""^l3)
207-
Printf.format(io, format, "$(name_workspace)", "nrows: $(workspace.m)", "ncols: $(workspace.n)")
208-
@printf(io, "├%s┼%s┼%s┤\n", ""^l1, ""^l2, ""^l3)
209-
Printf.format(io, format, "Precision: $FC", "Architecture: $architecture","Storage: $storage")
210-
@printf(io, "├%s┼%s┼%s┤\n", ""^l1, ""^l2, ""^l3)
211-
Printf.format(io, format, "Attribute", "Type", "Size")
212-
@printf(io, "├%s┼%s┼%s┤\n", ""^l1, ""^l2, ""^l3)
213-
for i=1:fieldcount(type_workspace)
214-
name_i = fieldname(type_workspace, i)
215-
type_i = fieldtype(type_workspace, i)
216-
field_i = getfield(workspace, name_i)
217-
size_i = ksizeof(field_i)
218-
(size_i 0) && Printf.format(io, format, string(name_i), type_i, format_bytes(size_i))
219-
end
220-
@printf(io, "└%s┴%s┴%s┘\n",""^l1,""^l2,""^l3)
221-
if show_stats
222-
@printf(io, "\n")
223-
show(io, workspace.stats)
224-
end
225-
return nothing
226-
end

src/interface.jl

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626

2727
export krylov_workspace, krylov_solve, krylov_solve!
2828

29+
export solution, nsolution, statistics, issolved, issolved_primal, issolved_dual
30+
export niterations, Aprod, Atprod, Bprod, warm_start!, krylov_elapsed_time
31+
32+
import Base.size
33+
2934
"""
3035
workspace = krylov_workspace(Val(method), args...; kwargs...)
3136
@@ -50,6 +55,79 @@ The argument `workspace` must be a subtype of [`KrylovWorkspace`](@ref) or [`Blo
5055
"""
5156
function krylov_solve! end
5257

58+
"""
59+
solution(workspace)
60+
61+
Return the solution(s) stored in the `workspace`.
62+
Optionally you can specify which solution you want to recover,
63+
`solution(workspace, 1)` returns `x` and `solution(workspace, 2)` returns `y`.
64+
"""
65+
function solution end
66+
67+
"""
68+
nsolution(workspace)
69+
70+
Return the number of outputs of `solution(workspace)`.
71+
"""
72+
function nsolution end
73+
74+
"""
75+
statistics(workspace)
76+
77+
Return the statistics stored in the `workspace`.
78+
"""
79+
function statistics end
80+
81+
"""
82+
issolved(workspace)
83+
84+
Return a boolean that determines whether the Krylov method associated to `workspace` succeeded.
85+
"""
86+
function issolved end
87+
88+
"""
89+
niterations(workspace)
90+
91+
Return the number of iterations performed by the Krylov method associated to `workspace`.
92+
"""
93+
function niterations end
94+
95+
"""
96+
Aprod(workspace)
97+
98+
Return the number of operator-vector products with `A` performed by the Krylov method associated to `workspace`.
99+
"""
100+
function Aprod end
101+
102+
"""
103+
Atprod(workspace)
104+
105+
Return the number of operator-vector products with `A'` performed by the Krylov method associated to `workspace`.
106+
"""
107+
function Atprod end
108+
109+
"""
110+
krylov_elapsed_time(workspace)
111+
112+
Return the time elapsed (in seconds) during the last call to the Krylov solver associated with `workspace`.
113+
"""
114+
function krylov_elapsed_time end
115+
116+
"""
117+
results(workspace)
118+
119+
Return a tuple containing the solution(s) and the statistics associated with the `workspace`.
120+
Allows retrieving the output arguments of an out-of-place method from the in-place method.
121+
122+
For example, instead of `x, stats = cg(A, b)`, you can use:
123+
```julia
124+
workspace = CgWorkspace(A, b)
125+
cg!(workspace, A, b)
126+
x, stats = results(workspace)
127+
```
128+
"""
129+
function results end
130+
53131
# Krylov methods
54132
for (workspace, krylov, args, def_args, optargs, def_optargs, kwargs, def_kwargs) in [
55133
(:LsmrWorkspace , :lsmr , args_lsmr , def_args_lsmr , () , () , kwargs_lsmr , def_kwargs_lsmr )
@@ -333,3 +411,129 @@ for (workspace, krylov, args, def_args, optargs, def_optargs, kwargs, def_kwargs
333411
end
334412
end
335413
end
414+
415+
for (KS, fun, nsol, nA, nAt, warm_start) in [
416+
(:CarWorkspace , :car! , 1, 1, 0, true )
417+
(:LsmrWorkspace , :lsmr! , 1, 1, 1, false)
418+
(:CgsWorkspace , :cgs! , 1, 2, 0, true )
419+
(:UsymlqWorkspace , :usymlq! , 1, 1, 1, true )
420+
(:LnlqWorkspace , :lnlq! , 2, 1, 1, false)
421+
(:BicgstabWorkspace , :bicgstab! , 1, 2, 0, true )
422+
(:CrlsWorkspace , :crls! , 1, 1, 1, false)
423+
(:LsqrWorkspace , :lsqr! , 1, 1, 1, false)
424+
(:MinresWorkspace , :minres! , 1, 1, 0, true )
425+
(:MinaresWorkspace , :minares! , 1, 1, 0, true )
426+
(:CgneWorkspace , :cgne! , 1, 1, 1, false)
427+
(:DqgmresWorkspace , :dqgmres! , 1, 1, 0, true )
428+
(:SymmlqWorkspace , :symmlq! , 1, 1, 0, true )
429+
(:TrimrWorkspace , :trimr! , 2, 1, 1, true )
430+
(:UsymqrWorkspace , :usymqr! , 1, 1, 1, true )
431+
(:BilqrWorkspace , :bilqr! , 2, 1, 1, true )
432+
(:CrWorkspace , :cr! , 1, 1, 0, true )
433+
(:CraigmrWorkspace , :craigmr! , 2, 1, 1, false)
434+
(:TricgWorkspace , :tricg! , 2, 1, 1, true )
435+
(:CraigWorkspace , :craig! , 2, 1, 1, false)
436+
(:DiomWorkspace , :diom! , 1, 1, 0, true )
437+
(:LslqWorkspace , :lslq! , 1, 1, 1, false)
438+
(:TrilqrWorkspace , :trilqr! , 2, 1, 1, true )
439+
(:CrmrWorkspace , :crmr! , 1, 1, 1, false)
440+
(:CgWorkspace , :cg! , 1, 1, 0, true )
441+
(:CglsWorkspace , :cgls! , 1, 1, 1, false)
442+
(:CgLanczosWorkspace, :cg_lanczos!, 1, 1, 0, true )
443+
(:BilqWorkspace , :bilq! , 1, 1, 1, true )
444+
(:MinresQlpWorkspace, :minres_qlp!, 1, 1, 0, true )
445+
(:QmrWorkspace , :qmr! , 1, 1, 1, true )
446+
(:GmresWorkspace , :gmres! , 1, 1, 0, true )
447+
(:FgmresWorkspace , :fgmres! , 1, 1, 0, true )
448+
(:FomWorkspace , :fom! , 1, 1, 0, true )
449+
(:GpmrWorkspace , :gpmr! , 2, 1, 0, true )
450+
(:CgLanczosShiftWorkspace , :cg_lanczos_shift! , 1, 1, 0, false)
451+
(:CglsLanczosShiftWorkspace, :cgls_lanczos_shift!, 1, 1, 1, false)
452+
]
453+
@eval begin
454+
krylov_elapsed_time(workspace :: $KS) = workspace.stats.timer
455+
size(workspace :: $KS) = workspace.m, workspace.n
456+
statistics(workspace :: $KS) = workspace.stats
457+
niterations(workspace :: $KS) = workspace.stats.niter
458+
Aprod(workspace :: $KS) = $nA * workspace.stats.niter
459+
Atprod(workspace :: $KS) = $nAt * workspace.stats.niter
460+
if $KS == GpmrWorkspace
461+
Bprod(workspace :: $KS) = workspace.stats.niter
462+
end
463+
nsolution(workspace :: $KS) = $nsol
464+
if $nsol == 1
465+
solution(workspace :: $KS) = workspace.x
466+
solution(workspace :: $KS, p :: Integer) = (p == 1) ? solution(workspace) : error("solution(workspace) has only one output.")
467+
results(workspace :: $KS) = (workspace.x, workspace.stats)
468+
end
469+
if $nsol == 2
470+
solution(workspace :: $KS) = (workspace.x, workspace.y)
471+
solution(workspace :: $KS, p :: Integer) = (1 p 2) ? solution(workspace)[p] : error("solution(workspace) has only two outputs.")
472+
results(workspace :: $KS) = (workspace.x, workspace.y, workspace.stats)
473+
end
474+
if $KS (BilqrWorkspace, TrilqrWorkspace)
475+
issolved_primal(workspace :: $KS) = workspace.stats.solved_primal
476+
issolved_dual(workspace :: $KS) = workspace.stats.solved_dual
477+
issolved(workspace :: $KS) = issolved_primal(workspace) && issolved_dual(workspace)
478+
else
479+
issolved(workspace :: $KS) = workspace.stats.solved
480+
end
481+
if $warm_start
482+
if $KS in (BilqrWorkspace, TrilqrWorkspace, TricgWorkspace, TrimrWorkspace, GpmrWorkspace)
483+
function warm_start!(workspace :: $KS, x0, y0)
484+
length(x0) == workspace.n || error("x0 should have size $n")
485+
length(y0) == workspace.m || error("y0 should have size $m")
486+
S = typeof(workspace.x)
487+
allocate_if(true, workspace, :Δx, S, workspace.x) # The length of Δx is n
488+
allocate_if(true, workspace, :Δy, S, workspace.y) # The length of Δy is m
489+
kcopy!(workspace.n, workspace.Δx, x0)
490+
kcopy!(workspace.m, workspace.Δy, y0)
491+
workspace.warm_start = true
492+
return workspace
493+
end
494+
else
495+
function warm_start!(workspace :: $KS, x0)
496+
S = typeof(workspace.x)
497+
length(x0) == workspace.n || error("x0 should have size $n")
498+
allocate_if(true, workspace, :Δx, S, workspace.x) # The length of Δx is n
499+
kcopy!(workspace.n, workspace.Δx, x0)
500+
workspace.warm_start = true
501+
return workspace
502+
end
503+
end
504+
end
505+
end
506+
end
507+
508+
for (KS, fun, nsol, nA, nAt, warm_start) in [
509+
(:BlockMinresWorkspace, :block_minres!, 1, 1, 0, true)
510+
(:BlockGmresWorkspace , :block_gmres! , 1, 1, 0, true)
511+
]
512+
@eval begin
513+
krylov_elapsed_time(workspace :: $KS) = workspace.stats.timer
514+
size(workspace :: $KS) = workspace.m, workspace.n
515+
nrhs(workspace :: $KS) = workspace.p
516+
statistics(workspace :: $KS) = workspace.stats
517+
niterations(workspace :: $KS) = workspace.stats.niter
518+
Aprod(workspace :: $KS) = $nA * workspace.stats.niter
519+
Atprod(workspace :: $KS) = $nAt * workspace.stats.niter
520+
nsolution(workspace :: $KS) = $nsol
521+
if $nsol == 1
522+
solution(workspace :: $KS) = workspace.X
523+
solution(workspace :: $KS, p :: Integer) = (p == 1) ? solution(workspace) : error("solution(workspace) has only one output.")
524+
results(workspace :: $KS) = (workspace.X, workspace.stats)
525+
end
526+
issolved(workspace :: $KS) = workspace.stats.solved
527+
if $warm_start
528+
function warm_start!(workspace :: $KS, X0)
529+
n2, p2 = size(X0)
530+
SM = typeof(workspace.X)
531+
(workspace.n == n2 && workspace.p == p2) || error("X0 should have size ($n, $p)")
532+
allocate_if(true, workspace, :ΔX, SM, workspace.n, workspace.p)
533+
copyto!(workspace.ΔX, X0)
534+
workspace.warm_start = true
535+
return workspace
536+
end
537+
end
538+
end
539+
end

0 commit comments

Comments
 (0)