From f3fa01fb482b894fa67d5b9e4ace8a730062e04c Mon Sep 17 00:00:00 2001 From: "github-merge-queue[bot]" Date: Fri, 1 Sep 2023 07:49:15 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20pdoc=20from=20@=20open-atmos/P?= =?UTF-8?q?ySDM@42f8485d4826c4bf8af6bd66794a97caa3f1a738=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PySDM/attributes/impl/derived_attribute.html | 1 + PySDM/attributes/impl/mapper.html | 4 + .../physics/equilibrium_supersaturation.html | 194 +++++++++++ PySDM/attributes/physics/index.html | 6 + .../frozen_particle_concentration.html | 8 +- .../freezing/ice_nuclei_concentration.html | 8 +- .../impl/activation_filtered_product.html | 89 +++++ .../products/impl/concentration_product.html | 13 +- PySDM/products/impl/index.html | 5 + PySDM/products/impl/moment_product.html | 3 + PySDM/products/size_spectral/index.html | 33 ++ PySDM/products/size_spectral/mean_radius.html | 38 +- .../size_spectral/mean_radius_activated.html | 138 ++++++++ .../size_spectral/mean_volume_radius.html | 137 ++++++++ .../size_spectral/particle_concentration.html | 8 +- .../particle_concentration_activated.html | 222 ++++++++++++ .../size_standard_deviation.html | 287 +++++++++++++++ .../total_particle_concentration.html | 4 +- ...total_particle_specific_concentration.html | 4 +- .../Grabowski_and_Pawlowska_2023/index.html | 78 +++++ .../settings.html | 326 ++++++++++++++++++ .../simulation.html | 323 +++++++++++++++++ .../Yang_et_al_2018/simulation.html | 149 ++++---- PySDM_examples/index.html | 5 + PySDM_examples/utils/basic_simulation.html | 1 + 25 files changed, 2012 insertions(+), 72 deletions(-) create mode 100644 PySDM/attributes/physics/equilibrium_supersaturation.html create mode 100644 PySDM/products/impl/activation_filtered_product.html create mode 100644 PySDM/products/size_spectral/mean_radius_activated.html create mode 100644 PySDM/products/size_spectral/mean_volume_radius.html create mode 100644 PySDM/products/size_spectral/particle_concentration_activated.html create mode 100644 PySDM/products/size_spectral/size_standard_deviation.html create mode 100644 PySDM_examples/Grabowski_and_Pawlowska_2023/index.html create mode 100644 PySDM_examples/Grabowski_and_Pawlowska_2023/settings.html create mode 100644 PySDM_examples/Grabowski_and_Pawlowska_2023/simulation.html diff --git a/PySDM/attributes/impl/derived_attribute.html b/PySDM/attributes/impl/derived_attribute.html index bb1a1b389..7094c8466 100644 --- a/PySDM/attributes/impl/derived_attribute.html +++ b/PySDM/attributes/impl/derived_attribute.html @@ -117,6 +117,7 @@

Subclasses

  • DryRadius
  • DryVolumeDynamic
  • OrganicFraction
  • +
  • EquilibriumSupersaturation
  • Kappa
  • Radius
  • RelativeFallVelocity
  • diff --git a/PySDM/attributes/impl/mapper.html b/PySDM/attributes/impl/mapper.html index b17590de0..64c321f02 100644 --- a/PySDM/attributes/impl/mapper.html +++ b/PySDM/attributes/impl/mapper.html @@ -61,6 +61,9 @@

    Module PySDM.attributes.impl.mapper

    DryVolumeOrganic, OrganicFraction, ) +from PySDM.attributes.physics.equilibrium_supersaturation import ( + EquilibriumSupersaturation, +) from PySDM.attributes.physics.hygroscopicity import Kappa, KappaTimesDryVolume from PySDM.attributes.physics.relative_fall_velocity import RelativeFallMomentum from PySDM.dynamics.impl.chemistry_utils import AQUEOUS_COMPOUNDS @@ -122,6 +125,7 @@

    Module PySDM.attributes.impl.mapper

    "freezing temperature": lambda _, __: FreezingTemperature, "immersed surface area": lambda _, __: ImmersedSurfaceArea, "critical supersaturation": lambda _, __: CriticalSupersaturation, + "equilibrium supersaturation": lambda _, __: EquilibriumSupersaturation, "wet to critical volume ratio": lambda _, __: WetToCriticalVolumeRatio, } diff --git a/PySDM/attributes/physics/equilibrium_supersaturation.html b/PySDM/attributes/physics/equilibrium_supersaturation.html new file mode 100644 index 000000000..9f7c77386 --- /dev/null +++ b/PySDM/attributes/physics/equilibrium_supersaturation.html @@ -0,0 +1,194 @@ + + + + + + +PySDM.attributes.physics.equilibrium_supersaturation API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.attributes.physics.equilibrium_supersaturation

    +
    +
    +

    kappa-Koehler equilibrium supersaturation calculated for actual environment temperature

    +
    + +Expand source code + +
    """
    +kappa-Koehler equilibrium supersaturation calculated for actual environment temperature
    +"""
    +from PySDM.attributes.impl.derived_attribute import DerivedAttribute
    +
    +
    +class EquilibriumSupersaturation(DerivedAttribute):
    +    def __init__(self, builder):
    +        self.r_wet = builder.get_attribute("radius")
    +        self.v_wet = builder.get_attribute("volume")
    +        self.v_dry = builder.get_attribute("dry volume")
    +        self.kappa = builder.get_attribute("kappa")
    +        self.f_org = builder.get_attribute("dry volume organic fraction")
    +
    +        super().__init__(
    +            builder=builder,
    +            name="equilibrium supersaturation",
    +            dependencies=(self.kappa, self.v_dry, self.f_org, self.r_wet),
    +        )
    +
    +    def recalculate(self):
    +        if len(self.particulator.environment["T"]) != 1:
    +            raise NotImplementedError()
    +        temperature = self.particulator.environment["T"][0]
    +        rd3 = self.v_dry.data.data / self.formulae.constants.PI_4_3
    +        sgm = self.formulae.surface_tension.sigma(
    +            temperature,
    +            self.v_wet.data.data,
    +            self.v_dry.data.data,
    +            self.f_org.data.data,
    +        )
    +
    +        self.data.data[:] = self.formulae.hygroscopicity.RH_eq(
    +            self.r_wet.data.data,
    +            T=temperature,
    +            kp=self.kappa.data.data,
    +            rd3=rd3,
    +            sgm=sgm,
    +        )
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class EquilibriumSupersaturation +(builder) +
    +
    +
    +
    + +Expand source code + +
    class EquilibriumSupersaturation(DerivedAttribute):
    +    def __init__(self, builder):
    +        self.r_wet = builder.get_attribute("radius")
    +        self.v_wet = builder.get_attribute("volume")
    +        self.v_dry = builder.get_attribute("dry volume")
    +        self.kappa = builder.get_attribute("kappa")
    +        self.f_org = builder.get_attribute("dry volume organic fraction")
    +
    +        super().__init__(
    +            builder=builder,
    +            name="equilibrium supersaturation",
    +            dependencies=(self.kappa, self.v_dry, self.f_org, self.r_wet),
    +        )
    +
    +    def recalculate(self):
    +        if len(self.particulator.environment["T"]) != 1:
    +            raise NotImplementedError()
    +        temperature = self.particulator.environment["T"][0]
    +        rd3 = self.v_dry.data.data / self.formulae.constants.PI_4_3
    +        sgm = self.formulae.surface_tension.sigma(
    +            temperature,
    +            self.v_wet.data.data,
    +            self.v_dry.data.data,
    +            self.f_org.data.data,
    +        )
    +
    +        self.data.data[:] = self.formulae.hygroscopicity.RH_eq(
    +            self.r_wet.data.data,
    +            T=temperature,
    +            kp=self.kappa.data.data,
    +            rd3=rd3,
    +            sgm=sgm,
    +        )
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def recalculate(self) +
    +
    +
    +
    + +Expand source code + +
    def recalculate(self):
    +    if len(self.particulator.environment["T"]) != 1:
    +        raise NotImplementedError()
    +    temperature = self.particulator.environment["T"][0]
    +    rd3 = self.v_dry.data.data / self.formulae.constants.PI_4_3
    +    sgm = self.formulae.surface_tension.sigma(
    +        temperature,
    +        self.v_wet.data.data,
    +        self.v_dry.data.data,
    +        self.f_org.data.data,
    +    )
    +
    +    self.data.data[:] = self.formulae.hygroscopicity.RH_eq(
    +        self.r_wet.data.data,
    +        T=temperature,
    +        kp=self.kappa.data.data,
    +        rd3=rd3,
    +        sgm=sgm,
    +    )
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/attributes/physics/index.html b/PySDM/attributes/physics/index.html index 5763a5efc..c6926e7f3 100644 --- a/PySDM/attributes/physics/index.html +++ b/PySDM/attributes/physics/index.html @@ -35,6 +35,7 @@

    Module PySDM.attributes.physics

    from .critical_volume import CriticalVolume, WetToCriticalVolumeRatio from .dry_radius import DryRadius from .dry_volume import DryVolume +from .equilibrium_supersaturation import EquilibriumSupersaturation from .heat import Heat from .multiplicities import Multiplicities from .radius import Radius @@ -67,6 +68,10 @@

    Sub-modules

    particle dry volume (subject to evolution due to collisions or aqueous chemistry)

    +
    PySDM.attributes.physics.equilibrium_supersaturation
    +
    +

    kappa-Koehler equilibrium supersaturation calculated for actual environment temperature

    +
    PySDM.attributes.physics.heat

    particle heat content (test-use only for now, exemplifying intensive/extensive attribute logic)

    @@ -131,6 +136,7 @@

    Index

  • PySDM.attributes.physics.critical_volume
  • PySDM.attributes.physics.dry_radius
  • PySDM.attributes.physics.dry_volume
  • +
  • PySDM.attributes.physics.equilibrium_supersaturation
  • PySDM.attributes.physics.heat
  • PySDM.attributes.physics.hygroscopicity
  • PySDM.attributes.physics.multiplicities
  • diff --git a/PySDM/products/freezing/frozen_particle_concentration.html b/PySDM/products/freezing/frozen_particle_concentration.html index ee607971f..5ed7b724f 100644 --- a/PySDM/products/freezing/frozen_particle_concentration.html +++ b/PySDM/products/freezing/frozen_particle_concentration.html @@ -93,7 +93,9 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code @@ -155,7 +157,9 @@

    Inherited members

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code diff --git a/PySDM/products/freezing/ice_nuclei_concentration.html b/PySDM/products/freezing/ice_nuclei_concentration.html index f2433e88f..5babe7cec 100644 --- a/PySDM/products/freezing/ice_nuclei_concentration.html +++ b/PySDM/products/freezing/ice_nuclei_concentration.html @@ -82,7 +82,9 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code @@ -139,7 +141,9 @@

    Inherited members

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code diff --git a/PySDM/products/impl/activation_filtered_product.html b/PySDM/products/impl/activation_filtered_product.html new file mode 100644 index 000000000..81d9d80e5 --- /dev/null +++ b/PySDM/products/impl/activation_filtered_product.html @@ -0,0 +1,89 @@ + + + + + + +PySDM.products.impl.activation_filtered_product API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.products.impl.activation_filtered_product

    +
    +
    +

    common base class for products filtering droplets based on their activation state

    +
    + +Expand source code + +
    """
    +common base class for products filtering droplets based on their activation state
    +"""
    +import numpy as np
    +
    +
    +class _ActivationFilteredProduct:
    +    def __init__(
    +        self,
    +        *,
    +        count_unactivated: bool,
    +        count_activated: bool,
    +    ):
    +        self.__filter_attr = "wet to critical volume ratio"
    +        self.__filter_range = [0, np.inf]
    +        if not count_activated:
    +            self.__filter_range[1] = 1
    +        if not count_unactivated:
    +            self.__filter_range[0] = 1
    +
    +    def impl(self, *, attr, rank):
    +        getattr(self, "_download_moment_to_buffer")(
    +            attr=attr,
    +            rank=rank,
    +            filter_attr=self.__filter_attr,
    +            filter_range=self.__filter_range,
    +        )
    +
    +    def register(self, builder):
    +        builder.request_attribute(self.__filter_attr)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/products/impl/concentration_product.html b/PySDM/products/impl/concentration_product.html index 24ffbf260..ccdf843e4 100644 --- a/PySDM/products/impl/concentration_product.html +++ b/PySDM/products/impl/concentration_product.html @@ -39,6 +39,10 @@

    Module PySDM.products.impl.concentration_product< class ConcentrationProduct(MomentProduct): def __init__(self, *, unit: str, name: str, specific: bool, stp: bool): + """ + `stp` toggles expressing the concentration in terms of standard temperature + and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity) + """ super().__init__(unit=unit, name=name) self.specific = specific self.stp = stp @@ -84,13 +88,19 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code
    class ConcentrationProduct(MomentProduct):
         def __init__(self, *, unit: str, name: str, specific: bool, stp: bool):
    +        """
    +        `stp` toggles expressing the concentration in terms of standard temperature
    +        and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)
    +        """
             super().__init__(unit=unit, name=name)
             self.specific = specific
             self.stp = stp
    @@ -131,6 +141,7 @@ 

    Subclasses

  • FrozenParticleConcentration
  • IceNucleiConcentration
  • ParticleConcentration
  • +
  • ActivatedParticleConcentration
  • TotalParticleConcentration
  • TotalParticleSpecificConcentration
  • diff --git a/PySDM/products/impl/index.html b/PySDM/products/impl/index.html index e8525293d..647b1f36d 100644 --- a/PySDM/products/impl/index.html +++ b/PySDM/products/impl/index.html @@ -38,6 +38,10 @@

    Module PySDM.products.impl

    Sub-modules

    +
    PySDM.products.impl.activation_filtered_product
    +
    +

    common base class for products filtering droplets based on their activation state

    +
    PySDM.products.impl.concentration_product

    common code for products computing particle concentrations with @@ -86,6 +90,7 @@

    Index

  • Sub-modules

    Methods

    diff --git a/PySDM/products/size_spectral/index.html b/PySDM/products/size_spectral/index.html index 3145baa3b..ed69c0139 100644 --- a/PySDM/products/size_spectral/index.html +++ b/PySDM/products/size_spectral/index.html @@ -36,8 +36,14 @@

    Module PySDM.products.size_spectral

    ) from .effective_radius import EffectiveRadius from .mean_radius import MeanRadius +from .mean_radius_activated import ActivatedMeanRadius +from .mean_volume_radius import MeanVolumeRadius from .number_size_spectrum import NumberSizeSpectrum from .particle_concentration import ParticleConcentration, ParticleSpecificConcentration +from .particle_concentration_activated import ( + ActivatedParticleConcentration, + ActivatedParticleSpecificConcentration, +) from .particle_size_spectrum import ( ParticleSizeSpectrumPerMass, ParticleSizeSpectrumPerVolume, @@ -48,6 +54,11 @@

    Module PySDM.products.size_spectral

    from .radius_binned_number_averaged_terminal_velocity import ( RadiusBinnedNumberAveragedTerminalVelocity, ) +from .size_standard_deviation import ( + AreaStandardDeviation, + RadiusStandardDeviation, + VolumeStandardDeviation, +) from .total_particle_concentration import TotalParticleConcentration from .total_particle_specific_concentration import TotalParticleSpecificConcentration from .water_mixing_ratio import WaterMixingRatio
  • @@ -69,6 +80,14 @@

    Sub-modules

    mean radius of particles within a grid cell (optionally restricted to a given size range)

    +
    PySDM.products.size_spectral.mean_radius_activated
    +
    +

    mean radius of particles within a grid cell, for activated, unactivated or both

    +
    +
    PySDM.products.size_spectral.mean_volume_radius
    +
    +

    mean volume radius of particles within a grid cell, for activated, unactivated or both

    +
    PySDM.products.size_spectral.number_size_spectrum

    n(V) particle volume spectrum per volume of air, @@ -79,6 +98,11 @@

    Sub-modules

    concentration of particles within a grid cell (either per-volume of per-mass-of-dry air, optionally restricted to a given size range)

    +
    PySDM.products.size_spectral.particle_concentration_activated
    +
    +

    concentration of particles within a grid cell (either per-volume of per-mass-of-dry air), +activated, unactivated or both

    +
    PySDM.products.size_spectral.particle_size_spectrum

    wet radius-binned particle size spectra (per mass of dry air or per volume of air)

    @@ -92,6 +116,11 @@

    Sub-modules

    Provides radius bin-resolved average terminal velocity (average is particle-number weighted)

    +
    PySDM.products.size_spectral.size_standard_deviation
    +
    +

    standard deviation of radius/area/volume of particles within a grid cell, +for activated, unactivated or both

    +
    PySDM.products.size_spectral.total_particle_concentration

    particle concentration (per volume of air)

    @@ -130,11 +159,15 @@

    Index

  • PySDM.products.size_spectral.arbitrary_moment
  • PySDM.products.size_spectral.effective_radius
  • PySDM.products.size_spectral.mean_radius
  • +
  • PySDM.products.size_spectral.mean_radius_activated
  • +
  • PySDM.products.size_spectral.mean_volume_radius
  • PySDM.products.size_spectral.number_size_spectrum
  • PySDM.products.size_spectral.particle_concentration
  • +
  • PySDM.products.size_spectral.particle_concentration_activated
  • PySDM.products.size_spectral.particle_size_spectrum
  • PySDM.products.size_spectral.particle_volume_versus_radius_logarithm_spectrum
  • PySDM.products.size_spectral.radius_binned_number_averaged_terminal_velocity
  • +
  • PySDM.products.size_spectral.size_standard_deviation
  • PySDM.products.size_spectral.total_particle_concentration
  • PySDM.products.size_spectral.total_particle_specific_concentration
  • PySDM.products.size_spectral.water_mixing_ratio
  • diff --git a/PySDM/products/size_spectral/mean_radius.html b/PySDM/products/size_spectral/mean_radius.html index 5080e4922..4ded1e556 100644 --- a/PySDM/products/size_spectral/mean_radius.html +++ b/PySDM/products/size_spectral/mean_radius.html @@ -30,15 +30,30 @@

    Module PySDM.products.size_spectral.mean_radius""" mean radius of particles within a grid cell (optionally restricted to a given size range) """ +import numpy as np + from PySDM.products.impl.moment_product import MomentProduct class MeanRadius(MomentProduct): - def __init__(self, name=None, unit="m"): + def __init__( + self, + name=None, + unit="m", + radius_range=(0, np.inf), + ): + self.radius_range = radius_range super().__init__(name=name, unit=unit) def _impl(self, **kwargs): - self._download_moment_to_buffer(attr="volume", rank=1 / 3) + self._download_moment_to_buffer( + attr="volume", + rank=1 / 3, + filter_range=( + self.formulae.trivia.volume(self.radius_range[0]), + self.formulae.trivia.volume(self.radius_range[1]), + ), + ) self.buffer[:] /= self.formulae.constants.PI_4_3 ** (1 / 3) return self.buffer

    @@ -54,7 +69,7 @@

    Classes

    class MeanRadius -(name=None, unit='m') +(name=None, unit='m', radius_range=(0, inf))

    Helper class that provides a standard way to create an ABC using @@ -64,11 +79,24 @@

    Classes

    Expand source code
    class MeanRadius(MomentProduct):
    -    def __init__(self, name=None, unit="m"):
    +    def __init__(
    +        self,
    +        name=None,
    +        unit="m",
    +        radius_range=(0, np.inf),
    +    ):
    +        self.radius_range = radius_range
             super().__init__(name=name, unit=unit)
     
         def _impl(self, **kwargs):
    -        self._download_moment_to_buffer(attr="volume", rank=1 / 3)
    +        self._download_moment_to_buffer(
    +            attr="volume",
    +            rank=1 / 3,
    +            filter_range=(
    +                self.formulae.trivia.volume(self.radius_range[0]),
    +                self.formulae.trivia.volume(self.radius_range[1]),
    +            ),
    +        )
             self.buffer[:] /= self.formulae.constants.PI_4_3 ** (1 / 3)
             return self.buffer
    diff --git a/PySDM/products/size_spectral/mean_radius_activated.html b/PySDM/products/size_spectral/mean_radius_activated.html new file mode 100644 index 000000000..ae0be79f9 --- /dev/null +++ b/PySDM/products/size_spectral/mean_radius_activated.html @@ -0,0 +1,138 @@ + + + + + + +PySDM.products.size_spectral.mean_radius_activated API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.products.size_spectral.mean_radius_activated

    +
    +
    +

    mean radius of particles within a grid cell, for activated, unactivated or both

    +
    + +Expand source code + +
    """
    +mean radius of particles within a grid cell, for activated, unactivated or both
    +"""
    +from PySDM.products.impl.activation_filtered_product import _ActivationFilteredProduct
    +from PySDM.products.impl.moment_product import MomentProduct
    +
    +
    +class ActivatedMeanRadius(MomentProduct, _ActivationFilteredProduct):
    +    def __init__(
    +        self, count_unactivated: bool, count_activated: bool, name=None, unit="m"
    +    ):
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=1 / 3)
    +        self.buffer[:] /= self.formulae.constants.PI_4_3 ** (1 / 3)
    +        return self.buffer
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class ActivatedMeanRadius +(count_unactivated: bool, count_activated: bool, name=None, unit='m') +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +
    + +Expand source code + +
    class ActivatedMeanRadius(MomentProduct, _ActivationFilteredProduct):
    +    def __init__(
    +        self, count_unactivated: bool, count_activated: bool, name=None, unit="m"
    +    ):
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=1 / 3)
    +        self.buffer[:] /= self.formulae.constants.PI_4_3 ** (1 / 3)
    +        return self.buffer
    +
    +

    Ancestors

    +
      +
    • MomentProduct
    • +
    • Product
    • +
    • abc.ABC
    • +
    • PySDM.products.impl.activation_filtered_product._ActivationFilteredProduct
    • +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/products/size_spectral/mean_volume_radius.html b/PySDM/products/size_spectral/mean_volume_radius.html new file mode 100644 index 000000000..8c29105dc --- /dev/null +++ b/PySDM/products/size_spectral/mean_volume_radius.html @@ -0,0 +1,137 @@ + + + + + + +PySDM.products.size_spectral.mean_volume_radius API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.products.size_spectral.mean_volume_radius

    +
    +
    +

    mean volume radius of particles within a grid cell, for activated, unactivated or both

    +
    + +Expand source code + +
    """
    +mean volume radius of particles within a grid cell, for activated, unactivated or both
    +"""
    +
    +from PySDM.products.impl.activation_filtered_product import _ActivationFilteredProduct
    +from PySDM.products.impl.moment_product import MomentProduct
    +
    +
    +class MeanVolumeRadius(MomentProduct, _ActivationFilteredProduct):
    +    def __init__(
    +        self, count_unactivated: bool, count_activated: bool, name=None, unit="m"
    +    ):
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=1)
    +        return self.formulae.trivia.radius(self.buffer[:])
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class MeanVolumeRadius +(count_unactivated: bool, count_activated: bool, name=None, unit='m') +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +
    + +Expand source code + +
    class MeanVolumeRadius(MomentProduct, _ActivationFilteredProduct):
    +    def __init__(
    +        self, count_unactivated: bool, count_activated: bool, name=None, unit="m"
    +    ):
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=1)
    +        return self.formulae.trivia.radius(self.buffer[:])
    +
    +

    Ancestors

    +
      +
    • MomentProduct
    • +
    • Product
    • +
    • abc.ABC
    • +
    • PySDM.products.impl.activation_filtered_product._ActivationFilteredProduct
    • +
    +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/products/size_spectral/particle_concentration.html b/PySDM/products/size_spectral/particle_concentration.html index d30e02a9d..d390753ce 100644 --- a/PySDM/products/size_spectral/particle_concentration.html +++ b/PySDM/products/size_spectral/particle_concentration.html @@ -83,7 +83,9 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code @@ -138,7 +140,9 @@

    Inherited members

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code diff --git a/PySDM/products/size_spectral/particle_concentration_activated.html b/PySDM/products/size_spectral/particle_concentration_activated.html new file mode 100644 index 000000000..25987cc9c --- /dev/null +++ b/PySDM/products/size_spectral/particle_concentration_activated.html @@ -0,0 +1,222 @@ + + + + + + +PySDM.products.size_spectral.particle_concentration_activated API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.products.size_spectral.particle_concentration_activated

    +
    +
    +

    concentration of particles within a grid cell (either per-volume of per-mass-of-dry air), +activated, unactivated or both

    +
    + +Expand source code + +
    """
    +concentration of particles within a grid cell (either per-volume of per-mass-of-dry air),
    + activated, unactivated or both
    +"""
    +
    +from PySDM.products.impl.activation_filtered_product import _ActivationFilteredProduct
    +from PySDM.products.impl.concentration_product import ConcentrationProduct
    +
    +
    +class ActivatedParticleConcentration(ConcentrationProduct, _ActivationFilteredProduct):
    +    # pylint: disable=too-many-arguments
    +    def __init__(
    +        self,
    +        *,
    +        count_unactivated: bool,
    +        count_activated: bool,
    +        specific=False,
    +        stp=False,
    +        name=None,
    +        unit="m^-3",
    +    ):
    +        ConcentrationProduct.__init__(
    +            self, name=name, unit=unit, specific=specific, stp=stp
    +        )
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, ConcentrationProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=0)
    +        return ConcentrationProduct._impl(self, **kwargs)
    +
    +
    +class ActivatedParticleSpecificConcentration(ActivatedParticleConcentration):
    +    def __init__(self, count_unactivated, count_activated, name=None, unit="kg^-1"):
    +        super().__init__(
    +            count_unactivated=count_unactivated,
    +            count_activated=count_activated,
    +            specific=True,
    +            name=name,
    +            unit=unit,
    +        )
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class ActivatedParticleConcentration +(*, count_unactivated: bool, count_activated: bool, specific=False, stp=False, name=None, unit='m^-3') +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    +
    + +Expand source code + +
    class ActivatedParticleConcentration(ConcentrationProduct, _ActivationFilteredProduct):
    +    # pylint: disable=too-many-arguments
    +    def __init__(
    +        self,
    +        *,
    +        count_unactivated: bool,
    +        count_activated: bool,
    +        specific=False,
    +        stp=False,
    +        name=None,
    +        unit="m^-3",
    +    ):
    +        ConcentrationProduct.__init__(
    +            self, name=name, unit=unit, specific=specific, stp=stp
    +        )
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        for base_class in (_ActivationFilteredProduct, ConcentrationProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr="volume", rank=0)
    +        return ConcentrationProduct._impl(self, **kwargs)
    +
    +

    Ancestors

    + +

    Subclasses

    + +

    Inherited members

    + +
    +
    +class ActivatedParticleSpecificConcentration +(count_unactivated, count_activated, name=None, unit='kg^-1') +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    +
    + +Expand source code + +
    class ActivatedParticleSpecificConcentration(ActivatedParticleConcentration):
    +    def __init__(self, count_unactivated, count_activated, name=None, unit="kg^-1"):
    +        super().__init__(
    +            count_unactivated=count_unactivated,
    +            count_activated=count_activated,
    +            specific=True,
    +            name=name,
    +            unit=unit,
    +        )
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/products/size_spectral/size_standard_deviation.html b/PySDM/products/size_spectral/size_standard_deviation.html new file mode 100644 index 000000000..ca14b5e27 --- /dev/null +++ b/PySDM/products/size_spectral/size_standard_deviation.html @@ -0,0 +1,287 @@ + + + + + + +PySDM.products.size_spectral.size_standard_deviation API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM.products.size_spectral.size_standard_deviation

    +
    +
    +

    standard deviation of radius/area/volume of particles within a grid cell, +for activated, unactivated or both

    +
    + +Expand source code + +
    """
    +standard deviation of radius/area/volume of particles within a grid cell,
    +for activated, unactivated or both
    +"""
    +import numpy as np
    +
    +from PySDM.products.impl.activation_filtered_product import _ActivationFilteredProduct
    +from PySDM.products.impl.moment_product import MomentProduct
    +
    +
    +class _SizeStandardDeviation(MomentProduct, _ActivationFilteredProduct):
    +    # pylint: disable=too-many-arguments
    +    def __init__(
    +        self,
    +        count_unactivated: bool,
    +        count_activated: bool,
    +        name=None,
    +        unit="m",
    +        attr="radius",
    +    ):
    +        self.attr = attr
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        builder.request_attribute(self.attr)
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr=self.attr, rank=1)
    +        tmp = np.empty_like(self.buffer)
    +        tmp[:] = -self.buffer**2
    +        _ActivationFilteredProduct.impl(self, attr=self.attr, rank=2)
    +        tmp[:] += self.buffer
    +        tmp[:] = np.sqrt(tmp)
    +        return tmp
    +
    +
    +RadiusStandardDeviation = _SizeStandardDeviation
    +
    +
    +class AreaStandardDeviation(_SizeStandardDeviation):
    +    def __init__(
    +        self, *, name=None, unit="m^2", count_activated: bool, count_unactivated: bool
    +    ):
    +        super().__init__(
    +            name=name,
    +            unit=unit,
    +            count_activated=count_activated,
    +            count_unactivated=count_unactivated,
    +            attr="area",
    +        )
    +
    +
    +class VolumeStandardDeviation(_SizeStandardDeviation):
    +    def __init__(
    +        self, *, name=None, unit="m^3", count_activated: bool, count_unactivated: bool
    +    ):
    +        super().__init__(
    +            name=name,
    +            unit=unit,
    +            count_activated=count_activated,
    +            count_unactivated=count_unactivated,
    +            attr="volume",
    +        )
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class AreaStandardDeviation +(*, name=None, unit='m^2', count_activated: bool, count_unactivated: bool) +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +
    + +Expand source code + +
    class AreaStandardDeviation(_SizeStandardDeviation):
    +    def __init__(
    +        self, *, name=None, unit="m^2", count_activated: bool, count_unactivated: bool
    +    ):
    +        super().__init__(
    +            name=name,
    +            unit=unit,
    +            count_activated=count_activated,
    +            count_unactivated=count_unactivated,
    +            attr="area",
    +        )
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +class VolumeStandardDeviation +(*, name=None, unit='m^3', count_activated: bool, count_unactivated: bool) +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +
    + +Expand source code + +
    class VolumeStandardDeviation(_SizeStandardDeviation):
    +    def __init__(
    +        self, *, name=None, unit="m^3", count_activated: bool, count_unactivated: bool
    +    ):
    +        super().__init__(
    +            name=name,
    +            unit=unit,
    +            count_activated=count_activated,
    +            count_unactivated=count_unactivated,
    +            attr="volume",
    +        )
    +
    +

    Ancestors

    + +

    Inherited members

    + +
    +
    +class RadiusStandardDeviation +(count_unactivated: bool, count_activated: bool, name=None, unit='m', attr='radius') +
    +
    +

    Helper class that provides a standard way to create an ABC using +inheritance.

    +
    + +Expand source code + +
    class _SizeStandardDeviation(MomentProduct, _ActivationFilteredProduct):
    +    # pylint: disable=too-many-arguments
    +    def __init__(
    +        self,
    +        count_unactivated: bool,
    +        count_activated: bool,
    +        name=None,
    +        unit="m",
    +        attr="radius",
    +    ):
    +        self.attr = attr
    +        MomentProduct.__init__(self, name=name, unit=unit)
    +        _ActivationFilteredProduct.__init__(
    +            self, count_activated=count_activated, count_unactivated=count_unactivated
    +        )
    +
    +    def register(self, builder):
    +        builder.request_attribute(self.attr)
    +        for base_class in (_ActivationFilteredProduct, MomentProduct):
    +            base_class.register(self, builder)
    +
    +    def _impl(self, **kwargs):
    +        _ActivationFilteredProduct.impl(self, attr=self.attr, rank=1)
    +        tmp = np.empty_like(self.buffer)
    +        tmp[:] = -self.buffer**2
    +        _ActivationFilteredProduct.impl(self, attr=self.attr, rank=2)
    +        tmp[:] += self.buffer
    +        tmp[:] = np.sqrt(tmp)
    +        return tmp
    +
    +

    Ancestors

    +
      +
    • MomentProduct
    • +
    • Product
    • +
    • abc.ABC
    • +
    • PySDM.products.impl.activation_filtered_product._ActivationFilteredProduct
    • +
    +

    Subclasses

    + +

    Inherited members

    + +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM/products/size_spectral/total_particle_concentration.html b/PySDM/products/size_spectral/total_particle_concentration.html index f6afe66f9..9c507c0e6 100644 --- a/PySDM/products/size_spectral/total_particle_concentration.html +++ b/PySDM/products/size_spectral/total_particle_concentration.html @@ -57,7 +57,9 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code diff --git a/PySDM/products/size_spectral/total_particle_specific_concentration.html b/PySDM/products/size_spectral/total_particle_specific_concentration.html index 025dd0776..a574cd640 100644 --- a/PySDM/products/size_spectral/total_particle_specific_concentration.html +++ b/PySDM/products/size_spectral/total_particle_specific_concentration.html @@ -57,7 +57,9 @@

    Classes

    Helper class that provides a standard way to create an ABC using -inheritance.

    +inheritance.

    +

    stp toggles expressing the concentration in terms of standard temperature +and pressure conditions (ground level of the ICAO standard atmosphere, zero humidity)

    Expand source code diff --git a/PySDM_examples/Grabowski_and_Pawlowska_2023/index.html b/PySDM_examples/Grabowski_and_Pawlowska_2023/index.html new file mode 100644 index 000000000..096b8f401 --- /dev/null +++ b/PySDM_examples/Grabowski_and_Pawlowska_2023/index.html @@ -0,0 +1,78 @@ + + + + + + +PySDM_examples.Grabowski_and_Pawlowska_2023 API documentation + + + + + + + + + + + +
    + + +
    + + + \ No newline at end of file diff --git a/PySDM_examples/Grabowski_and_Pawlowska_2023/settings.html b/PySDM_examples/Grabowski_and_Pawlowska_2023/settings.html new file mode 100644 index 000000000..a6eb95ca0 --- /dev/null +++ b/PySDM_examples/Grabowski_and_Pawlowska_2023/settings.html @@ -0,0 +1,326 @@ + + + + + + +PySDM_examples.Grabowski_and_Pawlowska_2023.settings API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM_examples.Grabowski_and_Pawlowska_2023.settings

    +
    +
    +
    + +Expand source code + +
    import numpy as np
    +from pystrict import strict
    +
    +from PySDM import Formulae
    +from PySDM.initialisation.spectra import Lognormal, Sum
    +from PySDM.physics import si
    +
    +
    +@strict
    +class Settings:
    +    def __init__(
    +        self,
    +        *,
    +        aerosol: str,
    +        vertical_velocity: float,
    +        dt: float,
    +        n_sd: int,
    +        initial_temperature: float = 283 * si.K,
    +        initial_pressure: float = 900 * si.mbar,
    +        initial_relative_humidity: float = 0.97,
    +        displacement: float = 1000 * si.m,
    +        mass_accommodation_coefficient: float = 0.3,
    +    ):
    +        self.formulae = Formulae(constants={"MAC": mass_accommodation_coefficient})
    +        self.n_sd = n_sd
    +        self.aerosol_modes_by_kappa = {
    +            "pristine": {
    +                1.28: Sum(
    +                    (
    +                        Lognormal(
    +                            norm_factor=125 / si.cm**3, m_mode=11 * si.nm, s_geom=1.2
    +                        ),
    +                        Lognormal(
    +                            norm_factor=65 / si.cm**3, m_mode=60 * si.nm, s_geom=1.7
    +                        ),
    +                    )
    +                )
    +            },
    +            "polluted": {
    +                1.28: Sum(
    +                    (
    +                        Lognormal(
    +                            norm_factor=160 / si.cm**3, m_mode=29 * si.nm, s_geom=1.36
    +                        ),
    +                        Lognormal(
    +                            norm_factor=380 / si.cm**3, m_mode=71 * si.nm, s_geom=1.57
    +                        ),
    +                    )
    +                )
    +            },
    +        }[aerosol]
    +
    +        const = self.formulae.constants
    +        self.vertical_velocity = vertical_velocity
    +        self.initial_pressure = initial_pressure
    +        self.initial_temperature = initial_temperature
    +        pv0 = (
    +            initial_relative_humidity
    +            * self.formulae.saturation_vapour_pressure.pvs_Celsius(
    +                initial_temperature - const.T0
    +            )
    +        )
    +        self.initial_vapour_mixing_ratio = const.eps * pv0 / (initial_pressure - pv0)
    +        self.t_max = displacement / vertical_velocity
    +        self.timestep = dt
    +        self.output_interval = self.timestep
    +
    +    @property
    +    def initial_air_density(self):
    +        const = self.formulae.constants
    +        dry_air_density = (
    +            self.formulae.trivia.p_d(
    +                self.initial_pressure, self.initial_vapour_mixing_ratio
    +            )
    +            / self.initial_temperature
    +            / const.Rd
    +        )
    +        return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
    +
    +    @property
    +    def nt(self) -> int:
    +        nt = self.t_max / self.timestep
    +        nt_int = round(nt)
    +        np.testing.assert_almost_equal(nt, nt_int)
    +        return nt_int
    +
    +    @property
    +    def steps_per_output_interval(self) -> int:
    +        return int(self.output_interval / self.timestep)
    +
    +    @property
    +    def output_steps(self) -> np.ndarray:
    +        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class Settings +(*, aerosol: str, vertical_velocity: float, dt: float, n_sd: int, initial_temperature: float = 283.0, initial_pressure: float = 90000.0, initial_relative_humidity: float = 0.97, displacement: float = 1000.0, mass_accommodation_coefficient: float = 0.3) +
    +
    +
    +
    + +Expand source code + +
    @strict
    +class Settings:
    +    def __init__(
    +        self,
    +        *,
    +        aerosol: str,
    +        vertical_velocity: float,
    +        dt: float,
    +        n_sd: int,
    +        initial_temperature: float = 283 * si.K,
    +        initial_pressure: float = 900 * si.mbar,
    +        initial_relative_humidity: float = 0.97,
    +        displacement: float = 1000 * si.m,
    +        mass_accommodation_coefficient: float = 0.3,
    +    ):
    +        self.formulae = Formulae(constants={"MAC": mass_accommodation_coefficient})
    +        self.n_sd = n_sd
    +        self.aerosol_modes_by_kappa = {
    +            "pristine": {
    +                1.28: Sum(
    +                    (
    +                        Lognormal(
    +                            norm_factor=125 / si.cm**3, m_mode=11 * si.nm, s_geom=1.2
    +                        ),
    +                        Lognormal(
    +                            norm_factor=65 / si.cm**3, m_mode=60 * si.nm, s_geom=1.7
    +                        ),
    +                    )
    +                )
    +            },
    +            "polluted": {
    +                1.28: Sum(
    +                    (
    +                        Lognormal(
    +                            norm_factor=160 / si.cm**3, m_mode=29 * si.nm, s_geom=1.36
    +                        ),
    +                        Lognormal(
    +                            norm_factor=380 / si.cm**3, m_mode=71 * si.nm, s_geom=1.57
    +                        ),
    +                    )
    +                )
    +            },
    +        }[aerosol]
    +
    +        const = self.formulae.constants
    +        self.vertical_velocity = vertical_velocity
    +        self.initial_pressure = initial_pressure
    +        self.initial_temperature = initial_temperature
    +        pv0 = (
    +            initial_relative_humidity
    +            * self.formulae.saturation_vapour_pressure.pvs_Celsius(
    +                initial_temperature - const.T0
    +            )
    +        )
    +        self.initial_vapour_mixing_ratio = const.eps * pv0 / (initial_pressure - pv0)
    +        self.t_max = displacement / vertical_velocity
    +        self.timestep = dt
    +        self.output_interval = self.timestep
    +
    +    @property
    +    def initial_air_density(self):
    +        const = self.formulae.constants
    +        dry_air_density = (
    +            self.formulae.trivia.p_d(
    +                self.initial_pressure, self.initial_vapour_mixing_ratio
    +            )
    +            / self.initial_temperature
    +            / const.Rd
    +        )
    +        return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
    +
    +    @property
    +    def nt(self) -> int:
    +        nt = self.t_max / self.timestep
    +        nt_int = round(nt)
    +        np.testing.assert_almost_equal(nt, nt_int)
    +        return nt_int
    +
    +    @property
    +    def steps_per_output_interval(self) -> int:
    +        return int(self.output_interval / self.timestep)
    +
    +    @property
    +    def output_steps(self) -> np.ndarray:
    +        return np.arange(0, self.nt + 1, self.steps_per_output_interval)
    +
    +

    Instance variables

    +
    +
    var initial_air_density
    +
    +
    +
    + +Expand source code + +
    @property
    +def initial_air_density(self):
    +    const = self.formulae.constants
    +    dry_air_density = (
    +        self.formulae.trivia.p_d(
    +            self.initial_pressure, self.initial_vapour_mixing_ratio
    +        )
    +        / self.initial_temperature
    +        / const.Rd
    +    )
    +    return dry_air_density * (1 + self.initial_vapour_mixing_ratio)
    +
    +
    +
    var nt : int
    +
    +
    +
    + +Expand source code + +
    @property
    +def nt(self) -> int:
    +    nt = self.t_max / self.timestep
    +    nt_int = round(nt)
    +    np.testing.assert_almost_equal(nt, nt_int)
    +    return nt_int
    +
    +
    +
    var output_steps : numpy.ndarray
    +
    +
    +
    + +Expand source code + +
    @property
    +def output_steps(self) -> np.ndarray:
    +    return np.arange(0, self.nt + 1, self.steps_per_output_interval)
    +
    +
    +
    var steps_per_output_interval : int
    +
    +
    +
    + +Expand source code + +
    @property
    +def steps_per_output_interval(self) -> int:
    +    return int(self.output_interval / self.timestep)
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM_examples/Grabowski_and_Pawlowska_2023/simulation.html b/PySDM_examples/Grabowski_and_Pawlowska_2023/simulation.html new file mode 100644 index 000000000..8e6c7d620 --- /dev/null +++ b/PySDM_examples/Grabowski_and_Pawlowska_2023/simulation.html @@ -0,0 +1,323 @@ + + + + + + +PySDM_examples.Grabowski_and_Pawlowska_2023.simulation API documentation + + + + + + + + + + + +
    +
    +
    +

    Module PySDM_examples.Grabowski_and_Pawlowska_2023.simulation

    +
    +
    +
    + +Expand source code + +
    import numpy as np
    +from PySDM_examples.utils import BasicSimulation
    +
    +from PySDM import Builder
    +from PySDM.backends import CPU
    +from PySDM.backends.impl_numba.test_helpers import scipy_ode_condensation_solver
    +from PySDM.dynamics import AmbientThermodynamics, Condensation
    +from PySDM.environments import Parcel
    +from PySDM.initialisation import equilibrate_wet_radii
    +from PySDM.initialisation.sampling.spectral_sampling import ConstantMultiplicity
    +from PySDM.physics import si
    +
    +
    +class Simulation(BasicSimulation):
    +    def __init__(
    +        self,
    +        settings,
    +        products=None,
    +        scipy_solver=False,
    +        sampling_class=ConstantMultiplicity,
    +    ):
    +        env = Parcel(
    +            dt=settings.timestep,
    +            p0=settings.initial_pressure,
    +            q0=settings.initial_vapour_mixing_ratio,
    +            T0=settings.initial_temperature,
    +            w=settings.vertical_velocity,
    +            mass_of_dry_air=44 * si.kg,
    +        )
    +        builder = Builder(n_sd=settings.n_sd, backend=CPU(formulae=settings.formulae))
    +        builder.set_environment(env)
    +        builder.add_dynamic(AmbientThermodynamics())
    +        builder.add_dynamic(Condensation())
    +        for attribute in (
    +            "critical supersaturation",
    +            "equilibrium supersaturation",
    +            "critical volume",
    +        ):
    +            builder.request_attribute(attribute)
    +
    +        volume = env.mass_of_dry_air / settings.initial_air_density
    +        attributes = {
    +            k: np.empty(0)
    +            for k in ("dry volume", "kappa times dry volume", "multiplicity", "kappa")
    +        }
    +
    +        assert len(settings.aerosol_modes_by_kappa.keys()) == 1
    +        kappa = tuple(settings.aerosol_modes_by_kappa.keys())[0]
    +        spectrum = settings.aerosol_modes_by_kappa[kappa]
    +
    +        r_dry, n_per_volume = sampling_class(spectrum).sample(settings.n_sd)
    +        v_dry = settings.formulae.trivia.volume(radius=r_dry)
    +        attributes["multiplicity"] = np.append(
    +            attributes["multiplicity"], n_per_volume * volume
    +        )
    +        attributes["dry volume"] = np.append(attributes["dry volume"], v_dry)
    +        attributes["kappa times dry volume"] = np.append(
    +            attributes["kappa times dry volume"], v_dry * kappa
    +        )
    +        attributes["kappa"] = np.append(
    +            attributes["kappa"], np.full(settings.n_sd, kappa)
    +        )
    +        r_wet = equilibrate_wet_radii(
    +            r_dry=settings.formulae.trivia.radius(volume=attributes["dry volume"]),
    +            environment=env,
    +            kappa_times_dry_volume=attributes["kappa times dry volume"],
    +        )
    +        attributes["volume"] = settings.formulae.trivia.volume(radius=r_wet)
    +
    +        super().__init__(
    +            particulator=builder.build(attributes=attributes, products=products)
    +        )
    +        if scipy_solver:
    +            scipy_ode_condensation_solver.patch_particulator(self.particulator)
    +
    +        self.output_attributes = {
    +            "volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "dry volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "critical supersaturation": tuple(
    +                [] for _ in range(self.particulator.n_sd)
    +            ),
    +            "equilibrium supersaturation": tuple(
    +                [] for _ in range(self.particulator.n_sd)
    +            ),
    +            "critical volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "multiplicity": tuple([] for _ in range(self.particulator.n_sd)),
    +        }
    +        self.settings = settings
    +
    +        self.__sanity_checks(attributes, volume)
    +
    +    def __sanity_checks(self, attributes, volume):
    +        for attribute in attributes.values():
    +            assert attribute.shape[0] == self.particulator.n_sd
    +        np.testing.assert_approx_equal(
    +            sum(attributes["multiplicity"]) / volume,
    +            sum(
    +                mode.norm_factor
    +                for mode in self.settings.aerosol_modes_by_kappa.values()
    +            ),
    +            significant=4,
    +        )
    +
    +    def _save(self, output):
    +        for key, attr in self.output_attributes.items():
    +            attr_data = self.particulator.attributes[key].to_ndarray()
    +            for drop_id in range(self.particulator.n_sd):
    +                attr[drop_id].append(attr_data[drop_id])
    +        super()._save(output)
    +
    +    def run(self):
    +        output_products = super()._run(
    +            self.settings.nt, self.settings.steps_per_output_interval
    +        )
    +        return {"products": output_products, "attributes": self.output_attributes}
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class Simulation +(settings, products=None, scipy_solver=False, sampling_class=PySDM.initialisation.sampling.spectral_sampling.ConstantMultiplicity) +
    +
    +
    +
    + +Expand source code + +
    class Simulation(BasicSimulation):
    +    def __init__(
    +        self,
    +        settings,
    +        products=None,
    +        scipy_solver=False,
    +        sampling_class=ConstantMultiplicity,
    +    ):
    +        env = Parcel(
    +            dt=settings.timestep,
    +            p0=settings.initial_pressure,
    +            q0=settings.initial_vapour_mixing_ratio,
    +            T0=settings.initial_temperature,
    +            w=settings.vertical_velocity,
    +            mass_of_dry_air=44 * si.kg,
    +        )
    +        builder = Builder(n_sd=settings.n_sd, backend=CPU(formulae=settings.formulae))
    +        builder.set_environment(env)
    +        builder.add_dynamic(AmbientThermodynamics())
    +        builder.add_dynamic(Condensation())
    +        for attribute in (
    +            "critical supersaturation",
    +            "equilibrium supersaturation",
    +            "critical volume",
    +        ):
    +            builder.request_attribute(attribute)
    +
    +        volume = env.mass_of_dry_air / settings.initial_air_density
    +        attributes = {
    +            k: np.empty(0)
    +            for k in ("dry volume", "kappa times dry volume", "multiplicity", "kappa")
    +        }
    +
    +        assert len(settings.aerosol_modes_by_kappa.keys()) == 1
    +        kappa = tuple(settings.aerosol_modes_by_kappa.keys())[0]
    +        spectrum = settings.aerosol_modes_by_kappa[kappa]
    +
    +        r_dry, n_per_volume = sampling_class(spectrum).sample(settings.n_sd)
    +        v_dry = settings.formulae.trivia.volume(radius=r_dry)
    +        attributes["multiplicity"] = np.append(
    +            attributes["multiplicity"], n_per_volume * volume
    +        )
    +        attributes["dry volume"] = np.append(attributes["dry volume"], v_dry)
    +        attributes["kappa times dry volume"] = np.append(
    +            attributes["kappa times dry volume"], v_dry * kappa
    +        )
    +        attributes["kappa"] = np.append(
    +            attributes["kappa"], np.full(settings.n_sd, kappa)
    +        )
    +        r_wet = equilibrate_wet_radii(
    +            r_dry=settings.formulae.trivia.radius(volume=attributes["dry volume"]),
    +            environment=env,
    +            kappa_times_dry_volume=attributes["kappa times dry volume"],
    +        )
    +        attributes["volume"] = settings.formulae.trivia.volume(radius=r_wet)
    +
    +        super().__init__(
    +            particulator=builder.build(attributes=attributes, products=products)
    +        )
    +        if scipy_solver:
    +            scipy_ode_condensation_solver.patch_particulator(self.particulator)
    +
    +        self.output_attributes = {
    +            "volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "dry volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "critical supersaturation": tuple(
    +                [] for _ in range(self.particulator.n_sd)
    +            ),
    +            "equilibrium supersaturation": tuple(
    +                [] for _ in range(self.particulator.n_sd)
    +            ),
    +            "critical volume": tuple([] for _ in range(self.particulator.n_sd)),
    +            "multiplicity": tuple([] for _ in range(self.particulator.n_sd)),
    +        }
    +        self.settings = settings
    +
    +        self.__sanity_checks(attributes, volume)
    +
    +    def __sanity_checks(self, attributes, volume):
    +        for attribute in attributes.values():
    +            assert attribute.shape[0] == self.particulator.n_sd
    +        np.testing.assert_approx_equal(
    +            sum(attributes["multiplicity"]) / volume,
    +            sum(
    +                mode.norm_factor
    +                for mode in self.settings.aerosol_modes_by_kappa.values()
    +            ),
    +            significant=4,
    +        )
    +
    +    def _save(self, output):
    +        for key, attr in self.output_attributes.items():
    +            attr_data = self.particulator.attributes[key].to_ndarray()
    +            for drop_id in range(self.particulator.n_sd):
    +                attr[drop_id].append(attr_data[drop_id])
    +        super()._save(output)
    +
    +    def run(self):
    +        output_products = super()._run(
    +            self.settings.nt, self.settings.steps_per_output_interval
    +        )
    +        return {"products": output_products, "attributes": self.output_attributes}
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def run(self) +
    +
    +
    +
    + +Expand source code + +
    def run(self):
    +    output_products = super()._run(
    +        self.settings.nt, self.settings.steps_per_output_interval
    +    )
    +    return {"products": output_products, "attributes": self.output_attributes}
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/PySDM_examples/Yang_et_al_2018/simulation.html b/PySDM_examples/Yang_et_al_2018/simulation.html index aa9b31e5f..16864f752 100644 --- a/PySDM_examples/Yang_et_al_2018/simulation.html +++ b/PySDM_examples/Yang_et_al_2018/simulation.html @@ -26,11 +26,14 @@

    Module PySDM_examples.Yang_et_al_2018.simulation< Expand source code -
    import PySDM.products as PySDM_products
    +
    import numpy as np
    +
    +import PySDM.products as PySDM_products
     from PySDM import Builder, Formulae
     from PySDM.backends import CPU
     from PySDM.dynamics import AmbientThermodynamics, Condensation
     from PySDM.environments import Parcel
    +from PySDM.physics import si
     
     
     class Simulation:
    @@ -77,6 +80,12 @@ 

    Module PySDM_examples.Yang_et_al_2018.simulation< PySDM_products.CondensationTimestepMin(name="dt_cond_min"), PySDM_products.CondensationTimestepMax(name="dt_cond_max"), PySDM_products.RipeningRate(), + PySDM_products.MeanRadius( + name="r_mean_gt_1_um", radius_range=(1 * si.um, np.inf) + ), + PySDM_products.ActivatedMeanRadius( + name="r_act", count_activated=True, count_unactivated=False + ), ] attributes = environment.init_attributes( @@ -96,28 +105,34 @@

    Module PySDM_examples.Yang_et_al_2018.simulation< volume = _sp.attributes["volume"].to_ndarray() output["r"].append(self.formulae.trivia.radius(volume=volume)) output["S"].append(_sp.environment["RH"][cell_id] - 1) - output["qv"].append(_sp.environment["qv"][cell_id]) - output["T"].append(_sp.environment["T"][cell_id]) - output["z"].append(_sp.environment["z"][cell_id]) - output["t"].append(_sp.environment["t"][cell_id]) - output["dt_cond_max"].append(_sp.products["dt_cond_max"].get()[cell_id].copy()) - output["dt_cond_min"].append(_sp.products["dt_cond_min"].get()[cell_id].copy()) - output["ripening rate"].append( - _sp.products["ripening rate"].get()[cell_id].copy() - ) + for key in ("qv", "T", "z", "t"): + output[key].append(_sp.environment[key][cell_id]) + for key in ( + "dt_cond_max", + "dt_cond_min", + "ripening rate", + "r_mean_gt_1_um", + "r_act", + ): + output[key].append(_sp.products[key].get()[cell_id].copy()) def run(self): output = { - "r": [], - "S": [], - "z": [], - "t": [], - "qv": [], - "T": [], - "r_bins_values": [], - "dt_cond_max": [], - "dt_cond_min": [], - "ripening rate": [], + key: [] + for key in ( + "r", + "S", + "z", + "t", + "qv", + "T", + "r_bins_values", + "dt_cond_max", + "dt_cond_min", + "ripening rate", + "r_mean_gt_1_um", + "r_act", + ) } self.save(output) @@ -190,6 +205,12 @@

    Classes

    PySDM_products.CondensationTimestepMin(name="dt_cond_min"), PySDM_products.CondensationTimestepMax(name="dt_cond_max"), PySDM_products.RipeningRate(), + PySDM_products.MeanRadius( + name="r_mean_gt_1_um", radius_range=(1 * si.um, np.inf) + ), + PySDM_products.ActivatedMeanRadius( + name="r_act", count_activated=True, count_unactivated=False + ), ] attributes = environment.init_attributes( @@ -209,28 +230,34 @@

    Classes

    volume = _sp.attributes["volume"].to_ndarray() output["r"].append(self.formulae.trivia.radius(volume=volume)) output["S"].append(_sp.environment["RH"][cell_id] - 1) - output["qv"].append(_sp.environment["qv"][cell_id]) - output["T"].append(_sp.environment["T"][cell_id]) - output["z"].append(_sp.environment["z"][cell_id]) - output["t"].append(_sp.environment["t"][cell_id]) - output["dt_cond_max"].append(_sp.products["dt_cond_max"].get()[cell_id].copy()) - output["dt_cond_min"].append(_sp.products["dt_cond_min"].get()[cell_id].copy()) - output["ripening rate"].append( - _sp.products["ripening rate"].get()[cell_id].copy() - ) + for key in ("qv", "T", "z", "t"): + output[key].append(_sp.environment[key][cell_id]) + for key in ( + "dt_cond_max", + "dt_cond_min", + "ripening rate", + "r_mean_gt_1_um", + "r_act", + ): + output[key].append(_sp.products[key].get()[cell_id].copy()) def run(self): output = { - "r": [], - "S": [], - "z": [], - "t": [], - "qv": [], - "T": [], - "r_bins_values": [], - "dt_cond_max": [], - "dt_cond_min": [], - "ripening rate": [], + key: [] + for key in ( + "r", + "S", + "z", + "t", + "qv", + "T", + "r_bins_values", + "dt_cond_max", + "dt_cond_min", + "ripening rate", + "r_mean_gt_1_um", + "r_act", + ) } self.save(output) @@ -252,16 +279,21 @@

    Methods

    def run(self):
         output = {
    -        "r": [],
    -        "S": [],
    -        "z": [],
    -        "t": [],
    -        "qv": [],
    -        "T": [],
    -        "r_bins_values": [],
    -        "dt_cond_max": [],
    -        "dt_cond_min": [],
    -        "ripening rate": [],
    +        key: []
    +        for key in (
    +            "r",
    +            "S",
    +            "z",
    +            "t",
    +            "qv",
    +            "T",
    +            "r_bins_values",
    +            "dt_cond_max",
    +            "dt_cond_min",
    +            "ripening rate",
    +            "r_mean_gt_1_um",
    +            "r_act",
    +        )
         }
     
         self.save(output)
    @@ -289,15 +321,16 @@ 

    Methods

    volume = _sp.attributes["volume"].to_ndarray() output["r"].append(self.formulae.trivia.radius(volume=volume)) output["S"].append(_sp.environment["RH"][cell_id] - 1) - output["qv"].append(_sp.environment["qv"][cell_id]) - output["T"].append(_sp.environment["T"][cell_id]) - output["z"].append(_sp.environment["z"][cell_id]) - output["t"].append(_sp.environment["t"][cell_id]) - output["dt_cond_max"].append(_sp.products["dt_cond_max"].get()[cell_id].copy()) - output["dt_cond_min"].append(_sp.products["dt_cond_min"].get()[cell_id].copy()) - output["ripening rate"].append( - _sp.products["ripening rate"].get()[cell_id].copy() - )
    + for key in ("qv", "T", "z", "t"): + output[key].append(_sp.environment[key][cell_id]) + for key in ( + "dt_cond_max", + "dt_cond_min", + "ripening rate", + "r_mean_gt_1_um", + "r_act", + ): + output[key].append(_sp.products[key].get()[cell_id].copy())
    diff --git a/PySDM_examples/index.html b/PySDM_examples/index.html index 6496b6d83..c516d648f 100644 --- a/PySDM_examples/index.html +++ b/PySDM_examples/index.html @@ -83,6 +83,10 @@

    Sub-modules

    example based on Ervens and Feingold 2012 (Atmos. Chem. Phys. 12) https://doi.org/10.5194/acp-12-5807-2012

    +
    PySDM_examples.Grabowski_and_Pawlowska_2023
    +
    +
    +
    PySDM_examples.Jaruga_and_Pawlowska_2018
    @@ -167,6 +171,7 @@

    Index

  • PySDM_examples.Berry_1967
  • PySDM_examples.Bieli_et_al_2022
  • PySDM_examples.Ervens_and_Feingold_2012
  • +
  • PySDM_examples.Grabowski_and_Pawlowska_2023
  • PySDM_examples.Jaruga_and_Pawlowska_2018
  • PySDM_examples.Kreidenweis_et_al_2003
  • PySDM_examples.Lowe_et_al_2019
  • diff --git a/PySDM_examples/utils/basic_simulation.html b/PySDM_examples/utils/basic_simulation.html index bc2dfd216..4ac5767c4 100644 --- a/PySDM_examples/utils/basic_simulation.html +++ b/PySDM_examples/utils/basic_simulation.html @@ -89,6 +89,7 @@

    Classes

    Subclasses