From ca90206244f6ab9b2f4ee07478f06380fc846e38 Mon Sep 17 00:00:00 2001 From: claresinger Date: Wed, 27 Nov 2024 17:27:52 -0500 Subject: [PATCH 01/56] add example of lifting parcel for time t_lift and then holding it to mimic the princeton expansion chamber --- .gitignore | 3 + .../expansion_chamber/__init__.py | 4 + .../expansion_chamber/aerosol.py | 48 ++++++ .../expansion_experiment.ipynb | 106 ++++++++++++ .../expansion_chamber/expansion_simulation.py | 158 ++++++++++++++++++ 5 files changed, 319 insertions(+) create mode 100644 examples/PySDM_examples/expansion_chamber/__init__.py create mode 100644 examples/PySDM_examples/expansion_chamber/aerosol.py create mode 100644 examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb create mode 100644 examples/PySDM_examples/expansion_chamber/expansion_simulation.py diff --git a/.gitignore b/.gitignore index f0b0fc0fb..1c298872a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ PySDM_examples/utils/temporary_files/* *.pkl *.vtu *.vts +*.png +*.csv +*.xlsx # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/examples/PySDM_examples/expansion_chamber/__init__.py b/examples/PySDM_examples/expansion_chamber/__init__.py new file mode 100644 index 000000000..8fca36f41 --- /dev/null +++ b/examples/PySDM_examples/expansion_chamber/__init__.py @@ -0,0 +1,4 @@ +# pylint: disable=invalid-name +""" +expansion chamber example imagined as an ascending parcel with updraft velocity matched to dp/dt +""" diff --git a/examples/PySDM_examples/expansion_chamber/aerosol.py b/examples/PySDM_examples/expansion_chamber/aerosol.py new file mode 100644 index 000000000..14b9f3434 --- /dev/null +++ b/examples/PySDM_examples/expansion_chamber/aerosol.py @@ -0,0 +1,48 @@ +from chempy import Substance +from pystrict import strict + +from PySDM.initialisation import spectra +from PySDM.initialisation.aerosol_composition import DryAerosolMixture +from PySDM.physics import si + + +@strict +class AerosolChamber(DryAerosolMixture): + def __init__( + self, + water_molar_volume: float, + N: float = 1e5 / si.cm**3, + ): + mode1 = {"CaCO3": 1.0} + + super().__init__( + compounds=("CaCO3",), + molar_masses={ + "CaCO3": Substance.from_formula("CaCO3").mass * si.g / si.mole + }, + densities={ + "CaCO3": 2.71 * si.g / si.cm**3, + }, + is_soluble={ + "CaCO3": True, + }, + ionic_dissociation_phi={ + "CaCO3": 2, + }, + ) + self.modes = ( + { + "kappa": self.kappa( + mass_fractions=mode1, + water_molar_volume=water_molar_volume, + ), + "spectrum": spectra.Lognormal( + norm_factor=N, + m_mode=158 * si.nm, + s_geom=2, + ), + # mean diameter 316nm, standard deviation 257nm + # not sure how to interpret the standard deviation given in the paper + # because it looks like it's a lognormal distribution in Fig 2 + }, + ) diff --git a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb new file mode 100644 index 000000000..ed35c96d4 --- /dev/null +++ b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb @@ -0,0 +1,106 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from scipy.ndimage import uniform_filter1d\n", + "from matplotlib import pyplot\n", + "from open_atmos_jupyter_utils import show_plot\n", + "from PySDM import Formulae\n", + "from PySDM.physics import si\n", + "\n", + "from PySDM_examples.expansion_chamber.aerosol import AerosolChamber\n", + "from PySDM_examples.expansion_chamber.expansion_simulation import run_expansion" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "n_steps=1473\n", + "n_steps=1473\n", + "n_steps=1473\n", + "n_steps=1473\n", + "n_steps=1473\n", + "n_steps=1473\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "n_sd_per_mode = 20\n", + "\n", + "for Na in [1, 10, 100, 1000, 10000, 100000]:\n", + "\n", + " formulae = Formulae()\n", + " const = formulae.constants\n", + " aerosol = AerosolChamber(\n", + " water_molar_volume=const.Mv / const.rho_w,\n", + " N=Na / si.cm**3,\n", + " )\n", + "\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode)\n", + " pyplot.plot(output.profile[\"t\"], np.array(output.profile[\"T\"]) - 273.15, label=f\"{Na}\")\n", + "\n", + "pyplot.xlabel(\"Time [s]\")\n", + "pyplot.ylabel(\"Temperature [°C]\")\n", + "pyplot.legend(title=\"$N_a$ [#/cc]\")\n", + "pyplot.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.9 ('pysdm')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "b14f34a08619f4a218d80d7380beed3f0c712c89ff93e7183219752d640ed427" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/PySDM_examples/expansion_chamber/expansion_simulation.py b/examples/PySDM_examples/expansion_chamber/expansion_simulation.py new file mode 100644 index 000000000..14898b3cc --- /dev/null +++ b/examples/PySDM_examples/expansion_chamber/expansion_simulation.py @@ -0,0 +1,158 @@ +from collections import namedtuple + +import numpy as np +from PySDM import Builder +from PySDM import products as PySDM_products +from PySDM.backends import CPU +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 + + +def run_expansion( + formulae, + aerosol, + n_sd_per_mode, + RH0=0.7, + dp=500 * si.hPa, + T0=296 * si.K, + p0=1000 * si.hPa, + dz=10 * si.m, + t_lift=2 * si.s, + t_max=5 * si.s, +): + + # calculate w, dt, n_steps + H = 8500 * si.m # atmospheric scale height + z_lift = -H * np.log(dp / p0) + w_lift = z_lift / t_lift + w = lambda t: w_lift if t < t_lift else 1e-5 + dt = dz / w_lift + n_steps = int(np.ceil(t_max / dt)) + # print(f"z_lift={z_lift}") + # print(f"w_lift={w_lift}") + # print(f"dz={dz}") + # print(f"dt={dt}") + print(f"n_steps={n_steps}") + + dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False) + wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False) + products = ( + PySDM_products.WaterMixingRatio(unit="g/kg", name="liquid_water_mixing_ratio"), + PySDM_products.PeakSupersaturation(name="smax"), + PySDM_products.AmbientRelativeHumidity(name="RH"), + PySDM_products.AmbientTemperature(name="T"), + PySDM_products.AmbientPressure(name="p"), + PySDM_products.AmbientWaterVapourMixingRatio( + unit="g/kg", name="water_vapour_mixing_ratio" + ), + PySDM_products.ParcelDisplacement(name="z"), + PySDM_products.Time(name="t"), + PySDM_products.ParticleSizeSpectrumPerVolume( + name="dry:dN/dR", + unit="m^-3 m^-1", + radius_bins_edges=dry_radius_bin_edges, + dry=True, + ), + PySDM_products.ParticleSizeSpectrumPerVolume( + name="wet:dN/dR", + unit="m^-3 m^-1", + radius_bins_edges=wet_radius_bin_edges, + dry=False, + ), + ) + + const = formulae.constants + pv0 = RH0 * formulae.saturation_vapour_pressure.pvs_water(T0) + + env = Parcel( + dt=dt, + mass_of_dry_air=1e3 * si.kg, + p0=p0, + initial_water_vapour_mixing_ratio=const.eps * pv0 / (p0 - pv0), + w=w, + T0=T0, + ) + + n_sd = n_sd_per_mode * len(aerosol.modes) + + builder = Builder(backend=CPU(formulae), n_sd=n_sd, environment=env) + builder.add_dynamic(AmbientThermodynamics()) + builder.add_dynamic(Condensation()) + builder.request_attribute("critical supersaturation") + + attributes = { + k: np.empty(0) for k in ("dry volume", "kappa times dry volume", "multiplicity") + } + for i, mode in enumerate(aerosol.modes): + kappa, spectrum = mode["kappa"]["Constant"], mode["spectrum"] + r_dry, concentration = ConstantMultiplicity(spectrum).sample(n_sd_per_mode) + v_dry = builder.formulae.trivia.volume(radius=r_dry) + specific_concentration = concentration / builder.formulae.constants.rho_STP + attributes["multiplicity"] = np.append( + attributes["multiplicity"], + specific_concentration * builder.particulator.environment.mass_of_dry_air, + ) + 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 + ) + + r_wet = equilibrate_wet_radii( + r_dry=builder.formulae.trivia.radius(volume=attributes["dry volume"]), + environment=builder.particulator.environment, + kappa_times_dry_volume=attributes["kappa times dry volume"], + ) + attributes["volume"] = builder.formulae.trivia.volume(radius=r_wet) + + particulator = builder.build(attributes, products=products) + + output = {product.name: [] for product in particulator.products.values()} + output_attributes = { + "multiplicity": tuple([] for _ in range(particulator.n_sd)), + "volume": tuple([] for _ in range(particulator.n_sd)), + "critical volume": tuple([] for _ in range(particulator.n_sd)), + "critical supersaturation": tuple([] for _ in range(particulator.n_sd)), + } + + for _ in range(n_steps): + particulator.run(steps=1) + for product in particulator.products.values(): + if product.name == "dry:dN/dR" or product.name == "wet:dN/dR": + continue + value = product.get() + if product.name == "t": + output[product.name].append(value) + else: + output[product.name].append(value[0]) + for key, attr in output_attributes.items(): + attr_data = particulator.attributes[key].to_ndarray() + for drop_id in range(particulator.n_sd): + attr[drop_id].append(attr_data[drop_id]) + + dry_spectrum = particulator.products["dry:dN/dR"].get() + wet_spectrum = particulator.products["wet:dN/dR"].get() + + Output = namedtuple( + "Output", + [ + "profile", + "attributes", + "aerosol", + "dry_radius_bin_edges", + "dry_spectrum", + "wet_radius_bin_edges", + "wet_spectrum", + ], + ) + return Output( + profile=output, + attributes=output_attributes, + aerosol=aerosol, + dry_radius_bin_edges=dry_radius_bin_edges, + dry_spectrum=dry_spectrum, + wet_radius_bin_edges=wet_radius_bin_edges, + wet_spectrum=wet_spectrum, + ) From f71685982966190dbd365246d72f30a4b3b46310 Mon Sep 17 00:00:00 2001 From: claresinger Date: Wed, 18 Dec 2024 21:42:21 -0500 Subject: [PATCH 02/56] do dp sweep to plot Tmin vs dp under a few conditions of S0 and C0 to match Fig 4 in the manuscript --- .../expansion_chamber/aerosol.py | 8 +- .../expansion_experiment.ipynb | 259 ++++++++++++++++-- .../expansion_chamber/expansion_simulation.py | 15 +- 3 files changed, 250 insertions(+), 32 deletions(-) diff --git a/examples/PySDM_examples/expansion_chamber/aerosol.py b/examples/PySDM_examples/expansion_chamber/aerosol.py index 14b9f3434..483de30c6 100644 --- a/examples/PySDM_examples/expansion_chamber/aerosol.py +++ b/examples/PySDM_examples/expansion_chamber/aerosol.py @@ -27,7 +27,7 @@ def __init__( "CaCO3": True, }, ionic_dissociation_phi={ - "CaCO3": 2, + "CaCO3": 1, }, ) self.modes = ( @@ -41,8 +41,8 @@ def __init__( m_mode=158 * si.nm, s_geom=2, ), - # mean diameter 316nm, standard deviation 257nm - # not sure how to interpret the standard deviation given in the paper - # because it looks like it's a lognormal distribution in Fig 2 }, ) + # mean diameter 316nm, standard deviation 257nm + # not sure how to interpret the standard deviation given in the paper + # because it looks like it's a lognormal distribution in Fig 2 diff --git a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb index ed35c96d4..f90444a05 100644 --- a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb +++ b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb @@ -19,38 +19,47 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "n_steps=1473\n", - "n_steps=1473\n", - "n_steps=1473\n", - "n_steps=1473\n", - "n_steps=1473\n", - "n_steps=1473\n" - ] - }, { "data": { - "image/png": "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", + "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T15:51:05.506783\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ - "
" + "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6b144d9af1a64fdb9f201e5e46f961d6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./C0_sweep_traces.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ "n_sd_per_mode = 20\n", "\n", - "for Na in [1, 10, 100, 1000, 10000, 100000]:\n", + "# plot p, T, S, qv, ql, reff\n", + "variables = [\"p\",\"T\",\"s\",\"water_vapour_mixing_ratio\",\"liquid_water_mixing_ratio\",\"reff\"]\n", + "offsets = [0, -273.15, 1, 0, 0, 0]\n", + "factors = [1/100, 1, 1, 1, 1, 1]\n", + "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\"]\n", + "fig,axes=pyplot.subplots(2,3,figsize=(10,5),sharex=True,sharey=False,constrained_layout=True)\n", + "\n", + "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", "\n", " formulae = Formulae()\n", " const = formulae.constants\n", @@ -59,13 +68,219 @@ " N=Na / si.cm**3,\n", " )\n", "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode)\n", - " pyplot.plot(output.profile[\"t\"], np.array(output.profile[\"T\"]) - 273.15, label=f\"{Na}\")\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, t_max=4*si.s, dz=10*si.m)\n", + " \n", + " for i,ax in enumerate(axes.flatten()):\n", + " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", + " ax.plot(output.profile[\"t\"], y, label=f\"{Na:.0e}\")\n", + " # if i == 2:\n", + " # ax.set_yscale(\"log\")\n", + " ax.set_xlabel(\"Time [s]\")\n", + " ax.set_ylabel(ylabels[i])\n", + "\n", + "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", + "show_plot(\"C0_sweep_traces.pdf\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 100.0\n", + "1 10000.0\n", + "2 15000.0\n", + "3 20000.0\n", + "4 25000.0\n", + "5 30000.0\n", + "6 35000.0\n", + "7 40000.0\n", + "8 45000.0\n", + "9 50000.0\n", + "10 55000.0\n", + "11 60000.0\n", + "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", + " 55000. 60000.]\n", + "[ 22.75197349 14.02952422 9.3313343 4.90250394 1.3754211\n", + " -2.22650374 -6.40524781 -11.31013493 -17.10985754 -23.96731697\n", + " -32.10461863 -41.61700796]\n", + "[ 22.75198932 14.0290065 9.32445132 4.22824895 -1.160582\n", + " -6.84208189 -13.01262823 -19.67291953 -26.92166646 -34.8575308\n", + " -43.67694679 -53.47821023]\n", + "[ 22.75239684 14.06569688 9.38070725 4.30527883 -1.06298974\n", + " -6.72410419 -12.87328365 -19.51053965 -26.73349356 -34.63977293\n", + " -43.42462343 -53.1856958 ]\n" + ] + } + ], + "source": [ + "n_sd_per_mode = 20\n", + "\n", + "p0 = 1000 * si.hPa\n", + "dp = np.insert(np.linspace(100,600,11),0,1) * si.hPa\n", + "Tmin = np.zeros_like(dp)\n", + "Smax = np.zeros_like(dp)\n", + "Tmin_clean = np.zeros_like(dp)\n", + "Smax_clean = np.zeros_like(dp)\n", + "Tmin_dry = np.zeros_like(dp)\n", + "Smax_dry = np.zeros_like(dp)\n", + "for i,dpi in enumerate(dp):\n", + " print(i,dpi)\n", + "\n", + " formulae = Formulae()\n", + " const = formulae.constants\n", + " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=2000 / si.cm**3)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", + " Tmin[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=1 / si.cm**3)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", + " Tmin_clean[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax_clean[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", + " Tmin_dry[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax_dry[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + "print(dp)\n", + "print(Tmin)\n", + "print(Tmin_clean)\n", + "print(Tmin_dry)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "p0 = 100000.0 Pa\n", + "T0 = 22.850000000000023 °C\n", + "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", + " 55000. 60000.]\n", + "Tmin (S0=0.5, C0=2000) = [ 22.75197349 14.02952422 9.3313343 4.90250394 1.3754211\n", + " -2.22650374 -6.40524781 -11.31013493 -17.10985754 -23.96731697\n", + " -32.10461863 -41.61700796]\n", + "Tmin (S0=0.5, C0=1) = [ 22.75198932 14.0290065 9.32445132 4.22824895 -1.160582\n", + " -6.84208189 -13.01262823 -19.67291953 -26.92166646 -34.8575308\n", + " -43.67694679 -53.47821023]\n", + "Tmin (S0=0, C0=1) = [ 22.75239684 14.06569688 9.38070725 4.30527883 -1.06298974\n", + " -6.72410419 -12.87328365 -19.51053965 -26.73349356 -34.63977293\n", + " -43.42462343 -53.1856958 ]\n" + ] + } + ], + "source": [ + "print(\"p0 =\",p0,\"Pa\")\n", + "print(\"T0 =\",296-273.15,\"°C\")\n", + "print(\"dp =\",dp)\n", + "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", + "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", + "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T16:33:27.085982\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0c08c55a52774c709495d5894c19db0d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./Tmin_dp.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T16:33:27.952633\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e465c105c5ad451bb9ab79297a8b9c96", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./dp_sweep.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", + "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", + "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", + "ax.legend(loc=3, frameon=False)\n", + "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", + "show_plot(\"Tmin_dp.pdf\")\n", + "\n", + "#########\n", + "\n", + "fig,axes = pyplot.subplots(2,1,figsize=(6,6),sharex=True)\n", + "\n", + "ax = axes[0]\n", + "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", + "ax.legend(loc=3, frameon=False)\n", + "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", + "\n", + "ax = axes[1]\n", + "ax.plot(dp/p0, Smax_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Smax_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Smax, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", + "ax.set_ylabel(r\"$S_{max}$\")\n", + "# ax.set_yscale(\"log\")\n", + "ax.set_ylim(-0.5,6)\n", + "ax.axhline(0, color=\"k\", lw=0.5)\n", + "ax.axhline(1, color=\"k\", lw=0.5)\n", + "ax.axhline(4, color=\"k\", lw=0.5)\n", "\n", - "pyplot.xlabel(\"Time [s]\")\n", - "pyplot.ylabel(\"Temperature [°C]\")\n", - "pyplot.legend(title=\"$N_a$ [#/cc]\")\n", - "pyplot.show()" + "show_plot(\"dp_sweep.pdf\")" ] }, { diff --git a/examples/PySDM_examples/expansion_chamber/expansion_simulation.py b/examples/PySDM_examples/expansion_chamber/expansion_simulation.py index 14898b3cc..6cd048f3c 100644 --- a/examples/PySDM_examples/expansion_chamber/expansion_simulation.py +++ b/examples/PySDM_examples/expansion_chamber/expansion_simulation.py @@ -16,32 +16,32 @@ def run_expansion( aerosol, n_sd_per_mode, RH0=0.7, - dp=500 * si.hPa, T0=296 * si.K, p0=1000 * si.hPa, + pf=500 * si.hPa, dz=10 * si.m, t_lift=2 * si.s, - t_max=5 * si.s, + t_max=4 * si.s, ): # calculate w, dt, n_steps H = 8500 * si.m # atmospheric scale height - z_lift = -H * np.log(dp / p0) + z_lift = -H * np.log(pf / p0) w_lift = z_lift / t_lift - w = lambda t: w_lift if t < t_lift else 1e-5 + w = lambda t: w_lift if t < t_lift else 1e-9 dt = dz / w_lift n_steps = int(np.ceil(t_max / dt)) # print(f"z_lift={z_lift}") # print(f"w_lift={w_lift}") # print(f"dz={dz}") # print(f"dt={dt}") - print(f"n_steps={n_steps}") + # print(f"n_steps={n_steps}") dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False) wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False) products = ( PySDM_products.WaterMixingRatio(unit="g/kg", name="liquid_water_mixing_ratio"), - PySDM_products.PeakSupersaturation(name="smax"), + PySDM_products.PeakSupersaturation(name="s"), PySDM_products.AmbientRelativeHumidity(name="RH"), PySDM_products.AmbientTemperature(name="T"), PySDM_products.AmbientPressure(name="p"), @@ -62,6 +62,9 @@ def run_expansion( radius_bins_edges=wet_radius_bin_edges, dry=False, ), + PySDM_products.ActivatedEffectiveRadius( + name="reff", unit="um", count_activated=True, count_unactivated=False + ), ) const = formulae.constants From 58f5e14c4f1cae2d385b0aec5d6051bb71e46ddb Mon Sep 17 00:00:00 2001 From: claresinger Date: Mon, 6 Jan 2025 19:24:54 -0500 Subject: [PATCH 03/56] add some placeholders for S&P classic nucleation theory homogeneous nucleation rate J --- .../__init__.py | 7 +++++ .../homogeneous_liquid_nucleation_rate/cnt.py | 26 +++++++++++++++++++ .../constant.py | 14 ++++++++++ .../null.py | 13 ++++++++++ 4 files changed, 60 insertions(+) create mode 100644 PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py create mode 100644 PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py create mode 100644 PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py create mode 100644 PySDM/physics/homogeneous_liquid_nucleation_rate/null.py diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py new file mode 100644 index 000000000..d5bf80400 --- /dev/null +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py @@ -0,0 +1,7 @@ +""" +homogeneous liquid droplet nucleation rate formulations +""" + +from .cnt import CNT +from .constant import Constant +from .null import Null diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py new file mode 100644 index 000000000..d965ba1f8 --- /dev/null +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -0,0 +1,26 @@ +""" +classical nucleation theory (CNT) +formulae from Seinfeld and Pandis Eq (11.47) +""" + +import numpy as np + + +class CNT: # pylint: disable=too-few-public-methods + def __init__(self, const): + assert np.isfinite(const.sgm_w) + + @staticmethod + def j_liq_homo(const, T, S): # pylint: disable=unused-argument + m1 = const.Mv / const.N_A * 1e-3 # kg per molecule + v1 = m1 / const.rho_w # m3 per molecule + e_s = self.pvs_water(const, T) + N1 = (S * e_s) / (m1 * const.Rv * T) # molecules per m3 + return ( + ((2 * const.sgm_w) / (np.pi * m1)) ** (1 / 2) + * (v1 * N1**2 / S) + * np.exp( + (-16 * np.pi * v1**2 * const.sgm_w**3) + / (3 * const.kB**3 * T**3 * np.log(S) ** 2) + ) + ) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py new file mode 100644 index 000000000..0cf202956 --- /dev/null +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py @@ -0,0 +1,14 @@ +""" +constant rate formulation (for tests) +""" + +import numpy as np + + +class Constant: # pylint: disable=too-few-public-methods + def __init__(self, const): + assert np.isfinite(const.J_LIQ_HOMO) + + @staticmethod + def j_liq_homo(const, T, S): # pylint: disable=unused-argument + return const.J_LIQ_HOMO diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py new file mode 100644 index 000000000..814f762e5 --- /dev/null +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py @@ -0,0 +1,13 @@ +""" +do-nothing null formulation (needed as other formulations require parameters + to be set before instantiation of Formulae) +""" + + +class Null: # pylint: disable=too-few-public-methods,unused-argument + def __init__(self, _): + pass + + @staticmethod + def j_liq_homo(const, T, S): + return 0 From 5f4dc31818fc694f1d887893c3d3c54a1c37c886 Mon Sep 17 00:00:00 2001 From: claresinger Date: Mon, 6 Jan 2025 19:29:33 -0500 Subject: [PATCH 04/56] add formulae for critical size of nucleated droplets --- .../homogeneous_liquid_nucleation_rate/cnt.py | 12 +++++++++--- .../homogeneous_liquid_nucleation_rate/constant.py | 5 +++++ .../homogeneous_liquid_nucleation_rate/null.py | 4 ++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py index d965ba1f8..79a1cb821 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -11,8 +11,8 @@ def __init__(self, const): assert np.isfinite(const.sgm_w) @staticmethod - def j_liq_homo(const, T, S): # pylint: disable=unused-argument - m1 = const.Mv / const.N_A * 1e-3 # kg per molecule + def j_liq_homo(const, T, S): + m1 = const.Mv / const.N_A # kg per molecule v1 = m1 / const.rho_w # m3 per molecule e_s = self.pvs_water(const, T) N1 = (S * e_s) / (m1 * const.Rv * T) # molecules per m3 @@ -21,6 +21,12 @@ def j_liq_homo(const, T, S): # pylint: disable=unused-argument * (v1 * N1**2 / S) * np.exp( (-16 * np.pi * v1**2 * const.sgm_w**3) - / (3 * const.kB**3 * T**3 * np.log(S) ** 2) + / (3 * const.k_B**3 * T**3 * np.log(S) ** 2) ) ) + + @staticmethod + def r_liq_homo(const, T, S): + m1 = const.Mv / const.N_A # kg per molecule + v1 = m1 / const.rho_w # m3 per molecule + return (2 * const.sgm_w * v1) / (const.k_B * T * np.log(S)) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py index 0cf202956..f83b460b3 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py @@ -8,7 +8,12 @@ class Constant: # pylint: disable=too-few-public-methods def __init__(self, const): assert np.isfinite(const.J_LIQ_HOMO) + assert np.isfinite(const.R_LIQ_HOMO) @staticmethod def j_liq_homo(const, T, S): # pylint: disable=unused-argument return const.J_LIQ_HOMO + + @staticmethod + def r_liq_homo(const, T, S): # pylint: disable=unused-argument + return const.R_LIQ_HOMO diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py index 814f762e5..6fb78f4d9 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py @@ -11,3 +11,7 @@ def __init__(self, _): @staticmethod def j_liq_homo(const, T, S): return 0 + + @staticmethod + def r_liq_homo(const, T, S): # pylint: disable=unused-argument + return 0 From 5d1be16593d8638a0404f5b0a7b294d3531a3e43 Mon Sep 17 00:00:00 2001 From: claresinger Date: Mon, 6 Jan 2025 19:34:07 -0500 Subject: [PATCH 05/56] doc eq origin --- PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py index 79a1cb821..933650fab 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -1,6 +1,6 @@ """ classical nucleation theory (CNT) -formulae from Seinfeld and Pandis Eq (11.47) +formulae from Seinfeld and Pandis Eq (11.47) and (11.52) """ import numpy as np From d0b56aac55452e3e95d022e96f785cbca95bd6cb Mon Sep 17 00:00:00 2001 From: claresinger Date: Tue, 7 Jan 2025 14:57:14 -0500 Subject: [PATCH 06/56] pylint --- PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py | 9 ++++----- .../homogeneous_liquid_nucleation_rate/constant.py | 4 ++-- PySDM/physics/homogeneous_liquid_nucleation_rate/null.py | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py index 933650fab..e9091f933 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -6,15 +6,14 @@ import numpy as np -class CNT: # pylint: disable=too-few-public-methods - def __init__(self, const): - assert np.isfinite(const.sgm_w) +class CNT: + def __init__(self, _): + return @staticmethod - def j_liq_homo(const, T, S): + def j_liq_homo(const, T, S, e_s): m1 = const.Mv / const.N_A # kg per molecule v1 = m1 / const.rho_w # m3 per molecule - e_s = self.pvs_water(const, T) N1 = (S * e_s) / (m1 * const.Rv * T) # molecules per m3 return ( ((2 * const.sgm_w) / (np.pi * m1)) ** (1 / 2) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py index f83b460b3..49dd74796 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/constant.py @@ -5,13 +5,13 @@ import numpy as np -class Constant: # pylint: disable=too-few-public-methods +class Constant: def __init__(self, const): assert np.isfinite(const.J_LIQ_HOMO) assert np.isfinite(const.R_LIQ_HOMO) @staticmethod - def j_liq_homo(const, T, S): # pylint: disable=unused-argument + def j_liq_homo(const, T, S, e_s): # pylint: disable=unused-argument return const.J_LIQ_HOMO @staticmethod diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py index 6fb78f4d9..6198fb3d1 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py @@ -4,14 +4,14 @@ """ -class Null: # pylint: disable=too-few-public-methods,unused-argument +class Null: # pylint: disable=unused-argument def __init__(self, _): pass @staticmethod - def j_liq_homo(const, T, S): + def j_liq_homo(const, T, S, e_s): return 0 @staticmethod - def r_liq_homo(const, T, S): # pylint: disable=unused-argument + def r_liq_homo(const, T, S): return 0 From c98eaabb9778fb86b9c66282e50112cdc1a04a4f Mon Sep 17 00:00:00 2001 From: claresinger Date: Tue, 7 Jan 2025 15:29:45 -0500 Subject: [PATCH 07/56] add unit tests for formulae relative to tables 11.1 and 11.4 in S&P. some entries currently failing. --- PySDM/formulae.py | 2 + PySDM/physics/__init__.py | 1 + PySDM/physics/constants_defaults.py | 1 + .../test_homogeneous_liquid_nucleation.py | 53 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py diff --git a/PySDM/formulae.py b/PySDM/formulae.py index af8dc10c6..ac7c94e06 100644 --- a/PySDM/formulae.py +++ b/PySDM/formulae.py @@ -44,6 +44,7 @@ def __init__( # pylint: disable=too-many-locals hydrostatics: str = "Default", freezing_temperature_spectrum: str = "Null", heterogeneous_ice_nucleation_rate: str = "Null", + homogeneous_liquid_nucleation_rate: str = "Null", fragmentation_function: str = "AlwaysN", isotope_equilibrium_fractionation_factors: str = "Null", isotope_meteoric_water_line_excess: str = "Null", @@ -76,6 +77,7 @@ def __init__( # pylint: disable=too-many-locals self.hydrostatics = hydrostatics self.freezing_temperature_spectrum = freezing_temperature_spectrum self.heterogeneous_ice_nucleation_rate = heterogeneous_ice_nucleation_rate + self.homogeneous_liquid_nucleation_rate = homogeneous_liquid_nucleation_rate self.fragmentation_function = fragmentation_function self.isotope_equilibrium_fractionation_factors = ( isotope_equilibrium_fractionation_factors diff --git a/PySDM/physics/__init__.py b/PySDM/physics/__init__.py index 93b1c4f3d..93972631e 100644 --- a/PySDM/physics/__init__.py +++ b/PySDM/physics/__init__.py @@ -25,6 +25,7 @@ fragmentation_function, freezing_temperature_spectrum, heterogeneous_ice_nucleation_rate, + homogeneous_liquid_nucleation_rate, hydrostatics, hygroscopicity, impl, diff --git a/PySDM/physics/constants_defaults.py b/PySDM/physics/constants_defaults.py index 439738ce8..afe601c30 100644 --- a/PySDM/physics/constants_defaults.py +++ b/PySDM/physics/constants_defaults.py @@ -56,6 +56,7 @@ R_str = sci.R * si.joule / si.kelvin / si.mole N_A = sci.N_A / si.mole +k_B = sci.k * si.joule / si.kelvin D0 = 2.26e-5 * si.metre**2 / si.second D_exp = 1.81 diff --git a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py new file mode 100644 index 000000000..314d806f4 --- /dev/null +++ b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py @@ -0,0 +1,53 @@ +import pytest + +import numpy as np + +from PySDM import Formulae +from PySDM.physics import constants_defaults as const +from PySDM.physics import si + + +@staticmethod +@pytest.mark.parametrize( + "T, S, table_r_star", + ( + (273, 2, 17.3e-10), + (273, 3, 10.9e-10), + (273, 4, 8.7e-10), + (273, 5, 7.5e-10), + (298, 2, 15.1e-10), + (298, 3, 9.5e-10), + (298, 4, 7.6e-10), + (298, 5, 6.5e-10), + ), +) +def test_seinfeld_pandis_table_11p1(T, S, table_r_star): + formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") + r_star = formulae.homogeneous_liquid_nucleation_rate.r_liq_homo(T, S) + np.testing.assert_approx_equal( + actual=r_star, desired=table_r_star * si.m, significant=1 + ) + + +@staticmethod +@pytest.mark.parametrize( + "T, S, table_J", + ( + (293, 2, 5.02e-54), + (293, 3, 1.76e-6), + (293, 4, 1.05e6), + (293, 5, 1.57e11), + (293, 6, 1.24e14), + (293, 7, 8.99e15), + (293, 8, 1.79e17), + (293, 9, 1.65e18), + (293, 10, 9.17e18), + ), +) +def test_seinfeld_pandis_table_11p4(T, S, table_J): + formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") + e_s = formulae.saturation_vapour_pressure.pvs_water(T) + J = formulae.homogeneous_liquid_nucleation_rate.j_liq_homo(T, S, e_s) + np.testing.assert_approx_equal( + actual=J, desired=table_J / si.cm**3 / si.s, significant=1 + ) From 099e7ca9c166f03fea5d6405559ceaf98e222ee0 Mon Sep 17 00:00:00 2001 From: claresinger Date: Tue, 7 Jan 2025 15:45:31 -0500 Subject: [PATCH 08/56] add bibliography entries. I'm not sure I did this correctly. --- docs/bibliography.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/bibliography.json b/docs/bibliography.json index dad2ca043..10babe71f 100644 --- a/docs/bibliography.json +++ b/docs/bibliography.json @@ -691,5 +691,15 @@ "usages": ["PySDM/physics/saturation_vapour_pressure/wexler_1976.py"], "title": "Vapor Pressure Formulation for Water in Range 0 to f 00 °C. A Revision", "label": "Wexler 1976 (J. Res. NBS A Phys. Ch. 80A)" + }, + "https://doi.org/10.48550/arXiv.2501.01467": { + "usages": ["examples/PySDM_examples/expansion_chamber/aerosol.py"], + "title": "Droplet Nucleation In a Rapid Expansion Aerosol Chamber", + "label": "Erinin et al. 2024 (arXiv:2501.01467)" + }, + "https://books.google.com/books/about/Atmospheric_Chemistry_and_Physics.html?id=n_RmCgAAQBAJ": { + "usages": ["PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py"], + "title": "Atmospheric Chemistry and Physics: From Air Pollution to Climate Change, 3rd Edition", + "label": "Seinfeld and Pandis, Ed.3" } } From 37053f84eb09427c707f52b90b7764451b25c113 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Tue, 7 Jan 2025 22:31:25 +0100 Subject: [PATCH 09/56] swtich url for S&P from 3rd to 2nd ed. (linked full text available on archive.org); mention both urls in the code --- PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py | 5 +++-- docs/bibliography.json | 6 +++--- examples/PySDM_examples/expansion_chamber/aerosol.py | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py index e9091f933..82e592966 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -1,7 +1,8 @@ """ classical nucleation theory (CNT) -formulae from Seinfeld and Pandis Eq (11.47) and (11.52) -""" +formulae from [Seinfeld and Pandis](https://archive.org/details/0237-pdf-atmospheric-chemistry-and-physics-2nd-ed-j.-seinfeld-s.-pandis-wiley-2006-ww) +Eq (11.47) and (11.52) +""" # pylint: disable=line-too-long import numpy as np diff --git a/docs/bibliography.json b/docs/bibliography.json index 10babe71f..ff1686cf5 100644 --- a/docs/bibliography.json +++ b/docs/bibliography.json @@ -697,9 +697,9 @@ "title": "Droplet Nucleation In a Rapid Expansion Aerosol Chamber", "label": "Erinin et al. 2024 (arXiv:2501.01467)" }, - "https://books.google.com/books/about/Atmospheric_Chemistry_and_Physics.html?id=n_RmCgAAQBAJ": { + "https://archive.org/details/0237-pdf-atmospheric-chemistry-and-physics-2nd-ed-j.-seinfeld-s.-pandis-wiley-2006-ww": { "usages": ["PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py"], - "title": "Atmospheric Chemistry and Physics: From Air Pollution to Climate Change, 3rd Edition", - "label": "Seinfeld and Pandis, Ed.3" + "title": "Atmospheric Chemistry and Physics: From Air Pollution to Climate Change, 2nd Edition", + "label": "Seinfeld & Pandis 2006 (Wiley)" } } diff --git a/examples/PySDM_examples/expansion_chamber/aerosol.py b/examples/PySDM_examples/expansion_chamber/aerosol.py index 483de30c6..8943ebe0b 100644 --- a/examples/PySDM_examples/expansion_chamber/aerosol.py +++ b/examples/PySDM_examples/expansion_chamber/aerosol.py @@ -1,3 +1,5 @@ +""" aerosol parameters from [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467) """ + from chempy import Substance from pystrict import strict From ca940e8c6f8bc96d1508b5df2dd681eaf8521330 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Wed, 8 Jan 2025 00:05:49 +0100 Subject: [PATCH 10/56] accommodate S&P url in doc-generating script --- docs/generate_html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generate_html.py b/docs/generate_html.py index 32bf061ce..0dff3c070 100644 --- a/docs/generate_html.py +++ b/docs/generate_html.py @@ -67,7 +67,7 @@ def check_urls(urls_from_json): r"\b(https://doi\.org/10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?![\"&\'<>^\\])\S)+)\b", r"\b(https://digitallibrary\.un\.org/record/(?:[0-9])+)\b", r"\b(http://mi\.mathnet\.ru/dan(?:[0-9])+)\b", - r"\b(https://archive.org/details/(?:[0-9a-z])+)\b", + r"\b(https://archive.org/details/(?:[0-9a-z_\.-])+)\b", ): urls = re.findall(pattern, text) if urls: From 70e0548d269d76344c8e6f5046db367a422ca040 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Wed, 8 Jan 2025 00:43:23 +0100 Subject: [PATCH 11/56] address pylint hints --- .../test_homogeneous_liquid_nucleation.py | 85 ++++++++++--------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py index 314d806f4..e81f8144c 100644 --- a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py +++ b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py @@ -1,53 +1,54 @@ +""" tests checking homogeneous liquid nucleation formulae """ + import pytest import numpy as np from PySDM import Formulae -from PySDM.physics import constants_defaults as const from PySDM.physics import si -@staticmethod -@pytest.mark.parametrize( - "T, S, table_r_star", - ( - (273, 2, 17.3e-10), - (273, 3, 10.9e-10), - (273, 4, 8.7e-10), - (273, 5, 7.5e-10), - (298, 2, 15.1e-10), - (298, 3, 9.5e-10), - (298, 4, 7.6e-10), - (298, 5, 6.5e-10), - ), -) -def test_seinfeld_pandis_table_11p1(T, S, table_r_star): - formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") - r_star = formulae.homogeneous_liquid_nucleation_rate.r_liq_homo(T, S) - np.testing.assert_approx_equal( - actual=r_star, desired=table_r_star * si.m, significant=1 +class TestSeinfeldPandis: + @staticmethod + @pytest.mark.parametrize( + "T, S, table_r_star", + ( + (273, 2, 17.3e-10), + (273, 3, 10.9e-10), + (273, 4, 8.7e-10), + (273, 5, 7.5e-10), + (298, 2, 15.1e-10), + (298, 3, 9.5e-10), + (298, 4, 7.6e-10), + (298, 5, 6.5e-10), + ), ) + def test_seinfeld_pandis_table_11p1(T, S, table_r_star): + formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") + r_star = formulae.homogeneous_liquid_nucleation_rate.r_liq_homo(T, S) + np.testing.assert_approx_equal( + actual=r_star, desired=table_r_star * si.m, significant=1 + ) - -@staticmethod -@pytest.mark.parametrize( - "T, S, table_J", - ( - (293, 2, 5.02e-54), - (293, 3, 1.76e-6), - (293, 4, 1.05e6), - (293, 5, 1.57e11), - (293, 6, 1.24e14), - (293, 7, 8.99e15), - (293, 8, 1.79e17), - (293, 9, 1.65e18), - (293, 10, 9.17e18), - ), -) -def test_seinfeld_pandis_table_11p4(T, S, table_J): - formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") - e_s = formulae.saturation_vapour_pressure.pvs_water(T) - J = formulae.homogeneous_liquid_nucleation_rate.j_liq_homo(T, S, e_s) - np.testing.assert_approx_equal( - actual=J, desired=table_J / si.cm**3 / si.s, significant=1 + @staticmethod + @pytest.mark.parametrize( + "T, S, table_J", + ( + (293, 2, 5.02e-54), + (293, 3, 1.76e-6), + (293, 4, 1.05e6), + (293, 5, 1.57e11), + (293, 6, 1.24e14), + (293, 7, 8.99e15), + (293, 8, 1.79e17), + (293, 9, 1.65e18), + (293, 10, 9.17e18), + ), ) + def test_seinfeld_pandis_table_11p4(T, S, table_J): + formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") + e_s = formulae.saturation_vapour_pressure.pvs_water(T) + J = formulae.homogeneous_liquid_nucleation_rate.j_liq_homo(T, S, e_s) + np.testing.assert_approx_equal( + actual=J, desired=table_J / si.cm**3 / si.s, significant=1 + ) From a501b8fe872a08b82df89bc3e1f013ea899f3074 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Wed, 8 Jan 2025 00:49:38 +0100 Subject: [PATCH 12/56] addressing devops_tests hints - header cells in the notebook --- docs/bibliography.json | 2 +- .../expansion_experiment.ipynb | 6305 ++++++++++++++++- 2 files changed, 6299 insertions(+), 8 deletions(-) diff --git a/docs/bibliography.json b/docs/bibliography.json index ff1686cf5..0299b0954 100644 --- a/docs/bibliography.json +++ b/docs/bibliography.json @@ -693,7 +693,7 @@ "label": "Wexler 1976 (J. Res. NBS A Phys. Ch. 80A)" }, "https://doi.org/10.48550/arXiv.2501.01467": { - "usages": ["examples/PySDM_examples/expansion_chamber/aerosol.py"], + "usages": ["examples/PySDM_examples/expansion_chamber/aerosol.py", "examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb"], "title": "Droplet Nucleation In a Rapid Expansion Aerosol Chamber", "label": "Erinin et al. 2024 (arXiv:2501.01467)" }, diff --git a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb index f90444a05..2a34aad99 100644 --- a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb +++ b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb @@ -1,5 +1,34 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "modeling expansion-chamber experiments described in [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "if 'google.colab' in sys.modules:\n", + " !pip --quiet install open-atmos-jupyter-utils\n", + " from open_atmos_jupyter_utils import pip_install_on_colab\n", + " pip_install_on_colab('PySDM-examples')" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -24,7 +53,2945 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T15:51:05.506783\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2024-12-18T15:51:05.506783\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ "
" ] @@ -194,7 +3161,1534 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T16:33:27.085982\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2024-12-18T16:33:27.085982\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ "
" ] @@ -220,7 +4714,1805 @@ }, { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2024-12-18T16:33:27.952633\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2024-12-18T16:33:27.952633\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ "
" ] @@ -293,7 +6585,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.10.9 ('pysdm')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -307,9 +6599,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.2" }, - "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "b14f34a08619f4a218d80d7380beed3f0c712c89ff93e7183219752d640ed427" @@ -317,5 +6608,5 @@ } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } From e09bdc4e016a22a3f097223241216dfa202fb47a Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Wed, 8 Jan 2025 00:51:56 +0100 Subject: [PATCH 13/56] whitespace removal --- .../PySDM_examples/expansion_chamber/expansion_experiment.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb index 2a34aad99..04865e7e6 100644 --- a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb +++ b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb @@ -6,7 +6,7 @@ "source": [ "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", - "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb) " + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)" ] }, { From 5c3df3493ea31e21ffff9c1cfe969485176e0fcd Mon Sep 17 00:00:00 2001 From: claresinger Date: Fri, 10 Jan 2025 09:54:42 -0500 Subject: [PATCH 14/56] remove null --- .../__init__.py | 2 +- .../homogeneous_liquid_nucleation_rate/null.py | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 PySDM/physics/homogeneous_liquid_nucleation_rate/null.py diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py index d5bf80400..3d1908e5a 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py @@ -4,4 +4,4 @@ from .cnt import CNT from .constant import Constant -from .null import Null +from PySDM.impl.null_physics_class import Null diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py deleted file mode 100644 index 6198fb3d1..000000000 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/null.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -do-nothing null formulation (needed as other formulations require parameters - to be set before instantiation of Formulae) -""" - - -class Null: # pylint: disable=unused-argument - def __init__(self, _): - pass - - @staticmethod - def j_liq_homo(const, T, S, e_s): - return 0 - - @staticmethod - def r_liq_homo(const, T, S): - return 0 From 4135c224a35909d0dd671abffd084be4c3f321af Mon Sep 17 00:00:00 2001 From: claresinger Date: Fri, 10 Jan 2025 09:54:53 -0500 Subject: [PATCH 15/56] better variable names --- .../homogeneous_liquid_nucleation_rate/cnt.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py index 82e592966..23d47531f 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py @@ -13,20 +13,20 @@ def __init__(self, _): @staticmethod def j_liq_homo(const, T, S, e_s): - m1 = const.Mv / const.N_A # kg per molecule - v1 = m1 / const.rho_w # m3 per molecule - N1 = (S * e_s) / (m1 * const.Rv * T) # molecules per m3 + mass_per_moleculue = const.Mv / const.N_A + volume_per_molecule = mass_per_moleculue / const.rho_w + N1 = (S * e_s) / (mass_per_moleculue * const.Rv * T) # molecules per m3 return ( - ((2 * const.sgm_w) / (np.pi * m1)) ** (1 / 2) - * (v1 * N1**2 / S) + ((2 * const.sgm_w) / (np.pi * mass_per_moleculue)) ** (1 / 2) + * (volume_per_molecule * N1**2 / S) * np.exp( - (-16 * np.pi * v1**2 * const.sgm_w**3) + (-16 * np.pi * volume_per_molecule**2 * const.sgm_w**3) / (3 * const.k_B**3 * T**3 * np.log(S) ** 2) ) ) @staticmethod def r_liq_homo(const, T, S): - m1 = const.Mv / const.N_A # kg per molecule - v1 = m1 / const.rho_w # m3 per molecule - return (2 * const.sgm_w * v1) / (const.k_B * T * np.log(S)) + mass_per_moleculue = const.Mv / const.N_A + volume_per_molecule = mass_per_moleculue / const.rho_w + return (2 * const.sgm_w * volume_per_molecule) / (const.k_B * T * np.log(S)) From 3b607caa639f4d04d70d23f371aff0f23d90fb32 Mon Sep 17 00:00:00 2001 From: claresinger Date: Fri, 10 Jan 2025 10:28:31 -0500 Subject: [PATCH 16/56] use Gaussian aerosol mode, not LogNormal --- .../expansion_chamber/aerosol.py | 9 +- .../expansion_experiment.ipynb | 6321 +---------------- 2 files changed, 32 insertions(+), 6298 deletions(-) diff --git a/examples/PySDM_examples/expansion_chamber/aerosol.py b/examples/PySDM_examples/expansion_chamber/aerosol.py index 8943ebe0b..d7fd58304 100644 --- a/examples/PySDM_examples/expansion_chamber/aerosol.py +++ b/examples/PySDM_examples/expansion_chamber/aerosol.py @@ -38,13 +38,10 @@ def __init__( mass_fractions=mode1, water_molar_volume=water_molar_volume, ), - "spectrum": spectra.Lognormal( + "spectrum": spectra.Gaussian( norm_factor=N, - m_mode=158 * si.nm, - s_geom=2, + loc=316 / 2 * si.nm, + scale=257 / 2 * si.nm, ), }, ) - # mean diameter 316nm, standard deviation 257nm - # not sure how to interpret the standard deviation given in the paper - # because it looks like it's a lognormal distribution in Fig 2 diff --git a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb index 04865e7e6..ab5874328 100644 --- a/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb +++ b/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -48,2950 +48,12 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2024-12-18T15:51:05.506783\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.5.1, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-10T10:00:24.794175\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -3004,7 +66,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "6b144d9af1a64fdb9f201e5e46f961d6", + "model_id": "2b728273fc454d1fa2daaeeec91d0a6e", "version_major": 2, "version_minor": 0 }, @@ -3051,7 +113,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -3072,15 +134,15 @@ "11 60000.0\n", "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", " 55000. 60000.]\n", - "[ 22.75197349 14.02952422 9.3313343 4.90250394 1.3754211\n", - " -2.22650374 -6.40524781 -11.31013493 -17.10985754 -23.96731697\n", - " -32.10461863 -41.61700796]\n", - "[ 22.75198932 14.0290065 9.32445132 4.22824895 -1.160582\n", - " -6.84208189 -13.01262823 -19.67291953 -26.92166646 -34.8575308\n", - " -43.67694679 -53.47821023]\n", - "[ 22.75239684 14.06569688 9.38070725 4.30527883 -1.06298974\n", - " -6.72410419 -12.87328365 -19.51053965 -26.73349356 -34.63977293\n", - " -43.42462343 -53.1856958 ]\n" + "[ 22.75198082 14.02926384 9.32894287 4.84298637 1.22984962\n", + " -2.41778535 -6.61993709 -11.54010229 -17.35239681 -24.22128186\n", + " -32.36940492 -41.89363976]\n", + "[ 22.75198932 14.02900637 9.3244501 4.22820117 -1.16081875\n", + " -6.84264641 -13.01362538 -19.67438567 -26.92357005 -34.85977791\n", + " -43.67940643 -53.4807279 ]\n", + "[ 22.75239692 14.06569695 9.38070731 4.30527889 -1.06298968\n", + " -6.72410413 -12.87328359 -19.51053959 -26.7334935 -34.63977286\n", + " -43.42462336 -53.18569574]\n" ] } ], @@ -3122,7 +184,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -3133,15 +195,15 @@ "T0 = 22.850000000000023 °C\n", "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", " 55000. 60000.]\n", - "Tmin (S0=0.5, C0=2000) = [ 22.75197349 14.02952422 9.3313343 4.90250394 1.3754211\n", - " -2.22650374 -6.40524781 -11.31013493 -17.10985754 -23.96731697\n", - " -32.10461863 -41.61700796]\n", - "Tmin (S0=0.5, C0=1) = [ 22.75198932 14.0290065 9.32445132 4.22824895 -1.160582\n", - " -6.84208189 -13.01262823 -19.67291953 -26.92166646 -34.8575308\n", - " -43.67694679 -53.47821023]\n", - "Tmin (S0=0, C0=1) = [ 22.75239684 14.06569688 9.38070725 4.30527883 -1.06298974\n", - " -6.72410419 -12.87328365 -19.51053965 -26.73349356 -34.63977293\n", - " -43.42462343 -53.1856958 ]\n" + "Tmin (S0=0.5, C0=2000) = [ 22.75198082 14.02926384 9.32894287 4.84298637 1.22984962\n", + " -2.41778535 -6.61993709 -11.54010229 -17.35239681 -24.22128186\n", + " -32.36940492 -41.89363976]\n", + "Tmin (S0=0.5, C0=1) = [ 22.75198932 14.02900637 9.3244501 4.22820117 -1.16081875\n", + " -6.84264641 -13.01362538 -19.67438567 -26.92357005 -34.85977791\n", + " -43.67940643 -53.4807279 ]\n", + "Tmin (S0=0, C0=1) = [ 22.75239692 14.06569695 9.38070731 4.30527889 -1.06298968\n", + " -6.72410413 -12.87328359 -19.51053959 -26.7334935 -34.63977286\n", + " -43.42462336 -53.18569574]\n" ] } ], @@ -3161,1534 +223,7 @@ "outputs": [ { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2024-12-18T16:33:27.085982\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.5.1, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-10T10:26:48.787466\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -4701,7 +236,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "0c08c55a52774c709495d5894c19db0d", + "model_id": "794520c3a7fb4c8aaef400bcaa8e8d86", "version_major": 2, "version_minor": 0 }, @@ -4714,1805 +249,7 @@ }, { "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2024-12-18T16:33:27.952633\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.5.1, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-10T10:26:49.178463\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -6525,7 +262,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e465c105c5ad451bb9ab79297a8b9c96", + "model_id": "8a663c63c25b44b2a0870973a8c94321", "version_major": 2, "version_minor": 0 }, @@ -6599,7 +336,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.10.9" }, "vscode": { "interpreter": { From f6f26bbafd2f9645b22484200712f775fe34901b Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 10 Jan 2025 23:41:23 +0100 Subject: [PATCH 17/56] change import order --- PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py index 3d1908e5a..361803925 100644 --- a/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py +++ b/PySDM/physics/homogeneous_liquid_nucleation_rate/__init__.py @@ -2,6 +2,6 @@ homogeneous liquid droplet nucleation rate formulations """ +from PySDM.impl.null_physics_class import Null from .cnt import CNT from .constant import Constant -from PySDM.impl.null_physics_class import Null From 33e2e3aa01fedbf1bbed1f710d0d34bc3687982d Mon Sep 17 00:00:00 2001 From: claresinger Date: Mon, 13 Jan 2025 16:07:07 -0500 Subject: [PATCH 18/56] add expansion_chamber environment. todo check the thermodynamics here are correct. [skip ci] --- PySDM/environments/expansion_chamber.py | 138 ++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 PySDM/environments/expansion_chamber.py diff --git a/PySDM/environments/expansion_chamber.py b/PySDM/environments/expansion_chamber.py new file mode 100644 index 000000000..38cfc0d79 --- /dev/null +++ b/PySDM/environments/expansion_chamber.py @@ -0,0 +1,138 @@ +""" +Zero-dimensional expansion chamber framework +""" + +import numpy as np + +from PySDM.environments.impl.moist import Moist +from PySDM.impl.mesh import Mesh +from PySDM.initialisation.equilibrate_wet_radii import ( + default_rtol, + equilibrate_wet_radii, +) +from PySDM.environments.impl import register_environment + + +@register_environment() +class ExpansionChamber(Moist): + def __init__( + self, + *, + dt, + volume: float, + p0: float, + T0: float, + initial_water_vapour_mixing_ratio: float, + pf: float, + tf: float, + variables, + mixed_phase=False, + ): + super().__init__(dt, Mesh.mesh_0d(), variables, mixed_phase=mixed_phase) + + self.volume = volume + self.p0 = p0 + self.T0 = T0 + self.initial_water_vapour_mixing_ratio = initial_water_vapour_mixing_ratio + self.pf = pf + self.tf = tf + + self.formulae = None + self.delta_liquid_water_mixing_ratio = np.nan + self.params = None + + def register(self, builder): + self.formulae = builder.particulator.formulae + pd0 = self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio) + rhod0 = self.formulae.state_variable_triplet.rhod_of_pd_T(pd0, self.T0) + self.mesh.dv = self.volume + + Moist.register(self, builder) + + params = (self.p0, self.T0, self.initial_water_vapour_mixing_ratio, 0) + self["p"][:] = params[0] + self["T"][:] = params[1] + self["water_vapour_mixing_ratio"][:] = params[2] + self["t"][:] = params[3] + + self._tmp["water_vapour_mixing_ratio"][:] = params[0] + self.sync_chamber_vars() + Moist.sync(self) + self.notify() + + def init_attributes( + self, + *, + n_in_dv: [float, np.ndarray], + kappa: float, + r_dry: [float, np.ndarray], + rtol=default_rtol, + include_dry_volume_in_attribute: bool = True, + ): + if not isinstance(n_in_dv, np.ndarray): + r_dry = np.array([r_dry]) + n_in_dv = np.array([n_in_dv]) + + attributes = {} + dry_volume = self.formulae.trivia.volume(radius=r_dry) + attributes["kappa times dry volume"] = dry_volume * kappa + attributes["multiplicity"] = n_in_dv + r_wet = equilibrate_wet_radii( + r_dry=r_dry, + environment=self, + kappa_times_dry_volume=attributes["kappa times dry volume"], + rtol=rtol, + ) + attributes["volume"] = self.formulae.trivia.volume(radius=r_wet) + if include_dry_volume_in_attribute: + attributes["dry volume"] = dry_volume + return attributes + + def formulae_drho_dp(const, p, T, water_vapour_mixing_ratio, lv, dql_dp): + R_q = const.Rv / (1 / water_vapour_mixing_ratio + 1) + const.Rd / ( + 1 + water_vapour_mixing_ratio + ) + cp_q = const.c_pv / (1 / water_vapour_mixing_ratio + 1) + const.c_pd / ( + 1 + water_vapour_mixing_ratio + ) + return -1 / R_q / T - p / R_q / T**2 * lv / cp_q * dql_dp + + def advance_chamber_vars(self): + dt = self.particulator.dt + T = self["T"][0] + p = self["p"][0] + t = self["t"][0] + + dp_dt = (self.pf - self.p0) / (self.tf) * (self.dt / 2) # mid-point + water_vapour_mixing_ratio = ( + self["water_vapour_mixing_ratio"][0] + - self.delta_liquid_water_mixing_ratio / 2 + ) + + drho_dp = self.formulae_drho_dp( + p=p, + T=T, + water_vapour_mixing_ratio=water_vapour_mixing_ratio, + lv=self.formulae.latent_heat.lv(T), + dql_dp=self.delta_liquid_water_mixing_ratio / dt, + ) + drhod_dp = drho_dp + + self.particulator.backend.explicit_euler(self._tmp["t"], dt, 1) + self.particulator.backend.explicit_euler(self._tmp["p"], dt, dp_dt) + self.particulator.backend.explicit_euler( + self._tmp["rhod"], dt, drhod_dp * dp_dt + ) + + def sync_chamber_vars(self): + self.delta_liquid_water_mixing_ratio = ( + self._tmp["water_vapour_mixing_ratio"][0] + - self["water_vapour_mixing_ratio"][0] + ) + for var in self.variables: + self._tmp[var][:] = self[var][:] + + def sync(self): + self.sync_chamber_vars() + self.advance_chamber_vars() + super().sync() From 03bffe78547e4280319cb859029fda8a205f87cf Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Mon, 27 Jan 2025 00:15:49 +0100 Subject: [PATCH 19/56] refactor ExpansionChamber env and use it in Erinin_et_al_2025 example --- PySDM/environments/__init__.py | 1 + PySDM/environments/expansion_chamber.py | 163 +++----- PySDM/environments/impl/moist.py | 4 + PySDM/environments/impl/moist_lagrangian.py | 31 ++ PySDM/environments/parcel.py | 27 +- .../aerosol.py | 0 .../expansion_experiment.ipynb | 370 ++++++++++++++++++ .../expansion_simulation.py | 46 +-- .../Erinin_et_al_2025/fig_3.ipynb | 181 +++++++++ .../expansion_experiment.ipynb | 349 ----------------- .../chamber/erinin_et_al_2025/test_fig_3.py | 34 ++ .../environments/test_expansion_chamber.py | 10 + 12 files changed, 714 insertions(+), 502 deletions(-) create mode 100644 PySDM/environments/impl/moist_lagrangian.py rename examples/PySDM_examples/{expansion_chamber => Erinin_et_al_2025}/aerosol.py (100%) create mode 100644 examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb rename examples/PySDM_examples/{expansion_chamber => Erinin_et_al_2025}/expansion_simulation.py (83%) create mode 100644 examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb delete mode 100644 examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb create mode 100644 tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py create mode 100644 tests/unit_tests/environments/test_expansion_chamber.py diff --git a/PySDM/environments/__init__.py b/PySDM/environments/__init__.py index f9e9d18f9..e4fb48fdc 100644 --- a/PySDM/environments/__init__.py +++ b/PySDM/environments/__init__.py @@ -8,3 +8,4 @@ from .kinematic_1d import Kinematic1D from .kinematic_2d import Kinematic2D from .parcel import Parcel +from .expansion_chamber import ExpansionChamber diff --git a/PySDM/environments/expansion_chamber.py b/PySDM/environments/expansion_chamber.py index 38cfc0d79..c82999100 100644 --- a/PySDM/environments/expansion_chamber.py +++ b/PySDM/environments/expansion_chamber.py @@ -2,137 +2,90 @@ Zero-dimensional expansion chamber framework """ -import numpy as np +from typing import Optional, List -from PySDM.environments.impl.moist import Moist +from PySDM.environments.impl.moist_lagrangian import MoistLagrangian from PySDM.impl.mesh import Mesh -from PySDM.initialisation.equilibrate_wet_radii import ( - default_rtol, - equilibrate_wet_radii, -) from PySDM.environments.impl import register_environment @register_environment() -class ExpansionChamber(Moist): +class ExpansionChamber(MoistLagrangian): def __init__( self, *, dt, volume: float, - p0: float, - T0: float, - initial_water_vapour_mixing_ratio: float, - pf: float, - tf: float, - variables, + initial_pressure: float, + initial_temperature: float, + initial_relative_humidity: float, + delta_pressure: float, + delta_temperature: float, + delta_time: float, + variables: Optional[List[str]] = None, mixed_phase=False, ): - super().__init__(dt, Mesh.mesh_0d(), variables, mixed_phase=mixed_phase) + variables = (variables or []) + ["rhod"] - self.volume = volume - self.p0 = p0 - self.T0 = T0 - self.initial_water_vapour_mixing_ratio = initial_water_vapour_mixing_ratio - self.pf = pf - self.tf = tf + super().__init__(dt, Mesh.mesh_0d(), variables, mixed_phase=mixed_phase) - self.formulae = None - self.delta_liquid_water_mixing_ratio = np.nan - self.params = None + self.dv = volume + self.initial_pressure = initial_pressure + self.initial_temperature = initial_temperature + self.initial_relative_humidity = initial_relative_humidity + self.delta_time = delta_time + self.dp_dt = delta_pressure / delta_time + self.dT_dt = delta_temperature / delta_time def register(self, builder): - self.formulae = builder.particulator.formulae - pd0 = self.formulae.trivia.p_d(self.p0, self.initial_water_vapour_mixing_ratio) - rhod0 = self.formulae.state_variable_triplet.rhod_of_pd_T(pd0, self.T0) - self.mesh.dv = self.volume - - Moist.register(self, builder) - - params = (self.p0, self.T0, self.initial_water_vapour_mixing_ratio, 0) - self["p"][:] = params[0] - self["T"][:] = params[1] - self["water_vapour_mixing_ratio"][:] = params[2] - self["t"][:] = params[3] + self.mesh.dv = self.dv - self._tmp["water_vapour_mixing_ratio"][:] = params[0] - self.sync_chamber_vars() - Moist.sync(self) - self.notify() - - def init_attributes( - self, - *, - n_in_dv: [float, np.ndarray], - kappa: float, - r_dry: [float, np.ndarray], - rtol=default_rtol, - include_dry_volume_in_attribute: bool = True, - ): - if not isinstance(n_in_dv, np.ndarray): - r_dry = np.array([r_dry]) - n_in_dv = np.array([n_in_dv]) + super().register(builder) - attributes = {} - dry_volume = self.formulae.trivia.volume(radius=r_dry) - attributes["kappa times dry volume"] = dry_volume * kappa - attributes["multiplicity"] = n_in_dv - r_wet = equilibrate_wet_radii( - r_dry=r_dry, - environment=self, - kappa_times_dry_volume=attributes["kappa times dry volume"], - rtol=rtol, + formulae = self.particulator.formulae + pv0 = ( + self.initial_relative_humidity + * formulae.saturation_vapour_pressure.pvs_water(self.initial_temperature) ) - attributes["volume"] = self.formulae.trivia.volume(radius=r_wet) - if include_dry_volume_in_attribute: - attributes["dry volume"] = dry_volume - return attributes - - def formulae_drho_dp(const, p, T, water_vapour_mixing_ratio, lv, dql_dp): - R_q = const.Rv / (1 / water_vapour_mixing_ratio + 1) + const.Rd / ( - 1 + water_vapour_mixing_ratio + th_std = formulae.trivia.th_std( + p=self.initial_pressure, T=self.initial_temperature ) - cp_q = const.c_pv / (1 / water_vapour_mixing_ratio + 1) + const.c_pd / ( - 1 + water_vapour_mixing_ratio + initial_water_vapour_mixing_ratio = ( + formulae.constants.eps * pv0 / (self.initial_pressure - pv0) ) - return -1 / R_q / T - p / R_q / T**2 * lv / cp_q * dql_dp - - def advance_chamber_vars(self): - dt = self.particulator.dt - T = self["T"][0] - p = self["p"][0] - t = self["t"][0] - dp_dt = (self.pf - self.p0) / (self.tf) * (self.dt / 2) # mid-point - water_vapour_mixing_ratio = ( - self["water_vapour_mixing_ratio"][0] - - self.delta_liquid_water_mixing_ratio / 2 + self["rhod"][:] = formulae.state_variable_triplet.rho_d( + p=self.initial_pressure, + water_vapour_mixing_ratio=initial_water_vapour_mixing_ratio, + theta_std=th_std, ) - - drho_dp = self.formulae_drho_dp( - p=p, - T=T, - water_vapour_mixing_ratio=water_vapour_mixing_ratio, - lv=self.formulae.latent_heat.lv(T), - dql_dp=self.delta_liquid_water_mixing_ratio / dt, + self["thd"][:] = formulae.state_variable_triplet.th_dry( + th_std, initial_water_vapour_mixing_ratio ) - drhod_dp = drho_dp + self["water_vapour_mixing_ratio"][:] = initial_water_vapour_mixing_ratio - self.particulator.backend.explicit_euler(self._tmp["t"], dt, 1) - self.particulator.backend.explicit_euler(self._tmp["p"], dt, dp_dt) - self.particulator.backend.explicit_euler( - self._tmp["rhod"], dt, drhod_dp * dp_dt - ) + self.post_register() - def sync_chamber_vars(self): - self.delta_liquid_water_mixing_ratio = ( - self._tmp["water_vapour_mixing_ratio"][0] - - self["water_vapour_mixing_ratio"][0] - ) + def advance_moist_vars(self): + """compute new values of dry density and thd, and write them to self._tmp and self["thd"] + assuming water-vapour mixing ratio is not altered by the expansion""" + dt = self.particulator.dt + t_new = (self.particulator.n_steps + 1) * dt + if t_new > self.delta_time: + return + + formulae = self.particulator.formulae + p_new = self["p"][0] + self.dp_dt * dt + T_new = self["T"][0] + self.dT_dt * dt + wvmr_new = self._tmp["water_vapour_mixing_ratio"][ + 0 + ] # TODO #1492 - should _tmp or self[] be used? + pv_new = wvmr_new * p_new / (wvmr_new + formulae.constants.eps) + pd_new = p_new - pv_new + + self._tmp["rhod"][:] = pd_new / T_new / formulae.constants.Rd + self["thd"][:] = formulae.trivia.th_std(p=pd_new, T=T_new) + + def sync_moist_vars(self): for var in self.variables: self._tmp[var][:] = self[var][:] - - def sync(self): - self.sync_chamber_vars() - self.advance_chamber_vars() - super().sync() diff --git a/PySDM/environments/impl/moist.py b/PySDM/environments/impl/moist.py index bef7c02dc..35009a166 100644 --- a/PySDM/environments/impl/moist.py +++ b/PySDM/environments/impl/moist.py @@ -71,6 +71,8 @@ def _recalculate_temperature_pressure_relative_humidity(self, target): ) def sync(self): + """fills the "predicted" set of thermodynamic variables with derived values freshly + computed from `self.get_thd()` and `self.get_water_vapour_mixing_ratio()`""" target = self._tmp target["water_vapour_mixing_ratio"].ravel(self.get_water_vapour_mixing_ratio()) target["thd"].ravel(self.get_thd()) @@ -108,6 +110,8 @@ def get_thd(self) -> np.ndarray: raise NotImplementedError() def notify(self): + """invalidates the "predicted" set of thermodynamic variables storing its + contents into the "current" set of vars""" if self._values["predicted"] is None: return diff --git a/PySDM/environments/impl/moist_lagrangian.py b/PySDM/environments/impl/moist_lagrangian.py new file mode 100644 index 000000000..805d4b8d4 --- /dev/null +++ b/PySDM/environments/impl/moist_lagrangian.py @@ -0,0 +1,31 @@ +""" +Zero-dimensional (Lagrangian) moist environment commons +""" + +from PySDM.environments.impl.moist import Moist + + +class MoistLagrangian(Moist): + """base class for moist Lagrangian environments (parcel, chamber, ...)""" + + def get_thd(self): + return self["thd"] + + def get_water_vapour_mixing_ratio(self): + return self["water_vapour_mixing_ratio"] + + def sync(self): + self.sync_moist_vars() + self.advance_moist_vars() + super().sync() + + def post_register(self): + self.sync_moist_vars() + super().sync() + self.notify() + + def sync_moist_vars(self): + raise NotImplementedError() + + def advance_moist_vars(self): + raise NotImplementedError() diff --git a/PySDM/environments/parcel.py b/PySDM/environments/parcel.py index 589f8f3ff..078ad4499 100644 --- a/PySDM/environments/parcel.py +++ b/PySDM/environments/parcel.py @@ -6,7 +6,7 @@ import numpy as np -from PySDM.environments.impl.moist import Moist +from PySDM.environments.impl.moist_lagrangian import MoistLagrangian from PySDM.impl.mesh import Mesh from PySDM.initialisation.equilibrate_wet_radii import ( default_rtol, @@ -16,7 +16,7 @@ @register_environment() -class Parcel(Moist): # pylint: disable=too-many-instance-attributes +class Parcel(MoistLagrangian): # pylint: disable=too-many-instance-attributes def __init__( self, *, @@ -60,7 +60,7 @@ def register(self, builder): rhod0, self.mass_of_dry_air ) - Moist.register(self, builder) + super().register(builder) params = ( self.initial_water_vapour_mixing_ratio, @@ -74,11 +74,9 @@ def register(self, builder): self["rhod"][:] = params[2] self["z"][:] = params[3] self["t"][:] = params[4] - self._tmp["water_vapour_mixing_ratio"][:] = params[0] - self.sync_parcel_vars() - Moist.sync(self) - self.notify() + + self.post_register() def init_attributes( self, @@ -108,7 +106,7 @@ def init_attributes( attributes["dry volume"] = dry_volume return attributes - def advance_parcel_vars(self): + def advance_moist_vars(self): dt = self.particulator.dt T = self["T"][0] p = self["p"][0] @@ -143,21 +141,10 @@ def advance_parcel_vars(self): (self._tmp["rhod"][0] + self["rhod"][0]) / 2, self.mass_of_dry_air ) - def get_thd(self): - return self["thd"] - - def get_water_vapour_mixing_ratio(self): - return self["water_vapour_mixing_ratio"] - - def sync_parcel_vars(self): + def sync_moist_vars(self): self.delta_liquid_water_mixing_ratio = ( self._tmp["water_vapour_mixing_ratio"][0] - self["water_vapour_mixing_ratio"][0] ) for var in self.variables: self._tmp[var][:] = self[var][:] - - def sync(self): - self.sync_parcel_vars() - self.advance_parcel_vars() - super().sync() diff --git a/examples/PySDM_examples/expansion_chamber/aerosol.py b/examples/PySDM_examples/Erinin_et_al_2025/aerosol.py similarity index 100% rename from examples/PySDM_examples/expansion_chamber/aerosol.py rename to examples/PySDM_examples/Erinin_et_al_2025/aerosol.py diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb new file mode 100644 index 000000000..14bedb315 --- /dev/null +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -0,0 +1,370 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "modeling expansion-chamber experiments described in [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467)" + ] + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T22:59:10.526065Z", + "start_time": "2025-01-26T22:59:10.512257Z" + } + }, + "source": [ + "import sys\n", + "if 'google.colab' in sys.modules:\n", + " !pip --quiet install open-atmos-jupyter-utils\n", + " from open_atmos_jupyter_utils import pip_install_on_colab\n", + " pip_install_on_colab('PySDM-examples')" + ], + "outputs": [], + "execution_count": 1 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T22:59:15.132318Z", + "start_time": "2025-01-26T22:59:10.732787Z" + } + }, + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot\n", + "from open_atmos_jupyter_utils import show_plot\n", + "from PySDM import Formulae\n", + "from PySDM.physics import si\n", + "\n", + "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", + "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" + ], + "outputs": [], + "execution_count": 2 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T23:02:46.906285Z", + "start_time": "2025-01-26T23:02:15.511473Z" + } + }, + "source": [ + "n_sd_per_mode = 20\n", + "DT = .1 * si.s\n", + "\n", + "variables = [\"p\", \"T\", \"s\", \"water_vapour_mixing_ratio\", \"liquid_water_mixing_ratio\", \"reff\"]\n", + "offsets = [0, -273.15, 1, 0, 0, 0]\n", + "factors = [1/100, 1, 1, 1, 1, 1]\n", + "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\"]\n", + "fig,axes=pyplot.subplots(2,3,figsize=(10,5),sharex=True,sharey=False,constrained_layout=True)\n", + "\n", + "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", + "\n", + " formulae = Formulae()\n", + " const = formulae.constants\n", + " aerosol = AerosolChamber(\n", + " water_molar_volume=const.Mv / const.rho_w,\n", + " N=Na / si.cm**3,\n", + " )\n", + "\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, t_max=4*si.s, dt=DT)\n", + " \n", + " for i,ax in enumerate(axes.flatten()):\n", + " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", + " ax.plot(output.profile[\"t\"], y, label=f\"{Na:.0e}\")\n", + " # if i == 2:\n", + " # ax.set_yscale(\"log\")\n", + " ax.set_xlabel(\"Time [s]\")\n", + " ax.set_ylabel(ylabels[i])\n", + "\n", + "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", + "show_plot(\"C0_sweep_traces.pdf\")" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:02:46.720656\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./C0_sweep_traces.pdf
\"), HT…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "fc98cca144cd4ae88fcbc22ce0239bf5" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 7 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T23:10:25.862264Z", + "start_time": "2025-01-26T23:04:07.407334Z" + } + }, + "source": [ + "n_sd_per_mode = 20\n", + "\n", + "p0 = 1000 * si.hPa\n", + "dp = np.insert(np.linspace(100,600,11),0,1) * si.hPa\n", + "Tmin = np.zeros_like(dp)\n", + "Smax = np.zeros_like(dp)\n", + "Tmin_clean = np.zeros_like(dp)\n", + "Smax_clean = np.zeros_like(dp)\n", + "Tmin_dry = np.zeros_like(dp)\n", + "Smax_dry = np.zeros_like(dp)\n", + "for i,dpi in enumerate(dp):\n", + " print(i,dpi)\n", + "\n", + " formulae = Formulae()\n", + " const = formulae.constants\n", + " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=2000 / si.cm**3)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " Tmin[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=1 / si.cm**3)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " Tmin_clean[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax_clean[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " Tmin_dry[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", + " Smax_dry[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "\n", + "print(dp)\n", + "print(Tmin)\n", + "print(Tmin_clean)\n", + "print(Tmin_dry)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 100.0\n", + "1 10000.0\n", + "2 15000.0\n", + "3 20000.0\n", + "4 25000.0\n", + "5 30000.0\n", + "6 35000.0\n", + "7 40000.0\n", + "8 45000.0\n", + "9 50000.0\n", + "10 55000.0\n", + "11 60000.0\n", + "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", + " 55000. 60000.]\n", + "[ 2.92063635 1.41283528 0.68841887 -0.24955163 -1.18235359 -2.12624348\n", + " -3.11137862 -4.15267802 -5.24563101 -6.39500098 -7.60453316 -8.87540371]\n", + "[-12.11122229 -12.11908333 -12.1228248 -12.12642564 -12.12978967\n", + " -12.13295447 -12.13595697 -12.13871335 -12.14123448 -12.14353175\n", + " -12.1455377 -12.14725418]\n", + "[-12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", + " -12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", + " -12.15000008 -12.15000008]\n" + ] + } + ], + "execution_count": 8 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T23:10:25.887693Z", + "start_time": "2025-01-26T23:10:25.865329Z" + } + }, + "source": [ + "print(\"p0 =\",p0,\"Pa\")\n", + "print(\"T0 =\",296-273.15,\"°C\")\n", + "print(\"dp =\",dp)\n", + "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", + "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", + "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" + ], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "p0 = 100000.0 Pa\n", + "T0 = 22.850000000000023 °C\n", + "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", + " 55000. 60000.]\n", + "Tmin (S0=0.5, C0=2000) = [ 2.92063635 1.41283528 0.68841887 -0.24955163 -1.18235359 -2.12624348\n", + " -3.11137862 -4.15267802 -5.24563101 -6.39500098 -7.60453316 -8.87540371]\n", + "Tmin (S0=0.5, C0=1) = [-12.11122229 -12.11908333 -12.1228248 -12.12642564 -12.12978967\n", + " -12.13295447 -12.13595697 -12.13871335 -12.14123448 -12.14353175\n", + " -12.1455377 -12.14725418]\n", + "Tmin (S0=0, C0=1) = [-12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", + " -12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", + " -12.15000008 -12.15000008]\n" + ] + } + ], + "execution_count": 9 + }, + { + "cell_type": "code", + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-26T23:10:44.964277Z", + "start_time": "2025-01-26T23:10:40.873425Z" + } + }, + "source": [ + "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", + "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", + "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", + "ax.legend(loc=3, frameon=False)\n", + "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", + "show_plot(\"Tmin_dp.pdf\")\n", + "\n", + "#########\n", + "\n", + "fig,axes = pyplot.subplots(2,1,figsize=(6,6),sharex=True)\n", + "\n", + "ax = axes[0]\n", + "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", + "ax.legend(loc=3, frameon=False)\n", + "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", + "\n", + "ax = axes[1]\n", + "ax.plot(dp/p0, Smax_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Smax_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", + "ax.plot(dp/p0, Smax, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", + "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", + "ax.set_ylabel(r\"$S_{max}$\")\n", + "# ax.set_yscale(\"log\")\n", + "ax.set_ylim(-0.5,6)\n", + "ax.axhline(0, color=\"k\", lw=0.5)\n", + "ax.axhline(1, color=\"k\", lw=0.5)\n", + "ax.axhline(4, color=\"k\", lw=0.5)\n", + "\n", + "show_plot(\"dp_sweep.pdf\")" + ], + "outputs": [ + { + "data": { + "text/plain": [ + "
" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:10:42.435826\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./Tmin_dp.pdf
\"), HTML(value=\"" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:10:44.732784\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./dp_sweep.pdf
\"), HTML(value=\"" + ], + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:09:45.089552\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "HBox(children=(HTML(value=\"./fig_3.pdf
\"), HTML(value=\"\n\n\n \n \n \n \n 2025-01-10T10:00:24.794175\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2b728273fc454d1fa2daaeeec91d0a6e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./C0_sweep_traces.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "n_sd_per_mode = 20\n", - "\n", - "# plot p, T, S, qv, ql, reff\n", - "variables = [\"p\",\"T\",\"s\",\"water_vapour_mixing_ratio\",\"liquid_water_mixing_ratio\",\"reff\"]\n", - "offsets = [0, -273.15, 1, 0, 0, 0]\n", - "factors = [1/100, 1, 1, 1, 1, 1]\n", - "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\"]\n", - "fig,axes=pyplot.subplots(2,3,figsize=(10,5),sharex=True,sharey=False,constrained_layout=True)\n", - "\n", - "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", - "\n", - " formulae = Formulae()\n", - " const = formulae.constants\n", - " aerosol = AerosolChamber(\n", - " water_molar_volume=const.Mv / const.rho_w,\n", - " N=Na / si.cm**3,\n", - " )\n", - "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, t_max=4*si.s, dz=10*si.m)\n", - " \n", - " for i,ax in enumerate(axes.flatten()):\n", - " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", - " ax.plot(output.profile[\"t\"], y, label=f\"{Na:.0e}\")\n", - " # if i == 2:\n", - " # ax.set_yscale(\"log\")\n", - " ax.set_xlabel(\"Time [s]\")\n", - " ax.set_ylabel(ylabels[i])\n", - "\n", - "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", - "show_plot(\"C0_sweep_traces.pdf\")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 100.0\n", - "1 10000.0\n", - "2 15000.0\n", - "3 20000.0\n", - "4 25000.0\n", - "5 30000.0\n", - "6 35000.0\n", - "7 40000.0\n", - "8 45000.0\n", - "9 50000.0\n", - "10 55000.0\n", - "11 60000.0\n", - "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", - " 55000. 60000.]\n", - "[ 22.75198082 14.02926384 9.32894287 4.84298637 1.22984962\n", - " -2.41778535 -6.61993709 -11.54010229 -17.35239681 -24.22128186\n", - " -32.36940492 -41.89363976]\n", - "[ 22.75198932 14.02900637 9.3244501 4.22820117 -1.16081875\n", - " -6.84264641 -13.01362538 -19.67438567 -26.92357005 -34.85977791\n", - " -43.67940643 -53.4807279 ]\n", - "[ 22.75239692 14.06569695 9.38070731 4.30527889 -1.06298968\n", - " -6.72410413 -12.87328359 -19.51053959 -26.7334935 -34.63977286\n", - " -43.42462336 -53.18569574]\n" - ] - } - ], - "source": [ - "n_sd_per_mode = 20\n", - "\n", - "p0 = 1000 * si.hPa\n", - "dp = np.insert(np.linspace(100,600,11),0,1) * si.hPa\n", - "Tmin = np.zeros_like(dp)\n", - "Smax = np.zeros_like(dp)\n", - "Tmin_clean = np.zeros_like(dp)\n", - "Smax_clean = np.zeros_like(dp)\n", - "Tmin_dry = np.zeros_like(dp)\n", - "Smax_dry = np.zeros_like(dp)\n", - "for i,dpi in enumerate(dp):\n", - " print(i,dpi)\n", - "\n", - " formulae = Formulae()\n", - " const = formulae.constants\n", - " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=2000 / si.cm**3)\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", - " Tmin[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", - "\n", - " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=1 / si.cm**3)\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", - " Tmin_clean[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax_clean[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", - "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dz=10*si.m)\n", - " Tmin_dry[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax_dry[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", - "\n", - "print(dp)\n", - "print(Tmin)\n", - "print(Tmin_clean)\n", - "print(Tmin_dry)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "p0 = 100000.0 Pa\n", - "T0 = 22.850000000000023 °C\n", - "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", - " 55000. 60000.]\n", - "Tmin (S0=0.5, C0=2000) = [ 22.75198082 14.02926384 9.32894287 4.84298637 1.22984962\n", - " -2.41778535 -6.61993709 -11.54010229 -17.35239681 -24.22128186\n", - " -32.36940492 -41.89363976]\n", - "Tmin (S0=0.5, C0=1) = [ 22.75198932 14.02900637 9.3244501 4.22820117 -1.16081875\n", - " -6.84264641 -13.01362538 -19.67438567 -26.92357005 -34.85977791\n", - " -43.67940643 -53.4807279 ]\n", - "Tmin (S0=0, C0=1) = [ 22.75239692 14.06569695 9.38070731 4.30527889 -1.06298968\n", - " -6.72410413 -12.87328359 -19.51053959 -26.7334935 -34.63977286\n", - " -43.42462336 -53.18569574]\n" - ] - } - ], - "source": [ - "print(\"p0 =\",p0,\"Pa\")\n", - "print(\"T0 =\",296-273.15,\"°C\")\n", - "print(\"dp =\",dp)\n", - "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", - "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", - "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-10T10:26:48.787466\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "794520c3a7fb4c8aaef400bcaa8e8d86", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./Tmin_dp.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-10T10:26:49.178463\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "8a663c63c25b44b2a0870973a8c94321", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./dp_sweep.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", - "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", - "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", - "ax.legend(loc=3, frameon=False)\n", - "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", - "show_plot(\"Tmin_dp.pdf\")\n", - "\n", - "#########\n", - "\n", - "fig,axes = pyplot.subplots(2,1,figsize=(6,6),sharex=True)\n", - "\n", - "ax = axes[0]\n", - "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", - "ax.legend(loc=3, frameon=False)\n", - "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", - "\n", - "ax = axes[1]\n", - "ax.plot(dp/p0, Smax_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Smax_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Smax, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", - "ax.set_ylabel(r\"$S_{max}$\")\n", - "# ax.set_yscale(\"log\")\n", - "ax.set_ylim(-0.5,6)\n", - "ax.axhline(0, color=\"k\", lw=0.5)\n", - "ax.axhline(1, color=\"k\", lw=0.5)\n", - "ax.axhline(4, color=\"k\", lw=0.5)\n", - "\n", - "show_plot(\"dp_sweep.pdf\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.9" - }, - "vscode": { - "interpreter": { - "hash": "b14f34a08619f4a218d80d7380beed3f0c712c89ff93e7183219752d640ed427" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py b/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py new file mode 100644 index 000000000..97d1d1615 --- /dev/null +++ b/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py @@ -0,0 +1,34 @@ +from pathlib import Path +import numpy as np +import pytest +from open_atmos_jupyter_utils import notebook_vars +from PySDM.physics import si +from PySDM_examples import Erinin_et_al_2025 + +PLOT = False + + +@pytest.fixture(scope="session", name="notebook_variables") +def notebook_variables_fixture(): + return notebook_vars( + file=Path(Erinin_et_al_2025.__file__).parent / "fig_3.ipynb", + plot=PLOT, + ) + + +class TestFig3: + @staticmethod + def test_final_pressure(notebook_variables): + assert ( + 0.45 * si.bar + < np.amin(notebook_variables["output"]["ambient pressure"]) + < 0.46 * si.bar + ) + + @staticmethod + def test_final_temperature(notebook_variables): + assert ( + 258 * si.K + < np.amin(notebook_variables["output"]["ambient temperature"]) + < 259 * si.K + ) diff --git a/tests/unit_tests/environments/test_expansion_chamber.py b/tests/unit_tests/environments/test_expansion_chamber.py new file mode 100644 index 000000000..3d830d327 --- /dev/null +++ b/tests/unit_tests/environments/test_expansion_chamber.py @@ -0,0 +1,10 @@ +from PySDM.environments import ExpansionChamber + + +def test_expansion_chamber(): + # arrange + env = ExpansionChamber() + + # act + + # assert From ce6e4546315db6d485458ab2767fcb681b10bcb6 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Mon, 27 Jan 2025 00:16:11 +0100 Subject: [PATCH 20/56] forgotten __init__ move --- examples/PySDM_examples/Erinin_et_al_2025/__init__.py | 4 ++++ examples/PySDM_examples/expansion_chamber/__init__.py | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 100644 examples/PySDM_examples/Erinin_et_al_2025/__init__.py delete mode 100644 examples/PySDM_examples/expansion_chamber/__init__.py diff --git a/examples/PySDM_examples/Erinin_et_al_2025/__init__.py b/examples/PySDM_examples/Erinin_et_al_2025/__init__.py new file mode 100644 index 000000000..3916bea26 --- /dev/null +++ b/examples/PySDM_examples/Erinin_et_al_2025/__init__.py @@ -0,0 +1,4 @@ +# pylint: disable=invalid-name +""" +expansion chamber example based on [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467) +""" diff --git a/examples/PySDM_examples/expansion_chamber/__init__.py b/examples/PySDM_examples/expansion_chamber/__init__.py deleted file mode 100644 index 8fca36f41..000000000 --- a/examples/PySDM_examples/expansion_chamber/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=invalid-name -""" -expansion chamber example imagined as an ascending parcel with updraft velocity matched to dp/dt -""" From b91a94cf91aeb4426039eb2281f8115e6a43d586 Mon Sep 17 00:00:00 2001 From: claresinger Date: Wed, 29 Jan 2025 14:46:28 -0500 Subject: [PATCH 21/56] replace assumed temperature profile with adiabatic temperature condition. --- PySDM/environments/expansion_chamber.py | 6 +- .../expansion_experiment.ipynb | 282 +++++++++--------- .../Erinin_et_al_2025/expansion_simulation.py | 14 +- .../Erinin_et_al_2025/fig_3.ipynb | 122 ++++---- 4 files changed, 218 insertions(+), 206 deletions(-) diff --git a/PySDM/environments/expansion_chamber.py b/PySDM/environments/expansion_chamber.py index c82999100..9b1346088 100644 --- a/PySDM/environments/expansion_chamber.py +++ b/PySDM/environments/expansion_chamber.py @@ -20,7 +20,6 @@ def __init__( initial_temperature: float, initial_relative_humidity: float, delta_pressure: float, - delta_temperature: float, delta_time: float, variables: Optional[List[str]] = None, mixed_phase=False, @@ -35,7 +34,6 @@ def __init__( self.initial_relative_humidity = initial_relative_humidity self.delta_time = delta_time self.dp_dt = delta_pressure / delta_time - self.dT_dt = delta_temperature / delta_time def register(self, builder): self.mesh.dv = self.dv @@ -76,7 +74,9 @@ def advance_moist_vars(self): formulae = self.particulator.formulae p_new = self["p"][0] + self.dp_dt * dt - T_new = self["T"][0] + self.dT_dt * dt + T_new = self.initial_temperature * (self.initial_pressure / p_new) ** ( + -2 / 7 + ) # adiabatic condition wvmr_new = self._tmp["water_vapour_mixing_ratio"][ 0 ] # TODO #1492 - should _tmp or self[] be used? diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 14bedb315..475e14986 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,30 +18,32 @@ }, { "cell_type": "code", + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T22:59:10.526065Z", "start_time": "2025-01-26T22:59:10.512257Z" } }, + "outputs": [], "source": [ "import sys\n", "if 'google.colab' in sys.modules:\n", " !pip --quiet install open-atmos-jupyter-utils\n", " from open_atmos_jupyter_utils import pip_install_on_colab\n", " pip_install_on_colab('PySDM-examples')" - ], - "outputs": [], - "execution_count": 1 + ] }, { "cell_type": "code", + "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T22:59:15.132318Z", "start_time": "2025-01-26T22:59:10.732787Z" } }, + "outputs": [], "source": [ "import numpy as np\n", "from matplotlib import pyplot\n", @@ -51,18 +53,45 @@ "\n", "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" - ], - "outputs": [], - "execution_count": 2 + ] }, { "cell_type": "code", + "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T23:02:46.906285Z", "start_time": "2025-01-26T23:02:15.511473Z" } }, + "outputs": [ + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:40:07.279582\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5fd67c7a698f44bc879854d84565f3fa", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./C0_sweep_traces.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "n_sd_per_mode = 20\n", "DT = .1 * si.s\n", @@ -82,7 +111,7 @@ " N=Na / si.cm**3,\n", " )\n", "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, t_max=4*si.s, dt=DT)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, total_time=4*si.s, dt=DT)\n", " \n", " for i,ax in enumerate(axes.flatten()):\n", " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", @@ -94,43 +123,48 @@ "\n", "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", "show_plot(\"C0_sweep_traces.pdf\")" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:02:46.720656\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "HBox(children=(HTML(value=\"./C0_sweep_traces.pdf
\"), HT…" - ], - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "fc98cca144cd4ae88fcbc22ce0239bf5" - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "execution_count": 7 + ] }, { "cell_type": "code", + "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T23:10:25.862264Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 100.0\n", + "1 10000.0\n", + "2 15000.0\n", + "3 20000.0\n", + "4 25000.0\n", + "5 30000.0\n", + "6 35000.0\n", + "7 40000.0\n", + "8 45000.0\n", + "9 50000.0\n", + "10 55000.0\n", + "11 60000.0\n", + "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", + " 55000. 60000.]\n", + "[ 22.76539614 14.07241918 9.42251052 5.04148984 1.22854917\n", + " -2.73095271 -7.13023918 -12.04458049 -17.52580689 -23.59720075\n", + " -30.26381921 -37.57848389]\n", + "[ 22.76539835 14.07229129 9.41976599 4.56762734 -0.50557679\n", + " -5.82580613 -11.4243729 -17.33934874 -23.61770124 -30.31832231\n", + " -37.51668399 -45.31183296]\n", + "[ 22.76539833 14.0722912 9.41976459 4.56742887 -0.50663758\n", + " -5.82842689 -11.42911249 -17.34657562 -23.62755213 -30.33073466\n", + " -37.53139951 -45.32857413]\n" + ] + } + ], "source": [ "n_sd_per_mode = 20\n", "\n", @@ -165,55 +199,17 @@ "print(Tmin)\n", "print(Tmin_clean)\n", "print(Tmin_dry)" - ], - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 100.0\n", - "1 10000.0\n", - "2 15000.0\n", - "3 20000.0\n", - "4 25000.0\n", - "5 30000.0\n", - "6 35000.0\n", - "7 40000.0\n", - "8 45000.0\n", - "9 50000.0\n", - "10 55000.0\n", - "11 60000.0\n", - "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", - " 55000. 60000.]\n", - "[ 2.92063635 1.41283528 0.68841887 -0.24955163 -1.18235359 -2.12624348\n", - " -3.11137862 -4.15267802 -5.24563101 -6.39500098 -7.60453316 -8.87540371]\n", - "[-12.11122229 -12.11908333 -12.1228248 -12.12642564 -12.12978967\n", - " -12.13295447 -12.13595697 -12.13871335 -12.14123448 -12.14353175\n", - " -12.1455377 -12.14725418]\n", - "[-12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", - " -12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", - " -12.15000008 -12.15000008]\n" - ] - } - ], - "execution_count": 8 + ] }, { "cell_type": "code", + "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T23:10:25.887693Z", "start_time": "2025-01-26T23:10:25.865329Z" } }, - "source": [ - "print(\"p0 =\",p0,\"Pa\")\n", - "print(\"T0 =\",296-273.15,\"°C\")\n", - "print(\"dp =\",dp)\n", - "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", - "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", - "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" - ], "outputs": [ { "name": "stdout", @@ -223,27 +219,90 @@ "T0 = 22.850000000000023 °C\n", "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", " 55000. 60000.]\n", - "Tmin (S0=0.5, C0=2000) = [ 2.92063635 1.41283528 0.68841887 -0.24955163 -1.18235359 -2.12624348\n", - " -3.11137862 -4.15267802 -5.24563101 -6.39500098 -7.60453316 -8.87540371]\n", - "Tmin (S0=0.5, C0=1) = [-12.11122229 -12.11908333 -12.1228248 -12.12642564 -12.12978967\n", - " -12.13295447 -12.13595697 -12.13871335 -12.14123448 -12.14353175\n", - " -12.1455377 -12.14725418]\n", - "Tmin (S0=0, C0=1) = [-12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", - " -12.15000008 -12.15000008 -12.15000008 -12.15000008 -12.15000008\n", - " -12.15000008 -12.15000008]\n" + "Tmin (S0=0.5, C0=2000) = [ 22.76539614 14.07241918 9.42251052 5.04148984 1.22854917\n", + " -2.73095271 -7.13023918 -12.04458049 -17.52580689 -23.59720075\n", + " -30.26381921 -37.57848389]\n", + "Tmin (S0=0.5, C0=1) = [ 22.76539835 14.07229129 9.41976599 4.56762734 -0.50557679\n", + " -5.82580613 -11.4243729 -17.33934874 -23.61770124 -30.31832231\n", + " -37.51668399 -45.31183296]\n", + "Tmin (S0=0, C0=1) = [ 22.76539833 14.0722912 9.41976459 4.56742887 -0.50663758\n", + " -5.82842689 -11.42911249 -17.34657562 -23.62755213 -30.33073466\n", + " -37.53139951 -45.32857413]\n" ] } ], - "execution_count": 9 + "source": [ + "print(\"p0 =\",p0,\"Pa\")\n", + "print(\"T0 =\",296-273.15,\"°C\")\n", + "print(\"dp =\",dp)\n", + "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", + "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", + "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" + ] }, { "cell_type": "code", + "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T23:10:44.964277Z", "start_time": "2025-01-26T23:10:40.873425Z" } }, + "outputs": [ + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:42:26.145849\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fafd72b8735245368a0ad8eaaa2c0b7e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./Tmin_dp.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:42:26.648680\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "27155a3c6f8c4efabb0091474c22289a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./dp_sweep.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", @@ -280,58 +339,7 @@ "ax.axhline(4, color=\"k\", lw=0.5)\n", "\n", "show_plot(\"dp_sweep.pdf\")" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "
" - ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:10:42.435826\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "HBox(children=(HTML(value=\"./Tmin_dp.pdf
\"), HTML(value=\"" - ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:10:44.732784\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "HBox(children=(HTML(value=\"./dp_sweep.pdf
\"), HTML(value=\"\n\n\n \n \n \n \n 2025-01-29T14:39:35.762702\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ - "
" - ], - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-27T00:09:45.089552\n image/svg+xml\n \n \n Matplotlib v3.8.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n" + "
" + ] + }, + "metadata": { + "needs_background": "light" }, - "metadata": {}, "output_type": "display_data" }, { "data": { - "text/plain": [ - "HBox(children=(HTML(value=\"./fig_3.pdf
\"), HTML(value=\"./fig_3
\")" + ] }, "metadata": {}, "output_type": "display_data" } ], - "execution_count": 9 + "source": [ + "fig, axs = pyplot.subplot_mosaic([['p'], ['RH'], ['T']], sharex=True, figsize=(5, 8))\n", + "\n", + "axs[\"p\"].plot(output['time'], in_unit(np.asarray(output['ambient pressure']), si.bar))\n", + "axs[\"p\"].set_ylabel('p (bar)')\n", + "\n", + "axs[\"RH\"].plot(output['time'], in_unit(np.asarray(output['ambient relative humidity']), PER_CENT))\n", + "axs[\"RH\"].set_ylabel('RH (%)')\n", + "\n", + "axs[\"T\"].plot(output['time'], np.asarray(output['ambient temperature']) - Formulae().constants.T0)\n", + "axs[\"T\"].set_ylabel('T (°C)')\n", + "axs[\"T\"].set_xlabel('t (s)')\n", + "for ax in axs.values(): ax.grid()\n", + "show_plot(filename='fig_3')" + ] }, { + "cell_type": "code", + "execution_count": null, + "id": "aa3c59f9f4f8b6e2", "metadata": { "ExecuteTime": { "end_time": "2025-01-25T23:19:48.244382956Z", "start_time": "2025-01-25T23:17:35.487229Z" } }, - "cell_type": "code", - "source": "", - "id": "aa3c59f9f4f8b6e2", "outputs": [], - "execution_count": null + "source": [] }, { - "metadata": {}, "cell_type": "code", - "outputs": [], "execution_count": null, - "source": "", - "id": "2dff758ee450b45c" + "id": "2dff758ee450b45c", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3.10.9 ('pysdm')", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "vscode": { + "interpreter": { + "hash": "b14f34a08619f4a218d80d7380beed3f0c712c89ff93e7183219752d640ed427" + } } }, "nbformat": 4, From a7f4950f56bbc69e10bee9b089e260879c1d36c3 Mon Sep 17 00:00:00 2001 From: claresinger Date: Wed, 29 Jan 2025 17:10:24 -0500 Subject: [PATCH 22/56] add new physics formulae for adiabatic exponent --- PySDM/environments/expansion_chamber.py | 8 +++++--- PySDM/formulae.py | 2 ++ PySDM/physics/__init__.py | 1 + PySDM/physics/adiabatic_exponent/__init__.py | 6 ++++++ PySDM/physics/adiabatic_exponent/dry.py | 13 +++++++++++++ .../adiabatic_exponent/moist_leading_terms.py | 18 ++++++++++++++++++ PySDM/physics/constants_defaults.py | 3 +++ .../expansion_experiment.ipynb | 8 ++++---- .../Erinin_et_al_2025/fig_3.ipynb | 4 ++-- 9 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 PySDM/physics/adiabatic_exponent/__init__.py create mode 100644 PySDM/physics/adiabatic_exponent/dry.py create mode 100644 PySDM/physics/adiabatic_exponent/moist_leading_terms.py diff --git a/PySDM/environments/expansion_chamber.py b/PySDM/environments/expansion_chamber.py index 9b1346088..10cfa5c61 100644 --- a/PySDM/environments/expansion_chamber.py +++ b/PySDM/environments/expansion_chamber.py @@ -74,9 +74,11 @@ def advance_moist_vars(self): formulae = self.particulator.formulae p_new = self["p"][0] + self.dp_dt * dt - T_new = self.initial_temperature * (self.initial_pressure / p_new) ** ( - -2 / 7 - ) # adiabatic condition + qv = self["water_vapour_mixing_ratio"][0] + gg = ( + 1 - formulae.adiabatic_exponent.gamma(qv) + ) / formulae.adiabatic_exponent.gamma(qv) + T_new = self.initial_temperature * (self.initial_pressure / p_new) ** gg wvmr_new = self._tmp["water_vapour_mixing_ratio"][ 0 ] # TODO #1492 - should _tmp or self[] be used? diff --git a/PySDM/formulae.py b/PySDM/formulae.py index 0b6ad1b0f..ac34339b2 100644 --- a/PySDM/formulae.py +++ b/PySDM/formulae.py @@ -58,6 +58,7 @@ def __init__( # pylint: disable=too-many-locals terminal_velocity: str = "GunnKinzer1949", air_dynamic_viscosity: str = "ZografosEtAl1987", bulk_phase_partitioning: str = "Null", + adiabatic_exponent: str = "Dry", handle_all_breakups: bool = False, ): # initialisation of the fields below is just to silence pylint and to enable code hints @@ -92,6 +93,7 @@ def __init__( # pylint: disable=too-many-locals self.air_dynamic_viscosity = air_dynamic_viscosity self.terminal_velocity = terminal_velocity self.bulk_phase_partitioning = bulk_phase_partitioning + self.adiabatic_exponent = adiabatic_exponent self._components = tuple( i diff --git a/PySDM/physics/__init__.py b/PySDM/physics/__init__.py index 0257b09e7..d50d8fc33 100644 --- a/PySDM/physics/__init__.py +++ b/PySDM/physics/__init__.py @@ -48,5 +48,6 @@ air_dynamic_viscosity, terminal_velocity, bulk_phase_partitioning, + adiabatic_exponent, ) from .constants import convert_to, in_unit, si diff --git a/PySDM/physics/adiabatic_exponent/__init__.py b/PySDM/physics/adiabatic_exponent/__init__.py new file mode 100644 index 000000000..d852b87f3 --- /dev/null +++ b/PySDM/physics/adiabatic_exponent/__init__.py @@ -0,0 +1,6 @@ +""" +Alternative formulations of adiabatic exponent +""" + +from .dry import Dry +from .moist_leading_terms import MoistLeadingTerms diff --git a/PySDM/physics/adiabatic_exponent/dry.py b/PySDM/physics/adiabatic_exponent/dry.py new file mode 100644 index 000000000..973e98651 --- /dev/null +++ b/PySDM/physics/adiabatic_exponent/dry.py @@ -0,0 +1,13 @@ +""" +adiabatic exponent, dry air +""" + + +class Dry: + def __init__(self, _): + pass + + # pylint: disable=too-many-arguments + @staticmethod + def gamma(const, qv): + return 1 + const.Rd / const.c_vd diff --git a/PySDM/physics/adiabatic_exponent/moist_leading_terms.py b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py new file mode 100644 index 000000000..799a0fee9 --- /dev/null +++ b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py @@ -0,0 +1,18 @@ +""" +adiabatic exponent, moist air, expanding to first order in qv, assuming qt=qv +""" + + +class MoistLeadingTerms: + def __init__(self, _): + pass + + # pylint: disable=too-many-arguments + @staticmethod + def gamma(const, qv): + return ( + 1 + + const.Rd / const.c_vd + + (const.Rv * qv) / (const.c_vd * (1 - qv)) + - (const.Rd * qv * const.c_vv) / (const.c_vd**2 * (1 - qv)) + ) diff --git a/PySDM/physics/constants_defaults.py b/PySDM/physics/constants_defaults.py index 5f4a19a85..80c6728b9 100644 --- a/PySDM/physics/constants_defaults.py +++ b/PySDM/physics/constants_defaults.py @@ -681,6 +681,9 @@ def compute_derived_values(c: dict): c["Rd_over_c_pd"] = c["Rd"] / c["c_pd"] + c["c_vd"] = c["c_pd"] - c["Rd"] + c["c_vv"] = c["c_pv"] - c["Rv"] + c["water_molar_volume"] = c["Mv"] / c["rho_w"] c["rho_STP"] = c["p_STP"] / c["Rd"] / c["T_STP"] c["H_u"] = c["M"] / c["p_STP"] diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 475e14986..b656c456c 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-26T22:59:15.132318Z", @@ -67,7 +67,7 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:40:07.279582\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T17:09:49.262684\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -80,7 +80,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5fd67c7a698f44bc879854d84565f3fa", + "model_id": "936f1b6b885a41aeb122de35134dcd71", "version_major": 2, "version_minor": 0 }, @@ -104,7 +104,7 @@ "\n", "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", "\n", - " formulae = Formulae()\n", + " formulae = Formulae(adiabatic_exponent=\"MoistLeadingTerms\")\n", " const = formulae.constants\n", " aerosol = AerosolChamber(\n", " water_molar_volume=const.Mv / const.rho_w,\n", diff --git a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb index ce50925a5..7b8e7a76b 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb @@ -95,7 +95,7 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:39:35.762702\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T17:07:20.007944\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -108,7 +108,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "d805a41f69e049368dc4643b78b11b02", + "model_id": "b256bffaf9a54c32b90b3259cfc86c27", "version_major": 2, "version_minor": 0 }, From 4ffd684dfdfff5920ee9cd0b7c0dc818ec6cbd95 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 30 Jan 2025 16:53:03 +0100 Subject: [PATCH 23/56] introduce homogeneous nucleation dynamic with some common code with seeding (termed spawning) --- PySDM/backends/impl_numba/methods/__init__.py | 2 +- ...seeding_methods.py => spawning_methods.py} | 38 +++++++++---------- .../dynamics/homogeneous_liquid_nucleation.py | 36 ++++++++++++++++++ PySDM/dynamics/impl/__init__.py | 1 + .../impl/super_particle_spawning_dynamic.py | 2 + PySDM/dynamics/seeding.py | 13 ++++--- PySDM/particulator.py | 32 ++++++++-------- 7 files changed, 82 insertions(+), 42 deletions(-) rename PySDM/backends/impl_numba/methods/{seeding_methods.py => spawning_methods.py} (60%) create mode 100644 PySDM/dynamics/homogeneous_liquid_nucleation.py create mode 100644 PySDM/dynamics/impl/super_particle_spawning_dynamic.py diff --git a/PySDM/backends/impl_numba/methods/__init__.py b/PySDM/backends/impl_numba/methods/__init__.py index 73d7ceed3..bab4fc1b8 100644 --- a/PySDM/backends/impl_numba/methods/__init__.py +++ b/PySDM/backends/impl_numba/methods/__init__.py @@ -12,4 +12,4 @@ from .pair_methods import PairMethods from .physics_methods import PhysicsMethods from .terminal_velocity_methods import TerminalVelocityMethods -from .seeding_methods import SeedingMethods +from .spawning_methods import SpawningMethods diff --git a/PySDM/backends/impl_numba/methods/seeding_methods.py b/PySDM/backends/impl_numba/methods/spawning_methods.py similarity index 60% rename from PySDM/backends/impl_numba/methods/seeding_methods.py rename to PySDM/backends/impl_numba/methods/spawning_methods.py index a1e6372ba..ec6fb3832 100644 --- a/PySDM/backends/impl_numba/methods/seeding_methods.py +++ b/PySDM/backends/impl_numba/methods/spawning_methods.py @@ -1,4 +1,4 @@ -""" CPU implementation of backend methods for particle injections """ +""" CPU implementation of backend methods for particle spawning """ from functools import cached_property @@ -7,17 +7,17 @@ from PySDM.backends.impl_common.backend_methods import BackendMethods -class SeedingMethods(BackendMethods): # pylint: disable=too-few-public-methods +class SpawningMethods(BackendMethods): # pylint: disable=too-few-public-methods @cached_property - def _seeding(self): + def _spawning(self): @numba.njit(**{**self.default_jit_flags, "parallel": False}) def body( # pylint: disable=too-many-arguments idx, multiplicity, extensive_attributes, - seeded_particle_index, - seeded_particle_multiplicity, - seeded_particle_extensive_attributes, + spawned_particle_index, + spawned_particle_multiplicity, + spawned_particle_extensive_attributes, number_of_super_particles_to_inject: int, ): number_of_super_particles_already_injected = 0 @@ -30,14 +30,14 @@ def body( # pylint: disable=too-many-arguments break if mult == 0: idx[i] = -1 - s = seeded_particle_index[ + s = spawned_particle_index[ number_of_super_particles_already_injected ] number_of_super_particles_already_injected += 1 - multiplicity[i] = seeded_particle_multiplicity[s] + multiplicity[i] = spawned_particle_multiplicity[s] for a in range(len(extensive_attributes)): extensive_attributes[a, i] = ( - seeded_particle_extensive_attributes[a, s] + spawned_particle_extensive_attributes[a, s] ) assert ( number_of_super_particles_to_inject @@ -46,23 +46,23 @@ def body( # pylint: disable=too-many-arguments return body - def seeding( + def spawning( self, *, idx, multiplicity, extensive_attributes, - seeded_particle_index, - seeded_particle_multiplicity, - seeded_particle_extensive_attributes, - number_of_super_particles_to_inject: int, + spawned_particle_index, + spawned_particle_multiplicity, + spawned_particle_extensive_attributes, + number_of_super_particles_to_spawn: int, ): - self._seeding( + self._spawning( idx=idx.data, multiplicity=multiplicity.data, extensive_attributes=extensive_attributes.data, - seeded_particle_index=seeded_particle_index.data, - seeded_particle_multiplicity=seeded_particle_multiplicity.data, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes.data, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, + spawned_particle_index=spawned_particle_index.data, + spawnd_particle_multiplicity=spawned_particle_multiplicity.data, + spawnd_particle_extensive_attributes=spawned_particle_extensive_attributes.data, + number_of_super_particles_to_spawn=number_of_super_particles_to_spawn, ) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py new file mode 100644 index 000000000..be5e3b45e --- /dev/null +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -0,0 +1,36 @@ +from PySDM.dynamics.impl import register_dynamic +from PySDM.dynamics.impl import SuperParticleSpawningDynamic + + +@register_dynamic() +class HomogeneousLiquidNucleation(SuperParticleSpawningDynamic): + def __init__(self): + self.particulator = None + self.formulae = None + self.index = None + + def register(self, builder): + self.particulator = builder.particulator + self.formulae = builder.formulae + self.index = self.particulator.Index.identity_index(1) + + def __call__(self): + env = self.particulator.environment + e_s = self.formulae.equilibrium_supersaturation(env["T"]) + j = self.formulae.j_liq_homo(env["T"], env["RH"], e_s) + new_sd_multiplicity = round(j * env.dv * self.particulator.dt) + if new_sd_multiplicity > 0: + r_wet = self.formulae.r_liq_homo(env["T"], env["RH"], e_s) + v_wet = self.formulae.trivia.volume(radius=r_wet) + new_sd_extensive_attributes = { + "water mass": v_wet * self.formulae.constants.rho_w, + "dry volume": 0, + "kappa times dry volume": 0, + } + self.particulator.spawn( + seeded_particle_index=self.index, + number_of_super_particles_to_inject=1, + seeded_particle_multiplicity=new_sd_multiplicity, + seeded_particle_extensive_attributes=new_sd_extensive_attributes, + ) + # TODO: subtract the water mass from ambient vapour diff --git a/PySDM/dynamics/impl/__init__.py b/PySDM/dynamics/impl/__init__.py index f56de9d66..dd9838afd 100644 --- a/PySDM/dynamics/impl/__init__.py +++ b/PySDM/dynamics/impl/__init__.py @@ -1,3 +1,4 @@ """ stuff not intended to be imported from user code """ from .register_dynamic import register_dynamic +from .super_particle_spawning_dynamic import SuperParticleSpawningDynamic diff --git a/PySDM/dynamics/impl/super_particle_spawning_dynamic.py b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py new file mode 100644 index 000000000..b77fe8372 --- /dev/null +++ b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py @@ -0,0 +1,2 @@ +class SuperParticleSpawningDynamic: + pass diff --git a/PySDM/dynamics/seeding.py b/PySDM/dynamics/seeding.py index 3655e62a6..cf85c64cb 100644 --- a/PySDM/dynamics/seeding.py +++ b/PySDM/dynamics/seeding.py @@ -8,10 +8,11 @@ from PySDM.dynamics.impl import register_dynamic from PySDM.initialisation import discretise_multiplicities +from PySDM.dynamics.impl import SuperParticleSpawningDynamic @register_dynamic() -class Seeding: +class Seeding(SuperParticleSpawningDynamic): def __init__( self, *, @@ -86,9 +87,9 @@ def __call__(self): # or if the number of super particles to inject # is equal to the number of possible seeds self.index.shuffle(self.u01) - self.particulator.seeding( - seeded_particle_index=self.index, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, - seeded_particle_multiplicity=self.seeded_particle_multiplicity, - seeded_particle_extensive_attributes=self.seeded_particle_extensive_attributes, + self.particulator.spawn( + spawned_particle_index=self.index, + number_of_super_particles_to_spawn=number_of_super_particles_to_inject, + spawned_particle_multiplicity=self.seeded_particle_multiplicity, + spawned_particle_extensive_attributes=self.seeded_particle_extensive_attributes, ) diff --git a/PySDM/particulator.py b/PySDM/particulator.py index 8176221bc..87dea3f59 100644 --- a/PySDM/particulator.py +++ b/PySDM/particulator.py @@ -439,39 +439,39 @@ def isotopic_fractionation(self, heavy_isotopes: tuple): for isotope in heavy_isotopes: self.attributes.mark_updated(f"moles_{isotope}") - def seeding( + def spawn( self, *, - seeded_particle_index, - seeded_particle_multiplicity, - seeded_particle_extensive_attributes, - number_of_super_particles_to_inject, + spawned_particle_index, + spawned_particle_multiplicity, + spawned_particle_extensive_attributes, + number_of_super_particles_to_spawn, ): n_null = self.n_sd - self.attributes.super_droplet_count if n_null == 0: raise ValueError( - "No available seeds to inject. Please provide particles with nan filled attributes." + "No available null SDs to spawn. Please provide particles with nan filled attributes." ) - if number_of_super_particles_to_inject > n_null: + if number_of_super_particles_to_spawn > n_null: raise ValueError( - "Trying to inject more super particles than space available." + "Trying to spawn more super particles than space available." ) - if number_of_super_particles_to_inject > len(seeded_particle_multiplicity): + if number_of_super_particles_to_spawn > len(spawned_particle_multiplicity): raise ValueError( - "Trying to inject multiple super particles with the same attributes. \ - Instead increase multiplicity of injected particles." + "Trying to spawn multiple super particles with the same attributes. \ + Instead increase multiplicity of spawned particles." ) - self.backend.seeding( + self.backend.spawn( idx=self.attributes._ParticleAttributes__idx, multiplicity=self.attributes["multiplicity"], extensive_attributes=self.attributes.get_extensive_attribute_storage(), - seeded_particle_index=seeded_particle_index, - seeded_particle_multiplicity=seeded_particle_multiplicity, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, + spawned_particle_index=spawned_particle_index, + spawned_particle_multiplicity=spawned_particle_multiplicity, + spawned_particle_extensive_attributes=spawned_particle_extensive_attributes, + number_of_super_particles_to_spawn=number_of_super_particles_to_spawn, ) self.attributes.reset_idx() self.attributes.sanitize() From cd3375bc56e40dd014acc9655044fd35b6e089c8 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 30 Jan 2025 16:58:59 +0100 Subject: [PATCH 24/56] raname seeding -> spawning in backend tests --- ...ng_methods.py => test_spawning_methods.py} | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) rename tests/unit_tests/backends/{test_seeding_methods.py => test_spawning_methods.py} (58%) diff --git a/tests/unit_tests/backends/test_seeding_methods.py b/tests/unit_tests/backends/test_spawning_methods.py similarity index 58% rename from tests/unit_tests/backends/test_seeding_methods.py rename to tests/unit_tests/backends/test_spawning_methods.py index d7002785b..5daf83c82 100644 --- a/tests/unit_tests/backends/test_seeding_methods.py +++ b/tests/unit_tests/backends/test_spawning_methods.py @@ -11,7 +11,7 @@ from PySDM.physics import si -class TestSeeding: +class TestSpawningMethods: max_number_to_inject = 4 @staticmethod @@ -54,29 +54,31 @@ def test_number_of_super_particles_to_inject( }, ) - seeded_particle_extensive_attributes = { - "water mass": [0.0001 * si.ng] * TestSeeding.max_number_to_inject, + spawned_particle_extensive_attributes = { + "water mass": [0.0001 * si.ng] * TestSpawningMethods.max_number_to_inject, } - seeded_particle_multiplicity = [1] * TestSeeding.max_number_to_inject + spawned_particle_multiplicity = [1] * TestSpawningMethods.max_number_to_inject - seeded_particle_index = particulator.Index.identity_index( - len(seeded_particle_multiplicity) + spawned_particle_index = particulator.Index.identity_index( + len(spawned_particle_multiplicity) ) - seeded_particle_multiplicity = particulator.IndexedStorage.from_ndarray( - seeded_particle_index, - np.asarray(seeded_particle_multiplicity), + spawned_particle_multiplicity = particulator.IndexedStorage.from_ndarray( + spawned_particle_index, + np.asarray(spawned_particle_multiplicity), ) - seeded_particle_extensive_attributes = particulator.IndexedStorage.from_ndarray( - seeded_particle_index, - np.asarray(list(seeded_particle_extensive_attributes.values())), + spawned_particle_extensive_attributes = ( + particulator.IndexedStorage.from_ndarray( + spawned_particle_index, + np.asarray(list(spawned_particle_extensive_attributes.values())), + ) ) # act with context: - particulator.seeding( - seeded_particle_index=seeded_particle_index, - seeded_particle_multiplicity=seeded_particle_multiplicity, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes, + particulator.spawning( + spawned_particle_index=spawned_particle_index, + spawned_particle_multiplicity=spawned_particle_multiplicity, + spawned_particle_extensive_attributes=spawned_particle_extensive_attributes, number_of_super_particles_to_inject=number_of_super_particles_to_inject, ) @@ -88,7 +90,7 @@ def test_number_of_super_particles_to_inject( @staticmethod @pytest.mark.parametrize( - "seeded_particle_index, context", + "spawned_particle_index, context", ( ([0, 0, 0], nullcontext()), ([0, 1, 2], nullcontext()), @@ -102,8 +104,8 @@ def test_number_of_super_particles_to_inject( ), ), ) - def test_seeded_particle_index_multiplicity_extensive_attributes( - seeded_particle_index, + def test_spawned_particle_index_multiplicity_extensive_attributes( + spawned_particle_index, context, n_sd=3, number_of_super_particles_to_inject=3, @@ -117,42 +119,42 @@ def test_seeded_particle_index_multiplicity_extensive_attributes( }, ) - seeded_particle_extensive_attributes = { + spawned_particle_extensive_attributes = { "water mass": [0.0001, 0.0003, 0.0002], } - seeded_particle_multiplicity = [1, 2, 3] + spawned_particle_multiplicity = [1, 2, 3] - seeded_particle_index_impl = particulator.Index.from_ndarray( - np.asarray(seeded_particle_index) + spawned_particle_index_impl = particulator.Index.from_ndarray( + np.asarray(spawned_particle_index) ) - seeded_particle_multiplicity_impl = particulator.IndexedStorage.from_ndarray( - seeded_particle_index_impl, - np.asarray(seeded_particle_multiplicity), + spawned_particle_multiplicity_impl = particulator.IndexedStorage.from_ndarray( + spawned_particle_index_impl, + np.asarray(spawned_particle_multiplicity), ) - seeded_particle_extensive_attributes_impl = ( + spawned_particle_extensive_attributes_impl = ( particulator.IndexedStorage.from_ndarray( - seeded_particle_index_impl, - np.asarray(list(seeded_particle_extensive_attributes.values())), + spawned_particle_index_impl, + np.asarray(list(spawned_particle_extensive_attributes.values())), ) ) # act with context: - particulator.seeding( - seeded_particle_index=seeded_particle_index_impl, - seeded_particle_multiplicity=seeded_particle_multiplicity_impl, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes_impl, + particulator.spawning( + spawned_particle_index=spawned_particle_index_impl, + spawned_particle_multiplicity=spawned_particle_multiplicity_impl, + spawned_particle_extensive_attributes=spawned_particle_extensive_attributes_impl, number_of_super_particles_to_inject=number_of_super_particles_to_inject, ) # assert np.testing.assert_array_equal( particulator.attributes["multiplicity"].to_ndarray(), - np.asarray(seeded_particle_multiplicity)[seeded_particle_index], + np.asarray(spawned_particle_multiplicity)[spawned_particle_index], ) np.testing.assert_array_equal( particulator.attributes["water mass"].to_ndarray(), - np.asarray(seeded_particle_extensive_attributes["water mass"])[ - seeded_particle_index + np.asarray(spawned_particle_extensive_attributes["water mass"])[ + spawned_particle_index ], ) From f9d99ceceea0197259aa64badfbd9ce360783e82 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 30 Jan 2025 16:59:57 +0100 Subject: [PATCH 25/56] raname injecting -> spawning in backend tests --- .../backends/test_spawning_methods.py | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/unit_tests/backends/test_spawning_methods.py b/tests/unit_tests/backends/test_spawning_methods.py index 5daf83c82..1dbf1c1bb 100644 --- a/tests/unit_tests/backends/test_spawning_methods.py +++ b/tests/unit_tests/backends/test_spawning_methods.py @@ -1,4 +1,4 @@ -""" Seeding backend tests of injection logic """ +""" Seeding backend tests of spawning logic """ from contextlib import nullcontext @@ -12,35 +12,35 @@ class TestSpawningMethods: - max_number_to_inject = 4 + max_number_to_spawn = 4 @staticmethod @pytest.mark.parametrize( - "n_sd, number_of_super_particles_to_inject, context", + "n_sd, number_of_super_particles_to_spawn, context", ( (1, 1, nullcontext()), ( 1, 2, pytest.raises( - ValueError, match="inject more super particles than space available" + ValueError, match="spawn more super particles than space available" ), ), - (max_number_to_inject, max_number_to_inject - 1, nullcontext()), - (max_number_to_inject, max_number_to_inject, nullcontext()), + (max_number_to_spawn, max_number_to_spawn - 1, nullcontext()), + (max_number_to_spawn, max_number_to_spawn, nullcontext()), ( - max_number_to_inject + 2, - max_number_to_inject + 1, + max_number_to_spawn + 2, + max_number_to_spawn + 1, pytest.raises( ValueError, - match="inject multiple super particles with the same attributes", + match="spawn multiple super particles with the same attributes", ), ), ), ) - def test_number_of_super_particles_to_inject( + def test_number_of_super_particles_to_spawn( n_sd, - number_of_super_particles_to_inject, + number_of_super_particles_to_spawn, context, dt=1, dv=1, @@ -55,9 +55,9 @@ def test_number_of_super_particles_to_inject( ) spawned_particle_extensive_attributes = { - "water mass": [0.0001 * si.ng] * TestSpawningMethods.max_number_to_inject, + "water mass": [0.0001 * si.ng] * TestSpawningMethods.max_number_to_spawn, } - spawned_particle_multiplicity = [1] * TestSpawningMethods.max_number_to_inject + spawned_particle_multiplicity = [1] * TestSpawningMethods.max_number_to_spawn spawned_particle_index = particulator.Index.identity_index( len(spawned_particle_multiplicity) @@ -79,12 +79,12 @@ def test_number_of_super_particles_to_inject( spawned_particle_index=spawned_particle_index, spawned_particle_multiplicity=spawned_particle_multiplicity, spawned_particle_extensive_attributes=spawned_particle_extensive_attributes, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, + number_of_super_particles_to_spawn=number_of_super_particles_to_spawn, ) # assert assert ( - number_of_super_particles_to_inject + number_of_super_particles_to_spawn == particulator.attributes.super_droplet_count ) @@ -108,7 +108,7 @@ def test_spawned_particle_index_multiplicity_extensive_attributes( spawned_particle_index, context, n_sd=3, - number_of_super_particles_to_inject=3, + number_of_super_particles_to_spawn=3, ): # arrange builder = Builder(n_sd, CPU(), Box(dt=np.nan, dv=np.nan)) @@ -144,7 +144,7 @@ def test_spawned_particle_index_multiplicity_extensive_attributes( spawned_particle_index=spawned_particle_index_impl, spawned_particle_multiplicity=spawned_particle_multiplicity_impl, spawned_particle_extensive_attributes=spawned_particle_extensive_attributes_impl, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, + number_of_super_particles_to_spawn=number_of_super_particles_to_spawn, ) # assert From 8bc50bb679e3c60179445d8e4d606d40aba34fd7 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 30 Jan 2025 17:15:36 +0100 Subject: [PATCH 26/56] comment on zero multiplicity -> MC sampling? --- PySDM/dynamics/homogeneous_liquid_nucleation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index be5e3b45e..3368b1fe0 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -18,7 +18,10 @@ def __call__(self): env = self.particulator.environment e_s = self.formulae.equilibrium_supersaturation(env["T"]) j = self.formulae.j_liq_homo(env["T"], env["RH"], e_s) + + # TODO: take care of caseswhere round yields zero -> MC sampling? new_sd_multiplicity = round(j * env.dv * self.particulator.dt) + if new_sd_multiplicity > 0: r_wet = self.formulae.r_liq_homo(env["T"], env["RH"], e_s) v_wet = self.formulae.trivia.volume(radius=r_wet) From e5abcb386bdff6e7863187fb621714a671bb64ee Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 30 Jan 2025 21:24:38 +0100 Subject: [PATCH 27/56] work in progress towards getting nucleation dynamic enabled in the expansion experiment notebook --- PySDM/backends/numba.py | 4 +- PySDM/dynamics/__init__.py | 1 + .../dynamics/homogeneous_liquid_nucleation.py | 14 ++- .../expansion_experiment.ipynb | 95 ++++++++++--------- .../Erinin_et_al_2025/expansion_simulation.py | 7 +- 5 files changed, 68 insertions(+), 53 deletions(-) diff --git a/PySDM/backends/numba.py b/PySDM/backends/numba.py index a42063265..f805d1e39 100644 --- a/PySDM/backends/numba.py +++ b/PySDM/backends/numba.py @@ -28,7 +28,7 @@ class Numba( # pylint: disable=too-many-ancestors,duplicate-code methods.DisplacementMethods, methods.TerminalVelocityMethods, methods.IsotopeMethods, - methods.SeedingMethods, + methods.SpawningMethods, ): Storage = ImportedStorage Random = ImportedRandom @@ -77,4 +77,4 @@ def __init__(self, formulae=None, double_precision=True, override_jit_flags=None methods.DisplacementMethods.__init__(self) methods.TerminalVelocityMethods.__init__(self) methods.IsotopeMethods.__init__(self) - methods.SeedingMethods.__init__(self) + methods.SpawningMethods.__init__(self) diff --git a/PySDM/dynamics/__init__.py b/PySDM/dynamics/__init__.py index 66056cf0d..bfbc375f6 100644 --- a/PySDM/dynamics/__init__.py +++ b/PySDM/dynamics/__init__.py @@ -16,3 +16,4 @@ from PySDM.dynamics.freezing import Freezing from PySDM.dynamics.relaxed_velocity import RelaxedVelocity from PySDM.dynamics.seeding import Seeding +from PySDM.dynamics.homogeneous_liquid_nucleation import HomogeneousLiquidNucleation diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index 3368b1fe0..f02a38851 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -15,11 +15,17 @@ def register(self, builder): self.index = self.particulator.Index.identity_index(1) def __call__(self): - env = self.particulator.environment - e_s = self.formulae.equilibrium_supersaturation(env["T"]) - j = self.formulae.j_liq_homo(env["T"], env["RH"], e_s) + env = { + k: self.particulator.environment[k].to_ndarray()[0] for k in ("T", "RH") + } # TODO: >0D + e_s = self.formulae.saturation_vapour_pressure.pvs_water( + env["T"] + ) # @Clare - is this change OK? + j = self.formulae.homogeneous_liquid_nucleation_rate.j_liq_homo( + env["T"], env["RH"], e_s + ) - # TODO: take care of caseswhere round yields zero -> MC sampling? + # TODO: take care of cases where round yields zero -> MC sampling? new_sd_multiplicity = round(j * env.dv * self.particulator.dt) if new_sd_multiplicity > 0: diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index b656c456c..16cfb4cc9 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,32 +18,30 @@ }, { "cell_type": "code", - "execution_count": 1, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T22:59:10.526065Z", - "start_time": "2025-01-26T22:59:10.512257Z" + "end_time": "2025-01-30T20:21:31.584604Z", + "start_time": "2025-01-30T20:21:31.573353Z" } }, - "outputs": [], "source": [ "import sys\n", "if 'google.colab' in sys.modules:\n", " !pip --quiet install open-atmos-jupyter-utils\n", " from open_atmos_jupyter_utils import pip_install_on_colab\n", " pip_install_on_colab('PySDM-examples')" - ] + ], + "outputs": [], + "execution_count": 1 }, { "cell_type": "code", - "execution_count": 1, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T22:59:15.132318Z", - "start_time": "2025-01-26T22:59:10.732787Z" + "end_time": "2025-01-30T20:21:37.280272Z", + "start_time": "2025-01-30T20:21:31.850352Z" } }, - "outputs": [], "source": [ "import numpy as np\n", "from matplotlib import pyplot\n", @@ -53,45 +51,18 @@ "\n", "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" - ] + ], + "outputs": [], + "execution_count": 2 }, { "cell_type": "code", - "execution_count": 3, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T23:02:46.906285Z", - "start_time": "2025-01-26T23:02:15.511473Z" + "end_time": "2025-01-30T20:23:04.715504Z", + "start_time": "2025-01-30T20:21:37.309294Z" } }, - "outputs": [ - { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T17:09:49.262684\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "936f1b6b885a41aeb122de35134dcd71", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./C0_sweep_traces.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], "source": [ "n_sd_per_mode = 20\n", "DT = .1 * si.s\n", @@ -104,7 +75,10 @@ "\n", "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", "\n", - " formulae = Formulae(adiabatic_exponent=\"MoistLeadingTerms\")\n", + " formulae = Formulae(\n", + " adiabatic_exponent=\"MoistLeadingTerms\",\n", + " homogeneous_liquid_nucleation_rate='CNT',\n", + " )\n", " const = formulae.constants\n", " aerosol = AerosolChamber(\n", " water_molar_volume=const.Mv / const.rho_w,\n", @@ -123,14 +97,43 @@ "\n", "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", "show_plot(\"C0_sweep_traces.pdf\")" - ] + ], + "outputs": [ + { + "ename": "TypingError", + "evalue": "Failed in nopython mode pipeline (step: nopython frontend)\n\u001B[1m\u001B[1mUnknown attribute 'k_B' of type Constants(float64, bool, int64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, int64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64)\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n\u001B[0m\n\u001B[0m\u001B[1mDuring: typing of get attribute at (10)\u001B[0m\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n", + "output_type": "error", + "traceback": [ + "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", + "\u001B[0;31mTypingError\u001B[0m Traceback (most recent call last)", + "Cell \u001B[0;32mIn[3], line 22\u001B[0m\n\u001B[1;32m 16\u001B[0m const \u001B[38;5;241m=\u001B[39m formulae\u001B[38;5;241m.\u001B[39mconstants\n\u001B[1;32m 17\u001B[0m aerosol \u001B[38;5;241m=\u001B[39m AerosolChamber(\n\u001B[1;32m 18\u001B[0m water_molar_volume\u001B[38;5;241m=\u001B[39mconst\u001B[38;5;241m.\u001B[39mMv \u001B[38;5;241m/\u001B[39m const\u001B[38;5;241m.\u001B[39mrho_w,\n\u001B[1;32m 19\u001B[0m N\u001B[38;5;241m=\u001B[39mNa \u001B[38;5;241m/\u001B[39m si\u001B[38;5;241m.\u001B[39mcm\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m3\u001B[39m,\n\u001B[1;32m 20\u001B[0m )\n\u001B[0;32m---> 22\u001B[0m output \u001B[38;5;241m=\u001B[39m \u001B[43mrun_expansion\u001B[49m\u001B[43m(\u001B[49m\u001B[43mformulae\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43maerosol\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mn_sd_per_mode\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtotal_time\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m4\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43msi\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43ms\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mdt\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mDT\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 24\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m i,ax \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28menumerate\u001B[39m(axes\u001B[38;5;241m.\u001B[39mflatten()):\n\u001B[1;32m 25\u001B[0m y \u001B[38;5;241m=\u001B[39m np\u001B[38;5;241m.\u001B[39marray(output\u001B[38;5;241m.\u001B[39mprofile[variables[i]]) \u001B[38;5;241m*\u001B[39m factors[i] \u001B[38;5;241m+\u001B[39m offsets[i]\n", + "File \u001B[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:113\u001B[0m, in \u001B[0;36mrun_expansion\u001B[0;34m(formulae, aerosol, n_sd_per_mode, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001B[0m\n\u001B[1;32m 105\u001B[0m output_attributes \u001B[38;5;241m=\u001B[39m {\n\u001B[1;32m 106\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmultiplicity\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 107\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mvolume\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 108\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcritical volume\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 109\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcritical supersaturation\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 110\u001B[0m }\n\u001B[1;32m 112\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(n_steps):\n\u001B[0;32m--> 113\u001B[0m \u001B[43mparticulator\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrun\u001B[49m\u001B[43m(\u001B[49m\u001B[43msteps\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m1\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 114\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m product \u001B[38;5;129;01min\u001B[39;00m particulator\u001B[38;5;241m.\u001B[39mproducts\u001B[38;5;241m.\u001B[39mvalues():\n\u001B[1;32m 115\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m product\u001B[38;5;241m.\u001B[39mname \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mdry:dN/dR\u001B[39m\u001B[38;5;124m\"\u001B[39m \u001B[38;5;129;01mor\u001B[39;00m product\u001B[38;5;241m.\u001B[39mname \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mwet:dN/dR\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n", + "File \u001B[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001B[0m, in \u001B[0;36mParticulator.run\u001B[0;34m(self, steps)\u001B[0m\n\u001B[1;32m 47\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m key, dynamic \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mdynamics\u001B[38;5;241m.\u001B[39mitems():\n\u001B[1;32m 48\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mtimers[key]:\n\u001B[0;32m---> 49\u001B[0m \u001B[43mdynamic\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 50\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mn_steps \u001B[38;5;241m+\u001B[39m\u001B[38;5;241m=\u001B[39m \u001B[38;5;241m1\u001B[39m\n\u001B[1;32m 51\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_notify_observers()\n", + "File \u001B[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:20\u001B[0m, in \u001B[0;36mHomogeneousLiquidNucleation.__call__\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 18\u001B[0m env \u001B[38;5;241m=\u001B[39m {k:\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mparticulator\u001B[38;5;241m.\u001B[39menvironment[k]\u001B[38;5;241m.\u001B[39mto_ndarray()[\u001B[38;5;241m0\u001B[39m] \u001B[38;5;28;01mfor\u001B[39;00m k \u001B[38;5;129;01min\u001B[39;00m (\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mT\u001B[39m\u001B[38;5;124m'\u001B[39m, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mRH\u001B[39m\u001B[38;5;124m'\u001B[39m)} \u001B[38;5;66;03m# TODO: >0D\u001B[39;00m\n\u001B[1;32m 19\u001B[0m e_s \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mformulae\u001B[38;5;241m.\u001B[39msaturation_vapour_pressure\u001B[38;5;241m.\u001B[39mpvs_water(env[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mT\u001B[39m\u001B[38;5;124m\"\u001B[39m]) \u001B[38;5;66;03m# @Clare - is this change OK?\u001B[39;00m\n\u001B[0;32m---> 20\u001B[0m j \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mformulae\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mhomogeneous_liquid_nucleation_rate\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mj_liq_homo\u001B[49m\u001B[43m(\u001B[49m\u001B[43menv\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mT\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43menv\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mRH\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43me_s\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 22\u001B[0m \u001B[38;5;66;03m# TODO: take care of cases where round yields zero -> MC sampling?\u001B[39;00m\n\u001B[1;32m 23\u001B[0m new_sd_multiplicity \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mround\u001B[39m(j \u001B[38;5;241m*\u001B[39m env\u001B[38;5;241m.\u001B[39mdv \u001B[38;5;241m*\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mparticulator\u001B[38;5;241m.\u001B[39mdt)\n", + "File \u001B[0;32m~/devel/venv/lib/python3.9/site-packages/numba/core/dispatcher.py:468\u001B[0m, in \u001B[0;36m_DispatcherBase._compile_for_args\u001B[0;34m(self, *args, **kws)\u001B[0m\n\u001B[1;32m 464\u001B[0m msg \u001B[38;5;241m=\u001B[39m (\u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;132;01m{\u001B[39;00m\u001B[38;5;28mstr\u001B[39m(e)\u001B[38;5;241m.\u001B[39mrstrip()\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;124mThis error may have been caused \u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m 465\u001B[0m \u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mby the following argument(s):\u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;132;01m{\u001B[39;00margs_str\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 466\u001B[0m e\u001B[38;5;241m.\u001B[39mpatch_message(msg)\n\u001B[0;32m--> 468\u001B[0m \u001B[43merror_rewrite\u001B[49m\u001B[43m(\u001B[49m\u001B[43me\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mtyping\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 469\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m errors\u001B[38;5;241m.\u001B[39mUnsupportedError \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[1;32m 470\u001B[0m \u001B[38;5;66;03m# Something unsupported is present in the user code, add help info\u001B[39;00m\n\u001B[1;32m 471\u001B[0m error_rewrite(e, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124munsupported_error\u001B[39m\u001B[38;5;124m'\u001B[39m)\n", + "File \u001B[0;32m~/devel/venv/lib/python3.9/site-packages/numba/core/dispatcher.py:409\u001B[0m, in \u001B[0;36m_DispatcherBase._compile_for_args..error_rewrite\u001B[0;34m(e, issue_type)\u001B[0m\n\u001B[1;32m 407\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[1;32m 408\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m--> 409\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m e\u001B[38;5;241m.\u001B[39mwith_traceback(\u001B[38;5;28;01mNone\u001B[39;00m)\n", + "\u001B[0;31mTypingError\u001B[0m: Failed in nopython mode pipeline (step: nopython frontend)\n\u001B[1m\u001B[1mUnknown attribute 'k_B' of type Constants(float64, bool, int64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, int64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64)\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n\u001B[0m\n\u001B[0m\u001B[1mDuring: typing of get attribute at (10)\u001B[0m\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "
" + ], + "image/png": "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" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "execution_count": 3 }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T23:10:25.862264Z", + "end_time": "2025-01-30T20:23:04.785100072Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, @@ -206,7 +209,7 @@ "execution_count": 5, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T23:10:25.887693Z", + "end_time": "2025-01-30T20:18:02.529987551Z", "start_time": "2025-01-26T23:10:25.865329Z" } }, @@ -245,7 +248,7 @@ "execution_count": 6, "metadata": { "ExecuteTime": { - "end_time": "2025-01-26T23:10:44.964277Z", + "end_time": "2025-01-30T20:18:02.702242840Z", "start_time": "2025-01-26T23:10:40.873425Z" } }, diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 127694dcd..0373eb7cf 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -4,7 +4,11 @@ from PySDM import Builder from PySDM import products as PySDM_products from PySDM.backends import CPU -from PySDM.dynamics import AmbientThermodynamics, Condensation +from PySDM.dynamics import ( + AmbientThermodynamics, + Condensation, + HomogeneousLiquidNucleation, +) from PySDM.environments import ExpansionChamber from PySDM.initialisation import equilibrate_wet_radii from PySDM.initialisation.sampling.spectral_sampling import ConstantMultiplicity @@ -73,6 +77,7 @@ def run_expansion( ) builder.add_dynamic(AmbientThermodynamics()) builder.add_dynamic(Condensation()) + builder.add_dynamic(HomogeneousLiquidNucleation()) builder.request_attribute("critical supersaturation") attributes = { From fedd946492840dc3436a2ce014386ab1d9305225 Mon Sep 17 00:00:00 2001 From: claresinger Date: Thu, 30 Jan 2025 15:31:56 -0500 Subject: [PATCH 28/56] add back boltzmann constant --- PySDM/physics/constants_defaults.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PySDM/physics/constants_defaults.py b/PySDM/physics/constants_defaults.py index 80c6728b9..653174ceb 100644 --- a/PySDM/physics/constants_defaults.py +++ b/PySDM/physics/constants_defaults.py @@ -94,6 +94,9 @@ N_A = sci.N_A / si.mole """ Avogadro constant (value from SciPy) """ +k_B = sci.k * si.joule / si.kelvin +""" Boltzmann constant (value from SciPy) """ + MAC = 1.0 """ mass accommodation coefficient of unity as recommended in [Laaksonen et al. 2005](https://doi.org/10.5194/acp-5-461-2005) """ From fe4bfb9c732118f212d127f3b3f6a00e67ccbb17 Mon Sep 17 00:00:00 2001 From: claresinger Date: Thu, 30 Jan 2025 16:39:06 -0500 Subject: [PATCH 29/56] fix errors in dynamic to get to error with 'No available null SDs to spawn' --- .../dynamics/homogeneous_liquid_nucleation.py | 20 +- PySDM/physics/constants_defaults.py | 5 +- .../expansion_experiment.ipynb | 210 ++++++------------ 3 files changed, 77 insertions(+), 158 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index f02a38851..653c5406c 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -18,18 +18,20 @@ def __call__(self): env = { k: self.particulator.environment[k].to_ndarray()[0] for k in ("T", "RH") } # TODO: >0D - e_s = self.formulae.saturation_vapour_pressure.pvs_water( - env["T"] - ) # @Clare - is this change OK? + e_s = self.formulae.saturation_vapour_pressure.pvs_water(env["T"]) j = self.formulae.homogeneous_liquid_nucleation_rate.j_liq_homo( env["T"], env["RH"], e_s ) # TODO: take care of cases where round yields zero -> MC sampling? - new_sd_multiplicity = round(j * env.dv * self.particulator.dt) + new_sd_multiplicity = round( + j * self.particulator.environment.mesh.dv * self.particulator.dt + ) if new_sd_multiplicity > 0: - r_wet = self.formulae.r_liq_homo(env["T"], env["RH"], e_s) + r_wet = self.formulae.homogeneous_liquid_nucleation_rate.r_liq_homo( + env["T"], env["RH"] + ) v_wet = self.formulae.trivia.volume(radius=r_wet) new_sd_extensive_attributes = { "water mass": v_wet * self.formulae.constants.rho_w, @@ -37,9 +39,9 @@ def __call__(self): "kappa times dry volume": 0, } self.particulator.spawn( - seeded_particle_index=self.index, - number_of_super_particles_to_inject=1, - seeded_particle_multiplicity=new_sd_multiplicity, - seeded_particle_extensive_attributes=new_sd_extensive_attributes, + spawned_particle_index=self.index, + number_of_super_particles_to_spawn=1, + spawned_particle_multiplicity=new_sd_multiplicity, + spawned_particle_extensive_attributes=new_sd_extensive_attributes, ) # TODO: subtract the water mass from ambient vapour diff --git a/PySDM/physics/constants_defaults.py b/PySDM/physics/constants_defaults.py index 653174ceb..924e0898a 100644 --- a/PySDM/physics/constants_defaults.py +++ b/PySDM/physics/constants_defaults.py @@ -94,9 +94,6 @@ N_A = sci.N_A / si.mole """ Avogadro constant (value from SciPy) """ -k_B = sci.k * si.joule / si.kelvin -""" Boltzmann constant (value from SciPy) """ - MAC = 1.0 """ mass accommodation coefficient of unity as recommended in [Laaksonen et al. 2005](https://doi.org/10.5194/acp-5-461-2005) """ @@ -690,3 +687,5 @@ def compute_derived_values(c: dict): c["water_molar_volume"] = c["Mv"] / c["rho_w"] c["rho_STP"] = c["p_STP"] / c["Rd"] / c["T_STP"] c["H_u"] = c["M"] / c["p_STP"] + + c["k_B"] = c["R_str"] / c["N_A"] diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 16cfb4cc9..97325b3d6 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,30 +18,32 @@ }, { "cell_type": "code", + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:31.584604Z", "start_time": "2025-01-30T20:21:31.573353Z" } }, + "outputs": [], "source": [ "import sys\n", "if 'google.colab' in sys.modules:\n", " !pip --quiet install open-atmos-jupyter-utils\n", " from open_atmos_jupyter_utils import pip_install_on_colab\n", " pip_install_on_colab('PySDM-examples')" - ], - "outputs": [], - "execution_count": 1 + ] }, { "cell_type": "code", + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:37.280272Z", "start_time": "2025-01-30T20:21:31.850352Z" } }, + "outputs": [], "source": [ "import numpy as np\n", "from matplotlib import pyplot\n", @@ -51,18 +53,66 @@ "\n", "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" - ], - "outputs": [], - "execution_count": 2 + ] }, { "cell_type": "code", + "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.715504Z", "start_time": "2025-01-30T20:21:37.309294Z" } }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.0088741793315877e-251\n", + "0.0\n", + "0.0\n", + "0.0\n", + "0.0\n", + "0.0\n", + "0.0\n", + "1.7154986878176384e-167\n", + "2.178592573781986e-91\n", + "5.5016580938091175e-52\n", + "4.5218624514050985e-29\n", + "1.2371157133280349e-14\n", + "5.4303370061083676e-05\n", + "292.405494788522\n" + ] + }, + { + "ename": "ValueError", + "evalue": "No available null SDs to spawn. Please provide particles with nan filled attributes.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/j_/wj_gdgdx2jdbw7vwy0bnq5hm0000gn/T/ipykernel_76947/519356353.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 20\u001b[0m )\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_expansion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mformulae\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maerosol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn_sd_per_mode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtotal_time\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdt\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDT\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0max\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Research/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py\u001b[0m in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001b[0m\n\u001b[1;32m 115\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn_steps\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 117\u001b[0;31m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msteps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 118\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mproduct\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproducts\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 119\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mproduct\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"dry:dN/dR\"\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mproduct\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"wet:dN/dR\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Research/PySDM/PySDM/particulator.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdynamic\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdynamics\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 48\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 49\u001b[0;31m \u001b[0mdynamic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 50\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_steps\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_notify_observers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Research/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0;34m\"kappa times dry volume\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 39\u001b[0m }\n\u001b[0;32m---> 40\u001b[0;31m self.particulator.spawn(\n\u001b[0m\u001b[1;32m 41\u001b[0m \u001b[0mspawned_particle_index\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[0mnumber_of_super_particles_to_spawn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Research/PySDM/PySDM/particulator.py\u001b[0m in \u001b[0;36mspawn\u001b[0;34m(self, spawned_particle_index, spawned_particle_multiplicity, spawned_particle_extensive_attributes, number_of_super_particles_to_spawn)\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0mn_null\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_sd\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msuper_droplet_count\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 451\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn_null\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 452\u001b[0;31m raise ValueError(\n\u001b[0m\u001b[1;32m 453\u001b[0m \u001b[0;34m\"No available null SDs to spawn. Please provide particles with nan filled attributes.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 454\u001b[0m )\n", + "\u001b[0;31mValueError\u001b[0m: No available null SDs to spawn. Please provide particles with nan filled attributes." + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "n_sd_per_mode = 20\n", "DT = .1 * si.s\n", @@ -73,7 +123,7 @@ "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\"]\n", "fig,axes=pyplot.subplots(2,3,figsize=(10,5),sharex=True,sharey=False,constrained_layout=True)\n", "\n", - "for Na in [1e3, 1e4, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", + "for Na in [1e1, 1e3, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", "\n", " formulae = Formulae(\n", " adiabatic_exponent=\"MoistLeadingTerms\",\n", @@ -97,77 +147,18 @@ "\n", "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", "show_plot(\"C0_sweep_traces.pdf\")" - ], - "outputs": [ - { - "ename": "TypingError", - "evalue": "Failed in nopython mode pipeline (step: nopython frontend)\n\u001B[1m\u001B[1mUnknown attribute 'k_B' of type Constants(float64, bool, int64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, int64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64)\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n\u001B[0m\n\u001B[0m\u001B[1mDuring: typing of get attribute at (10)\u001B[0m\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n", - "output_type": "error", - "traceback": [ - "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", - "\u001B[0;31mTypingError\u001B[0m Traceback (most recent call last)", - "Cell \u001B[0;32mIn[3], line 22\u001B[0m\n\u001B[1;32m 16\u001B[0m const \u001B[38;5;241m=\u001B[39m formulae\u001B[38;5;241m.\u001B[39mconstants\n\u001B[1;32m 17\u001B[0m aerosol \u001B[38;5;241m=\u001B[39m AerosolChamber(\n\u001B[1;32m 18\u001B[0m water_molar_volume\u001B[38;5;241m=\u001B[39mconst\u001B[38;5;241m.\u001B[39mMv \u001B[38;5;241m/\u001B[39m const\u001B[38;5;241m.\u001B[39mrho_w,\n\u001B[1;32m 19\u001B[0m N\u001B[38;5;241m=\u001B[39mNa \u001B[38;5;241m/\u001B[39m si\u001B[38;5;241m.\u001B[39mcm\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39m\u001B[38;5;241m3\u001B[39m,\n\u001B[1;32m 20\u001B[0m )\n\u001B[0;32m---> 22\u001B[0m output \u001B[38;5;241m=\u001B[39m \u001B[43mrun_expansion\u001B[49m\u001B[43m(\u001B[49m\u001B[43mformulae\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43maerosol\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mn_sd_per_mode\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtotal_time\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m4\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43msi\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43ms\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mdt\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mDT\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 24\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m i,ax \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28menumerate\u001B[39m(axes\u001B[38;5;241m.\u001B[39mflatten()):\n\u001B[1;32m 25\u001B[0m y \u001B[38;5;241m=\u001B[39m np\u001B[38;5;241m.\u001B[39marray(output\u001B[38;5;241m.\u001B[39mprofile[variables[i]]) \u001B[38;5;241m*\u001B[39m factors[i] \u001B[38;5;241m+\u001B[39m offsets[i]\n", - "File \u001B[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:113\u001B[0m, in \u001B[0;36mrun_expansion\u001B[0;34m(formulae, aerosol, n_sd_per_mode, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001B[0m\n\u001B[1;32m 105\u001B[0m output_attributes \u001B[38;5;241m=\u001B[39m {\n\u001B[1;32m 106\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mmultiplicity\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 107\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mvolume\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 108\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcritical volume\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 109\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mcritical supersaturation\u001B[39m\u001B[38;5;124m\"\u001B[39m: \u001B[38;5;28mtuple\u001B[39m([] \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(particulator\u001B[38;5;241m.\u001B[39mn_sd)),\n\u001B[1;32m 110\u001B[0m }\n\u001B[1;32m 112\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m _ \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mrange\u001B[39m(n_steps):\n\u001B[0;32m--> 113\u001B[0m \u001B[43mparticulator\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrun\u001B[49m\u001B[43m(\u001B[49m\u001B[43msteps\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m1\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 114\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m product \u001B[38;5;129;01min\u001B[39;00m particulator\u001B[38;5;241m.\u001B[39mproducts\u001B[38;5;241m.\u001B[39mvalues():\n\u001B[1;32m 115\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m product\u001B[38;5;241m.\u001B[39mname \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mdry:dN/dR\u001B[39m\u001B[38;5;124m\"\u001B[39m \u001B[38;5;129;01mor\u001B[39;00m product\u001B[38;5;241m.\u001B[39mname \u001B[38;5;241m==\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mwet:dN/dR\u001B[39m\u001B[38;5;124m\"\u001B[39m:\n", - "File \u001B[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001B[0m, in \u001B[0;36mParticulator.run\u001B[0;34m(self, steps)\u001B[0m\n\u001B[1;32m 47\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m key, dynamic \u001B[38;5;129;01min\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mdynamics\u001B[38;5;241m.\u001B[39mitems():\n\u001B[1;32m 48\u001B[0m \u001B[38;5;28;01mwith\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mtimers[key]:\n\u001B[0;32m---> 49\u001B[0m \u001B[43mdynamic\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 50\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mn_steps \u001B[38;5;241m+\u001B[39m\u001B[38;5;241m=\u001B[39m \u001B[38;5;241m1\u001B[39m\n\u001B[1;32m 51\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_notify_observers()\n", - "File \u001B[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:20\u001B[0m, in \u001B[0;36mHomogeneousLiquidNucleation.__call__\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 18\u001B[0m env \u001B[38;5;241m=\u001B[39m {k:\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mparticulator\u001B[38;5;241m.\u001B[39menvironment[k]\u001B[38;5;241m.\u001B[39mto_ndarray()[\u001B[38;5;241m0\u001B[39m] \u001B[38;5;28;01mfor\u001B[39;00m k \u001B[38;5;129;01min\u001B[39;00m (\u001B[38;5;124m'\u001B[39m\u001B[38;5;124mT\u001B[39m\u001B[38;5;124m'\u001B[39m, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mRH\u001B[39m\u001B[38;5;124m'\u001B[39m)} \u001B[38;5;66;03m# TODO: >0D\u001B[39;00m\n\u001B[1;32m 19\u001B[0m e_s \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mformulae\u001B[38;5;241m.\u001B[39msaturation_vapour_pressure\u001B[38;5;241m.\u001B[39mpvs_water(env[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mT\u001B[39m\u001B[38;5;124m\"\u001B[39m]) \u001B[38;5;66;03m# @Clare - is this change OK?\u001B[39;00m\n\u001B[0;32m---> 20\u001B[0m j \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mformulae\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mhomogeneous_liquid_nucleation_rate\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mj_liq_homo\u001B[49m\u001B[43m(\u001B[49m\u001B[43menv\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mT\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43menv\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mRH\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m]\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43me_s\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 22\u001B[0m \u001B[38;5;66;03m# TODO: take care of cases where round yields zero -> MC sampling?\u001B[39;00m\n\u001B[1;32m 23\u001B[0m new_sd_multiplicity \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mround\u001B[39m(j \u001B[38;5;241m*\u001B[39m env\u001B[38;5;241m.\u001B[39mdv \u001B[38;5;241m*\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mparticulator\u001B[38;5;241m.\u001B[39mdt)\n", - "File \u001B[0;32m~/devel/venv/lib/python3.9/site-packages/numba/core/dispatcher.py:468\u001B[0m, in \u001B[0;36m_DispatcherBase._compile_for_args\u001B[0;34m(self, *args, **kws)\u001B[0m\n\u001B[1;32m 464\u001B[0m msg \u001B[38;5;241m=\u001B[39m (\u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;132;01m{\u001B[39;00m\u001B[38;5;28mstr\u001B[39m(e)\u001B[38;5;241m.\u001B[39mrstrip()\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;124m \u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;124mThis error may have been caused \u001B[39m\u001B[38;5;124m\"\u001B[39m\n\u001B[1;32m 465\u001B[0m \u001B[38;5;124mf\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mby the following argument(s):\u001B[39m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;132;01m{\u001B[39;00margs_str\u001B[38;5;132;01m}\u001B[39;00m\u001B[38;5;130;01m\\n\u001B[39;00m\u001B[38;5;124m\"\u001B[39m)\n\u001B[1;32m 466\u001B[0m e\u001B[38;5;241m.\u001B[39mpatch_message(msg)\n\u001B[0;32m--> 468\u001B[0m \u001B[43merror_rewrite\u001B[49m\u001B[43m(\u001B[49m\u001B[43me\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[38;5;124;43mtyping\u001B[39;49m\u001B[38;5;124;43m'\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[1;32m 469\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m errors\u001B[38;5;241m.\u001B[39mUnsupportedError \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[1;32m 470\u001B[0m \u001B[38;5;66;03m# Something unsupported is present in the user code, add help info\u001B[39;00m\n\u001B[1;32m 471\u001B[0m error_rewrite(e, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124munsupported_error\u001B[39m\u001B[38;5;124m'\u001B[39m)\n", - "File \u001B[0;32m~/devel/venv/lib/python3.9/site-packages/numba/core/dispatcher.py:409\u001B[0m, in \u001B[0;36m_DispatcherBase._compile_for_args..error_rewrite\u001B[0;34m(e, issue_type)\u001B[0m\n\u001B[1;32m 407\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m e\n\u001B[1;32m 408\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m--> 409\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m e\u001B[38;5;241m.\u001B[39mwith_traceback(\u001B[38;5;28;01mNone\u001B[39;00m)\n", - "\u001B[0;31mTypingError\u001B[0m: Failed in nopython mode pipeline (step: nopython frontend)\n\u001B[1m\u001B[1mUnknown attribute 'k_B' of type Constants(float64, bool, int64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, int64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, int64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64, float64)\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n\u001B[0m\n\u001B[0m\u001B[1mDuring: typing of get attribute at (10)\u001B[0m\n\u001B[1m\nFile \"\", line 10:\u001B[0m\n\u001B[1m\u001B[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "
" - ], - "image/png": "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" - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "execution_count": 3 + ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.785100072Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 100.0\n", - "1 10000.0\n", - "2 15000.0\n", - "3 20000.0\n", - "4 25000.0\n", - "5 30000.0\n", - "6 35000.0\n", - "7 40000.0\n", - "8 45000.0\n", - "9 50000.0\n", - "10 55000.0\n", - "11 60000.0\n", - "[ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", - " 55000. 60000.]\n", - "[ 22.76539614 14.07241918 9.42251052 5.04148984 1.22854917\n", - " -2.73095271 -7.13023918 -12.04458049 -17.52580689 -23.59720075\n", - " -30.26381921 -37.57848389]\n", - "[ 22.76539835 14.07229129 9.41976599 4.56762734 -0.50557679\n", - " -5.82580613 -11.4243729 -17.33934874 -23.61770124 -30.31832231\n", - " -37.51668399 -45.31183296]\n", - "[ 22.76539833 14.0722912 9.41976459 4.56742887 -0.50663758\n", - " -5.82842689 -11.42911249 -17.34657562 -23.62755213 -30.33073466\n", - " -37.53139951 -45.32857413]\n" - ] - } - ], + "outputs": [], "source": [ "n_sd_per_mode = 20\n", "\n", @@ -206,34 +197,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:18:02.529987551Z", "start_time": "2025-01-26T23:10:25.865329Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "p0 = 100000.0 Pa\n", - "T0 = 22.850000000000023 °C\n", - "dp = [ 100. 10000. 15000. 20000. 25000. 30000. 35000. 40000. 45000. 50000.\n", - " 55000. 60000.]\n", - "Tmin (S0=0.5, C0=2000) = [ 22.76539614 14.07241918 9.42251052 5.04148984 1.22854917\n", - " -2.73095271 -7.13023918 -12.04458049 -17.52580689 -23.59720075\n", - " -30.26381921 -37.57848389]\n", - "Tmin (S0=0.5, C0=1) = [ 22.76539835 14.07229129 9.41976599 4.56762734 -0.50557679\n", - " -5.82580613 -11.4243729 -17.33934874 -23.61770124 -30.31832231\n", - " -37.51668399 -45.31183296]\n", - "Tmin (S0=0, C0=1) = [ 22.76539833 14.0722912 9.41976459 4.56742887 -0.50663758\n", - " -5.82842689 -11.42911249 -17.34657562 -23.62755213 -30.33073466\n", - " -37.53139951 -45.32857413]\n" - ] - } - ], + "outputs": [], "source": [ "print(\"p0 =\",p0,\"Pa\")\n", "print(\"T0 =\",296-273.15,\"°C\")\n", @@ -245,67 +216,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:18:02.702242840Z", "start_time": "2025-01-26T23:10:40.873425Z" } }, - "outputs": [ - { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:42:26.145849\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "fafd72b8735245368a0ad8eaaa2c0b7e", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./Tmin_dp.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T14:42:26.648680\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "27155a3c6f8c4efabb0091474c22289a", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"./dp_sweep.pdf
\")" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", From 59a0fa460c5885c45103fd626f52cdf729f5c96c Mon Sep 17 00:00:00 2001 From: claresinger Date: Thu, 30 Jan 2025 17:05:21 -0500 Subject: [PATCH 30/56] wip add nan SDs. getting error about index out of bounds. --- .../expansion_experiment.ipynb | 35 ++++--------------- .../Erinin_et_al_2025/expansion_simulation.py | 16 +++++++-- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 97325b3d6..5038e5f2f 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -66,38 +66,15 @@ }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.0088741793315877e-251\n", - "0.0\n", - "0.0\n", - "0.0\n", - "0.0\n", - "0.0\n", - "0.0\n", - "1.7154986878176384e-167\n", - "2.178592573781986e-91\n", - "5.5016580938091175e-52\n", - "4.5218624514050985e-29\n", - "1.2371157133280349e-14\n", - "5.4303370061083676e-05\n", - "292.405494788522\n" - ] - }, - { - "ename": "ValueError", - "evalue": "No available null SDs to spawn. Please provide particles with nan filled attributes.", + "ename": "IndexError", + "evalue": "index 20 is out of bounds for axis 0 with size 20", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/var/folders/j_/wj_gdgdx2jdbw7vwy0bnq5hm0000gn/T/ipykernel_76947/519356353.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 20\u001b[0m )\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_expansion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mformulae\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maerosol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn_sd_per_mode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtotal_time\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdt\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDT\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0max\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Research/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py\u001b[0m in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001b[0m\n\u001b[1;32m 115\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0m_\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn_steps\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 117\u001b[0;31m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msteps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 118\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mproduct\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproducts\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 119\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mproduct\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"dry:dN/dR\"\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mproduct\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m\"wet:dN/dR\"\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Research/PySDM/PySDM/particulator.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdynamic\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdynamics\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 48\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimers\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 49\u001b[0;31m \u001b[0mdynamic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 50\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_steps\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_notify_observers\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Research/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[0;34m\"kappa times dry volume\"\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 39\u001b[0m }\n\u001b[0;32m---> 40\u001b[0;31m self.particulator.spawn(\n\u001b[0m\u001b[1;32m 41\u001b[0m \u001b[0mspawned_particle_index\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[0mnumber_of_super_particles_to_spawn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Research/PySDM/PySDM/particulator.py\u001b[0m in \u001b[0;36mspawn\u001b[0;34m(self, spawned_particle_index, spawned_particle_multiplicity, spawned_particle_extensive_attributes, number_of_super_particles_to_spawn)\u001b[0m\n\u001b[1;32m 450\u001b[0m \u001b[0mn_null\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_sd\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msuper_droplet_count\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 451\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mn_null\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 452\u001b[0;31m raise ValueError(\n\u001b[0m\u001b[1;32m 453\u001b[0m \u001b[0;34m\"No available null SDs to spawn. Please provide particles with nan filled attributes.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 454\u001b[0m )\n", - "\u001b[0;31mValueError\u001b[0m: No available null SDs to spawn. Please provide particles with nan filled attributes." + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/j_/wj_gdgdx2jdbw7vwy0bnq5hm0000gn/T/ipykernel_77818/519356353.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 20\u001b[0m )\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_expansion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mformulae\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maerosol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn_sd_per_mode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtotal_time\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdt\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDT\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0max\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Research/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py\u001b[0m in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001b[0m\n\u001b[1;32m 139\u001b[0m \u001b[0mattr_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_ndarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdrop_id\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_sd\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 141\u001b[0;31m \u001b[0mattr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdrop_id\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattr_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdrop_id\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 142\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 143\u001b[0m \u001b[0mdry_spectrum\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproducts\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"dry:dN/dR\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mIndexError\u001b[0m: index 20 is out of bounds for axis 0 with size 20" ] }, { diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 0373eb7cf..fbdd101ed 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -19,6 +19,7 @@ def run_expansion( formulae, aerosol, n_sd_per_mode, + n_sd_homo_liq_nucleation=100, RH0=0.7, T0=296 * si.K, p0=1000 * si.hPa, @@ -68,7 +69,7 @@ def run_expansion( volume=volume, ) - n_sd = n_sd_per_mode * len(aerosol.modes) + n_sd = n_sd_per_mode * len(aerosol.modes) + n_sd_homo_liq_nucleation builder = Builder( backend=CPU(formulae, override_jit_flags={"parallel": False}), @@ -103,7 +104,18 @@ def run_expansion( ) attributes["volume"] = builder.formulae.trivia.volume(radius=r_wet) - particulator = builder.build(attributes, products=products) + particulator = builder.build( + attributes={ + k: np.pad( + array=v, + pad_width=(0, n_sd_homo_liq_nucleation), + mode="constant", + constant_values=np.nan if k == "multiplicity" else 0, + ) + for k, v in attributes.items() + }, + products=products, + ) output = {product.name: [] for product in particulator.products.values()} output_attributes = { From 3bb377bae07106bb01359c2b16ff36d8a7d01d66 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 31 Jan 2025 22:45:16 +0100 Subject: [PATCH 31/56] make attribute saving logic compatible with variable state-vector size --- .../dynamics/homogeneous_liquid_nucleation.py | 3 ++- PySDM/particulator.py | 2 +- .../Erinin_et_al_2025/expansion_simulation.py | 20 ++++++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index 653c5406c..f81d23045 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -1,3 +1,4 @@ +import numpy as np from PySDM.dynamics.impl import register_dynamic from PySDM.dynamics.impl import SuperParticleSpawningDynamic @@ -41,7 +42,7 @@ def __call__(self): self.particulator.spawn( spawned_particle_index=self.index, number_of_super_particles_to_spawn=1, - spawned_particle_multiplicity=new_sd_multiplicity, + spawned_particle_multiplicity=np.asarray((new_sd_multiplicity,)), spawned_particle_extensive_attributes=new_sd_extensive_attributes, ) # TODO: subtract the water mass from ambient vapour diff --git a/PySDM/particulator.py b/PySDM/particulator.py index 87dea3f59..adf1a0cfb 100644 --- a/PySDM/particulator.py +++ b/PySDM/particulator.py @@ -464,7 +464,7 @@ def spawn( Instead increase multiplicity of spawned particles." ) - self.backend.spawn( + self.backend.spawning( idx=self.attributes._ParticleAttributes__idx, multiplicity=self.attributes["multiplicity"], extensive_attributes=self.attributes.get_extensive_attribute_storage(), diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index fbdd101ed..a5a4142e3 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -119,10 +119,13 @@ def run_expansion( output = {product.name: [] for product in particulator.products.values()} output_attributes = { - "multiplicity": tuple([] for _ in range(particulator.n_sd)), - "volume": tuple([] for _ in range(particulator.n_sd)), - "critical volume": tuple([] for _ in range(particulator.n_sd)), - "critical supersaturation": tuple([] for _ in range(particulator.n_sd)), + k: [] + for k in ( + "multiplicity", + "volume", + "critical volume", + "critical supersaturation", + ) } for _ in range(n_steps): @@ -135,10 +138,13 @@ def run_expansion( output[product.name].append(value) else: output[product.name].append(value[0]) + mult = particulator.attributes["multiplicity"].to_ndarray(raw=True) for key, attr in output_attributes.items(): - attr_data = particulator.attributes[key].to_ndarray() - for drop_id in range(particulator.n_sd): - attr[drop_id].append(attr_data[drop_id]) + if key == "multiplicity": + continue + data = particulator.attributes[key].to_ndarray(raw=True) + data[mult == 0] = np.nan + attr.append(data) dry_spectrum = particulator.products["dry:dN/dR"].get() wet_spectrum = particulator.products["wet:dN/dR"].get() From c4f2ec8958543ce0a37af7ebdd0c7e5b11c94b4d Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Tue, 4 Feb 2025 00:16:55 +0100 Subject: [PATCH 32/56] introduce SuperParticleSpawningDynamic.check_extensive_attribute_keys() and use it in HomogeneousLiquidNucleation() ... but still fails --- .../impl_numba/methods/spawning_methods.py | 10 +++++----- PySDM/dynamics/homogeneous_liquid_nucleation.py | 15 +++++++++++---- .../impl/super_particle_spawning_dynamic.py | 17 ++++++++++++++++- PySDM/dynamics/seeding.py | 13 ++++--------- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/PySDM/backends/impl_numba/methods/spawning_methods.py b/PySDM/backends/impl_numba/methods/spawning_methods.py index ec6fb3832..98ad512e7 100644 --- a/PySDM/backends/impl_numba/methods/spawning_methods.py +++ b/PySDM/backends/impl_numba/methods/spawning_methods.py @@ -18,13 +18,13 @@ def body( # pylint: disable=too-many-arguments spawned_particle_index, spawned_particle_multiplicity, spawned_particle_extensive_attributes, - number_of_super_particles_to_inject: int, + number_of_super_particles_to_spawn: int, ): number_of_super_particles_already_injected = 0 # TODO #1387 start enumerating from the end of valid particle set for i, mult in enumerate(multiplicity): if ( - number_of_super_particles_to_inject + number_of_super_particles_to_spawn == number_of_super_particles_already_injected ): break @@ -40,7 +40,7 @@ def body( # pylint: disable=too-many-arguments spawned_particle_extensive_attributes[a, s] ) assert ( - number_of_super_particles_to_inject + number_of_super_particles_to_spawn == number_of_super_particles_already_injected ) @@ -62,7 +62,7 @@ def spawning( multiplicity=multiplicity.data, extensive_attributes=extensive_attributes.data, spawned_particle_index=spawned_particle_index.data, - spawnd_particle_multiplicity=spawned_particle_multiplicity.data, - spawnd_particle_extensive_attributes=spawned_particle_extensive_attributes.data, + spawned_particle_multiplicity=spawned_particle_multiplicity.data, + spawned_particle_extensive_attributes=spawned_particle_extensive_attributes.data, number_of_super_particles_to_spawn=number_of_super_particles_to_spawn, ) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index f81d23045..cefcf53c4 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -35,14 +35,21 @@ def __call__(self): ) v_wet = self.formulae.trivia.volume(radius=r_wet) new_sd_extensive_attributes = { - "water mass": v_wet * self.formulae.constants.rho_w, - "dry volume": 0, - "kappa times dry volume": 0, + "water mass": (v_wet * self.formulae.constants.rho_w,), + "dry volume": (0,), + "kappa times dry volume": (0,), } + self.check_extensive_attribute_keys( + particulator_attributes=self.particulator.attributes, + spawned_attributes=new_sd_extensive_attributes, + ) self.particulator.spawn( spawned_particle_index=self.index, number_of_super_particles_to_spawn=1, spawned_particle_multiplicity=np.asarray((new_sd_multiplicity,)), - spawned_particle_extensive_attributes=new_sd_extensive_attributes, + spawned_particle_extensive_attributes=self.particulator.IndexedStorage.from_ndarray( + self.index, + np.asarray(list(new_sd_extensive_attributes.values())), + ), ) # TODO: subtract the water mass from ambient vapour diff --git a/PySDM/dynamics/impl/super_particle_spawning_dynamic.py b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py index b77fe8372..b0725a93b 100644 --- a/PySDM/dynamics/impl/super_particle_spawning_dynamic.py +++ b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py @@ -1,2 +1,17 @@ +from PySDM.impl.particle_attributes import ParticleAttributes + + class SuperParticleSpawningDynamic: - pass + @staticmethod + def check_extensive_attribute_keys( + particulator_attributes: ParticleAttributes, + spawned_attributes: dict, + ): + if tuple(particulator_attributes.get_extensive_attribute_keys()) != tuple( + spawned_attributes.keys() + ): + raise ValueError( + f"extensive attributes ({spawned_attributes.keys()})" + " do not match those used in particulator" + f" ({particulator_attributes.get_extensive_attribute_keys()})" + ) diff --git a/PySDM/dynamics/seeding.py b/PySDM/dynamics/seeding.py index cf85c64cb..6ce31647b 100644 --- a/PySDM/dynamics/seeding.py +++ b/PySDM/dynamics/seeding.py @@ -34,15 +34,10 @@ def register(self, builder): self.particulator = builder.particulator def post_register_setup_when_attributes_are_known(self): - if tuple(self.particulator.attributes.get_extensive_attribute_keys()) != tuple( - self.seeded_particle_extensive_attributes.keys() - ): - raise ValueError( - f"extensive attributes ({self.seeded_particle_extensive_attributes.keys()})" - " do not match those used in particulator" - f" ({self.particulator.attributes.get_extensive_attribute_keys()})" - ) - + SuperParticleSpawningDynamic.check_extensive_attribute_keys( + particulator_attributes=self.particulator.attributes, + spawned_attributes=self.seeded_particle_extensive_attributes, + ) self.index = self.particulator.Index.identity_index( len(self.seeded_particle_multiplicity) ) From 763d853a6f0ae2bc4336c3866bb8c03d7c4d507a Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Tue, 4 Feb 2025 06:02:42 +0100 Subject: [PATCH 33/56] make multiplicity a Storage as well (currently stops on: "Python int too large to convert to C long") --- .../dynamics/homogeneous_liquid_nucleation.py | 21 ++++++++++++++----- .../Erinin_et_al_2025/expansion_simulation.py | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index cefcf53c4..63b123307 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -39,17 +39,28 @@ def __call__(self): "dry volume": (0,), "kappa times dry volume": (0,), } + + # TODO: to be done once, not every time we spawn self.check_extensive_attribute_keys( particulator_attributes=self.particulator.attributes, spawned_attributes=new_sd_extensive_attributes, ) + + # TODO: allocate once, reuse + new_sd_extensive_attributes = self.particulator.IndexedStorage.from_ndarray( + self.index, + np.asarray(list(new_sd_extensive_attributes.values())), + ) + # TODO: ditto + new_sd_multiplicity = self.particulator.IndexedStorage.from_ndarray( + self.index, + np.asarray((new_sd_multiplicity,), dtype=np.int64), + ) + self.particulator.spawn( spawned_particle_index=self.index, number_of_super_particles_to_spawn=1, - spawned_particle_multiplicity=np.asarray((new_sd_multiplicity,)), - spawned_particle_extensive_attributes=self.particulator.IndexedStorage.from_ndarray( - self.index, - np.asarray(list(new_sd_extensive_attributes.values())), - ), + spawned_particle_multiplicity=new_sd_multiplicity, + spawned_particle_extensive_attributes=new_sd_extensive_attributes, ) # TODO: subtract the water mass from ambient vapour diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index a5a4142e3..02bc46938 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -77,7 +77,7 @@ def run_expansion( environment=env, ) builder.add_dynamic(AmbientThermodynamics()) - builder.add_dynamic(Condensation()) + builder.add_dynamic(Condensation(adaptive=False)) builder.add_dynamic(HomogeneousLiquidNucleation()) builder.request_attribute("critical supersaturation") From 1dc09c9a1eaa47a9b535dabaf830b834caf8d7fb Mon Sep 17 00:00:00 2001 From: claresinger Date: Tue, 4 Feb 2025 11:25:28 -0500 Subject: [PATCH 34/56] make example run with nucleation by shortening timestep to avoid overflow. and increasing null SDs to avoid running out of SDs. add some new products to track nucleated particles better. --- .../expansion_experiment.ipynb | 51 ++++++++++--------- .../Erinin_et_al_2025/expansion_simulation.py | 12 ++++- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 5038e5f2f..506095dfe 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -65,42 +65,45 @@ } }, "outputs": [ - { - "ename": "IndexError", - "evalue": "index 20 is out of bounds for axis 0 with size 20", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m/var/folders/j_/wj_gdgdx2jdbw7vwy0bnq5hm0000gn/T/ipykernel_77818/519356353.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 20\u001b[0m )\n\u001b[1;32m 21\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 22\u001b[0;31m \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mrun_expansion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mformulae\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maerosol\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mn_sd_per_mode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtotal_time\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0ms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdt\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mDT\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 23\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 24\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0max\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maxes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflatten\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/Research/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py\u001b[0m in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume)\u001b[0m\n\u001b[1;32m 139\u001b[0m \u001b[0mattr_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto_ndarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mdrop_id\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mn_sd\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 141\u001b[0;31m \u001b[0mattr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdrop_id\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mattr_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdrop_id\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 142\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 143\u001b[0m \u001b[0mdry_spectrum\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparticulator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mproducts\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"dry:dN/dR\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mIndexError\u001b[0m: index 20 is out of bounds for axis 0 with size 20" - ] - }, { "data": { - "image/png": "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", + "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-04T11:23:07.958796\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ - "
" + "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b205696a8eb46afa50516c94a012690", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./C0_sweep_traces.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ "n_sd_per_mode = 20\n", - "DT = .1 * si.s\n", + "DT = .01 * si.s\n", "\n", - "variables = [\"p\", \"T\", \"s\", \"water_vapour_mixing_ratio\", \"liquid_water_mixing_ratio\", \"reff\"]\n", - "offsets = [0, -273.15, 1, 0, 0, 0]\n", - "factors = [1/100, 1, 1, 1, 1, 1]\n", - "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\"]\n", - "fig,axes=pyplot.subplots(2,3,figsize=(10,5),sharex=True,sharey=False,constrained_layout=True)\n", + "variables = [\"p\", \"T\", \"s\", \"sd_count\", \"water_vapour_mixing_ratio\", \"liquid_water_mixing_ratio\", \"reff\", \"n_drop\"]\n", + "offsets = [0, -273.15, 1, 0, 0, 0, 0, 0]\n", + "factors = [1/100, 1, 1, 1, 1, 1, 1, 1]\n", + "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"SD count\",\n", + " \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\", \"$N_d$ [cm$^{-3}$]\"]\n", + "fig,axes=pyplot.subplots(2,4,figsize=(12,5),sharex=True,sharey=False,constrained_layout=True)\n", "\n", - "for Na in [1e1, 1e3, 1e5]: #[1, 10, 100, 1000, 10000, 100000]:\n", + "for Na in [1e2, 5e2, 1e3]: #[1, 10, 100, 1000, 10000, 100000]:\n", "\n", " formulae = Formulae(\n", " adiabatic_exponent=\"MoistLeadingTerms\",\n", @@ -112,13 +115,13 @@ " N=Na / si.cm**3,\n", " )\n", "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, total_time=4*si.s, dt=DT)\n", + " output = run_expansion(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation=200, total_time=4*si.s, dt=DT)\n", " \n", " for i,ax in enumerate(axes.flatten()):\n", " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", " ax.plot(output.profile[\"t\"], y, label=f\"{Na:.0e}\")\n", - " # if i == 2:\n", - " # ax.set_yscale(\"log\")\n", + " if i == 7:\n", + " ax.set_yscale(\"log\")\n", " ax.set_xlabel(\"Time [s]\")\n", " ax.set_ylabel(ylabels[i])\n", "\n", diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 02bc46938..20ab103ca 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -33,6 +33,7 @@ def run_expansion( dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False) wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False) products = ( + PySDM_products.SuperDropletCountPerGridbox(name="sd_count"), PySDM_products.WaterMixingRatio(unit="g/kg", name="liquid_water_mixing_ratio"), PySDM_products.PeakSupersaturation(name="s"), PySDM_products.AmbientRelativeHumidity(name="RH"), @@ -55,7 +56,16 @@ def run_expansion( dry=False, ), PySDM_products.ActivatedEffectiveRadius( - name="reff", unit="um", count_activated=True, count_unactivated=False + name="act_reff", unit="um", count_activated=True, count_unactivated=False + ), + PySDM_products.EffectiveRadius( + name="reff", + unit="um", + ), + PySDM_products.ParticleConcentration( + name="n_drop", + unit="cm^-3", + # radius_range=(0.5 * si.um, 25 * si.um), ), ) From d53312a8b507242522e14edf2c0087906588f81f Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 6 Feb 2025 17:07:04 +0100 Subject: [PATCH 35/56] simplified units handling, enabled condensation adaptivity --- .../expansion_experiment.ipynb | 3987 ++++++++++++++++- .../Erinin_et_al_2025/expansion_simulation.py | 62 +- 2 files changed, 3964 insertions(+), 85 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 506095dfe..2bbb44bef 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:31.584604Z", @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:37.280272Z", @@ -49,15 +49,62 @@ "from matplotlib import pyplot\n", "from open_atmos_jupyter_utils import show_plot\n", "from PySDM import Formulae\n", - "from PySDM.physics import si\n", - "\n", + "from PySDM.physics import si, in_unit\n", + "from PySDM import products as PySDM_products\n", "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False)\n", + "wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False)\n", + "\n", + "products = (\n", + " PySDM_products.SuperDropletCountPerGridbox(name=\"SD count\"),\n", + " PySDM_products.WaterMixingRatio(unit=\"g/kg\", name=\"$q_\\ell$\"),\n", + " PySDM_products.PeakSupersaturation(name=\"Saturation ratio\"),\n", + " PySDM_products.AmbientRelativeHumidity(name=\"RH\"),\n", + " PySDM_products.AmbientTemperature(name=\"Temperature\", var=\"T\"),\n", + " PySDM_products.AmbientPressure(name=\"Pressure\", var=\"p\", unit=\"hPa\"),\n", + " PySDM_products.AmbientWaterVapourMixingRatio(\n", + " unit=\"g/kg\", name=\"$q_v$\", var=\"water_vapour_mixing_ratio\"\n", + " ),\n", + " PySDM_products.Time(name=\"t\"),\n", + " PySDM_products.ParticleSizeSpectrumPerVolume(\n", + " name=\"dry:dN/dR\",\n", + " unit=\"m^-3 m^-1\",\n", + " radius_bins_edges=dry_radius_bin_edges,\n", + " dry=True,\n", + " ),\n", + " PySDM_products.ParticleSizeSpectrumPerVolume(\n", + " name=\"wet:dN/dR\",\n", + " unit=\"m^-3 m^-1\",\n", + " radius_bins_edges=wet_radius_bin_edges,\n", + " dry=False,\n", + " ),\n", + " PySDM_products.ActivatedEffectiveRadius(\n", + " name=\"act_reff\", unit=\"um\", count_activated=True, count_unactivated=False\n", + " ),\n", + " PySDM_products.EffectiveRadius(\n", + " name=\"$r_{eff}$\",\n", + " unit=\"um\",\n", + " ),\n", + " PySDM_products.ParticleConcentration(\n", + " name=\"$N_d$\",\n", + " unit=\"cm^-3\",\n", + " # radius_range=(0.5 * si.um, 25 * si.um),\n", + " ),\n", + ") " + ] + }, + { + "cell_type": "code", + "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.715504Z", @@ -67,25 +114,3865 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-04T11:23:07.958796\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2025-02-06T17:05:49.112691\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3b205696a8eb46afa50516c94a012690", + "model_id": "3679baed2814450396d21052920ee569", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HTML(value=\"./C0_sweep_traces.pdf
\")" + "HBox(children=(HTML(value=\"./C0_sweep_traces.pdf
\"), HT…" ] }, "metadata": {}, @@ -94,51 +3981,75 @@ ], "source": [ "n_sd_per_mode = 20\n", - "DT = .01 * si.s\n", + "DT = .1 * si.s\n", "\n", - "variables = [\"p\", \"T\", \"s\", \"sd_count\", \"water_vapour_mixing_ratio\", \"liquid_water_mixing_ratio\", \"reff\", \"n_drop\"]\n", - "offsets = [0, -273.15, 1, 0, 0, 0, 0, 0]\n", - "factors = [1/100, 1, 1, 1, 1, 1, 1, 1]\n", - "ylabels = [\"Pressure [hPa]\", \"Temperature [°C]\", \"Saturation ratio\", \"SD count\",\n", - " \"$q_v$ [g kg$^{-1}$]\", \"$q_\\ell$ [g kg$^{-1}$]\", \"$r_{eff}$ [$\\mu$m]\", \"$N_d$ [cm$^{-3}$]\"]\n", - "fig,axes=pyplot.subplots(2,4,figsize=(12,5),sharex=True,sharey=False,constrained_layout=True)\n", - "\n", - "for Na in [1e2, 5e2, 1e3]: #[1, 10, 100, 1000, 10000, 100000]:\n", + "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", \"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", + "fig, axes = pyplot.subplots(2,4,figsize=(12,5), sharex=True, sharey=False, constrained_layout=True)\n", "\n", + "for Na in [1e2/si.cm**3, 5e2/si.cm**3, 1e3/si.cm**3]:\n", " formulae = Formulae(\n", " adiabatic_exponent=\"MoistLeadingTerms\",\n", " homogeneous_liquid_nucleation_rate='CNT',\n", " )\n", " const = formulae.constants\n", " aerosol = AerosolChamber(\n", - " water_molar_volume=const.Mv / const.rho_w,\n", - " N=Na / si.cm**3,\n", - " )\n", + " water_molar_volume=const.Mv / const.rho_w,\n", + " N=Na,\n", + " )\n", + " output = run_expansion(\n", + " formulae=formulae,\n", + " aerosol=aerosol,\n", + " n_sd_per_mode=n_sd_per_mode,\n", + " n_sd_homo_liq_nucleation=200,\n", + " total_time=4*si.s,\n", + " dt=DT,\n", + " products=products,\n", + " )\n", "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation=200, total_time=4*si.s, dt=DT)\n", - " \n", - " for i,ax in enumerate(axes.flatten()):\n", - " y = np.array(output.profile[variables[i]]) * factors[i] + offsets[i]\n", - " ax.plot(output.profile[\"t\"], y, label=f\"{Na:.0e}\")\n", + " for i, ax in enumerate(axes.flatten()):\n", + " y = np.array(output.profile[variables[i]])\n", + " ax.plot(output.profile[\"t\"], y, label=f\"{in_unit(Na, 1/si.cm**3):.0e}\")\n", " if i == 7:\n", " ax.set_yscale(\"log\")\n", - " ax.set_xlabel(\"Time [s]\")\n", - " ax.set_ylabel(ylabels[i])\n", + " ax.set_xlabel(f\"Time [{output.units['t']}]\")\n", + " ax.set_ylabel(f\"{variables[i]} [{output.units[variables[i]]}]\")\n", "\n", - "axes[0,0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", + "axes[0, 0].legend(title=\"$C_0$ [cm$^{-3}$]\")\n", "show_plot(\"C0_sweep_traces.pdf\")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.785100072Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 100.0\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'types.SimpleNamespace' object has no attribute 'j_liq_homo'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[5], line 17\u001b[0m\n\u001b[1;32m 15\u001b[0m const \u001b[38;5;241m=\u001b[39m formulae\u001b[38;5;241m.\u001b[39mconstants\n\u001b[1;32m 16\u001b[0m aerosol \u001b[38;5;241m=\u001b[39m AerosolChamber(water_molar_volume\u001b[38;5;241m=\u001b[39mconst\u001b[38;5;241m.\u001b[39mMv \u001b[38;5;241m/\u001b[39m const\u001b[38;5;241m.\u001b[39mrho_w, N\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2000\u001b[39m \u001b[38;5;241m/\u001b[39m si\u001b[38;5;241m.\u001b[39mcm\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m3\u001b[39m)\n\u001b[0;32m---> 17\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[43mrun_expansion\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maerosol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maerosol\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mRH0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0.5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mp0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mp0\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdpi\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDT\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproducts\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproducts\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 18\u001b[0m Tmin[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmin(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m \u001b[38;5;66;03m# °C\u001b[39;00m\n\u001b[1;32m 19\u001b[0m Smax[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmax(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m \u001b[38;5;66;03m# saturation ratio\u001b[39;00m\n", + "File \u001b[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:105\u001b[0m, in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume, products)\u001b[0m\n\u001b[1;32m 94\u001b[0m output_attributes \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 95\u001b[0m k: []\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 101\u001b[0m )\n\u001b[1;32m 102\u001b[0m }\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n_steps):\n\u001b[0;32m--> 105\u001b[0m \u001b[43mparticulator\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43msteps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m product \u001b[38;5;129;01min\u001b[39;00m particulator\u001b[38;5;241m.\u001b[39mproducts\u001b[38;5;241m.\u001b[39mvalues():\n\u001b[1;32m 107\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdry:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwet:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", + "File \u001b[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001b[0m, in \u001b[0;36mParticulator.run\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, dynamic \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdynamics\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimers[key]:\n\u001b[0;32m---> 49\u001b[0m \u001b[43mdynamic\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 50\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_steps \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers()\n", + "File \u001b[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:23\u001b[0m, in \u001b[0;36mHomogeneousLiquidNucleation.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 19\u001b[0m env \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 20\u001b[0m k: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment[k]\u001b[38;5;241m.\u001b[39mto_ndarray()[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 21\u001b[0m } \u001b[38;5;66;03m# TODO: >0D\u001b[39;00m\n\u001b[1;32m 22\u001b[0m e_s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mformulae\u001b[38;5;241m.\u001b[39msaturation_vapour_pressure\u001b[38;5;241m.\u001b[39mpvs_water(env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m---> 23\u001b[0m j \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhomogeneous_liquid_nucleation_rate\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mj_liq_homo\u001b[49m(\n\u001b[1;32m 24\u001b[0m env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m], env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m], e_s\n\u001b[1;32m 25\u001b[0m )\n\u001b[1;32m 27\u001b[0m \u001b[38;5;66;03m# TODO: take care of cases where round yields zero -> MC sampling?\u001b[39;00m\n\u001b[1;32m 28\u001b[0m new_sd_multiplicity \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mround\u001b[39m(\n\u001b[1;32m 29\u001b[0m j \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment\u001b[38;5;241m.\u001b[39mmesh\u001b[38;5;241m.\u001b[39mdv \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39mdt\n\u001b[1;32m 30\u001b[0m )\n", + "\u001b[0;31mAttributeError\u001b[0m: 'types.SimpleNamespace' object has no attribute 'j_liq_homo'" + ] + } + ], "source": [ "n_sd_per_mode = 20\n", "\n", @@ -156,16 +4067,16 @@ " formulae = Formulae()\n", " const = formulae.constants\n", " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=2000 / si.cm**3)\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", " Tmin[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", " Smax[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", "\n", " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=1 / si.cm**3)\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", " Tmin_clean[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", " Smax_clean[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", "\n", - " output = run_expansion(formulae, aerosol, n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dt=DT)\n", + " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", " Tmin_dry[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", " Smax_dry[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", "\n", @@ -266,7 +4177,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.2" }, "vscode": { "interpreter": { diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 20ab103ca..55d7ef7c3 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -2,7 +2,6 @@ import numpy as np from PySDM import Builder -from PySDM import products as PySDM_products from PySDM.backends import CPU from PySDM.dynamics import ( AmbientThermodynamics, @@ -16,6 +15,7 @@ def run_expansion( + *, formulae, aerosol, n_sd_per_mode, @@ -28,46 +28,9 @@ def run_expansion( total_time=4 * si.s, dt=0.1 * si.s, volume=0.14 * si.m**3, + products=None, ): n_steps = int(np.ceil(total_time / dt)) - dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False) - wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False) - products = ( - PySDM_products.SuperDropletCountPerGridbox(name="sd_count"), - PySDM_products.WaterMixingRatio(unit="g/kg", name="liquid_water_mixing_ratio"), - PySDM_products.PeakSupersaturation(name="s"), - PySDM_products.AmbientRelativeHumidity(name="RH"), - PySDM_products.AmbientTemperature(name="T"), - PySDM_products.AmbientPressure(name="p"), - PySDM_products.AmbientWaterVapourMixingRatio( - unit="g/kg", name="water_vapour_mixing_ratio" - ), - PySDM_products.Time(name="t"), - PySDM_products.ParticleSizeSpectrumPerVolume( - name="dry:dN/dR", - unit="m^-3 m^-1", - radius_bins_edges=dry_radius_bin_edges, - dry=True, - ), - PySDM_products.ParticleSizeSpectrumPerVolume( - name="wet:dN/dR", - unit="m^-3 m^-1", - radius_bins_edges=wet_radius_bin_edges, - dry=False, - ), - PySDM_products.ActivatedEffectiveRadius( - name="act_reff", unit="um", count_activated=True, count_unactivated=False - ), - PySDM_products.EffectiveRadius( - name="reff", - unit="um", - ), - PySDM_products.ParticleConcentration( - name="n_drop", - unit="cm^-3", - # radius_range=(0.5 * si.um, 25 * si.um), - ), - ) env = ExpansionChamber( dt=dt, @@ -87,7 +50,7 @@ def run_expansion( environment=env, ) builder.add_dynamic(AmbientThermodynamics()) - builder.add_dynamic(Condensation(adaptive=False)) + builder.add_dynamic(Condensation(adaptive=True)) builder.add_dynamic(HomogeneousLiquidNucleation()) builder.request_attribute("critical supersaturation") @@ -124,7 +87,7 @@ def run_expansion( ) for k, v in attributes.items() }, - products=products, + products=products or (), ) output = {product.name: [] for product in particulator.products.values()} @@ -161,22 +124,27 @@ def run_expansion( Output = namedtuple( "Output", - [ + ( "profile", "attributes", "aerosol", - "dry_radius_bin_edges", "dry_spectrum", - "wet_radius_bin_edges", "wet_spectrum", - ], + "units", + ), ) return Output( profile=output, attributes=output_attributes, aerosol=aerosol, - dry_radius_bin_edges=dry_radius_bin_edges, dry_spectrum=dry_spectrum, - wet_radius_bin_edges=wet_radius_bin_edges, wet_spectrum=wet_spectrum, + units={ + key: ( + product.unit[2:] + if product.unit[0:2] == "1 " + else product.unit[4:] if product.unit[0:4] == "1.0 " else product.unit + ).replace("**", "^") + for key, product in particulator.products.items() + }, ) From 0ee157d0e2a37a3bd19d8875a3954aafc0a20f50 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 6 Feb 2025 23:19:38 +0100 Subject: [PATCH 36/56] fix bib issues --- docs/bibliography.json | 8 ++++++-- examples/PySDM_examples/Erinin_et_al_2025/aerosol.py | 2 +- tests/unit_tests/backends/test_spawning_methods.py | 2 +- .../physics/test_homogeneous_liquid_nucleation.py | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/bibliography.json b/docs/bibliography.json index 272dd8aa9..f442ce3a5 100644 --- a/docs/bibliography.json +++ b/docs/bibliography.json @@ -707,14 +707,17 @@ "label": "Wexler 1976 (J. Res. NBS A Phys. Ch. 80A)" }, "https://doi.org/10.48550/arXiv.2501.01467": { - "usages": ["examples/PySDM_examples/expansion_chamber/aerosol.py", "examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb"], + "usages": [ + "examples/PySDM_examples/Erinin_et_al_2025/__init__.py", + "examples/PySDM_examples/Erinin_et_al_2025/aerosol.py", + "examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb"], "title": "Droplet Nucleation In a Rapid Expansion Aerosol Chamber", "label": "Erinin et al. 2024 (arXiv:2501.01467)" }, "https://archive.org/details/0237-pdf-atmospheric-chemistry-and-physics-2nd-ed-j.-seinfeld-s.-pandis-wiley-2006-ww": { "usages": [ "PySDM/physics/homogeneous_liquid_nucleation_rate/cnt.py", - "PySDM/physics/constants_defaults.py", + "PySDM/physics/constants_defaults.py" ], "title": "Atmospheric Chemistry and Physics: From Air Pollution to Climate Change, 2nd Edition", "label": "Seinfeld & Pandis 2006 (Wiley)" @@ -764,3 +767,4 @@ "title": "Isotopic Composition and Temperature of Formation of Antarctic Snows", "label": "Picciotto et al. 1960 (Nature 187)" } +} diff --git a/examples/PySDM_examples/Erinin_et_al_2025/aerosol.py b/examples/PySDM_examples/Erinin_et_al_2025/aerosol.py index d7fd58304..36dadaa51 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/aerosol.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/aerosol.py @@ -1,4 +1,4 @@ -""" aerosol parameters from [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467) """ +"""aerosol parameters from [Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467)""" from chempy import Substance from pystrict import strict diff --git a/tests/unit_tests/backends/test_spawning_methods.py b/tests/unit_tests/backends/test_spawning_methods.py index 1dbf1c1bb..cdf0acff6 100644 --- a/tests/unit_tests/backends/test_spawning_methods.py +++ b/tests/unit_tests/backends/test_spawning_methods.py @@ -1,4 +1,4 @@ -""" Seeding backend tests of spawning logic """ +"""Seeding backend tests of spawning logic""" from contextlib import nullcontext diff --git a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py index e81f8144c..de1a687cc 100644 --- a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py +++ b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py @@ -1,4 +1,4 @@ -""" tests checking homogeneous liquid nucleation formulae """ +"""tests checking homogeneous liquid nucleation formulae""" import pytest From ee6cca2c353604f64cad132ca4cef65114f5d5d0 Mon Sep 17 00:00:00 2001 From: claresinger Date: Thu, 6 Feb 2025 22:31:43 -0500 Subject: [PATCH 37/56] fix multiplicity product. print out fractional change in total particle count. seems like Nd is working. need to write an actual test for it. --- .../expansion_experiment.ipynb | 3982 +---------------- .../Erinin_et_al_2025/expansion_simulation.py | 1 + 2 files changed, 85 insertions(+), 3898 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 2bbb44bef..74c8586db 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:31.584604Z", @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:37.280272Z", @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -104,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.715504Z", @@ -113,3880 +113,30 @@ }, "outputs": [ { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2025-02-06T17:05:49.112691\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.8.1, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3679baed2814450396d21052920ee569", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(HTML(value=\"./C0_sweep_traces.pdf
\"), HT…" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "C0=4.00e+08\n", + "C0=4.25e+08\n", + "C0=4.50e+08\n", + "C0=5.00e+08\n", + "C0=5.50e+08\n", + "C0=6.00e+08\n" + ] } ], "source": [ "n_sd_per_mode = 20\n", - "DT = .1 * si.s\n", + "DT = .05 * si.s\n", "\n", - "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", \"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", - "fig, axes = pyplot.subplots(2,4,figsize=(12,5), sharex=True, sharey=False, constrained_layout=True)\n", + "C0_arr = np.array([1e2, 2.5e2, 5e2, 7.5e2, 1e3]) / si.cm**3\n", + "C0_arr = np.array([4e2, 4.25e2, 4.5e2, 5e2, 5.5e2, 6e2]) / si.cm**3\n", "\n", - "for Na in [1e2/si.cm**3, 5e2/si.cm**3, 1e3/si.cm**3]:\n", + "output_all = {}\n", + "\n", + "for Na in C0_arr:\n", + " key = f\"C0={Na:.2e}\"\n", + " print(key)\n", " formulae = Formulae(\n", " adiabatic_exponent=\"MoistLeadingTerms\",\n", " homogeneous_liquid_nucleation_rate='CNT',\n", @@ -4000,17 +150,75 @@ " formulae=formulae,\n", " aerosol=aerosol,\n", " n_sd_per_mode=n_sd_per_mode,\n", - " n_sd_homo_liq_nucleation=200,\n", + " n_sd_homo_liq_nucleation=100,\n", " total_time=4*si.s,\n", " dt=DT,\n", " products=products,\n", " )\n", "\n", + " output_all[key] = output\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4.022129924741352\n", + "0.33969348230391677\n", + "0.019729934281225308\n", + "7.873014603149206e-05\n", + "4.28580000171432e-07\n", + "0.0\n" + ] + }, + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-06T19:12:31.922266\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "65fcc2b974614f83b69cbb8c30e89b69", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./C0_sweep_traces.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", \"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", + "fig, axes = pyplot.subplots(2,4,figsize=(12,5), sharex=True, sharey=False, constrained_layout=True)\n", + "\n", + "for Na in C0_arr:\n", + " key = f\"C0={Na:.2e}\"\n", + " output = output_all[key]\n", + " init_mult = output.attributes[\"multiplicity\"][0]\n", + " final_mult = output.attributes[\"multiplicity\"][-1]\n", + " print((np.sum(final_mult) - np.sum(init_mult)) / np.sum(init_mult))\n", " for i, ax in enumerate(axes.flatten()):\n", " y = np.array(output.profile[variables[i]])\n", - " ax.plot(output.profile[\"t\"], y, label=f\"{in_unit(Na, 1/si.cm**3):.0e}\")\n", + " ax.plot(output.profile[\"t\"], y, label=f\"{in_unit(Na, 1/si.cm**3):.2e}\")\n", " if i == 7:\n", " ax.set_yscale(\"log\")\n", + " ax.set_ylim(3e2,8e2)\n", " ax.set_xlabel(f\"Time [{output.units['t']}]\")\n", " ax.set_ylabel(f\"{variables[i]} [{output.units[variables[i]]}]\")\n", "\n", @@ -4020,36 +228,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.785100072Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 100.0\n" - ] - }, - { - "ename": "AttributeError", - "evalue": "'types.SimpleNamespace' object has no attribute 'j_liq_homo'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[5], line 17\u001b[0m\n\u001b[1;32m 15\u001b[0m const \u001b[38;5;241m=\u001b[39m formulae\u001b[38;5;241m.\u001b[39mconstants\n\u001b[1;32m 16\u001b[0m aerosol \u001b[38;5;241m=\u001b[39m AerosolChamber(water_molar_volume\u001b[38;5;241m=\u001b[39mconst\u001b[38;5;241m.\u001b[39mMv \u001b[38;5;241m/\u001b[39m const\u001b[38;5;241m.\u001b[39mrho_w, N\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2000\u001b[39m \u001b[38;5;241m/\u001b[39m si\u001b[38;5;241m.\u001b[39mcm\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m3\u001b[39m)\n\u001b[0;32m---> 17\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[43mrun_expansion\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maerosol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maerosol\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mRH0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0.5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mp0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mp0\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdpi\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDT\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproducts\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproducts\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 18\u001b[0m Tmin[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmin(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m \u001b[38;5;66;03m# °C\u001b[39;00m\n\u001b[1;32m 19\u001b[0m Smax[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmax(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m \u001b[38;5;66;03m# saturation ratio\u001b[39;00m\n", - "File \u001b[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:105\u001b[0m, in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume, products)\u001b[0m\n\u001b[1;32m 94\u001b[0m output_attributes \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 95\u001b[0m k: []\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 101\u001b[0m )\n\u001b[1;32m 102\u001b[0m }\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n_steps):\n\u001b[0;32m--> 105\u001b[0m \u001b[43mparticulator\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43msteps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m product \u001b[38;5;129;01min\u001b[39;00m particulator\u001b[38;5;241m.\u001b[39mproducts\u001b[38;5;241m.\u001b[39mvalues():\n\u001b[1;32m 107\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdry:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mor\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwet:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", - "File \u001b[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001b[0m, in \u001b[0;36mParticulator.run\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, dynamic \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdynamics\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimers[key]:\n\u001b[0;32m---> 49\u001b[0m \u001b[43mdynamic\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 50\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_steps \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers()\n", - "File \u001b[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:23\u001b[0m, in \u001b[0;36mHomogeneousLiquidNucleation.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 19\u001b[0m env \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 20\u001b[0m k: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment[k]\u001b[38;5;241m.\u001b[39mto_ndarray()[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 21\u001b[0m } \u001b[38;5;66;03m# TODO: >0D\u001b[39;00m\n\u001b[1;32m 22\u001b[0m e_s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mformulae\u001b[38;5;241m.\u001b[39msaturation_vapour_pressure\u001b[38;5;241m.\u001b[39mpvs_water(env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m---> 23\u001b[0m j \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhomogeneous_liquid_nucleation_rate\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mj_liq_homo\u001b[49m(\n\u001b[1;32m 24\u001b[0m env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m], env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m], e_s\n\u001b[1;32m 25\u001b[0m )\n\u001b[1;32m 27\u001b[0m \u001b[38;5;66;03m# TODO: take care of cases where round yields zero -> MC sampling?\u001b[39;00m\n\u001b[1;32m 28\u001b[0m new_sd_multiplicity \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mround\u001b[39m(\n\u001b[1;32m 29\u001b[0m j \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment\u001b[38;5;241m.\u001b[39mmesh\u001b[38;5;241m.\u001b[39mdv \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39mdt\n\u001b[1;32m 30\u001b[0m )\n", - "\u001b[0;31mAttributeError\u001b[0m: 'types.SimpleNamespace' object has no attribute 'j_liq_homo'" - ] - } - ], + "outputs": [], "source": [ "n_sd_per_mode = 20\n", "\n", diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 55d7ef7c3..24b6875f7 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -114,6 +114,7 @@ def run_expansion( mult = particulator.attributes["multiplicity"].to_ndarray(raw=True) for key, attr in output_attributes.items(): if key == "multiplicity": + attr.append(mult) continue data = particulator.attributes[key].to_ndarray(raw=True) data[mult == 0] = np.nan From deb27c44cf6731c9122b36907892d036724f53ae Mon Sep 17 00:00:00 2001 From: claresinger Date: Tue, 11 Feb 2025 16:26:49 -0500 Subject: [PATCH 38/56] qv to vapour_mixing_ratio spelled out --- PySDM/environments/expansion_chamber.py | 6 +++--- PySDM/physics/adiabatic_exponent/moist_leading_terms.py | 8 +++++--- .../Erinin_et_al_2025/expansion_experiment.ipynb | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/PySDM/environments/expansion_chamber.py b/PySDM/environments/expansion_chamber.py index 10cfa5c61..88ad00db2 100644 --- a/PySDM/environments/expansion_chamber.py +++ b/PySDM/environments/expansion_chamber.py @@ -74,10 +74,10 @@ def advance_moist_vars(self): formulae = self.particulator.formulae p_new = self["p"][0] + self.dp_dt * dt - qv = self["water_vapour_mixing_ratio"][0] + vapour_mixing_ratio = self["water_vapour_mixing_ratio"][0] gg = ( - 1 - formulae.adiabatic_exponent.gamma(qv) - ) / formulae.adiabatic_exponent.gamma(qv) + 1 - formulae.adiabatic_exponent.gamma(vapour_mixing_ratio) + ) / formulae.adiabatic_exponent.gamma(vapour_mixing_ratio) T_new = self.initial_temperature * (self.initial_pressure / p_new) ** gg wvmr_new = self._tmp["water_vapour_mixing_ratio"][ 0 diff --git a/PySDM/physics/adiabatic_exponent/moist_leading_terms.py b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py index 799a0fee9..2cf33e213 100644 --- a/PySDM/physics/adiabatic_exponent/moist_leading_terms.py +++ b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py @@ -9,10 +9,12 @@ def __init__(self, _): # pylint: disable=too-many-arguments @staticmethod - def gamma(const, qv): + def gamma(const, vapour_mixing_ratio): return ( 1 + const.Rd / const.c_vd - + (const.Rv * qv) / (const.c_vd * (1 - qv)) - - (const.Rd * qv * const.c_vv) / (const.c_vd**2 * (1 - qv)) + + (const.Rv * vapour_mixing_ratio) + / (const.c_vd * (1 - vapour_mixing_ratio)) + - (const.Rd * vapour_mixing_ratio * const.c_vv) + / (const.c_vd**2 * (1 - vapour_mixing_ratio)) ) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 74c8586db..49fabb835 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -178,7 +178,7 @@ }, { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-06T19:12:31.922266\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-11T16:25:24.446560\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", "text/plain": [ "
" ] @@ -191,7 +191,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "65fcc2b974614f83b69cbb8c30e89b69", + "model_id": "151d019bdf4b487b933773ef34eb4832", "version_major": 2, "version_minor": 0 }, @@ -363,7 +363,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.10.9" }, "vscode": { "interpreter": { From 60cb1666d2d0db5278ef444e9cf7da40f66ae81a Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 01:16:53 +0100 Subject: [PATCH 39/56] fixing tests, addressing pylint hints --- .../dynamics/homogeneous_liquid_nucleation.py | 2 ++ .../impl/super_particle_spawning_dynamic.py | 8 ++++- .../environments/test_expansion_chamber.py | 26 ++++++++++++-- tests/unit_tests/test_particulator.py | 36 +++++++++---------- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index 63b123307..29b77b01f 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -1,3 +1,5 @@ +"""nucleation of droplets in CCN-void air that spawns new super-droplets""" + import numpy as np from PySDM.dynamics.impl import register_dynamic from PySDM.dynamics.impl import SuperParticleSpawningDynamic diff --git a/PySDM/dynamics/impl/super_particle_spawning_dynamic.py b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py index b0725a93b..64497d654 100644 --- a/PySDM/dynamics/impl/super_particle_spawning_dynamic.py +++ b/PySDM/dynamics/impl/super_particle_spawning_dynamic.py @@ -1,12 +1,18 @@ +"""common code for dynamics that spawn new super-droplets""" + from PySDM.impl.particle_attributes import ParticleAttributes -class SuperParticleSpawningDynamic: +class SuperParticleSpawningDynamic: # pylint: disable=too-few-public-methods + """base class for dynamics that spawn new super-droplets""" + @staticmethod def check_extensive_attribute_keys( particulator_attributes: ParticleAttributes, spawned_attributes: dict, ): + """checks if keys (and their order) in user-supplied `spawned_attributes` match + attributes used in the `particulator_attributes`""" if tuple(particulator_attributes.get_extensive_attribute_keys()) != tuple( spawned_attributes.keys() ): diff --git a/tests/unit_tests/environments/test_expansion_chamber.py b/tests/unit_tests/environments/test_expansion_chamber.py index 3d830d327..d5d914194 100644 --- a/tests/unit_tests/environments/test_expansion_chamber.py +++ b/tests/unit_tests/environments/test_expansion_chamber.py @@ -1,10 +1,32 @@ +"""expansion-chamber environment tests""" + +import numpy as np + +from PySDM import Builder from PySDM.environments import ExpansionChamber -def test_expansion_chamber(): +def test_expansion_chamber(backend_instance): + """a minimal instantiation test""" # arrange - env = ExpansionChamber() + env = ExpansionChamber( + dt=np.nan, + volume=np.nan, + initial_pressure=np.nan, + initial_temperature=np.nan, + initial_relative_humidity=np.nan, + delta_pressure=np.nan, + delta_time=np.nan, + ) + particulator = Builder(n_sd=1, backend=backend_instance, environment=env).build( + attributes={ + "multiplicity": np.asarray([1]), + "water mass": np.asarray([np.nan]), + }, + products=(), + ) # act # assert + # TODO #1492 diff --git a/tests/unit_tests/test_particulator.py b/tests/unit_tests/test_particulator.py index db2d19f00..5b52984c2 100644 --- a/tests/unit_tests/test_particulator.py +++ b/tests/unit_tests/test_particulator.py @@ -91,28 +91,28 @@ def sanitize(self): class DP(DummyParticulator): pass - particulator = DP(backend_class, 44) + particulator = DP(backend_class, n_sd=44) particulator.attributes = ParticleAttributes() # fmt: off - particulator.backend.seeding = ( + particulator.backend.spawning = ( lambda idx, multiplicity, extensive_attributes, - seeded_particle_index, - seeded_particle_multiplicity, - seeded_particle_extensive_attributes, - number_of_super_particles_to_inject: + spawned_particle_index, + spawned_particle_multiplicity, + spawned_particle_extensive_attributes, + number_of_super_particles_to_spawn: None ) # fmt: on # act - particulator.seeding( - seeded_particle_index=storage, - seeded_particle_multiplicity=storage, - seeded_particle_extensive_attributes=storage, - number_of_super_particles_to_inject=0, + particulator.spawn( + spawned_particle_index=storage, + spawned_particle_multiplicity=storage, + spawned_particle_extensive_attributes=storage, + number_of_super_particles_to_spawn=0, ) # assert @@ -121,7 +121,7 @@ class DP(DummyParticulator): assert particulator.attributes.sane @staticmethod - def test_seeding_fails_if_no_null_super_droplets_availale(backend_class): + def test_seeding_fails_if_no_null_super_droplets_available(backend_class): # arrange a_number = 44 @@ -133,10 +133,10 @@ def test_seeding_fails_if_no_null_super_droplets_availale(backend_class): )(super_droplet_count=a_number) # act - with pytest.raises(ValueError, match="No available seeds to inject"): - particulator.seeding( - seeded_particle_index=storage, - seeded_particle_multiplicity=storage, - seeded_particle_extensive_attributes=storage, - number_of_super_particles_to_inject=0, + with pytest.raises(ValueError, match="No available null SDs to spawn"): + particulator.spawn( + spawned_particle_index=storage, + spawned_particle_multiplicity=storage, + spawned_particle_extensive_attributes=storage, + number_of_super_particles_to_spawn=0, ) From 8989e388125a7553c738cb8fdc9e4e1a570bfbde Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 01:21:55 +0100 Subject: [PATCH 40/56] reinstantiate changes from #1509 --- PySDM/environments/parcel.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/PySDM/environments/parcel.py b/PySDM/environments/parcel.py index 43ccb534c..e574fbfbc 100644 --- a/PySDM/environments/parcel.py +++ b/PySDM/environments/parcel.py @@ -58,20 +58,13 @@ def register(self, builder): super().register(builder) - params = ( - self.initial_water_vapour_mixing_ratio, - self.formulae.trivia.th_std(pd0, self.T0), - rhod0, - self.z0, - 0, - ) - self["water_vapour_mixing_ratio"][:] = params[0] - self["thd"][:] = params[1] - self["rhod"][:] = params[2] - self["z"][:] = params[3] - self["t"][:] = params[4] - self._tmp["water_vapour_mixing_ratio"][:] = params[0] - + self["water_vapour_mixing_ratio"][:] = self.initial_water_vapour_mixing_ratio + self["thd"][:] = formulae.trivia.th_std(pd0, self.T0) + self["rhod"][:] = rhod0 + self["z"][:] = self.z0 + self._tmp["water_vapour_mixing_ratio"][ + : + ] = self.initial_water_vapour_mixing_ratio self.post_register() def init_attributes( From 84759aa736fa78765de0d6c2261f21340a037e26 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 01:28:30 +0100 Subject: [PATCH 41/56] addressing pylint hints --- PySDM/particulator.py | 2 +- PySDM/physics/adiabatic_exponent/dry.py | 5 +- .../adiabatic_exponent/moist_leading_terms.py | 3 +- .../backends/test_seeding_methods.py | 158 ------------------ .../backends/test_spawning_methods.py | 4 +- .../environments/test_expansion_chamber.py | 2 +- 6 files changed, 7 insertions(+), 167 deletions(-) delete mode 100644 tests/unit_tests/backends/test_seeding_methods.py diff --git a/PySDM/particulator.py b/PySDM/particulator.py index adf1a0cfb..2d1de506f 100644 --- a/PySDM/particulator.py +++ b/PySDM/particulator.py @@ -450,7 +450,7 @@ def spawn( n_null = self.n_sd - self.attributes.super_droplet_count if n_null == 0: raise ValueError( - "No available null SDs to spawn. Please provide particles with nan filled attributes." + "No available null SDs to spawn. Please provide SDs with nan filled attributes." ) if number_of_super_particles_to_spawn > n_null: diff --git a/PySDM/physics/adiabatic_exponent/dry.py b/PySDM/physics/adiabatic_exponent/dry.py index 973e98651..07db362c7 100644 --- a/PySDM/physics/adiabatic_exponent/dry.py +++ b/PySDM/physics/adiabatic_exponent/dry.py @@ -3,11 +3,10 @@ """ -class Dry: +class Dry: # pylint: disable=too-few-public-methods def __init__(self, _): pass - # pylint: disable=too-many-arguments @staticmethod - def gamma(const, qv): + def gamma(const, qv): # pylint: disable=unused-argument return 1 + const.Rd / const.c_vd diff --git a/PySDM/physics/adiabatic_exponent/moist_leading_terms.py b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py index 2cf33e213..1e5e3bac2 100644 --- a/PySDM/physics/adiabatic_exponent/moist_leading_terms.py +++ b/PySDM/physics/adiabatic_exponent/moist_leading_terms.py @@ -3,11 +3,10 @@ """ -class MoistLeadingTerms: +class MoistLeadingTerms: # pylint: disable=too-few-public-methods def __init__(self, _): pass - # pylint: disable=too-many-arguments @staticmethod def gamma(const, vapour_mixing_ratio): return ( diff --git a/tests/unit_tests/backends/test_seeding_methods.py b/tests/unit_tests/backends/test_seeding_methods.py deleted file mode 100644 index 09a10d450..000000000 --- a/tests/unit_tests/backends/test_seeding_methods.py +++ /dev/null @@ -1,158 +0,0 @@ -"""Seeding backend tests of injection logic""" - -from contextlib import nullcontext - -import numpy as np -import pytest - -from PySDM import Builder -from PySDM.environments import Box -from PySDM.backends import CPU -from PySDM.physics import si - - -class TestSeeding: - max_number_to_inject = 4 - - @staticmethod - @pytest.mark.parametrize( - "n_sd, number_of_super_particles_to_inject, context", - ( - (1, 1, nullcontext()), - ( - 1, - 2, - pytest.raises( - ValueError, match="inject more super particles than space available" - ), - ), - (max_number_to_inject, max_number_to_inject - 1, nullcontext()), - (max_number_to_inject, max_number_to_inject, nullcontext()), - ( - max_number_to_inject + 2, - max_number_to_inject + 1, - pytest.raises( - ValueError, - match="inject multiple super particles with the same attributes", - ), - ), - ), - ) - def test_number_of_super_particles_to_inject( - n_sd, - number_of_super_particles_to_inject, - context, - dt=1, - dv=1, - ): - # arrange - builder = Builder(n_sd, CPU(), Box(dt, dv)) - particulator = builder.build( - attributes={ - "multiplicity": np.full(n_sd, np.nan), - "water mass": np.zeros(n_sd), - }, - ) - - seeded_particle_extensive_attributes = { - "water mass": [0.0001 * si.ng] * TestSeeding.max_number_to_inject, - } - seeded_particle_multiplicity = [1] * TestSeeding.max_number_to_inject - - seeded_particle_index = particulator.Index.identity_index( - len(seeded_particle_multiplicity) - ) - seeded_particle_multiplicity = particulator.IndexedStorage.from_ndarray( - seeded_particle_index, - np.asarray(seeded_particle_multiplicity), - ) - seeded_particle_extensive_attributes = particulator.IndexedStorage.from_ndarray( - seeded_particle_index, - np.asarray(list(seeded_particle_extensive_attributes.values())), - ) - - # act - with context: - particulator.seeding( - seeded_particle_index=seeded_particle_index, - seeded_particle_multiplicity=seeded_particle_multiplicity, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, - ) - - # assert - assert ( - number_of_super_particles_to_inject - == particulator.attributes.super_droplet_count - ) - - @staticmethod - @pytest.mark.parametrize( - "seeded_particle_index, context", - ( - ([0, 0, 0], nullcontext()), - ([0, 1, 2], nullcontext()), - ([2, 1, 0], nullcontext()), - ( - [0], - pytest.raises( - ValueError, - match=" multiple super particles with the same attributes", - ), - ), - ), - ) - def test_seeded_particle_index_multiplicity_extensive_attributes( - seeded_particle_index, - context, - n_sd=3, - number_of_super_particles_to_inject=3, - ): - # arrange - builder = Builder(n_sd, CPU(), Box(dt=np.nan, dv=np.nan)) - particulator = builder.build( - attributes={ - "multiplicity": np.full(n_sd, np.nan), - "water mass": np.zeros(n_sd), - }, - ) - - seeded_particle_extensive_attributes = { - "water mass": [0.0001, 0.0003, 0.0002], - } - seeded_particle_multiplicity = [1, 2, 3] - - seeded_particle_index_impl = particulator.Index.from_ndarray( - np.asarray(seeded_particle_index) - ) - seeded_particle_multiplicity_impl = particulator.IndexedStorage.from_ndarray( - seeded_particle_index_impl, - np.asarray(seeded_particle_multiplicity), - ) - seeded_particle_extensive_attributes_impl = ( - particulator.IndexedStorage.from_ndarray( - seeded_particle_index_impl, - np.asarray(list(seeded_particle_extensive_attributes.values())), - ) - ) - - # act - with context: - particulator.seeding( - seeded_particle_index=seeded_particle_index_impl, - seeded_particle_multiplicity=seeded_particle_multiplicity_impl, - seeded_particle_extensive_attributes=seeded_particle_extensive_attributes_impl, - number_of_super_particles_to_inject=number_of_super_particles_to_inject, - ) - - # assert - np.testing.assert_array_equal( - particulator.attributes["multiplicity"].to_ndarray(), - np.asarray(seeded_particle_multiplicity)[seeded_particle_index], - ) - np.testing.assert_array_equal( - particulator.attributes["water mass"].to_ndarray(), - np.asarray(seeded_particle_extensive_attributes["water mass"])[ - seeded_particle_index - ], - ) diff --git a/tests/unit_tests/backends/test_spawning_methods.py b/tests/unit_tests/backends/test_spawning_methods.py index cdf0acff6..93a97b88f 100644 --- a/tests/unit_tests/backends/test_spawning_methods.py +++ b/tests/unit_tests/backends/test_spawning_methods.py @@ -75,7 +75,7 @@ def test_number_of_super_particles_to_spawn( # act with context: - particulator.spawning( + particulator.spawn( spawned_particle_index=spawned_particle_index, spawned_particle_multiplicity=spawned_particle_multiplicity, spawned_particle_extensive_attributes=spawned_particle_extensive_attributes, @@ -140,7 +140,7 @@ def test_spawned_particle_index_multiplicity_extensive_attributes( # act with context: - particulator.spawning( + particulator.spawn( spawned_particle_index=spawned_particle_index_impl, spawned_particle_multiplicity=spawned_particle_multiplicity_impl, spawned_particle_extensive_attributes=spawned_particle_extensive_attributes_impl, diff --git a/tests/unit_tests/environments/test_expansion_chamber.py b/tests/unit_tests/environments/test_expansion_chamber.py index d5d914194..09832dc83 100644 --- a/tests/unit_tests/environments/test_expansion_chamber.py +++ b/tests/unit_tests/environments/test_expansion_chamber.py @@ -18,7 +18,7 @@ def test_expansion_chamber(backend_instance): delta_pressure=np.nan, delta_time=np.nan, ) - particulator = Builder(n_sd=1, backend=backend_instance, environment=env).build( + _ = Builder(n_sd=1, backend=backend_instance, environment=env).build( attributes={ "multiplicity": np.asarray([1]), "water mass": np.asarray([np.nan]), From fe370f825497617f4dd859efce6be767dd1bf012 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 09:51:22 +0100 Subject: [PATCH 42/56] setup chamber smoke tests execution on CI --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cee90df82..c34321768 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -109,7 +109,7 @@ jobs: matrix: platform: [ubuntu-24.04, macos-13, macos-14, windows-latest] python-version: ["3.9", "3.12"] - test-suite: ["unit_tests/!(dynamics)", "unit_tests/dynamics/!(collisions)", "unit_tests/dynamics/collisions", "smoke_tests/no_env", "smoke_tests/box", "smoke_tests/parcel_a", "smoke_tests/parcel_b", "smoke_tests/parcel_c", "smoke_tests/parcel_d", "smoke_tests/kinematic_1d", "smoke_tests/kinematic_2d", "tutorials_tests"] + test-suite: ["unit_tests/!(dynamics)", "unit_tests/dynamics/!(collisions)", "unit_tests/dynamics/collisions", "smoke_tests/no_env", "smoke_tests/box", "smoke_tests/parcel_a", "smoke_tests/parcel_b", "smoke_tests/parcel_c", "smoke_tests/parcel_d", "smoke_tests/kinematic_1d", "smoke_tests/kinematic_2d", "smoke_tests/chamber", "tutorials_tests"] exclude: - platform: "macos-14" python-version: "3.9" From 2b811bdfc126fbb3f9c2442da85d9aecfb84fa48 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 09:51:38 +0100 Subject: [PATCH 43/56] address pylint hints --- tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py b/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py index 97d1d1615..04e3fa61f 100644 --- a/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py +++ b/tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py @@ -1,9 +1,12 @@ +"""tests supporting the +[Erinin et al. 2025](https://doi.org/10.48550/arXiv.2501.01467) example""" + from pathlib import Path import numpy as np import pytest from open_atmos_jupyter_utils import notebook_vars -from PySDM.physics import si from PySDM_examples import Erinin_et_al_2025 +from PySDM.physics import si PLOT = False From 2bd28ba0bac4127dc27561eb2190f598c8722740 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 09:52:23 +0100 Subject: [PATCH 44/56] fix badge URLs --- .../Erinin_et_al_2025/expansion_experiment.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 49fabb835..b5d411adf 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", - "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)\n", - "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/expansion_chamber/expansion_experiment.ipynb)" + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)" ] }, { From 2896faa2dc02829ef19d4067f4fe354e1b61d3c0 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 09:53:39 +0100 Subject: [PATCH 45/56] add TODO labels (pointing to the PR!_ --- PySDM/dynamics/homogeneous_liquid_nucleation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index 29b77b01f..aa7fc8aca 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -20,13 +20,13 @@ def register(self, builder): def __call__(self): env = { k: self.particulator.environment[k].to_ndarray()[0] for k in ("T", "RH") - } # TODO: >0D + } # TODO #1492: >0D e_s = self.formulae.saturation_vapour_pressure.pvs_water(env["T"]) j = self.formulae.homogeneous_liquid_nucleation_rate.j_liq_homo( env["T"], env["RH"], e_s ) - # TODO: take care of cases where round yields zero -> MC sampling? + # TODO #1492: take care of cases where round yields zero -> MC sampling? new_sd_multiplicity = round( j * self.particulator.environment.mesh.dv * self.particulator.dt ) @@ -42,18 +42,18 @@ def __call__(self): "kappa times dry volume": (0,), } - # TODO: to be done once, not every time we spawn + # TODO #1492: to be done once, not every time we spawn self.check_extensive_attribute_keys( particulator_attributes=self.particulator.attributes, spawned_attributes=new_sd_extensive_attributes, ) - # TODO: allocate once, reuse + # TODO #1492: allocate once, reuse new_sd_extensive_attributes = self.particulator.IndexedStorage.from_ndarray( self.index, np.asarray(list(new_sd_extensive_attributes.values())), ) - # TODO: ditto + # TODO #1492: ditto new_sd_multiplicity = self.particulator.IndexedStorage.from_ndarray( self.index, np.asarray((new_sd_multiplicity,), dtype=np.int64), @@ -65,4 +65,4 @@ def __call__(self): spawned_particle_multiplicity=new_sd_multiplicity, spawned_particle_extensive_attributes=new_sd_extensive_attributes, ) - # TODO: subtract the water mass from ambient vapour + # TODO #1492: subtract the water mass from ambient vapour From dc1217e5078fac6127a0b2b6c9a26c5c85af40d4 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 13:18:48 +0100 Subject: [PATCH 46/56] pylint hints, notebook header --- .../expansion_experiment.ipynb | 6873 ++++++++++++++++- .../Erinin_et_al_2025/expansion_simulation.py | 4 +- .../Erinin_et_al_2025/fig_3.ipynb | 1571 +++- 3 files changed, 8439 insertions(+), 9 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index b5d411adf..26017a8dc 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:31.584604Z", @@ -178,7 +178,6874 @@ }, { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-02-11T16:25:24.446560\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2025-02-11T16:25:24.446560\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ "
" ] @@ -363,7 +7230,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.2" }, "vscode": { "interpreter": { diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index 24b6875f7..daca596fc 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -57,7 +57,7 @@ def run_expansion( attributes = { k: np.empty(0) for k in ("dry volume", "kappa times dry volume", "multiplicity") } - for i, mode in enumerate(aerosol.modes): + for mode in aerosol.modes: kappa, spectrum = mode["kappa"]["Constant"], mode["spectrum"] r_dry, concentration = ConstantMultiplicity(spectrum).sample(n_sd_per_mode) v_dry = builder.formulae.trivia.volume(radius=r_dry) @@ -104,7 +104,7 @@ def run_expansion( for _ in range(n_steps): particulator.run(steps=1) for product in particulator.products.values(): - if product.name == "dry:dN/dR" or product.name == "wet:dN/dR": + if product.name in ("dry:dN/dR", "wet:dN/dR"): continue value = product.get() if product.name == "t": diff --git a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb index 7b8e7a76b..141e48228 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb @@ -1,5 +1,37 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "f523b05e-2bd0-4454-8256-6d7d4e9fbfc8", + "metadata": {}, + "source": [ + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb)" + ] + }, + { + "cell_type": "markdown", + "id": "13f49050-5018-4897-af86-af897858d521", + "metadata": {}, + "source": [ + "TODO #1492" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c84406ae-5606-4ea1-888c-be41826f6a9d", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "if 'google.colab' in sys.modules:\n", + " !pip --quiet install open-atmos-jupyter-utils\n", + " from open_atmos_jupyter_utils import pip_install_on_colab\n", + " pip_install_on_colab('PySDM-examples')" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -9,7 +41,10 @@ "end_time": "2025-01-25T23:31:05.929440Z", "start_time": "2025-01-25T23:31:02.733943Z" }, - "collapsed": true + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } }, "outputs": [], "source": [ @@ -95,7 +130,1535 @@ "outputs": [ { "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2025-01-29T17:07:20.007944\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2025-01-29T17:07:20.007944\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.5.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], "text/plain": [ "
" ] @@ -160,7 +1723,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.10.9 ('pysdm')", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -174,7 +1737,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.9.2" }, "vscode": { "interpreter": { From ab4412d0d86c0e9824a4c81b4140f7ecd9adec12 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 14:55:15 +0100 Subject: [PATCH 47/56] pylint hints --- .../expansion_experiment.ipynb | 8488 +++++++++-------- .../Erinin_et_al_2025/fig_3.ipynb | 737 +- 2 files changed, 4623 insertions(+), 4602 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 26017a8dc..1abe0be8a 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:21:37.280272Z", @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +66,7 @@ "\n", "products = (\n", " PySDM_products.SuperDropletCountPerGridbox(name=\"SD count\"),\n", - " PySDM_products.WaterMixingRatio(unit=\"g/kg\", name=\"$q_\\ell$\"),\n", + " PySDM_products.WaterMixingRatio(unit=\"g/kg\", name=r\"$q_\\ell$\"),\n", " PySDM_products.PeakSupersaturation(name=\"Saturation ratio\"),\n", " PySDM_products.AmbientRelativeHumidity(name=\"RH\"),\n", " PySDM_products.AmbientTemperature(name=\"Temperature\", var=\"T\"),\n", @@ -104,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.715504Z", @@ -161,17 +161,17 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "4.022129924741352\n", - "0.33969348230391677\n", - "0.019729934281225308\n", - "7.873014603149206e-05\n", + "4.021660843931165\n", + "0.33964378383596744\n", + "0.0197293310945584\n", + "7.870157403148062e-05\n", "4.28580000171432e-07\n", "0.0\n" ] @@ -182,16 +182,16 @@ "\n", "\n", - "\n", + "\n", " \n", " \n", " \n", " \n", - " 2025-02-11T16:25:24.446560\n", + " 2025-02-13T14:52:55.108172\n", " image/svg+xml\n", " \n", " \n", - " Matplotlib v3.5.1, https://matplotlib.org/\n", + " Matplotlib v3.8.1, https://matplotlib.org/\n", " \n", " \n", " \n", @@ -202,20 +202,19 @@ " \n", " \n", " \n", - " \n", + "\" style=\"fill: #ffffff\"/>\n", " \n", " \n", " \n", - " \n", " \n", @@ -223,46 +222,46 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1697,14 +1696,14 @@ " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1716,14 +1715,14 @@ " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1735,14 +1734,14 @@ " \n", " \n", " \n", - " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1757,10 +1756,10 @@ " \n", " \n", " \n", - " \n", " \n", @@ -1768,41 +1767,41 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1823,12 +1822,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1838,12 +1837,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1853,12 +1852,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1868,12 +1867,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1883,12 +1882,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1897,7 +1896,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -2479,41 +2478,41 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2534,12 +2533,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2547,12 +2546,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2560,12 +2559,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2573,12 +2572,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2586,12 +2585,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2599,19 +2598,19 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -3206,41 +3205,41 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3261,12 +3260,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3275,12 +3274,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3289,12 +3288,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3303,12 +3302,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3317,12 +3316,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3331,12 +3330,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3344,7 +3343,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -3925,12 +3924,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3938,12 +3937,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3951,12 +3950,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3964,12 +3963,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3977,19 +3976,19 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4010,12 +4009,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4023,12 +4022,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4036,12 +4035,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4049,12 +4048,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4062,12 +4061,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4075,12 +4074,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4088,7 +4087,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4212,530 +4211,530 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -4743,12 +4742,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4756,12 +4755,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4769,12 +4768,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4782,12 +4781,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4795,19 +4794,19 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4828,12 +4827,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4841,12 +4840,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4854,12 +4853,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4867,12 +4866,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4880,12 +4879,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4894,12 +4893,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4907,7 +4906,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4944,530 +4943,530 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -5475,12 +5474,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5488,12 +5487,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5501,12 +5500,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5514,12 +5513,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5527,19 +5526,19 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5560,12 +5559,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5573,12 +5572,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5586,12 +5585,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5600,12 +5599,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5613,7 +5612,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -5707,530 +5706,530 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", @@ -6238,12 +6237,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6251,12 +6250,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6264,12 +6263,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6277,12 +6276,12 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6290,19 +6289,19 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6323,17 +6322,17 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6499,571 +6498,569 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "\n" ], "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "151d019bdf4b487b933773ef34eb4832", + "model_id": "e81d7073148c4aeb87060bdbc12fe891", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HTML(value=\"./C0_sweep_traces.pdf

\")" + "HBox(children=(HTML(value=\"./C0_sweep_traces.pdf
\"), HT…" ] }, "metadata": {}, @@ -7071,7 +7068,7 @@ } ], "source": [ - "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", \"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", + "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", r\"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", "fig, axes = pyplot.subplots(2,4,figsize=(12,5), sharex=True, sharey=False, constrained_layout=True)\n", "\n", "for Na in C0_arr:\n", @@ -7095,14 +7092,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.785100072Z", "start_time": "2025-01-26T23:04:07.407334Z" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 100.0\n" + ] + }, + { + "ename": "AttributeError", + "evalue": "'types.SimpleNamespace' object has no attribute 'j_liq_homo'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[6], line 17\u001b[0m\n\u001b[1;32m 15\u001b[0m const \u001b[38;5;241m=\u001b[39m formulae\u001b[38;5;241m.\u001b[39mconstants\n\u001b[1;32m 16\u001b[0m aerosol \u001b[38;5;241m=\u001b[39m AerosolChamber(water_molar_volume\u001b[38;5;241m=\u001b[39mconst\u001b[38;5;241m.\u001b[39mMv \u001b[38;5;241m/\u001b[39m const\u001b[38;5;241m.\u001b[39mrho_w, N\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2000\u001b[39m \u001b[38;5;241m/\u001b[39m si\u001b[38;5;241m.\u001b[39mcm\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m3\u001b[39m)\n\u001b[0;32m---> 17\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[43mrun_expansion\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maerosol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maerosol\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mRH0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0.5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mp0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mp0\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdpi\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDT\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproducts\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproducts\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 18\u001b[0m Tmin[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmin(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m \u001b[38;5;66;03m# °C\u001b[39;00m\n\u001b[1;32m 19\u001b[0m Smax[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmax(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m \u001b[38;5;66;03m# saturation ratio\u001b[39;00m\n", + "File \u001b[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:105\u001b[0m, in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume, products)\u001b[0m\n\u001b[1;32m 94\u001b[0m output_attributes \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 95\u001b[0m k: []\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 101\u001b[0m )\n\u001b[1;32m 102\u001b[0m }\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n_steps):\n\u001b[0;32m--> 105\u001b[0m \u001b[43mparticulator\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43msteps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m product \u001b[38;5;129;01min\u001b[39;00m particulator\u001b[38;5;241m.\u001b[39mproducts\u001b[38;5;241m.\u001b[39mvalues():\n\u001b[1;32m 107\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdry:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwet:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n", + "File \u001b[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001b[0m, in \u001b[0;36mParticulator.run\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, dynamic \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdynamics\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimers[key]:\n\u001b[0;32m---> 49\u001b[0m \u001b[43mdynamic\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 50\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_steps \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers()\n", + "File \u001b[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:25\u001b[0m, in \u001b[0;36mHomogeneousLiquidNucleation.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 21\u001b[0m env \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 22\u001b[0m k: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment[k]\u001b[38;5;241m.\u001b[39mto_ndarray()[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 23\u001b[0m } \u001b[38;5;66;03m# TODO #1492: >0D\u001b[39;00m\n\u001b[1;32m 24\u001b[0m e_s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mformulae\u001b[38;5;241m.\u001b[39msaturation_vapour_pressure\u001b[38;5;241m.\u001b[39mpvs_water(env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m---> 25\u001b[0m j \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhomogeneous_liquid_nucleation_rate\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mj_liq_homo\u001b[49m(\n\u001b[1;32m 26\u001b[0m env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m], env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m], e_s\n\u001b[1;32m 27\u001b[0m )\n\u001b[1;32m 29\u001b[0m \u001b[38;5;66;03m# TODO #1492: take care of cases where round yields zero -> MC sampling?\u001b[39;00m\n\u001b[1;32m 30\u001b[0m new_sd_multiplicity \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mround\u001b[39m(\n\u001b[1;32m 31\u001b[0m j \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment\u001b[38;5;241m.\u001b[39mmesh\u001b[38;5;241m.\u001b[39mdv \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39mdt\n\u001b[1;32m 32\u001b[0m )\n", + "\u001b[0;31mAttributeError\u001b[0m: 'types.SimpleNamespace' object has no attribute 'j_liq_homo'" + ] + } + ], "source": [ "n_sd_per_mode = 20\n", "\n", @@ -7206,6 +7225,13 @@ "show_plot(\"dp_sweep.pdf\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb index 141e48228..49e552683 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/fig_3.ipynb @@ -34,16 +34,12 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "id": "initial_id", "metadata": { "ExecuteTime": { "end_time": "2025-01-25T23:31:05.929440Z", "start_time": "2025-01-25T23:31:02.733943Z" - }, - "collapsed": true, - "jupyter": { - "outputs_hidden": true } }, "outputs": [], @@ -62,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 6, "id": "7e6e3c6c48db80ee", "metadata": { "ExecuteTime": { @@ -72,7 +68,8 @@ }, "outputs": [], "source": [ - "class Simulation(BasicSimulation):\n", + "class Simulation(BasicSimulation): # pylint: disable=too-few-public-methods\n", + " \"\"\" minimal simulation setup \"\"\"\n", " def __init__(self):\n", " builder = Builder(n_sd=0, backend=CPU(), environment=ExpansionChamber(\n", " dt = .1 * si.s,\n", @@ -103,7 +100,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 7, "id": "d658455c740ae2de", "metadata": { "ExecuteTime": { @@ -119,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 8, "id": "d94f32bcd47f8205", "metadata": { "ExecuteTime": { @@ -134,16 +131,16 @@ "\n", "\n", - "\n", + "\n", " \n", " \n", " \n", " \n", - " 2025-01-29T17:07:20.007944\n", + " 2025-02-13T14:48:32.948908\n", " image/svg+xml\n", " \n", " \n", - " Matplotlib v3.5.1, https://matplotlib.org/\n", + " Matplotlib v3.8.1, https://matplotlib.org/\n", " \n", " \n", " \n", @@ -154,18 +151,17 @@ " \n", " \n", " \n", - " \n", + "\" style=\"fill: #ffffff\"/>\n", " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + "\" clip-path=\"url(#pe55993be79)\" style=\"fill: none; stroke: #b0b0b0; stroke-width: 0.8; stroke-linecap: square\"/>\n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -253,23 +249,23 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", @@ -786,83 +782,83 @@ " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -870,36 +866,36 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -908,18 +904,18 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -929,18 +925,18 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -950,18 +946,18 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1465,36 +1461,36 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1502,7 +1498,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", "\n" ], "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b256bffaf9a54c32b90b3259cfc86c27", + "model_id": "f7bc96feb07a4b7a9a6738491c8d97c6", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HTML(value=\"./fig_3

\")" + "HBox(children=(HTML(value=\"./fig_3.pdf
\"), HTML(value=\" Date: Thu, 13 Feb 2025 15:38:08 +0100 Subject: [PATCH 48/56] missing bib entry --- docs/bibliography.json | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/bibliography.json b/docs/bibliography.json index f442ce3a5..2bb2a77ab 100644 --- a/docs/bibliography.json +++ b/docs/bibliography.json @@ -710,6 +710,7 @@ "usages": [ "examples/PySDM_examples/Erinin_et_al_2025/__init__.py", "examples/PySDM_examples/Erinin_et_al_2025/aerosol.py", + "tests/smoke_tests/chamber/erinin_et_al_2025/test_fig_3.py", "examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb"], "title": "Droplet Nucleation In a Rapid Expansion Aerosol Chamber", "label": "Erinin et al. 2024 (arXiv:2501.01467)" From 897fb3ebdae895a323331f5d72b2e431fa1849d9 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 21:13:17 +0100 Subject: [PATCH 49/56] simplify notebook code; skip nucleation if RH<1 --- .../dynamics/homogeneous_liquid_nucleation.py | 4 + .../expansion_experiment.ipynb | 3849 +++++++++++++++-- 2 files changed, 3587 insertions(+), 266 deletions(-) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index aa7fc8aca..b1e3a531b 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -21,6 +21,10 @@ def __call__(self): env = { k: self.particulator.environment[k].to_ndarray()[0] for k in ("T", "RH") } # TODO #1492: >0D + + if env["RH"] < 1: + return + e_s = self.formulae.saturation_vapour_pressure.pvs_water(env["T"]) j = self.formulae.homogeneous_liquid_nucleation_rate.j_liq_homo( env["T"], env["RH"], e_s diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index 1abe0be8a..b5377e917 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -105,6 +105,25 @@ { "cell_type": "code", "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "FORMULAE = Formulae(\n", + " adiabatic_exponent=\"MoistLeadingTerms\",\n", + " homogeneous_liquid_nucleation_rate='CNT',\n", + ")\n", + "CONST = FORMULAE.constants\n", + "\n", + "N_SD_PER_MODE = 20\n", + "DT = .05 * si.s\n", + "\n", + "C0_arr = np.array([1e2, 2.5e2, 5e2, 7.5e2, 1e3]) / si.cm**3\n", + "C0_arr = np.array([4e2, 4.25e2, 4.5e2, 5e2, 5.5e2, 6e2]) / si.cm**3" + ] + }, + { + "cell_type": "code", + "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.715504Z", @@ -126,30 +145,19 @@ } ], "source": [ - "n_sd_per_mode = 20\n", - "DT = .05 * si.s\n", - "\n", - "C0_arr = np.array([1e2, 2.5e2, 5e2, 7.5e2, 1e3]) / si.cm**3\n", - "C0_arr = np.array([4e2, 4.25e2, 4.5e2, 5e2, 5.5e2, 6e2]) / si.cm**3\n", - "\n", "output_all = {}\n", "\n", "for Na in C0_arr:\n", " key = f\"C0={Na:.2e}\"\n", " print(key)\n", - " formulae = Formulae(\n", - " adiabatic_exponent=\"MoistLeadingTerms\",\n", - " homogeneous_liquid_nucleation_rate='CNT',\n", - " )\n", - " const = formulae.constants\n", " aerosol = AerosolChamber(\n", - " water_molar_volume=const.Mv / const.rho_w,\n", + " water_molar_volume=CONST.Mv / CONST.rho_w,\n", " N=Na,\n", " )\n", " output = run_expansion(\n", - " formulae=formulae,\n", + " formulae=FORMULAE,\n", " aerosol=aerosol,\n", - " n_sd_per_mode=n_sd_per_mode,\n", + " n_sd_per_mode=N_SD_PER_MODE,\n", " n_sd_homo_liq_nucleation=100,\n", " total_time=4*si.s,\n", " dt=DT,\n", @@ -161,7 +169,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -187,7 +195,7 @@ " \n", " \n", " \n", - " 2025-02-13T14:52:55.108172\n", + " 2025-02-13T20:58:52.082465\n", " image/svg+xml\n", " \n", " \n", @@ -222,40 +230,40 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -504,12 +512,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -577,7 +585,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -604,7 +612,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -660,7 +668,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -707,7 +715,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1013,7 +1021,7 @@ "L 208.293598 145.570424 \n", "L 210.207933 145.558885 \n", "L 212.122269 145.548493 \n", - "\" clip-path=\"url(#pbf3feff532)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pb18877d22d)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1822,7 +1830,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1837,7 +1845,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1852,7 +1860,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1867,7 +1875,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -1882,7 +1890,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2027,7 +2035,7 @@ "L 420.415473 121.886239 \n", "L 422.329808 121.824012 \n", "L 424.244144 121.767969 \n", - "\" clip-path=\"url(#paad5f0dc58)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pfdfa06052a)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2533,7 +2541,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2546,7 +2554,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2559,7 +2567,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2572,7 +2580,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2585,7 +2593,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2598,7 +2606,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -2759,7 +2767,7 @@ "L 626.174848 143.660262 \n", "L 628.089183 143.801817 \n", "L 630.003519 143.928935 \n", - "\" clip-path=\"url(#p38dcc9ac8c)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p5bf1f63db0)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3260,7 +3268,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3274,7 +3282,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3288,7 +3296,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3302,7 +3310,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3316,7 +3324,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3330,7 +3338,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3473,7 +3481,7 @@ "L 853.809223 14.797631 \n", "L 855.723558 14.797631 \n", "L 857.637894 14.797631 \n", - "\" clip-path=\"url(#p895b5751a5)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p1a131e9861)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3937,7 +3945,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3950,7 +3958,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3963,7 +3971,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -3976,7 +3984,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4009,7 +4017,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4022,7 +4030,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4035,7 +4043,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4048,7 +4056,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4061,7 +4069,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4074,7 +4082,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4291,7 +4299,7 @@ "L 208.293598 194.085176 \n", "L 210.207933 193.989257 \n", "L 212.122269 193.90287 \n", - "\" clip-path=\"url(#p0886f8ead2)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pd61f3cf11d)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4755,7 +4763,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4768,7 +4776,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4781,7 +4789,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4794,7 +4802,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4827,7 +4835,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4840,7 +4848,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4853,7 +4861,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4866,7 +4874,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4879,7 +4887,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -4893,7 +4901,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5023,7 +5031,7 @@ "L 420.415473 319.591925 \n", "L 422.329808 319.69714 \n", "L 424.244144 319.791902 \n", - "\" clip-path=\"url(#p0cce66529b)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p7325f63952)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5487,7 +5495,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5500,7 +5508,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5513,7 +5521,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5526,7 +5534,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5559,7 +5567,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5572,7 +5580,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5585,7 +5593,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5599,7 +5607,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -5786,7 +5794,7 @@ "L 626.174848 187.880012 \n", "L 628.089183 187.845858 \n", "L 630.003519 187.815113 \n", - "\" clip-path=\"url(#pc09be028a1)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#pccea6099bb)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6250,7 +6258,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6263,7 +6271,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6276,7 +6284,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6289,7 +6297,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6322,12 +6330,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6361,7 +6369,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6378,14 +6386,14 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6402,14 +6410,14 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -6578,7 +6586,7 @@ "L 853.809223 43.44031 \n", "L 855.723558 43.44031 \n", "L 857.637894 43.44031 \n", - "\" clip-path=\"url(#p1262034f74)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #1f77b4; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #ff7f0e; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #2ca02c; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #d62728; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #9467bd; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p9064ef2725)\" style=\"fill: none; stroke: #8c564b; stroke-width: 1.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7055,7 +7063,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e81d7073148c4aeb87060bdbc12fe891", + "model_id": "d5c1bb95a07e4ff7b732ae5711345dbf", "version_major": 2, "version_minor": 0 }, @@ -7092,7 +7100,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 12, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:23:04.785100072Z", @@ -7104,82 +7112,61 @@ "name": "stdout", "output_type": "stream", "text": [ - "0 100.0\n" - ] - }, - { - "ename": "AttributeError", - "evalue": "'types.SimpleNamespace' object has no attribute 'j_liq_homo'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[6], line 17\u001b[0m\n\u001b[1;32m 15\u001b[0m const \u001b[38;5;241m=\u001b[39m formulae\u001b[38;5;241m.\u001b[39mconstants\n\u001b[1;32m 16\u001b[0m aerosol \u001b[38;5;241m=\u001b[39m AerosolChamber(water_molar_volume\u001b[38;5;241m=\u001b[39mconst\u001b[38;5;241m.\u001b[39mMv \u001b[38;5;241m/\u001b[39m const\u001b[38;5;241m.\u001b[39mrho_w, N\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m2000\u001b[39m \u001b[38;5;241m/\u001b[39m si\u001b[38;5;241m.\u001b[39mcm\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m3\u001b[39m)\n\u001b[0;32m---> 17\u001b[0m output \u001b[38;5;241m=\u001b[39m \u001b[43mrun_expansion\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43maerosol\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43maerosol\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mn_sd_per_mode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mRH0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m0.5\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mp0\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mp0\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpf\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mp0\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mdpi\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDT\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproducts\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproducts\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 18\u001b[0m Tmin[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmin(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m273.15\u001b[39m \u001b[38;5;66;03m# °C\u001b[39;00m\n\u001b[1;32m 19\u001b[0m Smax[i] \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mnanmax(output\u001b[38;5;241m.\u001b[39mprofile[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ms\u001b[39m\u001b[38;5;124m\"\u001b[39m]) \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m1\u001b[39m \u001b[38;5;66;03m# saturation ratio\u001b[39;00m\n", - "File \u001b[0;32m~/devel/PySDM/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py:105\u001b[0m, in \u001b[0;36mrun_expansion\u001b[0;34m(formulae, aerosol, n_sd_per_mode, n_sd_homo_liq_nucleation, RH0, T0, p0, pf, delta_time, total_time, dt, volume, products)\u001b[0m\n\u001b[1;32m 94\u001b[0m output_attributes \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 95\u001b[0m k: []\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 101\u001b[0m )\n\u001b[1;32m 102\u001b[0m }\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(n_steps):\n\u001b[0;32m--> 105\u001b[0m \u001b[43mparticulator\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43msteps\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m product \u001b[38;5;129;01min\u001b[39;00m particulator\u001b[38;5;241m.\u001b[39mproducts\u001b[38;5;241m.\u001b[39mvalues():\n\u001b[1;32m 107\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m product\u001b[38;5;241m.\u001b[39mname \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdry:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwet:dN/dR\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n", - "File \u001b[0;32m~/devel/PySDM/PySDM/particulator.py:49\u001b[0m, in \u001b[0;36mParticulator.run\u001b[0;34m(self, steps)\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key, dynamic \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdynamics\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 48\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtimers[key]:\n\u001b[0;32m---> 49\u001b[0m \u001b[43mdynamic\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 50\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mn_steps \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_notify_observers()\n", - "File \u001b[0;32m~/devel/PySDM/PySDM/dynamics/homogeneous_liquid_nucleation.py:25\u001b[0m, in \u001b[0;36mHomogeneousLiquidNucleation.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 21\u001b[0m env \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 22\u001b[0m k: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment[k]\u001b[38;5;241m.\u001b[39mto_ndarray()[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m (\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 23\u001b[0m } \u001b[38;5;66;03m# TODO #1492: >0D\u001b[39;00m\n\u001b[1;32m 24\u001b[0m e_s \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mformulae\u001b[38;5;241m.\u001b[39msaturation_vapour_pressure\u001b[38;5;241m.\u001b[39mpvs_water(env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[0;32m---> 25\u001b[0m j \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mformulae\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhomogeneous_liquid_nucleation_rate\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mj_liq_homo\u001b[49m(\n\u001b[1;32m 26\u001b[0m env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mT\u001b[39m\u001b[38;5;124m\"\u001b[39m], env[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mRH\u001b[39m\u001b[38;5;124m\"\u001b[39m], e_s\n\u001b[1;32m 27\u001b[0m )\n\u001b[1;32m 29\u001b[0m \u001b[38;5;66;03m# TODO #1492: take care of cases where round yields zero -> MC sampling?\u001b[39;00m\n\u001b[1;32m 30\u001b[0m new_sd_multiplicity \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mround\u001b[39m(\n\u001b[1;32m 31\u001b[0m j \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39menvironment\u001b[38;5;241m.\u001b[39mmesh\u001b[38;5;241m.\u001b[39mdv \u001b[38;5;241m*\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mparticulator\u001b[38;5;241m.\u001b[39mdt\n\u001b[1;32m 32\u001b[0m )\n", - "\u001b[0;31mAttributeError\u001b[0m: 'types.SimpleNamespace' object has no attribute 'j_liq_homo'" + "dpi=100.0 case='base'\n", + "dpi=100.0 case='clean'\n", + "dpi=100.0 case='dry'\n", + "dpi=10000.0 case='base'\n", + "dpi=10000.0 case='clean'\n", + "dpi=10000.0 case='dry'\n", + "dpi=20000.0 case='base'\n", + "dpi=20000.0 case='clean'\n", + "dpi=20000.0 case='dry'\n", + "dpi=30000.0 case='base'\n", + "dpi=30000.0 case='clean'\n", + "dpi=30000.0 case='dry'\n", + "dpi=40000.0 case='base'\n", + "dpi=40000.0 case='clean'\n", + "dpi=40000.0 case='dry'\n", + "dpi=50000.0 case='base'\n", + "dpi=50000.0 case='clean'\n", + "dpi=50000.0 case='dry'\n" ] } ], "source": [ - "n_sd_per_mode = 20\n", - "\n", - "p0 = 1000 * si.hPa\n", - "dp = np.insert(np.linspace(100,600,11),0,1) * si.hPa\n", - "Tmin = np.zeros_like(dp)\n", - "Smax = np.zeros_like(dp)\n", - "Tmin_clean = np.zeros_like(dp)\n", - "Smax_clean = np.zeros_like(dp)\n", - "Tmin_dry = np.zeros_like(dp)\n", - "Smax_dry = np.zeros_like(dp)\n", - "for i,dpi in enumerate(dp):\n", - " print(i,dpi)\n", - "\n", - " formulae = Formulae()\n", - " const = formulae.constants\n", - " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=2000 / si.cm**3)\n", - " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", - " Tmin[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", - "\n", - " aerosol = AerosolChamber(water_molar_volume=const.Mv / const.rho_w, N=1 / si.cm**3)\n", - " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0.5, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", - " Tmin_clean[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax_clean[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", + "DP = np.insert(np.linspace(100, 500, 5), 0, 1) * si.hPa\n", + "P0 = 1000 * si.hPa\n", "\n", - " output = run_expansion(formulae=formulae, aerosol=aerosol, n_sd_per_mode=n_sd_per_mode, RH0=0, p0=p0, pf=(p0 - dpi), dt=DT, products=products)\n", - " Tmin_dry[i] = np.nanmin(output.profile[\"T\"]) - 273.15 # °C\n", - " Smax_dry[i] = np.nanmax(output.profile[\"s\"]) + 1 # saturation ratio\n", - "\n", - "print(dp)\n", - "print(Tmin)\n", - "print(Tmin_clean)\n", - "print(Tmin_dry)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2025-01-30T20:18:02.529987551Z", - "start_time": "2025-01-26T23:10:25.865329Z" - } - }, - "outputs": [], - "source": [ - "print(\"p0 =\",p0,\"Pa\")\n", - "print(\"T0 =\",296-273.15,\"°C\")\n", - "print(\"dp =\",dp)\n", - "print(\"Tmin (S0=0.5, C0=2000) =\", Tmin)\n", - "print(\"Tmin (S0=0.5, C0=1) =\", Tmin_clean)\n", - "print(\"Tmin (S0=0, C0=1) =\", Tmin_dry)" + "cases = {\n", + " 'base': {'N': 2000 / si.cm**3, 'RH0': 0.5, 'color': 'green'},\n", + " 'clean': {'N': 1 / si.cm**3, 'RH0': 0.5, 'color': 'turquoise'},\n", + " 'dry': {'N': 1 / si.cm**3, 'RH0': 0, 'color': 'black'},\n", + "}\n", + "output = {\n", + " 'Smax': {case: [] for case in cases},\n", + " 'Tmin': {case: [] for case in cases},\n", + "}\n", + "for dpi in DP:\n", + " for case, case_params in cases.items():\n", + " print(f\"{dpi=} {case=}\")\n", + " aerosol = AerosolChamber(water_molar_volume=CONST.Mv / CONST.rho_w, N=case_params['N'])\n", + " out = run_expansion(\n", + " formulae=FORMULAE,\n", + " aerosol=aerosol,\n", + " n_sd_per_mode=N_SD_PER_MODE,\n", + " RH0=case_params['RH0'],\n", + " pf=(P0 - dpi),\n", + " dt=DT,\n", + " p0=P0,\n", + " products=products\n", + " )\n", + " output['Tmin'][case].append(np.nanmin(out.profile[\"Temperature\"]))\n", + " output['Smax'][case].append(np.nanmax(out.profile[\"Saturation ratio\"]))" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:18:02.702242840Z", @@ -7188,49 +7175,3379 @@ }, "outputs": [], "source": [ - "fig,ax = pyplot.subplots(1,1,figsize=(5,4))\n", - "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", - "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", - "ax.legend(loc=3, frameon=False)\n", - "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", - "show_plot(\"Tmin_dp.pdf\")\n", - "\n", - "#########\n", - "\n", - "fig,axes = pyplot.subplots(2,1,figsize=(6,6),sharex=True)\n", - "\n", - "ax = axes[0]\n", - "ax.plot(dp/p0, Tmin_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Tmin, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_ylabel(r\"$T_{min}$ [°C]\")\n", - "ax.legend(loc=3, frameon=False)\n", - "ax.set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", - "\n", - "ax = axes[1]\n", - "ax.plot(dp/p0, Smax_dry, color=\"black\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Smax_clean, color=\"turquoise\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 1 $ cm$^{-3}$\")\n", - "ax.plot(dp/p0, Smax, color=\"green\", marker=\"o\", ls=\"--\", label=\"$S_0 = 0.5, C_0 = 2000$ cm$^{-3}$\")\n", - "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", - "ax.set_ylabel(r\"$S_{max}$\")\n", - "# ax.set_yscale(\"log\")\n", - "ax.set_ylim(-0.5,6)\n", - "ax.axhline(0, color=\"k\", lw=0.5)\n", - "ax.axhline(1, color=\"k\", lw=0.5)\n", - "ax.axhline(4, color=\"k\", lw=0.5)\n", - "\n", - "show_plot(\"dp_sweep.pdf\")" + "def plot(ax, cases, var):\n", + " for case, case_params in cases.items():\n", + " ax.plot(\n", + " DP/P0,\n", + " output[var][case],\n", + " color=case_params['color'],\n", + " marker=\"o\",\n", + " ls=\"--\",\n", + " label=f\"$S_0={case_params['RH0']}, C_0={in_unit(case_params['N'], si.cm**-3)}$ cm$^{{-3}}$\"\n", + " )" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2025-02-13T21:10:44.739772\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a4eebba9f6b549b7a78c37204f752570", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(HTML(value=\"./Tmin_dp.pdf
\"), HTML(value=\"\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2025-02-13T21:12:24.445585\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.1, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8e1ac3ba29dc45d987fdfcbda24cc496", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(HTML(value=\"./dp_sweep.pdf
\"), HTML(value=\" Date: Thu, 13 Feb 2025 21:24:12 +0100 Subject: [PATCH 50/56] address pylint hints --- .../expansion_experiment.ipynb | 290 +++++++++--------- 1 file changed, 145 insertions(+), 145 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index b5377e917..c18358a5a 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -7166,7 +7166,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 31, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:18:02.702242840Z", @@ -7175,21 +7175,21 @@ }, "outputs": [], "source": [ - "def plot(ax, cases, var):\n", - " for case, case_params in cases.items():\n", - " ax.plot(\n", + "def plot(axes, output, cases, var):\n", + " for _case, _case_params in cases.items():\n", + " axes.plot(\n", " DP/P0,\n", - " output[var][case],\n", - " color=case_params['color'],\n", + " output[var][_case],\n", + " color=_case_params['color'],\n", " marker=\"o\",\n", " ls=\"--\",\n", - " label=f\"$S_0={case_params['RH0']}, C_0={in_unit(case_params['N'], si.cm**-3)}$ cm$^{{-3}}$\"\n", + " label=f\"$S_0={_case_params['RH0']}, C_0={in_unit(_case_params['N'], si.cm**-3)}$ cm$^{{-3}}$\"\n", " )" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 32, "metadata": {}, "outputs": [ { @@ -7203,7 +7203,7 @@ " \n", " \n", " \n", - " 2025-02-13T21:10:44.739772\n", + " 2025-02-13T21:23:59.738907\n", " image/svg+xml\n", " \n", " \n", @@ -7238,12 +7238,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7288,7 +7288,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7319,7 +7319,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7360,7 +7360,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7409,7 +7409,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7445,7 +7445,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7565,12 +7565,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7585,7 +7585,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7632,7 +7632,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7659,7 +7659,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7715,7 +7715,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7889,9 +7889,9 @@ "L 211.625946 131.083372 \n", "L 262.454876 166.729437 \n", "L 313.283807 210.050582 \n", - "\" clip-path=\"url(#p1e2b685168)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -7919,9 +7919,9 @@ "L 211.625946 140.72807 \n", "L 262.454876 184.374277 \n", "L 313.283807 233.590456 \n", - "\" clip-path=\"url(#p1e2b685168)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -7949,9 +7949,9 @@ "L 211.625946 140.943321 \n", "L 262.454876 184.681843 \n", "L 313.283807 233.998125 \n", - "\" clip-path=\"url(#p1e2b685168)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -8508,7 +8508,7 @@ "L 75.965625 197.698437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8621,7 +8621,7 @@ "L 75.965625 213.598437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8653,7 +8653,7 @@ "L 75.965625 229.498437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8681,7 +8681,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8697,7 +8697,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a4eebba9f6b549b7a78c37204f752570", + "model_id": "e6462c3642a34f89a557df5b5be5048e", "version_major": 2, "version_minor": 0 }, @@ -8711,7 +8711,7 @@ ], "source": [ "fig, ax = pyplot.subplots(1, 1, figsize=(5,4))\n", - "plot(ax, cases, var='Tmin')\n", + "plot(ax, output, cases, var='Tmin')\n", "ax.set_xlabel(r\"$\\Delta p / p_i$\")\n", "ax.set_ylabel(r\"$T_{min}$ [K]\")\n", "ax.legend(loc=3, frameon=False)\n", @@ -8721,7 +8721,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -8735,7 +8735,7 @@ " \n", " \n", " \n", - " 2025-02-13T21:12:24.445585\n", + " 2025-02-13T21:24:00.638971\n", " image/svg+xml\n", " \n", " \n", @@ -8770,47 +8770,47 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8819,12 +8819,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8911,7 +8911,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8958,7 +8958,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8985,7 +8985,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -9041,7 +9041,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -9228,9 +9228,9 @@ "L 244.55801 96.476248 \n", "L 305.552726 120.780383 \n", "L 366.547443 150.317527 \n", - "\" clip-path=\"url(#p0318fb9871)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#pd97f14c2c6)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -9258,9 +9258,9 @@ "L 244.55801 103.052179 \n", "L 305.552726 132.810956 \n", "L 366.547443 166.367442 \n", - "\" clip-path=\"url(#p0318fb9871)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#pd97f14c2c6)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -9288,9 +9288,9 @@ "L 244.55801 103.19894 \n", "L 305.552726 133.02066 \n", "L 366.547443 166.645398 \n", - "\" clip-path=\"url(#p0318fb9871)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#pd97f14c2c6)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -9847,7 +9847,7 @@ "L 75.965625 127.138437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -9999,7 +9999,7 @@ "L 75.965625 143.038437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10047,7 +10047,7 @@ "L 75.965625 158.938437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10086,7 +10086,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10101,7 +10101,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10116,7 +10116,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10131,7 +10131,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10146,7 +10146,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10182,7 +10182,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10262,7 +10262,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10275,7 +10275,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10288,7 +10288,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10301,7 +10301,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10314,7 +10314,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10327,7 +10327,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10340,7 +10340,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10421,14 +10421,14 @@ "L 244.55801 329.074895 \n", "L 305.552726 323.152185 \n", "L 366.547443 315.380128 \n", - "\" clip-path=\"url(#p691227e657)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -10438,14 +10438,14 @@ "L 244.55801 310.140873 \n", "L 305.552726 245.704955 \n", "L 366.547443 49.392669 \n", - "\" clip-path=\"url(#p691227e657)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -10455,30 +10455,30 @@ "L 244.55801 366.588894 \n", "L 305.552726 366.588894 \n", "L 366.547443 366.588893 \n", - "\" clip-path=\"url(#p691227e657)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke: #000000; stroke-width: 0.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke: #000000; stroke-width: 0.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", + "\" clip-path=\"url(#p493fb12e55)\" style=\"fill: none; stroke: #000000; stroke-width: 0.5; stroke-linecap: square\"/>\n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -10522,7 +10522,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8e1ac3ba29dc45d987fdfcbda24cc496", + "model_id": "4970459fb58448c9bdd12c1471dea3d0", "version_major": 2, "version_minor": 0 }, @@ -10536,11 +10536,11 @@ ], "source": [ "fig, axs = pyplot.subplots(2,1,figsize=(6,6),sharex=True)\n", - "plot(axs[0], cases, var='Tmin')\n", + "plot(axs[0], output, cases, var='Tmin')\n", "axs[0].set_ylabel(r\"$T_{min}$ [K]\")\n", "axs[0].legend(loc=3, frameon=False)\n", "axs[0].set_title(\"PySDM parcel simulation, no homogeneous nucleation\")\n", - "plot(axs[1], cases, var='Smax')\n", + "plot(axs[1], output, cases, var='Smax')\n", "axs[1].set_xlabel(r\"$\\Delta p / p_i$\")\n", "axs[1].set_ylabel(r\"$S_{max}$\")\n", "axs[1].set_ylim(-0.5, 6)\n", From 7d180ad02c3767e9e04f70b6bd4bff5185ec113a Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 22:46:25 +0100 Subject: [PATCH 51/56] address pylint hints again --- .../expansion_experiment.ipynb | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb index c18358a5a..d4b936771 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb @@ -7166,7 +7166,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 34, "metadata": { "ExecuteTime": { "end_time": "2025-01-30T20:18:02.702242840Z", @@ -7175,11 +7175,11 @@ }, "outputs": [], "source": [ - "def plot(axes, output, cases, var):\n", - " for _case, _case_params in cases.items():\n", - " axes.plot(\n", - " DP/P0,\n", - " output[var][_case],\n", + "def plot(_axes, _output, _cases, var):\n", + " for _case, _case_params in _cases.items():\n", + " _axes.plot(\n", + " DP / P0,\n", + " _output[var][_case],\n", " color=_case_params['color'],\n", " marker=\"o\",\n", " ls=\"--\",\n", @@ -7189,7 +7189,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 35, "metadata": {}, "outputs": [ { @@ -7203,7 +7203,7 @@ " \n", " \n", " \n", - " 2025-02-13T21:23:59.738907\n", + " 2025-02-13T22:46:14.753708\n", " image/svg+xml\n", " \n", " \n", @@ -7238,12 +7238,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7288,7 +7288,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7319,7 +7319,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7360,7 +7360,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7409,7 +7409,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7445,7 +7445,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7565,12 +7565,12 @@ " \n", " \n", " \n", - " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7585,7 +7585,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7632,7 +7632,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7659,7 +7659,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7715,7 +7715,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -7889,9 +7889,9 @@ "L 211.625946 131.083372 \n", "L 262.454876 166.729437 \n", "L 313.283807 210.050582 \n", - "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p31a46f699b)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -7919,9 +7919,9 @@ "L 211.625946 140.72807 \n", "L 262.454876 184.374277 \n", "L 313.283807 233.590456 \n", - "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p31a46f699b)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -7949,9 +7949,9 @@ "L 211.625946 140.943321 \n", "L 262.454876 184.681843 \n", "L 313.283807 233.998125 \n", - "\" clip-path=\"url(#p97c9697e93)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", + "\" clip-path=\"url(#p31a46f699b)\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", @@ -8508,7 +8508,7 @@ "L 75.965625 197.698437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #008000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8621,7 +8621,7 @@ "L 75.965625 213.598437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #40e0d0; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8653,7 +8653,7 @@ "L 75.965625 229.498437 \n", "\" style=\"fill: none; stroke-dasharray: 5.55,2.4; stroke-dashoffset: 0; stroke: #000000; stroke-width: 1.5\"/>\n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8681,7 +8681,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -8697,7 +8697,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e6462c3642a34f89a557df5b5be5048e", + "model_id": "ee6aed70075c4f35ae142be20468587b", "version_major": 2, "version_minor": 0 }, From 649caba0e08f1a332e5326f47c22f764d2bdb15d Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 13 Feb 2025 23:14:22 +0100 Subject: [PATCH 52/56] fix MockParticulator --- tests/unit_tests/dynamics/test_seeding.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit_tests/dynamics/test_seeding.py b/tests/unit_tests/dynamics/test_seeding.py index 66f4ee2ff..8dd8db343 100644 --- a/tests/unit_tests/dynamics/test_seeding.py +++ b/tests/unit_tests/dynamics/test_seeding.py @@ -200,16 +200,16 @@ def __init__(self): self.seeding_call_count = 0 self.indices = [] - def seeding( + def spawn( self, *, - seeded_particle_index, - number_of_super_particles_to_inject, # pylint: disable=unused-argument - seeded_particle_multiplicity, # pylint: disable=unused-argument - seeded_particle_extensive_attributes, # pylint: disable=unused-argument + spawned_particle_index, + number_of_super_particles_to_spawn, # pylint: disable=unused-argument + spawned_particle_multiplicity, # pylint: disable=unused-argument + spawned_particle_extensive_attributes, # pylint: disable=unused-argument ): self.seeding_call_count += 1 - self.indices.append(seeded_particle_index.to_ndarray()) + self.indices.append(spawned_particle_index.to_ndarray()) Index = make_Index(backend) IndexedStorage = make_IndexedStorage(backend) From 89d1086c1da48403898d803cb8c0f8267ebbcd52 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 14 Feb 2025 10:26:08 +0100 Subject: [PATCH 53/56] extensions in homogeneous liquid nucleation unit tests --- PySDM/physics/constants_defaults.py | 6 + PySDM/physics/impl/fake_unit_registry.py | 2 + .../test_homogeneous_liquid_nucleation.py | 128 +++++++++++++----- 3 files changed, 103 insertions(+), 33 deletions(-) diff --git a/PySDM/physics/constants_defaults.py b/PySDM/physics/constants_defaults.py index 924e0898a..c358e6d4f 100644 --- a/PySDM/physics/constants_defaults.py +++ b/PySDM/physics/constants_defaults.py @@ -299,6 +299,12 @@ J_HET = np.nan """ constant ice nucleation rate """ +J_LIQ_HOMO = np.nan +""" constant liquid homogeneous-nucleation rate """ + +R_LIQ_HOMO = np.nan +""" constant particle size for liquid homogeneous nucleation """ + STRAUB_E_D1 = 0.04 * si.cm """ [Straub et al. 2010](https://doi.org/10.1175/2009JAS3175.1) """ STRAUB_MU2 = 0.095 * si.cm diff --git a/PySDM/physics/impl/fake_unit_registry.py b/PySDM/physics/impl/fake_unit_registry.py index c68cf0648..263a39814 100644 --- a/PySDM/physics/impl/fake_unit_registry.py +++ b/PySDM/physics/impl/fake_unit_registry.py @@ -28,6 +28,7 @@ def __init__(self, si): "hour", "newton", "watt", + "dyne", ): self.__setattr__(prefix + unit, _fake(si.__getattr__(prefix + unit))) self.__setattr__( @@ -52,5 +53,6 @@ def __init__(self, si): "bar", # note: "b" is barn !!! "N", "W", + "dyn", ): self.__setattr__(prefix + unit, _fake(si.__getattr__(prefix + unit))) diff --git a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py index de1a687cc..8739b3b1f 100644 --- a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py +++ b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py @@ -1,54 +1,116 @@ -"""tests checking homogeneous liquid nucleation formulae""" - +# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring import pytest import numpy as np from PySDM import Formulae -from PySDM.physics import si +from PySDM.physics import si, constants_defaults +from PySDM.physics.dimensional_analysis import DimensionalAnalysis -class TestSeinfeldPandis: +class TestHomogeneousLiquidNucleation: @staticmethod @pytest.mark.parametrize( - "T, S, table_r_star", + "temperature, saturation_ratio, sgm_w, table_r_star", ( - (273, 2, 17.3e-10), - (273, 3, 10.9e-10), - (273, 4, 8.7e-10), - (273, 5, 7.5e-10), - (298, 2, 15.1e-10), - (298, 3, 9.5e-10), - (298, 4, 7.6e-10), - (298, 5, 6.5e-10), + (273 * si.K, 2, 75.6 * si.dyn / si.cm, 17.3e-10 * si.m), + (273 * si.K, 3, 75.6 * si.dyn / si.cm, 10.9e-10 * si.m), + (273 * si.K, 4, 75.6 * si.dyn / si.cm, 8.70e-10 * si.m), + (273 * si.K, 5, 75.6 * si.dyn / si.cm, 7.50e-10 * si.m), + (298 * si.K, 2, 72.0 * si.dyn / si.cm, 15.1e-10 * si.m), + (298 * si.K, 3, 72.0 * si.dyn / si.cm, 9.50e-10 * si.m), + (298 * si.K, 4, 72.0 * si.dyn / si.cm, 7.60e-10 * si.m), + (298 * si.K, 5, 72.0 * si.dyn / si.cm, 6.50e-10 * si.m), ), ) - def test_seinfeld_pandis_table_11p1(T, S, table_r_star): - formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") - r_star = formulae.homogeneous_liquid_nucleation_rate.r_liq_homo(T, S) + def test_seinfeld_pandis_table_11p1( + temperature, saturation_ratio, sgm_w, table_r_star + ): + # arrange + formulae = Formulae( + homogeneous_liquid_nucleation_rate="CNT", constants={"sgm_w": sgm_w} + ) + + # act + r_star = formulae.homogeneous_liquid_nucleation_rate.r_liq_homo( + temperature, saturation_ratio + ) + + # assert np.testing.assert_approx_equal( - actual=r_star, desired=table_r_star * si.m, significant=1 + actual=r_star, desired=table_r_star, significant=2 ) @staticmethod @pytest.mark.parametrize( - "T, S, table_J", + "saturation_ratio, desired_j", ( - (293, 2, 5.02e-54), - (293, 3, 1.76e-6), - (293, 4, 1.05e6), - (293, 5, 1.57e11), - (293, 6, 1.24e14), - (293, 7, 8.99e15), - (293, 8, 1.79e17), - (293, 9, 1.65e18), - (293, 10, 9.17e18), + (+2, 5.02e-54 / si.cm**3 / si.s), + (+3, 1.76e-06 / si.cm**3 / si.s), + (+4, 1.05e06 / si.cm**3 / si.s), + (+5, 1.57e11 / si.cm**3 / si.s), + (+6, 1.24e14 / si.cm**3 / si.s), + (+7, 8.99e15 / si.cm**3 / si.s), + (+8, 1.79e17 / si.cm**3 / si.s), + (+9, 1.65e18 / si.cm**3 / si.s), + (10, 9.17e18 / si.cm**3 / si.s), ), ) - def test_seinfeld_pandis_table_11p4(T, S, table_J): - formulae = Formulae(homogeneous_liquid_nucleation_rate="CNT") - e_s = formulae.saturation_vapour_pressure.pvs_water(T) - J = formulae.homogeneous_liquid_nucleation_rate.j_liq_homo(T, S, e_s) - np.testing.assert_approx_equal( - actual=J, desired=table_J / si.cm**3 / si.s, significant=1 + def test_seinfeld_pandis_table_11p4(saturation_ratio, desired_j): + # arrange + temperature = 293 * si.K + e_s = 23365 * si.g / si.cm / si.s**2 + formulae = Formulae( + homogeneous_liquid_nucleation_rate="CNT", + constants={"sgm_w": 72.75 * si.dyn / si.cm}, + ) + + # act + actual_j = formulae.homogeneous_liquid_nucleation_rate.j_liq_homo( + temperature, saturation_ratio, e_s ) + + # assert + np.testing.assert_allclose( + actual=np.log10(actual_j), + desired=np.log10(desired_j), + rtol=0.25, + ) + + @staticmethod + @pytest.mark.parametrize( + "formulae_factory", + ( + pytest.param( + lambda _si: Formulae(homogeneous_liquid_nucleation_rate="CNT"), id="CNT" + ), + pytest.param( + lambda _si: Formulae( + homogeneous_liquid_nucleation_rate="Constant", + constants={ + "J_LIQ_HOMO": 1 / _si.s / _si.m**3, + "R_LIQ_HOMO": 1 * _si.m, + }, + ), + id="Constant", + ), + ), + ) + @pytest.mark.parametrize("check", ("r", "j")) + def test_units(formulae_factory, check): + with DimensionalAnalysis(): + # arrange + si = constants_defaults.si # pylint: disable=redefined-outer-name + sut = formulae_factory(si).homogeneous_liquid_nucleation_rate + + # act & assert + if check == "j": + assert sut.j_liq_homo( + T=1 * si.K, S=1 * si.dimensionless, e_s=1 * si.Pa + ).check("[frequency] / [volume]") + elif check == "r": + assert sut.r_liq_homo(T=1 * si.K, S=1 * si.dimensionless).check( + "[length]" + ) + else: + assert False From 12b55dd3753d4b4c4d780c777510c46a87a1d0e8 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 14 Feb 2025 16:06:12 +0100 Subject: [PATCH 54/56] less crazy test values for T and S --- .../unit_tests/physics/test_homogeneous_liquid_nucleation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py index 8739b3b1f..239e27def 100644 --- a/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py +++ b/tests/unit_tests/physics/test_homogeneous_liquid_nucleation.py @@ -106,10 +106,10 @@ def test_units(formulae_factory, check): # act & assert if check == "j": assert sut.j_liq_homo( - T=1 * si.K, S=1 * si.dimensionless, e_s=1 * si.Pa + T=300 * si.K, S=2 * si.dimensionless, e_s=600 * si.Pa ).check("[frequency] / [volume]") elif check == "r": - assert sut.r_liq_homo(T=1 * si.K, S=1 * si.dimensionless).check( + assert sut.r_liq_homo(T=300 * si.K, S=2 * si.dimensionless).check( "[length]" ) else: From 7150f84909c821718db324f07e641151907b8c4b Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Sat, 15 Feb 2025 00:17:29 +0100 Subject: [PATCH 55/56] unit test for homogeneous nucleation dynamic using constant rate --- .../dynamics/test_homogeneous_nucleation.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 tests/unit_tests/dynamics/test_homogeneous_nucleation.py diff --git a/tests/unit_tests/dynamics/test_homogeneous_nucleation.py b/tests/unit_tests/dynamics/test_homogeneous_nucleation.py new file mode 100644 index 000000000..f3f06a96c --- /dev/null +++ b/tests/unit_tests/dynamics/test_homogeneous_nucleation.py @@ -0,0 +1,71 @@ +# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring + +import pytest +import numpy as np +from PySDM import Formulae, Builder +from PySDM.dynamics import HomogeneousLiquidNucleation +from PySDM.products import SuperDropletCountPerGridbox, ParticleConcentration +from PySDM.environments import Box +from PySDM.physics import si + + +@pytest.mark.parametrize( + "nucleation_rate", + ( + 44 / si.s / si.m**3, + 444 / si.s / si.m**3, + ), +) +@pytest.mark.parametrize("timestep", (0.25 * si.s, 10 * si.s)) +@pytest.mark.parametrize("volume", (0.25 * si.m**3, 10 * si.m**3)) +@pytest.mark.parametrize("n_steps", (1, 44)) +def test_const_j_expectation_match( + nucleation_rate, backend_class, timestep, volume, n_steps +): + if backend_class.__name__ == "ThrustRTC": + pytest.skip("TODO #1492") + + # arrange + n_sd = n_steps + + formulae = Formulae( + homogeneous_liquid_nucleation_rate="Constant", + constants={"J_LIQ_HOMO": nucleation_rate, "R_LIQ_HOMO": 0}, + ) + builder = Builder( + backend=backend_class(formulae), + n_sd=n_sd, + environment=Box(dt=timestep, dv=volume), + ) + builder.add_dynamic(HomogeneousLiquidNucleation()) + + # TODO #1492 + for attr in ("dry volume", "kappa times dry volume"): + builder.request_attribute(attr) + + particulator = builder.build( + attributes={ + "multiplicity": np.full(n_sd, fill_value=np.nan), + "water mass": np.full(n_sd, fill_value=0), + "dry volume": np.full(n_sd, fill_value=0), + "kappa times dry volume": np.full(n_sd, fill_value=0), + }, + products=( + SuperDropletCountPerGridbox(name="n_super_particles_per_cell"), + ParticleConcentration(name="n_particles_per_dv"), + ), + ) + + for var in ("RH", "T"): + particulator.environment[var] = np.nan + + # act + particulator.run(steps=n_steps) + + # assert + assert particulator.products["n_super_particles_per_cell"].get() == n_steps + np.testing.assert_allclose( + actual=particulator.products["n_particles_per_dv"].get(), + desired=nucleation_rate * timestep * n_steps, + rtol=1e-1, + ) From 8bceee3f0a5efe16bd50c59ecb226b5229f02003 Mon Sep 17 00:00:00 2001 From: claresinger Date: Thu, 17 Jul 2025 14:06:34 -0400 Subject: [PATCH 56/56] new experiment without seed particles to look at homogeneous nucleation for different pressure drops --- PySDM/backends/impl_numba/methods/__init__.py | 1 - PySDM/backends/numba.py | 2 - .../dynamics/homogeneous_liquid_nucleation.py | 2 +- .../expansion_experiment_nucleation.ipynb | 279 ++++++++++++++++++ .../Erinin_et_al_2025/expansion_simulation.py | 6 +- 5 files changed, 283 insertions(+), 7 deletions(-) create mode 100644 examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment_nucleation.ipynb diff --git a/PySDM/backends/impl_numba/methods/__init__.py b/PySDM/backends/impl_numba/methods/__init__.py index d93c194fe..b3b2573b9 100644 --- a/PySDM/backends/impl_numba/methods/__init__.py +++ b/PySDM/backends/impl_numba/methods/__init__.py @@ -13,5 +13,4 @@ from .physics_methods import PhysicsMethods from .terminal_velocity_methods import TerminalVelocityMethods from .spawning_methods import SpawningMethods -from .seeding_methods import SeedingMethods from .deposition_methods import DepositionMethods diff --git a/PySDM/backends/numba.py b/PySDM/backends/numba.py index 24564fa8d..c522e23eb 100644 --- a/PySDM/backends/numba.py +++ b/PySDM/backends/numba.py @@ -29,7 +29,6 @@ class Numba( # pylint: disable=too-many-ancestors,duplicate-code methods.TerminalVelocityMethods, methods.IsotopeMethods, methods.SpawningMethods, - methods.SeedingMethods, methods.DepositionMethods, ): Storage = ImportedStorage @@ -80,5 +79,4 @@ def __init__(self, formulae=None, double_precision=True, override_jit_flags=None methods.TerminalVelocityMethods.__init__(self) methods.IsotopeMethods.__init__(self) methods.SpawningMethods.__init__(self) - methods.SeedingMethods.__init__(self) methods.DepositionMethods.__init__(self) diff --git a/PySDM/dynamics/homogeneous_liquid_nucleation.py b/PySDM/dynamics/homogeneous_liquid_nucleation.py index b1e3a531b..1f3869da6 100644 --- a/PySDM/dynamics/homogeneous_liquid_nucleation.py +++ b/PySDM/dynamics/homogeneous_liquid_nucleation.py @@ -41,7 +41,7 @@ def __call__(self): ) v_wet = self.formulae.trivia.volume(radius=r_wet) new_sd_extensive_attributes = { - "water mass": (v_wet * self.formulae.constants.rho_w,), + "signed water mass": (v_wet * self.formulae.constants.rho_w,), "dry volume": (0,), "kappa times dry volume": (0,), } diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment_nucleation.ipynb b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment_nucleation.ipynb new file mode 100644 index 000000000..4c441bc13 --- /dev/null +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment_nucleation.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[![preview notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)\n", + "[![launch on mybinder.org](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PySDM.git/main?urlpath=lab/tree/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)\n", + "[![launch on Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PySDM/blob/main/examples/PySDM_examples/Erinin_et_al_2025/expansion_experiment.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "modeling expansion-chamber experiments with empty chamber (~zero seed particles)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-30T20:21:31.584604Z", + "start_time": "2025-01-30T20:21:31.573353Z" + } + }, + "outputs": [], + "source": [ + "import sys\n", + "if 'google.colab' in sys.modules:\n", + " !pip --quiet install open-atmos-jupyter-utils\n", + " from open_atmos_jupyter_utils import pip_install_on_colab\n", + " pip_install_on_colab('PySDM-examples')" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-30T20:21:37.280272Z", + "start_time": "2025-01-30T20:21:31.850352Z" + } + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot\n", + "from open_atmos_jupyter_utils import show_plot\n", + "from PySDM import Formulae\n", + "from PySDM.physics import si, in_unit\n", + "from PySDM import products as PySDM_products\n", + "from PySDM_examples.Erinin_et_al_2025.aerosol import AerosolChamber\n", + "from PySDM_examples.Erinin_et_al_2025.expansion_simulation import run_expansion" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "dry_radius_bin_edges = np.geomspace(50 * si.nm, 2000 * si.nm, 40, endpoint=False)\n", + "wet_radius_bin_edges = np.geomspace(1 * si.um, 40 * si.um, 40, endpoint=False)\n", + "\n", + "products = (\n", + " PySDM_products.SuperDropletCountPerGridbox(name=\"SD count\"),\n", + " PySDM_products.WaterMixingRatio(unit=\"g/kg\", name=r\"$q_\\ell$\"),\n", + " PySDM_products.PeakSaturation(name=\"Saturation ratio\"),\n", + " PySDM_products.AmbientRelativeHumidity(name=\"RH\"),\n", + " PySDM_products.AmbientTemperature(name=\"Temperature\", var=\"T\"),\n", + " PySDM_products.AmbientPressure(name=\"Pressure\", var=\"p\", unit=\"hPa\"),\n", + " PySDM_products.AmbientWaterVapourMixingRatio(\n", + " unit=\"g/kg\", name=\"$q_v$\", var=\"water_vapour_mixing_ratio\"\n", + " ),\n", + " PySDM_products.Time(name=\"t\"),\n", + " PySDM_products.ParticleSizeSpectrumPerVolume(\n", + " name=\"dry:dN/dR\",\n", + " unit=\"m^-3 m^-1\",\n", + " radius_bins_edges=dry_radius_bin_edges,\n", + " dry=True,\n", + " ),\n", + " PySDM_products.ParticleSizeSpectrumPerVolume(\n", + " name=\"wet:dN/dR\",\n", + " unit=\"m^-3 m^-1\",\n", + " radius_bins_edges=wet_radius_bin_edges,\n", + " dry=False,\n", + " ),\n", + " PySDM_products.ActivatedEffectiveRadius(\n", + " name=\"act_reff\", unit=\"um\", count_activated=True, count_unactivated=False\n", + " ),\n", + " PySDM_products.EffectiveRadius(\n", + " name=\"$r_{eff}$\",\n", + " unit=\"um\",\n", + " ),\n", + " PySDM_products.ParticleConcentration(\n", + " name=\"$N_d$\",\n", + " unit=\"cm^-3\",\n", + " # radius_range=(0.5 * si.um, 25 * si.um),\n", + " ),\n", + ") " + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "FORMULAE = Formulae(\n", + " adiabatic_exponent=\"MoistLeadingTerms\",\n", + " homogeneous_liquid_nucleation_rate='CNT',\n", + ")\n", + "CONST = FORMULAE.constants\n", + "\n", + "N_SD_PER_MODE = 20\n", + "DT = .01 * si.s\n", + "\n", + "C0 = 1 / si.cm**3\n", + "P0 = 1000 * si.hPa\n", + "PF_arr = np.linspace(620,680,4)*si.hPa\n", + "DELTA_TIME = 0.5*si.s" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "ExecuteTime": { + "end_time": "2025-01-30T20:23:04.715504Z", + "start_time": "2025-01-30T20:21:37.309294Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pf=6.20e+04\n", + "pf=6.30e+04\n", + "pf=6.40e+04\n", + "pf=6.50e+04\n", + "pf=6.60e+04\n", + "pf=6.70e+04\n", + "pf=6.80e+04\n" + ] + } + ], + "source": [ + "output_all = {}\n", + "\n", + "aerosol = AerosolChamber(\n", + " water_molar_volume=CONST.Mv / CONST.rho_w,\n", + " N=C0,\n", + " )\n", + "\n", + "for PFi in PF_arr:\n", + " key = f\"pf={PFi:.2e}\"\n", + " print(key)\n", + " \n", + " output = run_expansion(\n", + " formulae=FORMULAE,\n", + " aerosol=aerosol,\n", + " n_sd_per_mode=N_SD_PER_MODE,\n", + " n_sd_homo_liq_nucleation=1000,\n", + " p0=P0,\n", + " pf=PFi,\n", + " delta_time=DELTA_TIME,\n", + " total_time=5*si.s,\n", + " dt=DT,\n", + " products=products,\n", + " )\n", + "\n", + " output_all[key] = output\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "130898688.89495\n", + "7358438.967978572\n", + "295163.2019142857\n", + "8023.87325\n", + "138.96157857142856\n", + "1.4229142857142858\n", + "0.007721428571428572\n" + ] + }, + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2025-07-17T14:05:25.052515\n image/svg+xml\n \n \n Matplotlib v3.5.1, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b9ff2d6977b84d08b84d5c3dabb2139e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HTML(value=\"./PF_sweep_traces.pdf
\")" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "variables = [\"Pressure\", \"Temperature\", \"Saturation ratio\", \"SD count\", r\"$q_\\ell$\", \"$q_v$\", \"$r_{eff}$\", \"$N_d$\"]\n", + "fig, axes = pyplot.subplots(2,4,figsize=(12,5), sharex=True, sharey=False, constrained_layout=True)\n", + "\n", + "for PFi in PF_arr:\n", + " key = f\"pf={PFi:.2e}\"\n", + " output = output_all[key]\n", + " init_mult = output.attributes[\"multiplicity\"][0]\n", + " final_mult = output.attributes[\"multiplicity\"][-1]\n", + " print((np.sum(final_mult) - np.sum(init_mult)) / np.sum(init_mult))\n", + " for i, ax in enumerate(axes.flatten()):\n", + " y = np.array(output.profile[variables[i]])\n", + " ax.plot(output.profile[\"t\"], y, label=f\"{in_unit(PFi, si.hPa):.2e}\")\n", + " if i == 7:\n", + " ax.set_yscale(\"log\")\n", + " # ax.set_ylim(3e2,8e2)\n", + " ax.set_xlabel(f\"Time [{output.units['t']}]\")\n", + " ax.set_ylabel(f\"{variables[i]} [{output.units[variables[i]]}]\")\n", + "\n", + "axes[0, 0].legend(title=\"$p_f$ [hPa]\")\n", + "fig.set_facecolor('white')\n", + "show_plot(\"PF_sweep_traces.pdf\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + }, + "vscode": { + "interpreter": { + "hash": "b14f34a08619f4a218d80d7380beed3f0c712c89ff93e7183219752d640ed427" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py index daca596fc..fd4409c8a 100644 --- a/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py +++ b/examples/PySDM_examples/Erinin_et_al_2025/expansion_simulation.py @@ -9,7 +9,7 @@ HomogeneousLiquidNucleation, ) from PySDM.environments import ExpansionChamber -from PySDM.initialisation import equilibrate_wet_radii +from PySDM.initialisation.hygroscopic_equilibrium import equilibrate_wet_radii from PySDM.initialisation.sampling.spectral_sampling import ConstantMultiplicity from PySDM.physics import si @@ -52,7 +52,7 @@ def run_expansion( builder.add_dynamic(AmbientThermodynamics()) builder.add_dynamic(Condensation(adaptive=True)) builder.add_dynamic(HomogeneousLiquidNucleation()) - builder.request_attribute("critical supersaturation") + builder.request_attribute("critical saturation") attributes = { k: np.empty(0) for k in ("dry volume", "kappa times dry volume", "multiplicity") @@ -97,7 +97,7 @@ def run_expansion( "multiplicity", "volume", "critical volume", - "critical supersaturation", + "critical saturation", ) }