100100
101101"""
102102 bulk_microphysics_tendencies(
103- ::Microphysics1Moment,
104- mp,
105- tps,
106- ρ,
107- T,
108- q_tot,
109- q_lcl,
110- q_icl,
111- q_rai,
112- q_sno,
103+ ::Microphysics1Moment, mp, tps,
104+ ρ, T, q_tot, q_lcl, q_icl, q_rai, q_sno,
113105 )
114106
115107Compute all 1-moment microphysics tendencies in one fused call.
@@ -156,17 +148,8 @@ This is a pure function of local thermodynamic state, suitable for:
156148 Limiters depend on timestep `dt` and should be applied by the caller after computing tendencies.
157149"""
158150@inline function bulk_microphysics_tendencies (
159- :: Microphysics1Moment ,
160- mp:: CMP.Microphysics1MParams ,
161- tps,
162- ρ,
163- T,
164- q_tot,
165- q_lcl,
166- q_icl,
167- q_rai,
168- q_sno,
169- N_lcl = zero (ρ),
151+ :: Microphysics1Moment , mp:: CMP.Microphysics1MParams , tps,
152+ ρ, T, q_tot, q_lcl, q_icl, q_rai, q_sno, N_lcl = zero (ρ),
170153)
171154 # Clamp negative inputs to zero (robustness against numerical errors)
172155 ρ = UT. clamp_to_nonneg (ρ)
@@ -543,12 +526,8 @@ the second form uses the supersaturation threshold `S_0 * q_vap_sat`.
543526- Does NOT include geopotential (caller adds Φ for energy tendency)
544527"""
545528@inline function bulk_microphysics_tendencies (
546- :: Microphysics0Moment ,
547- mp:: CMP.Microphysics0MParams ,
548- tps,
549- T,
550- q_lcl,
551- q_icl,
529+ :: Microphysics0Moment , mp:: CMP.Microphysics0MParams , tps,
530+ T, q_lcl, q_icl,
552531)
553532 q_lcl = UT. clamp_to_nonneg (q_lcl)
554533 q_icl = UT. clamp_to_nonneg (q_icl)
@@ -598,7 +577,7 @@ Used by both warm-only and warm+ice dispatch methods to reduce code duplication.
598577- `dn_lcl_dt`: Cloud number tendency (1/kg/s)
599578- `dn_rai_dt`: Rain number tendency (1/kg/s)
600579"""
601- @inline function warm_rain_tendencies_2m (sb, q_lcl, q_rai, ρ, n_lcl, n_rai)
580+ @inline function warm_rain_tendencies_2m (sb, q_tot, q_lcl, q_rai, q_ice , ρ, n_lcl, n_rai)
602581 # Convert to number densities for CM2 functions
603582 N_lcl = ρ * n_lcl
604583 N_rai = ρ * n_rai
@@ -610,6 +589,17 @@ Used by both warm-only and warm+ice dispatch methods to reduce code duplication.
610589 dn_lcl_dt = zero (FT)
611590 dn_rai_dt = zero (FT)
612591
592+ # --- Condensation of vapor / evaporation of cloud liquid water ---
593+ ∂ₜq_lcl_cond = CMNonEq. conv_q_vap_to_q_lcl_icl_MM2015 (lcl, tps, q_tot, q_lcl, q_ice, q_rai, zero (q_ice), ρ, T)
594+ ∂ₜn_lcl_cond = zero (∂ₜq_lcl_cond) # neglect number change from condensation/evaporation
595+ dq_lcl_dt += ∂ₜq_lcl_cond
596+ dn_lcl_dt += ∂ₜn_lcl_cond
597+
598+ # --- Evaporation of rain ---
599+ evap = CM2. rain_evaporation (sb, aps, tps, q_tot, q_lcl, q_ice, q_rai, zero (q_ice), ρ, N_rai, T)
600+ dq_rai_dt += evap.∂ₜq_rai
601+ dn_rai_dt += evap.∂ₜρn_rai / ρ
602+
613603 # --- Autoconversion ---
614604 acnv = CM2. autoconversion (sb. acnv, sb. pdf_c, q_lcl, q_rai, ρ, N_lcl)
615605 dq_lcl_dt += acnv. dq_lcl_dt
@@ -635,6 +625,17 @@ Used by both warm-only and warm+ice dispatch methods to reduce code duplication.
635625 dn_rai_br = CM2. rain_breakup (sb. pdf_r, sb. brek, q_rai, ρ, N_rai, dn_rai_sc)
636626 dn_rai_dt += dn_rai_br / ρ
637627
628+ # --- Number adjustment for mass limits ---
629+ # Cloud liquid
630+ dn_lcl_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_c. xc_max, q_lcl, ρ, N_lcl)
631+ dn_lcl_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_c. xc_min, q_lcl, ρ, N_lcl)
632+ dn_lcl_dt += (dn_lcl_inc + dn_lcl_dec) / ρ
633+
634+ # Rain
635+ dn_rai_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_r. xr_max, q_rai, ρ, N_rai)
636+ dn_rai_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_r. xr_min, q_rai, ρ, N_rai)
637+ dn_rai_dt += (dn_rai_inc + dn_rai_dec) / ρ
638+
638639 return (; dq_lcl_dt, dq_rai_dt, dn_lcl_dt, dn_rai_dt)
639640end
640641
645646 bulk_microphysics_tendencies(
646647 ::Microphysics2Moment,
647648 mp::Microphysics2MParams{FT, WR, Nothing},
648- ...
649+ ρ, T, q_tot, q_lcl, n_lcl, q_rai, n_rai,
649650 )
650651
651652Compute 2-moment **warm rain only** microphysics tendencies (Seifert-Beheng 2006).
@@ -675,21 +676,9 @@ For warm rain + P3 ice, see the method that accepts `Microphysics2MParams{FT, WR
675676- `db_rim_dt`: Rime volume tendency (always zero for warm-only)
676677"""
677678@inline function bulk_microphysics_tendencies (
678- :: Microphysics2Moment ,
679- mp:: CMP.Microphysics2MParams{FT, WR, Nothing} ,
680- tps,
681- ρ,
682- T,
683- q_tot,
684- q_lcl,
685- n_lcl,
686- q_rai,
687- n_rai,
688- q_ice = zero (ρ),
689- n_ice = zero (ρ),
690- q_rim = zero (ρ),
691- b_rim = zero (ρ),
692- logλ = zero (ρ),
679+ :: Microphysics2Moment , mp:: CMP.Microphysics2MParams{FT, WR, Nothing} , tps,
680+ ρ, T, q_tot, q_lcl, n_lcl, q_rai, n_rai,
681+ q_ice = zero (ρ), n_ice = zero (ρ), q_rim = zero (ρ), b_rim = zero (ρ), logλ = zero (ρ),
693682) where {FT, WR}
694683 # Clamp negative inputs to zero (robustness against numerical errors)
695684 ρ = UT. clamp_to_nonneg (ρ)
@@ -705,48 +694,28 @@ For warm rain + P3 ice, see the method that accepts `Microphysics2MParams{FT, WR
705694
706695 # Unpack warm rain parameters
707696 sb = mp. warm_rain. seifert_beheng
708- aps = mp. warm_rain. air_properties
709697
710698 # Initialize ice-related tendencies (always zero for warm-only)
711699 dq_ice_dt = zero (ρ)
712700 dq_rim_dt = zero (ρ)
713701 db_rim_dt = zero (ρ)
714702
715703 # --- Core Warm Rain Processes (shared helper) ---
716- warm = warm_rain_tendencies_2m (sb, q_lcl, q_rai, ρ, n_lcl, n_rai)
704+ warm = warm_rain_tendencies_2m (sb, q_tot, q_lcl, q_rai, q_ice , ρ, n_lcl, n_rai)
717705 dq_lcl_dt = warm. dq_lcl_dt
718706 dn_lcl_dt = warm. dn_lcl_dt
719707 dq_rai_dt = warm. dq_rai_dt
720708 dn_rai_dt = warm. dn_rai_dt
721709
722- # Convert to number densities for remaining functions
723- N_lcl = ρ * n_lcl
724- N_rai = ρ * n_rai
725-
726- # --- Rain evaporation ---
727- evap = CM2. rain_evaporation (sb, aps, tps, zero (ρ), q_lcl, zero (ρ), q_rai, zero (ρ), ρ, N_rai, T)
728- dq_rai_dt += evap. evap_rate_1
729- dn_rai_dt += evap. evap_rate_0 / ρ
730-
731- # --- Number adjustment for mass limits ---
732- # Cloud liquid
733- dn_lcl_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_c. xc_max, q_lcl, ρ, N_lcl)
734- dn_lcl_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_c. xc_min, q_lcl, ρ, N_lcl)
735- dn_lcl_dt += (dn_lcl_inc + dn_lcl_dec) / ρ
736-
737- # Rain
738- dn_rai_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_r. xr_max, q_rai, ρ, N_rai)
739- dn_rai_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_r. xr_min, q_rai, ρ, N_rai)
740- dn_rai_dt += (dn_rai_inc + dn_rai_dec) / ρ
741-
742710 return (; dq_lcl_dt, dn_lcl_dt, dq_rai_dt, dn_rai_dt, dq_ice_dt, dq_rim_dt, db_rim_dt)
743711end
744712
745713"""
746714 bulk_microphysics_tendencies(
747715 ::Microphysics2Moment,
748716 mp::Microphysics2MParams{FT, WR, <:P3IceParams},
749- ...
717+ ρ, T, q_tot, q_lcl, n_lcl, q_rai, n_rai,
718+ q_ice, n_ice, q_rim, b_rim, logλ,
750719 )
751720
752721Compute 2-moment **warm rain + P3 ice** microphysics tendencies.
@@ -784,21 +753,9 @@ to be non-Nothing, eliminating runtime type checks and dynamic dispatch.
784753- `db_rim_dt`: Rime volume tendency (m³/kg/s)
785754"""
786755@inline function bulk_microphysics_tendencies (
787- :: Microphysics2Moment ,
788- mp:: CMP.Microphysics2MParams{FT, WR, ICE} ,
789- tps,
790- ρ,
791- T,
792- q_tot,
793- q_lcl,
794- n_lcl,
795- q_rai,
796- n_rai,
797- q_ice = zero (ρ),
798- n_ice = zero (ρ),
799- q_rim = zero (ρ),
800- b_rim = zero (ρ),
801- logλ = zero (ρ),
756+ :: Microphysics2Moment , mp:: CMP.Microphysics2MParams{FT, WR, ICE} , tps,
757+ ρ, T, q_tot, q_lcl, n_lcl, q_rai, n_rai,
758+ q_ice = zero (ρ), n_ice = zero (ρ), q_rim = zero (ρ), b_rim = zero (ρ), logλ = zero (ρ),
802759) where {FT, WR, ICE <: CMP.P3IceParams }
803760 # Clamp negative inputs to zero (robustness against numerical errors)
804761 ρ = UT. clamp_to_nonneg (ρ)
@@ -824,7 +781,7 @@ to be non-Nothing, eliminating runtime type checks and dynamic dispatch.
824781 db_rim_dt = zero (ρ)
825782
826783 # --- Core Warm Rain Processes (shared helper) ---
827- warm = warm_rain_tendencies_2m (sb, q_lcl, q_rai, ρ, n_lcl, n_rai)
784+ warm = warm_rain_tendencies_2m (sb, q_tot, q_lcl, q_rai, q_ice , ρ, n_lcl, n_rai)
828785 dq_lcl_dt = warm. dq_lcl_dt
829786 dn_lcl_dt = warm. dn_lcl_dt
830787 dq_rai_dt = warm. dq_rai_dt
@@ -834,26 +791,7 @@ to be non-Nothing, eliminating runtime type checks and dynamic dispatch.
834791 N_lcl = ρ * n_lcl
835792 N_rai = ρ * n_rai
836793
837- # --- Rain evaporation ---
838- evap = CM2. rain_evaporation (sb, aps, tps, zero (ρ), q_lcl, zero (ρ), q_rai, zero (ρ), ρ, N_rai, T)
839- dq_rai_dt += evap. evap_rate_1
840- dn_rai_dt += evap. evap_rate_0 / ρ
841-
842- # --- Number adjustment for mass limits ---
843- # Cloud liquid
844- dn_lcl_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_c. xc_max, q_lcl, ρ, N_lcl)
845- dn_lcl_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_c. xc_min, q_lcl, ρ, N_lcl)
846- dn_lcl_dt += (dn_lcl_inc + dn_lcl_dec) / ρ
847-
848- # Rain
849- dn_rai_inc = CM2. number_increase_for_mass_limit (sb. numadj, sb. pdf_r. xr_max, q_rai, ρ, N_rai)
850- dn_rai_dec = CM2. number_decrease_for_mass_limit (sb. numadj, sb. pdf_r. xr_min, q_rai, ρ, N_rai)
851- dn_rai_dt += (dn_rai_inc + dn_rai_dec) / ρ
852-
853794 # --- P3 Ice Processes ---
854- # NOTE: P3 uses gamma_inc_inv from SpecialFunctions which is NOT GPU-compatible
855- # (it uses string formatting for errors). We must keep if-branches to skip
856- # P3 code when there is no ice, otherwise GPU compilation fails.
857795 p3 = mp. ice. scheme
858796 vel = mp. ice. terminal_velocity
859797 pdf_c = mp. ice. cloud_pdf
0 commit comments