PySDM.products.size_spectral.effective_radius
effective radius of particles within a grid cell (ratio of third to second moments, optionally restricted to a given size range)
1""" 2effective radius of particles within a grid cell (ratio of third to second moments, 3 optionally restricted to a given size range) 4""" 5 6import numba 7import numpy as np 8 9from PySDM.backends.impl_numba.conf import JIT_FLAGS 10from PySDM.physics import constants as const 11from PySDM.products.impl import MomentProduct, register_product 12 13GEOM_FACTOR = const.PI_4_3 ** (-1 / 3) 14 15 16@register_product() 17class EffectiveRadius(MomentProduct): 18 def __init__(self, *, radius_range=None, unit="m", name=None): 19 super().__init__(name=name, unit=unit) 20 self.volume_range = None 21 self.radius_range = radius_range or (0, np.inf) 22 23 def register(self, builder): 24 super().register(builder) 25 self.volume_range = self.formulae.trivia.volume(np.asarray(self.radius_range)) 26 27 @staticmethod 28 @numba.njit(**JIT_FLAGS) 29 def nan_aware_reff_impl(input_volume_output_reff, volume_2_3): 30 """computes the effective radius (<r^3>/<r^2>) based on <v^(2/3)> and <v>""" 31 input_volume_output_reff[:] = np.where( 32 volume_2_3[:] > 0, 33 input_volume_output_reff[:] 34 * GEOM_FACTOR 35 / ( 36 volume_2_3[:] + (volume_2_3[:] == 0) 37 ), # (+ x==0) to avoid div-by-zero warnings 38 np.nan, 39 ) 40 41 def _impl(self, **kwargs): 42 tmp = np.empty_like(self.buffer) 43 self._download_moment_to_buffer( 44 attr="volume", 45 rank=2 / 3, 46 filter_range=self.volume_range, 47 filter_attr="volume", 48 ) 49 tmp[:] = self.buffer[:] 50 self._download_moment_to_buffer( 51 attr="volume", 52 rank=1, 53 filter_range=self.volume_range, 54 filter_attr="volume", 55 ) 56 EffectiveRadius.nan_aware_reff_impl( 57 input_volume_output_reff=self.buffer, volume_2_3=tmp 58 ) 59 return self.buffer
GEOM_FACTOR =
0.6203504908994001
17@register_product() 18class EffectiveRadius(MomentProduct): 19 def __init__(self, *, radius_range=None, unit="m", name=None): 20 super().__init__(name=name, unit=unit) 21 self.volume_range = None 22 self.radius_range = radius_range or (0, np.inf) 23 24 def register(self, builder): 25 super().register(builder) 26 self.volume_range = self.formulae.trivia.volume(np.asarray(self.radius_range)) 27 28 @staticmethod 29 @numba.njit(**JIT_FLAGS) 30 def nan_aware_reff_impl(input_volume_output_reff, volume_2_3): 31 """computes the effective radius (<r^3>/<r^2>) based on <v^(2/3)> and <v>""" 32 input_volume_output_reff[:] = np.where( 33 volume_2_3[:] > 0, 34 input_volume_output_reff[:] 35 * GEOM_FACTOR 36 / ( 37 volume_2_3[:] + (volume_2_3[:] == 0) 38 ), # (+ x==0) to avoid div-by-zero warnings 39 np.nan, 40 ) 41 42 def _impl(self, **kwargs): 43 tmp = np.empty_like(self.buffer) 44 self._download_moment_to_buffer( 45 attr="volume", 46 rank=2 / 3, 47 filter_range=self.volume_range, 48 filter_attr="volume", 49 ) 50 tmp[:] = self.buffer[:] 51 self._download_moment_to_buffer( 52 attr="volume", 53 rank=1, 54 filter_range=self.volume_range, 55 filter_attr="volume", 56 ) 57 EffectiveRadius.nan_aware_reff_impl( 58 input_volume_output_reff=self.buffer, volume_2_3=tmp 59 ) 60 return self.buffer
Helper class that provides a standard way to create an ABC using inheritance.
def
register(self, builder):
24 def register(self, builder): 25 super().register(builder) 26 self.volume_range = self.formulae.trivia.volume(np.asarray(self.radius_range))
Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
@staticmethod
@numba.njit(**JIT_FLAGS)
def
nan_aware_reff_impl(input_volume_output_reff, volume_2_3):
28 @staticmethod 29 @numba.njit(**JIT_FLAGS) 30 def nan_aware_reff_impl(input_volume_output_reff, volume_2_3): 31 """computes the effective radius (<r^3>/<r^2>) based on <v^(2/3)> and <v>""" 32 input_volume_output_reff[:] = np.where( 33 volume_2_3[:] > 0, 34 input_volume_output_reff[:] 35 * GEOM_FACTOR 36 / ( 37 volume_2_3[:] + (volume_2_3[:] == 0) 38 ), # (+ x==0) to avoid div-by-zero warnings 39 np.nan, 40 )
computes the effective radius (