From be89a9d9c4675575b379e5a599291106f36f3582 Mon Sep 17 00:00:00 2001 From: Ferran Brosa Planella Date: Sat, 31 Oct 2026 11:34:19 +0000 Subject: [PATCH] Make the storage take exactly the flux law's heat at its wall The storage's heat-flux condition divided the flux law's flux by the conductivity at the extrapolated wall enthalpy, while the heat entering it is k grad(T) on the wall face, with k extrapolated from the nodes. While the PCM by the wall melted, with a sharp melting point and a conductivity dropping from 0.4 to 0.15 W.m-1.K-1, the packed bed took a fifth of the flux law's heat, and its fluid temperatures overshot and fell by 1 K to 2 K during a charge. Energy stayed exactly conserved, so no test saw it. The condition now divides by the face conductivity itself. The charge is monotonic and converges with the capsule mesh, the Nallusamy fit improves at every height, and the finned tubes move by at most 0.006 K, so the regression reference is regenerated (F-056, DESIGN D6). Co-Authored-By: Claude Opus 5.5 --- changelog.d/51.breaking.md | 1 + changelog.d/51.fix.md | 1 + docs/design/DESIGN.md | 7 +++++- docs/design/findings.md | 1 + src/pytes/submodels/coupling.py | 6 ++--- src/pytes/submodels/storage.py | 7 ++++-- tests/data/reference_regression.npz | Bin 29228 -> 29201 bytes tests/models/test_packed_bed.py | 37 ++++++++++++++++++++++++++++ 8 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 changelog.d/51.breaking.md create mode 100644 changelog.d/51.fix.md diff --git a/changelog.d/51.breaking.md b/changelog.d/51.breaking.md new file mode 100644 index 0000000..b2bb9a0 --- /dev/null +++ b/changelog.d/51.breaking.md @@ -0,0 +1 @@ +Packed-bed results change: during a charge, the fluid temperature at each height no longer overshoots and then falls by 1 K to 2 K. While the PCM at a capsule's surface melted, the capsule took up to five times less heat than the heat transfer coefficient gives; it now takes exactly that heat. The default packed bed now fits the measurements of Nallusamy et al. (2007) better at every height, and the finned-tube models move by at most 0.006 K. There is nothing to change in your code. diff --git a/changelog.d/51.fix.md b/changelog.d/51.fix.md new file mode 100644 index 0000000..b0e3f14 --- /dev/null +++ b/changelog.d/51.fix.md @@ -0,0 +1 @@ +The heat entering a storage through its wall is now exactly the surface flux law's heat flux, also while the material by the wall changes phase (F-056). diff --git a/docs/design/DESIGN.md b/docs/design/DESIGN.md index e29d4e4..a7d8b35 100644 --- a/docs/design/DESIGN.md +++ b/docs/design/DESIGN.md @@ -208,7 +208,12 @@ never from a separately discretised flux. This applies to **every** coupling, fl and storage-storage (maintainer, 2026-10-14). Rationale: PyBaMM imposes a Neumann condition on the gradient, so the flux the finite volumes use is `k_face / k_surface` times the one requested, and with a temperature (Dirichlet) condition it is whatever the scheme computes; -the ledger is exact in both cases, for any conductivity. In a bed, the film resistance works +the ledger is exact in both cases, for any conductivity. Exact conservation does not make the +flux right, though: with `k_surface` the conductivity at the extrapolated wall enthalpy, the +factor reached 5 while a PCM by the wall melted, and the packed bed took a fifth of the flux +law's heat (F-056). So a storage's heat-flux condition divides by `k_face` itself (the node +values of `k` extrapolated to the wall, as `k grad(T)` uses), making the factor 1: the flux +law's flux enters, and the ledger still counts it exactly. In a bed, the film resistance works as at the finned-tube wall: the flux uses the boundary value of `T(H)`, with no extra unknown (F-014). - **General surface flux law.** Because the ledger makes conservation independent of how the diff --git a/docs/design/findings.md b/docs/design/findings.md index b26a8aa..5614935 100644 --- a/docs/design/findings.md +++ b/docs/design/findings.md @@ -75,6 +75,7 @@ Seeded by the Stage A side-by-side diff (2026-10-11). Sources compared: | F-053 | Renames | PyTES had no way to deprecate a name: renames were clean breaks (F-036, F-050), and the only record of an old name was `BaseModel.renamed_options` (F-050), for options. Issue #17 adds `pytes.deprecation`: one registry of renames (`RENAMES`), `PyTESDeprecationWarning`, a module `__getattr__` for renamed classes and functions, and the option hook in `process_options`. `BaseModel.renamed_options` (unreleased) is replaced by the registry entry for F-050, whose error message is unchanged apart from the model name prefix. Option values are deferred (none renamed yet; the issue asked for them), and so are variable and parameter names: PyBaMM looks them up itself. No result changes. | Contract change (DESIGN D3, D17, maintainer, 2026-10-23). | Done; tests in `tests/toolkit/test_deprecation.py`; pytest turns the warning into an error; `CONTRIBUTING.md` "Renaming and deprecating". | closed | | F-054 | Names: steps, couplings | Names that said less than, or something other than, what the code does (issue #18, maintainer, 2026-10-23). `step.ConstantInputs` becomes `step.Inlet` and `step.ConstantPower` becomes `step.Power`: their values need not be constant, and the names now follow `pybamm.step` (named after what is held). New `step.Rest`: no flow, with the inlet temperature given or, by default, held where the previous step left it (the initial temperature for a first step), through a new solver input the runner sets from the previous step; until now a rest was `ConstantInputs(T_in, 0)`. `LedgerWallCoupling` becomes `WallCoupling` ("ledger" names how energy is accounted, not the physics) and `FinPCMCoupling` becomes `FinStorageCoupling` (the material between the fins need not change phase); its default submodel name becomes "Fin-storage coupling", and its keyword arguments `pcm_label` and `pcm_geometry` are kept, as the registry cannot deprecate keyword arguments. The old names are aliases through the registry (F-053): they warn until 0.2.0. Not changed: no `mass_flow_rate_below` termination (backwards flow is not supported), `Target`, `ConstantPropertyLiquid`. No result changes (the reference experiment is unchanged). The rename test for user-facing files no longer reads the changelog's copy in `docs/`, which keeps the names of its time. | Contract flaw (names). | Renamed everywhere, aliases in `pytes.deprecation.RENAMES`; DESIGN D10 and the contract updated; tests for `Rest`. | closed | | F-055 | Variables | Outputs for comparison with measurements (issue #14, maintainer's choices 2026-10-24). Required in every model: `Volume flow rate [m3.s-1]` (`mdot / rho(h_in)`, twin `[l.min-1]`), `Pumped volume [m3]` (its time integral, a solver state, twin `[l]`), `Inlet-outlet temperature difference [K]` (`T_in - T_out`, the example name of D12, which no model provided), `Heat transfer fluid velocity [m.s-1]` (mean velocity in the flow area; interstitial in a packed bed), `Charged energy [J]` (`-Discharged energy`), and `Discharged throughput [J]` and `Charged throughput [J]` (time integrals of `max(P, 0)` and `max(-P, 0)`, solver states). Every storage provides its volume-weighted averages, `