Skip to content

Commit 0f07fff

Browse files
committed
fix doc error + DistributionTools
1 parent dce882d commit 0f07fff

File tree

4 files changed

+29
-26
lines changed

4 files changed

+29
-26
lines changed

docs/src/plots/RainEvapoartionSB2006.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ function rain_evaporation_CPU(SB2006, aps, tps, q, q_rai, ρ, N_rai, T)
3030
x_star = SB2006.pdf_r.xr_min
3131
G = CO.G_func(aps, tps, T, TD.Liquid())
3232

33-
xr = CM2.pdf_rain_parameters(SB2006.pdf_r, q_rai, ρ, N_rai).xr
34-
Dr = (FT(6) / FT(π) / ρw)^FT(1 / 3) * xr^FT(1 / 3)
33+
(; xr_mean) = CM2.pdf_rain_parameters(SB2006.pdf_r, q_rai, ρ, N_rai)
34+
Dr = (FT(6) / FT(π) / ρw)^FT(1 / 3) * xr_mean^FT(1 / 3)
3535

36-
t_star = (FT(6) * x_star / xr)^FT(1 / 3)
36+
t_star = (FT(6) * x_star / xr_mean)^FT(1 / 3)
3737
a_vent_0 = av * FT(SF.gamma(-1, t_star)) / FT(6)^FT(-2 / 3)
3838
b_vent_0 =
3939
bv * FT(SF.gamma((-1 / 2) + (3 / 2) * β, t_star)) /
@@ -43,11 +43,11 @@ function rain_evaporation_CPU(SB2006, aps, tps, q, q_rai, ρ, N_rai, T)
4343
b_vent_1 =
4444
bv * SF.gamma(FT(5 / 2) + FT(3 / 2) * β) / FT(6)^FT/ 2 + 1 / 2)
4545

46-
N_Re = α * xr^β * sqrt(ρ0 / ρ) * Dr / ν_air
46+
N_Re = α * xr_mean^β * sqrt(ρ0 / ρ) * Dr / ν_air
4747
Fv0 = a_vent_0 + b_vent_0 * (ν_air / D_vapor)^FT(1 / 3) * sqrt(N_Re)
4848
Fv1 = a_vent_1 + b_vent_1 * (ν_air / D_vapor)^FT(1 / 3) * sqrt(N_Re)
4949

50-
evap_rate_0 = min(FT(0), FT(2) * FT(π) * G * S * N_rai * Dr * Fv0 / xr)
50+
evap_rate_0 = min(FT(0), FT(2) * FT(π) * G * S * N_rai * Dr * Fv0 / xr_mean)
5151
evap_rate_1 = min(FT(0), FT(2) * FT(π) * G * S * N_rai * Dr * Fv1 / ρ)
5252
end
5353

src/DistributionTools.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Mostly used for the 2-moment microphysics.
1111
module DistributionTools
1212

1313
import SpecialFunctions as SF
14+
import LogExpFunctions as LEF
1415

1516
"""
1617
generalized_gamma_quantile(ν, μ, B, Y)
@@ -58,7 +59,7 @@ function generalized_gamma_cdf(ν, μ, B, x)
5859
x 0 && return zero(x)
5960

6061
# Compute the regularized incomplete gamma function
61-
p, _ = SF.gamma_inc((ν + 1) / μ, (B * x)^μ)
62+
p, _ = SF.gamma_inc((ν + 1) / μ, B * x^μ)
6263
return p
6364
end
6465

@@ -110,7 +111,8 @@ function exponential_cdf(D_mean, D)
110111
# Handle edge cases
111112
D < 0 && return zero(D)
112113
# Calculate CDF: P(X ≤ D) = 1 - exp(-D/D_mean)
113-
return 1 - exp(-D / D_mean)
114+
logcdf = LEF.log1mexp(-D / D_mean) # careful calculation in log-space
115+
return exp(logcdf)
114116
end
115117

116118
"""
@@ -135,7 +137,8 @@ function exponential_quantile(D_mean, Y)
135137
(0 Y 1) || throw(DomainError(Y, "Probability Y must be in [0,1]"))
136138
D_mean > 0 || throw(DomainError(D_mean, "Mean parameter must be positive"))
137139
# Calculate quantile: x = -D_mean * ln(1-Y)
138-
return -D_mean * log(1 - Y)
140+
logquantile = log(D_mean) + LEF.cloglog(Y) # careful calculation in log-space
141+
return exp(logquantile)
139142
end
140143

141144
"""

src/Microphysics2M.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function pdf_rain_parameters(pdf_r::CMP.RainParticlePDF_SB2006_limited, qᵣ, ρ
8181
# Sequence of limiting steps in Seifert and Beheng 2006:
8282
x̃r = clamp(Lᵣ / Nᵣ, xr_min, xr_max) # Eq. (94) # TODO: Ill-defined for 0 / 0
8383
N₀r = clamp(Nᵣ * * ρw / x̃r), N0_min, N0_max) # Eq. (95)
84-
λr = clamp((π * ρw * N₀r / Lᵣ)^(1 // 4), λ_min, λ_max) # Eq. (96)
84+
λr = clamp(* ρw * N₀r / Lᵣ), λ_min, λ_max) # Eq. (96)
8585
xr_mean = clamp(Lᵣ * λr / N₀r, xr_min, xr_max) # Eq. (97)
8686

8787
Dr_mean = 1 / λr # The inverse of λr is the mean diameter of the raindrops (units: `m`)

test/microphysics2M_tests.jl

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -535,32 +535,32 @@ function test_microphysics2M(FT)
535535
Mⁿ(n, psd) = y -> y^n * psd(y)
536536

537537
# integral bounds computed based on the size distribution
538-
p = eps(FT)
538+
p = FT(1e-6)
539539
D_min, D_max = CM2.get_size_distribution_bounds(pdf_r, ρₐ, qᵣ, Nᵣ, p)
540540
x_min = DT.generalized_gamma_quantile(νr, μr, Br, p)
541541
x_max = DT.generalized_gamma_quantile(νr, μr, Br, 1 - p)
542542

543543
# Test that these bounds correspond to the correct probability levels
544-
TT.@test_broken DT.generalized_gamma_cdf(νr, μr, Br, x_min) p # it's a bit unstable at very low values
545-
TT.@test_broken DT.generalized_gamma_cdf(νr, μr, Br, x_max) 1 - p # TODO: fix this -- not clear why this doesn't work, seems like an issue with SpecialFunctions.jl??
544+
TT.@test DT.generalized_gamma_cdf(νr, μr, Br, x_min) p
545+
TT.@test DT.generalized_gamma_cdf(νr, μr, Br, x_max) 1 - p
546546
TT.@test DT.exponential_cdf(Dr_mean, D_min) p
547547
TT.@test DT.exponential_cdf(Dr_mean, D_max) 1 - p
548548

549549
# Sanity checks for number concentrations for rain
550550
ND = QGK.quadgk(f_D, D_min, D_max)[1]
551551
Nx = QGK.quadgk(f_x, x_min, x_max)[1]
552552
ND_psd = QGK.quadgk(psd, D_min, D_max)[1]
553-
TT.@test ND Nᵣ
554-
TT.@test Nx Nᵣ
555-
TT.@test ND_psd Nᵣ
553+
TT.@test ND Nᵣ rtol = 1e-5
554+
TT.@test Nx Nᵣ rtol = 5e-3
555+
TT.@test ND_psd Nᵣ rtol = 1e-5
556556

557557
# Sanity checks for specific contents for rain
558558
qD = QGK.quadgk(Mⁿ(3, f_D), D_min, D_max)[1] * k_m / ρₐ
559559
qx = QGK.quadgk(Mⁿ(1, f_x), x_min, x_max)[1] / ρₐ
560560
qD_psd = QGK.quadgk(Mⁿ(3, psd), D_min, D_max)[1] * k_m / ρₐ
561-
TT.@test qD qᵣ
562-
TT.@test qx qᵣ
563-
TT.@test qD_psd qᵣ
561+
TT.@test qD qᵣ rtol = 5e-3
562+
TT.@test qx qᵣ rtol = 5e-3
563+
TT.@test qD_psd qᵣ rtol = 5e-3
564564

565565
# Test relationship between exponential moments in diameter space and generalized gamma moments in mass space
566566
# For raindrops, we expect:
@@ -621,33 +621,33 @@ function test_microphysics2M(FT)
621621
Mⁿ(n, psd) = y -> y^n * psd(y)
622622

623623
# integral bounds guesstimated in meters for the mass distribution
624-
p = eps(FT)
624+
p = FT(1e-6)
625625
D_min, D_max = CM2.get_size_distribution_bounds(pdf_c, ρₐ, qₗ, Nₗ, p)
626626
x_min = DT.generalized_gamma_quantile(νc, μc, Bc, p)
627627
x_max = DT.generalized_gamma_quantile(νc, μc, Bc, 1 - p)
628628

629629
# Test that these bounds correspond to the correct probability levels
630630
TT.@test DT.generalized_gamma_cdf(νc, μc, Bc, x_min) p
631631
TT.@test DT.generalized_gamma_cdf(νc, μc, Bc, x_max) 1 - p
632-
TT.@test_broken DT.generalized_gamma_cdf(νcD, μcD, λc, D_min) p # TODO: fix this -- not clear why this doesn't work, seems like an issue with SpecialFunctions.jl??
632+
TT.@test DT.generalized_gamma_cdf(νcD, μcD, λc, D_min) p
633633
TT.@test DT.generalized_gamma_cdf(νcD, μcD, λc, D_max) 1 - p
634634

635635

636636
# Sanity checks of specific content and number concentration with mass distribution
637637
Nx = QGK.quadgk(Mⁿ(0, f_x), x_min, x_max)[1]
638638
qx = QGK.quadgk(Mⁿ(1, f_x), x_min, x_max)[1] / ρₐ
639-
TT.@test qx qₗ
640-
TT.@test Nx Nₗ
639+
TT.@test qx qₗ rtol = 1e-5
640+
TT.@test Nx Nₗ rtol = 1e-5
641641

642642
# Sanity checks of specific content and number concentration with diameter distribution
643643
ND = QGK.quadgk(Mⁿ(0, f_D), D_min, D_max)[1]
644644
ND_psd = QGK.quadgk(Mⁿ(0, psd), D_min, D_max)[1]
645645
qD = QGK.quadgk(Mⁿ(3, f_D), D_min, D_max)[1] * k_m / ρₐ
646646
qD_psd = QGK.quadgk(Mⁿ(3, psd), D_min, D_max)[1] * k_m / ρₐ
647-
TT.@test ND Nₗ
648-
TT.@test ND_psd Nₗ
649-
TT.@test qD qₗ
650-
TT.@test qD_psd qₗ
647+
TT.@test ND Nₗ rtol = 1e-5
648+
TT.@test ND_psd Nₗ rtol = 1e-5
649+
TT.@test qD qₗ rtol = 1e-5
650+
TT.@test qD_psd qₗ rtol = 1e-5
651651
end
652652
end
653653

0 commit comments

Comments
 (0)