From 1bdbaa95728981e6b3bad42b171427e40c72b574 Mon Sep 17 00:00:00 2001 From: Zachery Aaron Shores-Chmielewski Date: Sat, 25 Jul 2026 11:09:19 +0400 Subject: [PATCH] init --- .gitignore | 12 + ...frans_equation_first_hand_simulation.ipynb | 262 + .../airfrans_openfoam_algorithm_first.ipynb | 814 ++ ...ns_stepper_full_detail_learning_tool.ipynb | 7597 +++++++++++++++++ pyproject.toml | 25 + python/pyproject.toml | 15 + python/src/foam_stepper/__init__.py | 205 + python/src/foam_stepper/_foam_stepper.so | Bin 0 -> 1457424 bytes python/src/foam_stepper/_runtime.py | 70 + python/src/foam_stepper/types.py | 399 + scripts/build_openfoam_airfrans_subset.sh | 104 + scripts/build_python_stepper.sh | 46 + scripts/fuzz_python_stepper.py | 475 ++ scripts/fuzz_python_stepper.sh | 36 + scripts/openfoam_env.py | 73 + scripts/prepare_airfrans_stepper_case.py | 274 + scripts/quadrants_hello_world.py | 43 + scripts/verify_airfrans_stepper.py | 988 +++ scripts/verify_python_stepper.py | 194 + scripts/verify_python_stepper.sh | 40 + uv.lock | 1801 ++++ 21 files changed, 13473 insertions(+) create mode 100644 .gitignore create mode 100644 notebooks/airfrans_equation_first_hand_simulation.ipynb create mode 100644 notebooks/airfrans_openfoam_algorithm_first.ipynb create mode 100644 notebooks/airfrans_stepper_full_detail_learning_tool.ipynb create mode 100644 pyproject.toml create mode 100644 python/pyproject.toml create mode 100644 python/src/foam_stepper/__init__.py create mode 100755 python/src/foam_stepper/_foam_stepper.so create mode 100644 python/src/foam_stepper/_runtime.py create mode 100644 python/src/foam_stepper/types.py create mode 100755 scripts/build_openfoam_airfrans_subset.sh create mode 100755 scripts/build_python_stepper.sh create mode 100755 scripts/fuzz_python_stepper.py create mode 100755 scripts/fuzz_python_stepper.sh create mode 100644 scripts/openfoam_env.py create mode 100755 scripts/prepare_airfrans_stepper_case.py create mode 100755 scripts/quadrants_hello_world.py create mode 100755 scripts/verify_airfrans_stepper.py create mode 100755 scripts/verify_python_stepper.py create mode 100755 scripts/verify_python_stepper.sh create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84892d5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.venv/ +.loop/ +**/__pycache__ +python/src/foam_stepper.egg-info/ + +# foreign +OpenFOAM-14/ +ThirdParty-14/ +airfrans/ + +# no idea if this is some `make` residue or not but has some object files so we exclude it +pythonStepper/ diff --git a/notebooks/airfrans_equation_first_hand_simulation.ipynb b/notebooks/airfrans_equation_first_hand_simulation.ipynb new file mode 100644 index 0000000..69fd820 --- /dev/null +++ b/notebooks/airfrans_equation_first_hand_simulation.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f61d8fbc", + "metadata": {}, + "source": [ + "# AirfRANS finite-volume hand simulation\n", + "\n", + "Purpose: learn the computation, not the Python stepper or OpenFOAM object graph.\n", + "\n", + "This notebook reduces the AirfRANS/OpenFOAM momentum loop to the smallest useful stencil:\n", + "\n", + "1. one internal face shared by two cells;\n", + "2. one boundary face on one of those cells.\n", + "\n", + "Repo grounding:\n", + "\n", + "- AirfRANS case scale: $U_\\infty=(93.009,6.161,0)$ m/s, $\\nu=1.56\\times10^{-5}$ m²/s, fields `U`, `p`, `phi`, `nut`, `k`, `omega`.\n", + "- OpenFOAM v14 momentum predictor source: `OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C`.\n", + "- The real predictor assembles\n", + "\n", + "$$\n", + "\\texttt{fvm::ddt(U)} + \\texttt{fvm::div(phi,U)} + \\texttt{momentumTransport->divDevSigma(U)}\n", + "= \\texttt{fvModels().source(U)}\n", + "$$\n", + "\n", + "then solves\n", + "\n", + "$$\n", + "\\texttt{UEqn == -fvc::grad(p)}.\n", + "$$\n", + "\n", + "For the hand calculation, keep one velocity component, ignore time/MRF/source/non-orthogonal details, and replace the viscous/turbulent stress term by scalar diffusion with\n", + "\n", + "$$\n", + "\\Gamma = \\nu + \\nu_t.\n", + "$$\n", + "\n", + "For a cell $P$, use the residual convention\n", + "\n", + "$$\n", + "R_P =\n", + "\\sum_f \\underbrace{\\phi_f U_f}_{\\text{convection leaving cell}}\n", + "-\n", + "\\sum_f \\underbrace{\\Gamma_f \\nabla U_f\\cdot S_f}_{\\text{diffusion leaving cell}}\n", + "+\n", + "\\sum_f \\underbrace{p_f S_{f,x}}_{\\text{pressure-gradient contribution}}.\n", + "$$\n", + "\n", + "The equation wants $R_P=0$. A face loop is bookkeeping for these three numbers.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "176670ce", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:22:08.071527Z", + "iopub.status.busy": "2026-07-24T06:22:08.071431Z", + "iopub.status.idle": "2026-07-24T06:22:08.076755Z", + "shell.execute_reply": "2026-07-24T06:22:08.076272Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "internal face: P -> N\n", + "AirfRANS anchor: U_inf=(93.009, 6.161, 0.0) m/s, nu=1.560e-05 m^2/s\n", + "face flux phi_f = 91\n", + "upwind U_f = 92\n", + "\n", + "convection owner P 8372 | neighbour N -8372\n", + "diffusion owner P 0.0400312 | neighbour N -0.0400312\n", + "pressure owner P 0.15 | neighbour N -0.15\n", + "residual owner P 8372.19 | neighbour N -8372.19\n", + "\n", + "conservation check: R_P + R_N = 0\n" + ] + } + ], + "source": [ + "import math\n", + "\n", + "# Real AirfRANS scale, kept only to anchor the toy numbers.\n", + "U_INF = (93.00914503999995, 6.161356013756317, 0.0)\n", + "NU = 1.56e-5\n", + "\n", + "# Toy two-cell state. P is the OpenFOAM owner, N is the neighbour.\n", + "# Face area vector S points from P to N.\n", + "U_P = 92.0 # x-velocity in owner cell P [m/s]\n", + "U_N = 90.0 # x-velocity in neighbour cell N [m/s]\n", + "p_P = 0.20 # incompressible pressure p/rho in P [m^2/s^2]\n", + "p_N = 0.10 # incompressible pressure p/rho in N [m^2/s^2]\n", + "S = 1.0 # face area vector x-component, owner-outward [m^2]\n", + "d = 1.0 # owner-to-neighbour center distance [m]\n", + "Gamma = NU + 2e-2 # nu + toy turbulent viscosity [m^2/s]\n", + "\n", + "# 1) Face flux: surfaceScalarField phi = U_f · S_f.\n", + "U_for_phi = 0.5 * (U_P + U_N)\n", + "phi_f = U_for_phi * S\n", + "\n", + "# 2) Convection: upwind momentum carried through the face.\n", + "U_f = U_P if phi_f >= 0 else U_N\n", + "convection_P = phi_f * U_f\n", + "convection_N = -convection_P\n", + "\n", + "# 3) Diffusion: - Gamma * grad(U) · S.\n", + "grad_U_dot_S_P = (U_N - U_P) / d * S\n", + "diffusion_P = -Gamma * grad_U_dot_S_P\n", + "diffusion_N = -diffusion_P\n", + "\n", + "# 4) Pressure-gradient contribution: p_f * S.\n", + "p_f = 0.5 * (p_P + p_N)\n", + "pressure_P = p_f * S\n", + "pressure_N = -pressure_P\n", + "\n", + "# 5) Residual contribution from this single internal face.\n", + "R_P_internal = convection_P + diffusion_P + pressure_P\n", + "R_N_internal = convection_N + diffusion_N + pressure_N\n", + "\n", + "assert math.isclose(R_P_internal + R_N_internal, 0.0, abs_tol=1e-12)\n", + "\n", + "def row(label, owner, neighbour):\n", + " print(f\"{label:<13} owner P {owner:>12.6g} | neighbour N {neighbour:>12.6g}\")\n", + "\n", + "print(\"internal face: P -> N\")\n", + "print(f\"AirfRANS anchor: U_inf=({U_INF[0]:.3f}, {U_INF[1]:.3f}, {U_INF[2]:.1f}) m/s, nu={NU:.3e} m^2/s\")\n", + "print(f\"face flux phi_f = {phi_f:.6g}\")\n", + "print(f\"upwind U_f = {U_f:.6g}\")\n", + "print()\n", + "row(\"convection\", convection_P, convection_N)\n", + "row(\"diffusion\", diffusion_P, diffusion_N)\n", + "row(\"pressure\", pressure_P, pressure_N)\n", + "row(\"residual\", R_P_internal, R_N_internal)\n", + "print()\n", + "print(f\"conservation check: R_P + R_N = {R_P_internal + R_N_internal:.6g}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7325d390", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:22:08.077905Z", + "iopub.status.busy": "2026-07-24T06:22:08.077807Z", + "iopub.status.idle": "2026-07-24T06:22:08.081575Z", + "shell.execute_reply": "2026-07-24T06:22:08.080994Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "boundary face on P: noSlip wall\n", + "patch algebra: U_b=0, p_b=p_P, phi_b=0\n", + "\n", + "convection owner P 0\n", + "diffusion owner P 3.68287\n", + "pressure owner P -0.2\n", + "wall total owner P 3.48287\n", + "\n", + "R_P before boundary = 8372.19\n", + "R_P after boundary = 8375.67\n", + "R_N unchanged = -8372.19\n" + ] + } + ], + "source": [ + "# Add one boundary face on the left side of owner cell P.\n", + "# This mimics the airfoil wall idea: noSlip velocity, zeroGradient pressure, no normal flux.\n", + "\n", + "U_wall = 0.0 # noSlip\n", + "p_wall = p_P # zeroGradient pressure -> boundary value equals owner value\n", + "S_wall = -1.0 # owner-outward area vector points left\n", + "area_wall = 1.0\n", + "d_wall = 0.5 # distance from cell center to wall face\n", + "phi_wall = 0.0 # impermeable wall\n", + "\n", + "# Convection through an impermeable wall is zero.\n", + "convection_wall_P = phi_wall * U_wall\n", + "\n", + "# Boundary diffusion uses the patch value instead of a neighbour value.\n", + "grad_U_dot_S_wall = (U_wall - U_P) / d_wall * area_wall\n", + "diffusion_wall_P = -Gamma * grad_U_dot_S_wall\n", + "\n", + "# Pressure term uses the boundary pressure and the boundary area vector.\n", + "pressure_wall_P = p_wall * S_wall\n", + "\n", + "R_wall_P = convection_wall_P + diffusion_wall_P + pressure_wall_P\n", + "R_P_after_wall = R_P_internal + R_wall_P\n", + "R_N_after_wall = R_N_internal\n", + "\n", + "assert R_N_after_wall == R_N_internal\n", + "assert diffusion_wall_P > 0\n", + "\n", + "def one(label, value):\n", + " print(f\"{label:<13} owner P {value:>12.6g}\")\n", + "\n", + "print(\"boundary face on P: noSlip wall\")\n", + "print(\"patch algebra: U_b=0, p_b=p_P, phi_b=0\")\n", + "print()\n", + "one(\"convection\", convection_wall_P)\n", + "one(\"diffusion\", diffusion_wall_P)\n", + "one(\"pressure\", pressure_wall_P)\n", + "one(\"wall total\", R_wall_P)\n", + "print()\n", + "print(f\"R_P before boundary = {R_P_internal:.6g}\")\n", + "print(f\"R_P after boundary = {R_P_after_wall:.6g}\")\n", + "print(f\"R_N unchanged = {R_N_after_wall:.6g}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "ec2cb6d6", + "metadata": {}, + "source": [ + "## What this teaches\n", + "\n", + "The OpenFOAM loop shape is now visible:\n", + "\n", + "| notebook arithmetic | OpenFOAM idea |\n", + "|---|---|\n", + "| `convection_*` | `fvm::div(phi,U)` moves momentum with face flux |\n", + "| `diffusion_*` | `momentumTransport->divDevSigma(U)` / diffusion uses face area and cell spacing |\n", + "| `pressure_*` | `-fvc::grad(p)` appears as face pressure times area vector |\n", + "| internal equal/opposite signs | owner/neighbour addressing conserves internal face transfers |\n", + "| wall-only contribution | a boundary patch replaces the missing neighbour with boundary-condition algebra |\n", + "\n", + "This is not yet SIMPLE, turbulence, pressure correction, or a real airfoil mesh. It is the smallest executable picture of what every finite-volume face loop contributes to the residual.\n", + "\n", + "Good use: change one value at a time — `U_N`, `p_N`, `Gamma`, `U_wall`, or `phi_wall` — predict the sign of the residual change, then rerun.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.12.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/airfrans_openfoam_algorithm_first.ipynb b/notebooks/airfrans_openfoam_algorithm_first.ipynb new file mode 100644 index 0000000..5f66b79 --- /dev/null +++ b/notebooks/airfrans_openfoam_algorithm_first.ipynb @@ -0,0 +1,814 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "232f64cf", + "metadata": {}, + "source": [ + "# AirfRANS in OpenFOAM: algorithm-first, array-visible\n", + "\n", + "Purpose: understand what OpenFOAM is doing in the AirfRANS steady RANS solve, without drowning in C++ framework structure.\n", + "\n", + "Pattern used throughout:\n", + "\n", + "```text\n", + "OpenFOAM phase → algorithmic meaning → equations used → arrays touched → parallelization shape → small numeric probe\n", + "```\n", + "\n", + "This is not a generic CFD derivation. It follows the repo's real OpenFOAM v14 `incompressibleFluid` path used to run a migrated AirfRANS `kOmegaSST` case.\n" + ] + }, + { + "cell_type": "markdown", + "id": "7a6f30ae", + "metadata": {}, + "source": [ + "## 0. Mental model\n", + "\n", + "OpenFOAM is doing a finite-volume SIMPLE solve.\n", + "\n", + "```text\n", + "cells store unknowns\n", + "faces move flux\n", + "matrices encode neighbour coupling\n", + "pressure repairs continuity\n", + "turbulence updates effective viscosity\n", + "```\n", + "\n", + "Core arrays:\n", + "\n", + "| array | meaning |\n", + "|---|---|\n", + "| `V[c]` | cell volume |\n", + "| `C[c,3]` | cell centre |\n", + "| `Sf[f,3]` | oriented face area vector |\n", + "| `owner[f]`, `neighbour[f]` | face-to-cell topology |\n", + "| `phi[f]` | active solve face volume flux; empty front/back faces are bookkeeping for 2D |\n", + "| `U[c,3]` | mean velocity |\n", + "| `p[c]` | kinematic pressure |\n", + "| `k[c]`, `omega[c]`, `nut[c]` | SST turbulence state |\n", + "| `diag`, `upper`, `lower`, `source` | sparse finite-volume matrix storage |\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e6138eb2", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:07.329068Z", + "iopub.status.busy": "2026-07-24T06:27:07.328767Z", + "iopub.status.idle": "2026-07-24T06:27:09.064496Z", + "shell.execute_reply": "2026-07-24T06:27:09.063766Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'simulation': 'airFoil2D_SST_93.213_3.79_0.418_0.0_9.665', 'cells': 283400, 'internal_face_flux_entries': 565419, 'sparse_offdiag_entries': 565419, 'boundary_patches': ['aerofoil', 'freestream', 'frontAndBack'], 'U_shape': (283400, 3), 'p_shape': (283400,), 'phi_internal_shape': (565419,)}\n" + ] + } + ], + "source": [ + "# Fresh-kernel setup. Keep framework setup quarantined here.\n", + "from pathlib import Path\n", + "from contextlib import contextmanager\n", + "import os, sys, shutil, json, re\n", + "\n", + "# Automation can inject an incompatible PYTHONPATH. Drop it before compiled imports.\n", + "pythonpath = os.environ.pop(\"PYTHONPATH\", \"\")\n", + "for entry in pythonpath.split(os.pathsep):\n", + " if entry:\n", + " while entry in sys.path:\n", + " sys.path.remove(entry)\n", + "\n", + "import numpy as np\n", + "\n", + "\n", + "def find_repo_root(start):\n", + " start = Path(start).resolve()\n", + " for p in [start, *start.parents]:\n", + " if (p / \"pyproject.toml\").exists() and (p / \"OpenFOAM-14\").exists():\n", + " return p\n", + " raise RuntimeError(\"repo root not found\")\n", + "\n", + "\n", + "@contextmanager\n", + "def quiet_native_output():\n", + " # Suppress OpenFOAM banner/solver logs; this notebook prints selected facts instead.\n", + " sys.stdout.flush(); sys.stderr.flush()\n", + " devnull = os.open(os.devnull, os.O_WRONLY)\n", + " saved_out = os.dup(1)\n", + " saved_err = os.dup(2)\n", + " try:\n", + " os.dup2(devnull, 1)\n", + " os.dup2(devnull, 2)\n", + " yield\n", + " finally:\n", + " os.dup2(saved_out, 1)\n", + " os.dup2(saved_err, 2)\n", + " os.close(saved_out)\n", + " os.close(saved_err)\n", + " os.close(devnull)\n", + "\n", + "\n", + "def q(call, *args, **kwargs):\n", + " with quiet_native_output():\n", + " return call(*args, **kwargs)\n", + "\n", + "\n", + "ROOT = find_repo_root(Path.cwd())\n", + "os.chdir(ROOT)\n", + "sys.path.insert(0, str(ROOT / \"scripts\"))\n", + "\n", + "from openfoam_env import apply_openfoam_env\n", + "from prepare_airfrans_stepper_case import DEFAULT_SOURCE, prepare_case\n", + "\n", + "apply_openfoam_env()\n", + "import foam_stepper as foam\n", + "\n", + "WORK = ROOT / \"tmp\" / \"airfrans_openfoam_algorithm_first_notebook\"\n", + "CASE = WORK / \"airfrans_v14\"\n", + "SOURCE = DEFAULT_SOURCE\n", + "\n", + "# Rebuild the migrated case for every full notebook execution.\n", + "if CASE.exists():\n", + " shutil.rmtree(CASE)\n", + "WORK.mkdir(parents=True, exist_ok=True)\n", + "meta = prepare_case(SOURCE, CASE, end_time=1)\n", + "\n", + "with quiet_native_output():\n", + " stepper = foam.Case(CASE).make_stepper()\n", + " mesh = stepper.mesh()\n", + " fields = stepper.fields()\n", + "\n", + "# Plain arrays used by the rest of the notebook.\n", + "V = np.asarray(mesh.V)\n", + "C = np.asarray(mesh.C)\n", + "Cf = np.asarray(mesh.Cf)\n", + "Sf = np.asarray(mesh.Sf)\n", + "magSf = np.asarray(mesh.magSf)\n", + "owner = np.asarray(mesh.owner, dtype=np.int64)\n", + "neighbour = np.asarray(mesh.neighbour, dtype=np.int64)\n", + "patches = list(mesh.boundary)\n", + "\n", + "U0 = np.asarray(fields[\"U\"].internal)\n", + "p0 = np.asarray(fields[\"p\"].internal)\n", + "phi0 = np.asarray(fields[\"phi\"].internal)\n", + "k0 = np.asarray(fields[\"k\"].internal)\n", + "omega0 = np.asarray(fields[\"omega\"].internal)\n", + "nut0 = np.asarray(fields[\"nut\"].internal)\n", + "phi_field0 = fields[\"phi\"]\n", + "\n", + "print({\n", + " \"simulation\": meta.simulation,\n", + " \"cells\": int(V.size),\n", + " \"internal_face_flux_entries\": int(phi0.size),\n", + " \"sparse_offdiag_entries\": int(neighbour.size),\n", + " \"boundary_patches\": [patch.name for patch in patches],\n", + " \"U_shape\": U0.shape,\n", + " \"p_shape\": p0.shape,\n", + " \"phi_internal_shape\": phi0.shape,\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "763c6a18", + "metadata": {}, + "source": [ + "## 1. Case contract: what algorithm OpenFOAM has been asked to run\n", + "\n", + "Before thinking about kernels, read the dictionaries as the numerical contract:\n", + "\n", + "- `controlDict`: steady run controls and selected solver;\n", + "- `fvSchemes`: discrete operators, interpolation, gradients, divergence, laplacians;\n", + "- `fvSolution`: linear solvers, SIMPLE controls, relaxation;\n", + "- initial fields: boundary conditions and starting values;\n", + "- `momentumTransport`: RAS model choice, here `kOmegaSST`.\n", + "\n", + "`frontAndBack` is an OpenFOAM `empty` patch. It matters for declaring the case 2D, but it does not contribute active face-flux work in the solve view used below.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "eadd8926", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.065740Z", + "iopub.status.busy": "2026-07-24T06:27:09.065631Z", + "iopub.status.idle": "2026-07-24T06:27:09.069646Z", + "shell.execute_reply": "2026-07-24T06:27:09.069229Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "case\n", + "{'solver': 'incompressibleFluid', 'endTime': '1', 'deltaT': '1', 'RAS_model': 'kOmegaSST', 'freestream_speed': 93.213, 'alpha_deg': 3.79, 'Re': 5975192.3}\n", + "\n", + "patches\n", + "{'name': 'aerofoil', 'type': 'wall', 'active_faces_in_stepper_view': 1026}\n", + "{'name': 'freestream', 'type': 'patch', 'active_faces_in_stepper_view': 1736}\n", + "{'name': 'frontAndBack', 'type': 'empty', 'active_faces_in_stepper_view': 0}\n", + "frontAndBack is an empty 2D patch; it has no active solve-flux faces here.\n", + "\n", + "numerics\n", + "{'has_SIMPLE_block': True, 'has_div_phi_U_scheme': True, 'has_laplacian_schemes': True, 'has_relaxationFactors': True}\n" + ] + } + ], + "source": [ + "def assignment(text, key, default=None):\n", + " m = re.search(rf\"^\\s*{re.escape(key)}\\s+([^;]+);\", text, flags=re.MULTILINE)\n", + " return default if m is None else m.group(1).strip()\n", + "\n", + "\n", + "def contains_line(text, needle):\n", + " return any(needle in line for line in text.splitlines())\n", + "\n", + "control = (CASE / \"system/controlDict\").read_text(errors=\"replace\")\n", + "schemes = (CASE / \"system/fvSchemes\").read_text(errors=\"replace\")\n", + "solution = (CASE / \"system/fvSolution\").read_text(errors=\"replace\")\n", + "transport = (CASE / \"constant/momentumTransport\").read_text(errors=\"replace\")\n", + "\n", + "patch_rows = []\n", + "for patch in patches:\n", + " patch_rows.append((patch.name, patch.type, int(patch.size), int(patch.start)))\n", + "\n", + "print(\"case\")\n", + "print({\n", + " \"solver\": assignment(control, \"solver\"),\n", + " \"endTime\": assignment(control, \"endTime\"),\n", + " \"deltaT\": assignment(control, \"deltaT\"),\n", + " \"RAS_model\": assignment(transport, \"model\"),\n", + " \"freestream_speed\": meta.u_inf,\n", + " \"alpha_deg\": round(meta.alpha_deg, 6),\n", + " \"Re\": round(meta.reynolds, 1),\n", + "})\n", + "\n", + "print(\"\\npatches\")\n", + "for row in patch_rows:\n", + " print({\"name\": row[0], \"type\": row[1], \"active_faces_in_stepper_view\": row[2]})\n", + "print(\"frontAndBack is an empty 2D patch; it has no active solve-flux faces here.\")\n", + "\n", + "print(\"\\nnumerics\")\n", + "print({\n", + " \"has_SIMPLE_block\": \"SIMPLE\" in solution,\n", + " \"has_div_phi_U_scheme\": contains_line(schemes, \"div(phi,U)\"),\n", + " \"has_laplacian_schemes\": \"laplacianSchemes\" in schemes,\n", + " \"has_relaxationFactors\": \"relaxationFactors\" in solution,\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "943203bb", + "metadata": {}, + "source": [ + "## 2. The actual OpenFOAM solve order\n", + "\n", + "For this repo's OpenFOAM v14 path, `simpleFoam` maps to `foamRun -solver incompressibleFluid`.\n", + "The relevant algorithmic order is:\n", + "\n", + "```text\n", + "pre_solve\n", + "advance_time\n", + "begin SIMPLE/PIMPLE iteration\n", + " fv_models_correct\n", + " pre_predictor\n", + " momentum_transport_predictor\n", + " assemble momentum terms\n", + " assemble UEqn\n", + " relax UEqn\n", + " constrain UEqn\n", + " solve momentum predictor\n", + " compute pressure inputs: rAU, HbyA, phiHbyA\n", + " assemble pEqn\n", + " solve pEqn\n", + " correct phi, p, U\n", + " momentum_transport_corrector # k-omega SST: omega, k, nut\n", + "end iteration\n", + "post_solve\n", + "```\n", + "\n", + "Parallel intuition:\n", + "\n", + "```text\n", + "assembly is mostly face/cell parallel\n", + "linear solves are global iterative kernels\n", + "boundary conditions are patch kernels\n", + "residuals/convergence are reductions\n", + "phase boundaries are synchronization points\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d13855ca", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.070871Z", + "iopub.status.busy": "2026-07-24T06:27:09.070736Z", + "iopub.status.idle": "2026-07-24T06:27:09.080021Z", + "shell.execute_reply": "2026-07-24T06:27:09.079575Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'initial_continuity_residual': {'Linf': 0.061028931972296335, 'L1': 20.391531263432356}, 'note': 'Signed internal owner/neighbour flux plus boundary patch flux into each cell.'}\n" + ] + } + ], + "source": [ + "def continuity_residual_from_phi(phi_field, owner, neighbour, patches, n_cells):\n", + " \"\"\"Signed flux sum per cell, including boundary patch fluxes.\"\"\"\n", + " internal_phi = np.asarray(phi_field.internal)\n", + " r = np.zeros(n_cells, dtype=internal_phi.dtype)\n", + "\n", + " np.add.at(r, owner, internal_phi[:len(owner)])\n", + " np.add.at(r, neighbour, -internal_phi[:len(neighbour)])\n", + "\n", + " for patch in patches:\n", + " values = np.asarray(phi_field.boundary[patch.name].values).reshape(-1)\n", + " if values.size == 0:\n", + " continue\n", + " face_cells = np.asarray(patch.face_cells, dtype=np.int64)[:values.size]\n", + " np.add.at(r, face_cells, values)\n", + " return r\n", + "\n", + "\n", + "def norm_report(x):\n", + " x = np.asarray(x)\n", + " return {\n", + " \"Linf\": float(np.max(np.abs(x))) if x.size else 0.0,\n", + " \"L1\": float(np.sum(np.abs(x))) if x.size else 0.0,\n", + " }\n", + "\n", + "mass0 = continuity_residual_from_phi(phi_field0, owner, neighbour, patches, len(V))\n", + "print({\n", + " \"initial_continuity_residual\": norm_report(mass0),\n", + " \"note\": \"Signed internal owner/neighbour flux plus boundary patch flux into each cell.\",\n", + "})\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "3f5ddd40", + "metadata": {}, + "source": [ + "## 3. Momentum predictor\n", + "\n", + "OpenFOAM operation, stripped to computation:\n", + "\n", + "```text\n", + "UEqn = ddt(U) + div(phi, U) + turbulent_stress_divergence(U, nut) == sources\n", + "relax UEqn\n", + "apply matrix/boundary constraints\n", + "solve UEqn == -grad(p)\n", + "```\n", + "\n", + "Sparse-row view:\n", + "\n", + "$$\n", + "A_c U_c + \\sum_{n\\in N(c)} A_{cn}U_n = b_c - V_c(\\nabla p)_c\n", + "$$\n", + "\n", + "Arrays touched:\n", + "\n", + "```text\n", + "read: U, p, phi, nut, V, Sf, owner, neighbour, boundary fields, fvSchemes, fvSolution\n", + "write: UEqn.diag, UEqn.upper/lower, UEqn.source, possibly U\n", + "```\n", + "\n", + "Parallel shape:\n", + "\n", + "```text\n", + "per-face work: convection/diffusion coupling across owner-neighbour\n", + "per-cell work: diagonal/source accumulation and explicit terms\n", + "solver work: sparse matrix-vector iterations plus reductions\n", + "hazard: face contributions scatter into two cells unless accumulation is organized carefully\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "57ce4919", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.081243Z", + "iopub.status.busy": "2026-07-24T06:27:09.081153Z", + "iopub.status.idle": "2026-07-24T06:27:09.322109Z", + "shell.execute_reply": "2026-07-24T06:27:09.321878Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'phases_reached': ['pre_solve', 'advance_time', 'begin_pimple_iteration', 'fv_models_correct', 'pre_predictor', 'momentum_transport_predict', 'assemble_momentum_terms', 'assemble_UEqn'], 'momentum_terms': ['assemble_momentum_ddt', 'assemble_momentum_div_phi_U', 'assemble_momentum_divDevSigma', 'assemble_momentum_sources', 'assemble_momentum_MRF_DDt', 'assemble_momentum_pressure_rhs_grad_p'], 'diag': (283400,), 'upper': (565419,), 'lower': (565419,), 'source': (283400, 3), 'H': (283400, 3), 'diag_first_5': [4.5674015979225775, 4.426112149473814, 4.2788585852295125, 4.134855363049338, 3.9941324145628894]}\n" + ] + } + ], + "source": [ + "phase_names = []\n", + "for method in [\n", + " stepper.pre_solve,\n", + " stepper.advance_time,\n", + " stepper.begin_pimple_iteration,\n", + " stepper.fv_models_correct,\n", + " stepper.pre_predictor,\n", + " stepper.momentum_transport_predictor,\n", + "]:\n", + " result = q(method)\n", + " phase_names.append(result.name)\n", + "\n", + "terms = q(stepper.assemble_momentum_terms)\n", + "UEqn_result = q(stepper.assemble_momentum_matrix)\n", + "UEqn = UEqn_result.outputs[\"UEqn\"]\n", + "phase_names.extend([terms.name, UEqn_result.name])\n", + "\n", + "A_U = np.asarray(UEqn.diag)\n", + "upper_U = None if UEqn.upper is None else np.asarray(UEqn.upper)\n", + "lower_U = None if UEqn.lower is None else np.asarray(UEqn.lower)\n", + "b_U = np.asarray(UEqn.source)\n", + "H_U = None if UEqn.H is None else np.asarray(UEqn.H.internal)\n", + "\n", + "print({\n", + " \"phases_reached\": phase_names,\n", + " \"momentum_terms\": [t[\"name\"] for t in terms.outputs[\"terms\"]],\n", + " \"diag\": A_U.shape,\n", + " \"upper\": None if upper_U is None else upper_U.shape,\n", + " \"lower\": None if lower_U is None else lower_U.shape,\n", + " \"source\": b_U.shape,\n", + " \"H\": None if H_U is None else H_U.shape,\n", + " \"diag_first_5\": A_U[:5].tolist(),\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "63757c15", + "metadata": {}, + "source": [ + "## 4. One face as kernel anatomy, not serial control flow\n", + "\n", + "The one-face view is useful only as a stencil exemplar.\n", + "It should read as:\n", + "\n", + "```text\n", + "this is one work item shape; many faces run in parallel\n", + "```\n", + "\n", + "For an internal face `f`, a face kernel typically reads both adjacent cells and writes contributions to both matrix rows:\n", + "\n", + "```text\n", + "o = owner[f]\n", + "n = neighbour[f]\n", + "read: U[o], U[n], C[o], C[n], Sf[f], phi[f], nut[o], nut[n]\n", + "write: row contribution for o and row contribution for n\n", + "```\n", + "\n", + "Race risk appears if many faces scatter-add into the same cell row at once.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "39d467a5", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.323799Z", + "iopub.status.busy": "2026-07-24T06:27:09.323707Z", + "iopub.status.idle": "2026-07-24T06:27:09.325983Z", + "shell.execute_reply": "2026-07-24T06:27:09.325697Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'face': 282709, 'owner_cell': 141545, 'neighbour_cell': 141546, 'Sf': [-0.009744034299999982, -0.0027874465999999654, 0.0], 'magSf': 0.010134893338729693, 'phi_before': -0.9234587503553671, 'U_owner_before': [93.00914503999995, 6.161356013756317, 0.0], 'U_neighbour_before': [93.00914503999995, 6.161356013756317, 0.0], 'center_distance': 0.001573663286642463}\n" + ] + } + ], + "source": [ + "f = int(len(neighbour) // 2)\n", + "o = int(owner[f])\n", + "n = int(neighbour[f])\n", + "\n", + "face_probe = {\n", + " \"face\": f,\n", + " \"owner_cell\": o,\n", + " \"neighbour_cell\": n,\n", + " \"Sf\": Sf[f].tolist(),\n", + " \"magSf\": float(magSf[f]),\n", + " \"phi_before\": float(phi0[f]),\n", + " \"U_owner_before\": U0[o].tolist(),\n", + " \"U_neighbour_before\": U0[n].tolist(),\n", + " \"center_distance\": float(np.linalg.norm(C[n] - C[o])),\n", + "}\n", + "print(face_probe)\n" + ] + }, + { + "cell_type": "markdown", + "id": "906e541d", + "metadata": {}, + "source": [ + "## 5. Pressure correction\n", + "\n", + "OpenFOAM operation, stripped to computation:\n", + "\n", + "```text\n", + "rAU = 1 / UEqn.A\n", + "HbyA = constrained(rAU * UEqn.H)\n", + "phiHbyA = flux(HbyA) + time/mesh correction\n", + "apply pressure boundary consistency\n", + "pEqn = laplacian(rAU, p) == div(phiHbyA)\n", + "solve pEqn\n", + "phi = phiHbyA - pEqn.flux()\n", + "p.relax()\n", + "U = HbyA - rAU * grad(p)\n", + "correct U boundary conditions\n", + "```\n", + "\n", + "Why this exists:\n", + "\n", + "```text\n", + "momentum predicts U\n", + "predicted U may violate continuity\n", + "pressure solve computes a flux correction\n", + "corrected phi is the flux field OpenFOAM uses for continuity-error accounting\n", + "U is then corrected to be consistent with that pressure/flux repair\n", + "```\n", + "\n", + "Parallel shape:\n", + "\n", + "```text\n", + "per-cell: rAU, HbyA\n", + "per-face: interpolate HbyA/rAU and compute phiHbyA\n", + "solver: pressure Laplacian iterations are global\n", + "per-face: corrected phi\n", + "per-cell: corrected U\n", + "reduction: continuity errors\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "958d0625", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.327451Z", + "iopub.status.busy": "2026-07-24T06:27:09.327360Z", + "iopub.status.idle": "2026-07-24T06:27:09.655600Z", + "shell.execute_reply": "2026-07-24T06:27:09.655213Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'matrix_steps': ['relax_UEqn', 'constrain_UEqn', 'solve_UEqn'], 'pressure_steps': ['compute_pressure_inputs', 'assemble_pEqn'], 'rAU': (283400,), 'HbyA': (283400, 3), 'phiHbyA': (565419,), 'p_diag': (283400,), 'p_upper': (565419,), 'p_source': (283400,), 'rAU_first_5': [0.00026755862048551105, 0.00024708843305873933, 0.00022836470465003848, 0.00021125319224392247, 0.00019560221178537135]}\n" + ] + } + ], + "source": [ + "relax_result = q(stepper.relax_matrix)\n", + "constrain_result = q(stepper.constrain_matrix)\n", + "momentum_solve = q(stepper.solve_momentum)\n", + "pressure_inputs = q(stepper.compute_pressure_inputs)\n", + "pEqn_result = q(stepper.assemble_pressure_matrix)\n", + "pEqn = pEqn_result.outputs[\"pEqn\"]\n", + "\n", + "rAU = np.asarray(pressure_inputs.outputs[\"rAU\"].internal)\n", + "HbyA = np.asarray(pressure_inputs.outputs[\"HbyA\"].internal)\n", + "phiHbyA = np.asarray(pressure_inputs.outputs[\"phiHbyA\"].internal)\n", + "A_p = np.asarray(pEqn.diag)\n", + "upper_p = None if pEqn.upper is None else np.asarray(pEqn.upper)\n", + "b_p = np.asarray(pEqn.source)\n", + "\n", + "print({\n", + " \"matrix_steps\": [relax_result.name, constrain_result.name, momentum_solve.name],\n", + " \"pressure_steps\": [pressure_inputs.name, pEqn_result.name],\n", + " \"rAU\": rAU.shape,\n", + " \"HbyA\": HbyA.shape,\n", + " \"phiHbyA\": phiHbyA.shape,\n", + " \"p_diag\": A_p.shape,\n", + " \"p_upper\": None if upper_p is None else upper_p.shape,\n", + " \"p_source\": b_p.shape,\n", + " \"rAU_first_5\": rAU[:5].tolist(),\n", + "})\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ab30847e", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:09.656945Z", + "iopub.status.busy": "2026-07-24T06:27:09.656826Z", + "iopub.status.idle": "2026-07-24T06:27:12.376771Z", + "shell.execute_reply": "2026-07-24T06:27:12.376091Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'pressure_steps': ['solve_pEqn', 'correct_velocity_pressure_flux'], 'changed_fields': ['p', 'U', 'phi'], 'delta_U_Linf': 142.80037348998195, 'delta_p_Linf': 139306.85715654117, 'delta_phi_Linf': 0.12004663628376555, 'continuity_after_pressure': {'Linf': 0.026893021480056893, 'L1': 1.0664099985737665}}\n" + ] + } + ], + "source": [ + "pressure_solve = q(stepper.solve_pressure)\n", + "correct_result = q(stepper.correct_velocity_pressure_flux)\n", + "\n", + "fields_after_pressure = stepper.fields()\n", + "U_after_pressure = np.asarray(fields_after_pressure[\"U\"].internal)\n", + "p_after_pressure = np.asarray(fields_after_pressure[\"p\"].internal)\n", + "phi_after_pressure_field = fields_after_pressure[\"phi\"]\n", + "phi_after_pressure = np.asarray(phi_after_pressure_field.internal)\n", + "\n", + "mass_after_pressure = continuity_residual_from_phi(phi_after_pressure_field, owner, neighbour, patches, len(V))\n", + "\n", + "print({\n", + " \"pressure_steps\": [pressure_solve.name, correct_result.name],\n", + " \"changed_fields\": correct_result.changed_fields,\n", + " \"delta_U_Linf\": float(np.max(np.abs(U_after_pressure - U0))),\n", + " \"delta_p_Linf\": float(np.max(np.abs(p_after_pressure - p0))),\n", + " \"delta_phi_Linf\": float(np.max(np.abs(phi_after_pressure - phi0))),\n", + " \"continuity_after_pressure\": norm_report(mass_after_pressure),\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "4c384cfc", + "metadata": {}, + "source": [ + "## 6. Turbulence corrector: k-omega SST\n", + "\n", + "OpenFOAM's `kOmegaSST` corrector does this computationally:\n", + "\n", + "```text\n", + "compute grad(U)\n", + "compute strain magnitude S2\n", + "compute production G from nut and grad(U)\n", + "update omega wall coefficients\n", + "compute SST blending functions F1, F2/F23\n", + "assemble and solve omega equation\n", + "bound omega\n", + "assemble and solve k equation\n", + "bound k and omega\n", + "update nut = a1*k / max(a1*omega, b1*F2*sqrt(S2))\n", + "apply nut boundary conditions/constraints\n", + "```\n", + "\n", + "For parallelization:\n", + "\n", + "```text\n", + "grad(U): face/cell stencil\n", + "production/S2: per-cell\n", + "omega matrix: face/cell assembly + sparse solve\n", + "k matrix: face/cell assembly + sparse solve\n", + "nut update: embarrassingly per-cell, plus patch kernels for wall functions\n", + "```\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d8e88122", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-24T06:27:12.378174Z", + "iopub.status.busy": "2026-07-24T06:27:12.378067Z", + "iopub.status.idle": "2026-07-24T06:27:12.634993Z", + "shell.execute_reply": "2026-07-24T06:27:12.634592Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'final_steps': ['momentum_transport_correct', 'end_pimple_iteration', 'post_solve'], 'turbulence_changed_fields': ['viscosity', 'momentumTransport'], 'delta_k_Linf': 2.9020790511255652e-08, 'delta_omega_Linf': 1718225865.8661606, 'delta_nut_Linf': 3.1199999716434326e-09, 'final_continuity_residual': {'Linf': 0.026893021480056893, 'L1': 1.0664099985737665}, 'omega_delta_note': 'Linf is wall-dominated because omega wall coefficients update strongly.'}\n" + ] + } + ], + "source": [ + "turbulence_result = q(stepper.momentum_transport_corrector)\n", + "end_result = q(stepper.end_pimple_iteration)\n", + "post_result = q(stepper.post_solve, write=False)\n", + "\n", + "fields1 = stepper.fields()\n", + "U1 = np.asarray(fields1[\"U\"].internal)\n", + "p1 = np.asarray(fields1[\"p\"].internal)\n", + "phi_field1 = fields1[\"phi\"]\n", + "phi1 = np.asarray(phi_field1.internal)\n", + "k1 = np.asarray(fields1[\"k\"].internal)\n", + "omega1 = np.asarray(fields1[\"omega\"].internal)\n", + "nut1 = np.asarray(fields1[\"nut\"].internal)\n", + "\n", + "mass1 = continuity_residual_from_phi(phi_field1, owner, neighbour, patches, len(V))\n", + "\n", + "print({\n", + " \"final_steps\": [turbulence_result.name, end_result.name, post_result.name],\n", + " \"turbulence_changed_fields\": turbulence_result.changed_fields,\n", + " \"delta_k_Linf\": float(np.max(np.abs(k1 - k0))),\n", + " \"delta_omega_Linf\": float(np.max(np.abs(omega1 - omega0))),\n", + " \"delta_nut_Linf\": float(np.max(np.abs(nut1 - nut0))),\n", + " \"final_continuity_residual\": norm_report(mass1),\n", + " \"omega_delta_note\": \"Linf is wall-dominated because omega wall coefficients update strongly.\",\n", + "})\n" + ] + }, + { + "cell_type": "markdown", + "id": "a78169fd", + "metadata": {}, + "source": [ + "## 7. Parallelization map\n", + "\n", + "| OpenFOAM algorithm phase | natural work items | writes | synchronization / hazard |\n", + "|---|---|---|---|\n", + "| face flux/interpolation | faces | `phi[f]`, face temporaries | reads owner/neighbour cells |\n", + "| continuity residual | faces or cells | residual per cell | face scatter needs atomics or two-pass accumulation |\n", + "| momentum assembly | faces + cells | sparse matrix rows | owner/neighbour scatter or row-wise gather |\n", + "| matrix relaxation/constraints | cells + patches | matrix rows, boundary coeffs | patch-specific logic |\n", + "| momentum solve | sparse rows | `U` iterations | global reductions each Krylov iteration |\n", + "| pressure-input build | cells + faces | `rAU`, `HbyA`, `phiHbyA` | interpolation crosses faces |\n", + "| pressure assembly/solve | faces + sparse rows | pressure matrix, `p` iterations | global solve/reductions |\n", + "| flux/velocity correction | faces + cells | `phi`, `U` | pressure field must be solved first |\n", + "| SST corrector | cells + faces + patches | `omega`, `k`, `nut` | two scalar solves, wall-function patches |\n", + "\n", + "Main lesson for GPU work:\n", + "\n", + "```text\n", + "OpenFOAM's loop is phase-serial.\n", + "Inside each phase, most assembly/update work is data-parallel.\n", + "The sparse solvers and reductions are the major global synchronization points.\n", + "```\n" + ] + }, + { + "cell_type": "markdown", + "id": "3737d955", + "metadata": {}, + "source": [ + "## 8. What this notebook should let you explain\n", + "\n", + "After working through it, you should be able to say:\n", + "\n", + "1. which OpenFOAM phase builds the momentum matrix;\n", + "2. why pressure correction exists;\n", + "3. why `phi` is central to continuity;\n", + "4. where boundary conditions alter matrices/fields;\n", + "5. which parts are face-parallel, cell-parallel, patch-parallel, or globally synchronized;\n", + "6. why a one-face/one-cell probe is a kernel stencil example, not the serial algorithm.\n", + "\n", + "If a future section cannot be described as `phase → arrays → kernel shape`, it is probably framework spandrel and should be cut.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.12.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/airfrans_stepper_full_detail_learning_tool.ipynb b/notebooks/airfrans_stepper_full_detail_learning_tool.ipynb new file mode 100644 index 0000000..b1fa7b6 --- /dev/null +++ b/notebooks/airfrans_stepper_full_detail_learning_tool.ipynb @@ -0,0 +1,7597 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "full-detail-00", + "metadata": {}, + "source": [ + "# AirfRANS RANS simulation full-detail microscope\n", + "\n", + "This notebook is a full-detail companion to `airfrans_stepper_learning_tool.ipynb` for the same real AirfRANS OpenFOAM case:\n", + "\n", + "`airFoil2D_SST_93.213_3.79_0.418_0.0_9.665`\n", + "\n", + "The goal is to expose the simulation without silently hiding large structures:\n", + "\n", + "1. identify the physical problem encoded by the AirfRANS case;\n", + "2. inspect how OpenFOAM stores mesh topology, patches, fields, and boundary conditions;\n", + "3. display full tensor shapes, dtypes, entity counts, and truncation policy every time values are too large for a notebook cell;\n", + "4. visualize every large field or mesh object through histograms, binned spatial maps, and sparse-graph density plots so every entity contributes even when raw value text is truncated;\n", + "5. step through one steady SIMPLE iteration with the Python OpenFOAM stepper;\n", + "6. inspect each intermediate object: `MeshView`, `FieldView`, `PatchFieldView`, `MatrixView`, `SolveResult`, and `TransformResult`;\n", + "7. connect each object back to finite-volume RANS mechanics.\n", + "\n", + "Output contract for this full-detail edition: raw value displays may truncate values to keep cells readable, but every display keeps the exact shape, dtype, size, and entity count. Visualizations aggregate complete arrays unless explicitly labeled as a selected-row view for ragged OpenFOAM lists.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "full-detail-01", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:17.543442Z", + "iopub.status.busy": "2026-07-22T20:00:17.543233Z", + "iopub.status.idle": "2026-07-22T20:00:17.550312Z", + "shell.execute_reply": "2026-07-22T20:00:17.549370Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cwd=/home/aaron/data/openFOAM-RANS-to-GPU/notebooks\n", + "repo=/home/aaron/data/openFOAM-RANS-to-GPU\n", + "kernel_python=/home/aaron/data/openFOAM-RANS-to-GPU/.venv/bin/python\n", + "project_python=/home/aaron/data/openFOAM-RANS-to-GPU/.venv/bin/python\n", + "raw_case=/home/aaron/data/airfrans/data/raw/OF_dataset/airFoil2D_SST_93.213_3.79_0.418_0.0_9.665\n", + "raw_case_exists=True\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "import os\n", + "import re\n", + "import shutil\n", + "import subprocess\n", + "import sys\n", + "\n", + "\n", + "def find_repo_root(start: Path) -> Path:\n", + " \"\"\"Find the repo even when Jupyter starts in ./notebooks.\"\"\"\n", + " for candidate in (start.resolve(), *start.resolve().parents):\n", + " if (candidate / \"pyproject.toml\").exists() and (candidate / \"OpenFOAM-14\").exists() and (candidate / \"scripts\").exists():\n", + " return candidate\n", + " raise RuntimeError(f\"Could not find openFOAM-RANS-to-GPU repo root from {start}\")\n", + "\n", + "\n", + "def drop_ambient_pythonpath() -> None:\n", + " \"\"\"Avoid accidentally importing packages from an external PYTHONPATH.\"\"\"\n", + " pythonpath = os.environ.pop(\"PYTHONPATH\", \"\")\n", + " for entry in pythonpath.split(os.pathsep):\n", + " if not entry:\n", + " continue\n", + " while entry in sys.path:\n", + " sys.path.remove(entry)\n", + "\n", + "\n", + "ROOT = find_repo_root(Path.cwd())\n", + "PYTHON = ROOT / \".venv/bin/python\"\n", + "if not PYTHON.exists():\n", + " PYTHON = Path(sys.executable)\n", + "SCRIPTS = ROOT / \"scripts\"\n", + "if str(SCRIPTS) not in sys.path:\n", + " sys.path.insert(0, str(SCRIPTS))\n", + "\n", + "drop_ambient_pythonpath()\n", + "\n", + "RAW_CASE = ROOT.parent / \"airfrans/data/raw/OF_dataset/airFoil2D_SST_93.213_3.79_0.418_0.0_9.665\"\n", + "WORK = ROOT / \"tmp/airfrans_stepper_full_detail_learning_tool\"\n", + "CASE = WORK / \"split_case\"\n", + "HIGH_LEVEL_CASE = WORK / \"high_level_case\"\n", + "\n", + "print(f\"cwd={Path.cwd()}\")\n", + "print(f\"repo={ROOT}\")\n", + "print(f\"kernel_python={sys.executable}\")\n", + "print(f\"project_python={PYTHON}\")\n", + "print(f\"raw_case={RAW_CASE}\")\n", + "print(f\"raw_case_exists={RAW_CASE.exists()}\")\n", + "assert RAW_CASE.exists(), RAW_CASE\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-02", + "metadata": {}, + "source": [ + "## Notebook map\n", + "\n", + "The cells are ordered like the solver:\n", + "\n", + "```mermaid\n", + "flowchart TD\n", + " A[Raw AirfRANS case] --> B[v14 migrated working case]\n", + " B --> C[MeshView and boundary patches]\n", + " C --> D[FieldRegistryView: U, p, phi, nut, k, omega]\n", + " D --> E[preSolve and SIMPLE loop]\n", + " E --> F[Momentum terms and UEqn]\n", + " F --> G[Solve U]\n", + " G --> H[Pressure inputs and pEqn]\n", + " H --> I[Solve p and update phi]\n", + " I --> J[Correct U, p, phi]\n", + " J --> K[Correct turbulence: k, omega, nut]\n", + " K --> L[Parity sanity check]\n", + "```\n", + "\n", + "The key idea: OpenFOAM advances the simulation by repeatedly transforming named fields and matrices. The stepper lets Python stop after each transformation and inspect the exact native OpenFOAM objects.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "full-detail-03", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:17.552136Z", + "iopub.status.busy": "2026-07-22T20:00:17.551999Z", + "iopub.status.idle": "2026-07-22T20:00:18.009382Z", + "shell.execute_reply": "2026-07-22T20:00:18.008990Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "foam_stepper version=0.2.0\n" + ] + } + ], + "source": [ + "try:\n", + " import json\n", + " import math\n", + " from dataclasses import asdict\n", + "\n", + " import numpy as np\n", + " from IPython.display import Markdown, display\n", + "\n", + " from prepare_airfrans_stepper_case import (\n", + " assignment,\n", + " prepare_case,\n", + " read_text,\n", + " vector_assignment,\n", + " )\n", + " from openfoam_env import apply_openfoam_env\n", + "\n", + " apply_openfoam_env()\n", + " import foam_stepper as foam\n", + "except Exception as exc:\n", + " raise RuntimeError(\n", + " \"Notebook setup failed. Use the repo .venv kernel if possible: \"\n", + " f\"{PYTHON}. The first cell resolved paths correctly, but the current \"\n", + " \"kernel could not import the numerical/OpenFOAM bindings.\"\n", + " ) from exc\n", + "\n", + "\n", + "def fmt(value, digits: int = 4) -> str:\n", + " if value is None:\n", + " return \"\"\n", + " if isinstance(value, (bool, np.bool_)):\n", + " return str(bool(value))\n", + " if isinstance(value, (int, np.integer)):\n", + " return str(int(value))\n", + " if isinstance(value, (float, np.floating)):\n", + " if not np.isfinite(value):\n", + " return str(value)\n", + " return f\"{float(value):.{digits}g}\"\n", + " return str(value)\n", + "\n", + "\n", + "def md_table(headers, rows) -> Markdown:\n", + " def clean(value):\n", + " return fmt(value).replace(\"|\", \"\\\\|\").replace(\"\\n\", \"
\")\n", + " clean_headers = [clean(header) for header in headers]\n", + " lines = [\"| \" + \" | \".join(clean_headers) + \" |\", \"| \" + \" | \".join([\"---\"] * len(clean_headers)) + \" |\"]\n", + " for row in rows:\n", + " lines.append(\"| \" + \" | \".join(clean(value) for value in row) + \" |\")\n", + " return Markdown(\"\\n\".join(lines))\n", + "\n", + "\n", + "def show_table(title, headers, rows):\n", + " display(Markdown(f\"**{title}**\"))\n", + " display(md_table(headers, rows))\n", + "\n", + "\n", + "def arr_stats(array) -> dict[str, object]:\n", + " arr = np.asarray(array)\n", + " if arr.size == 0:\n", + " return {\"shape\": tuple(arr.shape), \"min\": None, \"max\": None, \"mean\": None, \"l2\": 0.0}\n", + " flat = arr.astype(float, copy=False).reshape(-1)\n", + " return {\n", + " \"shape\": tuple(arr.shape),\n", + " \"min\": float(np.nanmin(flat)),\n", + " \"max\": float(np.nanmax(flat)),\n", + " \"mean\": float(np.nanmean(flat)),\n", + " \"l2\": float(np.linalg.norm(flat)),\n", + " }\n", + "\n", + "\n", + "def stats_row(name, array):\n", + " stats = arr_stats(array)\n", + " return [name, stats[\"shape\"], stats[\"min\"], stats[\"max\"], stats[\"mean\"], stats[\"l2\"]]\n", + "\n", + "\n", + "def source_text(result) -> str:\n", + " source = result.source\n", + " if not source.file:\n", + " return \"native wrapper / OpenFOAM runtime\"\n", + " lines = \"\" if source.lines is None else f\":{source.lines[0]}-{source.lines[1]}\"\n", + " return f\"{source.file}{lines}::{source.function}\"\n", + "\n", + "\n", + "def transform_row(result):\n", + " return [\n", + " result.name,\n", + " result.phase,\n", + " \", \".join(result.changed_fields) or \"—\",\n", + " \", \".join(result.inputs.keys()) or \"—\",\n", + " \", \".join(result.outputs.keys()) or \"—\",\n", + " source_text(result),\n", + " ]\n", + "\n", + "\n", + "def field_summary_row(field):\n", + " stats = arr_stats(field.internal)\n", + " return [field.name, field.kind, field.dimensions, field.entity_kind, field.entity_count, stats[\"shape\"], stats[\"min\"], stats[\"max\"], stats[\"mean\"]]\n", + "\n", + "\n", + "def boundary_field_rows(field):\n", + " rows = []\n", + " for patch_name, patch_field in field.boundary.items():\n", + " stats = arr_stats(patch_field.values)\n", + " rows.append([\n", + " field.name,\n", + " patch_name,\n", + " patch_field.type,\n", + " stats[\"shape\"],\n", + " stats[\"min\"],\n", + " stats[\"max\"],\n", + " patch_field.fixes_value,\n", + " patch_field.assignable,\n", + " patch_field.coupled,\n", + " ])\n", + " return rows\n", + "\n", + "\n", + "def matrix_summary_row(label, matrix):\n", + " diag = arr_stats(matrix.diag)\n", + " source = arr_stats(matrix.source)\n", + " upper_shape = None if matrix.upper is None else tuple(np.asarray(matrix.upper).shape)\n", + " lower_shape = None if matrix.lower is None else tuple(np.asarray(matrix.lower).shape)\n", + " return [\n", + " label,\n", + " matrix.field_name,\n", + " matrix.value_rank,\n", + " matrix.dimensions,\n", + " diag[\"shape\"],\n", + " diag[\"min\"],\n", + " diag[\"max\"],\n", + " source[\"shape\"],\n", + " source[\"l2\"],\n", + " upper_shape,\n", + " lower_shape,\n", + " matrix.diagonal,\n", + " matrix.symmetric,\n", + " matrix.asymmetric,\n", + " ]\n", + "\n", + "\n", + "def field_snapshot(registry, names=(\"U\", \"p\", \"phi\", \"nut\", \"k\", \"omega\")):\n", + " return {name: np.array(registry[name].internal, copy=True) for name in names if name in registry}\n", + "\n", + "\n", + "def delta_rows(before, after, names=None):\n", + " rows = []\n", + " names = names or sorted(set(before) & set(after))\n", + " for name in names:\n", + " if name not in before or name not in after:\n", + " continue\n", + " diff = np.asarray(after[name]) - np.asarray(before[name])\n", + " stats = arr_stats(diff)\n", + " rows.append([name, stats[\"shape\"], stats[\"min\"], stats[\"max\"], stats[\"mean\"], stats[\"l2\"], float(np.max(np.abs(diff))) if diff.size else 0.0])\n", + " return rows\n", + "\n", + "\n", + "def matrix_delta_row(label, before, after):\n", + " diag = np.asarray(after.diag) - np.asarray(before.diag)\n", + " source = np.asarray(after.source) - np.asarray(before.source)\n", + " return [\n", + " label,\n", + " float(np.max(np.abs(diag))) if diag.size else 0.0,\n", + " float(np.linalg.norm(diag.reshape(-1))) if diag.size else 0.0,\n", + " float(np.max(np.abs(source))) if source.size else 0.0,\n", + " float(np.linalg.norm(source.reshape(-1))) if source.size else 0.0,\n", + " ]\n", + "\n", + "\n", + "def solve_result_row(result):\n", + " return [\n", + " result.field_name,\n", + " result.solver_name,\n", + " result.initial_residual,\n", + " result.final_residual,\n", + " result.n_iterations,\n", + " result.converged,\n", + " result.singular,\n", + " ]\n", + "\n", + "print(f\"foam_stepper version={foam.version()}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-04", + "metadata": {}, + "source": [ + "## Full-detail output policy\n", + "\n", + "Large OpenFOAM arrays can be hundreds of thousands of rows long. This notebook does not pretend those arrays are small:\n", + "\n", + "- every raw-array panel prints exact `shape`, `dtype`, `ndim`, and `size` before any value text;\n", + "- value text uses NumPy edge truncation only when a cell would flood the notebook;\n", + "- ragged mesh lists show exact row counts and selected rows with their full row lengths;\n", + "- charts and heatmaps are computed from the full input arrays, not from the displayed edge values;\n", + "- spatial heatmaps use cell or face centres as coordinates, so large tensors can be seen as geometry instead of scrollback.\n", + "\n", + "Tune `FULL_DETAIL_MAX_VALUES`, `FULL_DETAIL_EDGE_ITEMS`, and `FULL_DETAIL_GRID` below if you want denser text or finer binned plots.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "full-detail-05", + "metadata": {}, + "outputs": [], + "source": [ + "from IPython.display import HTML, SVG\n", + "import html\n", + "\n", + "FULL_DETAIL_MAX_VALUES = 256\n", + "FULL_DETAIL_EDGE_ITEMS = 4\n", + "FULL_DETAIL_ROW_ITEMS = 48\n", + "FULL_DETAIL_GRID = 96\n", + "\n", + "np.set_printoptions(\n", + " threshold=FULL_DETAIL_MAX_VALUES,\n", + " edgeitems=FULL_DETAIL_EDGE_ITEMS,\n", + " linewidth=180,\n", + " suppress=False,\n", + ")\n", + "\n", + "\n", + "def _html(value) -> str:\n", + " return html.escape(str(value), quote=False)\n", + "\n", + "\n", + "def shape_text(shape) -> str:\n", + " shape = tuple(int(dim) for dim in shape)\n", + " if not shape:\n", + " return \"scalar\"\n", + " return \" × \".join(f\"{dim:,}\" for dim in shape)\n", + "\n", + "\n", + "def exact_array_meta(array) -> dict[str, object]:\n", + " arr = np.asarray(array)\n", + " return {\n", + " \"shape\": tuple(int(dim) for dim in arr.shape),\n", + " \"shape text\": shape_text(arr.shape),\n", + " \"ndim\": int(arr.ndim),\n", + " \"dtype\": str(arr.dtype),\n", + " \"size\": int(arr.size),\n", + " }\n", + "\n", + "\n", + "def array_panel(name, array, *, max_values=FULL_DETAIL_MAX_VALUES, edgeitems=FULL_DETAIL_EDGE_ITEMS, open=True):\n", + " \"\"\"Display exact array metadata plus truncated value text when needed.\"\"\"\n", + " arr = np.asarray(array)\n", + " meta = exact_array_meta(arr)\n", + " status = \"complete value text\"\n", + " if arr.size > max_values:\n", + " status = (\n", + " f\"TRUNCATED value text; exact shape retained; \"\n", + " f\"size={arr.size:,}; threshold={max_values:,}; edgeitems={edgeitems}\"\n", + " )\n", + " try:\n", + " text = np.array2string(arr, threshold=max_values, edgeitems=edgeitems, max_line_width=180)\n", + " except Exception as exc:\n", + " text = f\"\\nrepr={arr!r}\"\n", + " attr = \" open\" if open else \"\"\n", + " summary = (\n", + " f\"{_html(name)} — shape={_html(meta['shape'])} \"\n", + " f\"({meta['shape text']}), dtype={_html(meta['dtype'])}, size={meta['size']:,}, {status}\"\n", + " )\n", + " display(HTML(\n", + " f\"\"\n", + " f\"{summary}\"\n", + " f\"
\"\n",
+    "        f\"{_html(text)}
\"\n", + " ))\n", + "\n", + "\n", + "def safe_array_panel(name, producer, *, open=False):\n", + " \"\"\"Show an array if an optional view exists; otherwise show the missing reason.\"\"\"\n", + " try:\n", + " value = producer()\n", + " except Exception as exc:\n", + " display(Markdown(f\"`{name}` unavailable: `{type(exc).__name__}: {exc}`\"))\n", + " return None\n", + " if value is None:\n", + " display(Markdown(f\"`{name}` is `None`.\"))\n", + " return None\n", + " array_panel(name, value, open=open)\n", + " return value\n", + "\n", + "\n", + "def selected_indices(n: int, edge: int = 4) -> list[int]:\n", + " n = int(n)\n", + " if n <= 0:\n", + " return []\n", + " if n <= 2 * edge + 3:\n", + " return list(range(n))\n", + " middle = n // 2\n", + " picks = set(range(edge))\n", + " picks.update([middle - 1, middle, middle + 1])\n", + " picks.update(range(max(0, n - edge), n))\n", + " return sorted(i for i in picks if 0 <= i < n)\n", + "\n", + "\n", + "def truncate_sequence(values, *, max_items=FULL_DETAIL_ROW_ITEMS):\n", + " values = list(values)\n", + " if len(values) <= max_items:\n", + " return values, False\n", + " edge = max(1, max_items // 3)\n", + " return values[:edge] + [\"...\"] + values[-edge:], True\n", + "\n", + "\n", + "def ragged_panel(name, ragged, n_rows: int, *, edge=4, max_items=FULL_DETAIL_ROW_ITEMS, open=True):\n", + " \"\"\"Display exact row count and selected ragged rows without pretending the list is rectangular.\"\"\"\n", + " n_rows = int(n_rows)\n", + " rows = []\n", + " for i in selected_indices(n_rows, edge=edge):\n", + " row = [int(x) for x in ragged.row(i)]\n", + " shown, truncated = truncate_sequence(row, max_items=max_items)\n", + " rows.append((i, len(row), shown, truncated))\n", + " lines = [\n", + " f\"{name}: ragged OpenFOAM label list\",\n", + " f\"exact row count={n_rows:,}\",\n", + " f\"selected rows={len(rows):,}; selected row values keep exact row length; long rows use ellipsis only in the middle\",\n", + " \"\",\n", + " ]\n", + " for i, length, shown, truncated in rows:\n", + " suffix = \" (row value text truncated)\" if truncated else \"\"\n", + " lines.append(f\"row {i:,}: length={length:,}{suffix}\")\n", + " lines.append(\" \" + repr(shown))\n", + " attr = \" open\" if open else \"\"\n", + " display(HTML(\n", + " f\"\"\n", + " f\"{_html(name)} — ragged rows={n_rows:,}\"\n", + " f\"
\"\n",
+    "        f\"{_html(chr(10).join(lines))}
\"\n", + " ))\n", + "\n", + "\n", + "_PALETTE = np.array(\n", + " [\n", + " [68, 1, 84],\n", + " [59, 82, 139],\n", + " [33, 145, 140],\n", + " [94, 201, 98],\n", + " [253, 231, 37],\n", + " ],\n", + " dtype=float,\n", + ")\n", + "\n", + "\n", + "def color_map(t) -> str:\n", + " t = float(np.clip(t, 0.0, 1.0))\n", + " pos = t * (len(_PALETTE) - 1)\n", + " i = int(np.floor(pos))\n", + " if i >= len(_PALETTE) - 1:\n", + " rgb = _PALETTE[-1]\n", + " else:\n", + " frac = pos - i\n", + " rgb = (1.0 - frac) * _PALETTE[i] + frac * _PALETTE[i + 1]\n", + " r, g, b = [int(round(x)) for x in rgb]\n", + " return f\"rgb({r},{g},{b})\"\n", + "\n", + "\n", + "def _finite_flat(data):\n", + " arr = np.asarray(data, dtype=float).reshape(-1)\n", + " return arr[np.isfinite(arr)]\n", + "\n", + "\n", + "def histogram_svg(title, data, *, bins=80, width=760, height=230, log_y=False):\n", + " values = _finite_flat(data)\n", + " if values.size == 0:\n", + " display(Markdown(f\"**{title}**: no finite values.\"))\n", + " return\n", + " lo = float(values.min())\n", + " hi = float(values.max())\n", + " if lo == hi:\n", + " pad = 0.5 if lo == 0 else abs(lo) * 0.01\n", + " lo -= pad\n", + " hi += pad\n", + " counts, edges = np.histogram(values, bins=bins, range=(lo, hi))\n", + " y_values = np.log1p(counts) if log_y else counts.astype(float)\n", + " y_max = float(y_values.max()) if y_values.size else 1.0\n", + " y_max = y_max if y_max > 0 else 1.0\n", + " left, right, top, bottom = 70, 18, 38, 48\n", + " plot_w = width - left - right\n", + " plot_h = height - top - bottom\n", + " bar_w = plot_w / len(counts)\n", + " rects = []\n", + " for i, y in enumerate(y_values):\n", + " h = 0.0 if y_max == 0 else (float(y) / y_max) * plot_h\n", + " x = left + i * bar_w\n", + " y0 = top + plot_h - h\n", + " rects.append(f\"\")\n", + " mean = float(values.mean())\n", + " std = float(values.std())\n", + " label = \"log1p(count)\" if log_y else \"count\"\n", + " svg = f\"\"\"\n", + " \n", + " \n", + " {_html(title)}\n", + " n={values.size:,} finite, min={lo:.6g}, max={hi:.6g}, mean={mean:.6g}, std={std:.6g}\n", + " x=value, y={label}, bins={bins}\n", + " \n", + " \n", + " {''.join(rects)}\n", + " \n", + " \"\"\"\n", + " display(SVG(svg))\n", + "\n", + "\n", + "def bar_chart_svg(title, labels, values, *, width=760, height=None):\n", + " labels = [str(x) for x in labels]\n", + " values = np.asarray(values, dtype=float)\n", + " if height is None:\n", + " height = max(220, 48 + 30 * len(labels))\n", + " if values.size == 0:\n", + " display(Markdown(f\"**{title}**: no values.\"))\n", + " return\n", + " vmax = float(values.max()) if float(values.max()) > 0 else 1.0\n", + " left, right, top, row_h = 170, 30, 34, 26\n", + " plot_w = width - left - right\n", + " rows = []\n", + " for i, (label, value) in enumerate(zip(labels, values)):\n", + " y = top + i * row_h\n", + " w = plot_w * float(value) / vmax\n", + " rows.append(\n", + " f\"{_html(label)}\"\n", + " f\"\"\n", + " f\"{value:,.0f}\"\n", + " )\n", + " svg = f\"\"\"\n", + " \n", + " \n", + " {_html(title)}\n", + " {''.join(rows)}\n", + " \n", + " \"\"\"\n", + " display(SVG(svg))\n", + "\n", + "\n", + "def density_svg(title, x, y, values=None, *, grid=FULL_DETAIL_GRID, width=700, height=560, statistic=\"mean\", log_counts=True):\n", + " x = np.asarray(x, dtype=float).reshape(-1)\n", + " y = np.asarray(y, dtype=float).reshape(-1)\n", + " if x.size != y.size:\n", + " raise ValueError(f\"x/y length mismatch: {x.size} != {y.size}\")\n", + " mask = np.isfinite(x) & np.isfinite(y)\n", + " v = None\n", + " if values is not None:\n", + " v = np.asarray(values, dtype=float).reshape(-1)\n", + " if v.size != x.size:\n", + " raise ValueError(f\"values length mismatch: {v.size} != {x.size}\")\n", + " mask &= np.isfinite(v)\n", + " v = v[mask]\n", + " x = x[mask]\n", + " y = y[mask]\n", + " if x.size == 0:\n", + " display(Markdown(f\"**{title}**: no finite coordinates.\"))\n", + " return\n", + " x_range = (float(x.min()), float(x.max()))\n", + " y_range = (float(y.min()), float(y.max()))\n", + " if x_range[0] == x_range[1]:\n", + " x_range = (x_range[0] - 0.5, x_range[1] + 0.5)\n", + " if y_range[0] == y_range[1]:\n", + " y_range = (y_range[0] - 0.5, y_range[1] + 0.5)\n", + " counts, x_edges, y_edges = np.histogram2d(x, y, bins=grid, range=[x_range, y_range])\n", + " if v is None:\n", + " Z = np.log1p(counts) if log_counts else counts\n", + " occupied = counts > 0\n", + " legend = \"log1p(count)\" if log_counts else \"count\"\n", + " raw_min = float(counts[occupied].min()) if np.any(occupied) else 0.0\n", + " raw_max = float(counts.max()) if counts.size else 0.0\n", + " else:\n", + " sums, _, _ = np.histogram2d(x, y, bins=grid, range=[x_range, y_range], weights=v)\n", + " with np.errstate(invalid=\"ignore\", divide=\"ignore\"):\n", + " Z = sums / counts\n", + " occupied = counts > 0\n", + " legend = statistic\n", + " raw_min = float(np.nanmin(Z[occupied])) if np.any(occupied) else 0.0\n", + " raw_max = float(np.nanmax(Z[occupied])) if np.any(occupied) else 0.0\n", + " if not np.any(occupied):\n", + " display(Markdown(f\"**{title}**: no occupied bins.\"))\n", + " return\n", + " z_values = Z[occupied]\n", + " z_min = float(np.nanmin(z_values))\n", + " z_max = float(np.nanmax(z_values))\n", + " if z_min == z_max:\n", + " denom = 1.0\n", + " else:\n", + " denom = z_max - z_min\n", + " left, right, top, bottom = 72, 18, 38, 58\n", + " plot_w = width - left - right\n", + " plot_h = height - top - bottom\n", + " cell_w = plot_w / grid\n", + " cell_h = plot_h / grid\n", + " rects = []\n", + " for ix, iy in np.argwhere(occupied):\n", + " z = float(Z[ix, iy])\n", + " t = 0.5 if z_min == z_max else (z - z_min) / denom\n", + " px = left + ix * cell_w\n", + " py = top + (grid - 1 - iy) * cell_h\n", + " rects.append(\n", + " f\"\")\n", + " svg = f\"\"\"\n", + " \n", + " \n", + " {_html(title)}\n", + " \n", + " {''.join(rects)}\n", + " points={x.size:,}; bins={grid}×{grid}; color={_html(legend)}; occupied bins={int(occupied.sum()):,}\n", + " x=[{x_range[0]:.6g}, {x_range[1]:.6g}], y=[{y_range[0]:.6g}, {y_range[1]:.6g}]\n", + " raw color range=[{raw_min:.6g}, {raw_max:.6g}]\n", + " \n", + " \"\"\"\n", + " display(SVG(svg))\n", + "\n", + "\n", + "def entity_scalar_values(array, n_entities: int):\n", + " arr = np.asarray(array)\n", + " if arr.shape[0] != int(n_entities):\n", + " raise ValueError(f\"first dimension {arr.shape[0]} does not match entity count {n_entities}\")\n", + " if arr.ndim == 1:\n", + " return arr.astype(float, copy=False)\n", + " flat = arr.reshape((int(n_entities), -1)).astype(float, copy=False)\n", + " if flat.shape[1] == 1:\n", + " return flat[:, 0]\n", + " return np.linalg.norm(flat, axis=1)\n", + "\n", + "\n", + "def show_field_histograms(field, *, bins=80):\n", + " arr = np.asarray(field.internal)\n", + " array_panel(f\"{field.name}.internal\", arr, open=False)\n", + " if arr.ndim == 1:\n", + " histogram_svg(f\"{field.name} internal values\", arr, bins=bins)\n", + " return\n", + " flat = arr.reshape((arr.shape[0], -1))\n", + " for j in range(min(flat.shape[1], 6)):\n", + " histogram_svg(f\"{field.name} component {j} internal values\", flat[:, j], bins=bins)\n", + " if flat.shape[1] > 1:\n", + " histogram_svg(f\"{field.name} internal vector/tensor magnitude\", np.linalg.norm(flat, axis=1), bins=bins)\n", + "\n", + "\n", + "def show_cell_field_map(mesh, field, *, title=None, grid=FULL_DETAIL_GRID):\n", + " coords = np.asarray(mesh.C)\n", + " values = entity_scalar_values(field.internal, mesh.n_cells)\n", + " density_svg(title or f\"{field.name} on cell centres\", coords[:, 0], coords[:, 1], values, grid=grid, statistic=\"bin mean\")\n", + "\n", + "\n", + "def show_face_field_map(mesh, field, *, title=None, grid=FULL_DETAIL_GRID):\n", + " coords = np.asarray(mesh.Cf[:mesh.n_internal_faces])\n", + " values = entity_scalar_values(field.internal, mesh.n_internal_faces)\n", + " density_svg(title or f\"{field.name} on internal face centres\", coords[:, 0], coords[:, 1], values, grid=grid, statistic=\"bin mean\")\n", + "\n", + "\n", + "def show_delta_map(mesh, name, before, after, *, grid=FULL_DETAIL_GRID):\n", + " diff = np.asarray(after[name]) - np.asarray(before[name])\n", + " values = entity_scalar_values(diff, diff.shape[0])\n", + " coords = np.asarray(mesh.C if diff.shape[0] == mesh.n_cells else mesh.Cf[:diff.shape[0]])\n", + " density_svg(f\"|Δ{name}| spatial distribution\", coords[:, 0], coords[:, 1], np.abs(values), grid=grid, statistic=\"bin mean |Δ|\")\n", + "\n", + "\n", + "def show_matrix_arrays(label, matrix, *, open_arrays=False):\n", + " array_panel(f\"{label}.diag\", matrix.diag, open=open_arrays)\n", + " array_panel(f\"{label}.source\", matrix.source, open=open_arrays)\n", + " if matrix.upper is not None:\n", + " array_panel(f\"{label}.upper\", matrix.upper, open=open_arrays)\n", + " if matrix.lower is not None:\n", + " array_panel(f\"{label}.lower\", matrix.lower, open=open_arrays)\n", + " histogram_svg(f\"{label}.diag coefficient distribution\", matrix.diag, bins=90, log_y=True)\n", + " histogram_svg(f\"{label}.source distribution\", matrix.source, bins=90, log_y=True)\n", + " if matrix.upper is not None:\n", + " histogram_svg(f\"{label}.upper coefficient distribution\", matrix.upper, bins=90, log_y=True)\n", + " if matrix.lower is not None:\n", + " histogram_svg(f\"{label}.lower coefficient distribution\", matrix.lower, bins=90, log_y=True)\n", + "\n", + "\n", + "def show_ldu_density(mesh, title=\"LDU owner-neighbour sparse graph density\", *, grid=FULL_DETAIL_GRID):\n", + " density_svg(title, np.asarray(mesh.owner), np.asarray(mesh.neighbour), grid=grid, statistic=\"count\", log_counts=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-06", + "metadata": {}, + "source": [ + "## The Python objects this notebook will use\n", + "\n", + "The stepper facade turns native OpenFOAM objects into small Python views. These are not reimplementations of OpenFOAM; they are snapshots of OpenFOAM-owned state.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "full-detail-07", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:18.010909Z", + "iopub.status.busy": "2026-07-22T20:00:18.010785Z", + "iopub.status.idle": "2026-07-22T20:00:18.015422Z", + "shell.execute_reply": "2026-07-22T20:00:18.014909Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Stepper data model**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Object | What it represents | Why it matters for the simulation |\n", + "| --- | --- | --- |\n", + "| MeshView | points, faces, owner/neighbour addressing, cell volumes, patch geometry | the finite-volume control-volume graph |\n", + "| PatchView | one boundary patch: wall, farfield, empty plane | where boundary conditions attach to mesh faces |\n", + "| FieldRegistryView | mapping of registered fields | what OpenFOAM currently knows: U, p, phi, turbulence fields |\n", + "| FieldView | internal field array plus boundary patch fields | cell or face values being solved/updated |\n", + "| PatchFieldView | boundary-condition type, values, coefficients | how wall/freestream/empty constraints enter equations |\n", + "| MatrixView | fvMatrix/lduMatrix diag, upper, lower, source | the sparse linear system OpenFOAM solves |\n", + "| SolveResult | solver residuals, iteration count, convergence flag | how hard the linear solve was |\n", + "| TransformResult | one named OpenFOAM operation with inputs, outputs, source location | the breadcrumb for every state transition |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_table(\n", + " \"Stepper data model\",\n", + " [\"Object\", \"What it represents\", \"Why it matters for the simulation\"],\n", + " [\n", + " [\"MeshView\", \"points, faces, owner/neighbour addressing, cell volumes, patch geometry\", \"the finite-volume control-volume graph\"],\n", + " [\"PatchView\", \"one boundary patch: wall, farfield, empty plane\", \"where boundary conditions attach to mesh faces\"],\n", + " [\"FieldRegistryView\", \"mapping of registered fields\", \"what OpenFOAM currently knows: U, p, phi, turbulence fields\"],\n", + " [\"FieldView\", \"internal field array plus boundary patch fields\", \"cell or face values being solved/updated\"],\n", + " [\"PatchFieldView\", \"boundary-condition type, values, coefficients\", \"how wall/freestream/empty constraints enter equations\"],\n", + " [\"MatrixView\", \"fvMatrix/lduMatrix diag, upper, lower, source\", \"the sparse linear system OpenFOAM solves\"],\n", + " [\"SolveResult\", \"solver residuals, iteration count, convergence flag\", \"how hard the linear solve was\"],\n", + " [\"TransformResult\", \"one named OpenFOAM operation with inputs, outputs, source location\", \"the breadcrumb for every state transition\"],\n", + " ],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-08", + "metadata": {}, + "source": [ + "## 1. Prepare the real AirfRANS case\n", + "\n", + "The sibling AirfRANS raw case is OpenFOAM.com v2112 syntax. This repo runs OpenFOAM Foundation v14. The helper copies the raw case into `tmp/` and migrates only the dictionaries needed for a one-iteration microscope run:\n", + "\n", + "- `controlDict`: uses `solver incompressibleFluid`, one time step, no function objects;\n", + "- `physicalProperties`: carries `rho` and molecular `nu`;\n", + "- `momentumTransport`: selects `RAS { model kOmegaSST; turbulence on; }`;\n", + "- mesh and initial fields are copied unchanged.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "full-detail-09", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:18.016773Z", + "iopub.status.busy": "2026-07-22T20:00:18.016585Z", + "iopub.status.idle": "2026-07-22T20:00:18.031003Z", + "shell.execute_reply": "2026-07-22T20:00:18.030338Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Selected case metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Quantity | Value | Meaning |\n", + "| --- | --- | --- |\n", + "| simulation | airFoil2D_SST_93.213_3.79_0.418_0.0_9.665 | AirfRANS raw OpenFOAM case directory |\n", + "| Uinf | 93.21 | freestream speed magnitude [m/s] |\n", + "| velocity | (93.00914503999995, 6.161356013756317, 0.0) | initial/freestream velocity vector [m/s] |\n", + "| nu | 1.56e-05 | kinematic viscosity [m^2/s] |\n", + "| rhoInf | 1.204 | reference density [kg/m^3] |\n", + "| Re | 5.975e+06 | Re = Uinf * chord / nu; AirfRANS chord is 1 m |\n", + "| Mach | 0.2693 | Uinf / 346.1, archived diagnostic |\n", + "| angle | 3.79 | angle from dragDir |\n", + "| raw endTime | 20000 | original AirfRANS run length |\n", + "| notebook endTime | 1 | one iteration for inspection |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "working_case=/home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case\n" + ] + } + ], + "source": [ + "if WORK.exists():\n", + " shutil.rmtree(WORK)\n", + "WORK.mkdir(parents=True)\n", + "\n", + "meta = prepare_case(RAW_CASE, CASE, end_time=1)\n", + "meta_dict = asdict(meta)\n", + "\n", + "show_table(\n", + " \"Selected case metadata\",\n", + " [\"Quantity\", \"Value\", \"Meaning\"],\n", + " [\n", + " [\"simulation\", meta.simulation, \"AirfRANS raw OpenFOAM case directory\"],\n", + " [\"Uinf\", meta.u_inf, \"freestream speed magnitude [m/s]\"],\n", + " [\"velocity\", meta.velocity, \"initial/freestream velocity vector [m/s]\"],\n", + " [\"nu\", meta.nu, \"kinematic viscosity [m^2/s]\"],\n", + " [\"rhoInf\", meta.rho_inf, \"reference density [kg/m^3]\"],\n", + " [\"Re\", meta.reynolds, \"Re = Uinf * chord / nu; AirfRANS chord is 1 m\"],\n", + " [\"Mach\", meta.mach, \"Uinf / 346.1, archived diagnostic\"],\n", + " [\"angle\", meta.alpha_deg, \"angle from dragDir\"],\n", + " [\"raw endTime\", meta.source_end_time, \"original AirfRANS run length\"],\n", + " [\"notebook endTime\", meta.migrated_end_time, \"one iteration for inspection\"],\n", + " ],\n", + ")\n", + "print(f\"working_case={CASE}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-10", + "metadata": {}, + "source": [ + "## 2. What the raw OpenFOAM dictionaries say\n", + "\n", + "These dictionaries are the simulation contract. They encode the solver, numerical schemes, SIMPLE controls, turbulence model, force directions, and output objects used by AirfRANS.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "full-detail-11", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:18.032543Z", + "iopub.status.busy": "2026-07-22T20:00:18.032363Z", + "iopub.status.idle": "2026-07-22T20:00:18.039450Z", + "shell.execute_reply": "2026-07-22T20:00:18.038878Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Raw dictionary facts**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Dictionary | Entry | Value | Interpretation |\n", + "| --- | --- | --- | --- |\n", + "| controlDict | application | simpleFoam | original OpenFOAM.com solver |\n", + "| controlDict | Uinf | 93.213 | freestream magnitude |\n", + "| controlDict | endTime | 20000 | original run has 20k steady iterations |\n", + "| controlDict | liftDir | (-0.06609975018244577, 0.9978130200723071, 0.0) | force projection direction |\n", + "| controlDict | dragDir | (0.9978130200723071, 0.06609975018244577, 0.0) | force projection direction |\n", + "| transportProperties | nu | 1.56e-5 | molecular kinematic viscosity |\n", + "| turbulenceProperties | simulationType | RAS | RAS turbulence closure active |\n", + "| fvSolution | SIMPLE.consistent | yes | SIMPLEC-style pressure/velocity coupling |\n", + "| fvSolution | SIMPLE.nNonOrthogonalCorrectors | 3 | four pressure solves in this v14 path: initial + 3 correctors |\n", + "| fvSchemes | ddtSchemes.default | steadyState | pseudo-time iteration, not physical transient integration |\n", + "| fvSchemes | div(phi,U) | bounded Gauss linearUpwind grad(U) | convective momentum flux discretization |\n", + "| fvSchemes | wallDist.method | meshWave | wall distance for k-omega SST near-wall handling |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "raw_control = read_text(RAW_CASE / \"system/controlDict\")\n", + "raw_solution = read_text(RAW_CASE / \"system/fvSolution\")\n", + "raw_schemes = read_text(RAW_CASE / \"system/fvSchemes\")\n", + "raw_turbulence = read_text(RAW_CASE / \"constant/turbulenceProperties\")\n", + "raw_transport = read_text(RAW_CASE / \"constant/transportProperties\")\n", + "\n", + "show_table(\n", + " \"Raw dictionary facts\",\n", + " [\"Dictionary\", \"Entry\", \"Value\", \"Interpretation\"],\n", + " [\n", + " [\"controlDict\", \"application\", assignment(raw_control, \"application\"), \"original OpenFOAM.com solver\"],\n", + " [\"controlDict\", \"Uinf\", assignment(raw_control, \"Uinf\"), \"freestream magnitude\"],\n", + " [\"controlDict\", \"endTime\", assignment(raw_control, \"endTime\"), \"original run has 20k steady iterations\"],\n", + " [\"controlDict\", \"liftDir\", vector_assignment(raw_control, \"liftDir\"), \"force projection direction\"],\n", + " [\"controlDict\", \"dragDir\", vector_assignment(raw_control, \"dragDir\"), \"force projection direction\"],\n", + " [\"transportProperties\", \"nu\", assignment(raw_transport, \"nu\"), \"molecular kinematic viscosity\"],\n", + " [\"turbulenceProperties\", \"simulationType\", assignment(raw_turbulence, \"simulationType\"), \"RAS turbulence closure active\"],\n", + " [\"fvSolution\", \"SIMPLE.consistent\", \"yes\", \"SIMPLEC-style pressure/velocity coupling\"],\n", + " [\"fvSolution\", \"SIMPLE.nNonOrthogonalCorrectors\", \"3\", \"four pressure solves in this v14 path: initial + 3 correctors\"],\n", + " [\"fvSchemes\", \"ddtSchemes.default\", \"steadyState\", \"pseudo-time iteration, not physical transient integration\"],\n", + " [\"fvSchemes\", \"div(phi,U)\", \"bounded Gauss linearUpwind grad(U)\", \"convective momentum flux discretization\"],\n", + " [\"fvSchemes\", \"wallDist.method\", \"meshWave\", \"wall distance for k-omega SST near-wall handling\"],\n", + " ],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-12", + "metadata": {}, + "source": [ + "## 3. Construct the OpenFOAM stepper and inspect the finite-volume mesh\n", + "\n", + "A finite-volume mesh is a graph:\n", + "\n", + "- cells are control volumes;\n", + "- faces connect cells or lie on boundary patches;\n", + "- each internal face has an owner cell and a neighbour cell;\n", + "- each boundary face belongs to exactly one patch;\n", + "- fields live either on cells (`vol*`) or faces (`surface*`).\n", + "\n", + "The AirfRANS case is a 2D airfoil extrusion. The `frontAndBack` patch is `empty`, which tells OpenFOAM the third direction is not solved as a real 3D thickness.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "full-detail-13", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:18.041099Z", + "iopub.status.busy": "2026-07-22T20:00:18.040919Z", + "iopub.status.idle": "2026-07-22T20:00:19.340747Z", + "shell.execute_reply": "2026-07-22T20:00:19.340216Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/*---------------------------------------------------------------------------*\\\n", + " ========= |\n", + " \\\\ / F ield | OpenFOAM: The Open Source CFD Toolbox\n", + " \\\\ / O peration | Website: https://openfoam.org\n", + " \\\\ / A nd | Version: 14\n", + " \\\\/ M anipulation |\n", + "\\*---------------------------------------------------------------------------*/\n", + "Build : 14-0db507470b5e\n", + "Exec : foam_stepper -case /home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case -noFunctionObjects -solver incompressibleFluid\n", + "Date : Jul 23 2026\n", + "Time : 11:44:59\n", + "Host : \"devuan-hpz\"\n", + "PID : 28708\n", + "I/O : uncollated\n", + "Case : /home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case\n", + "nProcs : 1\n", + "fileModificationChecking : Monitoring run-time modified files using timeStampMaster (fileModificationSkew 10)\n", + "allowSystemOperations : Allowing user-supplied system call operations\n", + "\n", + "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n", + "\n", + "Selecting viscosity model constant\n", + "\n", + "Selecting momentum transport model type RAS\n", + " Selecting RAS turbulence model kOmegaSST\n", + " bounding k, min: 0 max: 3.6353069999999998e-09 average: 3.6353069999910849e-09\n", + "\n", + "Selecting patchDistMethod meshWave\n", + "\n", + "SIMPLE: Convergence criteria found\n", + " p: tolerance 0\n", + " U: tolerance 0\n", + " nuTilda: tolerance 0\n", + " k: tolerance 0\n", + " omega: tolerance 0\n", + " h: tolerance 0\n", + "\n", + "\n", + "SIMPLE: Operating solver in steady-state mode with 1 outer corrector\n", + "SIMPLE: Operating solver in SIMPLE mode\n", + "\n", + "\n" + ] + }, + { + "data": { + "text/markdown": [ + "**Initial solver state**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Key | Value |\n", + "| --- | --- |\n", + "| case_path | /home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case |\n", + "| solver_name | incompressibleFluid |\n", + "| time_name | 0 |\n", + "| time_index | 0 |\n", + "| time_value | 0 |\n", + "| delta_t | 1 |\n", + "| pimple_iteration_open | False |\n", + "| has_momentum_matrix | False |\n", + "| has_pressure_inputs | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Mesh counts**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Quantity | Value | Meaning |\n", + "| --- | --- | --- |\n", + "| points | 569562 | mesh vertices |\n", + "| faces | 1134981 | internal + boundary faces |\n", + "| internal faces | 565419 | faces with owner and neighbour cells |\n", + "| cells | 283400 | finite-volume control volumes |\n", + "| ldu owner size | (565419,) | owner addressing for lower/upper matrix coefficients |\n", + "| ldu neighbour size | (565419,) | neighbour addressing for lower/upper matrix coefficients |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Boundary patches from MeshView**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | type | index | start | size | coupled | constraint | min area | max area | mean area |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| aerofoil | wall | 0 | 565419 | 1026 | False | False | 5.949e-06 | 0.0076 | 0.001976 |\n", + "| freestream | patch | 1 | 566445 | 1736 | False | False | 0.0001 | 11.11 | 0.8227 |\n", + "| frontAndBack | empty | 2 | 568181 | 0 | False | True | | | |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "case = foam.Case(CASE)\n", + "stepper = case.make_stepper()\n", + "state0 = stepper.state()\n", + "mesh = stepper.mesh()\n", + "fields = stepper.fields()\n", + "\n", + "show_table(\"Initial solver state\", [\"Key\", \"Value\"], list(state0.items()))\n", + "show_table(\n", + " \"Mesh counts\",\n", + " [\"Quantity\", \"Value\", \"Meaning\"],\n", + " [\n", + " [\"points\", mesh.n_points, \"mesh vertices\"],\n", + " [\"faces\", mesh.n_faces, \"internal + boundary faces\"],\n", + " [\"internal faces\", mesh.n_internal_faces, \"faces with owner and neighbour cells\"],\n", + " [\"cells\", mesh.n_cells, \"finite-volume control volumes\"],\n", + " [\"ldu owner size\", np.asarray(mesh.owner).shape, \"owner addressing for lower/upper matrix coefficients\"],\n", + " [\"ldu neighbour size\", np.asarray(mesh.neighbour).shape, \"neighbour addressing for lower/upper matrix coefficients\"],\n", + " ],\n", + ")\n", + "\n", + "patch_rows = []\n", + "for patch in mesh.boundary:\n", + " mag_stats = arr_stats(patch.magSf)\n", + " patch_rows.append([\n", + " patch.name,\n", + " patch.type,\n", + " patch.index,\n", + " patch.start,\n", + " patch.size,\n", + " patch.coupled,\n", + " patch.constraint,\n", + " mag_stats[\"min\"],\n", + " mag_stats[\"max\"],\n", + " mag_stats[\"mean\"],\n", + " ])\n", + "show_table(\"Boundary patches from MeshView\", [\"name\", \"type\", \"index\", \"start\", \"size\", \"coupled\", \"constraint\", \"min area\", \"max area\", \"mean area\"], patch_rows)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-14", + "metadata": {}, + "source": [ + "### Full-shape mesh arrays and geometry visualizations\n", + "\n", + "The tables above give counts. The panels below expose the arrays behind those counts. Text panels may truncate values, but they preserve exact shapes and sizes. The charts use the complete coordinate, volume, face-area, and addressing arrays.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "full-detail-15", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
mesh.points — shape=(569562, 3) (569,562 × 3), dtype=float64, size=1,708,686, TRUNCATED value text; exact shape retained; size=1,708,686; threshold=256; edgeitems=4
[[ 200.           13.15385029    0.        ]\n",
+       " [ 186.1155879    12.23609412    0.        ]\n",
+       " [ 173.1998558    11.38236745    0.        ]\n",
+       " [ 161.1852212    10.5882031     0.        ]\n",
+       " ...\n",
+       " [-199.3376715   -16.12037607    1.        ]\n",
+       " [-199.6203798   -12.17269963    1.        ]\n",
+       " [-199.8270894    -8.16952639    1.        ]\n",
+       " [-199.9546882    -4.11165538    1.        ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.C cell centres — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[ 193.10515307   12.69805363    0.5       ]\n",
+       " [ 179.70132112   11.81206564    0.5       ]\n",
+       " [ 167.23269792   10.98789461    0.5       ]\n",
+       " [ 155.63378164   10.22121091    0.5       ]\n",
+       " ...\n",
+       " [-192.71874543  -13.56339867    0.5       ]\n",
+       " [-192.92770495   -9.75145316    0.5       ]\n",
+       " [-193.06140841   -5.88666928    0.5       ]\n",
+       " [-193.11681557   -1.96987964    0.5       ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.Cf face centres — shape=(565419, 3) (565,419 × 3), dtype=float64, size=1,696,257, TRUNCATED value text; exact shape retained; size=1,696,257; threshold=256; edgeitems=4
[[ 186.1155888    12.23604618    0.5       ]\n",
+       " [ 193.05779485   12.69487427    0.5       ]\n",
+       " [ 193.05779395   12.6949722     0.5       ]\n",
+       " [ 173.1998576    11.38232148    0.5       ]\n",
+       " ...\n",
+       " [-192.4947848   -15.44731136    0.5       ]\n",
+       " [-192.7404734   -11.66449536    0.5       ]\n",
+       " [-192.9124636    -7.82846933    0.5       ]\n",
+       " [-193.0077474    -3.94000887    0.5       ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.Sf face area vectors — shape=(565419, 3) (565,419 × 3), dtype=float64, size=1,696,257, TRUNCATED value text; exact shape retained; size=1,696,257; threshold=256; edgeitems=4
[[-9.58700000e-05 -1.79999998e-06  0.00000000e+00]\n",
+       " [ 9.17752040e-01 -1.38844103e+01  0.00000000e+00]\n",
+       " [-9.17756170e-01  1.38844121e+01 -4.44089210e-16]\n",
+       " [-9.19400000e-05 -3.60000001e-06  0.00000000e+00]\n",
+       " ...\n",
+       " [-1.34612941e+00  1.36857734e+01  0.00000000e+00]\n",
+       " [-1.01640854e+00  1.37598128e+01  4.44089210e-16]\n",
+       " [-6.82114115e-01  1.38292516e+01  0.00000000e+00]\n",
+       " [-3.43293021e-01  1.38938816e+01  0.00000000e+00]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.V cell volumes — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[1.36059579e-03 1.21515680e-03 1.08571142e-03 9.70557105e-04 ... 5.22010257e+01 5.30622492e+01 5.39490060e+01 5.48621082e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.owner internal-face owner cells — shape=(565419,) (565,419), dtype=int64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[     0      0      0      1 ... 283395 283396 283397 283398]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.neighbour internal-face neighbour cells — shape=(565419,) (565,419), dtype=int64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[     1    137  29866      2 ... 283396 283397 283398 283399]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.faces point labels per face — ragged rows=1,134,981
mesh.faces point labels per face: ragged OpenFOAM label list\n",
+       "exact row count=1,134,981\n",
+       "selected rows=11; selected row values keep exact row length; long rows use ellipsis only in the middle\n",
+       "\n",
+       "row 0: length=4\n",
+       "  [1, 139, 30361, 30223]\n",
+       "row 1: length=4\n",
+       "  [138, 30360, 30361, 139]\n",
+       "row 2: length=4\n",
+       "  [0, 1, 30223, 30222]\n",
+       "row 3: length=4\n",
+       "  [2, 140, 30362, 30224]\n",
+       "row 567,489: length=4\n",
+       "  [173873, 227309, 227310, 173874]\n",
+       "row 567,490: length=4\n",
+       "  [173874, 227310, 227311, 173875]\n",
+       "row 567,491: length=4\n",
+       "  [173875, 227311, 227312, 173876]\n",
+       "row 1,134,977: length=4\n",
+       "  [59890, 59891, 60029, 60028]\n",
+       "row 1,134,978: length=4\n",
+       "  [60028, 60029, 60167, 60166]\n",
+       "row 1,134,979: length=4\n",
+       "  [60166, 60167, 60305, 60304]\n",
+       "row 1,134,980: length=4\n",
+       "  [60304, 60305, 60443, 60442]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
mesh.cells face labels per cell — ragged rows=283,400
mesh.cells face labels per cell: ragged OpenFOAM label list\n",
+       "exact row count=283,400\n",
+       "selected rows=11; selected row values keep exact row length; long rows use ellipsis only in the middle\n",
+       "\n",
+       "row 0: length=6\n",
+       "  [0, 1, 2, 567201, 821715, 1105115]\n",
+       "row 1: length=6\n",
+       "  [3, 4, 5, 821933, 1105333, 0]\n",
+       "row 2: length=6\n",
+       "  [6, 7, 8, 822151, 1105551, 3]\n",
+       "row 3: length=6\n",
+       "  [9, 10, 11, 822369, 1105769, 6]\n",
+       "row 141,699: length=6\n",
+       "  [283017, 283018, 818126, 1101526, 282530, 283015]\n",
+       "row 141,700: length=6\n",
+       "  [283019, 283020, 818344, 1101744, 282532, 283017]\n",
+       "row 141,701: length=6\n",
+       "  [283021, 283022, 818562, 1101962, 282534, 283019]\n",
+       "row 283,396: length=6\n",
+       "  [565416, 566979, 767868, 1051268, 565145, 565415]\n",
+       "row 283,397: length=6\n",
+       "  [565417, 566980, 768086, 1051486, 565147, 565416]\n",
+       "row 283,398: length=6\n",
+       "  [565418, 566981, 768304, 1051704, 565149, 565417]\n",
+       "row 283,399: length=6\n",
+       "  [566982, 768522, 1051922, 448621, 565150, 565418]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " Boundary patch sizes\n", + " aerofoil1,026freestream1,736frontAndBack0\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " Cell-volume distribution V\n", + " n=283,400 finite, min=1.27546e-11, max=57.9661, mean=0.503898, std=2.81004\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " Face-area magnitude distribution |Sf|\n", + " n=565,419 finite, min=1.72865e-06, max=17.5268, mean=0.636312, std=2.03571\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " All cell centres: occupancy density\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=log1p(count); occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[1, 170642]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " All face centres: occupancy density\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=log1p(count); occupied bins=7,291\n", + " x=[-193.023, 197.582], y=[-194.361, 195.068]\n", + " raw color range=[1, 340226]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " LDU owner-neighbour sparse graph density\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=log1p(count); occupied bins=360\n", + " x=[0, 283398], y=[1, 283399]\n", + " raw color range=[1, 5749]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch aerofoil.Cf face centres — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch aerofoil.Sf face area vectors — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch aerofoil: |Sf|**: no finite values." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch aerofoil: face-centre occupancy**: no finite coordinates." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch freestream.Cf face centres — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch freestream.Sf face area vectors — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch freestream: |Sf|**: no finite values." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch freestream: face-centre occupancy**: no finite coordinates." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch frontAndBack.Cf face centres — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
patch frontAndBack.Sf face area vectors — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch frontAndBack: |Sf|**: no finite values." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**patch frontAndBack: face-centre occupancy**: no finite coordinates." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "safe_array_panel(\"mesh.points\", lambda: mesh.points, open=False)\n", + "array_panel(\"mesh.C cell centres\", mesh.C, open=False)\n", + "array_panel(\"mesh.Cf face centres\", mesh.Cf, open=False)\n", + "array_panel(\"mesh.Sf face area vectors\", mesh.Sf, open=False)\n", + "array_panel(\"mesh.V cell volumes\", mesh.V, open=False)\n", + "array_panel(\"mesh.owner internal-face owner cells\", mesh.owner, open=False)\n", + "array_panel(\"mesh.neighbour internal-face neighbour cells\", mesh.neighbour, open=False)\n", + "ragged_panel(\"mesh.faces point labels per face\", mesh.faces, mesh.n_faces, open=False)\n", + "ragged_panel(\"mesh.cells face labels per cell\", mesh.cells, mesh.n_cells, open=False)\n", + "\n", + "bar_chart_svg(\n", + " \"Boundary patch sizes\",\n", + " [patch.name for patch in mesh.boundary],\n", + " [patch.size for patch in mesh.boundary],\n", + ")\n", + "histogram_svg(\"Cell-volume distribution V\", mesh.V, bins=90, log_y=True)\n", + "histogram_svg(\"Face-area magnitude distribution |Sf|\", np.linalg.norm(np.asarray(mesh.Sf), axis=1), bins=90, log_y=True)\n", + "density_svg(\"All cell centres: occupancy density\", np.asarray(mesh.C)[:, 0], np.asarray(mesh.C)[:, 1], grid=FULL_DETAIL_GRID, log_counts=True)\n", + "density_svg(\"All face centres: occupancy density\", np.asarray(mesh.Cf)[:, 0], np.asarray(mesh.Cf)[:, 1], grid=FULL_DETAIL_GRID, log_counts=True)\n", + "show_ldu_density(mesh)\n", + "\n", + "for patch in mesh.boundary:\n", + " start = int(patch.start)\n", + " stop = start + int(patch.size)\n", + " patch_cf = np.asarray(mesh.Cf[start:stop])\n", + " patch_sf = np.asarray(mesh.Sf[start:stop])\n", + " array_panel(f\"patch {patch.name}.Cf face centres\", patch_cf, open=False)\n", + " array_panel(f\"patch {patch.name}.Sf face area vectors\", patch_sf, open=False)\n", + " histogram_svg(f\"patch {patch.name}: |Sf|\", np.linalg.norm(patch_sf, axis=1), bins=60, log_y=True)\n", + " density_svg(f\"patch {patch.name}: face-centre occupancy\", patch_cf[:, 0], patch_cf[:, 1], grid=64, log_counts=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-16", + "metadata": {}, + "source": [ + "### Mesh topology samples\n", + "\n", + "The arrays below are the core OpenFOAM finite-volume addressing:\n", + "\n", + "- `mesh.faces` is ragged: each face has a variable number of point labels;\n", + "- `mesh.owner[f]` is the cell on one side of internal face `f`;\n", + "- `mesh.neighbour[f]` is the cell on the other side;\n", + "- the same addressing is later reused by `MatrixView.upper` and `MatrixView.lower`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "full-detail-17", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.342450Z", + "iopub.status.busy": "2026-07-22T20:00:19.342284Z", + "iopub.status.idle": "2026-07-22T20:00:19.351503Z", + "shell.execute_reply": "2026-07-22T20:00:19.350958Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Internal face samples**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| face | owner | neighbour | n points | point labels sample | face centre Cf | area vector Sf |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| 0 | 0 | 1 | 4 | (1, 139, 30361, 30223) | (186.11558879999995, 12.236046185, 0.49999999999999994) | (-9.587000000088608e-05, -1.7999999784024112e-06, 0.0) |\n", + "| 1 | 0 | 137 | 4 | (138, 30360, 30361, 139) | (193.05779484999996, 12.694874269999998, 0.5) | (0.9177520399999999, -13.884410300000013, 0.0) |\n", + "| 2 | 0 | 29866 | 4 | (0, 1, 30223, 30222) | (193.05779395, 12.694972204999997, 0.49999999999999994) | (-0.9177561699999988, 13.884412099999992, -4.440892098500626e-16) |\n", + "| 565418 | 283398 | 283399 | 4 | (510601, 510869, 569561, 569293) | (-193.0077474, -3.9400088735, 0.5) | (-0.3432930209999996, 13.893881599999986, 0.0) |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Cell samples**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| cell | n faces | face labels sample | cell centre C | volume V |\n", + "| --- | --- | --- | --- | --- |\n", + "| 0 | 6 | (0, 1, 2, 567201, 821715, 1105115) | (193.10515306703107, 12.698053626715934, 0.4999999999999795) | 0.001361 |\n", + "| 1 | 6 | (3, 4, 5, 821933, 1105333, 0) | (179.70132111689765, 11.812065637500481, 0.49999999999999994) | 0.001215 |\n", + "| 141700 | 6 | (283019, 283020, 818344, 1101744, 282532, 283017) | (0.4132102425057547, -0.18515406274195162, 0.5) | 6.852e-05 |\n", + "| 283399 | 6 | (566982, 768522, 1051922, 448621, 565150, 565418) | (-193.1168155735373, -1.9698796355742973, 0.5) | 54.86 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "face_indices = [0, 1, 2, mesh.n_internal_faces - 1]\n", + "face_rows = []\n", + "for face_i in face_indices:\n", + " points = mesh.faces.row(face_i)\n", + " face_rows.append([\n", + " face_i,\n", + " int(mesh.owner[face_i]),\n", + " int(mesh.neighbour[face_i]),\n", + " len(points),\n", + " tuple(int(x) for x in points[:8]),\n", + " tuple(float(x) for x in mesh.Cf[face_i]),\n", + " tuple(float(x) for x in mesh.Sf[face_i]),\n", + " ])\n", + "show_table(\"Internal face samples\", [\"face\", \"owner\", \"neighbour\", \"n points\", \"point labels sample\", \"face centre Cf\", \"area vector Sf\"], face_rows)\n", + "\n", + "cell_rows = []\n", + "for cell_i in [0, 1, mesh.n_cells // 2, mesh.n_cells - 1]:\n", + " faces_i = mesh.cells.row(cell_i)\n", + " cell_rows.append([\n", + " cell_i,\n", + " len(faces_i),\n", + " tuple(int(x) for x in faces_i[:10]),\n", + " tuple(float(x) for x in mesh.C[cell_i]),\n", + " float(mesh.V[cell_i]),\n", + " ])\n", + "show_table(\"Cell samples\", [\"cell\", \"n faces\", \"face labels sample\", \"cell centre C\", \"volume V\"], cell_rows)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-18", + "metadata": {}, + "source": [ + "## 4. Inspect registered fields and boundary conditions\n", + "\n", + "The initial state contains six important fields:\n", + "\n", + "- `U`: velocity, a cell vector field;\n", + "- `p`: kinematic pressure-like pressure used by incompressible OpenFOAM, a cell scalar field;\n", + "- `phi`: face flux, a surface scalar field on internal faces plus boundary patches;\n", + "- `nut`: turbulent viscosity from the RAS model;\n", + "- `k`: turbulent kinetic energy;\n", + "- `omega`: specific dissipation rate for k-omega SST.\n", + "\n", + "The internal arrays are what the linear systems update. The boundary patch fields tell OpenFOAM how to close the equations at the wall, freestream, and empty extrusion planes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "full-detail-19", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.353167Z", + "iopub.status.busy": "2026-07-22T20:00:19.352859Z", + "iopub.status.idle": "2026-07-22T20:00:19.399841Z", + "shell.execute_reply": "2026-07-22T20:00:19.399456Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Initial field registry**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | kind | dimensions | entity | count | shape | min | max | mean |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| p | volScalar | [0 2 -2 0 0 0 0] | cell | 283400 | (283400,) | 0 | 0 | 0 |\n", + "| U | volVector | [0 1 -1 0 0 0 0] | cell | 283400 | (283400, 3) | 0 | 93.01 | 33.06 |\n", + "| phi | surfaceScalar | [0 3 -1 0 0 0 0] | internal_face | 565419 | (565419,) | -1632 | 53.68 | -41.24 |\n", + "| nut | volScalar | [0 2 -1 0 0 0 0] | cell | 283400 | (283400,) | 1.574e-17 | 3.12e-09 | 3.109e-09 |\n", + "| k | volScalar | [0 2 -2 0 0 0 0] | cell | 283400 | (283400,) | 3.635e-09 | 3.635e-09 | 3.635e-09 |\n", + "| omega | volScalar | [0 0 -1 0 0 0 0] | cell | 283400 | (283400,) | 1.165 | 1.165 | 1.165 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Boundary-condition views**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | patch | BC type | values shape | min | max | fixes value | assignable | coupled |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| p | aerofoil | zeroGradient | (1026,) | 0 | 0 | False | True | False |\n", + "| p | freestream | freestreamPressure | (1736,) | 0 | 0 | True | False | False |\n", + "| p | frontAndBack | empty | (0,) | | | False | True | False |\n", + "| U | aerofoil | noSlip | (1026, 3) | 0 | 0 | True | False | False |\n", + "| U | freestream | freestreamVelocity | (1736, 3) | 0 | 93.01 | True | False | False |\n", + "| U | frontAndBack | empty | (0, 3) | | | False | True | False |\n", + "| phi | aerofoil | calculated | (1026,) | 0 | 0 | False | True | False |\n", + "| phi | freestream | calculated | (1736,) | -382.7 | 1034 | False | True | False |\n", + "| phi | frontAndBack | empty | (0,) | | | False | True | False |\n", + "| nut | aerofoil | nutLowReWallFunction | (1026,) | 0 | 0 | True | False | False |\n", + "| nut | freestream | freestream | (1736,) | 3.12e-09 | 1.56e-05 | True | True | False |\n", + "| nut | frontAndBack | empty | (0,) | | | False | True | False |\n", + "| k | aerofoil | fixedValue | (1026,) | 3.635e-09 | 3.635e-09 | True | False | False |\n", + "| k | freestream | freestream | (1736,) | 3.635e-09 | 3.635e-09 | True | True | False |\n", + "| k | frontAndBack | empty | (0,) | | | False | True | False |\n", + "| omega | aerofoil | omegaWallFunction | (1026,) | 1.165 | 1.165 | True | False | False |\n", + "| omega | freestream | freestream | (1736,) | 1.165 | 1.165 | True | True | False |\n", + "| omega | frontAndBack | empty | (0,) | | | False | True | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_table(\n", + " \"Initial field registry\",\n", + " [\"name\", \"kind\", \"dimensions\", \"entity\", \"count\", \"shape\", \"min\", \"max\", \"mean\"],\n", + " [field_summary_row(fields[name]) for name in fields],\n", + ")\n", + "\n", + "boundary_rows = []\n", + "for name in fields:\n", + " boundary_rows.extend(boundary_field_rows(fields[name]))\n", + "show_table(\n", + " \"Boundary-condition views\",\n", + " [\"field\", \"patch\", \"BC type\", \"values shape\", \"min\", \"max\", \"fixes value\", \"assignable\", \"coupled\"],\n", + " boundary_rows,\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-20", + "metadata": {}, + "source": [ + "### Full-shape field and boundary-condition arrays\n", + "\n", + "This replaces the small-sample field dump from the original notebook. Each internal field and each boundary patch field is shown with exact shape metadata. Histograms and spatial maps use the complete arrays.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "full-detail-21", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.410758Z", + "iopub.status.busy": "2026-07-22T20:00:19.410543Z", + "iopub.status.idle": "2026-07-22T20:00:19.422292Z", + "shell.execute_reply": "2026-07-22T20:00:19.420159Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### Field `U`: `volVector` on `cell`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**U exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 1 -1 0 0 0 0] |\n", + "| entity_kind | cell |\n", + "| entity_count | 283400 |\n", + "| internal_shape | (283400, 3) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
U.internal — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " ...\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U component 0 internal values\n", + " n=283,400 finite, min=92.0791, max=93.9392, mean=93.0091, std=1.42109e-14\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U component 1 internal values\n", + " n=283,400 finite, min=6.09974, max=6.22297, mean=6.16136, std=1.77636e-15\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U component 2 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U internal vector/tensor magnitude\n", + " n=283,400 finite, min=92.2809, max=94.1451, mean=93.213, std=2.84217e-14\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U: complete internal field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[93.213, 93.213]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**U boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | noSlip |\n", + "| values shape | (1026, 3) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
U.boundary['aerofoil'].values — shape=(1026, 3) (1,026 × 3), dtype=float64, size=3,078, TRUNCATED value text; exact shape retained; size=3,078; threshold=256; edgeitems=4
[[0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " ...\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U boundary `aerofoil` values\n", + " n=3,078 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**U boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | freestreamVelocity |\n", + "| values shape | (1736, 3) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
U.boundary['freestream'].values — shape=(1736, 3) (1,736 × 3), dtype=float64, size=5,208, TRUNCATED value text; exact shape retained; size=5,208; threshold=256; edgeitems=4
[[93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " ...\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " U boundary `freestream` values\n", + " n=5,208 finite, min=0, max=93.0091, mean=33.0568, std=42.4672\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**U boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0, 3) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
U.boundary['frontAndBack'].values — shape=(0, 3) (0 × 3), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Field `p`: `volScalar` on `cell`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**p exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 2 -2 0 0 0 0] |\n", + "| entity_kind | cell |\n", + "| entity_count | 283400 |\n", + "| internal_shape | (283400,) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
p.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " p internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " p: complete internal field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**p boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | zeroGradient |\n", + "| values shape | (1026,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
p.boundary['aerofoil'].values — shape=(1026,) (1,026), dtype=float64, size=1,026, TRUNCATED value text; exact shape retained; size=1,026; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " p boundary `aerofoil` values\n", + " n=1,026 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**p boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | freestreamPressure |\n", + "| values shape | (1736,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
p.boundary['freestream'].values — shape=(1736,) (1,736), dtype=float64, size=1,736, TRUNCATED value text; exact shape retained; size=1,736; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " p boundary `freestream` values\n", + " n=1,736 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**p boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
p.boundary['frontAndBack'].values — shape=(0,) (0), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Field `phi`: `surfaceScalar` on `internal_face`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**phi exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 3 -1 0 0 0 0] |\n", + "| entity_kind | internal_face |\n", + "| entity_count | 565419 |\n", + "| internal_shape | (565419,) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
phi.internal — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787718e-03 -1.87462300e-01  1.87089263e-01 -8.57344168e-03 ... -4.08794233e+01 -9.75618397e+00  2.17640919e+01  5.36757606e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phi internal values\n", + " n=565,419 finite, min=-1631.95, max=53.6758, mean=-41.2404, std=161.171\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phi: complete internal field mapped on internal face centres\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=bin mean; occupied bins=7,291\n", + " x=[-193.023, 197.582], y=[-194.361, 195.068]\n", + " raw color range=[-1631.79, 53.6758]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**phi boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | calculated |\n", + "| values shape | (1026,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
phi.boundary['aerofoil'].values — shape=(1026,) (1,026), dtype=float64, size=1,026, TRUNCATED value text; exact shape retained; size=1,026; threshold=256; edgeitems=4
[ 0.  0.  0.  0. ...  0. -0.  0. -0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phi boundary `aerofoil` values\n", + " n=1,026 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**phi boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | calculated |\n", + "| values shape | (1736,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
phi.boundary['freestream'].values — shape=(1736,) (1,736), dtype=float64, size=1,736, TRUNCATED value text; exact shape retained; size=1,736; threshold=256; edgeitems=4
[ 0.83994191  0.84201829  0.84387795  0.8455505  ... -0.90038459 -0.87774364 -0.85567199 -0.83415537]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phi boundary `freestream` values\n", + " n=1,736 finite, min=-382.701, max=1033.56, mean=2.09561e-15, std=123.688\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**phi boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
phi.boundary['frontAndBack'].values — shape=(0,) (0), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Field `nut`: `volScalar` on `cell`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**nut exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 2 -1 0 0 0 0] |\n", + "| entity_kind | cell |\n", + "| entity_count | 283400 |\n", + "| internal_shape | (283400,) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
nut.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[3.12e-09 3.12e-09 3.12e-09 3.12e-09 ... 3.12e-09 3.12e-09 3.12e-09 3.12e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut internal values\n", + " n=283,400 finite, min=1.57427e-17, max=3.12e-09, mean=3.1087e-09, std=1.87388e-10\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut: complete internal field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[3.10124e-09, 3.12e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**nut boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | nutLowReWallFunction |\n", + "| values shape | (1026,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
nut.boundary['aerofoil'].values — shape=(1026,) (1,026), dtype=float64, size=1,026, TRUNCATED value text; exact shape retained; size=1,026; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut boundary `aerofoil` values\n", + " n=1,026 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**nut boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | freestream |\n", + "| values shape | (1736,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
nut.boundary['freestream'].values — shape=(1736,) (1,736), dtype=float64, size=1,736, TRUNCATED value text; exact shape retained; size=1,736; threshold=256; edgeitems=4
[3.12e-09 3.12e-09 3.12e-09 3.12e-09 ... 1.56e-05 1.56e-05 1.56e-05 1.56e-05]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut boundary `freestream` values\n", + " n=1,736 finite, min=3.12e-09, max=1.56e-05, mean=7.68476e-06, std=7.79757e-06\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**nut boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
nut.boundary['frontAndBack'].values — shape=(0,) (0), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Field `k`: `volScalar` on `cell`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**k exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 2 -2 0 0 0 0] |\n", + "| entity_kind | cell |\n", + "| entity_count | 283400 |\n", + "| internal_shape | (283400,) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
k.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09 ... 3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k internal values\n", + " n=283,400 finite, min=3.59895e-09, max=3.67166e-09, mean=3.63531e-09, std=1.24077e-24\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k: complete internal field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[3.63531e-09, 3.63531e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**k boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | fixedValue |\n", + "| values shape | (1026,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
k.boundary['aerofoil'].values — shape=(1026,) (1,026), dtype=float64, size=1,026, TRUNCATED value text; exact shape retained; size=1,026; threshold=256; edgeitems=4
[3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09 ... 3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k boundary `aerofoil` values\n", + " n=1,026 finite, min=3.59895e-09, max=3.67166e-09, mean=3.63531e-09, std=8.27181e-25\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**k boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | freestream |\n", + "| values shape | (1736,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
k.boundary['freestream'].values — shape=(1736,) (1,736), dtype=float64, size=1,736, TRUNCATED value text; exact shape retained; size=1,736; threshold=256; edgeitems=4
[3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09 ... 3.635307e-09 3.635307e-09 3.635307e-09 3.635307e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k boundary `freestream` values\n", + " n=1,736 finite, min=3.59895e-09, max=3.67166e-09, mean=3.63531e-09, std=4.1359e-25\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**k boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
k.boundary['frontAndBack'].values — shape=(0,) (0), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Field `omega`: `volScalar` on `cell`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**omega exact field metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| dimensions | [0 0 -1 0 0 0 0] |\n", + "| entity_kind | cell |\n", + "| entity_count | 283400 |\n", + "| internal_shape | (283400,) |\n", + "| internal_dtype | float64 |\n", + "| boundary_patch_count | 3 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
omega.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[1.1651625 1.1651625 1.1651625 1.1651625 ... 1.1651625 1.1651625 1.1651625 1.1651625]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega internal values\n", + " n=283,400 finite, min=1.15351, max=1.17681, mean=1.16516, std=2.22045e-16\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega: complete internal field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[1.16516, 1.16516]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**omega boundary patch `aerofoil` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | omegaWallFunction |\n", + "| values shape | (1026,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | False |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
omega.boundary['aerofoil'].values — shape=(1026,) (1,026), dtype=float64, size=1,026, TRUNCATED value text; exact shape retained; size=1,026; threshold=256; edgeitems=4
[1.1651625 1.1651625 1.1651625 1.1651625 ... 1.1651625 1.1651625 1.1651625 1.1651625]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega boundary `aerofoil` values\n", + " n=1,026 finite, min=1.15351, max=1.17681, mean=1.16516, std=2.22045e-16\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**omega boundary patch `freestream` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | freestream |\n", + "| values shape | (1736,) |\n", + "| values dtype | float64 |\n", + "| fixes value | True |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
omega.boundary['freestream'].values — shape=(1736,) (1,736), dtype=float64, size=1,736, TRUNCATED value text; exact shape retained; size=1,736; threshold=256; edgeitems=4
[1.1651625 1.1651625 1.1651625 1.1651625 ... 1.1651625 1.1651625 1.1651625 1.1651625]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega boundary `freestream` values\n", + " n=1,736 finite, min=1.15351, max=1.17681, mean=1.16516, std=2.22045e-16\n", + " x=value, y=log1p(count), bins=60\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**omega boundary patch `frontAndBack` metadata**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| property | value |\n", + "| --- | --- |\n", + "| BC type | empty |\n", + "| values shape | (0,) |\n", + "| values dtype | float64 |\n", + "| fixes value | False |\n", + "| assignable | True |\n", + "| coupled | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
omega.boundary['frontAndBack'].values — shape=(0,) (0), dtype=float64, size=0, complete value text
[]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for name in [\"U\", \"p\", \"phi\", \"nut\", \"k\", \"omega\"]:\n", + " field = fields[name]\n", + " display(Markdown(f\"#### Field `{name}`: `{field.kind}` on `{field.entity_kind}`\"))\n", + " show_table(\n", + " f\"{name} exact field metadata\",\n", + " [\"property\", \"value\"],\n", + " [\n", + " [\"dimensions\", field.dimensions],\n", + " [\"entity_kind\", field.entity_kind],\n", + " [\"entity_count\", field.entity_count],\n", + " [\"internal_shape\", np.asarray(field.internal).shape],\n", + " [\"internal_dtype\", np.asarray(field.internal).dtype],\n", + " [\"boundary_patch_count\", len(field.boundary)],\n", + " ],\n", + " )\n", + " show_field_histograms(field)\n", + " if field.entity_kind == \"cell\" or np.asarray(field.internal).shape[0] == mesh.n_cells:\n", + " show_cell_field_map(mesh, field, title=f\"{name}: complete internal field mapped on cell centres\")\n", + " elif field.entity_kind == \"face\" or np.asarray(field.internal).shape[0] == mesh.n_internal_faces:\n", + " show_face_field_map(mesh, field, title=f\"{name}: complete internal field mapped on internal face centres\")\n", + " for patch_name, patch_field in field.boundary.items():\n", + " values = np.asarray(patch_field.values)\n", + " show_table(\n", + " f\"{name} boundary patch `{patch_name}` metadata\",\n", + " [\"property\", \"value\"],\n", + " [\n", + " [\"BC type\", patch_field.type],\n", + " [\"values shape\", values.shape],\n", + " [\"values dtype\", values.dtype],\n", + " [\"fixes value\", patch_field.fixes_value],\n", + " [\"assignable\", patch_field.assignable],\n", + " [\"coupled\", patch_field.coupled],\n", + " ],\n", + " )\n", + " array_panel(f\"{name}.boundary[{patch_name!r}].values\", values, open=False)\n", + " if values.size:\n", + " histogram_svg(f\"{name} boundary `{patch_name}` values\", values, bins=60, log_y=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-22", + "metadata": {}, + "source": [ + "## 5. The equations behind the objects\n", + "\n", + "For this steady incompressible RANS run, the solver is seeking a fixed point of the discretized equations, not integrating real physical time.\n", + "\n", + "Continuity enforces mass conservation:\n", + "\n", + "$$\\nabla \\cdot U = 0$$\n", + "\n", + "OpenFOAM stores the face-normal volume flux as `phi`. The momentum equation, after RANS modelling and finite-volume discretization, becomes a sparse linear system for velocity:\n", + "\n", + "$$A_U U = H(U, \\phi, \\nu_\\mathrm{eff}) - \\nabla p$$\n", + "\n", + "where `nuEff = nu + nut` is affected by the k-omega SST turbulence model. SIMPLE/SIMPLEC alternates between:\n", + "\n", + "1. assemble/solve a momentum predictor for `U`;\n", + "2. assemble/solve a pressure equation for `p` so corrected `phi` satisfies continuity;\n", + "3. correct `U`, `p`, and `phi`;\n", + "4. update turbulence quantities `k`, `omega`, and `nut`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "full-detail-23", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.425612Z", + "iopub.status.busy": "2026-07-22T20:00:19.425445Z", + "iopub.status.idle": "2026-07-22T20:00:19.438238Z", + "shell.execute_reply": "2026-07-22T20:00:19.431531Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Split-step execution plan**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Step | Phase | What to watch |\n", + "| --- | --- | --- |\n", + "| pre_solve | time | OpenFOAM preSolve hook: mesh/field housekeeping before the loop |\n", + "| advance_time | time | increment pseudo-time from 0 to 1 |\n", + "| begin_pimple_iteration | pimple | enter the SIMPLE/PIMPLE outer corrector |\n", + "| fv_models_correct | pimple | apply fvModels if present; none are active here |\n", + "| pre_predictor | pimple | module hook before momentum/turbulence predictor |\n", + "| momentum_transport_predictor | momentum | predict turbulence/momentum-transport state if enabled |\n", + "| assemble_momentum_terms | momentum | split the pieces that will become UEqn |\n", + "| assemble_UEqn | momentum | build the sparse fvVectorMatrix for U |\n", + "| relax_UEqn | momentum | apply equation relaxation from fvSolution |\n", + "| constrain_UEqn | momentum | apply constraints/boundary equation changes |\n", + "| solve_UEqn | momentum | linear solve for U components |\n", + "| compute_pressure_inputs | pressure | compute rAU, HbyA, phiHbyA, rAtU |\n", + "| assemble_pEqn | pressure | build the sparse fvScalarMatrix for p |\n", + "| solve_pEqn | pressure | pressure solves and flux update |\n", + "| correct_velocity_pressure_flux | pressure | final SIMPLEC correction of U, p, phi |\n", + "| momentum_transport_correct | momentum | solve/correct k, omega, nut |\n", + "| end_pimple_iteration | pimple | leave the outer corrector |\n", + "| post_solve | time | postSolve hook; optional write disabled here |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "step_plan = [\n", + " [\"pre_solve\", \"time\", \"OpenFOAM preSolve hook: mesh/field housekeeping before the loop\"],\n", + " [\"advance_time\", \"time\", \"increment pseudo-time from 0 to 1\"],\n", + " [\"begin_pimple_iteration\", \"pimple\", \"enter the SIMPLE/PIMPLE outer corrector\"],\n", + " [\"fv_models_correct\", \"pimple\", \"apply fvModels if present; none are active here\"],\n", + " [\"pre_predictor\", \"pimple\", \"module hook before momentum/turbulence predictor\"],\n", + " [\"momentum_transport_predictor\", \"momentum\", \"predict turbulence/momentum-transport state if enabled\"],\n", + " [\"assemble_momentum_terms\", \"momentum\", \"split the pieces that will become UEqn\"],\n", + " [\"assemble_UEqn\", \"momentum\", \"build the sparse fvVectorMatrix for U\"],\n", + " [\"relax_UEqn\", \"momentum\", \"apply equation relaxation from fvSolution\"],\n", + " [\"constrain_UEqn\", \"momentum\", \"apply constraints/boundary equation changes\"],\n", + " [\"solve_UEqn\", \"momentum\", \"linear solve for U components\"],\n", + " [\"compute_pressure_inputs\", \"pressure\", \"compute rAU, HbyA, phiHbyA, rAtU\"],\n", + " [\"assemble_pEqn\", \"pressure\", \"build the sparse fvScalarMatrix for p\"],\n", + " [\"solve_pEqn\", \"pressure\", \"pressure solves and flux update\"],\n", + " [\"correct_velocity_pressure_flux\", \"pressure\", \"final SIMPLEC correction of U, p, phi\"],\n", + " [\"momentum_transport_correct\", \"momentum\", \"solve/correct k, omega, nut\"],\n", + " [\"end_pimple_iteration\", \"pimple\", \"leave the outer corrector\"],\n", + " [\"post_solve\", \"time\", \"postSolve hook; optional write disabled here\"],\n", + "]\n", + "show_table(\"Split-step execution plan\", [\"Step\", \"Phase\", \"What to watch\"], step_plan)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-24", + "metadata": {}, + "source": [ + "## 6. Start the split-step walk\n", + "\n", + "`TransformResult` is the central learning object. Every step returns:\n", + "\n", + "- `name` and `phase`;\n", + "- `inputs`: fields/matrices consumed by that step;\n", + "- `outputs`: fields/matrices/results produced by that step;\n", + "- `changed_fields`: high-level names that changed;\n", + "- `source`: OpenFOAM source file/function/line provenance when known.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "full-detail-25", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.443811Z", + "iopub.status.busy": "2026-07-22T20:00:19.443591Z", + "iopub.status.idle": "2026-07-22T20:00:19.482622Z", + "shell.execute_reply": "2026-07-22T20:00:19.481846Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial split-step snapshot captured for: ['U', 'k', 'nut', 'omega', 'p', 'phi']\n" + ] + } + ], + "source": [ + "transform_results = []\n", + "initial_snapshot = field_snapshot(stepper.fields())\n", + "\n", + "\n", + "def record(result):\n", + " transform_results.append(result)\n", + " show_table(\n", + " f\"TransformResult: {result.name}\",\n", + " [\"name\", \"phase\", \"changed\", \"inputs\", \"outputs\", \"source\"],\n", + " [transform_row(result)],\n", + " )\n", + " return result\n", + "\n", + "print(\"Initial split-step snapshot captured for:\", sorted(initial_snapshot))\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-26", + "metadata": {}, + "source": [ + "### Time and SIMPLE loop setup\n", + "\n", + "These steps move OpenFOAM from case time `0` to pseudo-time `1` and open the outer SIMPLE/PIMPLE corrector. No velocity/pressure solve has happened yet.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "full-detail-27", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.484224Z", + "iopub.status.busy": "2026-07-22T20:00:19.484011Z", + "iopub.status.idle": "2026-07-22T20:00:19.496615Z", + "shell.execute_reply": "2026-07-22T20:00:19.496029Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: pre_solve**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| pre_solve | time | mesh, Uf | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:165-201::preSolve |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: advance_time**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| advance_time | time | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: begin_pimple_iteration**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| begin_pimple_iteration | pimple | — | — | active, state | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: fv_models_correct**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| fv_models_correct | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: pre_predictor**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| pre_predictor | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: momentum_transport_predict**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| momentum_transport_predict | momentum | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:208-211::momentumTransportPredictor |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**State after loop setup**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Key | Value |\n", + "| --- | --- |\n", + "| case_path | /home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case |\n", + "| solver_name | incompressibleFluid |\n", + "| time_name | 1 |\n", + "| time_index | 1 |\n", + "| time_value | 1 |\n", + "| delta_t | 1 |\n", + "| pimple_iteration_open | True |\n", + "| has_momentum_matrix | False |\n", + "| has_pressure_inputs | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for label, fn in [\n", + " (\"pre_solve\", stepper.pre_solve),\n", + " (\"advance_time\", stepper.advance_time),\n", + " (\"begin_pimple_iteration\", stepper.begin_pimple_iteration),\n", + " (\"fv_models_correct\", stepper.fv_models_correct),\n", + " (\"pre_predictor\", stepper.pre_predictor),\n", + " (\"momentum_transport_predictor\", stepper.momentum_transport_predictor),\n", + "]:\n", + " record(fn())\n", + "\n", + "show_table(\"State after loop setup\", [\"Key\", \"Value\"], list(stepper.state().items()))\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-28", + "metadata": {}, + "source": [ + "## 7. Momentum equation terms\n", + "\n", + "Before building the complete velocity matrix, the wrapper asks OpenFOAM for the pieces of the momentum equation. This is the best place to learn what `UEqn` is made of.\n", + "\n", + "The implicit pieces become matrix coefficients. The explicit pieces become source-like fields.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "full-detail-29", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.498401Z", + "iopub.status.busy": "2026-07-22T20:00:19.498073Z", + "iopub.status.idle": "2026-07-22T20:00:19.699758Z", + "shell.execute_reply": "2026-07-22T20:00:19.699342Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: assemble_momentum_terms**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| assemble_momentum_terms | momentum | — | p, U, phi, nut, k, omega | terms, source | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:36-53::Foam::solvers::incompressibleFluid::momentumPredictor |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Momentum-term decomposition**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | OpenFOAM expression | implicit | inputs | payload |\n", + "| --- | --- | --- | --- | --- |\n", + "| assemble_momentum_ddt | fvm::ddt(U) | True | U, phi, p | diag (283400,), source (283400, 3), upper None |\n", + "| assemble_momentum_div_phi_U | fvm::div(phi,U) | True | U, phi, p | diag (283400,), source (283400, 3), upper (565419,) |\n", + "| assemble_momentum_divDevSigma | momentumTransport->divDevSigma(U) | True | U, phi, p | diag (283400,), source (283400, 3), upper (565419,) |\n", + "| assemble_momentum_sources | fvModels().source(U) | True | U, phi, p | diag (283400,), source (283400, 3), upper None |\n", + "| assemble_momentum_MRF_DDt | MRF.DDt(U) | False | U | field MRFZoneList:DDt, shape (283400, 3), l2 0 |\n", + "| assemble_momentum_pressure_rhs_grad_p | -fvc::grad(p) | False | p | field grad(p), shape (283400, 3), l2 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "terms_result = record(stepper.assemble_momentum_terms())\n", + "terms = terms_result.outputs[\"terms\"]\n", + "term_rows = []\n", + "for term in terms:\n", + " if \"matrix\" in term:\n", + " matrix = term[\"matrix\"]\n", + " diag = arr_stats(matrix.diag)\n", + " source = arr_stats(matrix.source)\n", + " upper_shape = None if matrix.upper is None else tuple(np.asarray(matrix.upper).shape)\n", + " payload = f\"diag {diag['shape']}, source {source['shape']}, upper {upper_shape}\"\n", + " else:\n", + " field = term[\"field\"]\n", + " stats = arr_stats(field.internal)\n", + " payload = f\"field {field.name}, shape {stats['shape']}, l2 {fmt(stats['l2'])}\"\n", + " term_rows.append([\n", + " term[\"name\"],\n", + " term[\"kind\"],\n", + " term[\"implicit\"],\n", + " \", \".join(term[\"inputs\"]),\n", + " payload,\n", + " ])\n", + "show_table(\"Momentum-term decomposition\", [\"name\", \"OpenFOAM expression\", \"implicit\", \"inputs\", \"payload\"], term_rows)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-30", + "metadata": {}, + "source": [ + "### Full-shape momentum-term payloads\n", + "\n", + "Each term below is either a full matrix payload or a field payload. The raw panels keep complete shape metadata; histograms consume all coefficients or field values.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "full-detail-31", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_ddt` — `fvm::ddt(U)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_ddt.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_ddt.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " ...\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_ddt.diag coefficient distribution\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_ddt.source distribution\n", + " n=850,200 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_div_phi_U` — `fvm::div(phi,U)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_div_phi_U.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[1.87089263e-01 1.82963849e-01 1.70467373e-01 1.58836418e-01 ... 3.78668061e+02 3.73605332e+02 3.99969387e+02 4.36376495e+02]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_div_phi_U.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[-7.05168044e-13 -4.34221328e-15  0.00000000e+00]\n",
+       " [-1.27219059e-13 -4.18512726e-14  0.00000000e+00]\n",
+       " [ 6.58276063e-13  4.17470685e-14  0.00000000e+00]\n",
+       " [ 4.47464866e-14  3.70092311e-14  0.00000000e+00]\n",
+       " ...\n",
+       " [ 2.60823561e-12 -1.30219992e-13  0.00000000e+00]\n",
+       " [ 2.62017246e-13  2.56321219e-14  0.00000000e+00]\n",
+       " [ 1.78859210e-12  1.15501967e-13  0.00000000e+00]\n",
+       " [ 6.98628865e-13 -1.22370729e-13  0.00000000e+00]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_div_phi_U.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787718e-03 -1.87462300e-01  0.00000000e+00 -8.57344168e-03 ... -4.08794233e+01 -9.75618397e+00  0.00000000e+00  0.00000000e+00]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_div_phi_U.lower — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[  0.           0.          -0.18708926   0.         ...   0.           0.         -21.76409186 -53.67576057]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_div_phi_U.diag coefficient distribution\n", + " n=283,400 finite, min=-7.43849e-15, max=1639.56, mean=82.3761, std=224.185\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_div_phi_U.source distribution\n", + " n=850,200 finite, min=-2.83813, max=2.83813, mean=1.29282e-19, std=0.0453185\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_div_phi_U.upper coefficient distribution\n", + " n=565,419 finite, min=-1631.95, max=0, mean=-41.2645, std=161.165\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_div_phi_U.lower coefficient distribution\n", + " n=565,419 finite, min=-53.6758, max=0, mean=-0.0240981, std=0.278605\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_divDevSigma` — `momentumTransport->divDevSigma(U)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_divDevSigma.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[4.38031234e+00 4.24314830e+00 4.10839121e+00 3.97601895e+00 ... 1.17597557e-04 1.16564118e-04 1.15567290e-04 1.14997131e-04]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_divDevSigma.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[ 3.44131100e-18 -4.72770839e-16  4.64136331e-19]\n",
+       " [-6.78603060e-19 -2.03523451e-17 -4.88457210e-19]\n",
+       " [ 5.18358783e-17  3.43732527e-16 -9.50705393e-19]\n",
+       " [-1.83101493e-17  5.34586731e-16  5.21049275e-19]\n",
+       " ...\n",
+       " [-3.00758949e-20  2.36330044e-20 -3.69113144e-20]\n",
+       " [-4.27221240e-20  1.11161689e-19  6.85057839e-20]\n",
+       " [ 1.85703851e-20 -3.45231393e-19 -1.88776643e-22]\n",
+       " [ 9.30099529e-21  1.46540804e-19 -1.26750121e-21]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_divDevSigma.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-1.11501221e-10 -2.16066526e+00 -2.21964708e+00 -1.14931800e-10 ... -5.69477417e-05 -5.64008384e-05 -5.58727140e-05 -5.53628040e-05]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_divDevSigma.diag coefficient distribution\n", + " n=283,400 finite, min=4.22094e-05, max=4.38031, mean=0.0174517, std=0.138364\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_divDevSigma.source distribution\n", + " n=850,200 finite, min=-0.23184, max=0.10648, mean=-0.000101892, std=0.00384959\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_divDevSigma.upper coefficient distribution\n", + " n=565,419 finite, min=-2.21965, max=-1.11501e-10, mean=-0.00437359, std=0.0491913\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_sources` — `fvModels().source(U)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_sources.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[0. 0. 0. 0. ... 0. 0. 0. 0.]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
term assemble_momentum_sources.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " ...\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_sources.diag coefficient distribution\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_sources.source distribution\n", + " n=850,200 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_MRF_DDt` — `MRF.DDt(U)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
MRFZoneList:DDt.internal — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " ...\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " MRFZoneList:DDt component 0 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " MRFZoneList:DDt component 1 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " MRFZoneList:DDt component 2 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " MRFZoneList:DDt internal vector/tensor magnitude\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_MRF_DDt: field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Momentum term `assemble_momentum_pressure_rhs_grad_p` — `-fvc::grad(p)`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
grad(p).internal — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " ...\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]\n",
+       " [0. 0. 0.]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " grad(p) component 0 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " grad(p) component 1 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " grad(p) component 2 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " grad(p) internal vector/tensor magnitude\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " term assemble_momentum_pressure_rhs_grad_p: field mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for term in terms:\n", + " display(Markdown(f\"#### Momentum term `{term['name']}` — `{term['kind']}`\"))\n", + " if \"matrix\" in term:\n", + " show_matrix_arrays(f\"term {term['name']}\", term[\"matrix\"], open_arrays=False)\n", + " else:\n", + " field = term[\"field\"]\n", + " show_field_histograms(field)\n", + " if np.asarray(field.internal).shape[0] == mesh.n_cells:\n", + " show_cell_field_map(mesh, field, title=f\"term {term['name']}: field mapped on cell centres\")\n", + " elif np.asarray(field.internal).shape[0] == mesh.n_internal_faces:\n", + " show_face_field_map(mesh, field, title=f\"term {term['name']}: field mapped on internal face centres\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-32", + "metadata": {}, + "source": [ + "## 8. Assemble, relax, and constrain `UEqn`\n", + "\n", + "`UEqn` is a `MatrixView` over an OpenFOAM `fvVectorMatrix`:\n", + "\n", + "- `diag`: one diagonal coefficient per cell;\n", + "- `upper`/`lower`: off-diagonal coefficients for internal owner-neighbour faces;\n", + "- `source`: vector right-hand side, one 3-vector per cell;\n", + "- boundary coefficient lists carry patch contributions.\n", + "\n", + "Relaxation and constraints mutate the matrix before the linear solver sees it.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "full-detail-33", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:19.706933Z", + "iopub.status.busy": "2026-07-22T20:00:19.706754Z", + "iopub.status.idle": "2026-07-22T20:00:20.047584Z", + "shell.execute_reply": "2026-07-22T20:00:20.046319Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: assemble_UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| assemble_UEqn | momentum | — | p, U, phi, nut, k, omega | UEqn | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:36-44::momentumPredictor |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: relax_UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| relax_UEqn | momentum | — | — | UEqn | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: constrain_UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| constrain_UEqn | momentum | — | — | UEqn | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**UEqn MatrixView summaries**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| label | field | rank | dimensions | diag shape | diag min | diag max | source shape | source l2 | upper | lower | diagonal | symmetric | asymmetric |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| assembled | U | vector | [0 4 -2 0 0 0 0] | (283400,) | 4.221e-05 | 1640 | (283400, 3) | 42.07 | (565419,) | (565419,) | False | False | True |\n", + "| relaxed | U | vector | [0 4 -2 0 0 0 0] | (283400,) | 0.0006976 | 1829 | (283400, 3) | 1.329e+06 | (565419,) | (565419,) | False | False | True |\n", + "| constrained | U | vector | [0 4 -2 0 0 0 0] | (283400,) | 0.0006976 | 1829 | (283400, 3) | 1.329e+06 | (565419,) | (565419,) | False | False | True |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**How relaxation/constraints changed UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| change | diag max_abs | diag l2 | source max_abs | source l2 |\n", + "| --- | --- | --- | --- | --- |\n", + "| relaxed - assembled | 199.4 | 1.426e+04 | 1.855e+04 | 1.329e+06 |\n", + "| constrained - relaxed | 0 | 0 | 0 | 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "UEqn_assembled_result = record(stepper.assemble_momentum_matrix())\n", + "UEqn_assembled = UEqn_assembled_result.outputs[\"UEqn\"]\n", + "UEqn_relaxed_result = record(stepper.relax_matrix())\n", + "UEqn_relaxed = UEqn_relaxed_result.outputs[\"UEqn\"]\n", + "UEqn_constrained_result = record(stepper.constrain_matrix())\n", + "UEqn_constrained = UEqn_constrained_result.outputs[\"UEqn\"]\n", + "\n", + "show_table(\n", + " \"UEqn MatrixView summaries\",\n", + " [\"label\", \"field\", \"rank\", \"dimensions\", \"diag shape\", \"diag min\", \"diag max\", \"source shape\", \"source l2\", \"upper\", \"lower\", \"diagonal\", \"symmetric\", \"asymmetric\"],\n", + " [\n", + " matrix_summary_row(\"assembled\", UEqn_assembled),\n", + " matrix_summary_row(\"relaxed\", UEqn_relaxed),\n", + " matrix_summary_row(\"constrained\", UEqn_constrained),\n", + " ],\n", + ")\n", + "show_table(\n", + " \"How relaxation/constraints changed UEqn\",\n", + " [\"change\", \"diag max_abs\", \"diag l2\", \"source max_abs\", \"source l2\"],\n", + " [\n", + " matrix_delta_row(\"relaxed - assembled\", UEqn_assembled, UEqn_relaxed),\n", + " matrix_delta_row(\"constrained - relaxed\", UEqn_relaxed, UEqn_constrained),\n", + " ],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-34", + "metadata": {}, + "source": [ + "### Full-shape `UEqn` coefficient arrays and sparse graph view\n", + "\n", + "The `UEqn` panels expose diagonal, source, and off-diagonal arrays before and after relaxation/constraints. The sparse-graph density plot bins the full owner-neighbour addressing used by `upper` and `lower` coefficients.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "full-detail-35", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### UEqn assembled" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn assembled.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[  4.5674016    4.42611215   4.27885859   4.13485536 ... 378.66817863 373.60544841 399.9695021  436.37660966]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn assembled.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[-7.05164602e-13 -4.81498412e-15  4.64136331e-19]\n",
+       " [-1.27219738e-13 -4.18716250e-14 -4.88457210e-19]\n",
+       " [ 6.58327899e-13  4.20908010e-14 -9.50705393e-19]\n",
+       " [ 4.47281764e-14  3.75438178e-14  5.21049275e-19]\n",
+       " ...\n",
+       " [ 2.60823558e-12 -1.30219968e-13 -3.69113144e-20]\n",
+       " [ 2.62017204e-13  2.56322331e-14  6.85057839e-20]\n",
+       " [ 1.78859212e-12  1.15501622e-13 -1.88776643e-22]\n",
+       " [ 6.98628874e-13 -1.22370583e-13 -1.26750121e-21]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn assembled.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787729e-03 -2.34812756e+00 -2.21964708e+00 -8.57344179e-03 ... -4.08794802e+01 -9.75624037e+00 -5.58727140e-05 -5.53628040e-05]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn assembled.lower — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-1.11501221e-10 -2.16066526e+00 -2.40673634e+00 -1.14931800e-10 ... -5.69477417e-05 -5.64008384e-05 -2.17641477e+01 -5.36758159e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn assembled.diag coefficient distribution\n", + " n=283,400 finite, min=4.22094e-05, max=1639.56, mean=82.3935, std=224.179\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn assembled.source distribution\n", + " n=850,200 finite, min=-2.84873, max=2.83447, mean=-0.000101892, std=0.0456304\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn assembled.upper coefficient distribution\n", + " n=565,419 finite, min=-1631.95, max=-1.43895e-07, mean=-41.2689, std=161.164\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn assembled.lower coefficient distribution\n", + " n=565,419 finite, min=-53.6758, max=-1.11501e-10, mean=-0.0284717, std=0.283\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### UEqn relaxed" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn relaxed.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[  5.07593427   4.91790239   4.75428732   4.59428374 ... 420.7479423  415.15891126 444.65102908 485.47654639]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn relaxed.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[ 4.72981890e+01  3.13325084e+00  4.64136331e-19]\n",
+       " [ 4.57409897e+01  3.03009475e+00 -4.88457210e-19]\n",
+       " [ 4.42192199e+01  2.92928568e+00 -9.50705393e-19]\n",
+       " [ 4.27310402e+01  2.83070177e+00  5.21049275e-19]\n",
+       " ...\n",
+       " [ 3.91380284e+03  2.59268405e+02 -3.69113144e-20]\n",
+       " [ 3.86485205e+03  2.56025678e+02  6.85057839e-20]\n",
+       " [ 4.15579062e+03  2.75298795e+02 -1.88776643e-22]\n",
+       " [ 4.56674314e+03  3.02522190e+02 -1.26750121e-21]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn relaxed.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787729e-03 -2.34812756e+00 -2.21964708e+00 -8.57344179e-03 ... -4.08794802e+01 -9.75624037e+00 -5.58727140e-05 -5.53628040e-05]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn relaxed.lower — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-1.11501221e-10 -2.16066526e+00 -2.40673634e+00 -1.14931800e-10 ... -5.69477417e-05 -5.64008384e-05 -2.17641477e+01 -5.36758159e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn relaxed.diag coefficient distribution\n", + " n=283,400 finite, min=0.000697607, max=1828.85, mean=91.5997, std=249.292\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn relaxed.source distribution\n", + " n=850,200 finite, min=-1.62897, max=18549.2, mean=304.325, std=1408.6\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn relaxed.upper coefficient distribution\n", + " n=565,419 finite, min=-1631.95, max=-1.43895e-07, mean=-41.2689, std=161.164\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn relaxed.lower coefficient distribution\n", + " n=565,419 finite, min=-53.6758, max=-1.11501e-10, mean=-0.0284717, std=0.283\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### UEqn constrained" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn constrained.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[  5.07593427   4.91790239   4.75428732   4.59428374 ... 420.7479423  415.15891126 444.65102908 485.47654639]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn constrained.source — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[ 4.72981890e+01  3.13325084e+00  4.64136331e-19]\n",
+       " [ 4.57409897e+01  3.03009475e+00 -4.88457210e-19]\n",
+       " [ 4.42192199e+01  2.92928568e+00 -9.50705393e-19]\n",
+       " [ 4.27310402e+01  2.83070177e+00  5.21049275e-19]\n",
+       " ...\n",
+       " [ 3.91380284e+03  2.59268405e+02 -3.69113144e-20]\n",
+       " [ 3.86485205e+03  2.56025678e+02  6.85057839e-20]\n",
+       " [ 4.15579062e+03  2.75298795e+02 -1.88776643e-22]\n",
+       " [ 4.56674314e+03  3.02522190e+02 -1.26750121e-21]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn constrained.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787729e-03 -2.34812756e+00 -2.21964708e+00 -8.57344179e-03 ... -4.08794802e+01 -9.75624037e+00 -5.58727140e-05 -5.53628040e-05]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
UEqn constrained.lower — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-1.11501221e-10 -2.16066526e+00 -2.40673634e+00 -1.14931800e-10 ... -5.69477417e-05 -5.64008384e-05 -2.17641477e+01 -5.36758159e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn constrained.diag coefficient distribution\n", + " n=283,400 finite, min=0.000697607, max=1828.85, mean=91.5997, std=249.292\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn constrained.source distribution\n", + " n=850,200 finite, min=-1.62897, max=18549.2, mean=304.325, std=1408.6\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn constrained.upper coefficient distribution\n", + " n=565,419 finite, min=-1631.95, max=-1.43895e-07, mean=-41.2689, std=161.164\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn constrained.lower coefficient distribution\n", + " n=565,419 finite, min=-53.6758, max=-1.11501e-10, mean=-0.0284717, std=0.283\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " UEqn uses this complete owner-neighbour sparse graph\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=log1p(count); occupied bins=360\n", + " x=[0, 283398], y=[1, 283399]\n", + " raw color range=[1, 5749]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for label, matrix in [\n", + " (\"UEqn assembled\", UEqn_assembled),\n", + " (\"UEqn relaxed\", UEqn_relaxed),\n", + " (\"UEqn constrained\", UEqn_constrained),\n", + "]:\n", + " display(Markdown(f\"#### {label}\"))\n", + " show_matrix_arrays(label, matrix, open_arrays=False)\n", + "show_ldu_density(mesh, \"UEqn uses this complete owner-neighbour sparse graph\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-36", + "metadata": {}, + "source": [ + "## 9. Solve the momentum predictor\n", + "\n", + "The velocity solve updates `U` but it does not by itself guarantee continuity. It is a momentum prediction using the current pressure field. The following pressure correction will adjust `p`, `phi`, and `U` to enforce mass conservation more tightly.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "full-detail-37", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:20.066676Z", + "iopub.status.busy": "2026-07-22T20:00:20.066493Z", + "iopub.status.idle": "2026-07-22T20:00:20.363147Z", + "shell.execute_reply": "2026-07-22T20:00:20.362713Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DILUPBiCGStab: Solving for Ux, Initial residual = 0.99999991606780358, Final residual = 6.4677780734704781e-09, No Iterations 11\n", + "DILUPBiCGStab: Solving for Uy, Initial residual = 0.99999968448032772, Final residual = 7.4359526559359641e-09, No Iterations 11\n" + ] + }, + { + "data": { + "text/markdown": [ + "**TransformResult: solve_UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| solve_UEqn | momentum | U | U, UEqn | performance, matrix_before, field_before, field_after | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:50-55::momentumPredictor |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Momentum linear-solver performance**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | solver | initial residual | final residual | iterations | converged | singular |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| U | DILUPBiCGStab | (0.9999999160678036, 0.9999996844803277, 0.0) | (6.467778073470478e-09, 7.435952655935964e-09, 0.0) | (11, 11, 0) | False | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Field deltas caused by solve_UEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | shape | min Δ | max Δ | mean Δ | l2 Δ | max \\|Δ\\| |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| U | (283400, 3) | -107.7 | 1.559 | -0.2652 | 2940 | 107.7 |\n", + "| p | (283400,) | 0 | 0 | 0 | 0 | 0 |\n", + "| phi | (565419,) | 0 | 0 | 0 | 0 | 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pre_momentum_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "solve_U_result = record(stepper.solve_momentum())\n", + "post_momentum_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "\n", + "show_table(\n", + " \"Momentum linear-solver performance\",\n", + " [\"field\", \"solver\", \"initial residual\", \"final residual\", \"iterations\", \"converged\", \"singular\"],\n", + " [solve_result_row(solve_U_result.outputs[\"performance\"])],\n", + ")\n", + "show_table(\n", + " \"Field deltas caused by solve_UEqn\",\n", + " [\"field\", \"shape\", \"min Δ\", \"max Δ\", \"mean Δ\", \"l2 Δ\", \"max |Δ|\"],\n", + " delta_rows(pre_momentum_snapshot, post_momentum_snapshot, names=(\"U\", \"p\", \"phi\")),\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-38", + "metadata": {}, + "source": [ + "## 10. Pressure-correction inputs\n", + "\n", + "SIMPLE pressure correction uses quantities derived from the momentum matrix:\n", + "\n", + "- `rAU`: reciprocal diagonal of the velocity matrix;\n", + "- `HbyA`: non-pressure part of the predicted velocity;\n", + "- `phiHbyA`: face flux implied by `HbyA`;\n", + "- `rAtU`: SIMPLEC-consistent reciprocal coefficient.\n", + "\n", + "These are fields, not just temporary scalars, so we can inspect their shapes and magnitudes.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "full-detail-39", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:20.371643Z", + "iopub.status.busy": "2026-07-22T20:00:20.371435Z", + "iopub.status.idle": "2026-07-22T20:00:20.492873Z", + "shell.execute_reply": "2026-07-22T20:00:20.491123Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: compute_pressure_inputs**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| compute_pressure_inputs | pressure | — | — | rAU, HbyA, phiHbyA, rAtU, adjusted_phi_for_pressure_reference, consistent, source | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:47-81::Foam::solvers::incompressibleFluid::correctPressure |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Pressure-input fields**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | kind | dimensions | entity | count | shape | min | max | mean |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| (1\\|A(U)) | volScalar | [0 0 1 0 0 0 0] | cell | 283400 | (283400,) | 1.388e-08 | 0.1278 | 0.002038 |\n", + "| HbyA | volVector | [0 1 -1 0 0 0 0] | cell | 283400 | (283400, 3) | -14.68 | 93.01 | 32.79 |\n", + "| phiHbyA | surfaceScalar | [0 3 -1 0 0 0 0] | internal_face | 565419 | (565419,) | -1632 | 53.68 | -41.24 |\n", + "| (1\\|max(((1\\|(1\\|A(U)))-H(1)),(0.1\\|(1\\|A(U))))) | volScalar | [0 0 1 0 0 0 0] | cell | 283400 | (283400,) | 6.007e-08 | 1.191 | 0.02022 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Pressure-input switches**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| key | value | meaning |\n", + "| --- | --- | --- |\n", + "| consistent | True | SIMPLEC correction path is active |\n", + "| adjusted_phi_for_pressure_reference | False | whether flux was adjusted for pressure reference |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pressure_inputs_result = record(stepper.compute_pressure_inputs())\n", + "pressure_inputs = pressure_inputs_result.outputs\n", + "pressure_input_fields = [key for key in (\"rAU\", \"HbyA\", \"phiHbyA\", \"rAtU\") if key in pressure_inputs]\n", + "show_table(\n", + " \"Pressure-input fields\",\n", + " [\"name\", \"kind\", \"dimensions\", \"entity\", \"count\", \"shape\", \"min\", \"max\", \"mean\"],\n", + " [field_summary_row(pressure_inputs[name]) for name in pressure_input_fields],\n", + ")\n", + "show_table(\n", + " \"Pressure-input switches\",\n", + " [\"key\", \"value\", \"meaning\"],\n", + " [\n", + " [\"consistent\", pressure_inputs.get(\"consistent\"), \"SIMPLEC correction path is active\"],\n", + " [\"adjusted_phi_for_pressure_reference\", pressure_inputs.get(\"adjusted_phi_for_pressure_reference\"), \"whether flux was adjusted for pressure reference\"],\n", + " ],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-40", + "metadata": {}, + "source": [ + "### Full-shape pressure-input arrays and maps\n", + "\n", + "`rAU`, `HbyA`, `phiHbyA`, and `rAtU` are full OpenFOAM fields. The plots below show their distributions and geometry-aligned binned maps.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "full-detail-41", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### Pressure input `rAU`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
(1|A(U)).internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[0.00026756 0.00024709 0.00022836 0.00021125 ... 0.12406799 0.12781799 0.12135996 0.11307441]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " (1|A(U)) internal values\n", + " n=283,400 finite, min=1.38844e-08, max=0.127818, mean=0.00203795, std=0.00809275\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " rAU: complete pressure input mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[2.86833e-05, 0.127818]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Pressure input `HbyA`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
HbyA.internal — shape=(283400, 3) (283,400 × 3), dtype=float64, size=850,200, TRUNCATED value text; exact shape retained; size=850,200; threshold=256; edgeitems=4
[[93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " ...\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]\n",
+       " [93.00914504  6.16135601  0.        ]]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " HbyA component 0 internal values\n", + " n=283,400 finite, min=-14.6831, max=93.0091, mean=92.2819, std=5.44834\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " HbyA component 1 internal values\n", + " n=283,400 finite, min=-4.63575, max=7.72001, mean=6.09312, std=0.534427\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " HbyA component 2 internal values\n", + " n=283,400 finite, min=-0.5, max=0.5, mean=0, std=0\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " HbyA internal vector/tensor magnitude\n", + " n=283,400 finite, min=2.35378, max=93.213, mean=92.4988, std=5.19794\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " HbyA: complete pressure input mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[92.0268, 93.213]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Pressure input `phiHbyA`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
phiHbyA.internal — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[-8.92787718e-03 -1.87462300e-01  1.87089263e-01 -8.57344168e-03 ... -4.08794233e+01 -9.75618397e+00  2.17640919e+01  5.36757606e+01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phiHbyA internal values\n", + " n=565,419 finite, min=-1631.95, max=53.6758, mean=-41.2405, std=161.171\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " phiHbyA: complete pressure input mapped on internal face centres\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=bin mean; occupied bins=7,291\n", + " x=[-193.023, 197.582], y=[-194.361, 195.068]\n", + " raw color range=[-1631.79, 53.6758]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Pressure input `rAtU`" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
(1|max(((1|(1|A(U)))-H(1)),(0.1|(1|A(U))))).internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[0.00267559 0.00247088 0.00228365 0.00211253 ... 0.12701319 0.12781802 0.12760753 0.12713983]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " (1|max(((1|(1|A(U)))-H(1)),(0.1|(1|A(U))))) internal values\n", + " n=283,400 finite, min=6.00735e-08, max=1.19133, mean=0.0202164, std=0.0802763\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " rAtU: complete pressure input mapped on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0.000286831, 1.19133]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for name in pressure_input_fields:\n", + " field = pressure_inputs[name]\n", + " display(Markdown(f\"#### Pressure input `{name}`\"))\n", + " show_field_histograms(field)\n", + " if np.asarray(field.internal).shape[0] == mesh.n_cells:\n", + " show_cell_field_map(mesh, field, title=f\"{name}: complete pressure input mapped on cell centres\")\n", + " elif np.asarray(field.internal).shape[0] == mesh.n_internal_faces:\n", + " show_face_field_map(mesh, field, title=f\"{name}: complete pressure input mapped on internal face centres\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-42", + "metadata": {}, + "source": [ + "## 11. Assemble and solve `pEqn`\n", + "\n", + "The pressure equation is a scalar sparse matrix. Solving it updates pressure and the face flux `phi`. In this case `nNonOrthogonalCorrectors = 3`, so OpenFOAM performs multiple pressure solves inside `solve_pressure()`; the returned `SolveResult` is the final one.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "full-detail-43", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:20.500348Z", + "iopub.status.busy": "2026-07-22T20:00:20.500108Z", + "iopub.status.idle": "2026-07-22T20:00:23.601973Z", + "shell.execute_reply": "2026-07-22T20:00:23.601600Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: assemble_pEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| assemble_pEqn | pressure | — | — | pEqn | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:83-101::correctPressure |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**pEqn MatrixView summary**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| label | field | rank | dimensions | diag shape | diag min | diag max | source shape | source l2 | upper | lower | diagonal | symmetric | asymmetric |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| assembled | p | scalar | [0 3 -1 0 0 0 0] | (283400,) | -8244 | -4.016e-07 | (283400,) | 0.4615 | (565419,) | | False | True | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DICPCG: Solving for p, Initial residual = 1, Final residual = 0.030890897351242643, No Iterations 300\n" + ] + }, + { + "data": { + "text/markdown": [ + "**TransformResult: solve_pEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DICPCG: Solving for p, Initial residual = 7.2784937401803668e-05, Final residual = 9.4967147297221812e-07, No Iterations 199\n", + "DICPCG: Solving for p, Initial residual = 1.9461086386417007e-05, Final residual = 9.8677378665869984e-07, No Iterations 160\n", + "DICPCG: Solving for p, Initial residual = 8.7397651610059266e-06, Final residual = 9.9577380572382355e-07, No Iterations 125\n" + ] + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| solve_pEqn | pressure | p, phi | p, pEqn | performance, matrix_before, field_before, p, phi | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:103-108::correctPressure |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Pressure linear-solver performance, final non-orthogonal solve**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | solver | initial residual | final residual | iterations | converged | singular |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| p | DICPCG | 8.74e-06 | 9.958e-07 | 125 | True | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Field deltas caused by solve_pEqn**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | shape | min Δ | max Δ | mean Δ | l2 Δ | max \\|Δ\\| |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| U | (283400, 3) | 0 | 0 | 0 | 0 | 0 |\n", + "| p | (283400,) | -2.074e+04 | 1.393e+05 | 7713 | 1.433e+07 | 1.393e+05 |\n", + "| phi | (565419,) | -0.12 | 0.07011 | -0.001635 | 16.37 | 0.12 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pEqn_result = record(stepper.assemble_pressure_matrix())\n", + "pEqn = pEqn_result.outputs[\"pEqn\"]\n", + "show_table(\n", + " \"pEqn MatrixView summary\",\n", + " [\"label\", \"field\", \"rank\", \"dimensions\", \"diag shape\", \"diag min\", \"diag max\", \"source shape\", \"source l2\", \"upper\", \"lower\", \"diagonal\", \"symmetric\", \"asymmetric\"],\n", + " [matrix_summary_row(\"assembled\", pEqn)],\n", + ")\n", + "\n", + "pre_pressure_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "solve_p_result = record(stepper.solve_pressure())\n", + "post_pressure_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "\n", + "show_table(\n", + " \"Pressure linear-solver performance, final non-orthogonal solve\",\n", + " [\"field\", \"solver\", \"initial residual\", \"final residual\", \"iterations\", \"converged\", \"singular\"],\n", + " [solve_result_row(solve_p_result.outputs[\"performance\"])],\n", + ")\n", + "show_table(\n", + " \"Field deltas caused by solve_pEqn\",\n", + " [\"field\", \"shape\", \"min Δ\", \"max Δ\", \"mean Δ\", \"l2 Δ\", \"max |Δ|\"],\n", + " delta_rows(pre_pressure_snapshot, post_pressure_snapshot, names=(\"U\", \"p\", \"phi\")),\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-44", + "metadata": {}, + "source": [ + "### Full-shape `pEqn` arrays\n", + "\n", + "The pressure equation is scalar, but its diagonal/off-diagonal/source arrays still span the full cell graph.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "full-detail-45", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
pEqn assembled.diag — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[-768.51401632 -687.69317782 -615.60662007 -551.29512049 ...   -1.10414391   -1.10656942   -1.09019334   -1.07202383]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
pEqn assembled.source — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[ 1.02180417e-13 -7.38853423e-14 -5.16253706e-15  2.05391260e-15 ...  0.00000000e+00  0.00000000e+00  0.00000000e+00  0.00000000e+00]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
pEqn assembled.upper — shape=(565419,) (565,419), dtype=float64, size=565,419, TRUNCATED value text; exact shape retained; size=565,419; threshold=256; edgeitems=4
[1.83571656e-08 3.87796037e+02 3.80717980e+02 1.74812696e-08 ... 4.60832668e-01 4.60561132e-01 4.57325218e-01 4.51951588e-01]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " pEqn assembled.diag coefficient distribution\n", + " n=283,400 finite, min=-8243.87, max=-4.01646e-07, mean=-25.5789, std=238.124\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " pEqn assembled.source distribution\n", + " n=283,400 finite, min=-0.031998, max=0.0169861, mean=1.13639e-17, std=0.000866946\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " pEqn assembled.upper coefficient distribution\n", + " n=565,419 finite, min=3.33494e-11, max=4122.53, mean=6.41034, std=84.5465\n", + " x=value, y=log1p(count), bins=90\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " pEqn uses this complete owner-neighbour sparse graph\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=log1p(count); occupied bins=360\n", + " x=[0, 283398], y=[1, 283399]\n", + " raw color range=[1, 5749]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |ΔU| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δp| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0.000362124, 18846.4]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δphi| spatial distribution\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=bin mean |Δ|; occupied bins=7,291\n", + " x=[-193.023, 197.582], y=[-194.361, 195.068]\n", + " raw color range=[7.31074e-07, 0.0709497]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "show_matrix_arrays(\"pEqn assembled\", pEqn, open_arrays=False)\n", + "show_ldu_density(mesh, \"pEqn uses this complete owner-neighbour sparse graph\")\n", + "for name in (\"U\", \"p\", \"phi\"):\n", + " show_delta_map(mesh, name, pre_pressure_snapshot, post_pressure_snapshot)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-46", + "metadata": {}, + "source": [ + "## 12. Correct velocity, pressure, and flux\n", + "\n", + "After solving pressure, OpenFOAM performs the final pressure/velocity/flux correction. This is where `U`, `p`, and `phi` are made consistent with the pressure equation products.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "full-detail-47", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:23.608612Z", + "iopub.status.busy": "2026-07-22T20:00:23.608438Z", + "iopub.status.idle": "2026-07-22T20:00:23.673668Z", + "shell.execute_reply": "2026-07-22T20:00:23.672454Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "time step continuity errors : sum local = 7.4676177118375265e-06, global = 9.9407679212193635e-07\n" + ] + }, + { + "data": { + "text/markdown": [ + "**TransformResult: correct_velocity_pressure_flux**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| correct_velocity_pressure_flux | pressure | p, U, phi | — | p, U, phi, source | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Field deltas caused by correct_velocity_pressure_flux**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | shape | min Δ | max Δ | mean Δ | l2 Δ | max \\|Δ\\| |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| U | (283400, 3) | -142.8 | 59.18 | -2.593 | 1.342e+04 | 142.8 |\n", + "| p | (283400,) | 0 | 0 | 0 | 0 | 0 |\n", + "| phi | (565419,) | 0 | 0 | 0 | 0 | 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Boundary flux after correction**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| patch | phi BC type | shape | sum(phi) | max \\|phi\\| |\n", + "| --- | --- | --- | --- | --- |\n", + "| aerofoil | calculated | (1026,) | 0 | 0 |\n", + "| freestream | calculated | (1736,) | 0.142 | 1034 |\n", + "| frontAndBack | empty | (0,) | 0 | 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pre_correction_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "correction_result = record(stepper.correct_velocity_pressure_flux())\n", + "post_correction_snapshot = field_snapshot(stepper.fields(), names=(\"U\", \"p\", \"phi\"))\n", + "\n", + "show_table(\n", + " \"Field deltas caused by correct_velocity_pressure_flux\",\n", + " [\"field\", \"shape\", \"min Δ\", \"max Δ\", \"mean Δ\", \"l2 Δ\", \"max |Δ|\"],\n", + " delta_rows(pre_correction_snapshot, post_correction_snapshot, names=(\"U\", \"p\", \"phi\")),\n", + ")\n", + "\n", + "corrected_fields = stepper.fields()\n", + "flux_rows = []\n", + "for patch_name, patch_field in corrected_fields[\"phi\"].boundary.items():\n", + " values = np.asarray(patch_field.values)\n", + " flux_rows.append([patch_name, patch_field.type, values.shape, float(values.sum()) if values.size else 0.0, float(np.max(np.abs(values))) if values.size else 0.0])\n", + "show_table(\"Boundary flux after correction\", [\"patch\", \"phi BC type\", \"shape\", \"sum(phi)\", \"max |phi|\"], flux_rows)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-48", + "metadata": {}, + "source": [ + "### Spatial view of the final pressure/velocity/flux correction\n", + "\n", + "These heatmaps use the complete delta arrays from `correct_velocity_pressure_flux()` and bin them by cell or face centre.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "full-detail-49", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |ΔU| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[3.80655e-05, 19.7646]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δp| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δphi| spatial distribution\n", + " \n", + " \n", + " points=565,419; bins=96×96; color=bin mean |Δ|; occupied bins=7,291\n", + " x=[-193.023, 197.582], y=[-194.361, 195.068]\n", + " raw color range=[0, 0]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for name in (\"U\", \"p\", \"phi\"):\n", + " show_delta_map(mesh, name, pre_correction_snapshot, post_correction_snapshot)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-50", + "metadata": {}, + "source": [ + "## 13. Correct the turbulence model\n", + "\n", + "The k-omega SST model updates turbulence state after the pressure/velocity correction. Here the wrapper exposes the resulting fields (`nut`, `k`, `omega`) rather than splitting the turbulence equations into their own matrices. That is still enough to see how turbulence state changes during one iteration.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "full-detail-51", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:23.675514Z", + "iopub.status.busy": "2026-07-22T20:00:23.675348Z", + "iopub.status.idle": "2026-07-22T20:00:24.126363Z", + "shell.execute_reply": "2026-07-22T20:00:24.119094Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DILUPBiCGStab: Solving for omega, Initial residual = " + ] + }, + { + "data": { + "text/markdown": [ + "**TransformResult: momentum_transport_correct**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.00071906933244685197, Final residual = 1.3458793712123469e-09, No Iterations 3\n", + "DILUPBiCGStab: Solving for k, Initial residual = 0.99999999999345446, Final residual = 6.2532997654966409e-09, No Iterations 7\n" + ] + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| momentum_transport_correct | momentum | viscosity, momentumTransport | — | p, U, phi, nut, k, omega | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:233-237::momentumTransportCorrector |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Field deltas caused by momentum_transport_correct**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | shape | min Δ | max Δ | mean Δ | l2 Δ | max \\|Δ\\| |\n", + "| --- | --- | --- | --- | --- | --- | --- |\n", + "| nut | (283400,) | -3.12e-09 | 1.597e-10 | -1.502e-09 | 1.144e-06 | 3.12e-09 |\n", + "| k | (283400,) | -2.202e-09 | 2.902e-08 | 1.588e-09 | 3.252e-06 | 2.902e-08 |\n", + "| omega | (283400,) | -0.06781 | 1.718e+09 | 1.314e+07 | 5.498e+10 | 1.718e+09 |\n", + "| U | (283400, 3) | 0 | 0 | 0 | 0 | 0 |\n", + "| p | (283400,) | 0 | 0 | 0 | 0 | 0 |\n", + "| phi | (565419,) | 0 | 0 | 0 | 0 | 0 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Turbulence fields after correction**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | kind | dimensions | entity | count | shape | min | max | mean |\n", + "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n", + "| nut | volScalar | [0 2 -1 0 0 0 0] | cell | 283400 | (283400,) | 9.192e-19 | 3.28e-09 | 1.607e-09 |\n", + "| k | volScalar | [0 2 -2 0 0 0 0] | cell | 283400 | (283400,) | 1.434e-09 | 3.266e-08 | 5.224e-09 |\n", + "| omega | volScalar | [0 0 -1 0 0 0 0] | cell | 283400 | (283400,) | 1.097 | 1.718e+09 | 1.314e+07 |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pre_turbulence_snapshot = field_snapshot(stepper.fields(), names=(\"nut\", \"k\", \"omega\", \"U\", \"p\", \"phi\"))\n", + "turbulence_result = record(stepper.momentum_transport_corrector())\n", + "post_turbulence_snapshot = field_snapshot(stepper.fields(), names=(\"nut\", \"k\", \"omega\", \"U\", \"p\", \"phi\"))\n", + "\n", + "show_table(\n", + " \"Field deltas caused by momentum_transport_correct\",\n", + " [\"field\", \"shape\", \"min Δ\", \"max Δ\", \"mean Δ\", \"l2 Δ\", \"max |Δ|\"],\n", + " delta_rows(pre_turbulence_snapshot, post_turbulence_snapshot, names=(\"nut\", \"k\", \"omega\", \"U\", \"p\", \"phi\")),\n", + ")\n", + "show_table(\n", + " \"Turbulence fields after correction\",\n", + " [\"name\", \"kind\", \"dimensions\", \"entity\", \"count\", \"shape\", \"min\", \"max\", \"mean\"],\n", + " [field_summary_row(stepper.fields()[name]) for name in (\"nut\", \"k\", \"omega\")],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-52", + "metadata": {}, + "source": [ + "### Full-shape turbulence-correction outputs\n", + "\n", + "The turbulence corrector updates `nut`, `k`, and `omega`. The raw panels and maps below expose the complete post-correction fields and complete one-iteration deltas.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "full-detail-53", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "#### Turbulence field `nut` after correction" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
nut.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[3.12299427e-09 3.12135019e-09 3.12274815e-09 3.12226472e-09 ... 3.11722210e-09 3.11720802e-09 3.11721107e-09 3.11721779e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut internal values\n", + " n=283,400 finite, min=9.19177e-19, max=3.2797e-09, mean=1.60719e-09, std=1.53864e-09\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " nut: post-correction field on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[6.06727e-10, 3.13788e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δnut| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[3.99598e-14, 2.49499e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Turbulence field `k` after correction" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
k.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[3.64046932e-09 3.63712021e-09 3.64010971e-09 3.63917170e-09 ... 3.58815537e-09 3.58786899e-09 3.58793063e-09 3.58806572e-09]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k internal values\n", + " n=283,400 finite, min=1.43373e-09, max=3.26561e-08, mean=5.22354e-09, std=5.89869e-09\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " k: post-correction field on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[3.41962e-09, 6.28036e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δk| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[5.45733e-13, 2.6708e-09]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "#### Turbulence field `omega` after correction" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
omega.internal — shape=(283400,) (283,400), dtype=float64, size=283,400, TRUNCATED value text; exact shape retained; size=283,400; threshold=256; edgeitems=4
[1.16569837 1.1652394  1.16567508 1.16555514 ... 1.15107466 1.15098799 1.15100664 1.15104749]
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega internal values\n", + " n=283,400 finite, min=1.09735, max=1.71823e+09, mean=1.31364e+07, std=1.02433e+08\n", + " x=value, y=count, bins=80\n", + " \n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " omega: post-correction field on cell centres\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[1.09838, 2.18167e+07]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/svg+xml": [ + "\n", + " \n", + " |Δomega| spatial distribution\n", + " \n", + " \n", + " points=283,400; bins=96×96; color=bin mean |Δ|; occupied bins=4,847\n", + " x=[-193.117, 197.702], y=[-194.298, 195.038]\n", + " raw color range=[0.000175349, 2.18167e+07]\n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "for name in (\"nut\", \"k\", \"omega\"):\n", + " field = stepper.fields()[name]\n", + " display(Markdown(f\"#### Turbulence field `{name}` after correction\"))\n", + " show_field_histograms(field)\n", + " show_cell_field_map(mesh, field, title=f\"{name}: post-correction field on cell centres\")\n", + " show_delta_map(mesh, name, pre_turbulence_snapshot, post_turbulence_snapshot)\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-54", + "metadata": {}, + "source": [ + "## 14. Close the iteration and view the whole transform graph\n", + "\n", + "The final housekeeping steps close the SIMPLE/PIMPLE iteration and call `postSolve(write=False)`. The table then shows the whole path this notebook executed.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "full-detail-55", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:24.139309Z", + "iopub.status.busy": "2026-07-22T20:00:24.139042Z", + "iopub.status.idle": "2026-07-22T20:00:24.209193Z", + "shell.execute_reply": "2026-07-22T20:00:24.208452Z" + } + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "**TransformResult: end_pimple_iteration**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| end_pimple_iteration | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**TransformResult: post_solve**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| post_solve | time | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Complete executed transform graph**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| name | phase | changed | inputs | outputs | source |\n", + "| --- | --- | --- | --- | --- | --- |\n", + "| pre_solve | time | mesh, Uf | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:165-201::preSolve |\n", + "| advance_time | time | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |\n", + "| begin_pimple_iteration | pimple | — | — | active, state | native wrapper / OpenFOAM runtime |\n", + "| fv_models_correct | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |\n", + "| pre_predictor | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |\n", + "| momentum_transport_predict | momentum | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:208-211::momentumTransportPredictor |\n", + "| assemble_momentum_terms | momentum | — | p, U, phi, nut, k, omega | terms, source | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:36-53::Foam::solvers::incompressibleFluid::momentumPredictor |\n", + "| assemble_UEqn | momentum | — | p, U, phi, nut, k, omega | UEqn | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:36-44::momentumPredictor |\n", + "| relax_UEqn | momentum | — | — | UEqn | native wrapper / OpenFOAM runtime |\n", + "| constrain_UEqn | momentum | — | — | UEqn | native wrapper / OpenFOAM runtime |\n", + "| solve_UEqn | momentum | U | U, UEqn | performance, matrix_before, field_before, field_after | OpenFOAM-14/applications/modules/incompressibleFluid/momentumPredictor.C:50-55::momentumPredictor |\n", + "| compute_pressure_inputs | pressure | — | — | rAU, HbyA, phiHbyA, rAtU, adjusted_phi_for_pressure_reference, consistent, source | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:47-81::Foam::solvers::incompressibleFluid::correctPressure |\n", + "| assemble_pEqn | pressure | — | — | pEqn | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:83-101::correctPressure |\n", + "| solve_pEqn | pressure | p, phi | p, pEqn | performance, matrix_before, field_before, p, phi | OpenFOAM-14/applications/modules/incompressibleFluid/correctPressure.C:103-108::correctPressure |\n", + "| correct_velocity_pressure_flux | pressure | p, U, phi | — | p, U, phi, source | native wrapper / OpenFOAM runtime |\n", + "| momentum_transport_correct | momentum | viscosity, momentumTransport | — | p, U, phi, nut, k, omega | OpenFOAM-14/applications/modules/incompressibleFluid/incompressibleFluid.C:233-237::momentumTransportCorrector |\n", + "| end_pimple_iteration | pimple | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |\n", + "| post_solve | time | — | — | case_path, solver_name, time_name, time_index, time_value, delta_t, pimple_iteration_open, has_momentum_matrix, has_pressure_inputs | native wrapper / OpenFOAM runtime |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "**Final solver state**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| Key | Value |\n", + "| --- | --- |\n", + "| case_path | /home/aaron/data/openFOAM-RANS-to-GPU/tmp/airfrans_stepper_full_detail_learning_tool/split_case |\n", + "| solver_name | incompressibleFluid |\n", + "| time_name | 1 |\n", + "| time_index | 1 |\n", + "| time_value | 1 |\n", + "| delta_t | 1 |\n", + "| pimple_iteration_open | False |\n", + "| has_momentum_matrix | False |\n", + "| has_pressure_inputs | False |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "record(stepper.end_pimple_iteration())\n", + "record(stepper.post_solve(write=False))\n", + "\n", + "show_table(\n", + " \"Complete executed transform graph\",\n", + " [\"name\", \"phase\", \"changed\", \"inputs\", \"outputs\", \"source\"],\n", + " [transform_row(result) for result in transform_results],\n", + ")\n", + "show_table(\"Final solver state\", [\"Key\", \"Value\"], list(stepper.state().items()))\n" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-56", + "metadata": {}, + "source": [ + "## 15. Sanity check: split walk versus high-level `run_one_pimple_iteration()`\n", + "\n", + "The educational walk above called each step explicitly. The production-style convenience call `run_one_pimple_iteration()` should produce the same `U`, `p`, and `phi` for one iteration because both paths call the same OpenFOAM operations in the same order.\n", + "\n", + "The high-level call is run in a fresh Python subprocess to avoid OpenFOAM global `jobInfo` warnings from constructing a second independent case inside the same process. The resulting arrays are saved to `tmp/` and loaded back for comparison." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "full-detail-57", + "metadata": { + "execution": { + "iopub.execute_input": "2026-07-22T20:00:24.210779Z", + "iopub.status.busy": "2026-07-22T20:00:24.210628Z", + "iopub.status.idle": "2026-07-22T20:00:30.292997Z", + "shell.execute_reply": "2026-07-22T20:00:30.292487Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "subprocess returncode= 0\n", + "high-level subprocess log tail:\n", + "_full_detail_learning_tool/high_level_case\n", + "nProcs : 1\n", + "fileModificationChecking : Monitoring run-time modified files using timeStampMaster (fileModificationSkew 10)\n", + "allowSystemOperations : Allowing user-supplied system call operations\n", + "\n", + "// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //\n", + "\n", + "Selecting viscosity model constant\n", + "\n", + "Selecting momentum transport model type RAS\n", + " Selecting RAS turbulence model kOmegaSST\n", + " bounding k, min: 0 max: 3.6353069999999998e-09 average: 3.6353069999910849e-09\n", + "\n", + "Selecting patchDistMethod meshWave\n", + "\n", + "SIMPLE: Convergence criteria found\n", + " p: tolerance 0\n", + " U: tolerance 0\n", + " nuTilda: tolerance 0\n", + " k: tolerance 0\n", + " omega: tolerance 0\n", + " h: tolerance 0\n", + "\n", + "\n", + "SIMPLE: Operating solver in steady-state mode with 1 outer corrector\n", + "SIMPLE: Operating solver in SIMPLE mode\n", + "\n", + "\n", + "DILUPBiCGStab: Solving for Ux, Initial residual = 0.99999991606780358, Final residual = 6.4677780734704781e-09, No Iterations 11\n", + "DILUPBiCGStab: Solving for Uy, Initial residual = 0.99999968448032772, Final residual = 7.4359526559359641e-09, No Iterations 11\n", + "DICPCG: Solving for p, Initial residual = 1, Final residual = 0.030890897351242643, No Iterations 300\n", + "DICPCG: Solving for p, Initial residual = 7.2784937401803668e-05, Final residual = 9.4967147297221812e-07, No Iterations 199\n", + "DICPCG: Solving for p, Initial residual = 1.9461086386417007e-05, Final residual = 9.8677378665869984e-07, No Iterations 160\n", + "DICPCG: Solving for p, Initial residual = 8.7397651610059266e-06, Final residual = 9.9577380572382355e-07, No Iterations 125\n", + "time step continuity errors : sum local = 7.4676177118375265e-06, global = 9.9407679212193635e-07, cumulative = 9.9407679212193635e-07\n", + "DILUPBiCGStab: Solving for omega, Initial residual = 0.00071906933244685197, Final residual = 1.3458793712123469e-09, No Iterations 3\n", + "DILUPBiCGStab: Solving for k, Initial residual = 0.99999999999345446, Final residual = 6.2532997654966409e-09, No Iterations 7\n", + "\n" + ] + }, + { + "data": { + "text/markdown": [ + "**Split-step parity against run_one_pimple_iteration**" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/markdown": [ + "| field | split shape | run_one shape | max \\|diff\\| | allclose |\n", + "| --- | --- | --- | --- | --- |\n", + "| U | (283400, 3) | (283400, 3) | 0 | True |\n", + "| p | (283400,) | (283400,) | 0 | True |\n", + "| phi | (565419,) | (565419,) | 0 | True |" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "run_one graph:\n", + "['pre_solve', 'advance_time', 'begin_pimple_iteration', 'fv_models_correct', 'pre_predictor', 'momentum_transport_predict', 'assemble_UEqn', 'relax_UEqn', 'constrain_UEqn', 'solve_UEqn', 'constrain_U_after_momentum', 'compute_pressure_inputs', 'assemble_pEqn', 'solve_pEqn', 'update_phi_from_pEqn_flux', 'correct_velocity_pressure_flux', 'momentum_transport_correct', 'end_pimple_iteration', 'post_solve']\n" + ] + } + ], + "source": [ + "high_level_npz = WORK / \"high_level_fields.npz\"\n", + "subprocess_code = f\"\"\"\n", + "from pathlib import Path\n", + "import os\n", + "import sys\n", + "os.environ.pop('PYTHONPATH', None)\n", + "root = Path({str(ROOT)!r})\n", + "sys.path.insert(0, str(root / 'scripts'))\n", + "from prepare_airfrans_stepper_case import prepare_case\n", + "from openfoam_env import apply_openfoam_env\n", + "apply_openfoam_env()\n", + "import numpy as np\n", + "import foam_stepper as foam\n", + "raw_case = Path({str(RAW_CASE)!r})\n", + "high_level_case = Path({str(HIGH_LEVEL_CASE)!r})\n", + "out = Path({str(high_level_npz)!r})\n", + "prepare_case(raw_case, high_level_case, end_time=1)\n", + "result = foam.Case(high_level_case).make_stepper().run_one_pimple_iteration()\n", + "fields = result.outputs['fields']\n", + "np.savez(\n", + " out,\n", + " U=np.asarray(fields['U'].internal),\n", + " p=np.asarray(fields['p'].internal),\n", + " phi=np.asarray(fields['phi'].internal),\n", + " graph=np.asarray([node.name for node in result.outputs['graph']], dtype=object),\n", + ")\n", + "\"\"\"\n", + "completed = subprocess.run([str(PYTHON), \"-c\", subprocess_code], cwd=ROOT, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=600)\n", + "print(\"subprocess returncode=\", completed.returncode)\n", + "if completed.returncode != 0:\n", + " print(completed.stdout[-8000:])\n", + " raise SystemExit(completed.returncode)\n", + "print(\"high-level subprocess log tail:\")\n", + "print(completed.stdout[-2000:])\n", + "\n", + "high = np.load(high_level_npz, allow_pickle=True)\n", + "split_final_fields = stepper.fields()\n", + "\n", + "parity_rows = []\n", + "for name in (\"U\", \"p\", \"phi\"):\n", + " split_arr = np.asarray(split_final_fields[name].internal)\n", + " high_arr = np.asarray(high[name])\n", + " diff = split_arr - high_arr\n", + " parity_rows.append([\n", + " name,\n", + " split_arr.shape,\n", + " high_arr.shape,\n", + " float(np.max(np.abs(diff))) if diff.size else 0.0,\n", + " bool(np.allclose(split_arr, high_arr, rtol=1e-8, atol=1e-8)),\n", + " ])\n", + "show_table(\"Split-step parity against run_one_pimple_iteration\", [\"field\", \"split shape\", \"run_one shape\", \"max |diff|\", \"allclose\"], parity_rows)\n", + "\n", + "run_one_graph = list(high[\"graph\"])\n", + "print(\"run_one graph:\")\n", + "print(run_one_graph)\n", + "assert all(row[-1] for row in parity_rows)" + ] + }, + { + "cell_type": "markdown", + "id": "full-detail-58", + "metadata": {}, + "source": [ + "## What this one-iteration microscope teaches\n", + "\n", + "The AirfRANS simulation is not a black box once viewed through these intermediate objects:\n", + "\n", + "- The **mesh** is a finite-volume graph: cells, faces, owner/neighbour addressing, and boundary patches.\n", + "- The **fields** are typed OpenFOAM fields with dimensions, entity locations, and boundary conditions.\n", + "- The **momentum predictor** creates a vector sparse matrix `UEqn` from convection, turbulence stress, sources, and pressure-gradient terms.\n", + "- **Relaxation and constraints** alter matrix coefficients before solving.\n", + "- The **velocity solve** updates `U` but does not complete incompressibility.\n", + "- The **pressure correction** builds scalar matrix `pEqn`, updates `p` and `phi`, then corrects `U`/`p`/`phi` consistently.\n", + "- The **k-omega SST corrector** updates `k`, `omega`, and `nut`, changing the effective viscosity used by future momentum equations.\n", + "- `TransformResult.source` ties many Python-visible transitions back to specific OpenFOAM source files and functions.\n", + "\n", + "A next notebook can go deeper by exposing the turbulence equations as separate `MatrixView` objects, matching the already exposed momentum and pressure matrices.\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..e05b6be --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[project] +name = "openfoam-rans-to-gpu" +version = "0.1.0" +description = "OpenFOAM RANS-to-GPU experiments and Python stepper tooling" +requires-python = ">=3.12" +dependencies = [ + "foam-stepper", + "quadrants>=1.1.3", + "numpy>=2.0", + "pybind11>=2.13", +] + +[dependency-groups] +dev = [ + "ipykernel>=6.29", + "jupyterlab>=4.2", + "nbclient>=0.10", + "nbformat>=5.10", +] + +[tool.uv] +package = false + +[tool.uv.sources] +foam-stepper = { path = "python", editable = true } diff --git a/python/pyproject.toml b/python/pyproject.toml new file mode 100644 index 0000000..046c26e --- /dev/null +++ b/python/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "foam-stepper" +version = "0.2.0" +description = "Python-driven OpenFOAM observability stepper" +requires-python = ">=3.12" +dependencies = [ + "numpy>=2.0", +] + +[build-system] +requires = ["setuptools>=69"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.packages.find] +where = ["src"] diff --git a/python/src/foam_stepper/__init__.py b/python/src/foam_stepper/__init__.py new file mode 100644 index 0000000..2718b8d --- /dev/null +++ b/python/src/foam_stepper/__init__.py @@ -0,0 +1,205 @@ +"""Python-driven OpenFOAM observability stepper.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from ._runtime import configure_openfoam_environment + +configure_openfoam_environment() + +from . import _foam_stepper as _native +from .types import ( + PatchFieldView, + PatchView, + RaggedIntArray, + FieldRegistryView, + FieldView, + MatrixView, + MeshView, + SolveResult, + SourceLocation, + TransformResult, + _wrap_value, +) + +OpenFoamError = _native.OpenFoamError + + +def version() -> str: + return _native.version() + + +class Case: + """OpenFOAM case handle that creates Python-controlled steppers.""" + + def __init__(self, path: str | Path, solver: str = "incompressibleFluid", time: str | None = None, libs: list[str] | None = None): + if time is not None: + raise NotImplementedError("Explicit time selection is not implemented yet; OpenFOAM selects startTime") + if libs: + raise NotImplementedError("Additional library loading is not implemented yet") + self._path = str(path) + self._solver = solver + self._native = _native.Case(self._path, solver) + + @property + def path(self) -> str: + return self._path + + @property + def solver_name(self) -> str: + return self._solver + + def times(self) -> list[str]: + root = Path(self._path) + times: list[tuple[float, str]] = [] + for child in root.iterdir(): + if child.is_dir() and _looks_like_time(child.name): + times.append((float(child.name), child.name)) + return [name for _, name in sorted(times)] + + def control_dict(self) -> str: + return self.make_stepper().control_dict() + + def fv_schemes(self) -> str: + return self.make_stepper().fv_schemes() + + def fv_solution(self) -> str: + return self.make_stepper().fv_solution() + + def make_stepper(self) -> "SimpleStepper": + return SimpleStepper(self._native.make_stepper()) + + +class SimpleStepper: + """Python facade over the C++ OpenFOAM observability stepper.""" + + def __init__(self, native: Any): + self._native = native + + @property + def case_path(self) -> str: + return self._native.case_path + + @property + def solver_name(self) -> str: + return self._native.solver_name + + def state(self) -> dict[str, Any]: + return dict(self._native.state()) + + def control_dict(self) -> str: + return self._native.control_dict() + + def fv_schemes(self) -> str: + return self._native.fv_schemes() + + def fv_solution(self) -> str: + return self._native.fv_solution() + + def mesh(self) -> MeshView: + return MeshView.from_dict(self._native.mesh()) + + def fields(self) -> FieldRegistryView: + return FieldRegistryView.from_dict(self._native.fields()) + + def pre_solve(self) -> TransformResult: + return _transform(self._native.pre_solve()) + + def advance_time(self) -> TransformResult: + return _transform(self._native.advance_time()) + + def begin_pimple_iteration(self) -> TransformResult: + return _transform(self._native.begin_pimple_iteration()) + + def end_pimple_iteration(self) -> TransformResult: + return _transform(self._native.end_pimple_iteration()) + + def post_solve(self, write: bool = False) -> TransformResult: + return _transform(self._native.post_solve(write)) + + def fv_models_correct(self) -> TransformResult: + return _transform(self._native.fv_models_correct()) + + def pre_predictor(self) -> TransformResult: + return _transform(self._native.pre_predictor()) + + def momentum_transport_predictor(self) -> TransformResult: + return _transform(self._native.momentum_transport_predictor()) + + def momentum_transport_corrector(self) -> TransformResult: + return _transform(self._native.momentum_transport_corrector()) + + def assemble_momentum_terms(self) -> TransformResult: + return _transform(self._native.assemble_momentum_terms()) + + def assemble_momentum_matrix(self, terms: Any | None = None) -> TransformResult: + if terms is not None: + # C++ recomputes the OpenFOAM expression to preserve native invariants. + pass + return _transform(self._native.assemble_momentum_matrix()) + + def relax_matrix(self, matrix: Any | None = None) -> TransformResult: + return _transform(self._native.relax_matrix()) + + def constrain_matrix(self, matrix: Any | None = None) -> TransformResult: + return _transform(self._native.constrain_matrix()) + + def solve_momentum(self, matrix: Any | None = None) -> TransformResult: + return _transform(self._native.solve_momentum()) + + def compute_pressure_inputs(self, UEqn: Any | None = None) -> TransformResult: + return _transform(self._native.compute_pressure_inputs()) + + def assemble_pressure_matrix(self, inputs: Any | None = None) -> TransformResult: + return _transform(self._native.assemble_pressure_matrix()) + + def solve_pressure(self, matrix: Any | None = None) -> TransformResult: + return _transform(self._native.solve_pressure()) + + def correct_velocity_pressure_flux(self, inputs: Any | None = None, pEqn: Any | None = None) -> TransformResult: + return _transform(self._native.correct_velocity_pressure_flux()) + + def run_one_pimple_iteration(self) -> TransformResult: + return _transform(self._native.run_one_pimple_iteration()) + + def run_until(self, max_steps: int | None = None, max_iterations: int | None = None) -> list[TransformResult]: + limit = max_steps if max_steps is not None else max_iterations + results: list[TransformResult] = [] + while limit is None or len(results) < limit: + result = self.run_one_pimple_iteration() + results.append(result) + if not result.outputs.get("time_loop_active", False): + break + return results + + +def _transform(raw: Any) -> TransformResult: + return TransformResult.from_dict(raw) + + +def _looks_like_time(name: str) -> bool: + try: + float(name) + except ValueError: + return False + return True + + +__all__ = [ + "Case", + "SimpleStepper", + "OpenFoamError", + "PatchFieldView", + "PatchView", + "RaggedIntArray", + "FieldRegistryView", + "FieldView", + "MatrixView", + "MeshView", + "SolveResult", + "SourceLocation", + "TransformResult", + "version", +] diff --git a/python/src/foam_stepper/_foam_stepper.so b/python/src/foam_stepper/_foam_stepper.so new file mode 100755 index 0000000000000000000000000000000000000000..317b645d54245f2affed789c40d33ff0d936100c GIT binary patch literal 1457424 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 z zDti}yo()JITD!B#pc*5CyMChm!W;W{9|YQ=#)G;Ny!T+@ zL0w6rtQGrrFFC3m^8nbnK6cKnrAXKs(2;k)u+DhzONDUb%ZZr(dORrV&)#@Yw~U8= zYT`kSY$Mds$Dw}u5J%_#>^v=fe|-?I2Z{%^L$osw<3HqhP#so46Foq@_mhz>YsiC) z2UYoTo%!pD2XzCH-l%=Ep(5a!&XMX~K7(v_z!FE|=qU`Lo_J6r(4;rsdqjMJMbdsR z@!!|zEfH`EiT{2UUCd+EN)ZfrGCt_#1b1+evLMS3E)4uhlywIe2L4^_O8kQ`QJD__ zB}MnI83z7-5ChK(9ga~PT9~MfL~~uI`b5@j-Z1b#gE^vJHw^r1I>Qu^>d;OrRZ#FQ z<^+gYO>a{{ZxS5JH+CdNflF|_KY|Wie{qxR-;MuH_lN57->0yVn(^QJEW?$hu70(n z2y}O)_~XXMa7WAWzxM#>F4ZRP`Jc4$3HsH2P=XE^C+c3RdfqruQ4rv+zGX@L_gIM) zH5J=QaK6N*;J+LH{S9pR)fN9;tDUlp>MxqSrl*#C20cyVat8C)L>Awr^~Qf+F5~mW zA4wjoE7&Ln5&s>G${nv~f9!X6+fi{p{!nB9%URzmvGHzT2x!ad~*br-{{0nlPQgv5dR$=Zo0FaBO-0Y&nDC)Qz$Y z9kT+nhaS89b_8?T=~%rXNJpm>b-R=r1pCMEHtH?ncCa$jE{IaykdSE)8&=k75L+Tg zDhm|y5&trS!-v6V(O29>1W;iiz9A;XFs5af74wzqd1Z79>#o zK^5yciXn0$3s=Y&@orP!gjblwo>_<=_rj9T@SGWhzmxW@guKDlYmNI!GIo{0iE=!u z$PDhSE~AEsjADfZuNrhe`&h_6;uVv{Cv`2qmdRIUlbGI&hry32W8_(|>p?zy?I9~hGjVvFx*uB|gvza$ zs)!cnl`obvG)`oUgQH6DQ7F4?4$oh7;6v|w!>z60Sd1U}>5Ry$xQcX| zoi+y2cWy`KbK)JJ$fGMb{v8xyj(<;cEss`9XR(}zAFztQ6!L-5aw(37apmOrx0;Nv z$Vk%8Lbd8hA{lJ}Zn!01(NKa3tN%oB?P%40C^C5ZMPSA7&(V6f>Q5L-h^0%&ybyY- z1pQQvSqLBB!p8{e>h;IL#GlH=S&xEvH;fOOccV3lf7;!Y|8i=}i642Cz++T^KaAJ( z4F#^_f0XCpfD|9eB>Cr?*EjhZl=xFSW&d5`PvueJ#l3l`SN+M!^a4aXJ8EE@U%*7f zbh-gBGI}&yrFjO!-EI`hWT-7B{#3f)9C#Tv9#!8D&2rE)BD6bg4C&PW0b*p$-K?ki zr6b+(93fhU#GlG=d%Rn{L<)EOgA(=BuOBG`$U{Y{ox#R_ubRHr8-HrmJgq}Cp`bzc zTd@RmioFmOky(p8>G`Ys{;)?u)3xIZlYS0v;dlu5huw!|@;_KOHU$?6bHQTq%L)eg zqp~qwTsW=*ksjK@@nteRvv8bD60dfD80{CHh2vnI!LxA86+(>J1U{{m^p`RF5kt-Y zgZGD>^nqvn`1VlHp}9Y-^bDcHix6Q{?S=XYdIWismW=`YE19`S|#x1^IB$^WJDC6_2AJsj&f~gdn zAiVLYz~%Rz{g_k2*o8fpy7m|LAcJ>*q3rF79z- z#p;YZ38Z*mJ}QQJ{3#uEG-U$5>KxF-=+3(T4t(JnzDfm9d0-w(>rE!9=er-crCyZ8 zQ9@%mAu^<#;B>YdN&_$nH^{Z+_klkQ#z*KaYY!9tuxkYPL#ik${@HPwKb#=cAnWMz zGboW{9lb<|&;Odq^gA^QJ8dYcR6T|6wx}^s?L%_B48(UVDNuGDj^k5T{^=w)Gn2Is z#kgt>rWpnU#H7xww<2@%IeNq=&{~4pPQpd$1T<7pf~nv%s#_tEE6QAY_3Gncd(X@F za?;5xpbq!N5C7qDpn0r$$1CkUP4DKU|NR}WXFrEd)w1^#h&dzXSxoT%#NKlhMhZOH z!oJY%AF=l|BChG%V9kAh-$(2{H)BR?*?VrBdC2yj36Irf@5vqnJTms4-id-o&km>l zPn>Z4TU`BDX0JYb&l*wPpsBgL!V!DVDZ?UodTt}Bf9ZX!U(2y0kJ5NLSn3x%y|_ad zPg}^k$luUp>cUKR+Gk);>TLq(0QR0ux7KOzc@=i-TEL7qVGciqu0oM<^?e?D&lFTt zm%S&QY~2X37wG^(DJj;zPtIN(S)b`ei5-PCGy@P<;v04D86W zgu#9TfU%Hzf?2E3s&=ssGlo zekmb!oA|l(Z?Pu|e_UN~LLEyO*U#Nfd!+zyG3%Jw(E^v|fQw$o9E%ACa6UZ?AFz)3 z{cd^PWnO>ct6s;v)}FX1>zIk;TR8uRdR1#+Q8mDL*D*H_WFpovy|n1#JbBhJd$4Td z@K-|LGV7Rj1S)MZT*r)m9Zh0|NLNaCW#;ljw7-f{#_@N)H?p2t7v+wty}()4GdtRu zp6^!cxPWo|Q;*T8(3r!s)5fDBb(@)>$zoJPpPz-%h`!IY;_2>qjrEnQR1qkZ>IRm; zdrQ2B<-O+D*}=aU7TRig+gnB64S5)v>Cl~o96fgPWmYF+{1_9fyh!fE^lnk}5O5Vc3;zb3w) zX&)TT(PK-AFiw)131d5MX`$pJ?ID1G)h>P<6a-)Ka?q&SDsxVqPn0cZ0C-BC$Y5+1I371lmI?h%wa1n>#&w$>R}SgVa?sP6yF>iXOXV=#L(zI5SyVp9&KVCQ>*CmDsQnfAe_%u+DR)2!waC4gYLA~ zp$5Wp(qZfv!TYm0?730ctb*mYOKj*#u^a+#O=XOn<#v8BtNnrcgKRe0(QuPkIz~WP zl?#K2X}vqMeI(hkbTz-oz%Z8>V>nwoW_yg;WYiyGp$kn(Mm+_+p>{D4-OgBAl*A^Y z-3dO1AH!YFiZz6^3ARE4BJ&k&HLt;o;RjW#L(^zRw9_U*_|9#Os-QLv9ZI_Km+?nn z`xnKS=5VmJf7LHeeSk5^N3-VYC*2dGb14|Pto^$zapd>nVp>M)H7~FL^!HvA| zo_01|B3-cn?1b}}C~Uu6?SX)C`I)QV@rZeRh$bc- zc~{o6#~}`-=iMt%cH3MK?QeE7*yXqC}cl@hYRlnLZ8SkI`PkJ z6#MO{e9C_j`2GQZ61mIN(YLWK3FX*WYfe&BcV(OH+NN?I>(urx;ePPvU|s7_^w=%({DQhaCEtC zS6-Lfs%GRw@9Yx&OLla*tcw8r?7%OW;O}UfJ(29&8IlN$NmOxo!Tv(0bh}gTuNl5( zm!|X0$_QSX>wB+Lcll&xjK8!y-mb>))j6sA3f>Gg0J*o?6}nmfWB|b<;1K$h%a0^p z^m&lJCSLR-fSUvsfjW042+tcYx-qf^vl`)Kx;u8B9{CN^$#~JnCS`!JHtIqak1eeM ztxB@(7LWrt7|nn&7(58=q0V@u|AEsj*|?L4v&8LSBiO0CcQjYkRhccfBfHd;;am!u zM!nfBmtO9)W*rk4ZX(mZqY-#&Y!-sDH41iVlua8$PB07c07~)`&6XD_gc{46zmf+^ zny;8ANooa?z8w>)*QeJdGPFQ|9mHgqK31v~FH^aZ#DdLY=(VQMzPs?3_P*kYY{zL| ziXX)Pqqzbd;Ra{049VW!l@lH?z0UX%F>{r6Uo_k*zJR=0JiTcCB5ncy?^XslZJb6xLHTt6vy zH_FYuM0fSY#?sZt2BE8)Fl6-SejXJ^9~MCsa=SW|tj12em@S@w7DIo?^gw@b^+DVa zR{Olu=Mabg&UvS8H<bD`oc6jNB(+Pp2j>V1JfOx+Rsmn&r#(pVHSU}JmyM1#8n(Bhh;9^=_D!y^$V^;8| z&~+LW#dN2>CMyL3z6*8^JpcRiP9KQ=QQvu|S$zR7+h2em+;2Xg*izqlr=A0W7w@qD zPW-vY3SJDj3wW{ocF(z#t(5VO|D?Y(k~{-)HRoKq>Lu1OCM7^ZHkf{~PFl%Ifms8Y zWc!=2Yj{0gr*1cLth1!nI`6cTi*Y+`*3Ce{$GM8PV+v(#+;&e1Q$0bK2gAbw&O6SZr>=@0e}8JJ*de@HIShF7cgpK z%H7Ly`n=P5I;D~=V&vEB8ly~&aXPi3DVKrNa9{GdOs?rHuTw0sA*)I4#q6) zmn#diY|c9s55QQ>d8eL7%Qz?9fpPwhH3pzL0Ld!*VGy+E{;aE5#+-LLU6<*@G7C{A z+@BvbOS;sI{!u76X7rtDL3aF2P0DbpK6>;iIwjep+<=sDeUIq+{$hK8OqMron52cz zJMH}%{Y^A9gOR^tSoRozsLu0F<9lPq!~)z{{aJ)HxjFAt8d5-94U<>wFosTS({{a6%M?+%OQx5h1+UJEX91V!oe}C4o zNGAKyXN79rpY^RcX?f2IorZy#vqBrd$Qg8)+y`Xx#C5Jwv&Q{dTrX%#_5g~E@L8c5 zS|F;G*G0|>9q|6Fm#1KiSl*?3&Ifg)W`+UOzCUX&`ZFKXSEWXCP2%`ZYoN^*xzL8q z5Ms#G9RGsDbjn3Y0moR6lEjWJ;7I&EAC`$a?$1gHgzM>zMZ^K`&-w(`=vwz@jqAbs z5swM#Lqr#p{aaW%;QK<)`bF2WPqZ9}p_=Diu0**S`Q7!8b{Gz99f%2;k{7|p+wYIy zV~z87(a?|n=KS3#0;Kl&yK5jMeZ|v&gQ`8mn3y&wG~c?KT|U_R&Brje=lmUcPWXgf z{z-OV3JIkoKZjL6vdNnoIe#~z8!OR{qq$@{wdm$a%8CmLs;Up zo6gY%Xe~@rH}&LOr5ceJp{avDe|OoVwdrdo4V*$>7lV{M_OY~{=$odmleJlJ@qW!z zw*$0hI4^3^c6~!lU+a(p`Z|-05_C0=srdaIYF{1a?`Tgp^>m?FI?(yM+d+%9&flF$ zqyT+g4=x{>`Wp0gKOq+0&7>9mwQ1&YC z1ady!l@R~?y~-;oLu>6--a_iJV^)X7I;TD2_5#TM?fImOC_wG_4p$2}eMJMoLNe_a zxz%df#oT7KC-WsUcoV|32mXYE>tr+{!I=NRL-q4Jh`>Na$z}7$4+hCMM~&J}khZ)V z^ht9*>Dz{)gYNGK{Axyoa{TB0q4BFLF%%XP1TbJ|zYRnZ?qK1~3ig7*ob*)<;STwH z()CXt_Wsvz^#KN1mxUs8nDO zvGZYmgNT^ho4@s(PkQ>PgE^mM;wj?(Iys+op2~vgt?genfn4a{zQ6tiX!-xZzijhW zz{NVOvh%MD*Qq**#Pc3Z+5riQdfkIbr|Jw;YD8>Ts;FE{gdKBB zSd=_hjnMudy1#zx6CS^^p1Ghm<5zZvY#jRUyaDt!jasea|9Y3Ex9_|EjbGU&(H1>h z{?VZ6n)lZqAzF@{M?#F@`tPq#5_QG1h&l}dl34#W78%6)#pDJg^-`5b6Nn*{_Sy0* zgc8S90E!IcHx!vDMgHdgdWpwV?XX3%+6|046rN50lFc~>$FrXr#tuK~qLDL?Pil4- ze6?dvg8cfQ_?L{LP0o%VN4&1?U-ANV>uUZbU71&(Cwd%`yp~Hu*T)apzoY}iM(y)N zp)SBT<6rU@F1i7Z4d@GeYXt2i=ZW$~sCker;$N~5Qp)v%`gD`j z|IqcUpVRO7->A^_A1(EZf64m8xkeB_s1IozaQxFvrftwTVE4EaRjR9?-5K; z);>?v8A7=hFk>ELi{^#_)N_8}Q6NW|J_!^)zc7sonp4mDg%^Yl>p8zLj)`{6cp$<-oL|^W z#W8$-VIMks;PVT?%Q64v{KAV%W&VHagZW>@xpe#ux|{hIZXMB27s;B&gHZ=}e!L2bTygJUXA)jk~GgR96y5NsZ`P6uaW&+?sg)S09GUjlejfe?PM+|KK)ll zr3IT?sx|=*a?n9-!EEFhh%8aB03sRGLd=F)POyJ07c$eR5dp_uk@m`SoEfz1t0(zt z&q*MgISJMT9H!!TY?ab1_z74YI+uyS1}g4KK5xkkwoby1>L9g|jvl!4fjG+hz%l~+ zqlcapj?=g)2%HWqN%X{bUObU?TJt~wyg_yi-`e7>;^WBrD6JW^+quSH>BR43z8>q1 z`5L3;&-fqpeBF43^oFM`US`Y&bN-Lw!0{KFOli!7^M6nd)HE5W_x#^4SZPpS)0?cT zGC{9j^Aopq_y?1}MLkK$1F+o)b_8)hzl1=05qbHs3we~A{b&LJ5kWMF)D0hCm^j>} zFUp<%u%__;phQF+bp5?psmI@|ISfbM^D67W4i5Uf$|}ll1HW&-5%~4!1^8u%J;rbS zpy79_;2%6m2*Lg>&^y=PYZ>X^@wYb__X_5w-G^#b@8Rs2IH_bN@p|x@=T#o;gbWAp z_sY2!>A;s`^%7n~^BNYy$11Sk2yFhX^C}C$$L1P8uTQ_$_;ej$Am>%i(L&}&`W?bz zaimbJ|EL)Ky8m+N7|%&{`VZ$%{Jdt!;yCRV)T?rc9bSNV{k%qZWMaMNRdPAY7{+If{h6VN0H831+tynxI*t{`9bug1FCJ+HFsD-Mh2Z+Zz_#lP#}6HJeHt6jh! z6e-!Jhjk{0Wv9(RMani4@~#jw`daUKl}!(^zH-%*d=uRs!xDJU<|^E!-^hMb4gPf@ z^cs*4&W);Jm$5hT!_XVewN!H~VW^_-2e&D64`pe8ilzwVOYUWZLfBe`Zq?;p-$=JL z_v$O=DlhjsN<@X`UR^u0yAken>JYpe?)4r>mBi~C`#PElbFh;cQaG@r8V8HmJ#L}i zV(6^kOTnvO@<3-_YPqs;qXzZ|qHT&^QNgm1}`65JV%|WgF=kr*marQCCzBtFmB>^peqvzJbKN`Y0##bbhR=j!+ zWDESp{>sLJ(wDV}*9?82YpL?#?i%axc9Z^>Fw_PCe@Q72H)qG;$S$F@Jn4y=! z`XWP$JaNAi=c~kqlw8;W?uWuQf(W8qS+cZIQWP$nY0um8VtKJ(0tN-!UxgkU0uK3# zUcxg*!b{-SYJBz~K?*+BNI+mMa$6t5&OVju`zY7-Iz&w%P?1(>d~!9x+iLd@RH8PgzN%PCE}c zs$Kwai9!e`kk;WleCQ`q0ezvt5H3u-wyWiS^aO- zdK5^--S-S&hIZ1bBuED#4Ndk+O82$It&IFMjGva`B^oc8L?kBV@(;PE-SihI3vynZV|+K_ z4f{~T)a-S77+n_bW0)!SIjqJA{7`vj;E%)dk8?Ulqt!K*)C)Jr%!-$VE;)$#jip?< z;t8infAZV9ePK63`5=Wb|D+I3WFK^e>KurWP*>8M8=u=vSE~TS5RLbklC@W3N)qqb zS0ye*R&cZGM&aW4{}c;7xX%)`YS_LiflYoNU`-|*%Ve;LYCQLiF`#75BA6ZSE#0Cv ziM}}^DN#Lfx4=RMs2=1C?gKaha6!D1lNp@~=R1VQl~zDoMfh$aWv+EL_U^2Odm2_e z#*gP{xb|Kvb*bMMpgd&Ak(5LjZKAqRx1!F*FRIk7oi`X}rz-U_g{;iWiKhH)Q~pz7 z>ZKK>Y~wxBFV;8N2zltFU9cs_rDpefS6Bnp3Mz<1z4s0ys=Y4TwIs7PRlAGf&n^EcmB8i=l#$Bx3bn5Rksdb$`jqqyHy_!=_C`HF9b zzbuL2Vv$)yXg2&48V(oCS;L`yDAlVD@{;xdnpUTYA{##*&%!x_>!Qev?9diUO?PW)`m11{~-<@Gd^3T zdO%chT+I7n5>G&>&RoYi{=wg3{@ib8z`DW9dbi6calXo2)_any`EaWWWeYOTT9`XkNk%| z&M7Pw*i)5%g4J&&93mk?^7B<&6bf|}^#T4@s@>JdM6^5_$f{06B8&D18|TNfkdNwV?p+11ts;c2*aohbiIKJ@EQIa%K@#Ss za5G3VP!;Wah}XqgPLY`yneRjuJD>GGlC+25!)dqe{6)+_!YKz;C9)8s1?m~MoWXE0 z7ol8~#APi1!5y60kPos^^?-(LiOUt(_89?#f{~!q!7zXSsSI0vM^<+-f z`Fus!A(QdT@b}t4?oh6_(QJl-kRau%L~EN|o0mfTS@wq-UU}Exh0vVNj+?L9!NWLk zVK4CY1>-O;^!L5=B3)cYoLZ$*W!OwjHmMpeMfwVAw~i>b!CVcP3$v4})aUxiQs3c; z{Cb`F(nfv4Cw&WSPH?;H1||0}6%vl&shf_B^qWLLxJ@xpq07uV`2;YA&@%$)N;Ud+ z-B7wJFb&-y4H?eUS6<|PQ9c1;M*-a;gaU6Bbq;{f%YBpic_!*rCvZA|Mext%6Fv)6 zf;&|d-+^#@WD-VTp7(#I^Tw$k%(qzevneGA_$@OCP`)rvmRgP{0%ak7M4Hc7_R-n6<6Z~CW%bqa0WQDrY zbShEyQ$j<4j4Zp3!s{D|tm8fh<3F5>VJEFApZBAQicJLZWt8*yeG72c{TmD`pRmZq z>N4HGiQ}YySD}9d?xqZ8D6L4*`8&G#OVx2Ye_x&d6vv&k2^5KcF|yqD={sd_e90J&wXbacjX>?rJ;Y?#-= zmE&ej4ss6FCH(T9!q7MP11N=f{Um?4o8MpY%S?aN`2Ewo@5e9hlj{zQ?NJ^>M_jo8 z4W9N?px5AV4-4s5BZ9Kh1AGYk6G3_b!{103X(AjO&1-C&P<8NgLC;J$zcmm8ur^-4;_TA2%pM9zOMy2^z{Vl?0K_=aDeGm#ZXimXV~?eC*u zkrX&t3c1&-H9Jx&NO2Tl?KyDjy{9cdh561&f&!ixRnU{DhpXkFb>co*v|t63W!Z;S z13HB?9!|*3BkFN+LiRNHYJzSAl+A>X_26gD0;mE@`r`b!gZ}?{$*z#^S@X(hP_Q2k^1|hM zkSpFLK2)mBm+1HZz}Agv)BV|hldKQM-HC5f>aS%w*Q2J?8&ayY;!`rhwUA%hA3w0w zQor^fbV2NCDJjsU8WKqZh2#R!)a0A19l$Lj&7=5aH-sB@euE&cIqpT-6m$I7z;ZMR zXTDzK7`>*V96@nr8hFuPRT$3awD={0;%@pBeF2D8&SHzwC)^K!ZmBCU2ORm) z{38?vd0np7m+6dc)Tewx(PEi_O7%uRzL%>4y!#|xsh6J2W(1f?g9yi@*^xsBB)D$+ zU=2G%&iODA7Ty@>k!ba?>N$1?ugU6aw3|&*v5ygI;_9Z%*BnY5jUovm9|8Mf1~_Ah zM0J|<+5aZ&H>8bBsN3)zq=hHqyp8$Iwi_Y9pZ{@WV}CFkoKfi!`T9`#&fe|hbg(b* zbndK5mtx%ZiMuWmhD6}SsU6qv(|rtng&MPHI6CSI3<={hu80Fc+Dj8v9|nk z8UNg*Nn$p&Zp{)OI7LX}i_t<7kHl$~nADaT7FR%g5niXWR?N${SZ!fJ{Mc=LtyD*u z&r9(cx%p`y0D~O)%prjLxl}&%lOpBnDQ1;AS0RCQ2Jt1_f5z`#U(JY14hnG-^OYYx zV?oYtvihPA`fHEGWc;MwAE28jwd@15cV_rT9Y@@61Cf=5#t^`$O-9Tk8!+K7IQLQDcm;2zo|KfV~#M~<5zX2b!(+&;eda(iMayqH;*=LCnP z^XO@!uXzqI(K&MYQL#~h@6XQ(CPEVne2lBktd#M&J+XEw`!NRMEPW71&_>;T{eCnG zTGK9X_Y)kbCxx@0qTXGiUz61;V%E~qx2 zYp;{}T#B!MGoNRp8?3*dY2VCe_i%SQ^9l3WpbdY$^O+(k>RNOCNAvm84D_wO`Mlr|=d(%E`sTCo_ulzjbzQaj{C*+&5Shc;k~m2+3T3kc2wBxm?K(Mo6neQWj=R76Zo6?yiQsJ{j>f^cZ$qwvbv8?n9mD{ zIMwE}ucTmq11aJ8tag4|Z}tyTLxBrqrjw{qf_wHA?rC30-IaQ%s2KzK5ejPxE#s|S zJyk5{xw0Fv66x$BnBwi=L2nC_r5O!OFAlov)RxjiA#?G+;deI>p?4qi{nMGTS5hpr z*OaJ&>xc^J)Lt!fo-v5+1#DWd8S=YydIU`BLh&Cbd!}2|tj?5jBa#NHYZqwv{Q3$& z9#}HStGy1Gh?-kdf4x}r*IrB7NTtwUTUWd)`m257Rp;xe)5FrTIxBBqRj8+EpXh_p zZ!6V#KWUvycb59C?kM{hx<>1_wECc9x*_%9Sx{rskm9ko>vVMkCM9&L)^Ph@0&QUC z)ffS0_(=YNg|t$Qx(;KDK>T{>l#s=WdYJ29I+rb_j6(hSK}B*q!bDN33u z?_#=3pf!08-uX{Gd^tL*ZKj2Mzp4c+$rxn*aV<=q^(@Rj|?s@RIPf^kdJ zosxsZX7<^s=z{%WQlVrj(gs}DvNlmZ!m>7lxiE5$ zR3?S`WZ*+xw8Rt@;&Y2?N<`5+qyeHF`jZYC{6zNap(8o|uRbGy%T)+uiBM$unU;Mu zN6l}=rwKzS4swhvngipzbR2L%z45Gf%o0whyA%`~o@5qPYO!~2e9dD{Ylwpj*eu|5 zs-LojRsmnme_#HIRXe%^!(b`}8gTy4WcM(?8&H7%xH%%@3O5X)iL=H8aU=de3moB;;`!V4&05w2AhOXcbqy8D?v(qemzB%8(` z>$;CBaVGm|KJA3*3I=XDY)d;RP^(LDyA@oAOKzhBdt-;BwW`{+uu=Zu_9Yp?HVa@% ziQ2WWLH<#hzW0x~WI$H%h&EQBtU+KCVlnr}(!=-O5tn3)KcYEblH$ckQ9@tlz+ixJ+~?bVSV=urriqWEGHO1tLr zGtfkRBMS}O@5nEJ!qeyL0)+(Y0w$tBf|B(Jp5oMN_*Q|H#Nvt{`3JGX(+WR`iBdz( zV+D&VZs4C=_~#MLntryJ06XatwcuD`O|e6SH7y5*k*<55t4lUTA$jj1Tyb?Duv7A2 zd=}PC>OPk}atD`aUPx!^G!8&|*aV+LI)2V#IVZphb{iAr2NC8c^QX^)48SNFoE3{e z6_z@oGrP0J3jWB­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 e?Xlz56t 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%0AnV>OH=?;sK{oCD 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

V<3cJ>G+Qjt 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%0AYHvDVkoP4B^MN&-=+4wttYk^V8me&?~@*VK0 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 literal 0 HcmV?d00001 diff --git a/python/src/foam_stepper/_runtime.py b/python/src/foam_stepper/_runtime.py new file mode 100644 index 0000000..b485e40 --- /dev/null +++ b/python/src/foam_stepper/_runtime.py @@ -0,0 +1,70 @@ +"""Runtime OpenFOAM environment setup for the Python facade.""" + +from __future__ import annotations + +import os +import shlex +import subprocess +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[3] +OPENFOAM_ROOT = ROOT / "OpenFOAM-14" +_ENV_SENTINEL = "_FOAM_STEPPER_OPENFOAM_ENV" + + +def _capture_openfoam_env() -> dict[str, str] | None: + bashrc = OPENFOAM_ROOT / "etc/bashrc" + if not bashrc.exists(): + return None + + script = " ".join( + [ + "set +u;", + "source", + shlex.quote(str(bashrc)), + "WM_MPLIB=Dummy", + "ParaView_TYPE=none", + "SCOTCH_TYPE=none", + "ZOLTAN_TYPE=none;", + "set -u;", + "unset FOAM_SIGFPE;", + "unset PYTHONPATH;", + "env -0", + ] + ) + completed = subprocess.run( + ["bash", "-c", script], + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env={key: value for key, value in os.environ.items() if key not in {"PYTHONPATH", "FOAM_SIGFPE"}}, + ) + + env: dict[str, str] = {} + for item in completed.stdout.decode().split("\0"): + if not item or "=" not in item: + continue + key, value = item.split("=", 1) + env[key] = value + env.pop("PYTHONPATH", None) + env.pop("FOAM_SIGFPE", None) + env[_ENV_SENTINEL] = str(OPENFOAM_ROOT) + return env + + +def configure_openfoam_environment() -> dict[str, str]: + """Apply the repository OpenFOAM runtime environment if available.""" + + if os.environ.get(_ENV_SENTINEL) == str(OPENFOAM_ROOT): + os.environ.pop("PYTHONPATH", None) + os.environ.pop("FOAM_SIGFPE", None) + return dict(os.environ) + + env = _capture_openfoam_env() + if env is None: + return dict(os.environ) + + os.environ.update(env) + os.environ.pop("PYTHONPATH", None) + os.environ.pop("FOAM_SIGFPE", None) + return env diff --git a/python/src/foam_stepper/types.py b/python/src/foam_stepper/types.py new file mode 100644 index 0000000..7fbb8d8 --- /dev/null +++ b/python/src/foam_stepper/types.py @@ -0,0 +1,399 @@ +"""Typed Python facade objects for OpenFOAM observability snapshots.""" + +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Iterable, Iterator, Mapping + +import numpy as np + + +@dataclass(frozen=True) +class RaggedIntArray: + offsets: np.ndarray + values: np.ndarray + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "RaggedIntArray": + return cls(offsets=data["offsets"], values=data["values"]) + + def row(self, index: int) -> np.ndarray: + return self.values[self.offsets[index] : self.offsets[index + 1]] + + def to_dict(self) -> dict[str, Any]: + return {"offsets": self.offsets, "values": self.values} + + +@dataclass(frozen=True) +class SourceLocation: + file: str + function: str + lines: tuple[int, int] | None = None + + @classmethod + def from_dict(cls, data: Mapping[str, Any] | None) -> "SourceLocation": + if not data: + return cls(file="", function="", lines=None) + lines = data.get("lines") + return cls( + file=str(data.get("file", "")), + function=str(data.get("function", "")), + lines=tuple(lines) if lines is not None else None, + ) + + def to_dict(self) -> dict[str, Any]: + return {"file": self.file, "function": self.function, "lines": self.lines} + + +@dataclass(frozen=True) +class PatchView: + name: str + type: str + index: int + start: int + size: int + coupled: bool + constraint: bool + face_cells: np.ndarray + face_indices: np.ndarray + Cf: np.ndarray + Sf: np.ndarray + magSf: np.ndarray + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "PatchView": + return cls( + name=data["name"], + type=data["type"], + index=int(data["index"]), + start=int(data["start"]), + size=int(data["size"]), + coupled=bool(data["coupled"]), + constraint=bool(data["constraint"]), + face_cells=data["face_cells"], + face_indices=data["face_indices"], + Cf=data["Cf"], + Sf=data["Sf"], + magSf=data["magSf"], + raw=data, + ) + + def to_dict(self) -> Mapping[str, Any]: + return self.raw + + +@dataclass(frozen=True) +class PatchFieldView: + name: str + type: str + values: np.ndarray + fixes_value: bool + assignable: bool + coupled: bool + updated: bool + patch_internal: np.ndarray | None + value_internal_coeffs: np.ndarray | None + value_boundary_coeffs: np.ndarray | None + gradient_internal_coeffs: np.ndarray | None + gradient_boundary_coeffs: np.ndarray | None + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, name: str, data: Mapping[str, Any]) -> "PatchFieldView": + return cls( + name=name, + type=data["type"], + values=data["values"], + fixes_value=bool(data["fixes_value"]), + assignable=bool(data["assignable"]), + coupled=bool(data["coupled"]), + updated=bool(data["updated"]), + patch_internal=data.get("patch_internal"), + value_internal_coeffs=data.get("value_internal_coeffs"), + value_boundary_coeffs=data.get("value_boundary_coeffs"), + gradient_internal_coeffs=data.get("gradient_internal_coeffs"), + gradient_boundary_coeffs=data.get("gradient_boundary_coeffs"), + raw=data, + ) + + def to_dict(self) -> Mapping[str, Any]: + return self.raw + + +@dataclass(frozen=True) +class FieldView: + name: str + kind: str + dimensions: str + entity_kind: str + entity_count: int + internal: np.ndarray + boundary: Mapping[str, PatchFieldView] + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "FieldView": + boundary = { + name: PatchFieldView.from_dict(name, patch) + for name, patch in data.get("boundary", {}).items() + } + return cls( + name=data["name"], + kind=data["kind"], + dimensions=data["dimensions"], + entity_kind=data["entity_kind"], + entity_count=int(data["entity_count"]), + internal=data["internal"], + boundary=boundary, + raw=data, + ) + + def to_numpy(self, copy: bool = True) -> np.ndarray: + return np.array(self.internal, copy=copy) + + def to_dict(self, copy: bool = False) -> Mapping[str, Any]: + if not copy: + return self.raw + out = dict(self.raw) + out["internal"] = np.array(self.internal, copy=True) + return out + + +@dataclass(frozen=True) +class FieldRegistryView(Mapping[str, FieldView]): + fields: Mapping[str, FieldView] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "FieldRegistryView": + return cls({name: FieldView.from_dict(value) for name, value in data.items()}) + + def __getitem__(self, key: str) -> FieldView: + return self.fields[key] + + def __iter__(self) -> Iterator[str]: + return iter(self.fields) + + def __len__(self) -> int: + return len(self.fields) + + def __getattr__(self, key: str) -> FieldView: + try: + return self.fields[key] + except KeyError as exc: + raise AttributeError(key) from exc + + def to_dict(self) -> dict[str, Mapping[str, Any]]: + return {name: field.to_dict() for name, field in self.fields.items()} + + +@dataclass(frozen=True) +class MeshView: + n_points: int + n_faces: int + n_internal_faces: int + n_cells: int + points: np.ndarray + faces: RaggedIntArray + cells: RaggedIntArray + owner: np.ndarray + neighbour: np.ndarray + boundary: list[PatchView] + V: np.ndarray + C: np.ndarray + Cf: np.ndarray + Sf: np.ndarray + magSf: np.ndarray + ldu: Mapping[str, Any] + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "MeshView": + return cls( + n_points=int(data["n_points"]), + n_faces=int(data["n_faces"]), + n_internal_faces=int(data["n_internal_faces"]), + n_cells=int(data["n_cells"]), + points=data["points"], + faces=RaggedIntArray.from_dict(data["faces"]), + cells=RaggedIntArray.from_dict(data["cells"]), + owner=data["owner"], + neighbour=data["neighbour"], + boundary=[PatchView.from_dict(patch) for patch in data["boundary"]], + V=data["V"], + C=data["C"], + Cf=data["Cf"], + Sf=data["Sf"], + magSf=data["magSf"], + ldu=data["ldu"], + raw=data, + ) + + def patch(self, name: str) -> PatchView: + for patch in self.boundary: + if patch.name == name: + return patch + raise KeyError(name) + + def to_dict(self) -> Mapping[str, Any]: + return self.raw + + +@dataclass(frozen=True) +class MatrixView: + name: str + field_name: str + psi: FieldView + value_rank: str + dimensions: str + has_diag: bool + has_upper: bool + has_lower: bool + diagonal: bool + symmetric: bool + asymmetric: bool + diag: np.ndarray + upper: np.ndarray | None + lower: np.ndarray | None + source: np.ndarray + internal_coeffs: list[np.ndarray] + boundary_coeffs: list[np.ndarray] + face_flux_correction: FieldView | None + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "MatrixView": + face_flux = data.get("face_flux_correction") + return cls( + name=data["name"], + field_name=data["field_name"], + psi=FieldView.from_dict(data["psi"]), + value_rank=data["value_rank"], + dimensions=data["dimensions"], + has_diag=bool(data["has_diag"]), + has_upper=bool(data["has_upper"]), + has_lower=bool(data["has_lower"]), + diagonal=bool(data["diagonal"]), + symmetric=bool(data["symmetric"]), + asymmetric=bool(data["asymmetric"]), + diag=data["diag"], + upper=data.get("upper"), + lower=data.get("lower"), + source=data["source"], + internal_coeffs=list(data.get("internal_coeffs", [])), + boundary_coeffs=list(data.get("boundary_coeffs", [])), + face_flux_correction=( + FieldView.from_dict(face_flux) + if isinstance(face_flux, Mapping) and "kind" in face_flux + else None + ), + raw=data, + ) + + @property + def A(self) -> FieldView | None: + value = self.raw.get("A") + return FieldView.from_dict(value) if isinstance(value, Mapping) else None + + @property + def H(self) -> FieldView | None: + value = self.raw.get("H") + return FieldView.from_dict(value) if isinstance(value, Mapping) else None + + @property + def H1(self) -> FieldView | None: + value = self.raw.get("H1") + return FieldView.from_dict(value) if isinstance(value, Mapping) else None + + @property + def flux(self) -> FieldView | None: + value = self.raw.get("flux") + return FieldView.from_dict(value) if isinstance(value, Mapping) else None + + def residual(self) -> np.ndarray | None: + return self.raw.get("residual") + + def D(self) -> np.ndarray | None: + return self.raw.get("D") + + def DD(self) -> np.ndarray | None: + return self.raw.get("DD") + + def to_dict(self) -> Mapping[str, Any]: + return self.raw + + +@dataclass(frozen=True) +class SolveResult: + solver_name: str + field_name: str + initial_residual: Any + final_residual: Any + n_iterations: Any + converged: bool + singular: bool + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "SolveResult": + return cls( + solver_name=data["solver_name"], + field_name=data["field_name"], + initial_residual=data["initial_residual"], + final_residual=data["final_residual"], + n_iterations=data["n_iterations"], + converged=bool(data["converged"]), + singular=bool(data["singular"]), + raw=data, + ) + + +@dataclass(frozen=True) +class TransformResult: + name: str + phase: str + source: SourceLocation + inputs: Mapping[str, Any] + outputs: Mapping[str, Any] + changed_fields: list[str] + metadata: Mapping[str, Any] + raw: Mapping[str, Any] + + @classmethod + def from_dict(cls, data: Mapping[str, Any]) -> "TransformResult": + return cls( + name=data["name"], + phase=data["phase"], + source=SourceLocation.from_dict(data.get("source")), + inputs=_wrap_mapping(data.get("inputs", {})), + outputs=_wrap_mapping(data.get("outputs", {})), + changed_fields=list(data.get("changed_fields", [])), + metadata=dict(data.get("metadata", {})), + raw=data, + ) + + def to_dict(self) -> Mapping[str, Any]: + return self.raw + + +def _wrap_mapping(data: Mapping[str, Any]) -> dict[str, Any]: + return {key: _wrap_value(value) for key, value in data.items()} + + +def _wrap_value(value: Any) -> Any: + if isinstance(value, Mapping): + if {"n_cells", "owner", "neighbour"}.issubset(value): + return MeshView.from_dict(value) + if "kind" in value and "internal" in value: + return FieldView.from_dict(value) + if "value_rank" in value and "diag" in value: + return MatrixView.from_dict(value) + if {"solver_name", "field_name", "initial_residual"}.issubset(value): + return SolveResult.from_dict(value) + if {"name", "phase", "outputs"}.issubset(value): + return TransformResult.from_dict(value) + return _wrap_mapping(value) + if isinstance(value, list): + return [_wrap_value(item) for item in value] + return value diff --git a/scripts/build_openfoam_airfrans_subset.sh b/scripts/build_openfoam_airfrans_subset.sh new file mode 100755 index 0000000..73d8163 --- /dev/null +++ b/scripts/build_openfoam_airfrans_subset.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Build the OpenFOAM Foundation v14 serial subset needed for AirfRANS-style data generation. +# Tools built: foamRun/incompressibleFluid (simpleFoam replacement), simpleFoam wrapper, +# gmshToFoam, checkMesh, and foamToVTK. + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +OPENFOAM_REPO_URL="${OPENFOAM_REPO_URL:-https://github.com/OpenFOAM/OpenFOAM-14.git}" +THIRDPARTY_REPO_URL="${THIRDPARTY_REPO_URL:-https://github.com/OpenFOAM/ThirdParty-14.git}" +AIRFRANS_REPO_URL="${AIRFRANS_REPO_URL:-https://github.com/Extrality/AirfRANS.git}" +JOBS="${JOBS:-$(nproc)}" + +clone_if_missing() { + local url="$1" + local dir="$2" + + if [[ -d "${ROOT_DIR}/${dir}/.git" ]]; then + printf 'using existing %s\n' "${dir}" + else + git clone --depth 1 "${url}" "${ROOT_DIR}/${dir}" + fi +} + +clone_if_missing "${OPENFOAM_REPO_URL}" OpenFOAM-14 +clone_if_missing "${THIRDPARTY_REPO_URL}" ThirdParty-14 +clone_if_missing "${AIRFRANS_REPO_URL}" airfrans + +# Dummy MPI keeps this subset serial and avoids requiring mpicc/OpenMPI for p1. +# Use SYSTEMOPENMPI instead only after installing a system MPI development package. +# OpenFOAM's bashrc probes optional shell variables that may be unset. +# shellcheck disable=SC1091 +set +u +source "${ROOT_DIR}/OpenFOAM-14/etc/bashrc" \ + WM_MPLIB=Dummy \ + ParaView_TYPE=none \ + SCOTCH_TYPE=none \ + ZOLTAN_TYPE=none +set -u + +cd "${ROOT_DIR}/OpenFOAM-14" + +(cd wmake/src && make) + +src/Pstream/Allwmake -j "${JOBS}" +src/OSspecific/${WM_OSTYPE:-POSIX}/Allwmake -j "${JOBS}" +wmake -j "${JOBS}" libso src/OpenFOAM + +for target in \ + src/fileFormats \ + src/surfMesh \ + src/triSurface \ + src/meshTools \ + src/finiteVolume \ + src/ODE \ + src/physicalProperties \ + src/tracking \ + src/lagrangian/basic \ + src/generic/genericPatches \ + src/generic/genericFields \ + src/generic/genericFvPatches \ + src/generic/genericFvFields \ + src/sampling \ + src/meshCheck \ + src/mesh/extrudeModel \ + src/polyTopoChange \ + src/conversion \ + src/thermophysicalModels/specie \ + src/thermophysicalModels/thermophysicalProperties \ + src/thermophysicalModels/basic \ + src/thermophysicalModels/multicomponentThermo \ + src/thermophysicalModels/solidThermo \ + src/MomentumTransportModels/momentumTransportModels \ + src/MomentumTransportModels/incompressible \ + src/MomentumTransportModels/compressible \ + src/ThermophysicalTransportModels/thermophysicalTransportModel \ + src/ThermophysicalTransportModels/fluid \ + src/ThermophysicalTransportModels/fluidThermo \ + src/fvConstraints \ + src/fvModels/general \ + applications/modules/basicFluidSolver \ + applications/modules/incompressibleFluid + do + wmake -j "${JOBS}" libso "${target}" + done + +for app in \ + applications/solvers/foamRun \ + applications/utilities/mesh/conversion/gmshToFoam \ + applications/utilities/mesh/manipulation/checkMesh + do + wmake -j "${JOBS}" "${app}" + done + +applications/utilities/postProcessing/dataConversion/foamToVTK/Allwmake -j "${JOBS}" + +foamRun -help >/dev/null +foamRun -solver incompressibleFluid -help >/dev/null +gmshToFoam -help >/dev/null +checkMesh -help >/dev/null +foamToVTK -help >/dev/null +simpleFoam -help >/dev/null + +printf 'OpenFOAM v14 AirfRANS subset built and smoke-checked.\n' diff --git a/scripts/build_python_stepper.sh b/scripts/build_python_stepper.sh new file mode 100755 index 0000000..f912c26 --- /dev/null +++ b/scripts/build_python_stepper.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +PYTHON_BIN="${PYTHON_BIN:-${ROOT_DIR}/.venv/bin/python}" +JOBS="${JOBS:-$(nproc)}" + +if [[ ! -x "${PYTHON_BIN}" ]]; then + echo "Python interpreter not found: ${PYTHON_BIN}" >&2 + echo "Run: uv sync --dev" >&2 + exit 1 +fi + +# shellcheck disable=SC1091 +set +u +source "${ROOT_DIR}/OpenFOAM-14/etc/bashrc" \ + WM_MPLIB=Dummy \ + ParaView_TYPE=none \ + SCOTCH_TYPE=none \ + ZOLTAN_TYPE=none +set -u + +export FOAM_USER_LIBBIN="${ROOT_DIR}/python/src/foam_stepper" +export FOAM_USER_APPBIN="${ROOT_DIR}/pythonStepper/bin" +mkdir -p "${FOAM_USER_LIBBIN}" "${FOAM_USER_APPBIN}" + +export PYBIND11_INCLUDES="$("${PYTHON_BIN}" -m pybind11 --includes)" +PYTHON_LIBDIR="$("${PYTHON_BIN}" -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR") or "")')" +PYTHON_LINK_LIBS="$("${PYTHON_BIN}" -c 'import sysconfig; print(" ".join(v for v in [sysconfig.get_config_var("LIBDIR") and "-L" + sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY") and "-l" + sysconfig.get_config_var("LDLIBRARY").removeprefix("lib").removesuffix(".so"), sysconfig.get_config_var("LIBS"), sysconfig.get_config_var("SYSLIBS")] if v))')" +RPATH_DIRS=("${FOAM_LIBBIN}" "${FOAM_LIBBIN}/${FOAM_MPI}" "${FOAM_EXT_LIBBIN}") +if [[ -n "${PYTHON_LIBDIR}" ]]; then + RPATH_DIRS+=("${PYTHON_LIBDIR}") +fi +RPATH_LIBS="-Wl,--disable-new-dtags" +for lib_dir in "${RPATH_DIRS[@]}"; do + if [[ -d "${lib_dir}" ]]; then + RPATH_LIBS="${RPATH_LIBS} -Wl,-rpath,${lib_dir}" + fi +done +export PYTHON_LIBS="${PYTHON_LINK_LIBS} ${RPATH_LIBS}" + +rm -f "${FOAM_USER_LIBBIN}/_foam_stepper.so" + +wmake -j "${JOBS}" libso "${ROOT_DIR}/pythonStepper/pyfoam_stepper" + +printf 'Built %s/_foam_stepper.so\n' "${FOAM_USER_LIBBIN}" diff --git a/scripts/fuzz_python_stepper.py b/scripts/fuzz_python_stepper.py new file mode 100755 index 0000000..877fbf1 --- /dev/null +++ b/scripts/fuzz_python_stepper.py @@ -0,0 +1,475 @@ +#!/usr/bin/env python3 +"""Seeded equivalence fuzzer for the Python-driven OpenFOAM stepper.""" + +from __future__ import annotations + +import argparse +import importlib.util +import json +import os +import random +import shutil +import subprocess +import sys +from dataclasses import asdict, dataclass +from pathlib import Path + + +def _drop_ambient_pythonpath() -> None: + pythonpath = os.environ.pop("PYTHONPATH", "") + for entry in pythonpath.split(os.pathsep): + if not entry: + continue + while entry in sys.path: + sys.path.remove(entry) + + +_drop_ambient_pythonpath() + +import numpy as np + + +def _load_openfoam_env_helpers(): + try: + from openfoam_env import apply_openfoam_env, openfoam_env + except ModuleNotFoundError: + spec = importlib.util.spec_from_file_location("openfoam_env", Path(__file__).with_name("openfoam_env.py")) + if spec is None or spec.loader is None: + raise + module = importlib.util.module_from_spec(spec) + sys.modules["openfoam_env"] = module + spec.loader.exec_module(module) + return module.apply_openfoam_env, module.openfoam_env + return apply_openfoam_env, openfoam_env + + +apply_openfoam_env, openfoam_env = _load_openfoam_env_helpers() + +ROOT = Path(__file__).resolve().parents[1] +TUTORIAL = ROOT / "OpenFOAM-14/tutorials/incompressibleFluid/venturiTube" +DEFAULT_WORK = ROOT / "tmp/python_stepper_fuzz" +DEFAULT_SEEDS = 10 +DEFAULT_ATOL = 1e-10 +DEFAULT_RTOL = 1e-10 +FIELDS = ("U", "p", "phi") + + +@dataclass(frozen=True) +class CaseVariant: + seed: int + diameter: float + dia_cells: int + ven_cells: int + in_cells: int + out_cells: int + box_cells: int + rad_cells: int + out_grading: float + u_inlet: float + nu: float + p_relax: float + u_relax: float + p_tolerance: float + u_tolerance: float + n_non_orthogonal_correctors: int + + +def scalar(value: float) -> str: + return f"{value:.17g}" + + +def variant_for_seed(seed: int) -> CaseVariant: + rng = random.Random(seed) + return CaseVariant( + seed=seed, + diameter=rng.choice([0.05, 0.075, 0.1, 0.15, 0.2]), + dia_cells=rng.choice([4, 6, 8]), + ven_cells=rng.choice([2, 4]), + in_cells=rng.choice([6, 8, 10]), + out_cells=rng.choice([8, 10, 12]), + box_cells=rng.choice([2, 3, 4]), + rad_cells=rng.choice([4, 6, 8]), + out_grading=rng.choice([0.5, 0.75, 1.0, 1.25]), + u_inlet=rng.choice([0.05, 0.1, 0.2, 0.4]), + nu=rng.choice([2e-5, 4e-5, 8e-5, 1.6e-4]), + p_relax=rng.choice([0.2, 0.3, 0.5, 0.7]), + u_relax=rng.choice([0.5, 0.7, 0.9]), + p_tolerance=rng.choice([1e-6, 1e-7]), + u_tolerance=rng.choice([1e-7, 1e-8]), + n_non_orthogonal_correctors=rng.choice([0, 1]), + ) + + +def replace_required(path: Path, text: str, old: str, new: str) -> str: + count = text.count(old) + if count == 0: + raise AssertionError(f"{path}: missing literal {old!r}") + if count != 1: + raise AssertionError(f"{path}: expected one literal {old!r}, found {count}") + return text.replace(old, new, 1) + + +def patch_file(path: Path, replacements: list[tuple[str, str]]) -> None: + text = path.read_text() + for old, new in replacements: + text = replace_required(path, text, old, new) + path.write_text(text) + + +def patch_block_mesh(case: Path, variant: CaseVariant) -> None: + patch_file( + case / "system/blockMeshDict", + [ + ("diameter 0.1;", f"diameter {scalar(variant.diameter)};"), + ("diaCells 16;", f"diaCells {variant.dia_cells};"), + ("venCells 8;", f"venCells {variant.ven_cells};"), + ("inCells 20;", f"inCells {variant.in_cells};"), + ("outCells 40;", f"outCells {variant.out_cells};"), + ("boxCells 8;", f"boxCells {variant.box_cells};"), + ("radCells 16;", f"radCells {variant.rad_cells};"), + ("outGrading 0.5;", f"outGrading {scalar(variant.out_grading)};"), + ], + ) + + +def patch_initial_fields(case: Path, variant: CaseVariant) -> None: + patch_file(case / "0/U", [("Uinlet 0.2;", f"Uinlet {scalar(variant.u_inlet)};")]) + + +def patch_physical_properties(case: Path, variant: CaseVariant) -> None: + patch_file(case / "constant/physicalProperties", [("nu 4e-05;", f"nu {scalar(variant.nu)};")]) + + +def patch_fv_solution(case: Path, variant: CaseVariant) -> None: + patch_file( + case / "system/fvSolution", + [ + (" tolerance 1e-6;", f" tolerance {scalar(variant.p_tolerance)};"), + (" tolerance 1e-7;", f" tolerance {scalar(variant.u_tolerance)};"), + ( + " nNonOrthogonalCorrectors 0;", + f" nNonOrthogonalCorrectors {variant.n_non_orthogonal_correctors};", + ), + (" p 0.3;", f" p {scalar(variant.p_relax)};"), + (" U 0.7;", f" U {scalar(variant.u_relax)};"), + ], + ) + + +def patch_control_dict_for_seed(case: Path) -> None: + patch_file( + case / "system/controlDict", + [ + ("startFrom latestTime;", "startFrom startTime;"), + ("endTime 1000;", "endTime 1;"), + ("writeInterval 50;", "writeInterval 1;"), + ("writePrecision 8;", "writePrecision 17;"), + ], + ) + + +def patch_control_dict_to_latest(case: Path) -> None: + patch_file(case / "system/controlDict", [("startFrom startTime;", "startFrom latestTime;")]) + + +def run(cmd: list[str], *, log_path: Path | None = None) -> None: + env = openfoam_env() + if log_path is None: + subprocess.run(cmd, cwd=ROOT, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, env=env) + return + + with log_path.open("w") as log: + subprocess.run(cmd, cwd=ROOT, check=True, stdout=log, stderr=subprocess.STDOUT, env=env) + + +def prepare_case(dst: Path, variant: CaseVariant) -> None: + if dst.exists(): + shutil.rmtree(dst) + shutil.copytree(TUTORIAL, dst, ignore=shutil.ignore_patterns("processor*", "postProcessing", "*.log")) + for orig in (dst / "0").glob("*.orig"): + shutil.copyfile(orig, orig.with_suffix("")) + + patch_block_mesh(dst, variant) + patch_initial_fields(dst, variant) + patch_physical_properties(dst, variant) + patch_fv_solution(dst, variant) + patch_control_dict_for_seed(dst) + + run(["blockMesh", "-case", str(dst)]) + run(["createZones", "-case", str(dst)]) + + +def prepare_seed(seed_dir: Path, variant: CaseVariant) -> dict[str, Path]: + if seed_dir.exists(): + shutil.rmtree(seed_dir) + outputs = seed_dir / "outputs" + outputs.mkdir(parents=True) + (seed_dir / "variant.json").write_text(json.dumps(asdict(variant), indent=2, sort_keys=True) + "\n") + + cases = { + "foam": seed_dir / "foam_case", + "run_one": seed_dir / "python_run_one_case", + "run_split": seed_dir / "python_split_case", + } + for case in cases.values(): + prepare_case(case, variant) + return cases + + +def save_npz(out: Path, *, U: np.ndarray, p: np.ndarray, phi: np.ndarray) -> None: + out.parent.mkdir(parents=True, exist_ok=True) + np.savez_compressed(out, U=np.asarray(U), p=np.asarray(p), phi=np.asarray(phi)) + + +def child_load_fields(case: Path, out: Path) -> None: + import foam_stepper as foam + + fields = foam.Case(case).make_stepper().fields() + save_npz(out, U=fields.U.internal, p=fields.p.internal, phi=fields.phi.internal) + + +def child_run_one(case: Path, out: Path) -> None: + import foam_stepper as foam + + result = foam.Case(case).make_stepper().run_one_pimple_iteration() + fields = result.outputs["fields"] + save_npz(out, U=fields["U"].internal, p=fields["p"].internal, phi=fields["phi"].internal) + + +def child_run_split(case: Path, out: Path) -> None: + import foam_stepper as foam + + stepper = foam.Case(case).make_stepper() + stepper.pre_solve() + stepper.advance_time() + begin = stepper.begin_pimple_iteration() + assert begin.outputs["active"] is True + stepper.fv_models_correct() + stepper.pre_predictor() + stepper.momentum_transport_predictor() + stepper.assemble_momentum_matrix() + stepper.relax_matrix() + stepper.constrain_matrix() + stepper.solve_momentum() + stepper.compute_pressure_inputs() + stepper.assemble_pressure_matrix() + stepper.solve_pressure() + stepper.correct_velocity_pressure_flux() + stepper.momentum_transport_corrector() + stepper.end_pimple_iteration() + stepper.post_solve(write=False) + fields = stepper.fields() + save_npz(out, U=fields.U.internal, p=fields.p.internal, phi=fields.phi.internal) + + +def load_npz(path: Path) -> dict[str, np.ndarray]: + with np.load(path) as data: + return {field: data[field] for field in FIELDS} + + +def failure_message( + *, + seed: int, + variant: CaseVariant, + seed_dir: Path, + path_label: str, + field: str, + baseline_path: Path, + actual_path: Path, + expected_shape: tuple[int, ...], + actual_shape: tuple[int, ...], + max_abs: float, + max_rel: float, +) -> str: + return ( + f"fuzz equivalence failed seed={seed} path={path_label} field={field}\n" + f"variant={json.dumps(asdict(variant), sort_keys=True)}\n" + f"variant_json={seed_dir / 'variant.json'}\n" + f"foamRun_log={seed_dir / 'foamRun.log'}\n" + f"baseline_output={baseline_path}\n" + f"actual_output={actual_path}\n" + f"shape_pair=actual{actual_shape} expected{expected_shape}\n" + f"max_abs={max_abs:.17g}\n" + f"max_rel={max_rel:.17g}" + ) + + +def compare_field( + *, + seed: int, + variant: CaseVariant, + seed_dir: Path, + path_label: str, + field: str, + expected: np.ndarray, + actual: np.ndarray, + baseline_path: Path, + actual_path: Path, + atol: float, + rtol: float, +) -> float: + if actual.shape != expected.shape: + raise AssertionError( + failure_message( + seed=seed, + variant=variant, + seed_dir=seed_dir, + path_label=path_label, + field=field, + baseline_path=baseline_path, + actual_path=actual_path, + expected_shape=expected.shape, + actual_shape=actual.shape, + max_abs=float("nan"), + max_rel=float("nan"), + ) + ) + + abs_diff = np.abs(actual - expected) + max_abs = float(np.max(abs_diff)) if abs_diff.size else 0.0 + max_rel = float(np.max(abs_diff / np.maximum(np.abs(expected), atol))) if abs_diff.size else 0.0 + if not np.allclose(actual, expected, rtol=rtol, atol=atol): + raise AssertionError( + failure_message( + seed=seed, + variant=variant, + seed_dir=seed_dir, + path_label=path_label, + field=field, + baseline_path=baseline_path, + actual_path=actual_path, + expected_shape=expected.shape, + actual_shape=actual.shape, + max_abs=max_abs, + max_rel=max_rel, + ) + ) + return max_abs + + +def compare_outputs( + *, + seed: int, + variant: CaseVariant, + seed_dir: Path, + baseline_path: Path, + actual_paths: dict[str, Path], + atol: float, + rtol: float, +) -> dict[str, dict[str, float]]: + baseline = load_npz(baseline_path) + summary: dict[str, dict[str, float]] = {} + for path_label, actual_path in actual_paths.items(): + actual = load_npz(actual_path) + summary[path_label] = {} + for field in FIELDS: + summary[path_label][field] = compare_field( + seed=seed, + variant=variant, + seed_dir=seed_dir, + path_label=path_label, + field=field, + expected=baseline[field], + actual=actual[field], + baseline_path=baseline_path, + actual_path=actual_path, + atol=atol, + rtol=rtol, + ) + return summary + + +def run_child(child: str, case: Path, out: Path) -> None: + subprocess.run( + [sys.executable, str(Path(__file__).resolve()), "--child", child, "--case", str(case), "--out", str(out)], + cwd=ROOT, + check=True, + env=openfoam_env(), + ) + + +def run_seed(seed: int, variant: CaseVariant, work_dir: Path, *, atol: float, rtol: float) -> Path: + seed_dir = work_dir / f"seed_{seed}" + cases = prepare_seed(seed_dir, variant) + outputs = seed_dir / "outputs" + baseline_path = outputs / "baseline.npz" + run_one_path = outputs / "run_one.npz" + run_split_path = outputs / "run_split.npz" + + run( + ["foamRun", "-case", str(cases["foam"]), "-solver", "incompressibleFluid", "-noFunctionObjects"], + log_path=seed_dir / "foamRun.log", + ) + patch_control_dict_to_latest(cases["foam"]) + run_child("load-fields", cases["foam"], baseline_path) + run_child("run-one", cases["run_one"], run_one_path) + run_child("run-split", cases["run_split"], run_split_path) + + summary = compare_outputs( + seed=seed, + variant=variant, + seed_dir=seed_dir, + baseline_path=baseline_path, + actual_paths={"run_one": run_one_path, "run_split": run_split_path}, + atol=atol, + rtol=rtol, + ) + cells = int(load_npz(baseline_path)["U"].shape[0]) + print( + f"seed={seed} cells={cells} " + f"run_one: U={summary['run_one']['U']:.3e} p={summary['run_one']['p']:.3e} phi={summary['run_one']['phi']:.3e} " + f"split: U={summary['run_split']['U']:.3e} p={summary['run_split']['p']:.3e} phi={summary['run_split']['phi']:.3e}", + flush=True, + ) + return seed_dir + + +def run_parent(args: argparse.Namespace) -> None: + if args.seeds < 1: + raise SystemExit("--seeds must be at least 1") + + args.work_dir.mkdir(parents=True, exist_ok=True) + for seed in range(args.seed_start, args.seed_start + args.seeds): + variant = variant_for_seed(seed) + seed_dir = run_seed(seed, variant, args.work_dir, atol=args.atol, rtol=args.rtol) + if not args.keep_passing: + shutil.rmtree(seed_dir) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--seeds", type=int, default=DEFAULT_SEEDS) + parser.add_argument("--seed-start", type=int, default=0) + parser.add_argument("--work-dir", type=Path, default=DEFAULT_WORK) + parser.add_argument("--atol", type=float, default=DEFAULT_ATOL) + parser.add_argument("--rtol", type=float, default=DEFAULT_RTOL) + parser.add_argument("--keep-passing", action="store_true") + parser.add_argument("--child", choices=("load-fields", "run-one", "run-split")) + parser.add_argument("--case", type=Path) + parser.add_argument("--out", type=Path) + args = parser.parse_args() + + if args.child is not None and (args.case is None or args.out is None): + parser.error("--child requires --case and --out") + if args.child is None and (args.case is not None or args.out is not None): + parser.error("--case and --out are only valid with --child") + return args + + +def main() -> None: + args = parse_args() + if args.child == "load-fields": + apply_openfoam_env() + child_load_fields(args.case, args.out) + elif args.child == "run-one": + apply_openfoam_env() + child_run_one(args.case, args.out) + elif args.child == "run-split": + apply_openfoam_env() + child_run_split(args.case, args.out) + else: + run_parent(args) + + +if __name__ == "__main__": + main() diff --git a/scripts/fuzz_python_stepper.sh b/scripts/fuzz_python_stepper.sh new file mode 100755 index 0000000..1301f1b --- /dev/null +++ b/scripts/fuzz_python_stepper.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +JOBS="${JOBS:-$(nproc)}" +PYTHON_BIN="${PYTHON_BIN:-${ROOT_DIR}/.venv/bin/python}" + +if [[ ! -x "${PYTHON_BIN}" ]]; then + uv sync --dev +fi + +if ! PYTHONPATH= "${PYTHON_BIN}" -c 'import pybind11, numpy' >/dev/null 2>&1; then + uv sync --dev +fi + +"${ROOT_DIR}/scripts/build_openfoam_airfrans_subset.sh" >/dev/null + +set +u +source "${ROOT_DIR}/OpenFOAM-14/etc/bashrc" \ + WM_MPLIB=Dummy \ + ParaView_TYPE=none \ + SCOTCH_TYPE=none \ + ZOLTAN_TYPE=none +set -u +unset FOAM_SIGFPE + +( + cd "${ROOT_DIR}/OpenFOAM-14" + wmake -j "${JOBS}" libso src/mesh/blockMesh >/dev/null + wmake -j "${JOBS}" applications/utilities/mesh/generation/blockMesh >/dev/null + wmake -j "${JOBS}" applications/utilities/mesh/manipulation/createZones >/dev/null +) + +"${ROOT_DIR}/scripts/build_python_stepper.sh" >/dev/null + +"${PYTHON_BIN}" "${ROOT_DIR}/scripts/fuzz_python_stepper.py" "$@" diff --git a/scripts/openfoam_env.py b/scripts/openfoam_env.py new file mode 100644 index 0000000..5e39494 --- /dev/null +++ b/scripts/openfoam_env.py @@ -0,0 +1,73 @@ +"""Internal OpenFOAM environment resolution for Python scripts. + +This keeps user-facing commands rooted in the project .venv while still giving +OpenFOAM subprocesses the environment normally produced by etc/bashrc. +""" + +from __future__ import annotations + +import os +import shlex +import subprocess +from functools import lru_cache +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +@lru_cache(maxsize=1) +def openfoam_env() -> dict[str, str]: + """Return a sanitized environment with OpenFOAM v14 sourced. + + The returned environment intentionally removes ambient PYTHONPATH. The + project package is installed into .venv by `uv sync --dev`, so PYTHONPATH is + unnecessary and can accidentally shadow the venv's binary wheels. + """ + + bashrc = ROOT / "OpenFOAM-14/etc/bashrc" + if not bashrc.exists(): + raise RuntimeError(f"OpenFOAM bashrc not found: {bashrc}") + + command = " ".join( + [ + "set +u;", + "source", + shlex.quote(str(bashrc)), + "WM_MPLIB=Dummy", + "ParaView_TYPE=none", + "SCOTCH_TYPE=none", + "ZOLTAN_TYPE=none", + ">/dev/null;", + "set -u;", + "unset FOAM_SIGFPE;", + "unset PYTHONPATH;", + "env -0", + ] + ) + completed = subprocess.run( + ["bash", "-lc", command], + cwd=ROOT, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env={key: value for key, value in os.environ.items() if key not in {"PYTHONPATH", "FOAM_SIGFPE"}}, + ) + env: dict[str, str] = {} + for item in completed.stdout.decode().split("\0"): + if not item: + continue + key, _, value = item.partition("=") + env[key] = value + env.pop("PYTHONPATH", None) + env.pop("FOAM_SIGFPE", None) + return env + + +def apply_openfoam_env() -> dict[str, str]: + """Apply and return the sanitized OpenFOAM environment to this process.""" + + env = openfoam_env() + os.environ.update(env) + os.environ.pop("PYTHONPATH", None) + os.environ.pop("FOAM_SIGFPE", None) + return env diff --git a/scripts/prepare_airfrans_stepper_case.py b/scripts/prepare_airfrans_stepper_case.py new file mode 100755 index 0000000..612a40d --- /dev/null +++ b/scripts/prepare_airfrans_stepper_case.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python3 +"""Prepare a v14-compatible AirfRANS raw OpenFOAM case for the Python stepper. + +The source raw data lives in the sibling ../airfrans repo and must not be +modified. This helper copies only the files needed for one local v14 +OpenFOAM/stepper iteration: mesh, initial fields, fvSchemes, and fvSolution. +""" + +from __future__ import annotations + +import argparse +import json +import math +import re +import shutil +from dataclasses import asdict, dataclass +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +RAW_ROOT = ROOT.parent / "airfrans/data/raw/OF_dataset" +DEFAULT_SIMULATION = "airFoil2D_SST_93.213_3.79_0.418_0.0_9.665" +DEFAULT_SOURCE = RAW_ROOT / DEFAULT_SIMULATION +DEFAULT_DEST = ROOT / "tmp/airfrans_stepper_case" / f"{DEFAULT_SIMULATION}_v14" + +FLOAT_RE = re.compile(r"[-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?") + + +@dataclass(frozen=True) +class AirfransCaseMetadata: + simulation: str + source: str + u_inf: float + velocity: tuple[float, float, float] + nu: float + rho_inf: float + reynolds: float + mach: float + alpha_deg: float + drag_dir: tuple[float, float, float] + lift_dir: tuple[float, float, float] + source_end_time: int + migrated_end_time: int + + +def read_text(path: Path) -> str: + return path.read_text(errors="replace") + + +def assignment(text: str, key: str) -> str: + match = re.search(rf"^\s*{re.escape(key)}\s+([^;]+);", text, flags=re.MULTILINE) + if not match: + raise ValueError(f"missing assignment {key!r}") + return match.group(1).strip() + + +def vector_assignment(text: str, key: str) -> tuple[float, float, float]: + values = [float(value) for value in FLOAT_RE.findall(assignment(text, key))] + if len(values) != 3: + raise ValueError(f"expected 3-vector for {key!r}, got {values!r}") + return (values[0], values[1], values[2]) + + +def copy_required_file(src_root: Path, dst_root: Path, relative: str) -> None: + src = src_root / relative + dst = dst_root / relative + if not src.exists(): + raise FileNotFoundError(src) + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src, dst) + + +def copy_required_tree(src_root: Path, dst_root: Path, relative: str) -> None: + src = src_root / relative + dst = dst_root / relative + if not src.exists(): + raise FileNotFoundError(src) + if dst.exists(): + shutil.rmtree(dst) + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copytree(src, dst) + + +def header(class_name: str, location: str, object_name: str) -> str: + location_line = f' location "{location}";\n' if location else "" + return f"""/*--------------------------------*- C++ -*----------------------------------*\\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Version: 14 + \\/ M anipulation | +\\*---------------------------------------------------------------------------*/ +FoamFile +{{ + format ascii; + class {class_name}; +{location_line} object {object_name}; +}} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +""" + + +def write_control_dict(dst: Path, *, u_inf: float, end_time: int) -> None: + content = header("dictionary", "system", "controlDict") + f"""Uinf {u_inf:.17g}; + +solver incompressibleFluid; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime {end_time}; + +deltaT 1; + +writeControl timeStep; + +writeInterval {end_time}; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 17; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + +// Function objects are intentionally disabled for first-step parity; run +// foamRun/foam_stepper with -noFunctionObjects and parse archived raw force +// outputs separately in the notebook. + +// ************************************************************************* // +""" + (dst / "system/controlDict").write_text(content) + + +def write_physical_properties(dst: Path, *, nu: float, rho_inf: float) -> None: + content = header("dictionary", "constant", "physicalProperties") + f"""viscosityModel constant; + +rho {rho_inf:.17g}; + +nu {nu:.17g}; + +// ************************************************************************* // +""" + (dst / "constant/physicalProperties").write_text(content) + + +def write_momentum_transport(dst: Path) -> None: + content = header("dictionary", "constant", "momentumTransport") + """simulationType RAS; + +RAS +{ + model kOmegaSST; + turbulence on; +} + +// ************************************************************************* // +""" + (dst / "constant/momentumTransport").write_text(content) + + +def metadata_from_source(src: Path, migrated_end_time: int) -> AirfransCaseMetadata: + control = read_text(src / "system/controlDict") + transport = read_text(src / "constant/transportProperties") + u_field = read_text(src / "0/U") + + u_inf = float(assignment(control, "Uinf")) + velocity = vector_assignment(u_field, "field") + nu = float(assignment(transport, "nu")) + rho_inf = float(assignment(control, "rhoInf")) + drag_dir = vector_assignment(control, "dragDir") + lift_dir = vector_assignment(control, "liftDir") + source_end_time = int(float(assignment(control, "endTime"))) + alpha_deg = math.degrees(math.atan2(drag_dir[1], drag_dir[0])) + + return AirfransCaseMetadata( + simulation=src.name, + source=str(src), + u_inf=u_inf, + velocity=velocity, + nu=nu, + rho_inf=rho_inf, + reynolds=u_inf / nu, + mach=u_inf / 346.1, + alpha_deg=alpha_deg, + drag_dir=drag_dir, + lift_dir=lift_dir, + source_end_time=source_end_time, + migrated_end_time=migrated_end_time, + ) + + +def prepare_case(src: Path, dst: Path, *, end_time: int = 1) -> AirfransCaseMetadata: + src = src.resolve() + dst = dst.resolve() + if not src.exists(): + raise FileNotFoundError(src) + + required = [ + "system/fvSchemes", + "system/fvSolution", + "system/blockMeshDict", + "0/U", + "0/p", + "0/nut", + "0/k", + "0/omega", + "constant/transportProperties", + "constant/turbulenceProperties", + "constant/polyMesh/boundary", + "constant/polyMesh/points.gz", + "constant/polyMesh/faces.gz", + "constant/polyMesh/owner.gz", + "constant/polyMesh/neighbour.gz", + ] + missing = [relative for relative in required if not (src / relative).exists()] + if missing: + raise FileNotFoundError(f"missing required AirfRANS files: {missing}") + + if dst.exists(): + shutil.rmtree(dst) + dst.mkdir(parents=True) + + copy_required_tree(src, dst, "constant/polyMesh") + for relative in [ + "system/fvSchemes", + "system/fvSolution", + "system/blockMeshDict", + "0/U", + "0/p", + "0/nut", + "0/k", + "0/omega", + "constant/transportProperties", + "constant/turbulenceProperties", + ]: + copy_required_file(src, dst, relative) + + meta = metadata_from_source(src, end_time) + write_control_dict(dst, u_inf=meta.u_inf, end_time=end_time) + write_physical_properties(dst, nu=meta.nu, rho_inf=meta.rho_inf) + write_momentum_transport(dst) + + # Keep the original dictionaries for audit without letting v14 select them. + shutil.move(dst / "constant/transportProperties", dst / "constant/transportProperties.v2112") + shutil.move(dst / "constant/turbulenceProperties", dst / "constant/turbulenceProperties.v2112") + + (dst / "airfrans_case_metadata.json").write_text(json.dumps(asdict(meta), indent=2, sort_keys=True) + "\n") + return meta + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--source", type=Path, default=DEFAULT_SOURCE) + parser.add_argument("--dest", type=Path, default=DEFAULT_DEST) + parser.add_argument("--end-time", type=int, default=1) + args = parser.parse_args() + + meta = prepare_case(args.source, args.dest, end_time=args.end_time) + print(json.dumps(asdict(meta), indent=2, sort_keys=True)) + print(f"prepared={args.dest}") + + +if __name__ == "__main__": + main() diff --git a/scripts/quadrants_hello_world.py b/scripts/quadrants_hello_world.py new file mode 100755 index 0000000..68f33bc --- /dev/null +++ b/scripts/quadrants_hello_world.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +"""Minimal Quadrants CUDA kernel smoke run.""" + +from __future__ import annotations + +import argparse + +import numpy as np +import quadrants as qd + + +@qd.kernel +def axpy(n: int, x: qd.types.NDArray[qd.f32, 1], y: qd.types.NDArray[qd.f32, 1]) -> None: + for i in range(n): + y[i] = 2.0 * x[i] + 1.0 + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--arch", default="cuda", choices=("cuda", "gpu", "cpu", "x64")) + args = parser.parse_args() + + qd.init(arch=getattr(qd, args.arch)) + + x_np = np.arange(8, dtype=np.float32) + expected = 2.0 * x_np + 1.0 + + x = qd.ndarray(qd.f32, shape=x_np.shape) + y = qd.ndarray(qd.f32, shape=x_np.shape) + x.from_numpy(x_np) + + axpy(x_np.size, x, y) + qd.sync() + + actual = y.to_numpy() + if not np.array_equal(actual, expected): + raise SystemExit(f"Quadrants hello kernel mismatch: {actual} != {expected}") + + print(f"quadrants hello world ok on arch={args.arch}: {actual}") + + +if __name__ == "__main__": + main() diff --git a/scripts/verify_airfrans_stepper.py b/scripts/verify_airfrans_stepper.py new file mode 100755 index 0000000..54c8cdb --- /dev/null +++ b/scripts/verify_airfrans_stepper.py @@ -0,0 +1,988 @@ +#!/usr/bin/env python3 +"""Verifier harness for the migrated AirfRANS OpenFOAM stepper case.""" + +from __future__ import annotations + +import argparse +import dataclasses +import hashlib +import json +import math +import os +import shutil +import subprocess +import sys +import time +import traceback +from collections.abc import Mapping +from pathlib import Path +from typing import Any + + +def _drop_ambient_pythonpath() -> None: + pythonpath = os.environ.pop("PYTHONPATH", "") + for entry in pythonpath.split(os.pathsep): + if not entry: + continue + while entry in sys.path: + sys.path.remove(entry) + + +_drop_ambient_pythonpath() + +import numpy as np + +from openfoam_env import apply_openfoam_env, openfoam_env +from prepare_airfrans_stepper_case import DEFAULT_SOURCE, prepare_case + +ROOT = Path(__file__).resolve().parents[1] +DEFAULT_WORK = ROOT / "tmp/airfrans_stepper_verify" +PRIMARY_FIELDS = ("U", "p", "phi") +TURBULENCE_FIELDS = ("nut", "k", "omega") +REQUIRED_FIELDS = PRIMARY_FIELDS + TURBULENCE_FIELDS + +LOADING_FAILURE = "loading_or_parsing_failure" +ORACLE_FAILURE = "openfoam_oracle_failure" +STEPPER_FAILURE = "stepper_execution_failure" +COMPARISON_FAILURE = "numerical_comparison_failure" +INTERNAL_FAILURE = "internal_harness_failure" + +EXIT_CODES = { + LOADING_FAILURE: 2, + ORACLE_FAILURE: 3, + STEPPER_FAILURE: 4, + COMPARISON_FAILURE: 5, + INTERNAL_FAILURE: 6, +} + + +class HarnessError(Exception): + """Categorized verifier failure that can be serialized into the report.""" + + def __init__( + self, + category: str, + step: str, + message: str, + *, + details: Mapping[str, Any] | None = None, + cause: BaseException | None = None, + ) -> None: + super().__init__(message) + self.category = category + self.step = step + self.details = dict(details or {}) + self.cause = cause + + def to_dict(self) -> dict[str, Any]: + out: dict[str, Any] = { + "category": self.category, + "step": self.step, + "message": str(self), + "details": self.details, + } + if self.cause is not None: + out["cause"] = { + "type": type(self.cause).__name__, + "message": str(self.cause), + } + return json_ready(out) + + +def json_ready(value: Any) -> Any: + """Convert report values into strict JSON-compatible data.""" + + if dataclasses.is_dataclass(value) and not isinstance(value, type): + return json_ready(dataclasses.asdict(value)) + if isinstance(value, Path): + return str(value) + if isinstance(value, np.ndarray): + return array_stats(value) + if isinstance(value, np.generic): + return json_ready(value.item()) + if isinstance(value, float): + return value if math.isfinite(value) else None + if isinstance(value, (str, int, bool)) or value is None: + return value + if isinstance(value, Mapping): + return {str(key): json_ready(item) for key, item in value.items()} + if isinstance(value, (list, tuple, set)): + return [json_ready(item) for item in value] + return repr(value) + + +def array_shape(array: Any | None) -> list[int] | None: + if array is None: + return None + return [int(dim) for dim in np.asarray(array).shape] + + +def finite_float(value: Any) -> float | None: + try: + number = float(value) + except (TypeError, ValueError): + return None + return number if math.isfinite(number) else None + + +def array_stats(array: Any) -> dict[str, Any]: + arr = np.asarray(array) + out: dict[str, Any] = { + "shape": array_shape(arr), + "dtype": str(arr.dtype), + "size": int(arr.size), + } + if arr.size == 0 or not np.issubdtype(arr.dtype, np.number): + return out + + finite = np.isfinite(arr) + out["finite_count"] = int(np.count_nonzero(finite)) + out["nonfinite_count"] = int(arr.size - out["finite_count"]) + if out["finite_count"]: + finite_values = arr[finite] + out.update( + { + "min": finite_float(np.min(finite_values)), + "max": finite_float(np.max(finite_values)), + "mean": finite_float(np.mean(finite_values)), + } + ) + return out + + +def value_at(array: np.ndarray, index: tuple[int, ...]) -> Any: + value = array[index] + if isinstance(value, np.generic): + return json_ready(value.item()) + if isinstance(value, np.ndarray): + return json_ready(value.tolist()) + return json_ready(value) + + +def entity_value_at(array: np.ndarray, entity_index: int | None) -> Any: + if entity_index is None or array.ndim == 0: + return None + value = array[entity_index] + if isinstance(value, np.generic): + return json_ready(value.item()) + if isinstance(value, np.ndarray): + return json_ready(value.tolist()) + return json_ready(value) + + +def update_hash_text(digest: "hashlib._Hash", value: str) -> None: + encoded = value.encode("utf-8") + digest.update(len(encoded).to_bytes(8, "little")) + digest.update(encoded) + + +def update_hash_array(digest: "hashlib._Hash", label: str, array: Any) -> None: + arr = np.ascontiguousarray(np.asarray(array)) + update_hash_text(digest, label) + update_hash_text(digest, str(arr.dtype)) + update_hash_text(digest, repr(tuple(int(dim) for dim in arr.shape))) + digest.update(arr.tobytes()) + + +def source_summary(source: Any) -> dict[str, Any]: + return { + "file": getattr(source, "file", ""), + "function": getattr(source, "function", ""), + "lines": json_ready(getattr(source, "lines", None)), + } + + +def boundary_field_summary(patch: Any) -> dict[str, Any]: + return { + "type": getattr(patch, "type", ""), + "values_shape": array_shape(getattr(patch, "values", None)), + "fixes_value": bool(getattr(patch, "fixes_value", False)), + "assignable": bool(getattr(patch, "assignable", False)), + "coupled": bool(getattr(patch, "coupled", False)), + "updated": bool(getattr(patch, "updated", False)), + "patch_internal_shape": array_shape(getattr(patch, "patch_internal", None)), + "value_internal_coeffs_shape": array_shape(getattr(patch, "value_internal_coeffs", None)), + "value_boundary_coeffs_shape": array_shape(getattr(patch, "value_boundary_coeffs", None)), + "gradient_internal_coeffs_shape": array_shape(getattr(patch, "gradient_internal_coeffs", None)), + "gradient_boundary_coeffs_shape": array_shape(getattr(patch, "gradient_boundary_coeffs", None)), + } + + +def field_summary(field: Any) -> dict[str, Any]: + boundary = getattr(field, "boundary", {}) + return { + "name": getattr(field, "name", ""), + "kind": getattr(field, "kind", ""), + "dimensions": getattr(field, "dimensions", ""), + "entity_kind": getattr(field, "entity_kind", ""), + "entity_count": int(getattr(field, "entity_count", 0)), + "internal": array_stats(getattr(field, "internal")), + "boundary": {name: boundary_field_summary(patch) for name, patch in boundary.items()}, + } + + +def solve_summary(performance: Any) -> dict[str, Any]: + return { + "solver_name": getattr(performance, "solver_name", ""), + "field_name": getattr(performance, "field_name", ""), + "initial_residual": json_ready(getattr(performance, "initial_residual", None)), + "final_residual": json_ready(getattr(performance, "final_residual", None)), + "n_iterations": json_ready(getattr(performance, "n_iterations", None)), + "converged": bool(getattr(performance, "converged", False)), + "singular": bool(getattr(performance, "singular", False)), + } + + +def matrix_summary(matrix: Any) -> dict[str, Any]: + derived: dict[str, Any] = {} + for name in ("A", "H", "H1", "flux", "face_flux_correction"): + value = getattr(matrix, name, None) + if callable(value): + value = value() + if value is not None: + derived[name] = field_summary(value) + + for name in ("residual", "D", "DD"): + value = getattr(matrix, name, None) + if callable(value): + value = value() + if value is not None: + derived[name] = array_stats(value) + + return { + "name": getattr(matrix, "name", ""), + "field_name": getattr(matrix, "field_name", ""), + "value_rank": getattr(matrix, "value_rank", ""), + "dimensions": getattr(matrix, "dimensions", ""), + "has_diag": bool(getattr(matrix, "has_diag", False)), + "has_upper": bool(getattr(matrix, "has_upper", False)), + "has_lower": bool(getattr(matrix, "has_lower", False)), + "diagonal": bool(getattr(matrix, "diagonal", False)), + "symmetric": bool(getattr(matrix, "symmetric", False)), + "asymmetric": bool(getattr(matrix, "asymmetric", False)), + "diag": array_stats(getattr(matrix, "diag")), + "upper": None if getattr(matrix, "upper", None) is None else array_stats(getattr(matrix, "upper")), + "lower": None if getattr(matrix, "lower", None) is None else array_stats(getattr(matrix, "lower")), + "source": array_stats(getattr(matrix, "source")), + "psi": field_summary(getattr(matrix, "psi")), + "internal_coeff_shapes": [array_shape(item) for item in getattr(matrix, "internal_coeffs", [])], + "boundary_coeff_shapes": [array_shape(item) for item in getattr(matrix, "boundary_coeffs", [])], + "derived": derived, + } + + +def summarize_value(value: Any) -> Any: + if hasattr(value, "diag") and hasattr(value, "field_name") and hasattr(value, "source"): + return matrix_summary(value) + if hasattr(value, "internal") and hasattr(value, "entity_kind") and hasattr(value, "boundary"): + return field_summary(value) + if hasattr(value, "solver_name") and hasattr(value, "initial_residual"): + return solve_summary(value) + if hasattr(value, "name") and hasattr(value, "phase") and hasattr(value, "outputs"): + return transform_summary(value) + if isinstance(value, Mapping): + return {str(key): summarize_value(item) for key, item in value.items()} + if isinstance(value, list): + return [summarize_value(item) for item in value] + if isinstance(value, tuple): + return [summarize_value(item) for item in value] + return json_ready(value) + + +def transform_summary(result: Any) -> dict[str, Any]: + return { + "name": getattr(result, "name", ""), + "phase": getattr(result, "phase", ""), + "changed_fields": json_ready(getattr(result, "changed_fields", [])), + "source": source_summary(getattr(result, "source", None)), + "metadata": json_ready(getattr(result, "metadata", {})), + "outputs": summarize_value(getattr(result, "outputs", {})), + } + + +def selected_field_summaries(fields: Mapping[str, Any]) -> dict[str, Any]: + return {name: field_summary(fields[name]) for name in REQUIRED_FIELDS if name in fields} + + +def field_dict_to_mapping(fields: Any) -> dict[str, Any]: + if isinstance(fields, Mapping): + return dict(fields) + if hasattr(fields, "fields") and isinstance(fields.fields, Mapping): + return dict(fields.fields) + return {name: getattr(fields, name) for name in REQUIRED_FIELDS if hasattr(fields, name)} + + +def mesh_patch_table(mesh: Any) -> list[dict[str, Any]]: + patches = [] + for patch in getattr(mesh, "boundary", []): + patches.append( + { + "index": int(getattr(patch, "index", 0)), + "name": getattr(patch, "name", ""), + "type": getattr(patch, "type", ""), + "start": int(getattr(patch, "start", 0)), + "size": int(getattr(patch, "size", 0)), + "coupled": bool(getattr(patch, "coupled", False)), + "constraint": bool(getattr(patch, "constraint", False)), + } + ) + return patches + + +def mesh_topology_digest(mesh: Any) -> str: + digest = hashlib.sha256() + for name in ("n_points", "n_faces", "n_internal_faces", "n_cells"): + update_hash_text(digest, f"{name}={int(getattr(mesh, name))}") + update_hash_array(digest, "faces.offsets", mesh.faces.offsets) + update_hash_array(digest, "faces.values", mesh.faces.values) + update_hash_array(digest, "cells.offsets", mesh.cells.offsets) + update_hash_array(digest, "cells.values", mesh.cells.values) + update_hash_array(digest, "owner", mesh.owner) + update_hash_array(digest, "neighbour", mesh.neighbour) + ldu = getattr(mesh, "ldu", {}) + if isinstance(ldu, Mapping): + if "lower_addr" in ldu: + update_hash_array(digest, "ldu.lower_addr", ldu["lower_addr"]) + if "upper_addr" in ldu: + update_hash_array(digest, "ldu.upper_addr", ldu["upper_addr"]) + for entry in ldu.get("patch_addr", []): + update_hash_text(digest, f"ldu.patch_index={entry.get('patch_index')}") + update_hash_array(digest, "ldu.patch_addr", entry.get("addr", [])) + for patch in mesh_patch_table(mesh): + update_hash_text(digest, json.dumps(patch, sort_keys=True)) + return digest.hexdigest() + + +def mesh_geometry_digest(mesh: Any) -> str: + digest = hashlib.sha256() + for name in ("points", "V", "C", "Cf", "Sf", "magSf"): + update_hash_array(digest, name, getattr(mesh, name)) + return digest.hexdigest() + + +def mesh_identity(mesh: Any) -> dict[str, Any]: + return { + "n_points": int(mesh.n_points), + "n_faces": int(mesh.n_faces), + "n_internal_faces": int(mesh.n_internal_faces), + "n_cells": int(mesh.n_cells), + "patches": mesh_patch_table(mesh), + "topology_sha256": mesh_topology_digest(mesh), + "geometry_sha256": mesh_geometry_digest(mesh), + } + + +def compare_mesh_identity(mode: str, actual: Mapping[str, Any], expected: Mapping[str, Any]) -> tuple[dict[str, Any], list[dict[str, Any]]]: + keys = ("n_points", "n_faces", "n_internal_faces", "n_cells", "topology_sha256", "geometry_sha256", "patches") + differences = { + key: {"actual": actual.get(key), "expected": expected.get(key)} + for key in keys + if actual.get(key) != expected.get(key) + } + report = {"matches_oracle": not differences, "differences": differences} + if not differences: + return report, [] + return report, [{"mode": mode, "kind": "mesh_identity", "differences": differences}] + + +def field_compare_report(name: str, actual_field: Any, expected_field: Any, *, rtol: float, atol: float) -> tuple[dict[str, Any], dict[str, Any] | None]: + actual = np.asarray(actual_field.internal) + expected = np.asarray(expected_field.internal) + report: dict[str, Any] = { + "field": name, + "actual_shape": array_shape(actual), + "expected_shape": array_shape(expected), + "actual_entity_kind": getattr(actual_field, "entity_kind", ""), + "expected_entity_kind": getattr(expected_field, "entity_kind", ""), + "rtol": rtol, + "atol": atol, + } + + if actual.shape != expected.shape: + report.update({"allclose": False, "reason": "shape_mismatch"}) + return report, {"field": name, "reason": "shape_mismatch", **report} + + if actual.size == 0: + report.update( + { + "allclose": True, + "max_abs": 0.0, + "mean_abs": 0.0, + "location": None, + "actual_at_max": None, + "expected_at_max": None, + } + ) + return report, None + + diff = np.abs(actual - expected) + finite = np.isfinite(diff) + if not np.all(finite): + flat_index = int(np.flatnonzero(~finite)[0]) + max_abs: float | None = None + else: + flat_index = int(np.argmax(diff)) + max_abs = finite_float(diff.reshape(-1)[flat_index]) + + max_index = tuple(int(item) for item in np.unravel_index(flat_index, diff.shape)) + entity_index = max_index[0] if max_index else None + component_index = list(max_index[1:]) if len(max_index) > 1 else None + actual_at_max = value_at(actual, max_index) + expected_at_max = value_at(expected, max_index) + tolerance_at_max = None + if isinstance(expected_at_max, (int, float)): + tolerance_at_max = atol + rtol * abs(float(expected_at_max)) + + finite_diff = diff[finite] + allclose = bool(np.allclose(actual, expected, rtol=rtol, atol=atol, equal_nan=False)) + report.update( + { + "allclose": allclose, + "max_abs": max_abs, + "mean_abs": finite_float(np.mean(finite_diff)) if finite_diff.size else None, + "location": { + "array_index": list(max_index), + "entity_kind": getattr(actual_field, "entity_kind", ""), + "entity_index": entity_index, + "component_index": component_index, + }, + "actual_at_max": actual_at_max, + "expected_at_max": expected_at_max, + "actual_entity_at_max": entity_value_at(actual, entity_index), + "expected_entity_at_max": entity_value_at(expected, entity_index), + "tolerance_at_max": finite_float(tolerance_at_max), + "nonfinite_error_count": int(diff.size - np.count_nonzero(finite)), + } + ) + if allclose: + return report, None + report["reason"] = "value_mismatch" + return report, {"field": name, "reason": "value_mismatch", **report} + + +def compare_fields( + mode: str, + actual: Mapping[str, Any], + expected: Mapping[str, Any], + *, + rtol: float, + atol: float, +) -> tuple[dict[str, Any], list[dict[str, Any]]]: + report: dict[str, Any] = {} + mismatches: list[dict[str, Any]] = [] + for name in REQUIRED_FIELDS: + if name not in actual or name not in expected: + missing = { + "field": name, + "reason": "missing_field", + "missing_actual": name not in actual, + "missing_expected": name not in expected, + "actual_fields": sorted(actual), + "expected_fields": sorted(expected), + } + report[name] = {"field": name, "allclose": False, **missing} + mismatches.append({"mode": mode, **missing}) + continue + field_report, mismatch = field_compare_report(name, actual[name], expected[name], rtol=rtol, atol=atol) + report[name] = field_report + if mismatch is not None: + mismatches.append({"mode": mode, **mismatch}) + return report, mismatches + + +def run_openfoam_command(cmd: list[str], *, log_path: Path, timeout: int) -> dict[str, Any]: + started = time.monotonic() + env = openfoam_env() + log_path.parent.mkdir(parents=True, exist_ok=True) + try: + with log_path.open("w") as log: + subprocess.run(cmd, cwd=ROOT, env=env, check=True, stdout=log, stderr=subprocess.STDOUT, timeout=timeout) + except subprocess.TimeoutExpired as exc: + raise HarnessError( + ORACLE_FAILURE, + Path(cmd[0]).name, + f"OpenFOAM command timed out after {timeout}s: {' '.join(cmd)}", + details={"cmd": cmd, "timeout_seconds": timeout, "log_path": log_path}, + cause=exc, + ) from exc + except subprocess.CalledProcessError as exc: + raise HarnessError( + ORACLE_FAILURE, + Path(cmd[0]).name, + f"OpenFOAM command failed with exit code {exc.returncode}: {' '.join(cmd)}", + details={"cmd": cmd, "returncode": exc.returncode, "log_path": log_path}, + cause=exc, + ) from exc + return { + "cmd": cmd, + "returncode": 0, + "log_path": log_path, + "duration_seconds": round(time.monotonic() - started, 6), + "timeout_seconds": timeout, + } + + +def patch_start_from_latest(case: Path) -> None: + path = case / "system/controlDict" + text = path.read_text() + old = "startFrom startTime;" + new = "startFrom latestTime;" + if old not in text: + raise AssertionError(f"{path}: missing {old!r}") + path.write_text(text.replace(old, new, 1)) + + +def import_foam() -> Any: + apply_openfoam_env() + import foam_stepper as foam + + return foam + + +def prepare_work_cases(source: Path, work: Path, *, include_split: bool) -> dict[str, Any]: + if work.exists(): + shutil.rmtree(work) + work.mkdir(parents=True) + oracle = work / "oracle_case" + run_one = work / "run_one_case" + split = work / "split_case" if include_split else None + + oracle_meta = prepare_case(source, oracle, end_time=1) + run_one_meta = prepare_case(source, run_one, end_time=1) + split_meta = prepare_case(source, split, end_time=1) if split is not None else None + + return { + "oracle_case": oracle, + "run_one_case": run_one, + "split_case": split, + "metadata": { + "oracle": oracle_meta, + "run_one": run_one_meta, + "split": split_meta, + }, + } + + +def make_stepper(foam: Any, case: Path, label: str) -> Any: + try: + return foam.Case(case).make_stepper() + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + f"load_{label}_case", + f"failed to load {label} case with foam_stepper: {case}", + details={"case": case}, + cause=exc, + ) from exc + + +def read_mesh_identity(stepper: Any, label: str) -> dict[str, Any]: + try: + return mesh_identity(stepper.mesh()) + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + f"read_{label}_mesh", + f"failed to read {label} mesh identity", + details={"case": getattr(stepper, "case_path", "")}, + cause=exc, + ) from exc + + +def read_fields(stepper: Any, label: str) -> dict[str, Any]: + try: + return field_dict_to_mapping(stepper.fields()) + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + f"read_{label}_fields", + f"failed to read {label} fields", + details={"case": getattr(stepper, "case_path", "")}, + cause=exc, + ) from exc + + +def checked_step(stages: list[dict[str, Any]], name: str, fn: Any) -> Any: + try: + result = fn() + except Exception as exc: + raise HarnessError( + STEPPER_FAILURE, + name, + f"split-step stage failed: {name}", + cause=exc, + ) from exc + stages.append(transform_summary(result)) + return result + + +def run_split_iteration(stepper: Any) -> dict[str, Any]: + stages: list[dict[str, Any]] = [] + checked_step(stages, "pre_solve", stepper.pre_solve) + checked_step(stages, "advance_time", stepper.advance_time) + begin = checked_step(stages, "begin_pimple_iteration", stepper.begin_pimple_iteration) + if begin.outputs.get("active") is not True: + raise HarnessError( + STEPPER_FAILURE, + "begin_pimple_iteration", + "split-step PIMPLE iteration was inactive", + details={"outputs": summarize_value(begin.outputs)}, + ) + + checked_step(stages, "fv_models_correct", stepper.fv_models_correct) + checked_step(stages, "pre_predictor", stepper.pre_predictor) + checked_step(stages, "momentum_transport_predict", stepper.momentum_transport_predictor) + terms = checked_step(stages, "assemble_momentum_terms", stepper.assemble_momentum_terms) + UEqn = checked_step(stages, "assemble_UEqn", stepper.assemble_momentum_matrix) + checked_step(stages, "relax_UEqn", stepper.relax_matrix) + checked_step(stages, "constrain_UEqn", stepper.constrain_matrix) + checked_step(stages, "solve_UEqn", stepper.solve_momentum) + checked_step(stages, "compute_pressure_inputs", stepper.compute_pressure_inputs) + pEqn = checked_step(stages, "assemble_pEqn", stepper.assemble_pressure_matrix) + checked_step(stages, "solve_pEqn", stepper.solve_pressure) + checked_step(stages, "correct_velocity_pressure_flux", stepper.correct_velocity_pressure_flux) + checked_step(stages, "momentum_transport_correct", stepper.momentum_transport_corrector) + checked_step(stages, "end_pimple_iteration", stepper.end_pimple_iteration) + checked_step(stages, "post_solve", lambda: stepper.post_solve(write=False)) + + try: + fields = field_dict_to_mapping(stepper.fields()) + except Exception as exc: + raise HarnessError( + STEPPER_FAILURE, + "split_fields", + "failed to read split-step fields after execution", + cause=exc, + ) from exc + + momentum_terms = [term.get("name", "") for term in terms.outputs.get("terms", [])] + UEqn_matrix = UEqn.outputs["UEqn"] + pEqn_matrix = pEqn.outputs["pEqn"] + return { + "fields": fields, + "stages": stages, + "graph": [stage["name"] for stage in stages], + "momentum_terms": momentum_terms, + "UEqn": matrix_summary(UEqn_matrix), + "pEqn": matrix_summary(pEqn_matrix), + } + + +def visible_turbulence_fields(fields: Mapping[str, Any]) -> list[str]: + return [name for name in TURBULENCE_FIELDS if name in fields] + + +def base_report(args: argparse.Namespace) -> dict[str, Any]: + report_path = args.report if args.report is not None else args.work / "verifier_report.json" + return { + "harness": { + "name": "airfrans_stepper_verifier", + "spec": "VERIFIER_HARNESS_SPEC.md", + "schema_version": 1, + }, + "status": "running", + "failure": None, + "paths": { + "root": ROOT, + "source": args.source, + "work": args.work, + "report": report_path, + }, + "source_policy": "raw AirfRANS source is read-only; all solver runs use prepared work-directory copies", + "tolerances": { + "rtol": args.rtol, + "atol": args.atol, + "policy": "CPU stepper parity with the repository OpenFOAM oracle must pass np.allclose for every required field.", + }, + "required_fields": { + "primary": list(PRIMARY_FIELDS), + "turbulence": list(TURBULENCE_FIELDS), + "all": list(REQUIRED_FIELDS), + }, + "commands": [], + "case_preparation": {}, + "mesh_identity": {}, + "modes": { + "run_one": {"enabled": True}, + "split": {"enabled": not args.skip_split}, + }, + "tracked_turbulence_fields": {}, + "comparison_mismatches": [], + } + + +def run_harness(args: argparse.Namespace, report: dict[str, Any]) -> None: + try: + prepared = prepare_work_cases(args.source, args.work, include_split=not args.skip_split) + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + "prepare_cases", + "failed to prepare reproducible AirfRANS work cases", + details={"source": args.source, "work": args.work}, + cause=exc, + ) from exc + + oracle_case = prepared["oracle_case"] + run_one_case = prepared["run_one_case"] + split_case = prepared["split_case"] + report["case_preparation"] = json_ready(prepared) + + report["commands"].append( + run_openfoam_command(["checkMesh", "-case", str(oracle_case), "-constant"], log_path=args.work / "checkMesh.log", timeout=120) + ) + report["commands"].append( + run_openfoam_command( + ["foamRun", "-case", str(oracle_case), "-solver", "incompressibleFluid", "-noFunctionObjects"], + log_path=args.work / "foamRun_oracle.log", + timeout=600, + ) + ) + + try: + patch_start_from_latest(oracle_case) + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + "select_oracle_latest_time", + "failed to configure oracle case to load latestTime output", + details={"case": oracle_case}, + cause=exc, + ) from exc + + try: + foam = import_foam() + except Exception as exc: + raise HarnessError( + LOADING_FAILURE, + "import_foam_stepper", + "failed to import foam_stepper in the repository OpenFOAM environment", + cause=exc, + ) from exc + + oracle_stepper = make_stepper(foam, oracle_case, "oracle") + oracle_mesh = read_mesh_identity(oracle_stepper, "oracle") + oracle_fields = read_fields(oracle_stepper, "oracle") + report["mesh_identity"]["oracle"] = oracle_mesh + report["modes"]["oracle"] = { + "case": oracle_case, + "fields": selected_field_summaries(oracle_fields), + } + report["tracked_turbulence_fields"]["oracle"] = visible_turbulence_fields(oracle_fields) + + run_one_stepper = make_stepper(foam, run_one_case, "run_one") + run_one_mesh = read_mesh_identity(run_one_stepper, "run_one") + report["mesh_identity"]["run_one"] = run_one_mesh + mesh_report, mesh_mismatches = compare_mesh_identity("run_one", run_one_mesh, oracle_mesh) + report["modes"]["run_one"]["mesh_comparison"] = mesh_report + + try: + run_one_result = run_one_stepper.run_one_pimple_iteration() + run_one_fields = field_dict_to_mapping(run_one_result.outputs["fields"]) + except Exception as exc: + raise HarnessError( + STEPPER_FAILURE, + "run_one_pimple_iteration", + "full one-iteration stepper execution failed", + details={"case": run_one_case}, + cause=exc, + ) from exc + + run_one_comparisons, run_one_mismatches = compare_fields( + "run_one", + run_one_fields, + oracle_fields, + rtol=args.rtol, + atol=args.atol, + ) + report["modes"]["run_one"].update( + { + "case": run_one_case, + "stage": transform_summary(run_one_result), + "graph": [entry.name for entry in run_one_result.outputs.get("graph", [])], + "fields": selected_field_summaries(run_one_fields), + "comparisons": run_one_comparisons, + } + ) + report["tracked_turbulence_fields"]["run_one"] = visible_turbulence_fields(run_one_fields) + + mismatches = mesh_mismatches + run_one_mismatches + + if split_case is not None: + split_stepper = make_stepper(foam, split_case, "split") + split_mesh = read_mesh_identity(split_stepper, "split") + report["mesh_identity"]["split"] = split_mesh + split_mesh_report, split_mesh_mismatches = compare_mesh_identity("split", split_mesh, oracle_mesh) + report["modes"]["split"]["mesh_comparison"] = split_mesh_report + + split_result = run_split_iteration(split_stepper) + split_fields = split_result["fields"] + split_comparisons, split_mismatches = compare_fields( + "split", + split_fields, + oracle_fields, + rtol=args.rtol, + atol=args.atol, + ) + report["modes"]["split"].update( + { + "case": split_case, + "graph": split_result["graph"], + "stages": split_result["stages"], + "momentum_terms": split_result["momentum_terms"], + "UEqn": split_result["UEqn"], + "pEqn": split_result["pEqn"], + "fields": selected_field_summaries(split_fields), + "comparisons": split_comparisons, + } + ) + report["tracked_turbulence_fields"]["split"] = visible_turbulence_fields(split_fields) + mismatches.extend(split_mesh_mismatches) + mismatches.extend(split_mismatches) + + report["comparison_mismatches"] = json_ready(mismatches) + if mismatches: + raise HarnessError( + COMPARISON_FAILURE, + "compare_oracle_stepper_outputs", + f"{len(mismatches)} verifier comparison mismatch(es) observed", + details={"mismatches": mismatches}, + ) + + +def write_report(report: Mapping[str, Any], path: Path) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(json.dumps(json_ready(report), indent=2, sort_keys=True, allow_nan=False) + "\n") + + +def fmt_sci(value: Any) -> str: + if value is None: + return "none" + try: + return f"{float(value):.3e}" + except (TypeError, ValueError): + return str(value) + + +def format_location(location: Mapping[str, Any] | None) -> str: + if not location: + return "none" + component = location.get("component_index") + component_text = "" if component is None else f" component={component}" + return f"{location.get('entity_kind')}[{location.get('entity_index')}]{component_text}" + + +def print_human_summary(report: Mapping[str, Any]) -> None: + status = report.get("status") + print(f"airfrans_stepper_verification {status}") + print(f"source={report['paths']['source']}") + print(f"work={report['paths']['work']}") + print(f"report={report['paths']['report']}") + print(f"rtol={report['tolerances']['rtol']} atol={report['tolerances']['atol']}") + + if status != "passed": + failure = report.get("failure") or {} + print(f"failure_category={failure.get('category')}") + print(f"failure_step={failure.get('step')}") + print(f"failure_message={failure.get('message')}") + return + + oracle_mesh = report["mesh_identity"]["oracle"] + patch_names = [patch["name"] for patch in oracle_mesh["patches"]] + print(f"oracle_case={report['case_preparation']['oracle_case']}") + print(f"run_one_case={report['modes']['run_one']['case']}") + if report["modes"].get("split", {}).get("enabled"): + print(f"split_case={report['modes']['split']['case']}") + print(f"mesh_cells={oracle_mesh['n_cells']}") + print(f"mesh_internal_faces={oracle_mesh['n_internal_faces']}") + print(f"mesh_patches={patch_names}") + print(f"mesh_topology_sha256={oracle_mesh['topology_sha256']}") + + for mode in ("run_one", "split"): + mode_report = report["modes"].get(mode, {}) + if not mode_report.get("enabled", False): + continue + for field_name in REQUIRED_FIELDS: + data = mode_report.get("comparisons", {}).get(field_name) + if not data: + continue + print( + f"mode={mode} field={field_name} actual_shape={tuple(data['actual_shape'])} " + f"expected_shape={tuple(data['expected_shape'])} max_abs={fmt_sci(data.get('max_abs'))} " + f"location={format_location(data.get('location'))} allclose={data['allclose']}" + ) + graph = mode_report.get("graph") + if graph: + print(f"{mode}_graph={graph}") + + split_report = report["modes"].get("split", {}) + if split_report.get("enabled") and "UEqn" in split_report and "pEqn" in split_report: + print(f"split_momentum_terms={split_report.get('momentum_terms')}") + print(f"split_UEqn_diag_shape={tuple(split_report['UEqn']['diag']['shape'])}") + print(f"split_pEqn_diag_shape={tuple(split_report['pEqn']['diag']['shape'])}") + + print(f"visible_turbulence_fields={report['tracked_turbulence_fields']}") + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--source", type=Path, default=DEFAULT_SOURCE) + parser.add_argument("--work", type=Path, default=DEFAULT_WORK) + parser.add_argument("--report", type=Path, default=None, help="JSON report path; defaults to WORK/verifier_report.json") + parser.add_argument("--rtol", type=float, default=1e-8) + parser.add_argument("--atol", type=float, default=1e-8) + parser.add_argument("--skip-split", action="store_true", help="Skip the explicit split-step parity check for local debugging") + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + args.source = args.source.resolve() + args.work = args.work.resolve() + if args.report is None: + args.report = args.work / "verifier_report.json" + else: + args.report = args.report.resolve() + + report = base_report(args) + exit_code = 0 + try: + run_harness(args, report) + report["status"] = "passed" + except HarnessError as exc: + report["status"] = "failed" + report["failure"] = exc.to_dict() + exit_code = EXIT_CODES.get(exc.category, EXIT_CODES[INTERNAL_FAILURE]) + except Exception as exc: # pragma: no cover - keeps CLI failures categorized in the report. + report["status"] = "failed" + report["failure"] = json_ready( + { + "category": INTERNAL_FAILURE, + "step": "run_harness", + "message": str(exc), + "cause": {"type": type(exc).__name__, "message": str(exc)}, + "traceback": traceback.format_exc(), + } + ) + exit_code = EXIT_CODES[INTERNAL_FAILURE] + + try: + write_report(report, args.report) + except Exception as exc: + report["status"] = "failed" + report["failure"] = json_ready( + { + "category": INTERNAL_FAILURE, + "step": "write_report", + "message": f"failed to write verifier report: {args.report}", + "cause": {"type": type(exc).__name__, "message": str(exc)}, + } + ) + exit_code = EXIT_CODES[INTERNAL_FAILURE] + + print_human_summary(json_ready(report)) + return exit_code + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/verify_python_stepper.py b/scripts/verify_python_stepper.py new file mode 100755 index 0000000..93855b0 --- /dev/null +++ b/scripts/verify_python_stepper.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +"""Scenario checks for the Python-driven OpenFOAM observability stepper.""" + +from __future__ import annotations + +import os +import shutil +import subprocess +import sys +from pathlib import Path + + +def _drop_ambient_pythonpath() -> None: + pythonpath = os.environ.pop("PYTHONPATH", "") + for entry in pythonpath.split(os.pathsep): + if not entry: + continue + while entry in sys.path: + sys.path.remove(entry) + + +_drop_ambient_pythonpath() + +import numpy as np + +from openfoam_env import apply_openfoam_env, openfoam_env + +ROOT = Path(__file__).resolve().parents[1] +TUTORIAL = ROOT / "OpenFOAM-14/tutorials/incompressibleFluid/venturiTube" +WORK = ROOT / "tmp/python_stepper_verify" +LOAD_CASE = WORK / "load_case" +TRANSFORM_CASE = WORK / "transform_case" +PY_EQ_CASE = WORK / "python_equivalence_case" +FOAM_EQ_CASE = WORK / "foam_equivalence_case" + + +def run(cmd: list[str]) -> None: + subprocess.run(cmd, cwd=ROOT, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, env=openfoam_env()) + + +def patch_control_dict(case: Path, *, latest: bool = False) -> None: + path = case / "system/controlDict" + text = path.read_text() + replacements = { + "startFrom startTime;": "startFrom latestTime;" if latest else "startFrom startTime;", + "endTime 1000;": "endTime 1;", + "writeInterval 50;": "writeInterval 1;", + } + for old, new in replacements.items(): + text = text.replace(old, new) + path.write_text(text) + + +def prepare_case(dst: Path) -> None: + if dst.exists(): + shutil.rmtree(dst) + shutil.copytree(TUTORIAL, dst, ignore=shutil.ignore_patterns("processor*", "postProcessing", "*.log")) + for orig in (dst / "0").glob("*.orig"): + shutil.copyfile(orig, orig.with_suffix("")) + patch_control_dict(dst) + run(["blockMesh", "-case", str(dst)]) + run(["createZones", "-case", str(dst)]) + +def import_foam(): + apply_openfoam_env() + import foam_stepper as foam + + return foam + + + +def load_scenario() -> None: + foam = import_foam() + case = foam.Case(LOAD_CASE) + stepper = case.make_stepper() + mesh = stepper.mesh() + fields = stepper.fields() + assert mesh.n_cells == 57600 + assert mesh.n_internal_faces == fields.phi.internal.shape[0] + assert fields.U.internal.shape == (mesh.n_cells, 3) + assert fields.p.internal.shape == (mesh.n_cells,) + assert fields.phi.internal.shape == (mesh.n_internal_faces,) + assert {patch.name for patch in mesh.boundary} == {"inlet", "outlet", "walls"} + + try: + stepper.assemble_pressure_matrix() + except foam.OpenFoamError as exc: + assert "Momentum matrix is not assembled" in str(exc) + else: + raise AssertionError("assemble_pressure_matrix succeeded before momentum assembly") + + +def transformation_scenario() -> None: + foam = import_foam() + stepper = foam.Case(TRANSFORM_CASE).make_stepper() + stepper.pre_solve() + stepper.advance_time() + begin = stepper.begin_pimple_iteration() + assert begin.outputs["active"] is True + + terms = stepper.assemble_momentum_terms() + names = {term["name"] for term in terms.outputs["terms"]} + assert { + "assemble_momentum_ddt", + "assemble_momentum_div_phi_U", + "assemble_momentum_MRF_DDt", + "assemble_momentum_divDevSigma", + "assemble_momentum_sources", + "assemble_momentum_pressure_rhs_grad_p", + }.issubset(names) + + UEqn = stepper.assemble_momentum_matrix().outputs["UEqn"] + assert UEqn.diag.shape == (57600,) + assert UEqn.psi.internal.shape == (57600, 3) + assert UEqn.source.shape == (57600, 3) + assert UEqn.H is not None + + stepper.relax_matrix() + stepper.constrain_matrix() + momentum = stepper.solve_momentum() + assert momentum.outputs["performance"].field_name == "U" + + pressure_inputs = stepper.compute_pressure_inputs() + assert pressure_inputs.outputs["rAU"].internal.shape == (57600,) + assert pressure_inputs.outputs["HbyA"].internal.shape == (57600, 3) + assert pressure_inputs.outputs["phiHbyA"].internal.shape == (170624,) + + pEqn = stepper.assemble_pressure_matrix().outputs["pEqn"] + assert pEqn.diag.shape == (57600,) + assert pEqn.psi.internal.shape == (57600,) + assert pEqn.flux is not None + + pressure = stepper.solve_pressure() + assert pressure.name == "solve_pEqn" + assert pressure.outputs["performance"].field_name == "p" + assert pressure.outputs["p"].internal.shape == (57600,) + assert pressure.outputs["phi"].internal.shape == (170624,) + + correction = stepper.correct_velocity_pressure_flux() + assert correction.outputs["U"].internal.shape == (57600, 3) + assert correction.outputs["phi"].internal.shape == (170624,) + + +def equivalence_scenario() -> None: + foam = import_foam() + run(["foamRun", "-case", str(FOAM_EQ_CASE), "-solver", "incompressibleFluid", "-noFunctionObjects"]) + patch_control_dict(FOAM_EQ_CASE, latest=True) + baseline = foam.Case(FOAM_EQ_CASE).make_stepper().fields() + + result = foam.Case(PY_EQ_CASE).make_stepper().run_one_pimple_iteration() + actual = result.outputs["fields"] + + comparisons = { + "U": (actual["U"].internal, baseline.U.internal), + "p": (actual["p"].internal, baseline.p.internal), + "phi": (actual["phi"].internal, baseline.phi.internal), + } + for name, (lhs, rhs) in comparisons.items(): + if lhs.shape != rhs.shape: + raise AssertionError(f"{name} shape mismatch: {lhs.shape} != {rhs.shape}") + max_abs = float(np.max(np.abs(lhs - rhs))) + if not np.allclose(lhs, rhs, rtol=1e-7, atol=1e-7): + raise AssertionError(f"{name} mismatch: max_abs={max_abs}") + print(f"equivalence {name}: max_abs={max_abs:.3e}") + + graph = result.outputs["graph"] + graph_names = {entry.name for entry in graph} + assert {"pre_solve", "advance_time", "assemble_UEqn", "solve_UEqn", "assemble_pEqn", "solve_pEqn"}.issubset(graph_names) + + +def main() -> None: + if len(sys.argv) == 2: + scenarios = { + "load": load_scenario, + "transformation": transformation_scenario, + "equivalence": equivalence_scenario, + } + scenarios[sys.argv[1]]() + return + + if WORK.exists(): + shutil.rmtree(WORK) + WORK.mkdir(parents=True) + for case_dir in (LOAD_CASE, TRANSFORM_CASE, PY_EQ_CASE, FOAM_EQ_CASE): + prepare_case(case_dir) + + for scenario in ("load", "transformation", "equivalence"): + subprocess.run([sys.executable, __file__, scenario], cwd=ROOT, check=True, env=openfoam_env()) + + print("python stepper verification passed") + + +if __name__ == "__main__": + main() diff --git a/scripts/verify_python_stepper.sh b/scripts/verify_python_stepper.sh new file mode 100755 index 0000000..c45f4a0 --- /dev/null +++ b/scripts/verify_python_stepper.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" +JOBS="${JOBS:-$(nproc)}" +PYTHON_BIN="${PYTHON_BIN:-${ROOT_DIR}/.venv/bin/python}" + +if [[ ! -x "${PYTHON_BIN}" ]]; then + uv sync --dev +fi + +if ! PYTHONPATH= "${PYTHON_BIN}" -c 'import pybind11, numpy' >/dev/null 2>&1; then + uv sync --dev +fi + +"${ROOT_DIR}/scripts/build_openfoam_airfrans_subset.sh" >/dev/null + +# blockMesh/createZones are verification fixtures for deterministic tutorial cases. +set +u +source "${ROOT_DIR}/OpenFOAM-14/etc/bashrc" \ + WM_MPLIB=Dummy \ + ParaView_TYPE=none \ + SCOTCH_TYPE=none \ + ZOLTAN_TYPE=none +set -u + +# OpenFOAM's SIGFPE trap is useful for solver binaries but unsafe for Python's +# own floating-point formatting/comparison code inside the verification process. +unset FOAM_SIGFPE + +( + cd "${ROOT_DIR}/OpenFOAM-14" + wmake -j "${JOBS}" libso src/mesh/blockMesh >/dev/null + wmake -j "${JOBS}" applications/utilities/mesh/generation/blockMesh >/dev/null + wmake -j "${JOBS}" applications/utilities/mesh/manipulation/createZones >/dev/null +) + +"${ROOT_DIR}/scripts/build_python_stepper.sh" >/dev/null + +"${PYTHON_BIN}" "${ROOT_DIR}/scripts/verify_python_stepper.py" diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..002e489 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1801 @@ +version = 1 +revision = 3 +requires-python = ">=3.12" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version < '3.14'", +] + +[[package]] +name = "annotated-types" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, +] + +[[package]] +name = "anyio" +version = "4.14.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/1e/faf0f247f6f881b98fc4d6d07e14085cb89d13665084e6d6ac1dc2c03d0b/asttokens-3.0.2.tar.gz", hash = "sha256:3ecdbd8f2cc195f53ccada3a613538bb5f9ef6f6869129f13e03c30a677b8fe2", size = 63136, upload-time = "2026-07-12T03:31:49.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/2b/04b8a15f3a1c77bc79ddf5c73875327f34b4fa75982df2b76e45e402d364/asttokens-3.0.2-py3-none-any.whl", hash = "sha256:9da13157f5b28becde0bd374fc677dcd3c290614264eff096f167c469cd9f933", size = 28702, upload-time = "2026-07-12T03:31:47.542Z" }, +] + +[[package]] +name = "async-lru" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/1f/989ecfef8e64109a489fff357450cb73fa73a865a92bd8c272170a6922c2/async_lru-2.3.0.tar.gz", hash = "sha256:89bdb258a0140d7313cf8f4031d816a042202faa61d0ab310a0a538baa1c24b6", size = 16332, upload-time = "2026-03-19T01:04:32.413Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/e2/c2e3abf398f80732e58b03be77bde9022550d221dd8781bf586bd4d97cc1/async_lru-2.3.0-py3-none-any.whl", hash = "sha256:eea27b01841909316f2cc739807acea1c623df2be8c5cfad7583286397bb8315", size = 8403, upload-time = "2026-03-19T01:04:30.883Z" }, +] + +[[package]] +name = "attrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9a/8e/82a0fe20a541c03148528be8cac2408564a6c9a0cc7e9171802bc1d26985/attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32", size = 952055, upload-time = "2026-03-19T14:22:25.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, +] + +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/65/318323f98dbee45d42dff61d8f047181bc6f2268a9068cfad035a46be5af/beautifulsoup4-4.15.0.tar.gz", hash = "sha256:288e3ca7d54b06f2ac191970bc275c1939cb46d450b255bf6718b04aa37ab4f7", size = 632571, upload-time = "2026-06-07T16:44:20.453Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/c6/92fcd42f1ba33e1184263f25bfabf3d27c383410470f169e4b8163bf9c17/beautifulsoup4-4.15.0-py3-none-any.whl", hash = "sha256:d6f88de62e1d4e38ecb1077eb9724cd0eff29d2a08ca16a401e9b9e93f117cf9", size = 109924, upload-time = "2026-06-07T16:44:21.566Z" }, +] + +[[package]] +name = "bleach" +version = "6.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/3c/e12ac860709702bd5ebeb9b56a4fe334f1001246ee1b8f2b7ee28912df7d/bleach-6.4.0.tar.gz", hash = "sha256:4202482733d85cedd04e59fcb2f89f4e4c7c385a78d3c3c23c30446843a37452", size = 204857, upload-time = "2026-06-05T13:01:13.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/9d/40b6267367182187139a4000b82a3b287d84d745bccd808e75d916920e9d/bleach-6.4.0-py3-none-any.whl", hash = "sha256:4b6b6a54fff2e69a3dde9d21cc6301220bee3c3cb792187d11403fd795031081", size = 165109, upload-time = "2026-06-05T13:01:12.504Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + +[[package]] +name = "certifi" +version = "2026.7.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, +] + +[[package]] +name = "cffi" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/57/5f/ff100cae70ebe9d8df1c01a00e510e45d9adb5c1fdda84791b199141de97/cffi-2.1.0.tar.gz", hash = "sha256:efc1cdd798b1aaf39b4610bba7aad28c9bea9b910f25c784ccf9ec1fa719d1f9", size = 531036, upload-time = "2026-07-06T21:34:30.382Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/85/990925db5df586ec90beb97529c853497e7f85ba0234830447faf41c3057/cffi-2.1.0-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:df2b82571a1b30f58a87bf4e5a9e78d2b1eff6c6ce8fd3aa3757221f93f0863f", size = 184829, upload-time = "2026-07-06T21:32:44.324Z" }, + { url = "https://files.pythonhosted.org/packages/4b/92/e7bb136ad6b5352603732cf907ef862ca103f20f2031c1735a46300c20c9/cffi-2.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78474632761faa0fb96f30b1c928c84ebcf68713cbb80d15bab09dfe61640fde", size = 184728, upload-time = "2026-07-06T21:32:45.683Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c0/d1ec30ffb370f748f2fb54425972bfef9871e0132e82fb589c46b6676049/cffi-2.1.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:5972433ad71a9e46516584ef60a0fda12d9dc459938d1539c3ddecf9bdc1368d", size = 214815, upload-time = "2026-07-06T21:32:48.557Z" }, + { url = "https://files.pythonhosted.org/packages/1b/dc/5620cf930688be01f2d673804291de757a934c90b946dbdc3d84130c2ea4/cffi-2.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b6422532152adf4e59b110cb2808cee7a033800952f5c036b4af047ee43199e7", size = 222429, upload-time = "2026-07-06T21:32:49.848Z" }, + { url = "https://files.pythonhosted.org/packages/4b/a4/77b53abbf7a1e0beb9637edbef2a94d15f9c822f591e85d439ffd91519a6/cffi-2.1.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:46b1c8db8f6122420f32d02fffb924c2fe9bc772d228c7c711748fff56aabb2b", size = 210315, upload-time = "2026-07-06T21:32:51.221Z" }, + { url = "https://files.pythonhosted.org/packages/58/0c/f528df19cc94b675087324d4760d9e6d5bfae97d6217aa4fac43de4f5fcc/cffi-2.1.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9fafc5aa2e2a39aaf7f8cc0c1f044a9b07fca12e558dca53a3cc5c654ad67a7", size = 208859, upload-time = "2026-07-06T21:32:52.512Z" }, + { url = "https://files.pythonhosted.org/packages/62/f2/c9522a81c32132799a1972c39f5c5f8b4c8b9f00488a23feaa6c06f07741/cffi-2.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1e9f50d192a3e525b15a75ab5114e442d83d657b7ec29182a991bc9a88fd3a66", size = 221844, upload-time = "2026-07-06T21:32:53.704Z" }, + { url = "https://files.pythonhosted.org/packages/6e/28/bd53988b9833e8f8ad539d26f4c07a6b3f6bcb1e9e02e7ca038250b3428d/cffi-2.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98fff996e983a36d3aa2eca83af40c5821202e7e6f32d13ae94e3d2286f10cfe", size = 225287, upload-time = "2026-07-06T21:32:54.907Z" }, + { url = "https://files.pythonhosted.org/packages/79/99/0d0fd37f055224085f42bbb2c022d002e17dde4a97972822327b07d84101/cffi-2.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:379de10ce1ba048b1448599d1b37b24caee16309d1ac98d3982fc997f768700b", size = 223681, upload-time = "2026-07-06T21:32:56.329Z" }, + { url = "https://files.pythonhosted.org/packages/b0/80/c138990aa2a70b1a269f6e06348729836d733d6f970867943f61d367f8cc/cffi-2.1.0-cp312-cp312-win32.whl", hash = "sha256:9b8f0f26ca4e7513c534d351eca551947d053fac438f2a04ac96d882909b0d3a", size = 175269, upload-time = "2026-07-06T21:32:57.777Z" }, + { url = "https://files.pythonhosted.org/packages/a8/eb/f636456ff21a83fc13c032b58cc5dde061691546ac79efa284b2989b7982/cffi-2.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:c97f080ea627e2863524c5af3836e2270b5f5dfff1f104392b959f8df0c5d384", size = 185881, upload-time = "2026-07-06T21:32:59.253Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/400ea43e721727dca8a65c4521390e9196757caba4a45643acb2b63271b8/cffi-2.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:6d194185eabd279f1c05ebe3504265ddfc5ad2b58d0714f7db9f01da592e9eb6", size = 180088, upload-time = "2026-07-06T21:33:02.278Z" }, + { url = "https://files.pythonhosted.org/packages/96/88/a996879e2eeccb815f6e3a5967b12a308257412acec882039d386bd2aa7b/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:10537b1df4967ca26d21e5072d7d54188354483b91dc75058968d3f0cf13fbda", size = 194331, upload-time = "2026-07-06T21:33:03.697Z" }, + { url = "https://files.pythonhosted.org/packages/58/85/7ae00d5c8dd6266f4e944c3db630f3c5c9a98b61d469c714d848b1d8138a/cffi-2.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a95b05f9baf29b91171b3a8bd2020b028835243e7b0ff6bb23e2a3c228518b1b", size = 196966, upload-time = "2026-07-06T21:33:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e9/45c3a76ad8d43ad9261f4c95436da61128d3ca545d72b9612c0ab5be0b1c/cffi-2.1.0-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:15faec4adfff450819f3aee0e2e02c812de6edb88203aa58807955db2003472a", size = 184795, upload-time = "2026-07-06T21:33:06.699Z" }, + { url = "https://files.pythonhosted.org/packages/84/4c/82f132cb4418ee6d953d982b19191e87e2a6372c8a4ce36e50b69d6ade4a/cffi-2.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:716ff8ec22f20b4d988b12884086bcef0fc99737043e503f7a3935a6be99b1ea", size = 184746, upload-time = "2026-07-06T21:33:08.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1c/4ed5a0e5bdca6cbc275556de3328dd1b76fd0c11cc13c88fe66d1d8715f2/cffi-2.1.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:63960549e4f8dc41e31accb97b975abaecfc44c03e396c093a6436763c2ea7db", size = 214747, upload-time = "2026-07-06T21:33:09.671Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a6/e879bb68cc23a2bc9ba8f4b7d8019f0c2694bad2ab6c4a3701d429439f58/cffi-2.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff067a8d8d880e7809e4ac88eb009bb848870115317b306666502ccad30b147f", size = 222392, upload-time = "2026-07-06T21:33:10.896Z" }, + { url = "https://files.pythonhosted.org/packages/88/f6/01890cfd63c08f8eb96a8319b0443690197d240a8bd6346048cf7bde9190/cffi-2.1.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3b926723c13eba9f81d2ef3820d63aeceec3b2d4639906047bf675cb8a7a500d", size = 210285, upload-time = "2026-07-06T21:33:12.251Z" }, + { url = "https://files.pythonhosted.org/packages/a6/cf/2b684132056f438567b61e19d690dd31cd0921ace051e0a458be6074369e/cffi-2.1.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:47ff3a8bfd8cb9da1af7524b965127095055654c177fcfc7578debcb015eecd0", size = 208801, upload-time = "2026-07-06T21:33:13.617Z" }, + { url = "https://files.pythonhosted.org/packages/6f/08/f2e7d62c460faae0926f2d6e423694aa409ced3bc1fe2927a0a6e5f05416/cffi-2.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:799416bae98336e400981ff6e532d67d5c709cfb30afb79865a1315f94b0e224", size = 221808, upload-time = "2026-07-06T21:33:15.466Z" }, + { url = "https://files.pythonhosted.org/packages/38/37/04f54b8e63a02f3d908332c9effbf8c366167c6f733ed8a3d4f79b7e2a1e/cffi-2.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:961be50688f7fba2fa65f63712d3b9b341a22311f5253460ce933f52f0de1c8c", size = 225241, upload-time = "2026-07-06T21:33:16.869Z" }, + { url = "https://files.pythonhosted.org/packages/a9/d6/c72eecca433cd3e681c65ed313ab4835d9d4a379704d0f628a6a05f51c2e/cffi-2.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf5c6cf48238b0eb4c086978c492ad1cbc22373fc5b2d7353b3a598ce6db887a", size = 223588, upload-time = "2026-07-06T21:33:18.239Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4b/e706f67279140f92939da3475ad610df18bfd52d50f14953a8e5fede71d5/cffi-2.1.0-cp313-cp313-win32.whl", hash = "sha256:db3eb7d46527159a878ec3460e9d40615bc25ba337d477db681aea6e4f05c5d2", size = 175248, upload-time = "2026-07-06T21:33:19.799Z" }, + { url = "https://files.pythonhosted.org/packages/5a/47/59eb7975cb0e4ef0afa764ea945b29a5bb4537a9f771cb7d6c8a5dd74c95/cffi-2.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:8e74a6135550c4748af665b1b1118b6aab33b1fc6a16f9aff630af107c3b4512", size = 185717, upload-time = "2026-07-06T21:33:21.47Z" }, + { url = "https://files.pythonhosted.org/packages/5a/af/34fee85c48f8d94efc8597bc09470c9dd274c145f1c12e0fbc6ab6d38d74/cffi-2.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:2282cd5e38aa8accd03e99d1256af8411c84cdbee6a89d841b563fdbd1f3e50f", size = 180114, upload-time = "2026-07-06T21:33:22.515Z" }, + { url = "https://files.pythonhosted.org/packages/d8/f0/81478e482afa03f6d18dc8f2afb5edc45b3080853b634b5ed91961be0998/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:d2117334c3af3bdcb9a88522b844a2bdb5efdc4f71c6c822df55486ae1c3347a", size = 194142, upload-time = "2026-07-06T21:33:23.657Z" }, + { url = "https://files.pythonhosted.org/packages/7d/95/8de304305cd9204974b0ca051b86d307cafca13aa575a0ef1b44d92c0d8c/cffi-2.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:702c436735fbe99d59ada02a1f65cfc0d31c0ee8b7290912f8fbc5cd1e4b16c3", size = 196819, upload-time = "2026-07-06T21:33:25.007Z" }, + { url = "https://files.pythonhosted.org/packages/20/71/7c8372d30e42415602ed9f268f7cfd66f1b855fed881ecd168bcb45dbc0b/cffi-2.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:1ff3456eab0d889592d1936d6125bbfbc7ae4d3354a700f8bd80450a66445d4d", size = 184965, upload-time = "2026-07-06T21:33:26.605Z" }, + { url = "https://files.pythonhosted.org/packages/d6/5c/584e626835f0375c928176c04137c96927165cb8733cdb3150ec04e5ee5e/cffi-2.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c4165821e131d6d4ca444347c2b694e2311bcfa3fe5a861cc72968f28867beac", size = 184952, upload-time = "2026-07-06T21:33:27.823Z" }, + { url = "https://files.pythonhosted.org/packages/2e/d2/065fcae1c73979fac8e054462478d0ff8a29c40cdc2ed7ea5676a061df53/cffi-2.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:276f20fffd7b396e12516ba8edf9509210ac248cbbc5acbc39cd512f9f59ebe6", size = 222353, upload-time = "2026-07-06T21:33:29.178Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a5/e8bbb1ce5b3ac2f53ad6a10bde44318a5a8d99d4f4a000d44a6e39aeb3e4/cffi-2.1.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7d5980a3433d4b71a5e120f9dd551403d7824e31e2e67124fe2769c404c06913", size = 210051, upload-time = "2026-07-06T21:33:30.534Z" }, + { url = "https://files.pythonhosted.org/packages/28/ed/c127d3ac36e899c965e3361357c3befacd6578c03f40125183e41c3b219e/cffi-2.1.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6ca4919c6e4f89aa99c42510b42cf54596892c00b3f9077f6bdd1505e24b9c8d", size = 208630, upload-time = "2026-07-06T21:33:31.753Z" }, + { url = "https://files.pythonhosted.org/packages/cc/d7/97d3136f81db489ec8d1d67748c110d6c994268fd7528014aa9f2b085e4e/cffi-2.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d53d10f7da99ae46f7373b9150393e9c5eab9b224909982b43832668de4779f5", size = 221593, upload-time = "2026-07-06T21:33:33.044Z" }, + { url = "https://files.pythonhosted.org/packages/d3/27/93195977168ee63aed233a1a0993a2178798654d1f4bddcdd321d6fd3b21/cffi-2.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c351efb95e832a853a29361675f33a7ce53de1a109cd73fd47af0712213aa4ce", size = 225146, upload-time = "2026-07-06T21:33:34.224Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c1/6dbd291ee2ae5a50a034aa057207081f545923bbf15dad4511e985aafff5/cffi-2.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf7c7a88e2bac086f06d14577332760bdeecc42bdec8ac4077f6260557d9326", size = 223240, upload-time = "2026-07-06T21:33:35.57Z" }, + { url = "https://files.pythonhosted.org/packages/0f/6f/ade5ce9863a57992a6ea3d0d10d7e29b8749fc127204b3d493d667b2815f/cffi-2.1.0-cp314-cp314-win32.whl", hash = "sha256:1854b724d00f6654c742097d5387569021be12d3a0f770eae1df8f8acfcc6acd", size = 177723, upload-time = "2026-07-06T21:33:51.626Z" }, + { url = "https://files.pythonhosted.org/packages/41/de/92b9eeed4ae4a21d6fd9b2a2c8505cbed573299902ea73981cc13f7ff62c/cffi-2.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:1b96bfe2c4bd825681b7d311ad6d9b7280a091f43e8f63da5729638083cd3bfb", size = 187937, upload-time = "2026-07-06T21:33:53.403Z" }, + { url = "https://files.pythonhosted.org/packages/2e/1a/cc6ae6c2913a03aab8898eee57963cf1035b8df5872ed8b9115fcc7e2be8/cffi-2.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:7d28dff1db6764108bc30788d85d61c876beff416d9a49cb9dd7c5a9f34f5804", size = 183001, upload-time = "2026-07-06T21:33:54.74Z" }, + { url = "https://files.pythonhosted.org/packages/14/f0/134c00ce0779ec86dea2aa1aac69339c2741a8045072676763512363a2ea/cffi-2.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7ea6b3e2c4250ff1de21c630fe72d0f63eb95c2c32ffbf64a358cf4a8836d714", size = 188538, upload-time = "2026-07-06T21:33:36.792Z" }, + { url = "https://files.pythonhosted.org/packages/50/d8/3b86aba791cb610d24e8a3e1b2cd529e71fa15096b04e4d4e360049d4a4c/cffi-2.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6af371f3767faeffc6ac1ef57cdfd25844403e9d3f476c5537caee499de96376", size = 188230, upload-time = "2026-07-06T21:33:38.011Z" }, + { url = "https://files.pythonhosted.org/packages/14/d0/117dcd9209255ad8571fbc8c92ef32593a1d294dcec91ddc4e4db50606f2/cffi-2.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb4e8997a49aa2c08a3e43c9045d224448b8941d88e7ac163c7d383e560cbf98", size = 223899, upload-time = "2026-07-06T21:33:39.514Z" }, + { url = "https://files.pythonhosted.org/packages/b6/3d/f20f8b886b254e3ad10e15cd4186d3aed49f3e6a35ab37aab9f8f25f7c03/cffi-2.1.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:bf01d8c84cbea96b944c73b22182e6c7c432b3475632b8111dbfdc95ddad6e13", size = 211652, upload-time = "2026-07-06T21:33:40.851Z" }, + { url = "https://files.pythonhosted.org/packages/28/3b/fad54de07260b93ddeef4b96d0131d57ea900675df1d410ae1deee52d7a6/cffi-2.1.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:33eb1ad83ebe8f313e0df035c406227d55a79456704a863fad9842136af5ad7d", size = 210755, upload-time = "2026-07-06T21:33:42.183Z" }, + { url = "https://files.pythonhosted.org/packages/cc/82/3d5c705acb7abbba9bbd7d79b8e62e0f25b6120eb7ae6ac49f1b721722fe/cffi-2.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ac0f1a2d0cfa7eea3f2aaf006ab6e70e8feeb16b75d65b7e5939982ca2f11056", size = 223933, upload-time = "2026-07-06T21:33:43.603Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d0/47e338384ab6b1004241002fa616301020cea4fc95f283506565d252f276/cffi-2.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c16914df9fb7f500e440e6875fa23ff5e0b31db01fa9c06af98d59a91f0dc2e4", size = 226749, upload-time = "2026-07-06T21:33:45.046Z" }, + { url = "https://files.pythonhosted.org/packages/70/25/65bd5b58ea4bfdfc15cde02cb5365f89ef8ab8b2adfb8fe5c4bd4233382f/cffi-2.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5ecbd0499275d57506d397eebe1981cee87b47fcd9ef5c22cab7ed7644a39a94", size = 225703, upload-time = "2026-07-06T21:33:46.374Z" }, + { url = "https://files.pythonhosted.org/packages/dc/78/aa01ac599a8a4322533d45a1f9bc93b338276d2d59dabbe7c6d92a775c81/cffi-2.1.0-cp314-cp314t-win32.whl", hash = "sha256:7d034dcffa09e9a46c93fa3a3be402096cb5354ac6e41ab8e5cc9cd8b642ad76", size = 182857, upload-time = "2026-07-06T21:33:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/b9/26/d00496b22de4d4228f32dde94ad996f350c8aad676d63bcca0743c8dea4d/cffi-2.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0582a58f3051372229ca8e7f5f589f9e5632678208d8636fea3676711fdf7fe5", size = 194065, upload-time = "2026-07-06T21:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/d5/dd/0c7dbf815a579ff005008a2d815a55d6bb047c349eef536d9dc53d3f0a8d/cffi-2.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:510aeeeac94811b138077451da1fb18b308a5feab47dd2b603af55804155e1c8", size = 186404, upload-time = "2026-07-06T21:33:50.309Z" }, + { url = "https://files.pythonhosted.org/packages/55/c7/8c8c50cb11c6750051daf12164098a9a6f027ac4356967fd4d800a07f242/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphoneos.whl", hash = "sha256:2e9dabb9abcb7ad15938c7196ad5c1718a4e6d33cc79b4c0209bdb64c4a54a5c", size = 194121, upload-time = "2026-07-06T21:33:56.109Z" }, + { url = "https://files.pythonhosted.org/packages/99/e2/67680bf19a6b60d2bb7ff83baefa2a4c3d2d7dc0f3277034b802e1fc504c/cffi-2.1.0-cp315-cp315-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:37f525a7e7e50c017fdebe58b787be310ad59357ae43a053943a6e1a6c526001", size = 196820, upload-time = "2026-07-06T21:33:57.288Z" }, + { url = "https://files.pythonhosted.org/packages/ed/da/4bbe583a3b3a5c8c60892124fe17f3fa3656523faf0d3484eae90f091853/cffi-2.1.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:95f2954c2c9473d892eca6e0409f3568b37ab62a8eedb122461f73cc273476e3", size = 184936, upload-time = "2026-07-06T21:33:58.765Z" }, + { url = "https://files.pythonhosted.org/packages/e5/4b/1f4c36ab273980d7aa75bb126ea4f8971f24a96108acad3a0a084028c57b/cffi-2.1.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:cdf2448aab5f661c9315308ec8b93f4e8a1a67a3c733f8631067a2b67d5913dc", size = 185045, upload-time = "2026-07-06T21:34:00.085Z" }, + { url = "https://files.pythonhosted.org/packages/ef/c3/ad299dc38f3583f8d916b299f028af418a9ec98bc695fcbebeae7420691c/cffi-2.1.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:90bec57cf82089383bd06a605b3eb8daebf7e5a668520beaf6e327a83a947699", size = 222342, upload-time = "2026-07-06T21:34:01.814Z" }, + { url = "https://files.pythonhosted.org/packages/eb/d8/df4543cc087245044ed02ef3ad8e0a26619d0075ac7a77a12dc81177851b/cffi-2.1.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6274dcb2d15cef48daa73ed1be5a40d501d74dccd0cd6db364776d12cb6ba022", size = 210073, upload-time = "2026-07-06T21:34:03.255Z" }, + { url = "https://files.pythonhosted.org/packages/2c/0e/fac738d73728c6cea2a88a2883dca54892496cbba88a1dc1f2909cb8a6f5/cffi-2.1.0-cp315-cp315-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b71d409cccee78310ab5dec549aed052aaea483346e282c7b02362596e01bb0", size = 208551, upload-time = "2026-07-06T21:34:04.433Z" }, + { url = "https://files.pythonhosted.org/packages/e6/3f/0b04a700dd64f465c93020253a793a82c9b4dff9961f48facd0df945d9b8/cffi-2.1.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d3538f9c0e50670f4deb93dbb696576e60590369cae2faf7de681e597a8a1f1", size = 221649, upload-time = "2026-07-06T21:34:06.157Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/b7379a5704c79eda57ce075869ba70a0368d1c850f803b3c0d078d39dcaf/cffi-2.1.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:8f9ec95b8a043d3dfbc74d9abc6f7baf524dd27a8dc160b0a32ff9cdab650c28", size = 225203, upload-time = "2026-07-06T21:34:07.489Z" }, + { url = "https://files.pythonhosted.org/packages/5a/02/d5e6c43ea85c41bda2a184a3418f195fe7cf602967a8d2b94e085b83deef/cffi-2.1.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:af5e2915d41fe6c961694d7bfdc8562942638200f3ce2765dfb8b745cf997629", size = 223263, upload-time = "2026-07-06T21:34:08.712Z" }, + { url = "https://files.pythonhosted.org/packages/2c/d8/772b8259bf75749adffb1c546828978381fb516f60cf701f6c83daf60c85/cffi-2.1.0-cp315-cp315-win32.whl", hash = "sha256:0a42c688d19fca6e095a53c6a6e2295a5b050a8b289f109adab02a9e61a25de6", size = 177696, upload-time = "2026-07-06T21:34:26.355Z" }, + { url = "https://files.pythonhosted.org/packages/2f/dd/afa2191fc6d57fedd26e5844a2fe2fcc0bbfa00961bbaa5a41e4921e7cca/cffi-2.1.0-cp315-cp315-win_amd64.whl", hash = "sha256:bccbbb5ee76a61f9d99b5bf3846a51d7fca4b6a732fe46f89295610edaf41853", size = 187914, upload-time = "2026-07-06T21:34:27.58Z" }, + { url = "https://files.pythonhosted.org/packages/05/ef/6cd4f8c671517162379dc79cfae5aea9106bc38abb89628d5c16adf6a838/cffi-2.1.0-cp315-cp315-win_arm64.whl", hash = "sha256:8d35c139744adb3e727cd51b1a18324bbe44b8bd41bf8322bca4d41289f48eda", size = 183004, upload-time = "2026-07-06T21:34:28.905Z" }, + { url = "https://files.pythonhosted.org/packages/11/b6/12fc55092817a5faa26fb8c40c7f9d662e11a46ee248c137aafc42517d92/cffi-2.1.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:f9912624a0c0b834b7520d7769b3644453aabc0a7e1c839da7359f050750e9bc", size = 188378, upload-time = "2026-07-06T21:34:09.926Z" }, + { url = "https://files.pythonhosted.org/packages/8d/2e/cdac88979f295fde5daa69622c7d2111e56e7ceb94f211357fbe452339e4/cffi-2.1.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:df92f2aba50eb4d96718b68ef76f2e57a57b54f2fa62333496d16c6d585a85ca", size = 188319, upload-time = "2026-07-06T21:34:11.101Z" }, + { url = "https://files.pythonhosted.org/packages/e0/27/1d0b408497e41a74795af122d7b603c418c5fed0171450f899afd04e594f/cffi-2.1.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0520e1f4c35f44e209cbbb421b67eec42e6a157f59444dfb6058874ff3610e5d", size = 223904, upload-time = "2026-07-06T21:34:12.606Z" }, + { url = "https://files.pythonhosted.org/packages/8b/31/e115c985105dd7ffb32444505f18ceb874bb42d992af05d5dced7ecf1980/cffi-2.1.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:3681e031db29958a7502f5c0c9d6bbc4c36cb20f7b104086fa642d1799631ff8", size = 211554, upload-time = "2026-07-06T21:34:13.987Z" }, + { url = "https://files.pythonhosted.org/packages/5a/67/9e6e09409336d9e515c58367e7cfcf4f89df06ad25252675595a58eb59d5/cffi-2.1.0-cp315-cp315t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:762f99479dcb369f60ab9017ad4ab97a36a1dd7c1ee5a3b15db0f4b8659120cd", size = 210795, upload-time = "2026-07-06T21:34:15.972Z" }, + { url = "https://files.pythonhosted.org/packages/19/e5/d3cc82a4a0be7902af279c04181ad038449c096734464a5ae1de3e1401bd/cffi-2.1.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0611e7ebf90573a535ebdc33ae9da222d037853983e13359f580fab781ca017f", size = 223843, upload-time = "2026-07-06T21:34:17.509Z" }, + { url = "https://files.pythonhosted.org/packages/b9/65/b434abc97ce7cecc2c640fde160507c0ecc7e21544b483ba3325d2e2ea17/cffi-2.1.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:86cf8755a791f72c85dc287128cc62d4f24d392e3f1e15837245623f4a33cccc", size = 226773, upload-time = "2026-07-06T21:34:19.05Z" }, + { url = "https://files.pythonhosted.org/packages/b5/9f/d4dc66ca651eb1145a133314cda721abf13cfac3d28c4a0402263ae6ad75/cffi-2.1.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:ba00f661f8ba35d075c937174e27c2c421cec3942fd2e0ea3e66996757c0fdd9", size = 225719, upload-time = "2026-07-06T21:34:20.576Z" }, + { url = "https://files.pythonhosted.org/packages/68/5a/e536c528bc8057496c360c0978559a2dc45653f89dd6151078aa7d8fca1a/cffi-2.1.0-cp315-cp315t-win32.whl", hash = "sha256:cb96698e3c7413d906ce83f8ffd245ec1bd94707541f299d0ce4d6b0193e982b", size = 182760, upload-time = "2026-07-06T21:34:22.059Z" }, + { url = "https://files.pythonhosted.org/packages/d3/0b/0ffe8b82d3875bced5fa1e7986a7a46b748262a40ab7f60b475eb9fb1bb3/cffi-2.1.0-cp315-cp315t-win_amd64.whl", hash = "sha256:f146d154428a2523f9cc7936c02353c2459b8f6cf07d3cd1ee1c0a611109c5d5", size = 193769, upload-time = "2026-07-06T21:34:23.589Z" }, + { url = "https://files.pythonhosted.org/packages/a0/17/1073b53b68c9b5ca6914adf5f8bf55aacc2d3be102418c90700160ea8605/cffi-2.1.0-cp315-cp315t-win_arm64.whl", hash = "sha256:cbb7640ce37159548d2147b5b8c241f962143d4c71231431820783f4dc78f210", size = 186405, upload-time = "2026-07-06T21:34:24.857Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/2a/23f34ec9d04624958e137efdc394888716353190e75f25dd22c7a2c7a8aa/charset_normalizer-3.4.9.tar.gz", hash = "sha256:673611bbd43f0810bec0b0f028ddeaaa501190339cac411f347ac76917c3ae7b", size = 152439, upload-time = "2026-07-07T14:34:58.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/4a/ecbd131485c07fcdfad54e28946d513e3da22ef3b4bd854dcafae54ec739/charset_normalizer-3.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:45b0cc4e3556cd875e09102988d1ab8356c998b596c9fced84547c8138b487a0", size = 319300, upload-time = "2026-07-07T14:33:15.666Z" }, + { url = "https://files.pythonhosted.org/packages/ec/96/5d9364e3342d69f3a045e1777bc47c85c383e6e9466d561b33fdb419d1f9/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9b2aff1c7b3884512b9512c3eaadd9bab39fb45042ffaaa1dd08ff2b9f8109d9", size = 215802, upload-time = "2026-07-07T14:33:17.031Z" }, + { url = "https://files.pythonhosted.org/packages/4b/4c/5361f9aa7f2cb58d94f2ab831b3d493f69efb1d239654b4744e3c09527cb/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9104ed0bd76a429d46f9ec0dbc9b08ad1d2dcdf2b00a5a0daa1c145329b35b44", size = 237171, upload-time = "2026-07-07T14:33:18.576Z" }, + { url = "https://files.pythonhosted.org/packages/50/78/ce342ca4ff30b2eb49fe6d9578df85974f90c67d294113e94efdd9664cbd/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b86a2b16095d250c6f58b3d9b2eee6f4147754344f3dab0922f7c9bf7d226c9", size = 233075, upload-time = "2026-07-07T14:33:20.084Z" }, + { url = "https://files.pythonhosted.org/packages/01/c4/4fa4c8b3097a11f3c5f09a35b72ed6855fb1d332469504962ab7bafcc702/charset_normalizer-3.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e226f6218febc71f6c1fc2fafb91c226f75bdc1d8fb12d66823716e891608fd", size = 224256, upload-time = "2026-07-07T14:33:21.747Z" }, + { url = "https://files.pythonhosted.org/packages/87/3a/ad914516df7e358a81aae018caa5e0470ba827fa6d763b1d2e87d920a5f6/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:90c44bc373b7687f6948b693cceaea1348ae0975d7474746559494468e3c1d84", size = 208784, upload-time = "2026-07-07T14:33:23.313Z" }, + { url = "https://files.pythonhosted.org/packages/d7/74/3c12f9755717dfe5c5c87da63f35d765fa0c00382ec26bf23f7fae34f2ba/charset_normalizer-3.4.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9cdef90ae47919cae358d8ab15797a800ed41da7aba5d72419fb510729e2ed4b", size = 219928, upload-time = "2026-07-07T14:33:24.814Z" }, + { url = "https://files.pythonhosted.org/packages/33/9a/895095b83e7907abd6d3d99aad3a38ad0d9686cc186cb0c94c24320fe63e/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:60f44ade2cf573dad7a277e6f8ca9a51a21dda572b13bd7d8539bb3cd5dbedde", size = 218489, upload-time = "2026-07-07T14:33:26.42Z" }, + { url = "https://files.pythonhosted.org/packages/a1/34/ef5c05f412f42520d7709b7d3784d19640839eb7366ded1755511585429f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a1786910334ed46ab1dd73222f2cd1e05c2c3bb39f6dddb4f8b36fc382058a39", size = 210267, upload-time = "2026-07-07T14:33:27.952Z" }, + { url = "https://files.pythonhosted.org/packages/83/dc/9b29fa4412b318bf3bfea985c35d67eb55e04b59a7c3f2237168b0e0be6f/charset_normalizer-3.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03d07803992c6c7bbc976327f34b18b6160327fc81cb82c9d504720ac0be3b62", size = 226030, upload-time = "2026-07-07T14:33:29.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/42/6dbc00b8cd16011691203e33570fa42ed5746599a2e878112d16eab403a3/charset_normalizer-3.4.9-cp312-cp312-win32.whl", hash = "sha256:78841cccf1af7b40f6f716338d50c0902dbe88d9f800b3c973b7a9a0a693a642", size = 151185, upload-time = "2026-07-07T14:33:30.781Z" }, + { url = "https://files.pythonhosted.org/packages/80/cc/f920afd1a23c58ccd53c1d36085a71893a4737ff5e66e0371efab6809850/charset_normalizer-3.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:4b3dac63058cc36820b0dd072f89898604e2d39686fe05321729d00d8ac185a0", size = 162557, upload-time = "2026-07-07T14:33:32.176Z" }, + { url = "https://files.pythonhosted.org/packages/f0/e6/0386d43a261ff4e4b30c5857af7df877254b46bec7b9d1b74b6bf969a90b/charset_normalizer-3.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:78fa18e436a1a0e58dbd7e02fc4473f3f32cceb12df9dfca542d075961c307d2", size = 152665, upload-time = "2026-07-07T14:33:33.711Z" }, + { url = "https://files.pythonhosted.org/packages/b2/06/97ec2aeae780b31d742b6352218b43841a6871e2564578ca522dce4a45c3/charset_normalizer-3.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:440eede837960000d74978f0eba527be106b5b9aee0daf779d395276ed0b0614", size = 317688, upload-time = "2026-07-07T14:33:35.408Z" }, + { url = "https://files.pythonhosted.org/packages/d0/39/8ff066c672434225f8d25f8b739f992af250944392173dcc88362681c9bf/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21e764fd1e70b6a3e205a0e46f3051701f98a8cb3fad66eeb80e48bb502f8698", size = 214982, upload-time = "2026-07-07T14:33:36.996Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/3a47a3667c83c2df9483d91644c6c107de3bf8874aa1793da9d3012eb986/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e4fd89cc178bced6ad29cb3e6dd4aa63fa5017c3524dbd0b25998fb64a87cc8b", size = 236460, upload-time = "2026-07-07T14:33:38.536Z" }, + { url = "https://files.pythonhosted.org/packages/f1/60/b22cdbee7e4013dab8b0d7647fc6181120fbbbc8f7025c226d15bd5a47fc/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bd47ba7fc3ca94896759ea0109775132d3e7ab921fbf54038e1bab2e46c313c9", size = 232003, upload-time = "2026-07-07T14:33:40.059Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f8/72eb13dcabe7257035cea8aefd922caad2f110d252bf9f67c4c2ca763aee/charset_normalizer-3.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:84fd18bcc17526fc2b3c1af7d2b9217d32c9c04448c16ec693b9b4f1985c3d33", size = 223149, upload-time = "2026-07-07T14:33:41.631Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3e/faee8f9de92b14ee1198e9163252bb15efee7301b31256a3b6d9ebfdd0dd/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:5b10cd92fc5c498b35a8635df6d5a100207f88b63a4dc1de7ef9a548e1e2cd63", size = 207901, upload-time = "2026-07-07T14:33:43.209Z" }, + { url = "https://files.pythonhosted.org/packages/3a/25/45f30093ae27dd7b92a793b61882a38685f993700113ca36e0c9c14965e1/charset_normalizer-3.4.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a4fbdde9dd4a9ce5fd52c2b3a347bb50cc89483ef783f1cb00d408c13f7a96c0", size = 219176, upload-time = "2026-07-07T14:33:44.725Z" }, + { url = "https://files.pythonhosted.org/packages/48/18/c8f397329c35e32f6a837e488986f4ae03bd2abebc453b48714991630c2f/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:416c229f77e5ea25b3dfd4b582f8d73d7e43c22320302b9ab128a2d3a0b38efe", size = 217356, upload-time = "2026-07-07T14:33:46.192Z" }, + { url = "https://files.pythonhosted.org/packages/86/7e/5ce0bba863470fd1902d5e5843968951bddf38abe4742fc97116ef4598b3/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:75286256590a6320cf106a0d28970d3560aad9ee09aa7b34fb40524792436d35", size = 209614, upload-time = "2026-07-07T14:33:47.705Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ef/2473d3c4d869155be4af1191111d59c4d5c4e0173026f7e85b176e23bf65/charset_normalizer-3.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69b157c5d3292bcd443faca052f3096f637f1e074b98212a933c074ae23dc3b8", size = 224991, upload-time = "2026-07-07T14:33:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a3/53ddae3db108a088156aa8ddfafd411ebbc1340f48c5573f697b27f69a39/charset_normalizer-3.4.9-cp313-cp313-win32.whl", hash = "sha256:51307f5c71007673a2bf8232ad973483d281e74cb99c8c5a990af1eefa6277d9", size = 150622, upload-time = "2026-07-07T14:33:50.711Z" }, + { url = "https://files.pythonhosted.org/packages/e8/ef/6953a77c7cf2c2ff9998e6f575ab3e380119f100223381565a4f94c1f836/charset_normalizer-3.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:fe2c7201c642b7c308f1675355ad7ff7b66acfe3541625efe5a3ad38f29d6115", size = 161947, upload-time = "2026-07-07T14:33:52.197Z" }, + { url = "https://files.pythonhosted.org/packages/6e/fb/d560d1d1555debbfe7849d9cac6145c1b537709d79576bf22557ed803b82/charset_normalizer-3.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:611057cc5d5c0afc743ba8be6bd828c17e0aaa8643f9d0a9b9bb7dea80eb8012", size = 152594, upload-time = "2026-07-07T14:33:53.486Z" }, + { url = "https://files.pythonhosted.org/packages/7e/8d/496817fa0944239ecae662dd57ea765cfeaec6a735f9f025d4b7b72e7143/charset_normalizer-3.4.9-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", size = 317253, upload-time = "2026-07-07T14:33:54.994Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/ef4a69ea338ad3c0deceea0f5f7d2380ae8b52132b06d652cb0d2cd86706/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a79d9f4d8001473a30c163556b3c3bfebec837495a412dde78b51672f6134f9", size = 215898, upload-time = "2026-07-07T14:33:56.334Z" }, + { url = "https://files.pythonhosted.org/packages/8c/e7/5ddfd76fc061eb52de219658a4aa431cbacadf0a0219c8854f00da50d289/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:33bdcc2a32c0a0e861f60841a512c8acc658c87c2ac59d89e3a46dacf7d866e4", size = 236718, upload-time = "2026-07-07T14:33:57.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/ba/768fa3f36048d81c477a0ce61f813bc1454d80917ccfe550abd9f44f5e24/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f840ed6d8ecba8255df8c42b87fadeda98ddfc6eeec05e2dc66e26d46dd6f58a", size = 232519, upload-time = "2026-07-07T14:33:59.811Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c4/b3e049d2aa3766180c78507110543d9d50894cc97f57de543f1be521dcdc/charset_normalizer-3.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c25fe15c70c59eb7c5ce8c06a1f3fa1da0ecc5ea1e7a5922c40fd2fa9b0d5046", size = 223143, upload-time = "2026-07-07T14:34:01.517Z" }, + { url = "https://files.pythonhosted.org/packages/19/79/55c32d06d76ae4feafe053f061f3e3ab70bcf19f4007797ce8c3efda7830/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:f7fb7d750cfa0a070d2c24e831fd3481019a60dd317ea2b39acbcebc08b6ed81", size = 206742, upload-time = "2026-07-07T14:34:03.04Z" }, + { url = "https://files.pythonhosted.org/packages/10/e0/47c079dd82d217c807479cd59ffd30af56307ea31c108b75758970459ad3/charset_normalizer-3.4.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4d1c96a7a18b9690a4d46df09e3e3382406ae3213727cd1019ebade1c4a81917", size = 219191, upload-time = "2026-07-07T14:34:04.657Z" }, + { url = "https://files.pythonhosted.org/packages/42/ab/b9bc2e77d6b44a7e46ef62ec5cac1c9a6ba7b9135a5d560f002696ec9995/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a4cfde78a9f2880208d16a93b795726a3017d5977e08d1e162a7a31322479c41", size = 218328, upload-time = "2026-07-07T14:34:06.115Z" }, + { url = "https://files.pythonhosted.org/packages/f1/78/c9c71d599f5aa2d42bcdd35cbbd46d7f535351a57e40ff7d8e5a7e219401/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4d6fcde76f94f5cb9e43e9e9a61f16dacefd228cbbf6f1a09bd9b219a92f1a1", size = 207406, upload-time = "2026-07-07T14:34:07.554Z" }, + { url = "https://files.pythonhosted.org/packages/f6/39/c914445c321a845097ce4f6ac7de9a18228a77b766272125a1ce00d851eb/charset_normalizer-3.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:898f0e9068ca27d37f8e83a5b962821df851532e6c4a7d615c1c033f9da6eedf", size = 225157, upload-time = "2026-07-07T14:34:09.061Z" }, + { url = "https://files.pythonhosted.org/packages/9b/f2/c0d4b8508565a36bc5c624e88ed297f5b0b1095011034d7f5b83a69908b5/charset_normalizer-3.4.9-cp314-cp314-win32.whl", hash = "sha256:c1c948747b03be832dceed96ca815cef7360de9aa19d37c730f8e3f6101aca48", size = 151095, upload-time = "2026-07-07T14:34:10.901Z" }, + { url = "https://files.pythonhosted.org/packages/49/fd/a1d26144398c67486422a72bf5812cda22cb4ccfcd95a290fb41ceb4b8e2/charset_normalizer-3.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:16b65ea0f2465b6fb52aa22de5eca612aa964ddfec00a912e26f4656cbef890b", size = 162796, upload-time = "2026-07-07T14:34:12.47Z" }, + { url = "https://files.pythonhosted.org/packages/20/95/d75e82f8ce9fd323ebf059c16c9aadefb22a1ecde13b7840b35835e4886c/charset_normalizer-3.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:40a126142a56b2dfc0aacbad1de8310cbf60da7656db0e6b16eebd48e3e93519", size = 153334, upload-time = "2026-07-07T14:34:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/00/5e/17398df3a139985ba9d11ed072531986f408c8fca952835ef1ab1820c02b/charset_normalizer-3.4.9-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:609b3ba8fcc0fb5ab7af00719d0fb6ad0cb518e48e7712d12fd68f1327951198", size = 338848, upload-time = "2026-07-07T14:34:15.688Z" }, + { url = "https://files.pythonhosted.org/packages/cd/91/7253a32e86b7e1d1239b1b36ba6dd0f021a21107ab33054b53119cc083b9/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:51447e9aa2684679af07ca5021c3db526e0284347ebf4ffcec1154c3350cfe32", size = 223022, upload-time = "2026-07-07T14:34:17.248Z" }, + { url = "https://files.pythonhosted.org/packages/cb/32/2e64bd2be10e89c61e57ebe6a93fd98ae88eb7ebe414b5121f22c96c69eb/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cc1b0fff8ead343dae06305f954eb8468ba0ec1a97881f42489d198e4ce3c632", size = 241590, upload-time = "2026-07-07T14:34:18.813Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ef/d96ec496cfea0c21db43b0ad03891308b02388d054cc902cf0e5a1ad6a88/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fa36ec09ef71d158186bc79e359ff5fdd6e7996fe8ab638f00d6b93139ba4fcf", size = 239584, upload-time = "2026-07-07T14:34:20.52Z" }, + { url = "https://files.pythonhosted.org/packages/d4/ce/9af95f7876194bd7a14e3dfe4a4de2e0bff02666a3910d72beafd06cc297/charset_normalizer-3.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:df115d4d83168fdf2cae48ef1ff6d1cb4c466364e30861b37121de0f3bf1b990", size = 230224, upload-time = "2026-07-07T14:34:22.189Z" }, + { url = "https://files.pythonhosted.org/packages/52/94/af74dde74a3996bd959c350709bfe50e297823d70a8c1cbd54b838880863/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f86c6358749bd4fda175388691e3ba8c46e24c5347d0afd20f9b7edfc9faf07d", size = 212667, upload-time = "2026-07-07T14:34:23.857Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f0/f1c4fe746c395922961b5916ed1d7d6e7d4c84851d19ed43cc89980ec953/charset_normalizer-3.4.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:32286a2c8d167e897177b673176c1e3e00d4057caf5d2b64eef9a3666b03018e", size = 227179, upload-time = "2026-07-07T14:34:25.586Z" }, + { url = "https://files.pythonhosted.org/packages/e4/56/6c745619ac397e8871e2bcd3cea1eec86b877488f33888b3aef5c3ed506e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:83aed2c10721ddd90f68140685391b50811a880af20654c59af6b6c66c40513c", size = 225372, upload-time = "2026-07-07T14:34:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/78/ad/98aae8630ac71f16711968e38a5acfecce41b778bf2f0312851020f565a8/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cd6c3d4b783c556fa00bf540854e42f135e2f256abd29669fcd0da0f2dec79c2", size = 215222, upload-time = "2026-07-07T14:34:28.774Z" }, + { url = "https://files.pythonhosted.org/packages/f7/40/9593d54209765207a7f11073c06494c1721e4ca4a0a426c597679bf7f91e/charset_normalizer-3.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ee2f2a527e3c1a6e6411eb4209642e138b544a2d72fe5d0d76daf77b24063534", size = 231958, upload-time = "2026-07-07T14:34:30.345Z" }, + { url = "https://files.pythonhosted.org/packages/b1/27/693ee5e8a18191eb38647360c51cd505013e2bd3b366aa43fd5344c21e3c/charset_normalizer-3.4.9-cp314-cp314t-win32.whl", hash = "sha256:0d861473f743244d349b50f850d10eb87aeb22bbdcc8e64f79273c94af5a8226", size = 155580, upload-time = "2026-07-07T14:34:31.884Z" }, + { url = "https://files.pythonhosted.org/packages/80/3f/bd97d3d9c613013d07cb7733d299385b41df37f0471310f5a73dc359f0b8/charset_normalizer-3.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:9b8e0f3107e2200b76f6054de99016eac3ee6762713587b36baaa7e4bd2ae177", size = 167620, upload-time = "2026-07-07T14:34:33.438Z" }, + { url = "https://files.pythonhosted.org/packages/3d/c6/eee9dca4439b1061f76373f06ea855678cc4a64c1c3c90b50e479edbb8eb/charset_normalizer-3.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:19ac87f93086ce37b86e098888555c4b4bc48102279bae3350098c0ed664b501", size = 158037, upload-time = "2026-07-07T14:34:35.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/2b/f97f1c193fb855c345d678f5077d6926034db0722df74c8f057020e05a25/charset_normalizer-3.4.9-py3-none-any.whl", hash = "sha256:68e5f26a1ad57ded6d1cfb85331d1c1a195314756471d97758c48498bb4dcdf5", size = 64538, upload-time = "2026-07-07T14:34:56.993Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + +[[package]] +name = "debugpy" +version = "1.8.21" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/aa/12037145b7a56eaa5b29b41872f7a21b538e807e13f32c4d3c46e59be084/debugpy-1.8.21.tar.gz", hash = "sha256:a3c53278e84c94e11bd87c53970ec391d1a67396c8b22609fcac576520e611a6", size = 1697577, upload-time = "2026-06-01T19:30:35.156Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a2/df/bf625547431a9cadc9f4cbfeda38866e2b17f6aed147b625377e87834449/debugpy-1.8.21-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:9f96713896f39c3dff0ee841f47320c3f2983d33c341e009361bb0ebc79adc4e", size = 2483609, upload-time = "2026-06-01T19:30:50.794Z" }, + { url = "https://files.pythonhosted.org/packages/bf/09/59324b903599031ff9faaec1758292409f6561a0ec2492fe4b703327705a/debugpy-1.8.21-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:c193d474f0a211191f2b4449d2d06157c689013035bd952f3b617e0ef422b176", size = 3968900, upload-time = "2026-06-01T19:30:52.341Z" }, + { url = "https://files.pythonhosted.org/packages/14/cd/27f65b805d7fe005c44e1a36b9183ecdfbcdbf9d3e721a5115d461ecc7ee/debugpy-1.8.21-cp312-cp312-win32.whl", hash = "sha256:4743373c1cac7f9e74a1b9915bf1dbe0e900eca657ffb170ae07ac8363205ae9", size = 5336340, upload-time = "2026-06-01T19:30:54.047Z" }, + { url = "https://files.pythonhosted.org/packages/77/1d/c84e30c0c674184948b66f076ab271c01d940618a2824c23cd035a27bc20/debugpy-1.8.21-cp312-cp312-win_amd64.whl", hash = "sha256:bd7ba9dd3daa7c2f942c6ca8d4695a16bf9ac16b63615261c7982bc74f7ed20c", size = 5374751, upload-time = "2026-06-01T19:30:55.891Z" }, + { url = "https://files.pythonhosted.org/packages/77/6b/d817e1f8cc77aa055d37fba092e0febfdff40fe652d8d53d4cd7a86ad98d/debugpy-1.8.21-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:13678151fc401e2d68c9880b91e28714f797d40422994572b24560ef80910a88", size = 2477398, upload-time = "2026-06-01T19:30:57.644Z" }, + { url = "https://files.pythonhosted.org/packages/48/57/412421516afc3055fa577516f00beec3d663f9b0ab330639547ae6c57720/debugpy-1.8.21-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:ecbd158386c31ffe71d46f72d44d56e66331ab9b16cad649156d514368f23ab2", size = 3962096, upload-time = "2026-06-01T19:30:59.235Z" }, + { url = "https://files.pythonhosted.org/packages/c1/62/2c616337cf6ba7b07ebbc97f02c6c945a8e2f76b365e33ee809c32ee36d1/debugpy-1.8.21-cp313-cp313-win32.whl", hash = "sha256:2c2ae706dec41d99a9ca1f7ebc987a83e65578363be6f6b3ac9067504917fae1", size = 5336288, upload-time = "2026-06-01T19:31:00.79Z" }, + { url = "https://files.pythonhosted.org/packages/f8/99/9175103392f84c4b1bf7622888cdc68da07f0ff7d9e581266428f6776033/debugpy-1.8.21-cp313-cp313-win_amd64.whl", hash = "sha256:aa648733047443eb1d07682c4ef287d36a54507b643ffdf38b09a3ef002c72a0", size = 5376567, upload-time = "2026-06-01T19:31:02.56Z" }, + { url = "https://files.pythonhosted.org/packages/ce/3d/f4bbb323a548bfab2af3d6b4ffd9bf22636e55956a1285d317a1de643aad/debugpy-1.8.21-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9bb2a685287a2ac9b181cde89edcec64845cb51de7faaa75badb9a698bc24782", size = 2477209, upload-time = "2026-06-01T19:31:04.157Z" }, + { url = "https://files.pythonhosted.org/packages/8c/2d/6e7ec524984a1702777868de49a4c53202bddac2a432a76a093469587750/debugpy-1.8.21-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:3d6922439bf33fd38a3e2c447869ebc7b97da5cd3d329ff1ef9bc06c4903437e", size = 3927115, upload-time = "2026-06-01T19:31:05.863Z" }, + { url = "https://files.pythonhosted.org/packages/97/47/d1aa6d64005a98a9144647d99306b419396f9ad7bf1d73c119e17a81fb4d/debugpy-1.8.21-cp314-cp314-win32.whl", hash = "sha256:15d4963bd5ffa48f0da0947fd06757fa7621945048a14ad7705431566d3c0e7c", size = 5336724, upload-time = "2026-06-01T19:31:07.711Z" }, + { url = "https://files.pythonhosted.org/packages/5f/67/b905b90d163af11878c1af8abafa4a25206335e112e284e413454543a6da/debugpy-1.8.21-cp314-cp314-win_amd64.whl", hash = "sha256:fe0744a12353406de0ae8ccff0d0a4a666f00801a3db8fd04e7a5f761cd520e8", size = 5373803, upload-time = "2026-06-01T19:31:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/95/51/67e7cf11a53e40694f720457d5b3a1cdaaa3d5a9a633e482f225456b93ff/debugpy-1.8.21-py2.py3-none-any.whl", hash = "sha256:b1e37d333663c8851516a47364ef473da127f9caebe4417e6df6f5825a7e9a92", size = 5352888, upload-time = "2026-06-01T19:31:25.186Z" }, +] + +[[package]] +name = "decorator" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "dill" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + +[[package]] +name = "foam-stepper" +version = "0.2.0" +source = { editable = "python" } +dependencies = [ + { name = "numpy" }, +] + +[package.metadata] +requires-dist = [{ name = "numpy", specifier = ">=2.0" }] + +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "idna" +version = "3.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/63/9496c57188a2ee585e0f1db071d75089a11e98aa86eb99d9d7618fc1edce/idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848", size = 196711, upload-time = "2026-06-02T14:34:07.794Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/5e/d4e9f1a599fb8e573b7b87160658329fbf28d19eac2718f51fc3def3aa5a/idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", size = 65455, upload-time = "2026-06-02T14:34:06.319Z" }, +] + +[[package]] +name = "ipykernel" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio2" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/c4/e4a38f579de4225a561305666f7541cdabb30075def2aa1ac17bd73c1fb5/ipykernel-7.3.0.tar.gz", hash = "sha256:9acaaaf97d16355166e4085afe9d225bfbdf2b7ef520f9df3be8f2b248275e09", size = 184899, upload-time = "2026-06-10T08:41:25.481Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/02/77b271f5dc58bfbc0b577c877b2365d1ffea2afe66a80c13f2312820348c/ipykernel-7.3.0-py3-none-any.whl", hash = "sha256:897eb64da762549ef610698fca5e9675195ec6ac8ec7f19d81ce1ca20c876057", size = 120583, upload-time = "2026-06-10T08:41:23.648Z" }, +] + +[[package]] +name = "ipython" +version = "9.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "psutil", marker = "sys_platform != 'cygwin' and sys_platform != 'emscripten'" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/53/59/165d3b4d75cc34add3122c4417ecb229085140ac573103c223cd01dde96f/ipython-9.15.0.tar.gz", hash = "sha256:da2819ce2aa83135257df830660b1176d986c3d2876db24df01974fa955b2756", size = 4442580, upload-time = "2026-06-26T11:03:35.913Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/3a/948263ca3b9d65bb2b1b0c521b3a49fad5d59ada58724bd87d2bd5ff3f36/ipython-9.15.0-py3-none-any.whl", hash = "sha256:515ad9c3cdf0c932a5a9f6245419e8aba706b7bd03c3e1d3a1c83d9351d6aa6e", size = 630895, upload-time = "2026-06-26T11:03:33.809Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "json5" +version = "0.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/7d/05c46a96a78147ae3bf99c2f4169ce144a70220b8d6fcd56f6ec368b8ce9/json5-0.15.0.tar.gz", hash = "sha256:7424d1f1eb1d56da6e3d70643f53619862b4ce81440bdb8ecfd6f875e5ba4a71", size = 53278, upload-time = "2026-06-19T20:08:27.716Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/be/59527c99478aade6bb33a68d72e6e18dd4e6ff6eacfc7d01bdb15bc76912/json5-0.15.0-py3-none-any.whl", hash = "sha256:56636a30c0e8a4665fe2179c0212f32eae3796dea89ea6f649b9436ecdb39618", size = 36570, upload-time = "2026-06-19T20:08:26.748Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/c7/af399a2e7a67fd18d63c40c5e62d3af4e67b836a2107468b6a5ea24c4304/jsonpointer-3.1.1.tar.gz", hash = "sha256:0b801c7db33a904024f6004d526dcc53bbb8a4a0f4e32bfd10beadf60adf1900", size = 9068, upload-time = "2026-03-23T22:32:32.458Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/6a/a83720e953b1682d2d109d3c2dbb0bc9bf28cc1cbc205be4ef4be5da709d/jsonpointer-3.1.1-py3-none-any.whl", hash = "sha256:8ff8b95779d071ba472cf5bc913028df06031797532f08a7d5b602d8b2a488ca", size = 7659, upload-time = "2026-03-23T22:32:31.568Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter-builder" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/61/47f7ae054f5cd3983c10e1d65a6eb7fcd4b87ebb1056e190ef7d63ff4f19/jupyter_builder-1.1.1.tar.gz", hash = "sha256:1a13977912b08deda77fce2c803940131c27cf77a27ed64b9ffca25aa0ed7e6c", size = 971667, upload-time = "2026-07-17T13:14:47.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/cc/f6a12de1c890ea5dd2816c5c76d5ac6d3ed52db3c37f78691328207d13b9/jupyter_builder-1.1.1-py3-none-any.whl", hash = "sha256:f9c14bc55c0488a073f62af12d468936fcf9ecb7e9dd802f6f9c33de46ad70db", size = 913264, upload-time = "2026-07-17T13:14:45.857Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/dc/5512503b088997c2250b8bf18258fba9d9ce5ead641183700960d3c9d342/jupyter_client-8.9.1.tar.gz", hash = "sha256:a58f730dd9e728ba16ba1d62ebccf7ffe1ebbdbce4e95cfae941b7321ae1f4fa", size = 359256, upload-time = "2026-06-09T13:15:01.033Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/6f/56d39bf385c5c27988aebaf0c18a2a17e960575740100973511018bd904e/jupyter_client-8.9.1-py3-none-any.whl", hash = "sha256:0b7a295bc46e8751e9adae84781f726c851c1d911bd793edc4a3bde942e3da81", size = 109828, upload-time = "2026-06-09T13:14:58.835Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/f8/475c4241b2b75af0deaae453ed003c6c851766dbc44d332d8baf245dc931/jupyter_events-0.12.1.tar.gz", hash = "sha256:faff25f77218335752f35f23c5fe6e4a392a7bd99a5939ccb9b8fbf594636cf3", size = 62854, upload-time = "2026-04-20T23:17:50.66Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/6c/6fcde0c8f616ed360ffd3587f7db9e225a7e62b583a04494d2f069cf64ea/jupyter_events-0.12.1-py3-none-any.whl", hash = "sha256:c366585253f537a627da52fa7ca7410c5b5301fe893f511e7b077c2d93ec8bcf", size = 19512, upload-time = "2026-04-20T23:17:48.927Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/ff/1e4a61f5170a9a1d978f3ac3872449de6c01fc71eaf89657824c878b1549/jupyter_lsp-2.3.1.tar.gz", hash = "sha256:fdf8a4aa7d85813976d6e29e95e6a2c8f752701f926f2715305249a3829805a6", size = 55677, upload-time = "2026-04-02T08:10:06.749Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/23/e8/9d61dcbd1dce8ef418f06befd4ac084b4720429c26b0b1222bc218685eff/jupyter_lsp-2.3.1-py3-none-any.whl", hash = "sha256:71b954d834e85ff3096400554f2eefaf7fe37053036f9a782b0f7c5e42dadb81", size = 77513, upload-time = "2026-04-02T08:10:01.753Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6b/dc/db3a582633170186f8c8b31298d7eb26ad0eb031a1f53476c258b64eed05/jupyter_server-2.20.0.tar.gz", hash = "sha256:b5778ba337d8015a3dc2b80803ecdd5ac18d3797fddf61a50ea5fb472b4ebe14", size = 756523, upload-time = "2026-06-17T12:09:09.435Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/71/8c002223e873a870f5c41dc69b0a7c922301123e4a31d5d01ecb700aef77/jupyter_server-2.20.0-py3-none-any.whl", hash = "sha256:c3b67c93c471e947c18b5026f04f21614218adb706df8f48227d3ee8e0a7cdcc", size = 393143, upload-time = "2026-06-17T12:09:07.234Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.6.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-builder" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/7f/51c0c856ab286bdaf5709cf61ed13584ed9d4bee906479707da45b11b353/jupyterlab-4.6.2.tar.gz", hash = "sha256:e18ce8b34f3de350e93cd5b2c4f3ae884cbe266eb76bf5d6825a4ed34c13bcff", size = 28183650, upload-time = "2026-07-21T12:05:24.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/1f/e39b248c76bb3736bc05a9491a6aa1315414c32dea12f548ecc1b24c758e/jupyterlab-4.6.2-py3-none-any.whl", hash = "sha256:5964447036629adfcd3fc0969effc1da6f47d2cbd0a60b2c2eea7c31be0ec6a8", size = 17166703, upload-time = "2026-07-21T12:05:19.818Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, +] + +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "matplotlib-inline" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mistune" +version = "3.3.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/92/328a294a6de83bacb95bed01f04e0eaff4e3616ee359fc821a5dfc539b02/mistune-3.3.4.tar.gz", hash = "sha256:58b5c96d6fcb61190dfe5fae498d2b2065f99cf61e9649418fd54cf1ada86dfe", size = 121426, upload-time = "2026-07-22T05:22:30.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/e4/288365afae98953bc01de09f686f40d8ee84578135aa7767d5d4e60b5278/mistune-3.3.4-py3-none-any.whl", hash = "sha256:ee015381e955e370962968befe1d729ab60fafb6a715ac6751763fbce38c8d4a", size = 66862, upload-time = "2026-07-22T05:22:29.419Z" }, +] + +[[package]] +name = "nbclient" +version = "0.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/a5/b3bae4b590c0cbcada2c63a34f7580024e834a8ba213e949a2f906705787/nbclient-0.11.0.tar.gz", hash = "sha256:04a134a5b087f2c5887f228aca155db50169b8cd9334dee6942c8e927e56081a", size = 62535, upload-time = "2026-06-05T07:52:41.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/c9/94d73e5a01c5b926c3fa2496e97d7a8dc28ed5a77c0b2ed712f1a62e6694/nbclient-0.11.0-py3-none-any.whl", hash = "sha256:ef7fa0d59d6e1d41103933d8a445a18d5de860ca6b613b87b8574accdb3c2895", size = 25288, upload-time = "2026-06-05T07:52:40.115Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/01/b1/708e53fe2e429c103c6e6e159106bcf0357ac41aa4c28772bd8402339051/nbconvert-7.17.1.tar.gz", hash = "sha256:34d0d0a7e73ce3cbab6c5aae8f4f468797280b01fd8bd2ca746da8569eddd7d2", size = 865311, upload-time = "2026-04-08T00:44:14.914Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/f8/bb0a9d5f46819c821dc1f004aa2cc29b1d91453297dbf5ff20470f00f193/nbconvert-7.17.1-py3-none-any.whl", hash = "sha256:aa85c087b435e7bf1ffd03319f658e285f2b89eccab33bc1ba7025495ab3e7c8", size = 261927, upload-time = "2026-04-08T00:44:12.845Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio2" +version = "1.7.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/73/731debf26e27e0a0323d7bda270dc2f634b398e38f040a09da1f4351d0aa/nest_asyncio2-1.7.2.tar.gz", hash = "sha256:1921d70b92cc4612c374928d081552efb59b83d91b2b789d935c665fa01729a8", size = 14743, upload-time = "2026-02-13T00:34:04.386Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/3c/3179b85b0e1c3659f0369940200cd6d0fa900e6cefcc7ea0bc6dd0e29ffb/nest_asyncio2-1.7.2-py3-none-any.whl", hash = "sha256:f5dfa702f3f81f6a03857e9a19e2ba578c0946a4ad417b4c50a24d7ba641fe01", size = 7843, upload-time = "2026-02-13T00:34:02.691Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + +[[package]] +name = "numpy" +version = "2.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/22/fd/89965aa4ac08c74998539fcbf24fa3540f3e15237fbeb6bcf9c908f4aade/numpy-2.5.1.tar.gz", hash = "sha256:a48a113e6afea91f5608793bafa7ef2ad481fefbda87ec5069f483de61cb9fa3", size = 20755553, upload-time = "2026-07-04T17:08:00.933Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/7b/14687aa674250e5e546f616f486b0d56d3631cd5b2415739141ce40bdcea/numpy-2.5.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2c889b56fe48b1018f764b0eec8df59ab654e9148aa91faa12596043500de277", size = 16801574, upload-time = "2026-07-04T17:06:12.423Z" }, + { url = "https://files.pythonhosted.org/packages/e1/19/cc5bb2a3f2913d27d6dbb2c78d25921fabaedc6741d4a5a615a11f3c5bf3/numpy-2.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ab451b59c5643c570974c43aef780703ef1d3b4965d2be07afd530615a9358d1", size = 11772250, upload-time = "2026-07-04T17:06:15.726Z" }, + { url = "https://files.pythonhosted.org/packages/42/77/fdf34a71dd30f54979b18603bee915e0aaf825b07afe79acd60b04b691e2/numpy-2.5.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:78798bd5b9ad744056af8efa90e3b9ddaa53272a0848a483084a1cc0a13b2dc0", size = 5331516, upload-time = "2026-07-04T17:06:17.913Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e2/eb7efa015b4cce41e2517bf182a7fce0d7d5b9d9ed76a29bfa0f4fe4505c/numpy-2.5.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:2ae0ca40bcb22d6ba59c1dfd5446f49940b0f2d821fde133f10dda11f816b84e", size = 6664863, upload-time = "2026-07-04T17:06:20.02Z" }, + { url = "https://files.pythonhosted.org/packages/a9/4b/a2b32dd94ee9ffbeecb28152240042a3949db33b1c834d44090b80e1b3b8/numpy-2.5.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:61ac47e772e6b8ea489e1d2f441a34c5c3ac17327e7ce294cbdf535795ad4e75", size = 15167977, upload-time = "2026-07-04T17:06:21.621Z" }, + { url = "https://files.pythonhosted.org/packages/b8/a9/6e73d68500f80773f65f0654ea932019d6694329a0eb0ed0533de38df376/numpy-2.5.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:59fda5e192b570217ec2580c96f00e9a7e12ef6866a900eb089b62c1a32545ca", size = 16672469, upload-time = "2026-07-04T17:06:24.064Z" }, + { url = "https://files.pythonhosted.org/packages/24/7d/ad3e59015135f5261c95fd4cafeff159c955febd83a99a1d9250c4233815/numpy-2.5.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f7119ebff1a9829e9f431a4f9d28e703023bb6b9fe7c8f724467dbfc27c94ab3", size = 16527531, upload-time = "2026-07-04T17:06:26.69Z" }, + { url = "https://files.pythonhosted.org/packages/83/d0/a39b2fbcde9cb17a1dac678f254b33a6336298af9df338824c685425d5e8/numpy-2.5.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e824c2acf8862052246be5a44c15da1777940c60d010dd2aab897824d9c430f9", size = 18431940, upload-time = "2026-07-04T17:06:29.521Z" }, + { url = "https://files.pythonhosted.org/packages/04/12/cff070947791c1ed425ff76413189adbdc2fbe215eba7ce7fa454a03c7f8/numpy-2.5.1-cp312-cp312-win32.whl", hash = "sha256:08d60c810432eb83360958dea0999ac4cfb94531ea8efcbf0b7f277c2068aeb2", size = 6066764, upload-time = "2026-07-04T17:06:32.571Z" }, + { url = "https://files.pythonhosted.org/packages/65/66/53f31807a48a750f9d748da273bc3fcedd12b27ff1f3e373bfec55ef2dc0/numpy-2.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:f7d60026c0bdb1380e83bfa7a0419c4577ee4b9a08880afcb6dadeb74c649fa2", size = 12430966, upload-time = "2026-07-04T17:06:34.926Z" }, + { url = "https://files.pythonhosted.org/packages/2b/2a/d1a88066b1c14186f5d3c0d18c94f17b064511982bab0578d49ee9d43c29/numpy-2.5.1-cp312-cp312-win_arm64.whl", hash = "sha256:17a25e09640602e10bc8de0e6fa2b3fd68eedd84ba6d7842dc8f32f9ab87bd0b", size = 10350488, upload-time = "2026-07-04T17:06:37.785Z" }, + { url = "https://files.pythonhosted.org/packages/eb/07/ec2a3f0c91761581d4b7104a740791800025983f9a4dc4e73f91a99aeac4/numpy-2.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0bfebd8695f9863592fe744be833a258120b14a9f39da255e8aa8fade2c0ddd1", size = 16796419, upload-time = "2026-07-04T17:06:40.37Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ab/ddb499fc4f8780354395face5b65c7fd107bcd6e1d667a5f07d046956f6f/numpy-2.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30b44a6b53a7ae63c54c089a8726e5563ed302716c5b7ccc85afade40b0e7ff6", size = 11765832, upload-time = "2026-07-04T17:06:42.768Z" }, + { url = "https://files.pythonhosted.org/packages/88/b3/3c28c558a09fc72100c646dac6d2fce8e834c471b0edca01a29996706117/numpy-2.5.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:6165343f81b56ef8f514f396989e529b61d9dc709b99421b07e9f3e698e2287d", size = 5325143, upload-time = "2026-07-04T17:06:45.466Z" }, + { url = "https://files.pythonhosted.org/packages/5e/0e/ce19b985bb15c596f4f05954e76cccc77c845083b3b8f938a6c68e523128/numpy-2.5.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4939237038ada79308dda3204ac6462df056b5672b2e25db1149cf873668b3e1", size = 6659749, upload-time = "2026-07-04T17:06:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/2e/20/1ee6614d64332a1bba6411f38e68cb79eec1b2459e20a623777c5c5492a2/numpy-2.5.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c6759f538fb912fc46de0a6b1758ccf7b57bc7c7ebebc23974fdac3de8db0cd", size = 15164716, upload-time = "2026-07-04T17:06:49.494Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a7/2bcd3fdbb87804755c35b729bf8709d62025c5f4cfd7d5b2415997097515/numpy-2.5.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9726558e8db4a5bf7929a70ae50f63abda4daf0efe810e3bfbab95976f75fc1a", size = 16661440, upload-time = "2026-07-04T17:06:52.061Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d7/a41e3310c886fe457d36e670bbf24fae411aca8a7b6ad92a32afd924077c/numpy-2.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3935f3b419b244a02732676fa5317a9193cc596a4c0646db07e5b421229ac9f7", size = 16526305, upload-time = "2026-07-04T17:06:54.605Z" }, + { url = "https://files.pythonhosted.org/packages/53/75/4333a9a707c1edd3a4e1a0c58eca52c0f31e55089fa80db02b5565b24df7/numpy-2.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc932a65ded7ce9013d120845a2514dcccb1a67bfc8deb8d37633762951904a6", size = 18423008, upload-time = "2026-07-04T17:06:57.54Z" }, + { url = "https://files.pythonhosted.org/packages/ee/90/e314a32b1c11a2ffe818ddad3a57b50b4b6e1b6c487192eb50cdef0415d0/numpy-2.5.1-cp313-cp313-win32.whl", hash = "sha256:4b4ff1608417eb7a59da7b967bbb798cacfe071d2caf526a24281cd562072ed9", size = 6063885, upload-time = "2026-07-04T17:07:00.14Z" }, + { url = "https://files.pythonhosted.org/packages/10/70/800b3fca480af32df9e8ea9f3d4a0c8feb4b32d7f195d174eabbda4829ad/numpy-2.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:6c3fe51bc6a16453d452997053454f309e8e0ed7b42d6b361ce4ac8c32913d74", size = 12425674, upload-time = "2026-07-04T17:07:02.387Z" }, + { url = "https://files.pythonhosted.org/packages/8b/0b/196350c122f50f6ca56846f2d71efd5e0d24b7b2e07355e019b2e2c7a11e/numpy-2.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:f7feb014281029e628ba2d5a007407443b06e418b6fe451d1e2adcbc8eba0107", size = 10350256, upload-time = "2026-07-04T17:07:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/db/f4/731b6085a83faf6ca843394cbd5e217280c214399f7e8b21b9f552af0ae2/numpy-2.5.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:7c786fe9a5bbe360022e584c5a34cf6b54265c71bd7ec8ac3d8fec38968071f8", size = 16795063, upload-time = "2026-07-04T17:07:07.374Z" }, + { url = "https://files.pythonhosted.org/packages/bf/64/0e215f2048dd11a55bb989ed41b3585ef57452404e638d703a211a3e4157/numpy-2.5.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32985c896d897419ef8da6917872d80b78ad0ea26d85b23245c7366ffde76d75", size = 11776652, upload-time = "2026-07-04T17:07:09.907Z" }, + { url = "https://files.pythonhosted.org/packages/b5/59/2b844c7a6e9deff69b404a66221e1542937734f65d5e6e39411876053862/numpy-2.5.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:efd736408cc97c79b9e6917338dfc8f06013b2274f992e96b1d9a81a71e2a2c2", size = 5335944, upload-time = "2026-07-04T17:07:12.227Z" }, + { url = "https://files.pythonhosted.org/packages/86/51/9bf7cb2cabcebc9e017e4ec7e6322b378317a542c08b4cb68479c1efc716/numpy-2.5.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:ab84dc6b074fa881cae55bea94cc4f68e285181ba7f32497bf7dee6b1496165b", size = 6656266, upload-time = "2026-07-04T17:07:14.368Z" }, + { url = "https://files.pythonhosted.org/packages/83/3e/fb7615b211b82a32f44d5180a6d421b61f84d4fadd578b48ba4ac34e189f/numpy-2.5.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caf3e317d33d60c37986b452613f4ab51246d0691350c03d0cb4a898627f4a95", size = 15179720, upload-time = "2026-07-04T17:07:16.272Z" }, + { url = "https://files.pythonhosted.org/packages/41/5f/0f992cb24560673496c5d68de61913b57166ce530ffda07c1f280e0cc464/numpy-2.5.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:54ad769f17bc2d833b620851989f62054fb9ab93c969d9e1dc3c8e3d56beea21", size = 16664835, upload-time = "2026-07-04T17:07:19.021Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/97d6475ee91afe2587797d09446f9d3e475ad4cb681662d824809327b75a/numpy-2.5.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c12afb53450fa976d4c681c50a7423729a4c51c0465ed9f32b8a9cabbc472373", size = 16539135, upload-time = "2026-07-04T17:07:22.015Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5b/4db81e4ba0be7e2776b1de68c82aa862c7f8ec27e1b4927d4ae075e20678/numpy-2.5.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e8c11c405efc5ff6816d5983c96cdfa215bab3428961243af3ff59b228490438", size = 18426684, upload-time = "2026-07-04T17:07:24.941Z" }, + { url = "https://files.pythonhosted.org/packages/1f/64/c0ba2d90724d450279a7df8f32057241070250a26a7e2b5337d77347f481/numpy-2.5.1-cp314-cp314-win32.whl", hash = "sha256:f2479a47f8d5932d1718168a681ad6e536a9df484c83cfcf9de365e164537ace", size = 6116103, upload-time = "2026-07-04T17:07:27.622Z" }, + { url = "https://files.pythonhosted.org/packages/c1/1a/837f9ed7405adcd7a40538792eb169eddd8fa5630c16a1ef49dae71a30f4/numpy-2.5.1-cp314-cp314-win_amd64.whl", hash = "sha256:24d0eb82c0541d3415a33425db64ae439dffccd7b4dbcb30e7c35120205c506a", size = 12562177, upload-time = "2026-07-04T17:07:29.887Z" }, + { url = "https://files.pythonhosted.org/packages/22/ed/49707938b6dd0a78a9178dd93227dc89e4c11af47f5c798d70366e8d0483/numpy-2.5.1-cp314-cp314-win_arm64.whl", hash = "sha256:5a4c988b38d261deeeaad9954e3deb091ad905c94e8bb6708654ef1d97f286b0", size = 10627739, upload-time = "2026-07-04T17:07:32.568Z" }, + { url = "https://files.pythonhosted.org/packages/a6/c7/bb4b882cfe7f299cbc8b66e42e7dd78cf9d14e40f9469fc5e3db7e15b3bd/numpy-2.5.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a33276be12fa045805f477f22482088b66bb758ffbe89a9d21457de863a32e22", size = 11894709, upload-time = "2026-07-04T17:07:34.941Z" }, + { url = "https://files.pythonhosted.org/packages/40/3f/5af7f4a7f6224aef48017aa82bb6174c7a659d724be0c75017b7e64a55b4/numpy-2.5.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f089d7b00756190aacf1f5d34bdf38c3c430ac82b4f868f8cede73380460fce7", size = 5453810, upload-time = "2026-07-04T17:07:37.495Z" }, + { url = "https://files.pythonhosted.org/packages/20/c9/3474309bc94d634d3f9c3eddf03250ecb8c22cd948ef16fef69a77cc5d7b/numpy-2.5.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:09e9bfd8d2cf479c7d174804fb3811c53a8e9f20a37444008606b57d6b7a826d", size = 6761189, upload-time = "2026-07-04T17:07:39.563Z" }, + { url = "https://files.pythonhosted.org/packages/90/8a/558ae39fdd55d7e7f7fef9a84a6e964ac6b23edbd2a07e52bb084500507d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e68d8dd1e7eba712948f2053a29ec86917bc70ba1358df869d9f06649ef9cf09", size = 15225039, upload-time = "2026-07-04T17:07:41.682Z" }, + { url = "https://files.pythonhosted.org/packages/63/27/ca7392b2d030277bdf0273e7d23255b3ee57d57a7c170a6f4fb3981e1e5d/numpy-2.5.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99d5095fa265a0c4152e7bb12759e14381ef5496152f1ce58f44bdf55c44beb4", size = 16701306, upload-time = "2026-07-04T17:07:44.611Z" }, + { url = "https://files.pythonhosted.org/packages/02/42/03d53ae7996c44d4374a8262e9dc41671fd56cbb98f7d47ef85cf5da4c6b/numpy-2.5.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ab87a91b3cc3382b8956095bd8f95e00cf679bb81554339be1a2ba404a1473c1", size = 16589955, upload-time = "2026-07-04T17:07:47.694Z" }, + { url = "https://files.pythonhosted.org/packages/7b/15/6c1784ae469640e65db111e9a34b3d0f14d91e8a38b9ce34810ced370dbb/numpy-2.5.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:224ca51130ef7da85bea2191625181cb4f337f9cb64b471f10c1a12aa8b60077", size = 18464252, upload-time = "2026-07-04T17:07:50.684Z" }, + { url = "https://files.pythonhosted.org/packages/94/a8/f98e50356cf167df656c526c2dfeec2d7dde182f2a3da4b458a5938e2776/numpy-2.5.1-cp314-cp314t-win32.whl", hash = "sha256:6eab239876581b2b3c5a242281b6007bbdbcd1c7085d7709bb57c5929b11e6bf", size = 6263298, upload-time = "2026-07-04T17:07:53.445Z" }, + { url = "https://files.pythonhosted.org/packages/72/ac/96ae880cdecad0b3275d9359fcec72667b49a4863c9f12942e43679dda02/numpy-2.5.1-cp314-cp314t-win_amd64.whl", hash = "sha256:83ce9c80d5b521b0d77ddcbe5447c218d247929b6cc056ca5351342accfff0af", size = 12748623, upload-time = "2026-07-04T17:07:55.384Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5a/4d2b1601df3602dba7a14f3348ba9bfe94a18adb428e693df6154c293831/numpy-2.5.1-cp314-cp314t-win_arm64.whl", hash = "sha256:5a6db61f9aaa57e369905c67d852045d3c4f7126405b29d09b19dec118e9c9cb", size = 10697674, upload-time = "2026-07-04T17:07:58.506Z" }, +] + +[[package]] +name = "openfoam-rans-to-gpu" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "foam-stepper" }, + { name = "numpy" }, + { name = "pybind11" }, + { name = "quadrants" }, +] + +[package.dev-dependencies] +dev = [ + { name = "ipykernel" }, + { name = "jupyterlab" }, + { name = "nbclient" }, + { name = "nbformat" }, +] + +[package.metadata] +requires-dist = [ + { name = "foam-stepper", editable = "python" }, + { name = "numpy", specifier = ">=2.0" }, + { name = "pybind11", specifier = ">=2.13" }, + { name = "quadrants", specifier = ">=1.1.3" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "ipykernel", specifier = ">=6.29" }, + { name = "jupyterlab", specifier = ">=4.2" }, + { name = "nbclient", specifier = ">=0.10" }, + { name = "nbformat", specifier = ">=5.10" }, +] + +[[package]] +name = "packaging" +version = "26.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" }, +] + +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.11.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/78/9b/560e4be8e26f6fd133a03630a8df0c663b9e8d61b4ade152b72005aec83b/platformdirs-4.11.0.tar.gz", hash = "sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0", size = 31953, upload-time = "2026-07-21T13:09:36.565Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/68/d8d58938dfb1370b266a1a729e6d77a985be23689a0496498ee17b2cbf90/platformdirs-4.11.0-py3-none-any.whl", hash = "sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74", size = 23247, upload-time = "2026-07-21T13:09:35.422Z" }, +] + +[[package]] +name = "prometheus-client" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/fb/d9aa83ffe43ce1f19e557c0971d04b90561b0cfd50762aafb01968285553/prometheus_client-0.25.0.tar.gz", hash = "sha256:5e373b75c31afb3c86f1a52fa1ad470c9aace18082d39ec0d2f918d11cc9ba28", size = 86035, upload-time = "2026-04-09T19:53:42.359Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/9b/d4b1e644385499c8346fa9b622a3f030dce14cd6ef8a1871c221a17a67e7/prometheus_client-0.25.0-py3-none-any.whl", hash = "sha256:d5aec89e349a6ec230805d0df882f3807f74fd6c1a2fa86864e3c2279059fed1", size = 64154, upload-time = "2026-04-09T19:53:41.324Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pybind11" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/f0/35145a3c3baffeef55d4b8324caa33abaa8fa56ab345ecd4b2211d09163e/pybind11-3.0.4.tar.gz", hash = "sha256:3286b59c8a774b9ee650169302dd5a4eedc30a8617905a0560dd8ee44775130c", size = 589533, upload-time = "2026-04-19T03:08:15.925Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/06/c3a23c9a0263b136c519f033a58d4641e73065fefc7754e9667ec206d992/pybind11-3.0.4-py3-none-any.whl", hash = "sha256:961720ee652da51d531b7b2451a6bd2bc042b0106e6d9baa48ecb7d58034ce63", size = 314166, upload-time = "2026-04-19T03:08:14.091Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pydantic" +version = "2.13.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "annotated-types" }, + { name = "pydantic-core" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, +] + +[[package]] +name = "pydantic-core" +version = "2.46.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" }, + { url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" }, + { url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" }, + { url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" }, + { url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" }, + { url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" }, + { url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" }, + { url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" }, + { url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" }, + { url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" }, + { url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" }, + { url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" }, + { url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" }, + { url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" }, + { url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" }, + { url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" }, + { url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" }, + { url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" }, + { url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" }, + { url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" }, + { url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" }, + { url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" }, + { url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" }, + { url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" }, + { url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" }, + { url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, + { url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" }, + { url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" }, +] + +[[package]] +name = "pygments" +version = "2.20.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "python-json-logger" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/ff/3cc9165fd44106973cd7ac9facb674a65ed853494592541d339bdc9a30eb/python_json_logger-4.1.0.tar.gz", hash = "sha256:b396b9e3ed782b09ff9d6e4f1683d46c83ad0d35d2e407c09a9ebbf038f88195", size = 17573, upload-time = "2026-03-29T04:39:56.805Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/be/0631a861af4d1c875f096c07d34e9a63639560a717130e7a87cbc82b7e3f/python_json_logger-4.1.0-py3-none-any.whl", hash = "sha256:132994765cf75bf44554be9aa49b06ef2345d23661a96720262716438141b6b2", size = 15021, upload-time = "2026-03-29T04:39:55.266Z" }, +] + +[[package]] +name = "pywinpty" +version = "3.0.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/ef/2d27f30c59a67be7025b2d7858c8c2d282b74d66544b2384730b82de74fd/pywinpty-3.0.5.tar.gz", hash = "sha256:61db0db063de9865adbea66db294628f8577f608d9764a4c7d3384eeacc4e81b", size = 16223484, upload-time = "2026-06-11T00:11:58.93Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/34/942cc95ca4e26489875aa8a95192766247a687379ec29543eebe73ec945f/pywinpty-3.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:d62946adf14b15b54c0b8d785f93fe18b04da23f4ad59e2e8c4612646e9abd23", size = 2090915, upload-time = "2026-06-10T23:43:14.98Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/5b9053004844139ea8bd86209c57ade12b134b2782f383a095784c8531ec/pywinpty-3.0.5-cp312-cp312-win_arm64.whl", hash = "sha256:e9391c05fbfa7a992a97e831fc6849887b4014a614192e3d984a7ca59592b376", size = 815934, upload-time = "2026-06-10T23:41:42.384Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f4/2a464b9893cceb3b3f416356e94fdc3e1bca9476993927e4e6d99fe95382/pywinpty-3.0.5-cp313-cp313-win_amd64.whl", hash = "sha256:48db1b0ad9d0a1b81dcaaa7163a99a7808deaceb0c1b2344716dc1fc090c3c4c", size = 2090471, upload-time = "2026-06-10T23:42:11.071Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2c/a138491a0afbdb50eb79395577bd326d4b0fbde7209417d1a8087ff2493a/pywinpty-3.0.5-cp313-cp313-win_arm64.whl", hash = "sha256:2c6008fb2d3774b48693b2fcb7f2cc317ade9dc581289a964ffeeaf81307c9b5", size = 815518, upload-time = "2026-06-10T23:42:02.363Z" }, + { url = "https://files.pythonhosted.org/packages/6f/15/54400049a380582acd1282665c70fcf11e0bd3713679aca78e24c3aae738/pywinpty-3.0.5-cp313-cp313t-win_amd64.whl", hash = "sha256:22ce1b780d89821cc52daf6eac0708af22d93d000ce9c7c07e37489db8594598", size = 2089920, upload-time = "2026-06-10T23:44:13.395Z" }, + { url = "https://files.pythonhosted.org/packages/94/0c/6f24f3c0799f502259b24bdf841a99ad2b0d59df5c2525b4e2a286d14be2/pywinpty-3.0.5-cp313-cp313t-win_arm64.whl", hash = "sha256:9c2919a81bc5cfb09b86fc5a002112b2de95ca4304a07413cbeeb746a1307a5c", size = 814520, upload-time = "2026-06-10T23:43:28.588Z" }, + { url = "https://files.pythonhosted.org/packages/e9/23/f3cd1b1e5fc56517f54452c49f92049e7dd9ffc8a63de22a495581f50d04/pywinpty-3.0.5-cp314-cp314-win_amd64.whl", hash = "sha256:03bb3c16d691d9242267201830bcd0e64a9b663170e9042bc84b210da9de15ac", size = 2090663, upload-time = "2026-06-10T23:43:59.845Z" }, + { url = "https://files.pythonhosted.org/packages/9d/dd/96d6cbfc6d9ddab5c1c2f92c26545ae8997446a2ba7ee2024cd43c81f49b/pywinpty-3.0.5-cp314-cp314-win_arm64.whl", hash = "sha256:89c5c6ef08997a3b4b277b214a35fe15cab4dd6d119f0140aa71df5b1168fdbc", size = 815700, upload-time = "2026-06-10T23:40:50.001Z" }, + { url = "https://files.pythonhosted.org/packages/30/36/d98087bce0acaa4cce7f196103cfa7be3f63ce65f52473bb3e38784ae5d9/pywinpty-3.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:7b566165e0c5fdd6abe167a5ac8b954be6a843eb55a85946576d6bc1dea03d6d", size = 2090093, upload-time = "2026-06-10T23:40:58.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/fd/fe2b0db922ba052ce3976a08f3fc05d0c05047c8b4ebb6102e832b8ef563/pywinpty-3.0.5-cp314-cp314t-win_arm64.whl", hash = "sha256:24366280a8aa677323da87bec729cb3ea3b35367386cece0978bdc6e4695c690", size = 814517, upload-time = "2026-06-10T23:42:34.946Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, + { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, + { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, + { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, + { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, + { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, + { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, + { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, + { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "quadrants" +version = "1.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, + { name = "colorama" }, + { name = "dill" }, + { name = "numpy" }, + { name = "pydantic" }, + { name = "rich" }, + { name = "setuptools" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/55/4931a0f599726aa53ffb3ffed4b997374dde62d49aaf52cec975bae8aaba/quadrants-1.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7655ce9471e016924cdca7e7e6556c711414ad3776173966b5a2deccadf61552", size = 26664368, upload-time = "2026-07-17T21:39:28.577Z" }, + { url = "https://files.pythonhosted.org/packages/6e/a0/48ffbf7daace082d13b3ca56934329d992235c18366ee5ab70aac3a2ba73/quadrants-1.1.3-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:08a248df81d35ee5f70075e8defe7d5a1891d04e7aaffd51d0c1f9049853ce73", size = 38273767, upload-time = "2026-07-17T21:43:40.905Z" }, + { url = "https://files.pythonhosted.org/packages/40/d7/a01a36662187ed0be39280d6992f9dd443eac4be2b62de91cfbf9328470f/quadrants-1.1.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:273983d55683f15471a9909a94a5cd8c20db0ff2335dff446a8d92d87aee9efd", size = 40951378, upload-time = "2026-07-17T21:43:49.962Z" }, + { url = "https://files.pythonhosted.org/packages/cf/32/e2decde7e8f545edcd18dcc25b63acdb641895cb59ffbf010189a301c185/quadrants-1.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:2578b90ec3b26fb111412f421708282b5b16bda6a89f99a458c3792730503cc3", size = 30971283, upload-time = "2026-07-17T21:13:00.538Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b6/bd25caf6bb258384bd0b88d0e783021246e461427fa078e212aa106f4d9e/quadrants-1.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:55dadb45183bfa17879d456903a0419a1854aecaf80a3c6cb94c28b9b8c3de53", size = 26665102, upload-time = "2026-07-17T21:39:22.103Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a1/29338af40c1e4187a28c00c087660d8c64715e00c0d7e0512817de17af03/quadrants-1.1.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_34_aarch64.whl", hash = "sha256:1a4b598e594ed79fa7dbb2ca71ab340855b5cf5440bdd319a156a972bdc4e78b", size = 38268994, upload-time = "2026-07-17T21:43:40.84Z" }, + { url = "https://files.pythonhosted.org/packages/89/59/15f899bcb6bb798073cd40d888dde658398aa67364307d3b2be356f0b332/quadrants-1.1.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:500cb173aec4c06adaaae051f27bd41556bac02c9ca0429685c098e36911ebd8", size = 40952032, upload-time = "2026-07-17T21:43:41.683Z" }, + { url = "https://files.pythonhosted.org/packages/4e/9b/db1d1ff8f72653c7904901b2699ca4d9462928b281d5782e8acc93dcde60/quadrants-1.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:e8ec9bfa27856017e941753f375d62fd400c7d4ff13faed523986f3aa6bcd26b", size = 30970206, upload-time = "2026-07-17T21:12:53.139Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.34.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "rpds-py" +version = "2026.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/be/2e8974163072e7bab7df1a5acd54c4498e75e35d6d18b864d3a9d5dadc92/rpds_py-2026.6.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a0811d33247c3d6128a3001d763f2aa056bb3425204335400ac54f89eec3a0d0", size = 343691, upload-time = "2026-06-30T07:15:14.96Z" }, + { url = "https://files.pythonhosted.org/packages/a4/73/319dfa745dd668efe89309141ded489126461fcecd2b8f3a3cda185129b6/rpds_py-2026.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:538949e262e46caa31ac01bdb3c1e8f642622922cacbabbae6a8445d9dc33eaf", size = 338542, upload-time = "2026-06-30T07:15:16.267Z" }, + { url = "https://files.pythonhosted.org/packages/21/63/4239893be1c4d09b709b1a8f6be4188f0870084ff547f46606b8a75f1b03/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55927d532399c2c646100ff7feb48eaa940ad70f42cd68e1328f3ded9f81ca24", size = 368180, upload-time = "2026-06-30T07:15:17.62Z" }, + { url = "https://files.pythonhosted.org/packages/1c/ca/9c5de382225234ceb37b1844ebdb140db12b2a278bb9efe2fcd19f6c82ce/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f56f1695bc5c0871cbc33dc0130fcf503aab0c57dcc5a6700a4f49eba4f2652e", size = 375067, upload-time = "2026-06-30T07:15:18.952Z" }, + { url = "https://files.pythonhosted.org/packages/87/dc/863f69d1bf04ade34b7fe0d59b9fdf6f0135fe2d7cbca74f1d665589559d/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:270b293dae9058fc9fcedab50f13cebf46fb8ed1d1d54e0521a9da5d6b211975", size = 490509, upload-time = "2026-06-30T07:15:20.434Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ef/eac16a12048b45ec7c7fa94f2be3438a5f26bf9cc8580b18a1cfd609b7f6/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:127565fead0a10943b282957bd5447804ff3160ad79f2ad2635e6d249e380680", size = 382754, upload-time = "2026-06-30T07:15:21.831Z" }, + { url = "https://files.pythonhosted.org/packages/04/8f/d2f3f532616be4d06c316ef119683e832bd3d41e112bf3a88f4151c95b17/rpds_py-2026.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecabd69db66de867690f9797f2f8fa27ba501bbc24540cbdbdc649cd15888ba6", size = 366189, upload-time = "2026-06-30T07:15:23.371Z" }, + { url = "https://files.pythonhosted.org/packages/e3/29/41a7b0e98a4b44cd676ab7598419623373eb43b20be68c084935c1a8cf88/rpds_py-2026.6.3-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:58eadac9cd119677b60e1cf8ac4052f35949d71b8a9e5556efccbe82533cf22a", size = 377750, upload-time = "2026-06-30T07:15:24.659Z" }, + { url = "https://files.pythonhosted.org/packages/2e/05/ecda0bec46f9a1565090bcdc941d023f6a25aff85fda28f89f8d19878152/rpds_py-2026.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7491ee23305ac3eb59e492b6945881f5cd77a6f731061a3f25b77fd40f9e99a4", size = 395576, upload-time = "2026-06-30T07:15:25.987Z" }, + { url = "https://files.pythonhosted.org/packages/68/a8/6ed52f03ee6cb854ce78785cc9a9a672eb880e83fd7224d471f667d151f1/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2c99f7e8ccb3dd6e3e4bfeac657a7b208c9bac8075f4b078c02d7404c34107fa", size = 543807, upload-time = "2026-06-30T07:15:27.356Z" }, + { url = "https://files.pythonhosted.org/packages/8f/d6/156c0d3eea27ba09b92562ba2364ba124c0a061b199e17eac637cd25a5e2/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:62698275682bf121181861295c9181e789030a2d516071f5b8f3c23c170cd0fc", size = 611187, upload-time = "2026-06-30T07:15:28.931Z" }, + { url = "https://files.pythonhosted.org/packages/f1/31/774212ed989c62f7f310220089f9b0a3fb8f40f5443d1727abd5d9f52bc9/rpds_py-2026.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a214c993455f99a89aaeadc9b21241900037adc9d97203e374d75513c5911822", size = 573030, upload-time = "2026-06-30T07:15:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/c9/50/22f73127a41f1ce4f87fe39aadfb9a126345801c274aa93ae88456249327/rpds_py-2026.6.3-cp312-cp312-win32.whl", hash = "sha256:501f9f04a588d6a09179368c57071301445191767c64e4b52a6aa9871f1ef5ed", size = 202185, upload-time = "2026-06-30T07:15:32.027Z" }, + { url = "https://files.pythonhosted.org/packages/04/3a/f0ee4d4dde9d3b69dedf1b5f74e7a40017046d55052d173e418c6a94f960/rpds_py-2026.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:2c958bf94822e9290a40aaf2a822d4bc5c88099093e3948ad6c571eca9272e5f", size = 220394, upload-time = "2026-06-30T07:15:33.359Z" }, + { url = "https://files.pythonhosted.org/packages/f3/83/3382fe37f809b59f02aac04dbc4e765b480b46ee0227ed516e3bdc4d3dfc/rpds_py-2026.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:22bffe6042b9bcb0822bcd1955ec00e245daf17b4344e4ed8e9551b976b63e96", size = 215753, upload-time = "2026-06-30T07:15:34.778Z" }, + { url = "https://files.pythonhosted.org/packages/a4/9e/b818ee580026ec578138e961027a68820c40afeb1ec8f6819b54fb99e196/rpds_py-2026.6.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3cfe765c1da0072636ca06628261e0ea05688e160d5c8a03e0217c3854037223", size = 343012, upload-time = "2026-06-30T07:15:36.005Z" }, + { url = "https://files.pythonhosted.org/packages/f3/6b/686d9dc4359a8f163cfbbf89ee0b4e586431de22fe8248edb63a8cf50d49/rpds_py-2026.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f4d78253f6996be4901669ad25319f842f740eccf4d58e3c7f3dd39e6dde1d8f", size = 338203, upload-time = "2026-06-30T07:15:37.462Z" }, + { url = "https://files.pythonhosted.org/packages/9e/9b/069aa329940f8207615e091f5eedbbd40e1e15eac68a0790fd05ccdf796c/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54f45a148e28767bf343d33a684693c70e451c6f4c0e9904709a723fafbdfc1f", size = 367984, upload-time = "2026-06-30T07:15:39.008Z" }, + { url = "https://files.pythonhosted.org/packages/14/db/34c203e4becff3703e4d3bc121842c00b8689197f398161203a880052f4e/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:842e7b070435622248c7a2c44ae53fa1440e073cc3023bc919fed570884097a7", size = 374815, upload-time = "2026-06-30T07:15:40.253Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7d/8071067d2cc453d916ad836e828c943f575e8a44612537759002a1e07381/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8020133a74bd81b4572dd8e4be028a6b1ebcd70e6726edc3918008c08bee6ee6", size = 490545, upload-time = "2026-06-30T07:15:41.729Z" }, + { url = "https://files.pythonhosted.org/packages/a3/42/da06c5aa8f0484ff07f270787434204d9f4535e2f8c3b51ed402267e63c3/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cdc7e35386f3847df728fbcb5e887e2d79c19e2fa1eba9e51b6621d23e3243af", size = 382828, upload-time = "2026-06-30T07:15:43.327Z" }, + { url = "https://files.pythonhosted.org/packages/57/d7/fe978efc2ae50abe48eb7464668ea99f53c010c60aeebb7b35ad27f23661/rpds_py-2026.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acac386b453c2516111b50985d60ce46e7fadb5ea71ae7b25f4c946935bf27cf", size = 365678, upload-time = "2026-06-30T07:15:44.992Z" }, + { url = "https://files.pythonhosted.org/packages/69/9d/1d8922e1990b2a6eb532b6ff53d3e73d2b3bbffc84116c75826bee73dfc6/rpds_py-2026.6.3-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:425560c6fa0415f27261727bb20bd097568485e5eb0c121f1949417d1c516885", size = 377811, upload-time = "2026-06-30T07:15:46.523Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3d/198dceafb4fb034a6a47347e1b0735d34e0bd4a50be4e898d408ee66cb14/rpds_py-2026.6.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a550fb4950a06dde3beb4721f5ad4b25bf4513784665b0a8522c792e2bd822a4", size = 395382, upload-time = "2026-06-30T07:15:47.955Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f1/13968e49655d40b6b19d8b9140296bbc6f1d86b3f0f6c346cf9f1adddf4b/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f4bca01b63096f606e095734dd56e74e175f94cfbf24ff3d63281cec61f7bb7", size = 543832, upload-time = "2026-06-30T07:15:49.33Z" }, + { url = "https://files.pythonhosted.org/packages/ac/ab/289bcb1b90bd3e40a2900c561fa0e2087345ecbb094f0b870f2345142b7c/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ccffae9a092a00deb7efd545fe5e2c33c33b88e7c054337e9a74c179347d0b7d", size = 611011, upload-time = "2026-06-30T07:15:50.847Z" }, + { url = "https://files.pythonhosted.org/packages/1e/16/5043105e679436ccfbc8e5e0dd2d663ed18a8b8113515fd06a5e5d77c83e/rpds_py-2026.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1cf01971c4f2c5553b772a542e4aaf191789cd331bc2cd4ff0e6e65ba49e1e97", size = 572431, upload-time = "2026-06-30T07:15:52.394Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/adab103321c0a6565d5ae1c2998349bc3ee175b82ccc5ae8fc04cc413075/rpds_py-2026.6.3-cp313-cp313-win32.whl", hash = "sha256:8c3d1e9c15b9d51ca0391e13da1a25a0a4df3c58a37c9dc368e0736cf7f69df0", size = 201710, upload-time = "2026-06-30T07:15:53.894Z" }, + { url = "https://files.pythonhosted.org/packages/7b/ed/a03b09668e74e5dabbf2e211f6468e1820c0552f7b0500082da31841bf7b/rpds_py-2026.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:9250a9a0a6fd4648b3f868da8d91a4c52b5811a62df58e753d50ae4454a36f80", size = 219454, upload-time = "2026-06-30T07:15:55.25Z" }, + { url = "https://files.pythonhosted.org/packages/27/17/b8642c12930b71bc2b25831f6708ccf0f75abcd11883932ec9ce54ba3a78/rpds_py-2026.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:900a67df3fd1660b035a4761c4ce73c382ea6b35f90f9863c36c6fd8bf8b09bb", size = 215063, upload-time = "2026-06-30T07:15:56.573Z" }, + { url = "https://files.pythonhosted.org/packages/b6/36/7fbe9dcdaf857fb3f63c2a2284b62492d95f5e8334e947e5fb6e7f68c9be/rpds_py-2026.6.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:931908d9fc855d8f74783377822be318edb6dcb19e47169dc038f9a1bf60b06e", size = 344510, upload-time = "2026-06-30T07:15:57.921Z" }, + { url = "https://files.pythonhosted.org/packages/ba/54/f785cc3d3f60839ca57a5af4927a9f347b07b2799c373fc20f7949f87c7e/rpds_py-2026.6.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d7469697dce35be237db177d42e2a2ee26e6dcc5fc052078a6fefabd288c6edd", size = 339495, upload-time = "2026-06-30T07:15:59.238Z" }, + { url = "https://files.pythonhosted.org/packages/63/ef/d4cdaf309e6b095b43597103cf8c0b951d6cca2acce68c474f75ec12e0c7/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcfbcf66006befb9fd2aeaa9e01feaf881b4dc330a02ba07d2322b1c11be7b5d", size = 369454, upload-time = "2026-06-30T07:16:01.021Z" }, + { url = "https://files.pythonhosted.org/packages/96/4a/9559a68b7ee15db09d7981212e8c2e219d2a1d6d4faa0391d813c3496a36/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847927daf4cffbd4e90e42bc890069897101edd015f956cb8721b3473372edda", size = 374583, upload-time = "2026-06-30T07:16:02.287Z" }, + { url = "https://files.pythonhosted.org/packages/ef/75/8964aa7d2c6e8ac43eba8eb6e6b0fdda1f46d39f2fc3e6aa9f2cb17f485d/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aca6c1ef08a82bfe327cc156da694660f599923e2e6665b6d81c9c2d0ac9ffc8", size = 492919, upload-time = "2026-06-30T07:16:03.723Z" }, + { url = "https://files.pythonhosted.org/packages/8f/97/6908094ac804115e65aedfd90f1b5fee4eebebd3f6c4cfc5419939267565/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ae50181a047c871561212bb97f7932a2d45fb53e947bd9b57ebad85b529cbc53", size = 383725, upload-time = "2026-06-30T07:16:05.305Z" }, + { url = "https://files.pythonhosted.org/packages/d1/9c/0d1fdc2e7aba23e290d603bc494e97bd205bae262ce33c6b32a69768ed5e/rpds_py-2026.6.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc319e5a1de4b6913aac94bf6a2f9e847371e0a140a43dd4991db1a09bc2d504", size = 367255, upload-time = "2026-06-30T07:16:07.086Z" }, + { url = "https://files.pythonhosted.org/packages/c4/fe/f0209ca4a9ed074bc8acb44dfd0e81c3122e94c9689f5645b7973a866719/rpds_py-2026.6.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:e4316bf32babbed84e691e352faf967ce2f0f024174a8643c37c94a1080374fc", size = 379060, upload-time = "2026-06-30T07:16:08.525Z" }, + { url = "https://files.pythonhosted.org/packages/c6/8d/f1cc54c616b9d8897de8738aac148d20afca93f68187475fe194d09a71b9/rpds_py-2026.6.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8c6e5a2f750cc71c3e3b11d71661f21d6f9bc6cebc6564b1466417a1ec03ec77", size = 395960, upload-time = "2026-06-30T07:16:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/fb/04/aafff00f73aeca2945f734f1d483c64ab8f472d0864ab02377fd8e89c3b2/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4470ce197d4090875cf6affbf1f853338387428df97c4fb7b7106317b8214698", size = 545356, upload-time = "2026-06-30T07:16:11.816Z" }, + { url = "https://files.pythonhosted.org/packages/fd/cc/e229663b9e4ddac5a4acbe9085dd80a71af2a5d356b8b39d6bff233f24b0/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ea964164cc9afa72d4d9b23cc28dafae93693c0a53e0b42acbff15b22c3f9ddd", size = 612319, upload-time = "2026-06-30T07:16:13.586Z" }, + { url = "https://files.pythonhosted.org/packages/e3/7a/8a0e6d3e6cd066af108b71b43122c3fe158dd9eb86acac626593a2582eb1/rpds_py-2026.6.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:639c8929aa0afe81be836b04de888460d6bed38b9c54cfc18da8f6bfabf5af5d", size = 573508, upload-time = "2026-06-30T07:16:15.23Z" }, + { url = "https://files.pythonhosted.org/packages/87/03/2a69ab618a789cf6cf85c86bb844c62d090e700ab1a2aa676b3741b6c516/rpds_py-2026.6.3-cp314-cp314-win32.whl", hash = "sha256:882076c00c0a608b131187055ddc5ae29f2e7eaf870d6168980420d58528a5c8", size = 202504, upload-time = "2026-06-30T07:16:16.893Z" }, + { url = "https://files.pythonhosted.org/packages/85/62/a3892ba945f4e24c78f352e5de3c7620d8479f73f211406a97263d13c7d2/rpds_py-2026.6.3-cp314-cp314-win_amd64.whl", hash = "sha256:0be972be84cfcaf46c8c6edf690ca0f154ac17babf1f6a955a51579b34ad2dc5", size = 220380, upload-time = "2026-06-30T07:16:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e7/c2bd44dc831931815ad11ebb5f430b5a0a4d3caa9de837107876c30c3432/rpds_py-2026.6.3-cp314-cp314-win_arm64.whl", hash = "sha256:2a9c6f195058cb45335e8cc3802745c603d716eb96bc9625950c1aac71c0c703", size = 215976, upload-time = "2026-06-30T07:16:19.654Z" }, + { url = "https://files.pythonhosted.org/packages/79/9c/fff7b74bce9a091ec9a012a03f9ff5f69364eaf9451060dfc4486da2ffdd/rpds_py-2026.6.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:f90938e92afda60266da758ee7d363447f7f0138c9559f9e1811629580582d90", size = 346840, upload-time = "2026-06-30T07:16:21.268Z" }, + { url = "https://files.pythonhosted.org/packages/e9/44/77bcb1168b33704908295533d27f10eb811e9e3e193e8993dc99572211d3/rpds_py-2026.6.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec829541c45bca16e61c7ae50c20501f213605beb75d1aba91a6ee37fbbb56a4", size = 340282, upload-time = "2026-06-30T07:16:22.875Z" }, + { url = "https://files.pythonhosted.org/packages/87/3c/7a9081c7c9e645b39efe19e4ffbeccd80add246327cd9b888aecffd72317/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afd70d95892096cdb26f15a00c45907b17817577aa8d1c76b2dcc2788391f9e9", size = 370403, upload-time = "2026-06-30T07:16:24.415Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/af47021eb7dad6ff3396cb001c08f0f3c4d06c20253f75be6421a59fe6b7/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:29dfa0533a5d4c94d4dfa1b694fcb56c9c63aad8330ffdd816fd225d0a7a162f", size = 376055, upload-time = "2026-06-30T07:16:26.111Z" }, + { url = "https://files.pythonhosted.org/packages/81/fc/a3bcf517084396a6dd258c592567a3c011ba4557f2fde23dceaf26e74f2e/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af05d726809bff6b141be124d4c7ce998f9c9c7f30edb1f46c07aa103d540b41", size = 494419, upload-time = "2026-06-30T07:16:27.596Z" }, + { url = "https://files.pythonhosted.org/packages/c9/eb/13d529d1788135425c7bf207f8463458ca5d92e43f3f701365b83e9dffc1/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9826217f048f620d9a712672818bf231442c1b35d96b227a07eabd11b4bb6945", size = 384848, upload-time = "2026-06-30T07:16:29.183Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f4/b7ac49f30013aba8f7b9566b1dd07e81de95e708c1374b7bacc5b9bc5c9c/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:536bceea4fa4acf7e1c61da2b5786304367c816c8895be71b8f537c480b0ea1f", size = 371369, upload-time = "2026-06-30T07:16:30.912Z" }, + { url = "https://files.pythonhosted.org/packages/31/86/6260bafa622f788b07ddec0e52d810305c8b9b0b8c27f58a2ab04bf62b4f/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:bc0011654b91cc4fb2ae701bec0a0ba1e552c0714247fa7af6c59e0ccfa3a4e1", size = 379673, upload-time = "2026-06-30T07:16:32.486Z" }, + { url = "https://files.pythonhosted.org/packages/19/c3/03f1ee79a047b48daeca157c89a18509cde22b6b951d642b9b0af1be660a/rpds_py-2026.6.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:539d75de9e0d536c84ff18dfeb805398e58227001ce09231a26a08b9aed1ee0e", size = 397500, upload-time = "2026-06-30T07:16:34.471Z" }, + { url = "https://files.pythonhosted.org/packages/f0/95/8ed0cd8c377dca12aea498f119fe639fc474d1461545c39d2b5872eb1c0f/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:166cf54d9f44fc6ceb53c7860258dde44a81406646de79f8ed3234fca3b6e538", size = 545978, upload-time = "2026-06-30T07:16:36.45Z" }, + { url = "https://files.pythonhosted.org/packages/d3/f2/0eb57f0eaa83f8fc152a7e03de968ab77e1f00732bebc892b190c6eebde7/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:d34c20167764fbcf927194d532dd7e0c56772f0a5f943fa5ef9e9afbba8fb9db", size = 613350, upload-time = "2026-06-30T07:16:38.213Z" }, + { url = "https://files.pythonhosted.org/packages/5b/de/e0674bdbc3ef7634989b3f854c3f34bc1f587d36e5bfdc5c378d57034619/rpds_py-2026.6.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ea7bb13b7c9a29791f87a0387ba7d3ad3a6d783d827e4d3f27b40a0ff44495e2", size = 576486, upload-time = "2026-06-30T07:16:39.797Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f6/21101359743cd136ada781e8210a85769578422ba460672eea0e29739200/rpds_py-2026.6.3-cp314-cp314t-win32.whl", hash = "sha256:6de4744d05bd1aa1be4ed7ea1189e3979196808008113bbbf899a460966b925e", size = 201068, upload-time = "2026-06-30T07:16:41.316Z" }, + { url = "https://files.pythonhosted.org/packages/a6/b2/9574d4d44f7760c2aa32d92a0a4f41698e33f5b204a0bf5c9758f52c79d5/rpds_py-2026.6.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c7b9a2f8f4d8e90af72571d3d495deebdd7e3c75451f5b41719aee166e940fc2", size = 220600, upload-time = "2026-06-30T07:16:43.091Z" }, + { url = "https://files.pythonhosted.org/packages/08/ae/f23a2697e6ee6340a578b0f136be6483657bef0c6f9497b752bb5c0964bb/rpds_py-2026.6.3-cp315-cp315-macosx_10_12_x86_64.whl", hash = "sha256:e059c5dde6452b44424bd1834557556c226b57781dee1227af23518459722b13", size = 344726, upload-time = "2026-06-30T07:16:44.5Z" }, + { url = "https://files.pythonhosted.org/packages/c3/63/e7b3a1a5358dd32c930a1062d8e15b67fd6e8922e81df9e91706d66ee5c8/rpds_py-2026.6.3-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:2f7c26fbc5acd2522b95d4177fe4710ffd8e9b20529e703ffbf8db4d93903f05", size = 339587, upload-time = "2026-06-30T07:16:46.255Z" }, + { url = "https://files.pythonhosted.org/packages/ec/64/10a85681916ca55fffb91b0a211f84e34297c109243484dd6394660a8a7c/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3086b538543802f84c843911242db20447de00d8752dd0efc936dbcf02218ba", size = 369585, upload-time = "2026-06-30T07:16:48.101Z" }, + { url = "https://files.pythonhosted.org/packages/76/c2/baf95c7c38823e12ba34407c5f5767a89e5cf2233895e56f608167ae9493/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f2e5c5ee828d42cb11760761c0af6507927bec42d0ad5458f97c9203b054617", size = 375479, upload-time = "2026-06-30T07:16:49.93Z" }, + { url = "https://files.pythonhosted.org/packages/6a/94/0aad06c72d65101e11d33528d438cda99a39ce0da99466e156158f2541d3/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed0c1e5d10cdc7135537988c74a0188da68e2f3c30813ba3744ab1e42e0480f9", size = 492418, upload-time = "2026-06-30T07:16:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/b5/17/de3f5a479a1f056535d7489819639d8cd591ea6281d700390b43b1abd745/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c2642a7603ec0b16ed77da4555db3b4b472341904873788327c0b0d7b95f1bb", size = 384123, upload-time = "2026-06-30T07:16:53.622Z" }, + { url = "https://files.pythonhosted.org/packages/46/7d/bf09bd1b145bb2671c03e1e6d1ab8651858d90d8c7dfeadd85a37a934fd8/rpds_py-2026.6.3-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4320744c1ffdd95a603def63344bfab2d33edeab301c5007e7de9f9f5b3885", size = 367351, upload-time = "2026-06-30T07:16:55.241Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ea/1bb734f314b8be319149ddee80b18bd41372bdcfbdf88d28131c0cd37719/rpds_py-2026.6.3-cp315-cp315-manylinux_2_31_riscv64.whl", hash = "sha256:a9f4645593036b81bbdb36b9c8e0ea0d1c3fee968c4d59db0344c14087ef143a", size = 378827, upload-time = "2026-06-30T07:16:56.841Z" }, + { url = "https://files.pythonhosted.org/packages/4b/93/d9611e5b25e26df9a3649813ed66193ace9347a7c7fc4ab7cf70e94851c0/rpds_py-2026.6.3-cp315-cp315-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e55d236be29255554da47abe5c577637db7c24a02b8b46f0ca9524c855801868", size = 395966, upload-time = "2026-06-30T07:16:58.557Z" }, + { url = "https://files.pythonhosted.org/packages/c3/cb/99d77e16e5534ae1d90629bbe419ba6ee170833a6a85e3aa1cc41726fbbc/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:24e9c5386e16669b674a69c156c8eeefcb578f3b3397b713b08e6d60f3c7b187", size = 545680, upload-time = "2026-06-30T07:17:00.164Z" }, + { url = "https://files.pythonhosted.org/packages/59/15/11a29755f790cef7a2f755e8e14f4f0c33f39489e1893a632a2eee59672b/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:c60924535c75f1566b6eb75b5c31a48a43fef04fa2d0d201acbad8a9969c6107", size = 611853, upload-time = "2026-06-30T07:17:01.962Z" }, + { url = "https://files.pythonhosted.org/packages/68/86/0c27547e21644da938fb530f7e1a8148dd24d02db07e7a5f2567a17ce710/rpds_py-2026.6.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:38a2fea2787428f811719ceb9114cb78964a3138838320c29ac39526c79c16ba", size = 573715, upload-time = "2026-06-30T07:17:03.693Z" }, + { url = "https://files.pythonhosted.org/packages/29/71/4d8fcf700931815594bce892255bbd973b94efaf0fc1932b0590df18d886/rpds_py-2026.6.3-cp315-cp315-win32.whl", hash = "sha256:d483fe17f01ad64b7bf7cc38fcefff1ca9fb83f8c2b2542b68f97ffe0611b369", size = 202864, upload-time = "2026-06-30T07:17:05.746Z" }, + { url = "https://files.pythonhosted.org/packages/eb/62/b577562de0edbb55b2be85ce5fd09c33e386b9b13eee09833af4240fd5c4/rpds_py-2026.6.3-cp315-cp315-win_amd64.whl", hash = "sha256:67e3a721ffc5d8d2210d3671872298c4a84e4b8035cfe42ffd7cde35d772b146", size = 220430, upload-time = "2026-06-30T07:17:07.471Z" }, + { url = "https://files.pythonhosted.org/packages/c8/95/d6d0b2509825141eef60669a5739eec88dbc6a48053d6c92993a5704defe/rpds_py-2026.6.3-cp315-cp315-win_arm64.whl", hash = "sha256:6e84adbcf4bf841aed8116a8264b9f50b4cb3e7bd89b516122e616ac56ca269e", size = 215877, upload-time = "2026-06-30T07:17:09.008Z" }, + { url = "https://files.pythonhosted.org/packages/b7/bf/f3ea278f0afd615c1d0f19cb69043a41526e2bb600c2b536eb192218eb27/rpds_py-2026.6.3-cp315-cp315t-macosx_10_12_x86_64.whl", hash = "sha256:ae6dd8f10bd17aad820876d24caec9efdafd80a318d16c0a48edb5e136902c6b", size = 346933, upload-time = "2026-06-30T07:17:10.762Z" }, + { url = "https://files.pythonhosted.org/packages/9d/29/9907bdf1c5346763cf10b7f6852aad86652168c259def904cbe0082c5864/rpds_py-2026.6.3-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:bdbd97738551fca3917c1bd7188bec1920bb520104f28e7e1007f9ceb17b7690", size = 340274, upload-time = "2026-06-30T07:17:12.266Z" }, + { url = "https://files.pythonhosted.org/packages/6f/2c/8e03767b5778ef25cebf74a7a91a2c3806f8eced4c92cb7406bbe060756d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b95977e7211527ab0ba576e286d023389fbeeb32a6b7b771665d333c60e5342", size = 370763, upload-time = "2026-06-30T07:17:14.107Z" }, + { url = "https://files.pythonhosted.org/packages/2e/e1/df2a7e1ba2efd796af26194250b8d42c821b46592311595162af9ef0528d/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15fde0e6fb0d88a60d221204873743e5d9f0b7d29165e62cd86d0413ad74ba6", size = 376467, upload-time = "2026-06-30T07:17:15.76Z" }, + { url = "https://files.pythonhosted.org/packages/6b/de/8a0814d1946af29cb068fb259aa8622f856df1d0bab58429448726b537f5/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a136d453475ac0fcbda502ef1e6504bd28d6d904700915d278deeab0d00fe140", size = 496689, upload-time = "2026-06-30T07:17:17.308Z" }, + { url = "https://files.pythonhosted.org/packages/df/f3/f19e0c852ba13694f5a79f3b719331051573cb5693feacf8a88ffffc3a71/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f826877d462181e5eb1c26a0026b8d0cab05d99844ecb6d8bf3627a2ca0c0442", size = 385340, upload-time = "2026-06-30T07:17:18.928Z" }, + { url = "https://files.pythonhosted.org/packages/e2/ae/7ec3a9d2d4351f99e37bcb06b6b6f954512646bfdbf9742e1de727865daf/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79486287de1730dbaff3dbd124d0ca4d2ef7f9d29bf2544f1f93c09b5bcbbd12", size = 372179, upload-time = "2026-06-30T07:17:20.539Z" }, + { url = "https://files.pythonhosted.org/packages/d3/ac/9cee911dff2aaa9a5a8354f6610bf2e6a616de9197c5fff4f54f82585f1e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_31_riscv64.whl", hash = "sha256:808345f53cb952433ca2816f1604ff3515608a81784954f38d4452acfe8e61d5", size = 379993, upload-time = "2026-06-30T07:17:22.212Z" }, + { url = "https://files.pythonhosted.org/packages/83/6b/7c2a07ba88d1e9a936612f7a5d067467ed03d971d5a06f7d309dff044a7e/rpds_py-2026.6.3-cp315-cp315t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1967debc37f64f2c4dc90a7f563aec558b471966e12adcac4e1c4240496b6ebf", size = 398909, upload-time = "2026-06-30T07:17:23.66Z" }, + { url = "https://files.pythonhosted.org/packages/97/0b/776ffcb66783637b0031f6d58d6fb55913c8b5abf00aeecd46bf933fb477/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:f0840b5b17057f7fd918b76183a4b5a0635f43e14eb2ce60dce1d4ee4707ea00", size = 546584, upload-time = "2026-06-30T07:17:25.264Z" }, + { url = "https://files.pythonhosted.org/packages/55/33/ba3bc04d7092bd553c9b2b195624992d2cc4f3de1f380b7b93cbee67bd79/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:faa679d19a6696fd54259ad321251ad77a13e70e03dd834daa762a44fb6196ef", size = 614357, upload-time = "2026-06-30T07:17:26.888Z" }, + { url = "https://files.pythonhosted.org/packages/8b/71/14edf065f04630b1a8472f7653cad03f6c478bcf95ea0e6aed55451e33ea/rpds_py-2026.6.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:23a439f31ccbeff1574e24889128821d1f7917470e830cf6544dced1c662262a", size = 576533, upload-time = "2026-06-30T07:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/ba/76/65002b08596c389105720a8c0d22298b8dc25a4baf89b2ce431343c8b1de/rpds_py-2026.6.3-cp315-cp315t-win32.whl", hash = "sha256:913ca42ccad3f8cc6e292b587ae8ae49c8c823e5dce51a736252fc7c7cdfa577", size = 201204, upload-time = "2026-06-30T07:17:30.193Z" }, + { url = "https://files.pythonhosted.org/packages/8c/97/d855d6b3c322d1f27e26f5241c42016b56cf01377ea8ed348285f54652f0/rpds_py-2026.6.3-cp315-cp315t-win_amd64.whl", hash = "sha256:ae3d4fe8c0b9213624fdce7279d70e3b148b682ca20719ebd193a23ebfa47324", size = 220719, upload-time = "2026-06-30T07:17:31.788Z" }, +] + +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "83.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/26/f5d29e25ffdb535afef2d35cdb55b325298f96debd670da4c325e08d70f4/setuptools-83.0.0.tar.gz", hash = "sha256:025bccbbf0fa05b6192bc64ae1e7b16e001fd6d6d4d5de03c97b1c1ade523bef", size = 1154254, upload-time = "2026-07-04T15:31:22.699Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/40/e1e72872c6354b306daef1703549e8e83b4d43cfea356311bf722a043752/setuptools-83.0.0-py3-none-any.whl", hash = "sha256:29b23c360f22f414dc7336bb39178cc7bcbf6021ed2733cde173f09dba19abb3", size = 1008090, upload-time = "2026-07-04T15:31:20.885Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "soupsieve" +version = "2.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/38/e12680bbe6b4f8f3d17adcaf38d26850aa756c85cf4a80e79fc12a018fe8/soupsieve-2.9.1.tar.gz", hash = "sha256:c33e6605bbc71dd628b00c632d58ae607c22bade247e52553928f83bbb75b4ba", size = 122261, upload-time = "2026-07-21T16:57:17.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/2c/437fe806897c2d6cfdc3ee43a18da8bf8e568530a4ae9bac781541ca9896/soupsieve-2.9.1-py3-none-any.whl", hash = "sha256:4f4477399246b7a0c720a88ca2454b11cd6bb9ae4c9d170140786e916776c14c", size = 37404, upload-time = "2026-07-21T16:57:16.421Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + +[[package]] +name = "tinycss2" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/ae/2ca4913e5c0f09781d75482874c3a95db9105462a92ddd303c7d285d3df2/tinycss2-1.5.1.tar.gz", hash = "sha256:d339d2b616ba90ccce58da8495a78f46e55d4d25f9fd71dfd526f07e7d53f957", size = 88195, upload-time = "2025-11-23T10:29:10.082Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/45/c7b5c3168458db837e8ceab06dc77824e18202679d0463f0e8f002143a97/tinycss2-1.5.1-py3-none-any.whl", hash = "sha256:3415ba0f5839c062696996998176c4a3751d18b7edaaeeb658c9ce21ec150661", size = 28404, upload-time = "2025-11-23T10:29:08.676Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/64/24/95ec527ad67b76d59299e5465b3935d05e4294b7e0290a3924b7487df30b/tornado-6.5.7.tar.gz", hash = "sha256:66c513a76cda70d53907bc27cf1447557699c2e95aa48ba27a442ff61c3ddfc2", size = 519252, upload-time = "2026-06-08T17:34:51.232Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/dc/c7043cab6fed8ae159fc1923ce829ada35c4dbd797d408a43858ffaf9639/tornado-6.5.7-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:148b2eb15c2c765a50796172c1e499649b35f30d2e3c3d3e15913cfa56bfb163", size = 448543, upload-time = "2026-06-08T17:34:38.052Z" }, + { url = "https://files.pythonhosted.org/packages/92/4f/090b1431e5a43df696feceffc268c5383cc079ecb5f08ce58f917109aafe/tornado-6.5.7-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9da38de27f1da3b78a966f0dae12b5a1ea9afe72ca805d84ff06508272ddf100", size = 446707, upload-time = "2026-06-08T17:34:39.594Z" }, + { url = "https://files.pythonhosted.org/packages/37/d8/ef374952fd5da67d4463122c2b8e5a96536ec10b4b339254c6dcde81d01c/tornado-6.5.7-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8d759e71906ee783f8867b93bf26a265743da4c1e2f4a018464c1ba019862972", size = 449774, upload-time = "2026-06-08T17:34:41.204Z" }, + { url = "https://files.pythonhosted.org/packages/35/37/d434c73f4c6e014b745b9b37085f34f40c022f007efff3d7fe65991899f3/tornado-6.5.7-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a46347a18f23fb92b396beebe0fb78f61dda0cc302445202c16203d8a18848b", size = 450745, upload-time = "2026-06-08T17:34:42.531Z" }, + { url = "https://files.pythonhosted.org/packages/b6/2b/56b9aff361d7f1ab728a805ec7d7ea835f8807afa9f5cc690ea0e630efb9/tornado-6.5.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7778b30bef919231265e91c69963ce0f49a1e9c07ac900bbe75b19ce2575ba92", size = 450578, upload-time = "2026-06-08T17:34:43.787Z" }, + { url = "https://files.pythonhosted.org/packages/02/30/a7444fb23aa76860a14198fab96ac79f1866b0a6e19e26c4381b0938e50f/tornado-6.5.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:e726f0c75da7726eec023aa62751ff8878bd2737e34fbdd33b1ae5897d2200f5", size = 449985, upload-time = "2026-06-08T17:34:45.326Z" }, + { url = "https://files.pythonhosted.org/packages/5c/42/5f0e56c01e8d9d36f4e23f367b85ae6cae0c1ecddd5e6977d8388ad27488/tornado-6.5.7-cp39-abi3-win32.whl", hash = "sha256:f8de3bf12d3efdd0cbe7c8887868198f8a91415e3f29fcf258d9b8eb7b1d9ae4", size = 451047, upload-time = "2026-06-08T17:34:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/c9/a4/b393076ffb21b469eec5b328a0534cf03a3b90bfc6b1f09507cdd075d938/tornado-6.5.7-cp39-abi3-win_amd64.whl", hash = "sha256:de942f843533a039ef9fa3d9c88c7cd8a7c94553fb5ad0154270989b3d99a2c4", size = 451485, upload-time = "2026-06-08T17:34:48.248Z" }, + { url = "https://files.pythonhosted.org/packages/71/2e/7b1c769803121b809112cf9a00681c472eae1d80e32d7ec0e0bd61d0d0e1/tornado-6.5.7-cp39-abi3-win_arm64.whl", hash = "sha256:ff934fce95643af5f11efdae618eaa73d469dc588641e5c8d19295a0c65c4796", size = 450506, upload-time = "2026-06-08T17:34:49.702Z" }, +] + +[[package]] +name = "traitlets" +version = "5.15.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/a9/a2584b8313b89f94869ddb3c4074617a691de1812a614d2d50e32ca5a7a6/traitlets-5.15.1.tar.gz", hash = "sha256:7b1c07854fe25acb39e009bae49f11b79ff6cbb2f27999104e9110e7a6b53722", size = 163344, upload-time = "2026-06-03T12:26:06.181Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/8d/1080ee4c231f361b6ce4470d556c8c435b67c7e0753aaa641497ee92f88b/traitlets-5.15.1-py3-none-any.whl", hash = "sha256:770a53705f84b81ac107e83a1b3328ff2dae16094d8fc3cfc004e4b22dfd8e92", size = 85858, upload-time = "2026-06-03T12:26:04.395Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" }, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + +[[package]] +name = "urllib3" +version = "2.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +]