@@ -33,22 +33,24 @@ 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`.
3940
4041By default, TriCG solves Hermitian and quasi-definite linear systems with `τ = 1` and `ν = -1`.
42+ TriCG could breakdown if `τ = 0` or `ν = 0`. It's recommended to use TriMR in these cases.
4143
4244TriCG is based on the preconditioned orthogonal tridiagonalization process
4345and its relation with the preconditioned block-Lanczos process.
4446
4547The matrix
4648
47- [ M 0 ]
48- [ 0 N ]
49+ [ E⁻¹ 0 ]
50+ [ 0 F⁻¹ ]
4951
5052indicates the weighted norm in which residuals are measured, here denoted `‖·‖`.
51- It's the Euclidean norm when `M` and `N` are identity operators.
53+ When `M` and `N` are identity operators and `τ` and `ν` are ±1, it's the Euclidean norm .
5254
5355TriCG stops when `itmax` iterations are reached or when `‖rₖ‖ ≤ atol + ‖r₀‖ * rtol`.
5456`atol` is an absolute tolerance and `rtol` is a relative tolerance.
@@ -70,7 +72,9 @@ For an in-place variant that reuses memory across solves, see [`tricg!`](@ref).
7072* `x0`: a vector of length `m` that represents an initial guess of the solution `x`;
7173* `y0`: a vector of length `n` that represents an initial guess of the solution `y`.
7274
73- Warm-starting is supported only when `M` and `N` are either `I` or the corresponding coefficient (`τ` or `ν`) is zero.
75+ Warm-starting is supported only when:
76+ * ldiv = true; or
77+ * `M` and `N` are either `I` or the corresponding coefficient (`τ` or `ν`) is zero.
7478
7579#### Keyword arguments
7680
@@ -178,8 +182,10 @@ kwargs_tricg = (:M, :N, :ldiv, :spd, :snd, :flip, :τ, :ν, :atol, :rtol, :itmax
178182 snd && (τ = - one (T) ; ν = - one (T))
179183
180184 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." )
185+ if ! ldiv
186+ warm_start && (τ ≠ 0 ) && ! MisI && error (" Warm-start with preconditioners is not supported." )
187+ warm_start && (ν ≠ 0 ) && ! NisI && error (" Warm-start with preconditioners is not supported." )
188+ end
183189
184190 # Compute the adjoint of A
185191 Aᴴ = A'
@@ -212,15 +218,27 @@ kwargs_tricg = (:M, :N, :ldiv, :spd, :snd, :flip, :τ, :ν, :atol, :rtol, :itmax
212218 kfill! (M⁻¹vₖ₋₁, zero (FC)) # v₀ = 0
213219 kfill! (N⁻¹uₖ₋₁, zero (FC)) # u₀ = 0
214220
215- # [ τI A ] [ xₖ ] = [ b - τΔx - AΔy ] = [ b₀ ]
216- # [ Aᴴ νI ] [ yₖ ] [ c - AᴴΔx - νΔy ] [ c₀ ]
217221 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₀)
222+ if ldiv
223+ # [ τM A ] [ xₖ ] = [ b - τMΔx - AΔy ] = [ b₀ ]
224+ # [ Aᴴ νN ] [ yₖ ] [ c - AᴴΔx - νNΔy ] [ c₀ ]
225+ kmul! (b₀, A, Δy)
226+ (τ ≠ 0 ) && mul! (b₀, M, Δx, τ, one (FC)) # b₀ ← τMΔx + AΔy
227+ kaxpby! (m, one (FC), b, - one (FC), b₀)
228+ kmul! (c₀, Aᴴ, Δx)
229+ (ν ≠ 0 ) && mul! (c₀, N, Δy, ν, one (FC)) # c₀ ← νNΔy + AᴴΔx
230+ kaxpby! (n, one (FC), c, - one (FC), c₀)
231+ else
232+ # Only supported for M = I or τ = 0, and N = I or ν = 0
233+ # [ τI A ] [ xₖ ] = [ b - τΔx - AΔy ] = [ b₀ ]
234+ # [ Aᴴ νI ] [ yₖ ] [ c - AᴴΔx - νΔy ] [ c₀ ]
235+ kmul! (b₀, A, Δy)
236+ (τ ≠ 0 ) && kaxpy! (m, τ, Δx, b₀)
237+ kaxpby! (m, one (FC), b, - one (FC), b₀)
238+ kmul! (c₀, Aᴴ, Δx)
239+ (ν ≠ 0 ) && kaxpy! (n, ν, Δy, c₀)
240+ kaxpby! (n, one (FC), c, - one (FC), c₀)
241+ end
224242 end
225243
226244 # β₁Ev₁ = b ↔ β₁v₁ = Mb
0 commit comments