Fix BPX 1.1 hysteresis parameter mapping#5507
Conversation
`OCP (lithiation) [V]` / `OCP (delithiation) [V]` / `OCP hysteresis decay constant` were being passed through `_get_pybamm_name` unchanged, so the resulting parameter set carried the literal BPX aliases (e.g. "Negative electrode OCP (lithiation) [V]") instead of the names PyBaMM's Axen one-state hysteresis OCP submodel evaluates. The decay constant in particular also needs to fan out to two FunctionParameters (lithiation + delithiation branches) on the particle pre-name, not the electrode pre-name. While here: - Extract `Initial hysteresis state: Positive/Negative electrode` from `bpx.state.initial_conditions` (previously silently dropped). Handles both scalar values for single-phase electrodes and per-particle-phase dicts for blended electrodes, mapping BPX phase names to PyBaMM `Primary: ` / `Secondary: ` prefixes by particle order. - Replace the unconditional `pybamm_dict.update(...)` for `Total heat transfer coefficient [W.m-2.K-1]` with `setdefault` so the value pulled from `bpx.state.thermal_environment` isn't silently clobbered back to 0. - Default `target_soc` in `create_from_bpx` / `create_from_bpx_obj` to `None` and resolve it to `bpx.state.initial_conditions.initial_soc` when the BPX file has a State section. Falls back to 1.0 when there is no State section. Refs pybamm-team#5463 (follow-up to pybamm-team#5469). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- `bpx_to_param_dict` already builds `domain_phases` at the top; the new initial-hysteresis-state loop was recomputing `_get_phase_names` per electrode. Reuse the cached value. - Lift the two `OCP (lithiation/delithiation) [V]` rename branches in `_get_pybamm_name` into a `_BPX_OCP_HYSTERESIS_RENAMES` mapping next to `_OPTIONAL_HYSTERESIS_FIELDS`. - Compare `domain.name` rather than `domain is negative_electrode` for the decay-constant fan-out, so dispatch doesn't lean on the module-level singleton invariant. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
|
@ejfdickinson could you please take a look and see if any issues remain with any BPX files you have? |
…pping # Conflicts: # CHANGELOG.md
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5507 +/- ##
==========================================
- Coverage 98.09% 98.09% -0.01%
==========================================
Files 338 338
Lines 31246 31272 +26
==========================================
+ Hits 30650 30675 +25
- Misses 596 597 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@rtimms Thanks, everything BPX-related is working for me for the test cases we have. Notes:
|
|
@ejfdickinson thanks for testing!
|
|
@rtimms I diagnosed the problem - it was due to some placeholder zeroes for electrolyte properties, so no issues here. Just the runtime error path had changed compared to expectations from previous versions. Good to go for this PR as far as I can see! Thank you! |
| pybamm.logger.warning( | ||
| "Initial concentrations cannot be set using stoichiometry limits for " | ||
| "blend electrodes. Please set the initial concentrations manually." | ||
| ) |
There was a problem hiding this comment.
Hi @rtimms, can we please have the initial concentrations calculated via ESOH and added in for blended electrodes too?
There was a problem hiding this comment.
This would be great, but it's a known limitation also for beginning-of-life preceding the degradation content in BPX, so I'd ask this not be at the expense of delaying a PyBaMM release covering the schema support!
@Daniel-Nicolae23 @rtimms You are welcome to inspect some of the tools we use to implement this after BPX import in our AEPyBaMM toolkit. Currently the code supports this for negative electrode blends only, but we are also working on some general-purpose utilities to be released soon.
https://github.com/About-Energy-OpenSource/AEPyBaMM/blob/main/src/aepybamm/sci_tools.py
see compute_lithiation_bounds and add_initial_concentrations
Summary
Follow-up to #5469 (which added BPX 1.x support). The newly-introduced hysteresis fields on BPX 1.1's
Particleblock weren't being translated byparameters/bpx.py::_get_pybamm_name, so:OCP (lithiation) [V]ended up asNegative electrode OCP (lithiation) [V](PyBaMM expectsNegative electrode lithiation OCP [V])OCP (delithiation) [V]similarlyOCP hysteresis decay constantended up under its raw BPX alias on the electrode pre-name; PyBaMM's Axen one-state hysteresis OCP submodel (OneStateHysteresisOpenCircuitPotential) evaluates two FunctionParameters —<Domain> particle lithiation hysteresis decay rateand<Domain> particle delithiation hysteresis decay rate— both on the particle pre-name. The BPX scalar now fans out to both with the same value.While auditing the State section I found three adjacent gaps and fixed them in the same PR:
Initial hysteresis state: Positive/Negative electrodewere extracted intobpx.statebut never copied to the PyBaMM dict, so the FunctionParameter was always falling back to 0. Now mapped to[<Phase>: ]Initial hysteresis state in <domain> electrode. Handles both the scalar (single-phase) and the per-particle-phase dict (blended) shapes by routing the blended-ness decision through the existing_get_phase_nameshelper and matching BPX phase keys to PyBaMMPrimary:/Secondary:by particle declaration order.Total heat transfer coefficient [W.m-2.K-1]frombpx.state.thermal_environmentwas being silently clobbered to 0 a few lines later by an unconditionalpybamm_dict.update(...). Replaced withsetdefault.target_socdefaulted to1.0regardless of what the BPX file declared inState.initial_conditions.initial_soc. The default is nowNone, resolved to the BPX value when a State section is present and 1.0 otherwise.Implementation note:
_get_pybamm_namenow returnslist[str]instead ofstrto support the 1→2 fan-out for the decay constant. The two call sites in_bpx_to_domain_param_dictiterate the returned list. Missing/None-valued optional hysteresis fields are skipped so they don't pollute the parameter dict.Refs #5463.
Test plan
tests/unit/test_parameters/test_bpx.pystill pass (13/13)Nonetarget_soc=Nonefalls back to BPXInitial state-of-chargeNotes for reviewer
<Domain> particle hysteresis decay rate(withoutlithiation/delithiationprefix). Users on that submodel will still need to add it manually.State.degradation(LLI,LAM: Positive electrode,LAM: Negative electrode) is still unhandled — it has no direct PyBaMM equivalent and is out of scope here. Worth a separate issue if/when there's demand.🤖 Generated with Claude Code