Skip to content

Commit

Permalink
Merge pull request #2771 from CliMA/as/spaces-test
Browse files Browse the repository at this point in the history
Interface tests: ClimaAtmos spaces, callbacks and parameterized tendency construction
  • Loading branch information
akshaysridhar authored Apr 8, 2024
2 parents 99d2578 + ab3dddc commit d8dd580
Show file tree
Hide file tree
Showing 18 changed files with 748 additions and 120 deletions.
10 changes: 5 additions & 5 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,27 +96,27 @@ steps:
steps:

- label: ":computer: non-orographic gravity wave parameterization unit test 3d"
command: "julia --color=yes --project=examples test/gravity_wave/non_orographic_gravity_wave/nogw_test_3d.jl"
command: "julia --color=yes --project=examples test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_3d.jl"
artifact_paths: "nonorographic_gravity_wave_test_3d/output_active/*"
agents:
slurm_mem: 20GB

- label: ":computer: non-orographic gravity wave parameterization test with MiMA output"
command: "julia --color=yes --project=examples test/gravity_wave/non_orographic_gravity_wave/nogw_test_mima.jl"
command: "julia --color=yes --project=examples test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_mima.jl"
artifact_paths: "nonorographic_gravity_wave_test_mima/output_active/*"
agents:
slurm_mem: 20GB

- label: ":computer: non-orographic gravity wave parameterization unit test single column"
command: "julia --color=yes --project=examples test/gravity_wave/non_orographic_gravity_wave/nogw_test_single_column.jl"
command: "julia --color=yes --project=examples test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_single_column.jl"
artifact_paths: "nonorographic_gravity_wave_test_single_column/output_active/*"

- label: ":computer: orographic gravity wave parameterization unit test for base flux calculation"
command: "julia --color=yes --project=examples test/gravity_wave/orographic_gravity_wave/ogwd_baseflux.jl"
command: "julia --color=yes --project=examples test/parameterized_tendencies/gravity_wave/orographic_gravity_wave/ogwd_baseflux.jl"
artifact_paths: "orographic_gravity_wave_test_baseflux/output_active/*"

- label: ":computer: orographic gravity wave parameterization unit test for 3d calculation"
command: "julia --color=yes --project=examples test/gravity_wave/orographic_gravity_wave/ogwd_3d.jl"
command: "julia --color=yes --project=examples test/parameterized_tendencies/gravity_wave/orographic_gravity_wave/ogwd_3d.jl"
artifact_paths: "orographic_gravity_wave_test_3d/output_active/*"

- label: ":computer: single column non-orographic gravity wave parameterization"
Expand Down
72 changes: 72 additions & 0 deletions test/callbacks.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Test
import ClimaAtmos as CA
import SciMLBase as SMB

testfun!() = π
cb_default = CA.call_every_n_steps(testfun!;)
test_nsteps = 999
test_dt = 1
test_tend = 999.0

cb_1 = CA.call_every_n_steps(
testfun!,
test_nsteps;
skip_first = false,
call_at_end = false,
condition = nothing,
)
cb_2 =
CA.call_every_dt(testfun!, test_dt; skip_first = false, call_at_end = false)
cb_3 = CA.callback_from_affect(cb_2.affect!)
cb_4 = CA.call_every_n_steps(
testfun!,
3;
skip_first = false,
call_at_end = false,
condition = nothing,
)
cb_set = SMB.CallbackSet(cb_1, cb_2, cb_4)

@testset "simple default callback" begin
@test cb_default.condition.n == 1
@test cb_default.affect!.f!() == π
end

# per n steps
@testset "every n-steps callback" begin
@test cb_1.initialize.skip_first == false
@test cb_1.condition.n == test_nsteps
@test cb_1.affect!.f!() == π
@test_throws AssertionError CA.call_every_n_steps(
testfun!,
Inf;
skip_first = false,
call_at_end = false,
)
end

# per dt interval
@testset "dt interval callback" begin
@test cb_2 isa SMB.DiscreteCallback
@test cb_2.affect!.dt == test_dt
@test cb_2.affect!.cb!.f!() == π
@test_throws AssertionError CA.call_every_dt(
testfun!,
Inf;
skip_first = false,
call_at_end = false,
)
end

@testset "atmos callbacks and callback sets" begin
# atmoscallbacks from discrete callbacks
@test cb_3.f!() == π
atmos_cbs = CA.atmos_callbacks(cb_set)
# test against expected callback outcomes
tspan = [0, test_tend]
@test CA.n_expected_calls(cb_set, test_dt, tspan)[2] == test_tend
@test CA.n_steps_per_cycle_per_cb(cb_set, test_dt) ==
[test_nsteps; test_dt; 3]
end

# query functions
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ using ClimaCoreTempestRemap
using Interpolations

const FT = Float64
include("../../../post_processing/remap/remap_helpers.jl")
include(
joinpath(pkgdir(ClimaAtmos), "post_processing/remap", "remap_helpers.jl"),
)
include("../gw_plotutils.jl")

comms_ctx = ClimaComms.SingletonCommsContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ using ClimaCoreTempestRemap
const FT = Float64

include("../gw_plotutils.jl")
include("../../../post_processing/remap/remap_helpers.jl")
include(
joinpath(pkgdir(ClimaAtmos), "post_processing/remap", "remap_helpers.jl"),
)

comms_ctx = ClimaComms.SingletonCommsContext()

Expand Down
110 changes: 110 additions & 0 deletions test/parameterized_tendencies/microphysics/precipitation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

import ClimaAtmos as CA
import SurfaceFluxes as SF
import ClimaAtmos.Parameters as CAP
import ClimaCore as CC
import Thermodynamics as TD
import CloudMicrophysics as CM

include("../../test_helpers.jl")

### Common Objects ###
@testset begin
"Precipitation tendency functions"
### Boilerplate default integrator objects
config = CA.AtmosConfig(
Dict(
"initial_condition" => "PrecipitatingColumn",
"moist" => "nonequil",
"precip_model" => "0M",
"config" => "column",
"output_default_diagnostics" => false,
),
)
(; Y, p, params) = generate_test_simulation(config)

FT = eltype(Y)
ᶜYₜ = zero(Y)
### Component test begins here

@info "0M Scheme"
### 0-Moment Scheme
precip_model = CA.Microphysics0Moment()
precip_cache = CA.precipitation_cache(Y, precip_model)
# Test cache to verify expected variables exist in tendency function
test_varnames = (
:ᶜS_ρq_tot,
:ᶜ3d_rain,
:ᶜ3d_snow,
:col_integrated_rain,
:col_integrated_snow,
)
for var_name in test_varnames
@test var_name propertynames(precip_cache)
end
turbconv_model = nothing # Extend to other turbulence convection models
CC.Fields.bycolumn(axes(Y.c)) do colidx
CA.compute_precipitation_cache!(
Y,
p,
colidx,
precip_model,
turbconv_model,
)
end
@test maximum(abs.(p.precipitation.ᶜS_ρq_tot)) <= sqrt(eps(FT))

# Test that tendencies result in correct water-mass budget,
# and that the tendency modification corresponds exactly to the
# cached source term.
CC.Fields.bycolumn(axes(Y.c)) do colidx
CA.precipitation_tendency!(
ᶜYₜ,
Y,
p,
FT(0),
colidx,
precip_model,
turbconv_model,
)
end
@test ᶜYₜ.c.ρ == ᶜYₜ.c.ρq_tot
@test ᶜYₜ.c.ρ == p.precipitation.ᶜS_ρq_tot

### 1-Moment Scheme
@info "1M Scheme"
config = CA.AtmosConfig(
Dict(
"initial_condition" => "PrecipitatingColumn",
"moist" => "nonequil",
"precip_model" => "1M",
"config" => "column",
"output_default_diagnostics" => false,
),
)
(; Y, p, params) = generate_test_simulation(config)
precip_model = CA.Microphysics1Moment()
(; turbconv_model) = p.atmos
precip_cache = CA.precipitation_cache(Y, precip_model)
ᶜYₜ = Y .* FT(0)
test_varnames = (:ᶜSqₜᵖ, :ᶜSqᵣᵖ, :ᶜSqₛᵖ, :ᶜSeₜᵖ)
for var_name in test_varnames
@test var_name propertynames(precip_cache)
end
@test CA.qₚ(FT(10), FT(2)) == FT(5)
@test CA.qₚ(FT(-10), FT(2)) == FT(0)
@test CA.limit(FT(10), FT(2)) == FT(1)
CC.Fields.bycolumn(axes(Y.c)) do colidx
CA.precipitation_tendency!(
ᶜYₜ,
Y,
p,
FT(0),
colidx,
precip_model,
turbconv_model,
)
end
@test ᶜYₜ.c.ρ == ᶜYₜ.c.ρq_tot
@test ᶜYₜ.c.ρ == Y.c.ρ .* p.precipitation.ᶜSqₜᵖ
end
37 changes: 37 additions & 0 deletions test/parameterized_tendencies/sponge/rayleigh_sponge.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

import ClimaAtmos as CA
import SurfaceFluxes as SF
import ClimaAtmos.Parameters as CAP
import ClimaCore as CC

include("../../test_helpers.jl")
### Common Objects ###
@testset begin
"Rayleigh-sponge functions"
### Boilerplate default integrator objects
config = CA.AtmosConfig(Dict("initial_condition" => "DryBaroclinicWave"))
(; Y) = generate_test_simulation(config)
zmax = maximum(CC.Fields.coordinate_field(Y.f).z)
z = CC.Fields.coordinate_field(Y.c).z
Y.c.uₕ.components.data.:1 .= ones(axes(Y.c))
Y.c.uₕ.components.data.:2 .= ones(axes(Y.c))
FT = eltype(Y)
ᶜYₜ = zero(Y)
### Component test begins here
rs = CA.RayleighSponge(; zd = FT(0), α_uₕ = FT(1), α_w = FT(1))
(; ᶜβ_rayleigh_uₕ) = CA.rayleigh_sponge_cache(Y, rs)
@test ᶜβ_rayleigh_uₕ == @. sin(FT(π) / 2 * z / zmax)^2
test_cache = (; rayleigh_sponge = (; ᶜβ_rayleigh_uₕ = ᶜβ_rayleigh_uₕ))
CC.Fields.bycolumn(axes(Y.c)) do colidx
CA.rayleigh_sponge_tendency!(ᶜYₜ, Y, test_cache, FT(0), colidx, rs)
end
# Test that only required tendencies are affected
for (var_name) in filter(x -> (x != :uₕ), propertynames(Y.c))
@test ᶜYₜ.c.:($var_name) == zeros(axes(Y.c))
end
for (var_name) in propertynames(Y.f)
@test ᶜYₜ.f.:($var_name) == zeros(axes(Y.f))
end
@test ᶜYₜ.c.uₕ.components.data.:1 == -1 .* (ᶜβ_rayleigh_uₕ)
@test ᶜYₜ.c.uₕ.components.data.:2 == -1 .* (ᶜβ_rayleigh_uₕ)
end
30 changes: 30 additions & 0 deletions test/parameterized_tendencies/sponge/viscous_sponge.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

import ClimaAtmos as CA
import SurfaceFluxes as SF
import ClimaAtmos.Parameters as CAP
import ClimaCore as CC
include("../../test_helpers.jl")

### Common Objects ###
@testset begin
"Rayleigh-sponge functions"
### Boilerplate default integrator objects
config = CA.AtmosConfig(Dict("initial_condition" => "DryBaroclinicWave"))
(; Y) = generate_test_simulation(config)
z = CC.Fields.coordinate_field(Y.c).z
zmax = maximum(CC.Fields.coordinate_field(Y.f).z)
Y.c.uₕ.components.data.:1 .= ones(axes(Y.c))
Y.c.uₕ.components.data.:2 .= ones(axes(Y.c))
ᶜYₜ = Y .* FT(0)
FT = eltype(Y)
### Component test begins here
rs = CA.RayleighSponge(; zd = FT(0), α_uₕ = FT(1), α_w = FT(1))
(; ᶜβ_rayleigh_uₕ) = CA.viscous_sponge_cache(Y, rs)
@test ᶜβ_rayleigh_uₕ == @. sin(FT(π) / 2 * z / zmax)^2
test_cache = (; viscous_sponge = (; ᶜβ_rayleigh_uₕ = ᶜβ_rayleigh_uₕ))
CC.Fields.bycolumn(axes(Y.c)) do colidx
CA.viscous_sponge_tendency!(ᶜYₜ, Y, test_cache, FT(0), colidx, rs)
end
@test ᶜYₜ.c.uₕ.components.data.:1 == -1 .* (ᶜβ_rayleigh_uₕ)
@test ᶜYₜ.c.uₕ.components.data.:2 == -1 .* (ᶜβ_rayleigh_uₕ)
end
File renamed without changes.
Loading

0 comments on commit d8dd580

Please sign in to comment.