11"""
2- CPU implementation of backend methods for freezing (singular and time-dependent immersion freezing)
2+ CPU implementation of backend methods for homogeneous freezing and
3+ heterogeneous freezing (singular and time-dependent immersion freezing)
34"""
45
56from functools import cached_property
1213from ...impl_common .freezing_attributes import (
1314 SingularAttributes ,
1415 TimeDependentAttributes ,
16+ TimeDependentHomogeneousAttributes ,
1517)
1618
1719
1820class FreezingMethods (BackendMethods ):
19- def __init__ (self ):
20- BackendMethods .__init__ (self )
21- unfrozen_and_saturated = self .formulae .trivia .unfrozen_and_saturated
22- frozen_and_above_freezing_point = (
23- self .formulae .trivia .frozen_and_above_freezing_point
24- )
25-
26- @numba .njit (** {** self .default_jit_flags , "parallel" : False })
27- def _freeze (water_mass , i ):
28- water_mass [i ] = - 1 * water_mass [i ]
21+ @cached_property
22+ def _freeze (self ):
23+ @numba .njit (** {** self .default_jit_flags , ** {"parallel" : False }})
24+ def body (signed_water_mass , i ):
25+ signed_water_mass [i ] = - 1 * signed_water_mass [i ]
2926 # TODO #599: change thd (latent heat)!
3027
31- @numba .njit (** {** self .default_jit_flags , "parallel" : False })
32- def _thaw (water_mass , i ):
33- water_mass [i ] = - 1 * water_mass [i ]
28+ return body
29+
30+ @cached_property
31+ def _thaw (self ):
32+ @numba .njit (** {** self .default_jit_flags , ** {"parallel" : False }})
33+ def body (signed_water_mass , i ):
34+ signed_water_mass [i ] = - 1 * signed_water_mass [i ]
3435 # TODO #599: change thd (latent heat)!
3536
37+ return body
38+
39+ @cached_property
40+ def _freeze_singular_body (self ):
41+ _thaw = self ._thaw
42+ _freeze = self ._freeze
43+ frozen_and_above_freezing_point = (
44+ self .formulae .trivia .frozen_and_above_freezing_point
45+ )
46+ unfrozen_and_saturated = self .formulae .trivia .unfrozen_and_saturated
47+
3648 @numba .njit (** self .default_jit_flags )
37- def freeze_singular_body (
38- attributes , temperature , relative_humidity , cell , thaw
39- ):
49+ def body (attributes , temperature , relative_humidity , cell , thaw ):
4050 n_sd = len (attributes .freezing_temperature )
4151 for i in numba .prange (n_sd ): # pylint: disable=not-an-iterable
4252 if attributes .freezing_temperature [i ] == 0 :
@@ -53,13 +63,21 @@ def freeze_singular_body(
5363 ):
5464 _freeze (attributes .signed_water_mass , i )
5565
56- self . freeze_singular_body = freeze_singular_body
66+ return body
5767
68+ @cached_property
69+ def _freeze_time_dependent_body (self ):
70+ _thaw = self ._thaw
71+ _freeze = self ._freeze
72+ frozen_and_above_freezing_point = (
73+ self .formulae .trivia .frozen_and_above_freezing_point
74+ )
75+ unfrozen_and_saturated = self .formulae .trivia .unfrozen_and_saturated
5876 j_het = self .formulae .heterogeneous_ice_nucleation_rate .j_het
5977 prob_zero_events = self .formulae .trivia .poissonian_avoidance_function
6078
6179 @numba .njit (** self .default_jit_flags )
62- def freeze_time_dependent_body ( # pylint: disable=too-many-arguments
80+ def body ( # pylint: disable=too-many-arguments
6381 rand ,
6482 attributes ,
6583 timestep ,
@@ -90,12 +108,69 @@ def freeze_time_dependent_body( # pylint: disable=too-many-arguments
90108 if rand [i ] < prob :
91109 _freeze (attributes .signed_water_mass , i )
92110
93- self .freeze_time_dependent_body = freeze_time_dependent_body
111+ return body
112+
113+ @cached_property
114+ def _freeze_time_dependent_homogeneous_body (self ):
115+ _thaw = self ._thaw
116+ _freeze = self ._freeze
117+ frozen_and_above_freezing_point = (
118+ self .formulae .trivia .frozen_and_above_freezing_point
119+ )
120+ unfrozen_and_ice_saturated = self .formulae .trivia .unfrozen_and_ice_saturated
121+ j_hom = self .formulae .homogeneous_ice_nucleation_rate .j_hom
122+ prob_zero_events = self .formulae .trivia .poissonian_avoidance_function
123+ d_a_w_ice_within_range = (
124+ self .formulae .homogeneous_ice_nucleation_rate .d_a_w_ice_within_range
125+ )
126+ d_a_w_ice_maximum = (
127+ self .formulae .homogeneous_ice_nucleation_rate .d_a_w_ice_maximum
128+ )
129+
130+ @numba .njit (** self .default_jit_flags )
131+ def body ( # pylint: disable=unused-argument,too-many-arguments
132+ rand ,
133+ attributes ,
134+ timestep ,
135+ cell ,
136+ a_w_ice ,
137+ temperature ,
138+ relative_humidity_ice ,
139+ thaw ,
140+ ):
141+
142+ n_sd = len (attributes .signed_water_mass )
143+ for i in numba .prange (n_sd ): # pylint: disable=not-an-iterable
144+ cell_id = cell [i ]
145+ if thaw and frozen_and_above_freezing_point (
146+ attributes .signed_water_mass [i ], temperature [cell_id ]
147+ ):
148+ _thaw (attributes .signed_water_mass , i )
149+ elif unfrozen_and_ice_saturated (
150+ attributes .signed_water_mass [i ], relative_humidity_ice [cell_id ]
151+ ):
152+ d_a_w_ice = (relative_humidity_ice [cell_id ] - 1.0 ) * a_w_ice [
153+ cell_id
154+ ]
155+
156+ if d_a_w_ice_within_range (d_a_w_ice ):
157+ d_a_w_ice = d_a_w_ice_maximum (d_a_w_ice )
158+ rate_assuming_constant_temperature_within_dt = (
159+ j_hom (temperature [cell_id ], d_a_w_ice )
160+ * attributes .volume [i ]
161+ )
162+ prob = 1 - prob_zero_events (
163+ r = rate_assuming_constant_temperature_within_dt , dt = timestep
164+ )
165+ if rand [i ] < prob :
166+ _freeze (attributes .signed_water_mass , i )
167+
168+ return body
94169
95170 def freeze_singular (
96171 self , * , attributes , temperature , relative_humidity , cell , thaw : bool
97172 ):
98- self .freeze_singular_body (
173+ self ._freeze_singular_body (
99174 SingularAttributes (
100175 freezing_temperature = attributes .freezing_temperature .data ,
101176 signed_water_mass = attributes .signed_water_mass .data ,
@@ -118,7 +193,7 @@ def freeze_time_dependent(
118193 relative_humidity ,
119194 thaw : bool ,
120195 ):
121- self .freeze_time_dependent_body (
196+ self ._freeze_time_dependent_body (
122197 rand .data ,
123198 TimeDependentAttributes (
124199 immersed_surface_area = attributes .immersed_surface_area .data ,
@@ -132,6 +207,32 @@ def freeze_time_dependent(
132207 thaw = thaw ,
133208 )
134209
210+ def freeze_time_dependent_homogeneous (
211+ self ,
212+ * ,
213+ rand ,
214+ attributes ,
215+ timestep ,
216+ cell ,
217+ a_w_ice ,
218+ temperature ,
219+ relative_humidity_ice ,
220+ thaw : bool ,
221+ ):
222+ self ._freeze_time_dependent_homogeneous_body (
223+ rand .data ,
224+ TimeDependentHomogeneousAttributes (
225+ volume = attributes .volume .data ,
226+ signed_water_mass = attributes .signed_water_mass .data ,
227+ ),
228+ timestep ,
229+ cell .data ,
230+ a_w_ice .data ,
231+ temperature .data ,
232+ relative_humidity_ice .data ,
233+ thaw = thaw ,
234+ )
235+
135236 @cached_property
136237 def _record_freezing_temperatures_body (self ):
137238 ff = self .formulae_flattened
0 commit comments