Skip to content

Commit 5a797ef

Browse files
authored
split computation in Jacobian (#1121)
1 parent 60fc129 commit 5a797ef

File tree

13 files changed

+138
-129
lines changed

13 files changed

+138
-129
lines changed

experiments/benchmarks/bucket.jl

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import ClimaUtilities.TimeVaryingInputs: TimeVaryingInput
2323

2424
import ClimaTimeSteppers as CTS
2525
import NCDatasets
26-
using ClimaCore
26+
import ClimaCore
27+
@show pkgversion(ClimaCore)
2728
import ClimaLand
2829
using ClimaParams
2930
using ClimaLand.Bucket:
@@ -66,13 +67,10 @@ function setup_prob(t0, tf, Δt; nelements = (200, 7))
6667
# We set up the problem in a function so that we can make multiple copies (for profiling)
6768

6869
# Set up simulation domain
69-
soil_depth = FT(3.5)
70-
bucket_domain = ClimaLand.Domains.SphericalShell(;
71-
radius = FT(6.3781e6),
72-
depth = soil_depth,
73-
nelements = nelements,
74-
dz_tuple = FT.((1.0, 0.05)),
75-
)
70+
dz_tuple = FT.((1.0, 0.05))
71+
depth = FT(3.5)
72+
bucket_domain =
73+
ClimaLand.global_domain(FT; nelements, dz_tuple, depth = depth)
7674
start_date = DateTime(2005)
7775

7876
# Initialize parameters
@@ -259,7 +257,7 @@ if profiler == "flamegraph"
259257
end
260258

261259
if get(ENV, "BUILDKITE_PIPELINE_SLUG", nothing) == "climaland-benchmark"
262-
PREVIOUS_BEST_TIME = 1.69
260+
PREVIOUS_BEST_TIME = 0.533
263261
if average_timing_s > PREVIOUS_BEST_TIME + std_timing_s
264262
@info "Possible performance regression, previous average time was $(PREVIOUS_BEST_TIME)"
265263
elseif average_timing_s < PREVIOUS_BEST_TIME - std_timing_s

experiments/benchmarks/richards.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ ClimaComms.@import_required_backends
3636
import ClimaUtilities.TimeVaryingInputs: TimeVaryingInput
3737
import ClimaUtilities.Regridders: InterpolationsRegridder
3838
import ClimaTimeSteppers as CTS
39-
using ClimaCore
39+
import ClimaCore
40+
@show pkgversion(ClimaCore)
4041
using ClimaParams
4142

4243
import ClimaLand
@@ -305,7 +306,7 @@ if profiler == "flamegraph"
305306
end
306307

307308
if get(ENV, "BUILDKITE_PIPELINE_SLUG", nothing) == "climaland-benchmark"
308-
PREVIOUS_BEST_TIME = 1.49
309+
PREVIOUS_BEST_TIME = 0.6
309310
if average_timing_s > PREVIOUS_BEST_TIME + std_timing_s
310311
@info "Possible performance regression, previous average time was $(PREVIOUS_BEST_TIME)"
311312
elseif average_timing_s < PREVIOUS_BEST_TIME - std_timing_s

experiments/benchmarks/snowy_land.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import SciMLBase
3030
import ClimaComms
3131
ClimaComms.@import_required_backends
3232
import ClimaTimeSteppers as CTS
33-
using ClimaCore
33+
import ClimaCore
34+
@show pkgversion(ClimaCore)
3435
using ClimaUtilities.ClimaArtifacts
3536

3637
import ClimaUtilities.TimeVaryingInputs:
@@ -490,7 +491,7 @@ if profiler == "flamegraph"
490491
@info "Saved allocation flame to $alloc_flame_file"
491492
end
492493
if get(ENV, "BUILDKITE_PIPELINE_SLUG", nothing) == "climaland-benchmark"
493-
PREVIOUS_BEST_TIME = 3.29
494+
PREVIOUS_BEST_TIME = 0.74
494495
if average_timing_s > PREVIOUS_BEST_TIME + std_timing_s
495496
@info "Possible performance regression, previous average time was $(PREVIOUS_BEST_TIME)"
496497
elseif average_timing_s < PREVIOUS_BEST_TIME - std_timing_s

experiments/long_runs/bucket.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import SciMLBase
1414
import ClimaComms
1515
ClimaComms.@import_required_backends
1616
import ClimaTimeSteppers as CTS
17-
using ClimaCore
17+
import ClimaCore
18+
@show pkgversion(ClimaCore)
1819
using ClimaUtilities.ClimaArtifacts
1920
import Interpolations
2021
import ClimaUtilities.TimeVaryingInputs:

experiments/long_runs/land_region.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import SciMLBase
1919
import ClimaComms
2020
ClimaComms.@import_required_backends
2121
import ClimaTimeSteppers as CTS
22-
using ClimaCore
22+
import ClimaCore
23+
@show pkgversion(ClimaCore)
2324
using ClimaUtilities.ClimaArtifacts
2425

2526
import ClimaDiagnostics

experiments/long_runs/snowy_land.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import SciMLBase
1919
import ClimaComms
2020
ClimaComms.@import_required_backends
2121
import ClimaTimeSteppers as CTS
22-
using ClimaCore
22+
import ClimaCore
23+
@show pkgversion(ClimaCore)
2324
using ClimaUtilities.ClimaArtifacts
2425
import ClimaUtilities.OnlineLogging: WallTimeInfo, report_walltime
2526
import ClimaUtilities.TimeManager: ITime, date

experiments/long_runs/soil.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ import SciMLBase
1818
import ClimaComms
1919
ClimaComms.@import_required_backends
2020
import ClimaTimeSteppers as CTS
21-
using ClimaCore
21+
import ClimaCore
22+
@show pkgversion(ClimaCore)
2223
using ClimaUtilities.ClimaArtifacts
2324

2425
using ClimaDiagnostics

src/shared_utilities/Domains.jl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,12 @@ function Column(;
169169
subsurface_space =
170170
ClimaCore.Spaces.CenterFiniteDifferenceSpace(device, mesh)
171171
surface_space = obtain_surface_space(subsurface_space)
172-
space = (; surface = surface_space, subsurface = subsurface_space)
172+
subsurface_face_space = obtain_face_space(subsurface_space)
173+
space = (;
174+
surface = surface_space,
175+
subsurface = subsurface_space,
176+
subsurface_face = subsurface_face_space,
177+
)
173178
fields = get_additional_coordinate_field_data(subsurface_space)
174179
return Column{FT}(
175180
zlim,
@@ -470,7 +475,12 @@ function HybridBox(;
470475
)
471476

472477
surface_space = obtain_surface_space(subsurface_space)
473-
space = (; surface = surface_space, subsurface = subsurface_space)
478+
subsurface_face_space = obtain_face_space(subsurface_space)
479+
space = (;
480+
surface = surface_space,
481+
subsurface = subsurface_space,
482+
subsurface_face = subsurface_face_space,
483+
)
474484
fields = get_additional_coordinate_field_data(subsurface_space)
475485
return HybridBox{FT}(
476486
horzdomain.xlim,
@@ -593,7 +603,12 @@ function SphericalShell(;
593603
vert_center_space,
594604
)
595605
surface_space = obtain_surface_space(subsurface_space)
596-
space = (; surface = surface_space, subsurface = subsurface_space)
606+
subsurface_face_space = obtain_face_space(subsurface_space)
607+
space = (;
608+
surface = surface_space,
609+
subsurface = subsurface_space,
610+
subsurface_face = subsurface_face_space,
611+
)
597612
fields = get_additional_coordinate_field_data(subsurface_space)
598613
return SphericalShell{FT}(
599614
radius,

src/standalone/Soil/boundary_conditions.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ top boundary.
883883
These variables are updated in place in `boundary_flux!`.
884884
"""
885885
boundary_vars(bc::MoistureStateBC, ::ClimaLand.TopBoundary) =
886-
(:top_bc, :top_bc_wvec, :dfluxBCdY)
886+
(:top_bc, :top_bc_wvec, :dfluxBCdY, :topBC_scratch)
887887

888888
"""
889889
boundary_var_domain_names(::MoistureStateBC, ::ClimaLand.TopBoundary)
@@ -892,7 +892,7 @@ An extension of the `boundary_var_domain_names` method for MoistureStateBC at th
892892
top boundary.
893893
"""
894894
boundary_var_domain_names(bc::MoistureStateBC, ::ClimaLand.TopBoundary) =
895-
(:surface, :surface, :surface)
895+
(:surface, :surface, :surface, :subsurface_face)
896896
"""
897897
boundary_var_types(::RichardsModel{FT},
898898
::MoistureStateBC,
@@ -910,6 +910,7 @@ boundary_var_types(
910910
FT,
911911
ClimaCore.Geometry.WVector{FT},
912912
ClimaCore.Geometry.Covariant3Vector{FT},
913+
ClimaCore.Geometry.Covariant3Vector{FT},
913914
)
914915

915916

src/standalone/Soil/energy_hydrology.jl

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,29 @@ function ClimaLand.make_compute_jacobian(model::EnergyHydrology{FT}) where {FT}
343343
∂ϑres∂ϑ = matrix[@name(soil.ϑ_l), @name(soil.ϑ_l)]
344344
∂ρeres∂ρe = matrix[@name(soil.ρe_int), @name(soil.ρe_int)]
345345
∂ρeres∂ϑ = matrix[@name(soil.ρe_int), @name(soil.ϑ_l)]
346+
347+
# Derivatives with respect to ϑ:
348+
349+
# Precompute intermediate quantities to improve performance
350+
# due to fusing of broadcasted expressions involving matrices
351+
# First, the gradient of ∂ψ∂ϑ
352+
# This term is used again below, so we do not alter it once we have made it
353+
@. p.soil.bidiag_matrix_scratch =
354+
gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
355+
ClimaLand.Soil.dψdϑ(
356+
hydrology_cm,
357+
Y.soil.ϑ_l,
358+
ν - Y.soil.θ_i, #ν_eff
359+
θ_r,
360+
S_s,
361+
),
362+
)
363+
# Now the full Darcy flux term. This term is the one that gets altered with the BC
364+
# contribution in place, below
365+
@. p.soil.full_bidiag_matrix_scratch =
366+
MatrixFields.DiagonalMatrixRow(interpc2f_op(-p.soil.K))
367+
p.soil.bidiag_matrix_scratch
368+
346369
# If the top BC is a `MoistureStateBC`, add the term from the top BC
347370
# flux before applying divergence
348371
if haskey(p.soil, :dfluxBCdY)
@@ -353,80 +376,47 @@ function ClimaLand.make_compute_jacobian(model::EnergyHydrology{FT}) where {FT}
353376
Geometry.Covariant3Vector(zero(FT)),
354377
),
355378
)
356-
# Add term from top boundary condition before applying divergence
357379
# Note: need to pass 3D field on faces to `topBC_op`. Interpolating `K` to faces
358380
# for this is inefficient - we should find a better solution.
359-
@. ∂ϑres∂ϑ =
360-
-dtγ * (
361-
divf2c_matrix() (
362-
MatrixFields.DiagonalMatrixRow(
363-
interpc2f_op(-p.soil.K),
364-
) gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
365-
ClimaLand.Soil.dψdϑ(
366-
hydrology_cm,
367-
Y.soil.ϑ_l,
368-
ν - Y.soil.θ_i, #ν_eff
369-
θ_r,
370-
S_s,
371-
),
372-
) + MatrixFields.LowerDiagonalMatrixRow(
373-
topBC_op(
374-
Geometry.Covariant3Vector(
375-
zero(interpc2f_op(p.soil.K)),
376-
),
377-
),
378-
)
379-
)
380-
) - (I,)
381-
else
382-
@. ∂ϑres∂ϑ =
383-
-dtγ * (
384-
divf2c_matrix()
385-
MatrixFields.DiagonalMatrixRow(interpc2f_op(-p.soil.K))
386-
gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
387-
ClimaLand.Soil.dψdϑ(
388-
hydrology_cm,
389-
Y.soil.ϑ_l,
390-
ν - Y.soil.θ_i, #ν_eff
391-
θ_r,
392-
S_s,
393-
),
394-
)
395-
) - (I,)
381+
@. p.soil.topBC_scratch = topBC_op(
382+
Geometry.Covariant3Vector(zero(interpc2f_op(p.soil.K))),
383+
)
384+
@. p.soil.full_bidiag_matrix_scratch +=
385+
MatrixFields.LowerDiagonalMatrixRow(p.soil.topBC_scratch)
396386
end
387+
388+
@. ∂ϑres∂ϑ =
389+
-dtγ * (divf2c_matrix() p.soil.full_bidiag_matrix_scratch) - (I,)
390+
391+
# Now create the flux term for ∂ρe∂ϑ using bidiag_matrix_scratch
392+
# This overwrites full_bidiag_matrix_scratch
393+
@. p.soil.full_bidiag_matrix_scratch =
394+
MatrixFields.DiagonalMatrixRow(
395+
-interpc2f_op(
396+
volumetric_internal_energy_liq(
397+
p.soil.T,
398+
model.parameters.earth_param_set,
399+
) * p.soil.K,
400+
),
401+
) p.soil.bidiag_matrix_scratch
397402
@. ∂ρeres∂ϑ =
398-
-dtγ * (
399-
divf2c_matrix() MatrixFields.DiagonalMatrixRow(
400-
-interpc2f_op(
401-
volumetric_internal_energy_liq(
402-
p.soil.T,
403-
model.parameters.earth_param_set,
404-
) * p.soil.K,
405-
),
406-
) gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
407-
ClimaLand.Soil.dψdϑ(
408-
hydrology_cm,
409-
Y.soil.ϑ_l,
410-
ν - Y.soil.θ_i, #ν_eff
411-
θ_r,
412-
S_s,
413-
),
414-
)
415-
) - (I,)
403+
-dtγ * (divf2c_matrix() p.soil.full_bidiag_matrix_scratch) - (I,)
416404

405+
# Now overwrite bidiag_matrix_scratch and full_bidiag scratch for the ρe ρe bidiagonal
406+
@. p.soil.bidiag_matrix_scratch =
407+
gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
408+
1 / ClimaLand.Soil.volumetric_heat_capacity(
409+
p.soil.θ_l,
410+
Y.soil.θ_i,
411+
ρc_ds,
412+
earth_param_set,
413+
),
414+
)
415+
@. p.soil.full_bidiag_matrix_scratch =
416+
MatrixFields.DiagonalMatrixRow(interpc2f_op(-p.soil.κ))
417+
p.soil.bidiag_matrix_scratch
417418
@. ∂ρeres∂ρe =
418-
-dtγ * (
419-
divf2c_matrix()
420-
MatrixFields.DiagonalMatrixRow(interpc2f_op(-p.soil.κ))
421-
gradc2f_matrix() MatrixFields.DiagonalMatrixRow(
422-
1 / ClimaLand.Soil.volumetric_heat_capacity(
423-
p.soil.θ_l,
424-
Y.soil.θ_i,
425-
ρc_ds,
426-
earth_param_set,
427-
),
428-
)
429-
) - (I,)
419+
-dtγ * (divf2c_matrix() p.soil.full_bidiag_matrix_scratch) - (I,)
430420
end
431421
return compute_jacobian!
432422
end
@@ -505,6 +495,8 @@ ClimaLand.auxiliary_vars(soil::EnergyHydrology) = (
505495
:θ_l,
506496
:T,
507497
,
498+
:bidiag_matrix_scratch,
499+
:full_bidiag_matrix_scratch,
508500
boundary_vars(soil.boundary_conditions.top, ClimaLand.TopBoundary())...,
509501
boundary_vars(
510502
soil.boundary_conditions.bottom,
@@ -526,6 +518,8 @@ ClimaLand.auxiliary_types(soil::EnergyHydrology{FT}) where {FT} = (
526518
FT,
527519
FT,
528520
FT,
521+
MatrixFields.BidiagonalMatrixRow{Geometry.Covariant3Vector{FT}},
522+
MatrixFields.BidiagonalMatrixRow{Geometry.Covariant3Vector{FT}},
529523
boundary_var_types(
530524
soil,
531525
soil.boundary_conditions.top,
@@ -546,6 +540,8 @@ ClimaLand.auxiliary_domain_names(soil::EnergyHydrology) = (
546540
:subsurface,
547541
:subsurface,
548542
:subsurface,
543+
:subsurface_face,
544+
:subsurface_face,
549545
boundary_var_domain_names(
550546
soil.boundary_conditions.top,
551547
ClimaLand.TopBoundary(),

0 commit comments

Comments
 (0)