Skip to content

Added InputParameter support in PyBamm experiments - #4826

Merged
MarcBerliner merged 20 commits into
pybamm-team:developfrom
Rishab87:input-params
Feb 21, 2025
Merged

Added InputParameter support in PyBamm experiments#4826
MarcBerliner merged 20 commits into
pybamm-team:developfrom
Rishab87:input-params

Conversation

@Rishab87

@Rishab87 Rishab87 commented Feb 7, 2025

Copy link
Copy Markdown
Member

Description

Added InputParameter support in experiments, now you can pass them something like this:

current_step = pybamm.step.current(1, input_parameters=pybamm.InputParameter("I_app"), termination="2.5 V")
experiment = pybamm.Experiment(
    input_parameters={"I_app": 1},
    termination="2.5 V",
    operating_conditions=[current_step],
)

Fixes #4799

Type of change

Please add a line in the relevant section of CHANGELOG.md to document the change (include PR #) - note reverse order of PR #s. If necessary, also add to the list of breaking changes.

  • New feature (non-breaking change which adds functionality)
  • Optimization (back-end change that speeds up the code)
  • Bug fix (non-breaking change which fixes an issue)

Key checklist:

  • No style issues: $ pre-commit run (or $ nox -s pre-commit) (see CONTRIBUTING.md for how to set this up to run automatically when committing locally, in just two lines of code)
  • All tests pass: $ python -m pytest (or $ nox -s tests)
  • The documentation builds: $ python -m pytest --doctest-plus src (or $ nox -s doctests)

You can run integration tests, unit tests, and doctests together at once, using $ nox -s quick.

Further checks:

  • Code is commented, particularly in hard-to-understand areas
  • Tests added that prove fix is effective or that feature works

@valentinsulzer valentinsulzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking this on but this isn't quite what I had in mind, the interface should be:

step = pybamm.step.current(pybamm.InputParameter("I_app"), termination="2.5 V")
experiment = pybamm.Experiment([step])
sim = pybamm.Simulation(..., experiment=experiment)
sim.solve(inputs={"I_app": 1})

@Rishab87

Copy link
Copy Markdown
Member Author

made changes, now user can pass input params like this:

step = pybamm.step.current(pybamm.InputParameter("I_app"), termination="2.5 V")
experiment = pybamm.Experiment([step])
sim = pybamm.Simulation(..., experiment=experiment)
sim.solve(inputs={"I_app": 1})

@codecov

codecov Bot commented Feb 15, 2025

Copy link
Copy Markdown

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.70%. Comparing base (0d5af5c) to head (f21f01a).
Report is 83 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #4826   +/-   ##
========================================
  Coverage    98.70%   98.70%           
========================================
  Files          304      304           
  Lines        23432    23452   +20     
========================================
+ Hits         23129    23149   +20     
  Misses         303      303           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Rishab87
Rishab87 requested a review from a team as a code owner February 16, 2025 06:30
@Rishab87

Copy link
Copy Markdown
Member Author

Just a follow up anything else I need to change?

@MarcBerliner MarcBerliner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rishab87 thanks for putting this PR together! I left a few comments

Comment thread src/pybamm/experiment/step/base_step.py Outdated
Comment thread src/pybamm/experiment/step/base_step.py Outdated
Comment thread src/pybamm/experiment/step/base_step.py Outdated
Comment thread src/pybamm/experiment/step/base_step.py Outdated
Comment thread src/pybamm/experiment/step/base_step.py Outdated
@aabills

aabills commented Feb 18, 2025

Copy link
Copy Markdown
Contributor

The operator is only a property of the termination function. For example, if the termination function is "2.5 V", whether that means that the step terminates when the battery goes above 2.5 V or below 2.5 V is not well defined. The workaround for this in the past was that we could detect whether the battery was charging or discharging based on the current, and to assume that the termination would be hit if the battery goes above the voltage during charge or below during discharge. This is actually the only reason we ever needed to know the direction anyway. In the case that it is an input parameter, we can no longer calculate whether the battery is charging or discharging a priori, so instead, we have to provide an operator to fully define the event.

So for this PR, we need to ensure that any termination has an operator, because we cannot make the assumption. We probably want to keep the string parsing available, so a nice syntax would be "{operator} {value} {unit}", e.g. "< 2.5 V". But the operator must be in the termination, not the step.

@Rishab87

Copy link
Copy Markdown
Member Author

@aabills I've made changes accordingly just as you told now operator gets passed in termination like "< 2.5 V". And thanks for explaining about why we need directions in first place and why we need an operator now it helped me a lot while making changes

@Rishab87
Rishab87 requested a review from aabills February 19, 2025 17:18
@Rishab87

Copy link
Copy Markdown
Member Author

@aabills thanks for the review I've added the callable case and also added few test cases accordingly to ensure full coverage

@Rishab87
Rishab87 requested a review from aabills February 20, 2025 05:42

@aabills aabills left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So close! Just one more change and this is good from my side

Comment thread src/pybamm/experiment/step/base_step.py Outdated
@Rishab87

Copy link
Copy Markdown
Member Author

@aabills I've changed the code and added a check to see if symbol has input params

@Rishab87
Rishab87 requested a review from aabills February 20, 2025 17:32
@aabills

aabills commented Feb 20, 2025

Copy link
Copy Markdown
Contributor

Looks good! Fix coverage and you're good to go from my side. @MarcBerliner @valentinsulzer anything else from y'all?

@aabills

aabills commented Feb 20, 2025

Copy link
Copy Markdown
Contributor

Oh and don't forget to add something to the CHANGELOG.md

@aabills

aabills commented Feb 20, 2025

Copy link
Copy Markdown
Contributor

Also fix this failing integration test.

valentinsulzer
valentinsulzer previously approved these changes Feb 20, 2025

@valentinsulzer valentinsulzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

aabills
aabills previously approved these changes Feb 21, 2025
@aabills
aabills self-requested a review February 21, 2025 00:53
@Rishab87
Rishab87 dismissed stale reviews from aabills and valentinsulzer via 9084495 February 21, 2025 08:50
@Rishab87

Copy link
Copy Markdown
Member Author

@aabills added my PR to changelog and tests for full coverage. Also fixed the integration test

@aabills aabills left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me!

@MarcBerliner MarcBerliner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @Rishab87! Looks great

@MarcBerliner
MarcBerliner enabled auto-merge (squash) February 21, 2025 17:00
@MarcBerliner
MarcBerliner merged commit 651584f into pybamm-team:develop Feb 21, 2025
gaoflow added a commit to gaoflow/PyBaMM that referenced this pull request Jun 5, 2026
…om termination check

When pybamm.step.current/voltage/power/resistance is
called with a Python callable value(t) that genuinely depends on
t, BaseStep.__init__ rewrites self.value as
value(pybamm.t - pybamm.InputParameter('start time')) so that the
runtime start time injected by Simulation can offset time at
solve. That InputParameter is an implementation detail — its name
is reserved by Simulation._START_TIME_INPUT — but
_check_input_params was walking the symbol tree and reporting
True for *any* InputParameter leaf, including this internal one.

That breaks two downstream assumptions:

1. _parse_termination then raises
   ValueError: Termination must include an operator when using
   InputParameter. against plain string terminations like
   '4.3 V' even though the user never passed an InputParameter.
   This is the regression reported in pybamm-team#5018, where code that worked
   in 25.1 stops working in 25.4+ (the operator-or-bust check was
   added by pybamm-team#4826).
2. value_based_charge_or_discharge returns None for every
   callable-driven step, so direction inference silently goes away.

The fix narrows _check_input_params to user-supplied
InputParameters by filtering out leaves whose name is 'start time'.
Genuine user inputs (e.g. pybamm.InputParameter('I_app') or
I_coeff * pybamm.t) still trigger the check, so the operator
requirement introduced by pybamm-team#4826 is preserved.

Tests cover the helper directly, both branches of the filter
(internal-only vs mixed with a user input), the operator-free string
termination path, the [CustomTermination, '4.3 V'] shape from
the OP's reproducer, the restored direction inference, and a
non-regression on the existing 'must include an operator' guard for
true InputParameter values.
gaoflow added a commit to gaoflow/PyBaMM that referenced this pull request Jun 9, 2026
…om termination check

When pybamm.step.current/voltage/power/resistance is
called with a Python callable value(t) that genuinely depends on
t, BaseStep.__init__ rewrites self.value as
value(pybamm.t - pybamm.InputParameter('start time')) so that the
runtime start time injected by Simulation can offset time at
solve. That InputParameter is an implementation detail — its name
is reserved by Simulation._START_TIME_INPUT — but
_check_input_params was walking the symbol tree and reporting
True for *any* InputParameter leaf, including this internal one.

That breaks two downstream assumptions:

1. _parse_termination then raises
   ValueError: Termination must include an operator when using
   InputParameter. against plain string terminations like
   '4.3 V' even though the user never passed an InputParameter.
   This is the regression reported in pybamm-team#5018, where code that worked
   in 25.1 stops working in 25.4+ (the operator-or-bust check was
   added by pybamm-team#4826).
2. value_based_charge_or_discharge returns None for every
   callable-driven step, so direction inference silently goes away.

The fix narrows _check_input_params to user-supplied
InputParameters by filtering out leaves whose name is 'start time'.
Genuine user inputs (e.g. pybamm.InputParameter('I_app') or
I_coeff * pybamm.t) still trigger the check, so the operator
requirement introduced by pybamm-team#4826 is preserved.

Tests cover the helper directly, both branches of the filter
(internal-only vs mixed with a user input), the operator-free string
termination path, the [CustomTermination, '4.3 V'] shape from
the OP's reproducer, the restored direction inference, and a
non-regression on the existing 'must include an operator' guard for
true InputParameter values.
gaoflow added a commit to gaoflow/PyBaMM that referenced this pull request Jun 12, 2026
…om termination check

When pybamm.step.current/voltage/power/resistance is
called with a Python callable value(t) that genuinely depends on
t, BaseStep.__init__ rewrites self.value as
value(pybamm.t - pybamm.InputParameter('start time')) so that the
runtime start time injected by Simulation can offset time at
solve. That InputParameter is an implementation detail — its name
is reserved by Simulation._START_TIME_INPUT — but
_check_input_params was walking the symbol tree and reporting
True for *any* InputParameter leaf, including this internal one.

That breaks two downstream assumptions:

1. _parse_termination then raises
   ValueError: Termination must include an operator when using
   InputParameter. against plain string terminations like
   '4.3 V' even though the user never passed an InputParameter.
   This is the regression reported in pybamm-team#5018, where code that worked
   in 25.1 stops working in 25.4+ (the operator-or-bust check was
   added by pybamm-team#4826).
2. value_based_charge_or_discharge returns None for every
   callable-driven step, so direction inference silently goes away.

The fix narrows _check_input_params to user-supplied
InputParameters by filtering out leaves whose name is 'start time'.
Genuine user inputs (e.g. pybamm.InputParameter('I_app') or
I_coeff * pybamm.t) still trigger the check, so the operator
requirement introduced by pybamm-team#4826 is preserved.

Tests cover the helper directly, both branches of the filter
(internal-only vs mixed with a user input), the operator-free string
termination path, the [CustomTermination, '4.3 V'] shape from
the OP's reproducer, the restored direction inference, and a
non-regression on the existing 'must include an operator' guard for
true InputParameter values.
gaoflow added a commit to gaoflow/PyBaMM that referenced this pull request Jun 18, 2026
…om termination check

When pybamm.step.current/voltage/power/resistance is
called with a Python callable value(t) that genuinely depends on
t, BaseStep.__init__ rewrites self.value as
value(pybamm.t - pybamm.InputParameter('start time')) so that the
runtime start time injected by Simulation can offset time at
solve. That InputParameter is an implementation detail — its name
is reserved by Simulation._START_TIME_INPUT — but
_check_input_params was walking the symbol tree and reporting
True for *any* InputParameter leaf, including this internal one.

That breaks two downstream assumptions:

1. _parse_termination then raises
   ValueError: Termination must include an operator when using
   InputParameter. against plain string terminations like
   '4.3 V' even though the user never passed an InputParameter.
   This is the regression reported in pybamm-team#5018, where code that worked
   in 25.1 stops working in 25.4+ (the operator-or-bust check was
   added by pybamm-team#4826).
2. value_based_charge_or_discharge returns None for every
   callable-driven step, so direction inference silently goes away.

The fix narrows _check_input_params to user-supplied
InputParameters by filtering out leaves whose name is 'start time'.
Genuine user inputs (e.g. pybamm.InputParameter('I_app') or
I_coeff * pybamm.t) still trigger the check, so the operator
requirement introduced by pybamm-team#4826 is preserved.

Tests cover the helper directly, both branches of the filter
(internal-only vs mixed with a user input), the operator-free string
termination path, the [CustomTermination, '4.3 V'] shape from
the OP's reproducer, the restored direction inference, and a
non-regression on the existing 'must include an operator' guard for
true InputParameter values.
gaoflow added a commit to gaoflow/PyBaMM that referenced this pull request Jul 31, 2026
…om termination check

When pybamm.step.current/voltage/power/resistance is
called with a Python callable value(t) that genuinely depends on
t, BaseStep.__init__ rewrites self.value as
value(pybamm.t - pybamm.InputParameter('start time')) so that the
runtime start time injected by Simulation can offset time at
solve. That InputParameter is an implementation detail — its name
is reserved by Simulation._START_TIME_INPUT — but
_check_input_params was walking the symbol tree and reporting
True for *any* InputParameter leaf, including this internal one.

That breaks two downstream assumptions:

1. _parse_termination then raises
   ValueError: Termination must include an operator when using
   InputParameter. against plain string terminations like
   '4.3 V' even though the user never passed an InputParameter.
   This is the regression reported in pybamm-team#5018, where code that worked
   in 25.1 stops working in 25.4+ (the operator-or-bust check was
   added by pybamm-team#4826).
2. value_based_charge_or_discharge returns None for every
   callable-driven step, so direction inference silently goes away.

The fix narrows _check_input_params to user-supplied
InputParameters by filtering out leaves whose name is 'start time'.
Genuine user inputs (e.g. pybamm.InputParameter('I_app') or
I_coeff * pybamm.t) still trigger the check, so the operator
requirement introduced by pybamm-team#4826 is preserved.

Tests cover the helper directly, both branches of the filter
(internal-only vs mixed with a user input), the operator-free string
termination path, the [CustomTermination, '4.3 V'] shape from
the OP's reproducer, the restored direction inference, and a
non-regression on the existing 'must include an operator' guard for
true InputParameter values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use InputParameter in pybamm experiment

6 participants