@@ -33,22 +33,25 @@ Given a matrix `A` of dimension m × n, TriCG solves the Hermitian linear system
3333 [ τE A ] [ x ] = [ b ]
3434 [ Aᴴ νF ] [ y ] [ c ],
3535
36- of size (n+m) × (n+m) where `τ` and `ν` are real numbers, `E` = `M⁻¹` ≻ 0 and `F` = `N⁻¹` ≻ 0.
37- TriCG could breakdown if `τ = 0` or `ν = 0`.
38- It's recommended to use TriMR in these cases.
36+ of size (n+m) × (n+m) where `τ` and `ν` are real numbers, `E` ≻ 0 and `F` ≻ 0.
37+ `E` and `F` are related to the preconditioners `M` and `N` as `E = M⁻¹` and `F =
38+ N⁻¹` when `ldiv = false` (the default), and `E = M` and `F = N` when `ldiv =
39+ true`. `tricg` is applicable when `E` and `F` are represented through their
40+ inverses or have an efficient `ldiv!` implementation.
3941
4042By default, TriCG solves Hermitian and quasi-definite linear systems with `τ = 1` and `ν = -1`.
43+ TriCG could breakdown if `τ = 0` or `ν = 0`. It's recommended to use TriMR in these cases.
4144
4245TriCG is based on the preconditioned orthogonal tridiagonalization process
4346and its relation with the preconditioned block-Lanczos process.
4447
4548The matrix
4649
47- [ M 0 ]
48- [ 0 N ]
50+ [ E⁻¹ 0 ]
51+ [ 0 F⁻¹ ]
4952
5053indicates the weighted norm in which residuals are measured, here denoted `‖·‖`.
51- It's the Euclidean norm when `M` and `N` are identity operators.
54+ When `M` and `N` are identity operators and `τ` and `ν` are ±1, it's the Euclidean norm .
5255
5356TriCG stops when `itmax` iterations are reached or when `‖rₖ‖ ≤ atol + ‖r₀‖ * rtol`.
5457`atol` is an absolute tolerance and `rtol` is a relative tolerance.
@@ -70,7 +73,9 @@ For an in-place variant that reuses memory across solves, see [`tricg!`](@ref).
7073* `x0`: a vector of length `m` that represents an initial guess of the solution `x`;
7174* `y0`: a vector of length `n` that represents an initial guess of the solution `y`.
7275
73- Warm-starting is supported only when `M` and `N` are either `I` or the corresponding coefficient (`τ` or `ν`) is zero.
76+ Warm-starting is supported only when:
77+ * ldiv = true; or
78+ * `M` and `N` are either `I` or the corresponding coefficient (`τ` or `ν`) is zero.
7479
7580#### Keyword arguments
7681
@@ -178,8 +183,10 @@ kwargs_tricg = (:M, :N, :ldiv, :spd, :snd, :flip, :τ, :ν, :atol, :rtol, :itmax
178183 snd && (τ = - one (T) ; ν = - one (T))
179184
180185 warm_start = workspace. warm_start
181- warm_start && (τ ≠ 0 ) && ! MisI && error (" Warm-start with preconditioners is not supported." )
182- warm_start && (ν ≠ 0 ) && ! NisI && error (" Warm-start with preconditioners is not supported." )
186+ if ! ldiv
187+ warm_start && (τ ≠ 0 ) && ! MisI && error (" Warm-start with preconditioners is not supported." )
188+ warm_start && (ν ≠ 0 ) && ! NisI && error (" Warm-start with preconditioners is not supported." )
189+ end
183190
184191 # Compute the adjoint of A
185192 Aᴴ = A'
@@ -212,15 +219,27 @@ kwargs_tricg = (:M, :N, :ldiv, :spd, :snd, :flip, :τ, :ν, :atol, :rtol, :itmax
212219 kfill! (M⁻¹vₖ₋₁, zero (FC)) # v₀ = 0
213220 kfill! (N⁻¹uₖ₋₁, zero (FC)) # u₀ = 0
214221
215- # [ τI A ] [ xₖ ] = [ b - τΔx - AΔy ] = [ b₀ ]
216- # [ Aᴴ νI ] [ yₖ ] [ c - AᴴΔx - νΔy ] [ c₀ ]
217222 if warm_start
218- kmul! (b₀, A, Δy)
219- (τ ≠ 0 ) && kaxpy! (m, τ, Δx, b₀)
220- kaxpby! (m, one (FC), b, - one (FC), b₀)
221- kmul! (c₀, Aᴴ, Δx)
222- (ν ≠ 0 ) && kaxpy! (n, ν, Δy, c₀)
223- kaxpby! (n, one (FC), c, - one (FC), c₀)
223+ if ldiv
224+ # [ τM A ] [ xₖ ] = [ b - τMΔx - AΔy ] = [ b₀ ]
225+ # [ Aᴴ νN ] [ yₖ ] [ c - AᴴΔx - νNΔy ] [ c₀ ]
226+ kmul! (b₀, A, Δy)
227+ (τ ≠ 0 ) && mul! (b₀, M, Δx, τ, one (FC)) # b₀ ← τMΔx + AΔy
228+ kaxpby! (m, one (FC), b, - one (FC), b₀)
229+ kmul! (c₀, Aᴴ, Δx)
230+ (ν ≠ 0 ) && mul! (c₀, N, Δy, ν, one (FC)) # c₀ ← νNΔy + AᴴΔx
231+ kaxpby! (n, one (FC), c, - one (FC), c₀)
232+ else
233+ # Only supported for M = I or τ = 0, and N = I or ν = 0
234+ # [ τI A ] [ xₖ ] = [ b - τΔx - AΔy ] = [ b₀ ]
235+ # [ Aᴴ νI ] [ yₖ ] [ c - AᴴΔx - νΔy ] [ c₀ ]
236+ kmul! (b₀, A, Δy)
237+ (τ ≠ 0 ) && kaxpy! (m, τ, Δx, b₀)
238+ kaxpby! (m, one (FC), b, - one (FC), b₀)
239+ kmul! (c₀, Aᴴ, Δx)
240+ (ν ≠ 0 ) && kaxpy! (n, ν, Δy, c₀)
241+ kaxpby! (n, one (FC), c, - one (FC), c₀)
242+ end
224243 end
225244
226245 # β₁Ev₁ = b ↔ β₁v₁ = Mb
0 commit comments