Skip to content

Commit 5024850

Browse files
committed
Initial Implementation
1 parent 8b33589 commit 5024850

File tree

8 files changed

+272
-31
lines changed

8 files changed

+272
-31
lines changed

noxfile.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,19 @@ def run_tests(session):
141141
set_environment_variables(PYBAMM_ENV, session=session)
142142
session.install("setuptools", silent=False)
143143
session.install("-e", ".[all,dev,jax]", silent=False)
144+
warning_flags = [
145+
"-W",
146+
"error::DeprecationWarning",
147+
"-W",
148+
"error::PendingDeprecationWarning",
149+
"-W",
150+
"error::FutureWarning",
151+
]
144152
session.run(
145153
"python",
146154
"-m",
147155
"pytest",
156+
*warning_flags,
148157
*(session.posargs if session.posargs else ["-m", "unit or integration"]),
149158
)
150159

src/pybamm/expression_tree/symbol.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#
44
from __future__ import annotations
55
import numbers
6-
import warnings
76

87
import numpy as np
98
import sympy
@@ -15,6 +14,7 @@
1514
import pybamm
1615
from pybamm.util import import_optional_dependency
1716
from pybamm.expression_tree.printing.print_name import prettify_print_name
17+
from utils import deprecate_function
1818

1919
if TYPE_CHECKING: # pragma: no cover
2020
import casadi
@@ -356,6 +356,9 @@ def domain(self, domain):
356356
)
357357

358358
@property
359+
@deprecate_function(
360+
msg="symbol.auxiliary_domains has been deprecated, use symbol.domains instead"
361+
)
359362
def auxiliary_domains(self):
360363
"""Returns auxiliary domains."""
361364
raise NotImplementedError(
@@ -994,18 +997,20 @@ def create_copy(
994997
children = self._children_for_copying(new_children)
995998
return self.__class__(self.name, children, domains=self.domains)
996999

1000+
# Assuming `deprecate_function` is imported from deprecation_decorators
1001+
1002+
@deprecate_function(
1003+
version="2.0.0",
1004+
msg="The 'new_copy' function for expression tree symbols is deprecated, use 'create_copy' instead.",
1005+
)
9971006
def new_copy(
9981007
self,
9991008
new_children: list[Symbol] | None = None,
10001009
perform_simplifications: bool = True,
10011010
):
1002-
""" """
1003-
warnings.warn(
1004-
"The 'new_copy' function for expression tree symbols is deprecated, use "
1005-
"'create_copy' instead.",
1006-
DeprecationWarning,
1007-
stacklevel=2,
1008-
)
1011+
"""
1012+
This function is deprecated. Use 'create_copy' instead.
1013+
"""
10091014
return self.create_copy(new_children, perform_simplifications)
10101015

10111016
@cached_property

src/pybamm/parameters/parameter_values.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pprint import pformat
55
from warnings import warn
66
from collections import defaultdict
7+
from utils import deprecate_multiple_renamedParameters
78

89

910
class ParameterValues:
@@ -417,18 +418,24 @@ def set_initial_ocps(
417418
return parameter_values
418419

419420
@staticmethod
421+
@deprecate_multiple_renamedParameters(
422+
{
423+
"propotional term": "... proportional term [s-1]",
424+
"1 + dlnf/dlnc": "Thermodynamic factor",
425+
"electrode diffusivity": "particle diffusivity",
426+
}
427+
)
420428
def check_parameter_values(values):
421429
for param in list(values.keys()):
422430
if "propotional term" in param:
423431
raise ValueError(
424432
f"The parameter '{param}' has been renamed to "
425433
"'... proportional term [s-1]', and its value should now be divided"
426-
"by 3600 to get the same results as before."
434+
" by 3600 to get the same results as before."
427435
)
428-
# specific check for renamed parameter "1 + dlnf/dlnc"
429436
if "1 + dlnf/dlnc" in param:
430437
raise ValueError(
431-
f"parameter '{param}' has been renamed to 'Thermodynamic factor'"
438+
f"The parameter '{param}' has been renamed to 'Thermodynamic factor'"
432439
)
433440
if "electrode diffusivity" in param:
434441
new_param = param.replace("electrode", "particle")

src/pybamm/simulation.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from datetime import timedelta
99
import pybamm.telemetry
1010
from pybamm.util import import_optional_dependency
11+
from utils import deprecate_function
1112

1213
from pybamm.expression_tree.operations.serialise import Serialise
1314

@@ -171,7 +172,11 @@ def _set_random_seed(self):
171172
% (2**32)
172173
)
173174

175+
@deprecate_function(
176+
msg="pybamm.simulation.set_up_and_parameterise_experiment is deprecated and not meant to be accessed by users."
177+
)
174178
def set_up_and_parameterise_experiment(self, solve_kwargs=None):
179+
"""Sets up and parameterizes the experiment."""
175180
msg = "pybamm.simulation.set_up_and_parameterise_experiment is deprecated and not meant to be accessed by users."
176181
warnings.warn(msg, DeprecationWarning, stacklevel=2)
177182
self._set_up_and_parameterise_experiment(solve_kwargs=solve_kwargs)
@@ -254,12 +259,17 @@ def _set_up_and_parameterise_experiment(self, solve_kwargs=None):
254259
parameterised_model
255260
)
256261

262+
@deprecate_function(
263+
version="2.0.0",
264+
msg="pybamm.set_parameters is deprecated and not meant to be accessed by users.",
265+
)
257266
def set_parameters(self):
267+
"""Sets the parameters."""
258268
msg = (
259269
"pybamm.set_parameters is deprecated and not meant to be accessed by users."
260270
)
261271
warnings.warn(msg, DeprecationWarning, stacklevel=2)
262-
self._set_parameters()
272+
self._set_parameters() # Call the internal method
263273

264274
def _set_parameters(self):
265275
"""

src/pybamm/solvers/base_solver.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import pybamm
1414
from pybamm.expression_tree.binary_operators import _Heaviside
1515
from pybamm import ParameterValues
16+
from utils import deprecated_params
1617

1718

1819
class BaseSolver:
@@ -1162,6 +1163,14 @@ def process_t_interp(self, t_interp):
11621163

11631164
return t_interp
11641165

1166+
@deprecated_params(
1167+
{
1168+
"npts": (
1169+
"t_eval",
1170+
"The 'npts' parameter is deprecated, use 't_eval' instead.",
1171+
)
1172+
}
1173+
)
11651174
def step(
11661175
self,
11671176
old_solution,
@@ -1199,12 +1208,6 @@ def step(
11991208
Save solution with all previous timesteps. Defaults to True.
12001209
calculate_sensitivities : list of str or bool, optional
12011210
Whether the solver calculates sensitivities of all input parameters. Defaults to False.
1202-
If only a subset of sensitivities are required, can also pass a
1203-
list of input parameter names. **Limitations**: sensitivities are not calculated up to numerical tolerances
1204-
so are not guarenteed to be within the tolerances set by the solver, please raise an issue if you
1205-
require this functionality. Also, when using this feature with `pybamm.Experiment`, the sensitivities
1206-
do not take into account the movement of step-transitions wrt input parameters, so do not use this feature
1207-
if the timings of your experimental protocol change rapidly with respect to your input parameters.
12081211
t_interp : None, list or ndarray, optional
12091212
The times (in seconds) at which to interpolate the solution. Defaults to None.
12101213
Only valid for solvers that support intra-solve interpolation (`IDAKLUSolver`).
@@ -1223,31 +1226,20 @@ def step(
12231226
or old_solution.termination == "final time"
12241227
or "[experiment]" in old_solution.termination
12251228
):
1226-
# Return same solution as an event has already been triggered
1227-
# With hack to allow stepping past experiment current / voltage cut-off
12281229
return old_solution
12291230

1230-
# Make sure model isn't empty
12311231
self._check_empty_model(model)
12321232

1233-
# Make sure dt is greater than zero
12341233
if dt <= 0:
12351234
raise pybamm.SolverError("Step time must be >0")
12361235

1237-
# Raise deprecation warning for npts and convert it to t_eval
1238-
if npts is not None:
1239-
warnings.warn(
1240-
"The 'npts' parameter is deprecated, use 't_eval' instead.",
1241-
DeprecationWarning,
1242-
stacklevel=2,
1243-
)
1244-
t_eval = np.linspace(0, dt, npts)
1245-
elif t_eval is None:
1236+
if t_eval is None:
12461237
t_eval = np.array([0, dt])
12471238
elif t_eval[0] != 0 or t_eval[-1] != dt:
12481239
raise pybamm.SolverError(
12491240
"Elements inside array t_eval must lie in the closed interval 0 to dt"
12501241
)
1242+
12511243
else:
12521244
pass
12531245

utils/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .decorators import *

utils/decorators.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import functools
2+
import warnings
3+
from .exceptions import DeprecatedFunctionWarning
4+
5+
6+
def deprecate_function(func=None, version=None, msg=None):
7+
"""
8+
A decorator to mark a function as deprecated.
9+
10+
Parameters:
11+
- func: The function to decorate. If no function is provided, the decorator will be used as a factory.
12+
- version: The version in which the function was deprecated.
13+
- msg: Custom message to display alongside the deprecation warning.
14+
15+
If no message is provided, a default message is used.
16+
"""
17+
18+
def decorator(func):
19+
@functools.wraps(func)
20+
def wrapper(*args, **kwargs):
21+
# Construct the warning message
22+
message = (
23+
msg
24+
or f"Function '{func.__name__}' is deprecated and will be removed in future versions."
25+
)
26+
if version:
27+
message += f" Deprecated since version {version}."
28+
29+
# Raise the deprecation warning
30+
warnings.warn(message, category=DeprecatedFunctionWarning, stacklevel=2)
31+
32+
return func(*args, **kwargs)
33+
34+
return wrapper
35+
36+
# If no function is passed (when used as a decorator with parameters)
37+
if func is None:
38+
return decorator
39+
else:
40+
return decorator(func)
41+
42+
43+
def deprecate_multiple_renamedParameters(param_dict: dict):
44+
"""
45+
Decorator to handle deprecated parameter names dynamically, issuing warnings when old
46+
parameter names are found and replacing them with the new ones provided in the param_dict.
47+
param_dict is a dictionary mapping old parameter names to new parameter names.
48+
"""
49+
50+
def decorator(func):
51+
@functools.wraps(func)
52+
def wrapper(self, values, *args, **kwargs):
53+
# Iterate over the old-to-new parameter mapping
54+
for old_param, new_param in param_dict.items():
55+
if old_param in values:
56+
# Issue a deprecation warning and update the parameter
57+
warnings.warn(
58+
f"The parameter '{old_param}' has been renamed to '{new_param}'",
59+
DeprecationWarning,
60+
stacklevel=2,
61+
)
62+
values[new_param] = values.pop(old_param)
63+
# Call the original function with the updated values
64+
return func(self, values, *args, **kwargs)
65+
66+
return wrapper
67+
68+
return decorator
69+
70+
71+
def deprecated_params(param_map):
72+
"""
73+
A decorator to handle deprecated parameters in a function.
74+
75+
Parameters
76+
----------
77+
param_map : dict
78+
A dictionary mapping deprecated parameter names to a tuple containing the
79+
new parameter name (or None if it's removed) and a message explaining the deprecation.
80+
81+
Example
82+
-------
83+
@handle_deprecated_params({
84+
'npts': ('t_eval', "The 'npts' parameter is deprecated, use 't_eval' instead.")
85+
})
86+
def step(...):
87+
...
88+
"""
89+
90+
def decorator(func):
91+
@functools.wraps(func)
92+
def wrapper(*args, **kwargs):
93+
for deprecated_param, (new_param, message) in param_map.items():
94+
if deprecated_param in kwargs:
95+
warnings.warn(message, DeprecationWarning, stacklevel=2)
96+
if new_param:
97+
kwargs[new_param] = kwargs.pop(deprecated_param)
98+
return func(*args, **kwargs)
99+
100+
return wrapper
101+
102+
return decorator

0 commit comments

Comments
 (0)