Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Summary variables calculated only when called #4621

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

## Breaking changes

- Summary variables now calculated only when called, accessed via a class in the same manner as other variables rather than a dictionary. ([#4621](https://github.com/pybamm-team/PyBaMM/pull/4621))
- The conda distribution (`pybamm`) now installs all optional dependencies available on conda-forge. Use the new `pybamm-base` conda
package to install PyBaMM with only the required dependencies. ([conda-forge/pybamm-feedstock#70](https://github.com/conda-forge/pybamm-feedstock/pull/70))
- Separated extrapolation options for `pybamm.BoundaryValue` and `pybamm.BoundaryGradient`, and updated the default to be "linear" for the value and "quadratic" for the gradient. ([#4614](https://github.com/pybamm-team/PyBaMM/pull/4614))
Expand Down
1 change: 1 addition & 0 deletions docs/source/api/solvers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Solvers
algebraic_solvers
solution
processed_variable
summary_variables
5 changes: 5 additions & 0 deletions docs/source/api/solvers/summary_variables.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Summary Variables
======================

.. autoclass:: pybamm.SummaryVariables
:members:
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"id": "right-skiing",
"metadata": {},
"outputs": [
Expand Down Expand Up @@ -638,7 +638,7 @@
}
],
"source": [
"sorted(sol.summary_variables.keys())"
"sorted(sol.summary_variables.all_variables)"
]
},
{
Expand Down Expand Up @@ -1936,7 +1936,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "venv",
"language": "python",
"name": "python3"
},
Expand All @@ -1950,7 +1950,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
"version": "3.11.10"
},
"toc": {
"base_numbering": 1,
Expand All @@ -1964,11 +1964,6 @@
"toc_position": {},
"toc_section_display": true,
"toc_window_display": true
},
"vscode": {
"interpreter": {
"hash": "612adcc456652826e82b485a1edaef831aa6d5abc680d008e93d513dd8724f14"
}
}
},
"nbformat": 4,
Expand Down
1 change: 1 addition & 0 deletions src/pybamm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
from .solvers.processed_variable_time_integral import ProcessedVariableTimeIntegral
from .solvers.processed_variable import ProcessedVariable, process_variable
from .solvers.processed_variable_computed import ProcessedVariableComputed
from .solvers.summary_variable import SummaryVariables
from .solvers.base_solver import BaseSolver
from .solvers.dummy_solver import DummySolver
from .solvers.algebraic_solver import AlgebraicSolver
Expand Down
2 changes: 1 addition & 1 deletion src/pybamm/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def on_cycle_end(self, logs):

voltage_stop = logs["stopping conditions"]["voltage"]
if voltage_stop is not None:
min_voltage = logs["summary variables"]["Minimum voltage [V]"]
min_voltage = logs["Minimum voltage [V]"]
if min_voltage > voltage_stop[0]:
self.logger.notice(
f"Minimum voltage is now {min_voltage:.3f} V "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,27 @@ def __init__(
self.__get_electrode_soh_sims_split
)

def __getstate__(self):
"""
Return dictionary of picklable items
"""
result = self.__dict__.copy()
result["_get_electrode_soh_sims_full"] = None # Exclude LRU cache
result["_get_electrode_soh_sims_split"] = None # Exclude LRU cache
return result

def __setstate__(self, state):
"""
Unpickle, restoring unpicklable relationships
"""
self.__dict__ = state
self._get_electrode_soh_sims_full = lru_cache()(
self.__get_electrode_soh_sims_full
)
self._get_electrode_soh_sims_split = lru_cache()(
self.__get_electrode_soh_sims_split
)

def _get_lims_ocp(self):
parameter_values = self.parameter_values

Expand Down
4 changes: 2 additions & 2 deletions src/pybamm/plotting/plot_summary_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ def plot_summary_variables(
for solution in solutions:
# plot summary variable v/s cycle number
ax.plot(
solution.summary_variables["Cycle number"],
solution.summary_variables.cycle_number,
solution.summary_variables[var],
)
# label the axes
ax.set_xlabel("Cycle number")
ax.set_ylabel(var)
ax.set_xlim([1, solution.summary_variables["Cycle number"][-1]])
ax.set_xlim([1, solution.summary_variables.cycle_number[-1]])

fig.tight_layout()

Expand Down
4 changes: 2 additions & 2 deletions src/pybamm/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ def solve(
# See PR #3995
if voltage_stop is not None:
min_voltage = np.min(cycle_solution["Battery voltage [V]"].data)
logs["summary variables"]["Minimum voltage [V]"] = min_voltage
logs["Minimum voltage [V]"] = min_voltage

callbacks.on_cycle_end(logs)

Expand All @@ -941,7 +941,7 @@ def solve(

if self._solution is not None and len(all_cycle_solutions) > 0:
self._solution.cycles = all_cycle_solutions
self._solution.set_summary_variables(all_summary_variables)
self._solution.update_summary_variables(all_summary_variables)
self._solution.all_first_states = all_first_states

callbacks.on_experiment_end(logs)
Expand Down
59 changes: 5 additions & 54 deletions src/pybamm/solvers/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,16 +563,10 @@ def initial_start_time(self, value):
"""Updates the initial start time of the experiment"""
self._initial_start_time = value

def set_summary_variables(self, all_summary_variables):
summary_variables = {var: [] for var in all_summary_variables[0]}
for sum_vars in all_summary_variables:
for name, value in sum_vars.items():
summary_variables[name].append(value)

summary_variables["Cycle number"] = range(1, len(all_summary_variables) + 1)
def update_summary_variables(self, all_summary_variables):
self.all_summary_variables = all_summary_variables
self._summary_variables = pybamm.FuzzyDict(
{name: np.array(value) for name, value in summary_variables.items()}
self._summary_variables = pybamm.SummaryVariables(
self, cycle_summary_variables=all_summary_variables
)

def update(self, variables):
Expand Down Expand Up @@ -1142,8 +1136,8 @@ def make_cycle_solution(

cycle_solution.steps = step_solutions

cycle_summary_variables = _get_cycle_summary_variables(
cycle_solution, esoh_solver, user_inputs=inputs
cycle_summary_variables = pybamm.SummaryVariables(
cycle_solution, esoh_solver=esoh_solver, user_inputs=inputs
)

cycle_first_state = cycle_solution.first_state
Expand All @@ -1154,46 +1148,3 @@ def make_cycle_solution(
cycle_solution = None

return cycle_solution, cycle_summary_variables, cycle_first_state


def _get_cycle_summary_variables(cycle_solution, esoh_solver, user_inputs=None):
user_inputs = user_inputs or {}
model = cycle_solution.all_models[0]
cycle_summary_variables = pybamm.FuzzyDict({})

# Summary variables
summary_variables = model.summary_variables
first_state = cycle_solution.first_state
last_state = cycle_solution.last_state
for var in summary_variables:
data_first = first_state[var].data
data_last = last_state[var].data
cycle_summary_variables[var] = data_last[0]
var_lowercase = var[0].lower() + var[1:]
cycle_summary_variables["Change in " + var_lowercase] = (
data_last[0] - data_first[0]
)

# eSOH variables (full-cell lithium-ion model only, for now)
if (
esoh_solver is not None
and isinstance(model, pybamm.lithium_ion.BaseModel)
and model.options.electrode_types["negative"] == "porous"
and "Negative electrode capacity [A.h]" in model.variables
and "Positive electrode capacity [A.h]" in model.variables
):
Q_n = last_state["Negative electrode capacity [A.h]"].data[0]
Q_p = last_state["Positive electrode capacity [A.h]"].data[0]
Q_Li = last_state["Total lithium capacity in particles [A.h]"].data[0]
all_inputs = {**user_inputs, "Q_n": Q_n, "Q_p": Q_p, "Q_Li": Q_Li}
try:
esoh_sol = esoh_solver.solve(inputs=all_inputs)
except pybamm.SolverError as error: # pragma: no cover
raise pybamm.SolverError(
"Could not solve for summary variables, run "
"`sim.solve(calc_esoh=False)` to skip this step"
) from error

cycle_summary_variables.update(esoh_sol)

return cycle_summary_variables
Loading
Loading