diff --git a/docs/src/API.md b/docs/src/API.md index c9487ef651..d0878d97bb 100644 --- a/docs/src/API.md +++ b/docs/src/API.md @@ -85,6 +85,7 @@ AerosolActivation.total_M_activated ```@docs HetIceNucleation HetIceNucleation.dust_activated_number_fraction +HetIceNucleation.deposition_J HetIceNucleation.ABIFM_J ``` diff --git a/src/IceNucleation.jl b/src/IceNucleation.jl index 2c80312a4b..3c18ab17fc 100644 --- a/src/IceNucleation.jl +++ b/src/IceNucleation.jl @@ -7,6 +7,7 @@ import ..Parameters as CMP import Thermodynamics as TD export dust_activated_number_fraction +export deposition_J export ABIFM_J """ @@ -40,6 +41,27 @@ function dust_activated_number_fraction( end end +""" + deposition_J(dust, ip, Δa_w) + + - `dust` - a struct with dust parameters + - `Δa_w` - change in water activity [unitless]. + +Returns the deposition nucleation rate coefficient, `J`, in m^-2 s^-1 +for different minerals in liquid droplets. +The free parameters `m` and `c` are derived from China et al (2017) +see DOI: 10.1002/2016JD025817 +""" +function deposition_J( + dust::Union{CMP.Ferrihydrite, CMP.Feldspar, CMP.Kaolinite}, + Δa_w::FT, +) where {FT} + + logJ::FT = dust.deposition_m * Δa_w + dust.deposition_c + + return max(FT(0), FT(10)^logJ * FT(1e4)) # converts cm^-2 s^-1 to m^-2 s^-1 +end + """ ABIFM_J(dust, ip, Δa_w) @@ -56,7 +78,7 @@ function ABIFM_J( Δa_w::FT, ) where {FT} - logJ::FT = dust.m * Δa_w + dust.c + logJ::FT = dust.ABIFM_m * Δa_w + dust.ABIFM_c return max(FT(0), FT(10)^logJ * FT(1e4)) # converts cm^-2 s^-1 to m^-2 s^-1 end diff --git a/src/parameters/AerosolFeldspar.jl b/src/parameters/AerosolFeldspar.jl new file mode 100644 index 0000000000..59125de447 --- /dev/null +++ b/src/parameters/AerosolFeldspar.jl @@ -0,0 +1,28 @@ +export Feldspar + +""" + Feldspar{FT} + +Parameters for Feldspar from Alpert et al 2022 +DOI: 10.1039/D1EA00077B + +# Fields +$(DocStringExtensions.FIELDS) +""" +struct Feldspar{FT} <: AerosolType{FT} + "m coefficient for deposition nucleation J [-]" + deposition_m::FT + "c coefficient for deposition nucleation J [-]" + deposition_c::FT +end + +function Feldspar( + ::Type{FT}, + toml_dict::CP.AbstractTOMLDict = CP.create_toml_dict(FT), +) where {FT} + (; data) = toml_dict + return Feldspar( + FT(data["Alpert2022_J_deposition_m_Feldspar"]["value"]), + FT(data["Alpert2022_J_deposition_c_Feldspar"]["value"]), + ) +end diff --git a/src/parameters/AerosolFerrihydrite.jl b/src/parameters/AerosolFerrihydrite.jl new file mode 100644 index 0000000000..f1762383b2 --- /dev/null +++ b/src/parameters/AerosolFerrihydrite.jl @@ -0,0 +1,28 @@ +export Ferrihydrite + +""" + Ferrihydrite{FT} + +Parameters for Ferrihydrite from Alpert et al 2022 +DOI: 10.1039/D1EA00077B + +# Fields +$(DocStringExtensions.FIELDS) +""" +struct Ferrihydrite{FT} <: AerosolType{FT} + "m coefficient for deposition nucleation J [-]" + deposition_m::FT + "c coefficient for deposition nucleation J [-]" + deposition_c::FT +end + +function Ferrihydrite( + ::Type{FT}, + toml_dict::CP.AbstractTOMLDict = CP.create_toml_dict(FT), +) where {FT} + (; data) = toml_dict + return Ferrihydrite( + FT(data["Alpert2022_J_deposition_m_Ferrihydrite"]["value"]), + FT(data["Alpert2022_J_deposition_c_Ferrihydrite"]["value"]), + ) +end diff --git a/src/parameters/AerosolKaolinite.jl b/src/parameters/AerosolKaolinite.jl index 657bc85c14..3bc6af6463 100644 --- a/src/parameters/AerosolKaolinite.jl +++ b/src/parameters/AerosolKaolinite.jl @@ -4,16 +4,21 @@ export Kaolinite Kaolinite{FT} Parameters for kaolinite from Knopf and Alpert 2013 -DOI: 10.1039/C3FD00035D +DOI: 10.1039/C3FD00035D and China et al 2017 +DOI: 10.1002/2016JD025817 # Fields $(DocStringExtensions.FIELDS) """ struct Kaolinite{FT} <: AerosolType{FT} + "m coefficient for deposition nucleation J [-]" + deposition_m::FT + "c coefficient for deposition nucleation J [-]" + deposition_c::FT "m coefficient for immersion freezing J [-]" - m::FT + ABIFM_m::FT "c coefficient for immersion freezing J [-]" - c::FT + ABIFM_c::FT end function Kaolinite( @@ -22,6 +27,8 @@ function Kaolinite( ) where {FT} (; data) = toml_dict return Kaolinite( + FT(data["China2017_J_deposition_m_Kaolinite"]["value"]), + FT(data["China2017_J_deposition_c_Kaolinite"]["value"]), FT(data["KnopfAlpert2013_J_ABIFM_m_Kaolinite"]["value"]), FT(data["KnopfAlpert2013_J_ABIFM_c_Kaolinite"]["value"]), ) diff --git a/test/gpu_tests.jl b/test/gpu_tests.jl index 25d51180c5..508b57a7e9 100644 --- a/test/gpu_tests.jl +++ b/test/gpu_tests.jl @@ -480,6 +480,23 @@ end end end +@kernel function IceNucleation_deposition_J_kernel!( + output::AbstractArray{FT}, + kaolinite, + feldspar, + ferrihydrate, + Delta_a_w, +) where {FT} + + i = @index(Group, Linear) + + @inbounds begin + output[1] = CMI_het.ABIFM_J(kaolinite, Delta_a_w[1]) + output[2] = CMI_het.ABIFM_J(feldspar, Delta_a_w[2]) + output[3] = CMI_het.ABIFM_J(ferrihydrate, Delta_a_w[2]) + end +end + @kernel function IceNucleation_ABIFM_J_kernel!( output::AbstractArray{FT}, kaolinite, @@ -576,6 +593,8 @@ function test_gpu(FT) H2SO4_prs = CMP.H2SO4SolutionParameters(FT) illite = CMP.Illite(FT) kaolinite = CMP.Kaolinite(FT) + feldspar = CMP.Feldspar(FT) + ferrihydrate = CMP.Ferrihydrite(FT) ip = CMP.IceNucleationParameters(FT) @testset "Aerosol activation kernels" begin @@ -821,6 +840,19 @@ function test_gpu(FT) end @testset "Ice Nucleation kernels" begin + dims = (1, 3) + (; output, ndrange) = setup_output(dims, FT) + + Delta_a_w = ArrayType([FT(0.16), FT(0.15)]) + + kernel! = IceNucleation_deposition_J_kernel!(backend, work_groups) + kernel!(output, kaolinite, feldspar, ferrihydrate, Delta_a_w; ndrange) + + # test if deposition_J is callable and returns reasonable values + @test Array(output)[1] ≈ FT(153.65772539109) + @test Array(output)[2] ≈ FT(31.870032033791) + @test Array(output)[3] ≈ FT(31.870032033791) + dims = (1, 2) (; output, ndrange) = setup_output(dims, FT) diff --git a/test/heterogeneous_ice_nucleation_tests.jl b/test/heterogeneous_ice_nucleation_tests.jl index 7f0648a916..746f5c1d32 100644 --- a/test/heterogeneous_ice_nucleation_tests.jl +++ b/test/heterogeneous_ice_nucleation_tests.jl @@ -21,6 +21,8 @@ function test_heterogeneous_ice_nucleation(FT) desert_dust = CMP.DesertDust(FT) illite = CMP.Illite(FT) kaolinite = CMP.Kaolinite(FT) + feldspar = CMP.Feldspar(FT) + ferrihydrate = CMP.ferrihydrate(FT) TT.@testset "dust_activation" begin @@ -81,6 +83,39 @@ function test_heterogeneous_ice_nucleation(FT) end end + TT.@testset "Deposition Nucleation J" begin + + T_warm_1 = FT(229.2) + T_cold_1 = FT(228.8) + x_sulph = FT(0.1) + + T_warm_2 = FT(285) + T_cold_2 = FT(251) + e_warm = FT(1088) + e_cold = FT(544) + + # higher nucleation rate at colder temperatures + for dust in [feldspar, ferrihydrite, kaolinite] + TT.@test CMI_het.deposition_J( + dust, + CO.a_w_xT(H2SO4_prs, tps, x_sulph, T_cold_1) - + CO.a_w_ice(tps, T_cold_1), + ) > CMI_het.deposition_J( + dust, + CO.a_w_xT(H2SO4_prs, tps, x_sulph, T_warm_1) - + CO.a_w_ice(tps, T_warm_1), + ) + + TT.@test CMI_het.depostition_J( + dust, + CO.a_w_eT(tps, e_cold, T_cold_2) - CO.a_w_ice(tps, T_cold_2), + ) > CMI_het.deposition_J( + dust, + CO.a_w_eT(tps, e_warm, T_warm_2) - CO.a_w_ice(tps, T_warm_2), + ) + end + end + TT.@testset "ABIFM J" begin T_warm_1 = FT(229.2) diff --git a/test/performance_tests.jl b/test/performance_tests.jl index 8f67a1f682..dfa04750d8 100644 --- a/test/performance_tests.jl +++ b/test/performance_tests.jl @@ -59,6 +59,7 @@ function benchmark_test(FT) ap = CMP.AerosolActivationParameters(FT) # ice nucleation desert_dust = CMP.DesertDust(FT) + kaolinite = CMP.Kaolinite(FT) ip = CMP.IceNucleationParameters(FT) H2SO4_prs = CMP.H2SO4SolutionParameters(FT) # aerosol nucleation parameters @@ -136,6 +137,7 @@ function benchmark_test(FT) (desert_dust, ip.deposition, S_ice, T_air_2), 50, ) + bench_press(CMI_het.deposition_J, (kaolinite, Delta_a_w), 230) bench_press(CMI_het.ABIFM_J, (desert_dust, Delta_a_w), 230) bench_press(CMI_hom.homogeneous_J, (ip.homogeneous, Delta_a_w), 230)