-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update examples to use new implicit solver interface
- Loading branch information
1 parent
557e755
commit e3d3f8e
Showing
19 changed files
with
843 additions
and
884 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import LinearAlgebra: ldiv! | ||
using ClimaCore: Spaces, Fields, Operators | ||
using ClimaCore.Utilities: half | ||
using ClimaCore.MatrixFields | ||
using ClimaCore.MatrixFields: @name | ||
|
||
struct ImplicitEquationJacobian{TJ, RJ, F, T1, T2} | ||
# nonzero blocks of the implicit tendency's Jacobian | ||
∂Yₜ∂Y::TJ | ||
|
||
# the full implicit residual's Jacobian, and its linear solver | ||
∂R∂Y::RJ | ||
|
||
# whether this struct is used to compute Wfact_t or Wfact | ||
transform::Bool | ||
|
||
# flags for computing the Jacobian | ||
flags::F | ||
|
||
# cache that is used to evaluate ldiv! | ||
temp1::T1 | ||
temp2::T2 | ||
end | ||
|
||
function ImplicitEquationJacobian(Y, transform, flags) | ||
FT = eltype(Y) | ||
|
||
ᶜρ_name = @name(c.ρ) | ||
ᶜ𝔼_name = if :ρθ in propertynames(Y.c) | ||
@name(c.ρθ) | ||
elseif :ρe in propertynames(Y.c) | ||
@name(c.ρe) | ||
elseif :ρe_int in propertynames(Y.c) | ||
@name(c.ρe_int) | ||
end | ||
ᶠ𝕄_name = @name(f.w) | ||
|
||
BidiagonalRow_C3 = BidiagonalMatrixRow{C3{FT}} | ||
BidiagonalRow_ACT3 = BidiagonalMatrixRow{Adjoint{FT, CT3{FT}}} | ||
QuaddiagonalRow_ACT3 = QuaddiagonalMatrixRow{Adjoint{FT, CT3{FT}}} | ||
TridiagonalRow_C3xACT3 = | ||
TridiagonalMatrixRow{typeof(C3(FT(0)) * CT3(FT(0))')} | ||
∂ᶜ𝔼ₜ∂ᶠ𝕄_Row_ACT3 = | ||
flags.∂ᶜ𝔼ₜ∂ᶠ𝕄_mode == :exact && :ρe in propertynames(Y.c) ? | ||
QuaddiagonalRow_ACT3 : BidiagonalRow_ACT3 | ||
∂Yₜ∂Y = FieldMatrix( | ||
(ᶜρ_name, ᶠ𝕄_name) => Fields.Field(BidiagonalRow_ACT3, axes(Y.c)), | ||
(ᶜ𝔼_name, ᶠ𝕄_name) => Fields.Field(∂ᶜ𝔼ₜ∂ᶠ𝕄_Row_ACT3, axes(Y.c)), | ||
(ᶠ𝕄_name, ᶜρ_name) => Fields.Field(BidiagonalRow_C3, axes(Y.f)), | ||
(ᶠ𝕄_name, ᶜ𝔼_name) => Fields.Field(BidiagonalRow_C3, axes(Y.f)), | ||
(ᶠ𝕄_name, ᶠ𝕄_name) => | ||
Fields.Field(TridiagonalRow_C3xACT3, axes(Y.f)), | ||
) | ||
|
||
dtγ = FT(1) | ||
I = MatrixFields.identity_field_matrix(Y) # one(∂Yₜ∂Y) can't get every block | ||
∂R∂Y = transform ? I ./ dtγ .- ∂Yₜ∂Y : dtγ .* ∂Yₜ∂Y .- I | ||
alg = MatrixFields.BlockArrowheadSolve(ᶜρ_name, ᶜ𝔼_name) | ||
|
||
return ImplicitEquationJacobian( | ||
∂Yₜ∂Y, | ||
FieldMatrixWithSolver(∂R∂Y, Y, alg), | ||
transform, | ||
flags, | ||
similar(Y), | ||
similar(Y), | ||
) | ||
end | ||
|
||
# Required for compatibility with OrdinaryDiffEq.jl | ||
Base.similar(A::ImplicitEquationJacobian) = ImplicitEquationJacobian( | ||
similar(A.∂Yₜ∂Y), | ||
similar(A.∂R∂Y), | ||
A.transform, | ||
A.flags, | ||
A.temp1, | ||
A.temp2, | ||
) | ||
|
||
# Required for compatibility with ClimaTimeSteppers.jl | ||
Base.zero(A::ImplicitEquationJacobian) = ImplicitEquationJacobian( | ||
zero(A.∂Yₜ∂Y), | ||
zero(A.∂R∂Y), | ||
A.transform, | ||
A.flags, | ||
A.temp1, | ||
A.temp2, | ||
) | ||
|
||
# This method for ldiv! is called by Newton's method from ClimaTimeSteppers.jl. | ||
# It solves ∂R∂Y * x = b for x, where R is the implicit residual. | ||
ldiv!( | ||
x::Fields.FieldVector, | ||
A::ImplicitEquationJacobian, | ||
b::Fields.FieldVector, | ||
) = ldiv!(x, A.∂R∂Y, b) | ||
|
||
# This method for ldiv! is called by Krylov.jl from ClimaTimeSteppers.jl. | ||
# See https://github.com/JuliaSmoothOptimizers/Krylov.jl/issues/605 for a | ||
# a similar way of handling the AbstractVectors generated by Krylov.jl. | ||
function ldiv!( | ||
x::AbstractVector, | ||
A::ImplicitEquationJacobian, | ||
b::AbstractVector, | ||
) | ||
A.temp_b .= b | ||
ldiv!(A.temp_x, A, A.temp_b) | ||
x .= A.temp_x | ||
end | ||
|
||
# This function is called by Newton's method from OrdinaryDiffEq.jl. | ||
linsolve!(::Type{Val{:init}}, f, u0; kwargs...) = _linsolve! | ||
_linsolve!(x, A, b, update_matrix = false; kwargs...) = ldiv!(x, A, b) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.