From 1451f7075c38b12f9a82fc422c442952947eedc6 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 15 Oct 2026 00:20:53 +0200 Subject: [PATCH 01/11] bump PySDM requirement (in notebooks that use it) to >=3.0.0 and adapt code to new PySDM v3 API --- examples/additive_coag_comparison.ipynb | 36 +- examples/lognorm_ex.ipynb | 51 ++- examples/terminal_velocities.ipynb | 479 +++++++++++++----------- 3 files changed, 297 insertions(+), 269 deletions(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index 2da7753b..21251707 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -74,7 +74,7 @@ "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('PyPartMC', 'PySDM','dustpy')\n", + " pip_install_on_colab('PyPartMC', 'PySDM>3.0.0','dustpy')\n", "\n", " # install julia if not in system\n", " if shutil.which('julia') is None:\n", @@ -287,26 +287,19 @@ " import PySDM\n", " from PySDM.physics import si\n", "\n", - " builder = PySDM.Builder(\n", - " settings.N_PART,\n", - " backend=PySDM.backends.CPU(override_jit_flags={\"parallel\": False}),\n", - " environment=PySDM.environments.Box(\n", - " dt=settings.DT_SEC * si.s,\n", - " dv=settings.VOLUME_M3 * si.m**3\n", - " )\n", + " backend = PySDM.backends.CPU()\n", + " box = environment=PySDM.environments.Box(\n", + " dt=settings.DT_SEC * si.s,\n", + " dv=settings.VOLUME_M3 * si.m**3,\n", + " backend=backend,\n", " )\n", - " trivia = builder.formulae.trivia\n", + " trivia = backend.formulae.trivia\n", " spectrum = PySDM.initialisation.spectra.Exponential(\n", " norm_factor=settings.NUM_CONC_PER_M3 * settings.VOLUME_M3 / si.m**3,\n", " scale=trivia.volume(radius=settings.DIAM_AT_MEAN_VOL_M / 2 * si.m)\n", " )\n", - " builder.add_dynamic(PySDM.dynamics.Coalescence(\n", - " collision_kernel=PySDM.dynamics.collisions.collision_kernels.Golovin(\n", - " b=settings.ADDITIVE_KERNEL_COEFF\n", - " ), adaptive=False\n", - " ))\n", - "\n", - " self.particulator = builder.build(\n", + " self.particulator = Particulator(\n", + " n_sd=settings.N_PART,\n", " attributes=builder.particulator.environment.init_attributes(\n", " spectral_discretisation=PySDM.initialisation.sampling.spectral_sampling.Logarithmic(\n", " spectrum,\n", @@ -321,7 +314,14 @@ " radius_bins_edges=settings.RADIUS_BIN_EDGES_M,\n", " name='Volume Density (1/ unit ln R)',\n", " )\n", - " )\n", + " ),\n", + " dynamics=(\n", + " PySDM.dynamics.Coalescence(\n", + " collision_kernel=PySDM.dynamics.collisions.collision_kernels.Golovin(\n", + " b=settings.ADDITIVE_KERNEL_COEFF\n", + " ), adaptive=False\n", + " ),\n", + " ),\n", " )\n", " super().__init__(settings)\n", "\n", @@ -1070,7 +1070,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.2" + "version": "3.13.5" } }, "nbformat": 4, diff --git a/examples/lognorm_ex.ipynb b/examples/lognorm_ex.ipynb index 7d8613b9..bb2e20c5 100644 --- a/examples/lognorm_ex.ipynb +++ b/examples/lognorm_ex.ipynb @@ -36,9 +36,9 @@ "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('PyPartMC', 'PySDM')\n", + " pip_install_on_colab('PyPartMC', 'PySDM>=3.0.0')\n", "elif 'JUPYTER_IMAGE' in os.environ and '.arm.gov' in os.environ['JUPYTER_IMAGE']:\n", - " !pip --quiet install PyPartMC PySDM open-atmos-jupyter-utils\n", + " !pip --quiet install PyPartMC 'PySDM>=3.0.0' open-atmos-jupyter-utils\n", " _pypartmc_path = !pip show PyPartMC | fgrep Location | cut -f2 -d' '\n", " sys.path.extend(_pypartmc_path if _pypartmc_path[0] not in sys.path else [])" ] @@ -54,14 +54,13 @@ "import ipywidgets as widgets\n", "import numpy as np\n", "from PySDM.environments import Box\n", - "from PySDM import Builder\n", "from PySDM.backends import CPU\n", - "from PySDM.initialisation import equilibrate_wet_radii\n", + "from PySDM.initialisation.hygroscopic_equilibrium import equilibrate_wet_radii\n", "from matplotlib import pyplot\n", "from IPython.display import display, clear_output\n", "from open_atmos_jupyter_utils import show_plot\n", "from PyPartMC import si\n", - "import PyPartMC as ppmc\n" + "import PyPartMC as ppmc" ] }, { @@ -234,16 +233,14 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 17, "id": "4d9881b4", "metadata": {}, "outputs": [], "source": [ "def pysdm(dry_diameters, temp, rel_humid, kappa):\n", " r_dry = dry_diameters / 2\n", - " builder = Builder(n_sd=0, backend=CPU())\n", - " environment = Box(dt=np.nan, dv=np.nan)\n", - " environment.register(builder)\n", + " environment = Box(dt=np.nan, dv=np.nan, backend=CPU())\n", " environment['T'] = temp\n", " environment['RH'] = rel_humid\n", " kappa_times_dry_volume = kappa * (np.pi / 6) * dry_diameters**3\n", @@ -256,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 18, "id": "ee131ad8", "metadata": {}, "outputs": [], @@ -269,14 +266,14 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 19, "id": "56fd1c71", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8413898068594929b63f25b06825f179", + "model_id": "2a2407370aa24bde8fb70b9e8ec5d5ac", "version_major": 2, "version_minor": 0 }, @@ -290,7 +287,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "a6ae915030f7410292141561b880b036", + "model_id": "69d5191b28fe45ed8c16fb1dce09e4a3", "version_major": 2, "version_minor": 0 }, @@ -304,7 +301,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "ccef33aae7484b94bf014631e97a5ce7", + "model_id": "5b841ee13d2f414781d71e9d5ada2662", "version_major": 2, "version_minor": 0 }, @@ -318,7 +315,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "210dc96de734412e969291856705b875", + "model_id": "2de009dab50a484f852ef4bc0953b394", "version_major": 2, "version_minor": 0 }, @@ -332,7 +329,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b367f53a27d14a5fa96b7c44f342877f", + "model_id": "5e013b0a4d7d4d428fdf12121f7f32d2", "version_major": 2, "version_minor": 0 }, @@ -346,7 +343,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "52c9258492e24a4581b6621f148818c5", + "model_id": "43c68b80d3374c3aa17998bd2c057515", "version_major": 2, "version_minor": 0 }, @@ -360,12 +357,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f6339251b9dd4d819c1d00fc965e6a64", + "model_id": "dd4071d070b544b496984f5001b54d10", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(Label(value='Mode 1 Geometric Mean Diameter [microns]:'), FloatSlider(value=0.9, max=10.0, min=…" + "HBox(children=(Label(value='Mode 1 Geometric Mean Diameter [microns]:'), FloatSlider(value=0.901, max=10.0, mi…" ] }, "metadata": {}, @@ -374,7 +371,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "074657939eee416eaad66e74a0db2041", + "model_id": "2dc027992cc748719d3f979e145014c9", "version_major": 2, "version_minor": 0 }, @@ -388,7 +385,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "0774b29ac6384f1eb7d9b4ba4e519a88", + "model_id": "6f697a6bb1f943d6b8c1b6866ae40481", "version_major": 2, "version_minor": 0 }, @@ -402,12 +399,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "d31861643fad408cbdc92b9ac5a4f1ce", + "model_id": "041227f317094df7b9cb3b1b60dc5de0", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HBox(children=(Label(value='Mode 2 Geometric Mean Diameter [microns]:'), FloatSlider(value=5.8, max=10.0, min=…" + "HBox(children=(Label(value='Mode 2 Geometric Mean Diameter [microns]:'), FloatSlider(value=5.801, max=10.0, mi…" ] }, "metadata": {}, @@ -416,7 +413,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "df434a9a1721464b95c35ce8ee79a0cc", + "model_id": "44b2228c41c244e9b513d786025f9151", "version_major": 2, "version_minor": 0 }, @@ -430,7 +427,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "fa23ee7ebb8c4defbe29892795ed986a", + "model_id": "2be546cfe3fc4125a420832b2c6ef335", "version_major": 2, "version_minor": 0 }, @@ -444,7 +441,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "b709cc132b6f4d60af07434521f4abcc", + "model_id": "03ae40fabaa04509993c675ad0ad02cd", "version_major": 2, "version_minor": 0 }, @@ -549,7 +546,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.13.5" }, "vscode": { "interpreter": { diff --git a/examples/terminal_velocities.ipynb b/examples/terminal_velocities.ipynb index 63458ef3..b43fd836 100644 --- a/examples/terminal_velocities.ipynb +++ b/examples/terminal_velocities.ipynb @@ -1,5 +1,36 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "9238ec23-e4f8-40cc-80f1-23b404fb42e5", + "metadata": {}, + "source": [ + "[![View notebook](https://img.shields.io/static/v1?label=render%20on&logo=github&color=87ce3e&message=GitHub)](https://github.com/open-atmos/PyPartMC/blob/main/examples/terminal_velocities.ipynb) \n", + "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-atmos/PyPartMC/blob/main/examples/terminal_velocities.ipynb) \n", + "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/open-atmos/PyPartMC.git/main?urlpath=lab/tree/examples/terminal_velocities.ipynb) \n", + "[![ARM JupyterHub](https://img.shields.io/static/v1?label=launch%20in&logo=jupyter&color=lightblue&message=ARM+JupyterHub)](https://jupyterhub.arm.gov/hub/user-redirect/git-pull?repo=https%3A//github.com/open-atmos/PyPartMC&branch=main&urlPath=) (requires [logging in with ARM account](https://www.arm.gov/capabilities/computing-resources) and directing Jupyter to a notebook within the cloned repo) \n", + "[![Voila](https://img.shields.io/static/v1?label=Voil%C3%A0&logo=jupyter&color=teal&message=web+app)](https://mybinder.org/v2/gh/open-atmos/PyPartMC/main?urlpath=voila%2Frender%2Fexamples%2Fterminal_velocities.ipynb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc5b5985-f650-4f98-8016-bcee208ab905", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import os\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>=3.0.0')\n", + "elif 'JUPYTER_IMAGE' in os.environ and '.arm.gov' in os.environ['JUPYTER_IMAGE']:\n", + " !pip --quiet install 'PySDM>=3.0.0' open_atmos_jupyter_utils\n", + " _pypartmc_path = !pip show PyPartMC | fgrep Location | cut -f2 -d' '\n", + " sys.path.extend(_pypartmc_path if _pypartmc_path[0] not in sys.path else [])" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -7,7 +38,7 @@ "metadata": {}, "outputs": [], "source": [ - "from PySDM import Builder\n", + "from PySDM import Particulator\n", "from PySDM.backends import CPU\n", "from PySDM.physics import si\n", "from PySDM.environments import Box\n", @@ -28,20 +59,23 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "id": "ad975357", "metadata": {}, "outputs": [], "source": [ - "builder = Builder(n_sd=100, backend=CPU())\n", - "builder.set_environment(Box(dt=np.nan, dv=np.nan))\n", - "builder.request_attribute('terminal velocity')\n", - "particulator = builder.build(attributes={'n': np.ones_like(volumes), 'volume': volumes})" + "box = Box(dt=np.nan, dv=np.nan, backend=CPU())\n", + "particulator = Particulator(\n", + " n_sd=100,\n", + " environment=box,\n", + " attributes={'multiplicity': np.ones_like(volumes), 'volume': volumes},\n", + " requested_attributes=('terminal velocity',)\n", + ")" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "id": "c8a54ad2", "metadata": {}, "outputs": [], @@ -51,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "ed9ca429", "metadata": {}, "outputs": [ @@ -61,16 +95,16 @@ "\n", "\n", - "\n", + "\n", " \n", " \n", " \n", " \n", - " 2022-07-26T15:21:03.094638\n", + " 2026-10-15T00:15:32.748681\n", " image/svg+xml\n", " \n", " \n", - " Matplotlib v3.5.2, https://matplotlib.org/\n", + " Matplotlib v3.10.8, https://matplotlib.org/\n", " \n", " \n", " \n", @@ -81,19 +115,18 @@ " \n", " \n", " \n", - " \n", + "\" style=\"fill: #ffffff\"/>\n", " \n", " \n", " \n", - " \n", @@ -101,23 +134,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", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -651,83 +684,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", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", + " \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": "d184a6cdf7154a21b395cce92f3857e5", + "model_id": "169be05838fd457e92993a04ae59d091", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "HTML(value=\"./terminal_velocities.pdf

\")" + "HBox(children=(HTML(value=\"./terminal_velocities.pdf Date: Thu, 15 Oct 2026 08:20:09 +0200 Subject: [PATCH 02/11] enforce examples dependencies for pylint workflow --- .github/workflows/pylint.yml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 735a6d88..164d5b7a 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -22,7 +22,7 @@ jobs: - run: | python -m pip install --upgrade pip pip install pylint nbqa - pip install -e .[tests] + pip install -e .[tests,examples] pip install -r .binder/requirements.txt - run: pylint --unsafe-load-any-extension=y --disable=fixme,no-member,trailing-newlines,missing-module-docstring,missing-class-docstring,missing-function-docstring,unnecessary-pass $(git ls-files '*.py') - run: nbqa pylint --unsafe-load-any-extension=y --disable=fixme,no-member,duplicate-code,wrong-import-position,ungrouped-imports,trailing-whitespace,missing-function-docstring,missing-module-docstring,unsubscriptable-object,invalid-name $(git ls-files '*.ipynb') diff --git a/pyproject.toml b/pyproject.toml index 49ee77f3..8d2989d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -280,7 +280,7 @@ examples = [ "ipywidgets", "voila", "open-atmos-jupyter-utils", - "PySDM", + "PySDM >= 3.0.0", "PyMieScatt", "SciPy", "dustpy; platform_system != 'Windows'" From 007eaa4c3af13f1a91a5536f341be43a5ce08174 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 15 Oct 2026 08:30:22 +0200 Subject: [PATCH 03/11] bump Python version for pylint workflow (needed by JAX - a new PySDM dependency) --- .github/workflows/pylint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml index 164d5b7a..3c4a636e 100644 --- a/.github/workflows/pylint.yml +++ b/.github/workflows/pylint.yml @@ -18,7 +18,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-python@v6 with: - python-version: 3.9 + python-version: 3.14 - run: | python -m pip install --upgrade pip pip install pylint nbqa From b1a612cfff31af9765f902a1d8ceab939963f86d Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 15 Oct 2026 12:41:31 +0200 Subject: [PATCH 04/11] fix import --- examples/additive_coag_comparison.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index 21251707..f414ea69 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -298,7 +298,7 @@ " norm_factor=settings.NUM_CONC_PER_M3 * settings.VOLUME_M3 / si.m**3,\n", " scale=trivia.volume(radius=settings.DIAM_AT_MEAN_VOL_M / 2 * si.m)\n", " )\n", - " self.particulator = Particulator(\n", + " self.particulator = PySDM.Particulator(\n", " n_sd=settings.N_PART,\n", " attributes=builder.particulator.environment.init_attributes(\n", " spectral_discretisation=PySDM.initialisation.sampling.spectral_sampling.Logarithmic(\n", From 47fcaa1a16fe21b1ea3611ec8fc0b92a67a16f2f Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 15 Oct 2026 14:34:32 +0200 Subject: [PATCH 05/11] one more fix in PySDM code --- examples/additive_coag_comparison.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index f414ea69..f394275a 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -300,7 +300,7 @@ " )\n", " self.particulator = PySDM.Particulator(\n", " n_sd=settings.N_PART,\n", - " attributes=builder.particulator.environment.init_attributes(\n", + " attributes=box.init_attributes(\n", " spectral_discretisation=PySDM.initialisation.sampling.spectral_sampling.Logarithmic(\n", " spectrum,\n", " )\n", From a4d36f51d75021d0715487b56795989d1a5a93ae Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Thu, 15 Oct 2026 15:03:05 +0200 Subject: [PATCH 06/11] address pylint hint --- tests/test_loss_rate.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_loss_rate.py b/tests/test_loss_rate.py index 96b49dc6..676077c0 100644 --- a/tests/test_loss_rate.py +++ b/tests/test_loss_rate.py @@ -4,7 +4,7 @@ # Authors: https://github.com/open-atmos/PyPartMC/graphs/contributors # #################################################################################################### -from cmath import nan +import math import numpy as np import pytest @@ -57,7 +57,7 @@ def test_loss_rate(loss_function_params: str): rate = ppmc.loss_rate(scenario, vol, density, aero_data, env_state) # assert - assert rate is not nan + assert not math.isnan(rate) @staticmethod def test_loss_rate_dry_dep(): @@ -77,4 +77,4 @@ def test_loss_rate_dry_dep(): rate = ppmc.loss_rate_dry_dep(vol, density, aero_data, env_state) # assert - assert rate is not nan + assert not math.isnan(rate) From c6eabbd258e6f5584b635af04338f52ef099fa34 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 16 Oct 2026 20:07:50 +0200 Subject: [PATCH 07/11] use sample_deterministic instead of obsolete init_attributes --- examples/additive_coag_comparison.ipynb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index f394275a..8b9f46b1 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -298,13 +298,14 @@ " norm_factor=settings.NUM_CONC_PER_M3 * settings.VOLUME_M3 / si.m**3,\n", " scale=trivia.volume(radius=settings.DIAM_AT_MEAN_VOL_M / 2 * si.m)\n", " )\n", + " attributes = {}\n", + " attributes['volume'], attributes['multiplicity'] = PySDM.initialisation.sampling.spectral_sampling.Logarithmic(spectrum).sample_deterministic(\n", + " backend=backend,\n", + " n_sd=settings.N_PART,\n", + " )\n", " self.particulator = PySDM.Particulator(\n", " n_sd=settings.N_PART,\n", - " attributes=box.init_attributes(\n", - " spectral_discretisation=PySDM.initialisation.sampling.spectral_sampling.Logarithmic(\n", - " spectrum,\n", - " )\n", - " ),\n", + " attributes=attributes,\n", " products=(\n", " PySDM.products.ParticleSizeSpectrumPerVolume(\n", " radius_bins_edges=settings.RADIUS_BIN_EDGES_M,\n", From 30ad899d5f9fd877b65ad1a6c0e511e8f6e78cd7 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 16 Oct 2026 22:36:00 +0200 Subject: [PATCH 08/11] fix Particulator instantiation; drop macos-intel from run_example_notebooks job; simplify C++ example install --- .github/workflows/buildwheels.yml | 4 ++-- examples/additive_coag_comparison.ipynb | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/buildwheels.yml b/.github/workflows/buildwheels.yml index df90af11..0fd530a8 100644 --- a/.github/workflows/buildwheels.yml +++ b/.github/workflows/buildwheels.yml @@ -92,7 +92,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, macos-14, macos-15, macos-15-intel, windows-latest] + os: [ubuntu-latest, ubuntu-24.04-arm, macos-14, macos-15, windows-latest] steps: - uses: actions/checkout@v7 @@ -391,7 +391,7 @@ jobs: - run: | temp=`find dist/ -name "*cp312*.whl"` - python -m pip install $temp[examples] + python -m pip install $temp - run: pip install pytest-codeblocks pytest - run: mkdir readme_cpp diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index 8b9f46b1..bd956593 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -304,6 +304,7 @@ " n_sd=settings.N_PART,\n", " )\n", " self.particulator = PySDM.Particulator(\n", + " environment=box,\n", " n_sd=settings.N_PART,\n", " attributes=attributes,\n", " products=(\n", From 4b268ba00593cebc97b1efd138acc441e800f1c9 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Fri, 16 Oct 2026 23:12:53 +0200 Subject: [PATCH 09/11] pylint hints --- examples/additive_coag_comparison.ipynb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index bd956593..750b14f7 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -288,7 +288,7 @@ " from PySDM.physics import si\n", "\n", " backend = PySDM.backends.CPU()\n", - " box = environment=PySDM.environments.Box(\n", + " box = PySDM.environments.Box(\n", " dt=settings.DT_SEC * si.s,\n", " dv=settings.VOLUME_M3 * si.m**3,\n", " backend=backend,\n", @@ -299,7 +299,12 @@ " scale=trivia.volume(radius=settings.DIAM_AT_MEAN_VOL_M / 2 * si.m)\n", " )\n", " attributes = {}\n", - " attributes['volume'], attributes['multiplicity'] = PySDM.initialisation.sampling.spectral_sampling.Logarithmic(spectrum).sample_deterministic(\n", + " (\n", + " attributes['volume'],\n", + " attributes['multiplicity'],\n", + " ) = PySDM.initialisation.sampling.spectral_sampling.Logarithmic(\n", + " spectrum\n", + " ).sample_deterministic(\n", " backend=backend,\n", " n_sd=settings.N_PART,\n", " )\n", From 9b85213f1113269dc0470765960ed8443ac14eb4 Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Sat, 17 Oct 2026 11:02:59 +0200 Subject: [PATCH 10/11] run() -> advance() --- examples/additive_coag_comparison.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index 750b14f7..099dfc48 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -339,7 +339,7 @@ " 'Mass Density (kg/m^3/unit ln R)':{}}\n", " for step in range(self.settings.N_PLOT_STEPS + 1):\n", " if step != 0:\n", - " self.particulator.run(int(self.settings.PLOT_TIME_STEP_SEC // self.settings.DT_SEC))\n", + " self.particulator.advance(int(self.settings.PLOT_TIME_STEP_SEC // self.settings.DT_SEC))\n", " #next two lines convert from dr to dlnr\n", " pysdm_output['Number Concentration (#/m^3/unit ln R)'][step] = (\n", " self.particulator.products['Number Concentration (#/m^3/m)'].get()\n", From b104833af842ff7704836c9e38ff6f415afec45d Mon Sep 17 00:00:00 2001 From: Sylwester Arabas Date: Sat, 17 Oct 2026 11:12:24 +0200 Subject: [PATCH 11/11] shorter lines... --- examples/additive_coag_comparison.ipynb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/additive_coag_comparison.ipynb b/examples/additive_coag_comparison.ipynb index 099dfc48..6548654b 100644 --- a/examples/additive_coag_comparison.ipynb +++ b/examples/additive_coag_comparison.ipynb @@ -339,7 +339,8 @@ " 'Mass Density (kg/m^3/unit ln R)':{}}\n", " for step in range(self.settings.N_PLOT_STEPS + 1):\n", " if step != 0:\n", - " self.particulator.advance(int(self.settings.PLOT_TIME_STEP_SEC // self.settings.DT_SEC))\n", + " n_steps = int(self.settings.PLOT_TIME_STEP_SEC // self.settings.DT_SEC)\n", + " self.particulator.advance(n_steps)\n", " #next two lines convert from dr to dlnr\n", " pysdm_output['Number Concentration (#/m^3/unit ln R)'][step] = (\n", " self.particulator.products['Number Concentration (#/m^3/m)'].get()\n",