Skip to content

Commit e743a79

Browse files
Merge pull request #3815 from CliMA/dy/implicit_interface
Add preliminary implicit solver interface and documentation
2 parents f110b57 + c69e43b commit e743a79

File tree

7 files changed

+295
-466
lines changed

7 files changed

+295
-466
lines changed

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ makedocs(;
3535
"Ocean Surface Albedo Parameterization" => "surface_albedo.md",
3636
"Topography Representation" => "topography.md",
3737
"Tracers" => "tracers.md",
38+
"Implicit Solver" => "implicit_solver.md",
3839
"Radiative Equilibrium" => "radiative_equilibrium.md",
3940
"Single Column Model" => "single_column_prospect.md",
4041
"Restarts and checkpoints" => "restarts.md",

docs/src/api.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ ClimaAtmos.InitialConditions.Bomex
4343
ClimaAtmos.InitialConditions.Soares
4444
```
4545

46-
### Implicit Solver
46+
### Jacobian
4747

4848
```@docs
49-
ClimaAtmos.ImplicitEquationJacobian
49+
ClimaAtmos.Jacobian
50+
ClimaAtmos.JacobianAlgorithm
51+
ClimaAtmos.ManualSparseJacobian
5052
```
5153

5254
### Helper

docs/src/implicit_solver.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Implicit Solver
2+
3+
When we use an implicit or split implicit-explicit (IMEX) timestepping scheme,
4+
we end up with a nonlinear equation of the form ``R(Y) = 0``, where
5+
```math
6+
R(Y) = Y_{imp}(Y) - Y = Y_{prev} + Δt * T_{imp}(Y) - Y.
7+
```
8+
In this expression, ``Y_{imp}(Y)`` denotes the state at some time ``t + Δt``.
9+
This can be expressed as the sum of ``Y_{prev}``, the contribution from the
10+
state at time ``t`` (and possibly also at earlier times, depending on the order
11+
of the timestepping scheme), and ``Δt * T_{imp}(Y)``, the contribution from the
12+
implicit tendency ``T_{imp}`` between times ``t`` and ``t + Δt``. The new state
13+
at the end of each implicit step in the timestepping scheme is the value of
14+
``Y`` that solves this equation, i.e., the value of ``Y`` that is consistent
15+
with the state ``Y_{imp}(Y)`` predicted by the implicit step.
16+
17+
Note: When we use a higher-order timestepping scheme, the full step ``Δt`` is
18+
divided into several sub-steps or "stages", where the duration of stage ``i`` is
19+
``Δt * γ_i`` for some constant ``γ_i`` between 0 and 1.
20+
21+
In order to solve this equation using Newton's method, we must specify the
22+
derivative ``∂R/∂Y``. Since ``Y_{prev}`` does not depend on ``Y`` (it is only a
23+
function of the state at or before time ``t``), this derivative is
24+
```math
25+
R'(Y) = Δt * T_{imp}'(Y) - I.
26+
```
27+
In addition, we must specify how to divide ``R(Y)`` by this derivative, i.e.,
28+
how to solve the linear equation
29+
```math
30+
R'(Y) * ΔY = R(Y).
31+
```
32+
33+
Note: This equation comes from assuming that there is some ``ΔY`` such that
34+
``R(Y - ΔY) = 0`` and making the first-order approximation
35+
```math
36+
R(Y - ΔY) \approx R(Y) - R'(Y) * ΔY.
37+
```
38+
39+
After initializing ``Y`` to ``Y[0] = Y_{prev}``, Newton's method executes the
40+
following steps:
41+
- Compute the derivative ``R'(Y[0])``.
42+
- Compute the implicit tendency ``T_{imp}(Y[0])`` and use it to get ``R(Y[0])``.
43+
- Solve the linear equation ``R'(Y[0]) * ΔY[0] = R(Y[0])`` for ``ΔY[0]``.
44+
- Update ``Y`` to ``Y[1] = Y[0] - ΔY[0]``.
45+
46+
If the number of Newton iterations is limited to 1, this new value of ``Y`` is
47+
taken to be the solution of the implicit equation. Otherwise, this sequence of
48+
steps is repeated, i.e., ``ΔY[1]`` is computed and used to update ``Y`` to
49+
``Y[2] = Y[1] - ΔY[1]``, then ``ΔY[2]`` is computed and used to update ``Y`` to
50+
``Y[3] = Y[2] - ΔY[2]``, and so on. The iterative process is terminated either
51+
when the residual ``R(Y)`` is sufficiently close to 0 (according to the
52+
convergence condition passed to Newton's method), or when the maximum number of
53+
iterations is reached.
54+
55+
In ClimaAtmos, the derivative ``∂R/∂Y`` is represented as a
56+
[`ClimaAtmos.Jacobian`](@ref), and the method for computing it is given by a
57+
[`ClimaAtmos.JacobianAlgorithm`](@ref).

src/ClimaAtmos.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module ClimaAtmos
22

33
using NVTX
44
import Adapt
5+
import LinearAlgebra
56
import NullBroadcasts: NullBroadcasted
67
import LazyBroadcast
78
import LazyBroadcast: lazy
@@ -55,7 +56,9 @@ include(joinpath("prognostic_equations", "pressure_work.jl"))
5556
include(joinpath("prognostic_equations", "zero_velocity.jl"))
5657

5758
include(joinpath("prognostic_equations", "implicit", "implicit_tendency.jl"))
58-
include(joinpath("prognostic_equations", "implicit", "implicit_solver.jl"))
59+
include(
60+
joinpath("prognostic_equations", "implicit", "manual_sparse_jacobian.jl"),
61+
)
5962

6063
include(joinpath("prognostic_equations", "water_advection.jl"))
6164
include(joinpath("prognostic_equations", "remaining_tendency.jl"))

0 commit comments

Comments
 (0)