PySDM.products.impl.product

logic around the PySDM.products.impl.product.Product - parent class for all products

  1"""
  2logic around the `PySDM.products.impl.product.Product` - parent class for all products
  3"""
  4
  5import inspect
  6from abc import abstractmethod
  7from typing import Optional
  8
  9import pint
 10
 11from PySDM.physics.constants import PPB, PPM, PPT
 12from PySDM.impl.camel_case import camel_case_to_words
 13
 14_UNIT_REGISTRY = pint.UnitRegistry()
 15
 16
 17class Product:
 18    def __init__(self, *, unit: str, name: Optional[str] = None):
 19        self.name = name or camel_case_to_words(self.__class__.__name__)
 20
 21        self._unit = self._parse_unit(unit)
 22        self.unit_magnitude_in_base_units = self._unit.to_base_units().magnitude
 23        self.__check_unit()
 24
 25        self.shape = None
 26        self.buffer = None
 27        self.particulator = None
 28        self.formulae = None
 29
 30    def register(self, builder):
 31        self.particulator = builder.particulator
 32        self.formulae = self.particulator.formulae
 33        self.shape = self.particulator.mesh.grid
 34
 35    def set_buffer(self, buffer):
 36        self.buffer = buffer
 37
 38    def _download_to_buffer(self, storage):
 39        storage.download(self.buffer.ravel())
 40
 41    @staticmethod
 42    def _parse_unit(unit: str):
 43        if unit in ("%", "percent"):
 44            return 0.01 * _UNIT_REGISTRY.dimensionless
 45        if unit in ("PPB", "ppb"):
 46            return PPB * _UNIT_REGISTRY.dimensionless
 47        if unit in ("PPM", "ppm"):
 48            return PPM * _UNIT_REGISTRY.dimensionless
 49        if unit in ("PPT", "ppt"):
 50            return PPT * _UNIT_REGISTRY.dimensionless
 51        return _UNIT_REGISTRY.parse_expression(unit)
 52
 53    def __check_unit(self):
 54        init = inspect.signature(self.__init__)
 55        if "unit" not in init.parameters:
 56            raise AssertionError(
 57                f"method __init__ of class {type(self).__name__}"
 58                f" is expected to have a unit parameter"
 59            )
 60
 61        default_unit_arg = init.parameters["unit"].default
 62
 63        if (
 64            default_unit_arg is inspect._empty
 65            or default_unit_arg is None
 66            or str(default_unit_arg).strip() == ""
 67        ):
 68            raise AssertionError(
 69                f"unit parameter of {type(self).__name__}.__init__"
 70                f" is expected to have a non-empty default value"
 71            )
 72
 73        default_unit = self._parse_unit(default_unit_arg)
 74
 75        if default_unit.to_base_units().magnitude != 1:
 76            raise AssertionError(
 77                f'default value "{default_unit_arg}"'
 78                f" of {type(self).__name__}.__init__() unit parameter"
 79                f" is not a base SI unit"
 80            )
 81
 82        if self._unit.dimensionality != default_unit.dimensionality:
 83            raise AssertionError(
 84                f"provided unit ({self._unit}) has different dimensionality"
 85                f" ({self._unit.dimensionality}) than the default one"
 86                f" ({default_unit.dimensionality})"
 87                f" for product {type(self).__name__}"
 88            )
 89
 90    @property
 91    def unit(self):
 92        return str(self._unit)
 93
 94    @abstractmethod
 95    def _impl(self, **kwargs):
 96        raise NotImplementedError()
 97
 98    def get(self, **kwargs):
 99        result = self._impl(**kwargs)
100        result /= self.unit_magnitude_in_base_units
101        return result
class Product:
 18class Product:
 19    def __init__(self, *, unit: str, name: Optional[str] = None):
 20        self.name = name or camel_case_to_words(self.__class__.__name__)
 21
 22        self._unit = self._parse_unit(unit)
 23        self.unit_magnitude_in_base_units = self._unit.to_base_units().magnitude
 24        self.__check_unit()
 25
 26        self.shape = None
 27        self.buffer = None
 28        self.particulator = None
 29        self.formulae = None
 30
 31    def register(self, builder):
 32        self.particulator = builder.particulator
 33        self.formulae = self.particulator.formulae
 34        self.shape = self.particulator.mesh.grid
 35
 36    def set_buffer(self, buffer):
 37        self.buffer = buffer
 38
 39    def _download_to_buffer(self, storage):
 40        storage.download(self.buffer.ravel())
 41
 42    @staticmethod
 43    def _parse_unit(unit: str):
 44        if unit in ("%", "percent"):
 45            return 0.01 * _UNIT_REGISTRY.dimensionless
 46        if unit in ("PPB", "ppb"):
 47            return PPB * _UNIT_REGISTRY.dimensionless
 48        if unit in ("PPM", "ppm"):
 49            return PPM * _UNIT_REGISTRY.dimensionless
 50        if unit in ("PPT", "ppt"):
 51            return PPT * _UNIT_REGISTRY.dimensionless
 52        return _UNIT_REGISTRY.parse_expression(unit)
 53
 54    def __check_unit(self):
 55        init = inspect.signature(self.__init__)
 56        if "unit" not in init.parameters:
 57            raise AssertionError(
 58                f"method __init__ of class {type(self).__name__}"
 59                f" is expected to have a unit parameter"
 60            )
 61
 62        default_unit_arg = init.parameters["unit"].default
 63
 64        if (
 65            default_unit_arg is inspect._empty
 66            or default_unit_arg is None
 67            or str(default_unit_arg).strip() == ""
 68        ):
 69            raise AssertionError(
 70                f"unit parameter of {type(self).__name__}.__init__"
 71                f" is expected to have a non-empty default value"
 72            )
 73
 74        default_unit = self._parse_unit(default_unit_arg)
 75
 76        if default_unit.to_base_units().magnitude != 1:
 77            raise AssertionError(
 78                f'default value "{default_unit_arg}"'
 79                f" of {type(self).__name__}.__init__() unit parameter"
 80                f" is not a base SI unit"
 81            )
 82
 83        if self._unit.dimensionality != default_unit.dimensionality:
 84            raise AssertionError(
 85                f"provided unit ({self._unit}) has different dimensionality"
 86                f" ({self._unit.dimensionality}) than the default one"
 87                f" ({default_unit.dimensionality})"
 88                f" for product {type(self).__name__}"
 89            )
 90
 91    @property
 92    def unit(self):
 93        return str(self._unit)
 94
 95    @abstractmethod
 96    def _impl(self, **kwargs):
 97        raise NotImplementedError()
 98
 99    def get(self, **kwargs):
100        result = self._impl(**kwargs)
101        result /= self.unit_magnitude_in_base_units
102        return result
Product(*, unit: str, name: Optional[str] = None)
19    def __init__(self, *, unit: str, name: Optional[str] = None):
20        self.name = name or camel_case_to_words(self.__class__.__name__)
21
22        self._unit = self._parse_unit(unit)
23        self.unit_magnitude_in_base_units = self._unit.to_base_units().magnitude
24        self.__check_unit()
25
26        self.shape = None
27        self.buffer = None
28        self.particulator = None
29        self.formulae = None
name
unit_magnitude_in_base_units
shape
buffer
particulator
formulae
def register(self, builder):
31    def register(self, builder):
32        self.particulator = builder.particulator
33        self.formulae = self.particulator.formulae
34        self.shape = self.particulator.mesh.grid
def set_buffer(self, buffer):
36    def set_buffer(self, buffer):
37        self.buffer = buffer
unit
91    @property
92    def unit(self):
93        return str(self._unit)
def get(self, **kwargs):
 99    def get(self, **kwargs):
100        result = self._impl(**kwargs)
101        result /= self.unit_magnitude_in_base_units
102        return result