Skip to content

Commit

Permalink
Reorganise Tests
Browse files Browse the repository at this point in the history
	renamed:    test/gravity_wave/gw_plotutils.jl -> test/parameterized_tendencies/gravity_wave/gw_plotutils.jl
	renamed:    test/gravity_wave/non_orographic_gravity_wave/nogw_test_3d.jl -> test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_3d.jl
	renamed:    test/gravity_wave/non_orographic_gravity_wave/nogw_test_mima.jl -> test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_mima.jl
	renamed:    test/gravity_wave/non_orographic_gravity_wave/nogw_test_single_column.jl -> test/parameterized_tendencies/gravity_wave/non_orographic_gravity_wave/nogw_test_single_column.jl
	renamed:    test/gravity_wave/orographic_gravity_wave/ogwd_3d.jl -> test/parameterized_tendencies/gravity_wave/orographic_gravity_wave/ogwd_3d.jl
	renamed:    test/gravity_wave/orographic_gravity_wave/ogwd_baseflux.jl -> test/parameterized_tendencies/gravity_wave/orographic_gravity_wave/ogwd_baseflux.jl

        modified:   .buildkite/pipeline.yml
	modified:   parameterized_tendencies/sponge/rayleigh_sponge.jl
	modified:   parameterized_tendencies/microphysics/precipitation.jl
	modified:   test/parameterized_tendencies/microphysics/precipitation.jl
	modified:   test/parameterized_tendencies/sponge/rayleigh_sponge.jl
	modified:   test/rrtmgp_interface.jl
	modified:   test/solver/model_getters.jl
	modified:   runtests.jl

	new file:   test/parameters/parameter_tests.jl
	new file:   test/parameters/parameter_tests.toml
	new file:   sponge/rayleigh_sponge.jl
	new file:   parameterized_tendencies/microphysics/precipitation.jl
	new file:   solver/model_getters.jl

	modified:   runtests.jl
  • Loading branch information
akshaysridhar committed Mar 21, 2024
1 parent 9a03f13 commit 25bb105
Show file tree
Hide file tree
Showing 17 changed files with 708 additions and 114 deletions.
10 changes: 5 additions & 5 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,27 +95,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/*"
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/*"
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/*"

- 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/*"

- 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/*"

- 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.
103 changes: 103 additions & 0 deletions test/parameterized_tendencies/microphysics/precipitation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

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

### 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",
),
)
parsed_args = config.parsed_args
simulation = CA.get_simulation(config)
(; integrator) = simulation
Y = integrator.u
p = integrator.p
params = p.params
cm_params = CAP.microphysics_params(params)
thermo_params = CAP.thermodynamics_params(params)

FT = eltype(Y)
ᶜYₜ = Y .* FT(0)
### 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)
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",
),
)
parsed_args = config.parsed_args
simulation = CA.get_simulation(config)
(; integrator) = simulation
Y = integrator.u
p = integrator.p
params = p.params
cm_params = CAP.microphysics_params(params)
thermo_params = CAP.thermodynamics_params(params)
precip_model = CA.Microphysics1Moment()
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)
end
@test ᶜYₜ.c.ρ == ᶜYₜ.c.ρq_tot
@test ᶜYₜ.c.ρ == Y.c.ρ .* p.precipitation.ᶜSqₜᵖ
end
39 changes: 39 additions & 0 deletions test/parameterized_tendencies/sponge/rayleigh_sponge.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

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

### Common Objects ###
@testset begin
"Rayleigh-sponge functions"
### Boilerplate default integrator objects
config = CA.AtmosConfig(Dict("initial_condition" => "DryBaroclinicWave"))
parsed_args = config.parsed_args
simulation = CA.get_simulation(config)
(; integrator) = simulation
Y = integrator.u
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ₜ = Y .* FT(0)
### 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
File renamed without changes.
149 changes: 149 additions & 0 deletions test/rrtmgp_interface.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
using Test
using Random
Random.seed!(1234)
import ClimaAtmos as CA
import ClimaAtmos.RRTMGPInterface as RRTMGPI
import ClimaParams as CP
import RRTMGP.Parameters.RRTMGPParameters

param_dict = CP.create_toml_dict(Float64)
params = RRTMGPParameters(param_dict)

using Statistics

include("test_helpers.jl")

@testset "array <-> field" begin
(; bubble_space) = get_spherical_spaces()
test_field = ones(bubble_space)
idx = size(parent(test_field)) # IJFH layout
npts = idx[1] * idx[2] * idx[4]
@assert test_field isa Fields.Field
test_array = RRTMGPI.field2array(test_field)
@test test_array isa Array
@test length(test_array) == npts
new_field = RRTMGPI.array2field(test_array, bubble_space)
@test new_field == test_field
@test size(parent(new_field)) == idx
end

@testset "arithmetic ops" begin
FloatType = (Float32, Float64)
for FT in FloatType
_T = [FT(1)]
_Tꜛ = [FT(1)]
_Tꜜ = [FT(2)]
_p = [FT(1 // 2)]
_p₁ = [FT(2)]
_p₂ = [FT(3)]
_Tₛ = [FT(5)]
XT = similar(_T)
XP = similar(_p)
@test RRTMGPI.uniform_z_p.(_T, _p₁, _Tꜜ, _p₁, _Tꜛ) == _p₁
@test RRTMGPI.uniform_z_p.(_T, _p₁, _Tꜜ, _p₁, _Tꜛ) == _p₁

RRTMGPI.interp!(RRTMGPI.ArithmeticMean(), XP, XT, _p₁, _Tꜜ, _p₂, _Tꜛ)
@test XT[1] == (_Tꜜ[1] + _Tꜛ[1]) / 2
@test XP[1] == (_p₁[1] + _p₂[1]) / 2

RRTMGPI.interp!(RRTMGPI.GeometricMean(), XP, XT, _p₁, _Tꜜ, _p₂, _Tꜛ)
@test XT[1] == sqrt(_Tꜜ[1] * _Tꜛ[1])
@test XP[1] == sqrt(_p₁[1] * _p₂[1])

RRTMGPI.interp!(RRTMGPI.UniformZ(), XP, XT, _p₁, _Tꜜ, _p₂, _Tꜛ)
@test XT[1] == (_Tꜜ[1] + _Tꜛ[1]) / 2
@test XP[1] == RRTMGPI.uniform_z_p.(XT, _p₁, _Tꜜ, _p₂, _Tꜛ)[]

RRTMGPI.interp!(RRTMGPI.UniformP(), XP, XT, _p₁, _Tꜜ, _p₂, _Tꜛ)
@test XP[1] == (_p₁[1] + _p₂[1]) / 2
# The second result entry has the same function form as uniform_z_p,
# with arguments swapped
@test XT[1] == RRTMGPI.uniform_z_p.(XP, _Tꜜ, _p₁, _Tꜛ, _p₂)[]

RRTMGPI.extrap!(
RRTMGPI.ArithmeticMean(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
@test XP[1] == @. (3 * _p₁[1] - _p₂[1]) / 2
@test XT[1] == @. (3 * _Tꜜ[1] - _Tꜛ[1]) / 2

RRTMGPI.extrap!(
RRTMGPI.GeometricMean(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
@test XP[1] == @. sqrt(_p₁[1]^3 / _p₂[1])
@test XT[1] == @. sqrt(_Tꜜ[1]^3 / _Tꜛ[1])

RRTMGPI.extrap!(
RRTMGPI.ArithmeticMean(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
_XP = XP
RRTMGPI.extrap!(
RRTMGPI.UniformZ(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
@test _XP[1] == XP[1]
# The result entry has the same function form as uniform_z_p,
# with arguments swapped
@test XT[1] == RRTMGPI.uniform_z_p.(XP, _Tꜜ, _p₁, _Tꜛ, _p₂)[]

RRTMGPI.extrap!(
RRTMGPI.ArithmeticMean(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
_XT = XT
RRTMGPI.extrap!(
RRTMGPI.UniformP(),
XP,
XT,
_p₁,
_Tꜜ,
_p₂,
_Tꜛ,
_Tₛ,
params,
)
@test XP[1] == RRTMGPI.uniform_z_p.(XT, _p₁, _Tꜜ, _p₂, _Tꜛ)[]
@test _XT[1] == XT[1]

# RRTMGPI.extrap!(RRTMGPI.UseSurfaceTempAtBottom(), XP, XT, _p₁, _Tꜜ, _p₂, _Tꜛ, _Tₛ, params)
# @test XT[1] == _Tₛ[1]

end
end
Loading

0 comments on commit 25bb105

Please sign in to comment.