{ "cells": [ { "cell_type": "markdown", "id": "cell-001", "metadata": {}, "source": [ "# SVDSBTL backend — validation against HEOS\n", "\n", "This page compares the **SVDSBTL** surrogate backend against the **HEOS** Helmholtz-energy reference for `rho` as a function of two different input pairs: `(P, T)` and `(H, P)`. Each fluid below shows `log10 | (rho_SVDSBTL - rho_HEOS) / rho_HEOS |` over single-phase rectangles in the two coordinate systems.\n", "\n", "The heatmaps are interactive — hover for the local error value, drag to pan, scroll to zoom, double-click to reset. The figures are static HTML (no kernel, no Binder, no JupyterLite); the interactivity is plotly.js embedded by nbsphinx.\n", "\n", "**Backends:** `HEOS` (reference) vs `SVDSBTL&HEOS` (rank-truncated SVD surrogate over HEOS). \n", "**Inputs:** `PT_INPUTS` and `HmassP_INPUTS`. **Output:** `rhomass()` [kg/m^3]. \n", "**Fluids:** `Water`, `Argon`, `Hydrogen`, `R1234yf`, `R245fa`, `D6`.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "cell-002", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.331133Z", "iopub.status.busy": "2026-05-29T01:49:23.330961Z", "iopub.status.idle": "2026-05-29T01:49:23.546337Z", "shell.execute_reply": "2026-05-29T01:49:23.545937Z" } }, "outputs": [ { "ename": "ModuleNotFoundError", "evalue": "No module named 'plotly'", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mModuleNotFoundError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 16\u001b[39m\n\u001b[32m 13\u001b[39m Path(_cache).mkdir(parents=\u001b[38;5;28;01mTrue\u001b[39;00m, exist_ok=\u001b[38;5;28;01mTrue\u001b[39;00m)\n\u001b[32m 15\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mnumpy\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mnp\u001b[39;00m\n\u001b[32m---> \u001b[39m\u001b[32m16\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mplotly\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mio\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mpio\u001b[39;00m\n\u001b[32m 17\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mplotly\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mgraph_objects\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mgo\u001b[39;00m\n\u001b[32m 18\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mCoolProp\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mCoolProp\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mas\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mCP\u001b[39;00m\n", "\u001b[31mModuleNotFoundError\u001b[39m: No module named 'plotly'" ] } ], "source": [ "import os\n", "from pathlib import Path\n", "\n", "# Route SVDSBTL surface I/O to a docs-dedicated cache directory so the\n", "# build does not collide with developer interactive work in\n", "# ~/.CoolProp/SVDTables/. Setting this *before* importing CoolProp lets\n", "# the C++ config-init read the env var on first access, and joblib's\n", "# loky workers inherit the env so they hit the same cache.\n", "_cache = os.environ.setdefault(\n", " 'COOLPROP_ALTERNATIVE_SVDTABLES_DIRECTORY',\n", " str(Path.home() / '.CoolProp' / 'SVDTables-docs'),\n", ")\n", "Path(_cache).mkdir(parents=True, exist_ok=True)\n", "\n", "import numpy as np\n", "import plotly.io as pio\n", "import plotly.graph_objects as go\n", "import CoolProp.CoolProp as CP\n", "from CoolProp.CoolProp import PT_INPUTS, HmassP_INPUTS, QT_INPUTS\n", "\n", "# Also set via the explicit config setter in the parent process. NOTE:\n", "# this only mutates the parent's Configuration singleton; joblib's loky\n", "# workers spawn fresh interpreters with their own singletons and rely\n", "# entirely on env-var inheritance (which is why os.environ.setdefault\n", "# above MUST stay before the CoolProp import — do not remove it).\n", "CP.set_config_string(CP.ALTERNATIVE_SVDTABLES_DIRECTORY, _cache)\n", "\n", "pio.renderers.default = 'notebook_connected'\n", "print(f'SVDSBTL cache directory: {_cache}')\n", "\n", "FLUIDS = ['Water', 'Argon', 'Hydrogen', 'R1234yf', 'R245fa', 'D6', 'CO2', 'Helium']\n", "INPUT_PAIRS = ['PT', 'HP']\n", "N_X, N_Y = 300, 300 # grid resolution per axis (90k cells per panel)\n", "BAND_REL = 0.02 # half-width band around saturation line to mask (PT only)\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "cell-003", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.548391Z", "iopub.status.busy": "2026-05-29T01:49:23.547953Z", "iopub.status.idle": "2026-05-29T01:49:23.594020Z", "shell.execute_reply": "2026-05-29T01:49:23.593630Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'N_X' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[2]\u001b[39m\u001b[32m, line 24\u001b[39m\n\u001b[32m 21\u001b[39m h_max += delta\n\u001b[32m 22\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m np.linspace(h_min, h_max, N_Y)\n\u001b[32m---> \u001b[39m\u001b[32m24\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mcompute_error_grid\u001b[39m(fluid, input_pair, N_X=\u001b[43mN_X\u001b[49m, N_Y=N_Y):\n\u001b[32m 25\u001b[39m \u001b[38;5;250m \u001b[39m\u001b[33;03m\"\"\"Return (x_axis, y_axis, log10_err, Tc, pc, x_label, y_label, err_msg).\u001b[39;00m\n\u001b[32m 26\u001b[39m \n\u001b[32m 27\u001b[39m \u001b[33;03m input_pair is 'PT' or 'HP'.\u001b[39;00m\n\u001b[32m (...)\u001b[39m\u001b[32m 35\u001b[39m \u001b[33;03m the returned grid is all-NaN in that case.\u001b[39;00m\n\u001b[32m 36\u001b[39m \u001b[33;03m \"\"\"\u001b[39;00m\n\u001b[32m 37\u001b[39m ref = CP.AbstractState(\u001b[33m'\u001b[39m\u001b[33mHEOS\u001b[39m\u001b[33m'\u001b[39m, fluid)\n", "\u001b[31mNameError\u001b[39m: name 'N_X' is not defined" ] } ], "source": [ "def _hp_axes(ref, Tmin, Tmax, pmin, pmax, N_Y):\n", " \"\"\"Probe the four corners of the (T, p) rectangle to estimate an\n", " enthalpy range that covers the single-phase region for the HP plot.\n", " \"\"\"\n", " hs = []\n", " for T_q, p_q in [(Tmin, pmin), (Tmin, pmax), (Tmax, pmin), (Tmax, pmax)]:\n", " try:\n", " ref.update(PT_INPUTS, p_q, T_q)\n", " hs.append(ref.hmass())\n", " except Exception:\n", " pass\n", " if not hs:\n", " return np.linspace(0.0, 1e6, N_Y)\n", " h_min, h_max = min(hs), max(hs)\n", " if h_max == h_min:\n", " # All surviving probes returned the same enthalpy. Expand by a\n", " # small relative delta so np.linspace produces a non-degenerate\n", " # axis; the panel will be uninformative but at least renders.\n", " delta = max(abs(h_min) * 1e-6, 1e-6)\n", " h_min -= delta\n", " h_max += delta\n", " return np.linspace(h_min, h_max, N_Y)\n", "\n", "def compute_error_grid(fluid, input_pair, N_X=N_X, N_Y=N_Y):\n", " \"\"\"Return (x_axis, y_axis, log10_err, Tc, pc, x_label, y_label, err_msg).\n", "\n", " input_pair is 'PT' or 'HP'.\n", " 'PT' -> x = p (log, in Pa), y = T (linear, in K).\n", " Mask a +/- BAND_REL band around the saturation line.\n", " 'HP' -> x = p (log, in Pa), y = h (linear, in J/kg).\n", " No explicit saturation mask; the SVDSBTL surface is undefined\n", " inside the dome and queries there are caught and set to NaN.\n", "\n", " SVDSBTL surface build failures are caught and reported via err_msg;\n", " the returned grid is all-NaN in that case.\n", " \"\"\"\n", " ref = CP.AbstractState('HEOS', fluid)\n", " Tc = ref.T_critical()\n", " pc = ref.p_critical()\n", " Tmin = max(ref.Tmin(), 0.6 * Tc)\n", " Tmax = min(ref.Tmax(), 1.4 * Tc)\n", " pmin = max(1e3, 0.01 * pc)\n", " pmax = 3.0 * pc\n", "\n", " p_axis = np.geomspace(pmin, pmax, N_X)\n", " if input_pair == 'PT':\n", " y_axis = np.linspace(Tmin, Tmax, N_Y)\n", " y_label = 'reduced temperature T / T_c'\n", " # Saturation line p_sat(T) for masking.\n", " psat = np.full_like(y_axis, np.nan)\n", " for i, T in enumerate(y_axis):\n", " if T < Tc:\n", " try:\n", " ref.update(QT_INPUTS, 0.0, T)\n", " psat[i] = ref.p()\n", " except Exception:\n", " pass\n", " elif input_pair == 'HP':\n", " y_axis = _hp_axes(ref, Tmin, Tmax, pmin, pmax, N_Y)\n", " y_label = 'specific enthalpy h [kJ/kg]'\n", " psat = None\n", " else:\n", " raise ValueError(f'unknown input_pair: {input_pair!r}')\n", "\n", " x_label = 'reduced pressure p / p_c'\n", " err = np.full((N_Y, N_X), np.nan)\n", "\n", " try:\n", " svd = CP.AbstractState('SVDSBTL&HEOS', fluid)\n", " except Exception as e:\n", " return (p_axis, y_axis, err, Tc, pc, x_label, y_label,\n", " f'SVDSBTL surface build failed: {e}')\n", "\n", " for i, y in enumerate(y_axis):\n", " for j, p in enumerate(p_axis):\n", " if psat is not None and np.isfinite(psat[i]) and abs(p - psat[i]) / psat[i] < BAND_REL:\n", " continue\n", " try:\n", " if input_pair == 'PT':\n", " ref.update(PT_INPUTS, p, y)\n", " svd.update(PT_INPUTS, p, y)\n", " else: # HP\n", " ref.update(HmassP_INPUTS, y, p)\n", " svd.update(HmassP_INPUTS, y, p)\n", " rho_ref = ref.rhomass()\n", " rho_svd = svd.rhomass()\n", " if rho_ref > 0:\n", " err[i, j] = abs(rho_svd - rho_ref) / rho_ref\n", " except Exception:\n", " pass\n", " # Floor zero / near-zero errors at 1e-16 so exact-match cells render at\n", " # the colorbar floor (best-possible accuracy) instead of going to -inf\n", " # and being shown as NaN/white — which would falsely suggest a failed\n", " # query. SVDSBTL inside the two-phase dome returns the same density as\n", " # HEOS (both go through the same saturation lookup), so err is 0 there.\n", " with np.errstate(divide='ignore', invalid='ignore'):\n", " log_err = np.log10(np.maximum(err, 1e-16))\n", " return p_axis, y_axis, log_err, Tc, pc, x_label, y_label, None\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "cell-004", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.595716Z", "iopub.status.busy": "2026-05-29T01:49:23.595544Z", "iopub.status.idle": "2026-05-29T01:49:23.599903Z", "shell.execute_reply": "2026-05-29T01:49:23.599575Z" } }, "outputs": [], "source": [ "def plot_from_grid(fluid, input_pair, grid):\n", " p_axis, y_axis, log_err, Tc, pc, x_label, y_label, err_msg = grid\n", " pr = p_axis / pc\n", " title = f'{fluid} [{input_pair}] \\u2014 Tc={Tc:.2f} K, pc={pc/1e5:.3f} bar'\n", " if err_msg is not None:\n", " title += ' [SVDSBTL surface unavailable]'\n", " if input_pair == 'PT':\n", " # x = p (log), y = T (linear). z is stored as [y_index, x_index].\n", " Tr = y_axis / Tc\n", " heat = go.Heatmap(\n", " x=pr, y=Tr, z=log_err,\n", " colorscale='Viridis', zmin=-12, zmax=-2,\n", " colorbar=dict(title='log10 |\\u0394\\u03c1/\\u03c1|'),\n", " hovertemplate=('p/p_c=%{x:.3f}
'\n", " 'T/T_c=%{y:.3f}
'\n", " 'log10 err=%{z:.2f}'),\n", " )\n", " xaxis = dict(title=x_label, type='log')\n", " yaxis = dict(title=y_label)\n", " else: # HP — Mollier convention: x = h (linear), y = p (log).\n", " h_disp = y_axis / 1e3 # J/kg -> kJ/kg for display\n", " heat = go.Heatmap(\n", " x=h_disp, y=pr, z=log_err.T,\n", " colorscale='Viridis', zmin=-12, zmax=-2,\n", " colorbar=dict(title='log10 |\\u0394\\u03c1/\\u03c1|'),\n", " hovertemplate=('h=%{x:.1f} kJ/kg
'\n", " 'p/p_c=%{y:.3f}
'\n", " 'log10 err=%{z:.2f}'),\n", " )\n", " xaxis = dict(title=y_label) # 'specific enthalpy h [kJ/kg]'\n", " yaxis = dict(title='reduced pressure p / p_c', type='log')\n", " fig = go.Figure(heat)\n", " fig.update_layout(\n", " title=title,\n", " xaxis=xaxis,\n", " yaxis=yaxis,\n", " width=720, height=480,\n", " margin=dict(l=70, r=20, t=50, b=60),\n", " )\n", " if err_msg is not None:\n", " print(err_msg)\n", " return fig\n" ] }, { "cell_type": "markdown", "id": "cell-005", "metadata": {}, "source": [ "### Parallel grid computation\n", "\n", "Each `(fluid, input_pair)` pair is an independent unit of work, so we compute all 12 of them concurrently via `joblib` (process-based workers; `n_jobs=min(len(FLUIDS)*len(INPUT_PAIRS), cpu_count)`). Wall-clock and per-panel timings are printed below.\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "cell-006", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.601655Z", "iopub.status.busy": "2026-05-29T01:49:23.601331Z", "iopub.status.idle": "2026-05-29T01:49:23.624494Z", "shell.execute_reply": "2026-05-29T01:49:23.624144Z" } }, "outputs": [ { "ename": "ModuleNotFoundError", "evalue": "No module named 'joblib'", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mModuleNotFoundError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mtime\u001b[39;00m,\u001b[38;5;250m \u001b[39m\u001b[34;01mos\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mjoblib\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m Parallel, delayed\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34mcompute_timed\u001b[39m(fluid, input_pair):\n\u001b[32m 5\u001b[39m t0 = time.perf_counter()\n", "\u001b[31mModuleNotFoundError\u001b[39m: No module named 'joblib'" ] } ], "source": [ "import time, os\n", "from joblib import Parallel, delayed\n", "\n", "def compute_timed(fluid, input_pair):\n", " t0 = time.perf_counter()\n", " grid = compute_error_grid(fluid, input_pair)\n", " return (fluid, input_pair), grid, time.perf_counter() - t0\n", "\n", "tasks = [(f, ip) for f in FLUIDS for ip in INPUT_PAIRS]\n", "n_jobs = min(len(tasks), os.cpu_count() or 1)\n", "t0 = time.perf_counter()\n", "results = Parallel(n_jobs=n_jobs, backend='loky')(\n", " delayed(compute_timed)(f, ip) for f, ip in tasks\n", ")\n", "wall = time.perf_counter() - t0\n", "\n", "GRIDS = {key: grid for key, grid, _ in results}\n", "print(f'wall-clock: {wall:.2f} s (n_jobs={n_jobs}, '\n", " f'cores={os.cpu_count()}, panels={len(tasks)})')\n", "for key, _, dt in results:\n", " print(f' {key[0]:9s} {key[1]:>3s} {dt:6.2f} s')\n", "print(f' sum {sum(dt for _, _, dt in results):6.2f} s '\n", " f'speedup vs serial: {sum(dt for _, _, dt in results) / wall:.2f}x')\n" ] }, { "cell_type": "markdown", "id": "cell-007", "metadata": {}, "source": [ "## Water" ] }, { "cell_type": "markdown", "id": "cell-008", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 5, "id": "cell-009", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.626303Z", "iopub.status.busy": "2026-05-29T01:49:23.625962Z", "iopub.status.idle": "2026-05-29T01:49:23.641455Z", "shell.execute_reply": "2026-05-29T01:49:23.641045Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mWater\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mWater\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Water', 'PT', GRIDS[('Water', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-010", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 6, "id": "cell-011", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.643028Z", "iopub.status.busy": "2026-05-29T01:49:23.642852Z", "iopub.status.idle": "2026-05-29T01:49:23.658384Z", "shell.execute_reply": "2026-05-29T01:49:23.657960Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[6]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mWater\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mWater\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Water', 'HP', GRIDS[('Water', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-012", "metadata": {}, "source": [ "## Argon" ] }, { "cell_type": "markdown", "id": "cell-013", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 7, "id": "cell-014", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.659906Z", "iopub.status.busy": "2026-05-29T01:49:23.659753Z", "iopub.status.idle": "2026-05-29T01:49:23.675238Z", "shell.execute_reply": "2026-05-29T01:49:23.674828Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[7]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mArgon\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mArgon\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Argon', 'PT', GRIDS[('Argon', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-015", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 8, "id": "cell-016", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.677032Z", "iopub.status.busy": "2026-05-29T01:49:23.676624Z", "iopub.status.idle": "2026-05-29T01:49:23.691968Z", "shell.execute_reply": "2026-05-29T01:49:23.691545Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mArgon\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mArgon\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Argon', 'HP', GRIDS[('Argon', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-017", "metadata": {}, "source": [ "## Hydrogen" ] }, { "cell_type": "markdown", "id": "cell-018", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 9, "id": "cell-019", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.693466Z", "iopub.status.busy": "2026-05-29T01:49:23.693318Z", "iopub.status.idle": "2026-05-29T01:49:23.708600Z", "shell.execute_reply": "2026-05-29T01:49:23.708277Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[9]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mHydrogen\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mHydrogen\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Hydrogen', 'PT', GRIDS[('Hydrogen', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-020", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 10, "id": "cell-021", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.710169Z", "iopub.status.busy": "2026-05-29T01:49:23.709914Z", "iopub.status.idle": "2026-05-29T01:49:23.725490Z", "shell.execute_reply": "2026-05-29T01:49:23.724988Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[10]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mHydrogen\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mHydrogen\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Hydrogen', 'HP', GRIDS[('Hydrogen', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-022", "metadata": {}, "source": [ "## R1234yf" ] }, { "cell_type": "markdown", "id": "cell-023", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 11, "id": "cell-024", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.729636Z", "iopub.status.busy": "2026-05-29T01:49:23.729243Z", "iopub.status.idle": "2026-05-29T01:49:23.745317Z", "shell.execute_reply": "2026-05-29T01:49:23.744850Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[11]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mR1234yf\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mR1234yf\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('R1234yf', 'PT', GRIDS[('R1234yf', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-025", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 12, "id": "cell-026", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.747045Z", "iopub.status.busy": "2026-05-29T01:49:23.746709Z", "iopub.status.idle": "2026-05-29T01:49:23.762102Z", "shell.execute_reply": "2026-05-29T01:49:23.761707Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[12]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mR1234yf\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mR1234yf\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('R1234yf', 'HP', GRIDS[('R1234yf', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-027", "metadata": {}, "source": [ "## R245fa" ] }, { "cell_type": "markdown", "id": "cell-028", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 13, "id": "cell-029", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.763591Z", "iopub.status.busy": "2026-05-29T01:49:23.763446Z", "iopub.status.idle": "2026-05-29T01:49:23.778631Z", "shell.execute_reply": "2026-05-29T01:49:23.778300Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[13]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mR245fa\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mR245fa\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('R245fa', 'PT', GRIDS[('R245fa', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-030", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 14, "id": "cell-031", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.780098Z", "iopub.status.busy": "2026-05-29T01:49:23.779949Z", "iopub.status.idle": "2026-05-29T01:49:23.797279Z", "shell.execute_reply": "2026-05-29T01:49:23.796859Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[14]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mR245fa\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mR245fa\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('R245fa', 'HP', GRIDS[('R245fa', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-032", "metadata": {}, "source": [ "## D6" ] }, { "cell_type": "markdown", "id": "cell-033", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 15, "id": "cell-034", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.798783Z", "iopub.status.busy": "2026-05-29T01:49:23.798632Z", "iopub.status.idle": "2026-05-29T01:49:23.813837Z", "shell.execute_reply": "2026-05-29T01:49:23.813382Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[15]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mD6\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mD6\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('D6', 'PT', GRIDS[('D6', 'PT')])" ] }, { "cell_type": "markdown", "id": "cell-035", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 16, "id": "cell-036", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.815309Z", "iopub.status.busy": "2026-05-29T01:49:23.815133Z", "iopub.status.idle": "2026-05-29T01:49:23.830490Z", "shell.execute_reply": "2026-05-29T01:49:23.830027Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[16]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mD6\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mD6\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('D6', 'HP', GRIDS[('D6', 'HP')])" ] }, { "cell_type": "markdown", "id": "75bcff77", "metadata": {}, "source": [ "## CO2" ] }, { "cell_type": "markdown", "id": "30a226c0", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 17, "id": "5eacc916", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.832041Z", "iopub.status.busy": "2026-05-29T01:49:23.831785Z", "iopub.status.idle": "2026-05-29T01:49:23.847054Z", "shell.execute_reply": "2026-05-29T01:49:23.846700Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[17]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mCO2\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mCO2\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('CO2', 'PT', GRIDS[('CO2', 'PT')])" ] }, { "cell_type": "markdown", "id": "89211e3f", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 18, "id": "a3b06964", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.848663Z", "iopub.status.busy": "2026-05-29T01:49:23.848495Z", "iopub.status.idle": "2026-05-29T01:49:23.865474Z", "shell.execute_reply": "2026-05-29T01:49:23.864999Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[18]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mCO2\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mCO2\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('CO2', 'HP', GRIDS[('CO2', 'HP')])" ] }, { "cell_type": "markdown", "id": "f0c0a2ec", "metadata": {}, "source": [ "## Helium" ] }, { "cell_type": "markdown", "id": "49e923af", "metadata": {}, "source": [ "### PT" ] }, { "cell_type": "code", "execution_count": 19, "id": "708bb10a", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.867189Z", "iopub.status.busy": "2026-05-29T01:49:23.866922Z", "iopub.status.idle": "2026-05-29T01:49:23.887406Z", "shell.execute_reply": "2026-05-29T01:49:23.886723Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[19]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mHelium\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mHelium\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mPT\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Helium', 'PT', GRIDS[('Helium', 'PT')])" ] }, { "cell_type": "markdown", "id": "51413aff", "metadata": {}, "source": [ "### HP" ] }, { "cell_type": "code", "execution_count": 20, "id": "fafcc40e", "metadata": { "execution": { "iopub.execute_input": "2026-05-29T01:49:23.890480Z", "iopub.status.busy": "2026-05-29T01:49:23.889630Z", "iopub.status.idle": "2026-05-29T01:49:23.907135Z", "shell.execute_reply": "2026-05-29T01:49:23.906779Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'GRIDS' is not defined", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[20]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m plot_from_grid(\u001b[33m'\u001b[39m\u001b[33mHelium\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m, \u001b[43mGRIDS\u001b[49m[(\u001b[33m'\u001b[39m\u001b[33mHelium\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mHP\u001b[39m\u001b[33m'\u001b[39m)])\n", "\u001b[31mNameError\u001b[39m: name 'GRIDS' is not defined" ] } ], "source": [ "plot_from_grid('Helium', 'HP', GRIDS[('Helium', 'HP')])" ] }, { "cell_type": "markdown", "id": "cell-037", "metadata": {}, "source": [ "## Notes\n", "\n", "- **PT panels** mask a 2-percent band around the saturation line, since (T, p) inside that band straddles the dome at ULP scale and SVDSBTL is single-phase only.\n", "- **HP panels** have no explicit mask: the two-phase dome is a true 2D region in (h, p), and SVDSBTL surface queries inside it throw — caught and reported as NaN. The white wedge in each HP heatmap is the dome.\n", "- `R1234yf`, `R245fa`, and `D6` have narrow native `Tmin/Tmax` envelopes that may clip the plot domain below the nominal `0.6 Tc` lower bound.\n", "- The 12 panels are computed concurrently via `joblib` (process workers; `n_jobs=min(panels, cpu_count)`). Wall-clock and per-panel breakdown are in the parallel-compute cell above.\n", "- This notebook is re-executed on every `make html` build (`Web/conf.py` pre-executes all `.ipynb` via `jupyter nbconvert --execute`). Surfaces are cached at the directory printed in the first code cell (default `~/.CoolProp/SVDTables-docs/`, override via `COOLPROP_ALTERNATIVE_SVDTABLES_DIRECTORY`). First build of a fresh (fluid, input_pair) takes 20-80 s; subsequent builds reuse the serialized surface and run in ~1 s.\n", "- Source generator: `Web/coolprop/_gen/gen_SVDSBTLValidation.py`.\n" ] } ], "metadata": { "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.13.3" } }, "nbformat": 4, "nbformat_minor": 5 }