|
| 1 | +import OrdinaryDiffEq as ODE |
| 2 | +import CairoMakie as MK |
| 3 | + |
| 4 | +import ClimaParams as CP |
| 5 | +import CloudMicrophysics as CM |
| 6 | +import CloudMicrophysics.Parameters as CMP |
| 7 | +import CloudMicrophysics.ThermodynamicsInterface as TDI |
| 8 | + |
| 9 | +# definition of the ODE problem for parcel model |
| 10 | +include(joinpath(pkgdir(CM), "parcel", "Parcel.jl")) |
| 11 | + |
| 12 | +function run_parcel_model(Nₐ, Nₗ, Nᵢ, rₗ, rᵢ, w, FT) |
| 13 | + |
| 14 | + # Get free parameters |
| 15 | + tps = TDI.TD.Parameters.ThermodynamicsParameters(FT) |
| 16 | + wps = CMP.WaterProperties(FT) |
| 17 | + |
| 18 | + # Initial conditions |
| 19 | + T₀ = FT(230) |
| 20 | + cᵥ₀ = FT(5 * 1e-5) |
| 21 | + ln_INPC = FT(0) |
| 22 | + |
| 23 | + # Constants |
| 24 | + ρₗ = wps.ρw |
| 25 | + ρᵢ = wps.ρi |
| 26 | + ϵₘ = TDI.Rd_over_Rv(tps) |
| 27 | + eₛ = TDI.saturation_vapor_pressure_over_liquid(tps, T₀) |
| 28 | + qᵥ = ϵₘ / (ϵₘ - 1 + 1 / cᵥ₀) |
| 29 | + Sₗ = FT(1.0) |
| 30 | + e = Sₗ * eₛ |
| 31 | + p₀ = e / cᵥ₀ |
| 32 | + ρ_air = TDI.air_density(tps, T₀, p₀, qᵥ, FT(0), FT(0)) |
| 33 | + qₗ = Nₗ * FT(4 / 3 * π) * (rₗ)^3 * ρₗ / ρ_air |
| 34 | + qᵢ = Nᵢ * FT(4 / 3 * π) * (rᵢ)^3 * ρᵢ / ρ_air |
| 35 | + IC = [Sₗ, p₀, T₀, qᵥ, qₗ, qᵢ, Nₐ, Nₗ, Nᵢ, ln_INPC, qₗ, Nₗ] |
| 36 | + |
| 37 | + # Simulation parameters passed into ODE solver |
| 38 | + const_dt = FT(1e-2) # model timestep |
| 39 | + t_max = FT(60) # total time |
| 40 | + aerosol = CMP.Sulfate(FT) |
| 41 | + |
| 42 | + condensation_growth = "Condensation" |
| 43 | + deposition_growth = "Deposition" |
| 44 | + aerosol_act = "AeroAct" # turn on aerosol activation |
| 45 | + aero_σ_g = FT(2.3) |
| 46 | + r_nuc = FT(4e-8) |
| 47 | + |
| 48 | + params = parcel_params{FT}( |
| 49 | + w = w, |
| 50 | + const_dt = const_dt, |
| 51 | + aerosol_act = aerosol_act, |
| 52 | + aerosol = aerosol, |
| 53 | + aero_σ_g = aero_σ_g, |
| 54 | + r_nuc = r_nuc, |
| 55 | + condensation_growth = condensation_growth, |
| 56 | + deposition_growth = deposition_growth, |
| 57 | + Nₐ = Nₐ, |
| 58 | + liq_size_distribution = "MonodisperseMix", |
| 59 | + ) |
| 60 | + |
| 61 | + # solve ODE |
| 62 | + sol = run_parcel(IC, FT(0), t_max, params) |
| 63 | + |
| 64 | + S_max = maximum(sol[1, :]) - FT(1) |
| 65 | + |
| 66 | + # ARG results |
| 67 | + ad = AM.Mode_κ( |
| 68 | + params.r_nuc, |
| 69 | + params.aero_σ_g, |
| 70 | + params.Nₐ, |
| 71 | + (FT(1.0),), |
| 72 | + (FT(1.0),), |
| 73 | + (params.aerosol.M,), |
| 74 | + (params.aerosol.κ,), |
| 75 | + ) |
| 76 | + all_ad = AM.AerosolDistribution((ad,)) |
| 77 | + S_max_ARG = AA.max_supersaturation(params.aap, all_ad, params.aps, params.tps, T₀, p₀, w, qᵥ + qₗ + qᵢ, qₗ, qᵢ) |
| 78 | + S_max_mod = |
| 79 | + AA.max_supersaturation(params.aap, all_ad, params.aps, params.tps, T₀, p₀, w, qᵥ + qₗ + qᵢ, qₗ, qᵢ, Nₗ, Nᵢ) |
| 80 | + |
| 81 | + return S_max / S_max_ARG, S_max_mod / S_max_ARG |
| 82 | +end |
| 83 | + |
| 84 | + |
| 85 | +FT = Float32 |
| 86 | +Nₐ = FT(5e8) |
| 87 | +Nₗ = FT(1e8) |
| 88 | +Nᵢ = FT(1e6) |
| 89 | +rₗ = FT(20e-6) |
| 90 | +rᵢ = FT(20e-6) |
| 91 | +w = FT(1.2) # updraft speed |
| 92 | + |
| 93 | +n_points = 10 |
| 94 | +Nₗ_range = range(FT(0), stop = FT(1e8), length = n_points) |
| 95 | +Nᵢ_range = range(FT(0), stop = FT(1e6), length = n_points) |
| 96 | +rₗ_range = range(FT(0e-6), stop = FT(25e-6), length = n_points) |
| 97 | +rᵢ_range = range(FT(0e-6), stop = FT(25e-6), length = n_points) |
| 98 | + |
| 99 | +S_max_parcel_Nₗ = zeros(n_points) |
| 100 | +S_max_ARGmod_Nₗ = zeros(n_points) |
| 101 | +S_max_parcel_Nᵢ = zeros(n_points) |
| 102 | +S_max_ARGmod_Nᵢ = zeros(n_points) |
| 103 | +S_max_parcel_rₗ = zeros(n_points) |
| 104 | +S_max_ARGmod_rₗ = zeros(n_points) |
| 105 | +S_max_parcel_rᵢ = zeros(n_points) |
| 106 | +S_max_ARGmod_rᵢ = zeros(n_points) |
| 107 | +for i in 1:n_points |
| 108 | + S_max_parcel_Nₗ[i], S_max_ARGmod_Nₗ[i] = run_parcel_model.(Nₐ, Nₗ_range[i], FT(0), rₗ, rᵢ, w, FT) |
| 109 | + S_max_parcel_Nᵢ[i], S_max_ARGmod_Nᵢ[i] = run_parcel_model.(Nₐ, FT(0), Nᵢ_range[i], rₗ, rᵢ, w, FT) |
| 110 | + S_max_parcel_rₗ[i], S_max_ARGmod_rₗ[i] = run_parcel_model.(Nₐ, Nₗ, FT(0), rₗ_range[i], rᵢ, w, FT) |
| 111 | + S_max_parcel_rᵢ[i], S_max_ARGmod_rᵢ[i] = run_parcel_model.(Nₐ, FT(0), Nᵢ, rₗ, rᵢ_range[i], w, FT) |
| 112 | +end |
| 113 | + |
| 114 | +# Plot results |
| 115 | +fig = MK.Figure(size = (800, 600), fontsize = 20) |
| 116 | +ax1 = MK.Axis(fig[1, 1], ylabel = "S_max / S_max_ARG", xlabel = "Nₗ [cm⁻³]", title = "No ice particle, rₗ=20 μm") |
| 117 | +ax2 = MK.Axis(fig[1, 2], ylabel = "S_max / S_max_ARG", xlabel = "Nᵢ [cm⁻³]", title = "No liquid droplets, rᵢ=20 μm") |
| 118 | +ax3 = MK.Axis(fig[2, 1], ylabel = "S_max / S_max_ARG", xlabel = "rₗ [μm]", title = "No ice particle, Nₗ=100 cm⁻³") |
| 119 | +ax4 = MK.Axis(fig[2, 2], ylabel = "S_max / S_max_ARG", xlabel = "rᵢ [μm]", title = "No liquid droplets, Nᵢ=1 cm⁻³") |
| 120 | + |
| 121 | +MK.lines!(ax1, Nₗ_range * 1e-6, S_max_parcel_Nₗ, label = "Parcel", linewidth = 2, color = :blue) |
| 122 | +MK.lines!(ax1, Nₗ_range * 1e-6, S_max_ARGmod_Nₗ, label = "Modified ARG", linewidth = 2, color = :red) |
| 123 | +MK.lines!(ax2, Nᵢ_range * 1e-6, S_max_parcel_Nᵢ, label = "Parcel", linewidth = 2, color = :blue) |
| 124 | +MK.lines!(ax2, Nᵢ_range * 1e-6, S_max_ARGmod_Nᵢ, label = "Modified ARG", linewidth = 2, color = :red) |
| 125 | +MK.lines!(ax3, rₗ_range * 1e6, S_max_parcel_rₗ, label = "Parcel", linewidth = 2, color = :blue) |
| 126 | +MK.lines!(ax3, rₗ_range * 1e6, S_max_ARGmod_rₗ, label = "Modified ARG", linewidth = 2, color = :red) |
| 127 | +MK.lines!(ax4, rᵢ_range * 1e6, S_max_parcel_rᵢ, label = "Parcel", linewidth = 2, color = :blue) |
| 128 | +MK.lines!(ax4, rᵢ_range * 1e6, S_max_ARGmod_rᵢ, label = "Modified ARG", linewidth = 2, color = :red) |
| 129 | + |
| 130 | +MK.ylims!(ax1, -0.05, 1.1) |
| 131 | +MK.ylims!(ax3, -0.05, 1.1) |
| 132 | +MK.axislegend(ax1, framevisible = false, labelsize = 16, position = :rc) |
| 133 | +MK.axislegend(ax2, framevisible = false, labelsize = 16, position = :rc) |
| 134 | +MK.axislegend(ax3, framevisible = false, labelsize = 16, position = :rc) |
| 135 | +MK.axislegend(ax4, framevisible = false, labelsize = 16, position = :rc) |
| 136 | + |
| 137 | +MK.save("parcel_vs_modifiedARG_aerosol_activation.svg", fig) |
0 commit comments