Skip to content

Commit 71b68ee

Browse files
#709 allow current to be input parameter
1 parent 5a707af commit 71b68ee

File tree

10 files changed

+142
-140
lines changed

10 files changed

+142
-140
lines changed

examples/notebooks/change-input-current.ipynb

+7-10
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@
4646
"param = model.default_parameter_values\n",
4747
"\n",
4848
"# change the current function to be an input parameter\n",
49-
"def current_function(t):\n",
50-
" return pybamm.InputParameter(\"current\")\n",
51-
"\n",
52-
"param[\"Current function [A]\"] = current_function"
49+
"param[\"Current function [A]\"] = \"[input]\""
5350
]
5451
},
5552
{
@@ -69,7 +66,7 @@
6966
{
7067
"data": {
7168
"application/vnd.jupyter.widget-view+json": {
72-
"model_id": "839ef921550749ecaae748a2068ee9cc",
69+
"model_id": "770ba7f159054c5bad11038ac7be3f72",
7370
"version_major": 2,
7471
"version_minor": 0
7572
},
@@ -97,7 +94,7 @@
9794
"solver = model.default_solver\n",
9895
"n = 300\n",
9996
"t_eval = np.linspace(0, 0.02, n)\n",
100-
"solution = solver.solve(model, t_eval, inputs={\"current\": 16})\n",
97+
"solution = solver.solve(model, t_eval, inputs={\"Current function [A]\": 16})\n",
10198
"\n",
10299
"# plot\n",
103100
"quick_plot = pybamm.QuickPlot(solution)\n",
@@ -121,7 +118,7 @@
121118
{
122119
"data": {
123120
"application/vnd.jupyter.widget-view+json": {
124-
"model_id": "cfb285a7877c4853ae7144891b38e4cd",
121+
"model_id": "4625a91d401b456d8e43aae201f4a380",
125122
"version_major": 2,
126123
"version_minor": 0
127124
},
@@ -135,7 +132,7 @@
135132
],
136133
"source": [
137134
"# Solve the model at the given time points\n",
138-
"solution = solver.solve(model, t_eval, inputs={\"current\": 0})\n",
135+
"solution = solver.solve(model, t_eval, inputs={\"Current function [A]\": 0})\n",
139136
"\n",
140137
"# plot\n",
141138
"quick_plot = pybamm.QuickPlot(solution)\n",
@@ -161,7 +158,7 @@
161158
{
162159
"data": {
163160
"application/vnd.jupyter.widget-view+json": {
164-
"model_id": "d31307d03a2b4082a5ad7b4d91f85823",
161+
"model_id": "88c9c957b666420e9cf6f615ff43817c",
165162
"version_major": 2,
166163
"version_minor": 0
167164
},
@@ -285,7 +282,7 @@
285282
{
286283
"data": {
287284
"application/vnd.jupyter.widget-view+json": {
288-
"model_id": "bb1a66bff842443cb81abb44a4b4a6a1",
285+
"model_id": "a8b90dfe860644c68af15c7c07e3adeb",
289286
"version_major": 2,
290287
"version_minor": 0
291288
},

examples/notebooks/change-settings.ipynb

+47-59
Large diffs are not rendered by default.

examples/notebooks/compare-comsol-discharge-curve.ipynb

+4-7
Large diffs are not rendered by default.

examples/notebooks/models/compare-lithium-ion.ipynb

+10-14
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
{
105105
"data": {
106106
"text/plain": [
107-
"<pybamm.models.full_battery_models.lithium_ion.dfn.DFN at 0x10597e518>"
107+
"<pybamm.models.full_battery_models.lithium_ion.dfn.DFN at 0x109dcd710>"
108108
]
109109
},
110110
"execution_count": 4,
@@ -153,11 +153,7 @@
153153
"outputs": [],
154154
"source": [
155155
"param = dfn.default_parameter_values\n",
156-
"\n",
157-
"def current_function(t):\n",
158-
" return pybamm.InputParameter(\"current\")\n",
159-
"\n",
160-
"param[\"Current function [A]\"] = current_function"
156+
"param[\"Current function [A]\"] = \"[input]\""
161157
]
162158
},
163159
{
@@ -253,9 +249,9 @@
253249
"name": "stdout",
254250
"output_type": "stream",
255251
"text": [
256-
"Solved the Doyle-Fuller-Newman model in 2.111 seconds\n",
257-
"Solved the Single Particle Model in 0.386 seconds\n",
258-
"Solved the Single Particle Model with electrolyte in 0.399 seconds\n"
252+
"Solved the Doyle-Fuller-Newman model in 2.609 seconds\n",
253+
"Solved the Single Particle Model in 0.462 seconds\n",
254+
"Solved the Single Particle Model with electrolyte in 0.491 seconds\n"
259255
]
260256
}
261257
],
@@ -266,7 +262,7 @@
266262
"solver = pybamm.CasadiSolver()\n",
267263
"for model_name, model in models.items():\n",
268264
" start = timer.time()\n",
269-
" solution = solver.solve(model, t_eval, inputs={\"current\": 1})\n",
265+
" solution = solver.solve(model, t_eval, inputs={\"Current function [A]\": 1})\n",
270266
" end = timer.time()\n",
271267
" print(\"Solved the {} in {:.3f} seconds\".format(model.name, end-start))\n",
272268
" solutions[model_name] = solution"
@@ -349,7 +345,7 @@
349345
{
350346
"data": {
351347
"application/vnd.jupyter.widget-view+json": {
352-
"model_id": "af31d03838e4456aac24954eb1b5d0df",
348+
"model_id": "36cafdf1324c44b19fa3bf54a8e579cb",
353349
"version_major": 2,
354350
"version_minor": 0
355351
},
@@ -371,7 +367,7 @@
371367
"cell_type": "markdown",
372368
"metadata": {},
373369
"source": [
374-
"# A note on changing parameters:"
370+
"# Changing parameters"
375371
]
376372
},
377373
{
@@ -389,7 +385,7 @@
389385
{
390386
"data": {
391387
"application/vnd.jupyter.widget-view+json": {
392-
"model_id": "7226178875b24a0eacb8c38ab1c4fafc",
388+
"model_id": "fc6e5fae66414fdda8e177864e49cb02",
393389
"version_major": 2,
394390
"version_minor": 0
395391
},
@@ -404,7 +400,7 @@
404400
"source": [
405401
"# update parameter values and solve again\n",
406402
"for model_name, model in models.items():\n",
407-
" solutions[model_name] = model.default_solver.solve(model, t_eval, inputs={\"current\": 5})\n",
403+
" solutions[model_name] = model.default_solver.solve(model, t_eval, inputs={\"Current function [A]\": 5})\n",
408404
"\n",
409405
"# Plot\n",
410406
"list_of_models = list(models.values())\n",

examples/notebooks/models/lead-acid.ipynb

+8-10
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,8 @@
219219
"models = [loqs, composite, full]\n",
220220
"\n",
221221
"# process parameters\n",
222-
"def current_function(t):\n",
223-
" return pybamm.InputParameter(\"current\")\n",
224222
"param = models[0].default_parameter_values\n",
225-
"param[\"Current function [A]\"] = current_function\n",
223+
"param[\"Current function [A]\"] = \"[input]\"\n",
226224
"for model in models:\n",
227225
" param.process_model(model)"
228226
]
@@ -267,9 +265,9 @@
267265
"name": "stdout",
268266
"output_type": "stream",
269267
"text": [
270-
"Solved the LOQS model in 0.133 seconds\n",
271-
"Solved the Composite model in 1.034 seconds\n",
272-
"Solved the Full model in 1.187 seconds\n"
268+
"Solved the LOQS model in 0.127 seconds\n",
269+
"Solved the Composite model in 1.075 seconds\n",
270+
"Solved the Full model in 1.143 seconds\n"
273271
]
274272
}
275273
],
@@ -280,7 +278,7 @@
280278
"solver = pybamm.CasadiSolver()\n",
281279
"for model in models:\n",
282280
" start = timer.time()\n",
283-
" solution = solver.solve(model, t_eval, inputs={\"current\": 1})\n",
281+
" solution = solver.solve(model, t_eval, inputs={\"Current function [A]\": 1})\n",
284282
" end = timer.time()\n",
285283
" print(\"Solved the {} in {:.3f} seconds\".format(model.name, end-start))\n",
286284
" solutions[model] = solution"
@@ -345,7 +343,7 @@
345343
{
346344
"data": {
347345
"application/vnd.jupyter.widget-view+json": {
348-
"model_id": "6145d7740fa04796aa4dae9bb09c125e",
346+
"model_id": "a08ab3900db7448f81089148ae3ee749",
349347
"version_major": 2,
350348
"version_minor": 0
351349
},
@@ -381,7 +379,7 @@
381379
{
382380
"data": {
383381
"application/vnd.jupyter.widget-view+json": {
384-
"model_id": "3578ee915f79432c931ffecf4b543c1b",
382+
"model_id": "71e4761492ee47d6836cb51fd0882812",
385383
"version_major": 2,
386384
"version_minor": 0
387385
},
@@ -395,7 +393,7 @@
395393
],
396394
"source": [
397395
"for model in models:\n",
398-
" solutions[model] = solver.solve(model, t_eval, inputs={\"current\": 20})\n",
396+
" solutions[model] = solver.solve(model, t_eval, inputs={\"Current function [A]\": 20})\n",
399397
"\n",
400398
"# Plot\n",
401399
"solution_values = [solutions[model] for model in models]\n",

examples/scripts/compare_comsol/discharge_curve.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,10 @@
1616

1717

1818
# load parameters and process model and geometry
19-
def current_function(t):
20-
return pybamm.InputParameter("current")
21-
22-
2319
param = model.default_parameter_values
2420
param["Electrode width [m]"] = 1
2521
param["Electrode height [m]"] = 1
26-
param["Current function [A]"] = current_function
22+
param["Current function [A]"] = "[input]"
2723
param.process_model(model)
2824
param.process_geometry(geometry)
2925

@@ -72,7 +68,7 @@ def current_function(t):
7268
# solve model at comsol times
7369
t = comsol_time / tau
7470
solution = pybamm.CasadiSolver(mode="fast").solve(
75-
model, t, inputs={"current": current}
71+
model, t, inputs={"Current function [A]": current}
7672
)
7773

7874
# discharge capacity

pybamm/parameters/parameter_values.py

+23-6
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ def check_and_update_parameter_values(self, values):
278278
data = values["C-rate"][1]
279279
data[:, 1] = data[:, 1] * capacity
280280
value = (values["C-rate"][0] + "_to_Crate", data)
281+
elif values["C-rate"] == "[input]":
282+
value = CrateToCurrent(values["C-rate"], capacity, typ="input")
281283
else:
282284
value = values["C-rate"] * capacity
283285
self._dict_items["Current function [A]"] = value
@@ -288,6 +290,10 @@ def check_and_update_parameter_values(self, values):
288290
data = values["Current function [A]"][1]
289291
data[:, 1] = data[:, 1] / capacity
290292
value = (values["Current function [A]"][0] + "_to_current", data)
293+
elif values["Current function [A]"] == "[input]":
294+
value = CurrentToCrate(
295+
values["Current function [A]"], capacity, typ="input"
296+
)
291297
else:
292298
value = values["Current function [A]"] / capacity
293299
self._dict_items["C-rate"] = value
@@ -472,6 +478,9 @@ def _process_symbol(self, symbol):
472478
function = pybamm.Scalar(
473479
function_name, name=symbol.name
474480
) * pybamm.ones_like(*new_children)
481+
elif isinstance(function_name, pybamm.InputParameter):
482+
# Replace the function with an input parameter
483+
function = function_name
475484
else:
476485
# otherwise evaluate the function to create a new PyBaMM object
477486
function = function_name(*new_children)
@@ -547,20 +556,28 @@ def evaluate(self, symbol):
547556
class CurrentToCrate:
548557
"Convert a current function to a C-rate function"
549558

550-
def __init__(self, function, capacity):
551-
self.function = function
559+
def __init__(self, current, capacity, typ="function"):
560+
self.current = current
552561
self.capacity = capacity
562+
self.type = typ
553563

554564
def __call__(self, t):
555-
return self.function(t) / self.capacity
565+
if self.type == "function":
566+
return self.current(t) / self.capacity
567+
elif self.type == "input":
568+
return pybamm.InputParameter("Current function [A]") / self.capacity
556569

557570

558571
class CrateToCurrent:
559572
"Convert a C-rate function to a current function"
560573

561-
def __init__(self, function, capacity):
562-
self.function = function
574+
def __init__(self, Crate, capacity, typ="function"):
575+
self.Crate = Crate
563576
self.capacity = capacity
577+
self.type = typ
564578

565579
def __call__(self, t):
566-
return self.function(t) * self.capacity
580+
if self.type == "function":
581+
return self.Crate(t) * self.capacity
582+
elif self.type == "input":
583+
return pybamm.InputParameter("C-rate") * self.capacity

tests/integration/test_models/test_full_battery_models/test_lead_acid/test_asymptotics_convergence.py

+10-20
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@ def test_leading_order_convergence(self):
1818
composite_model = pybamm.lead_acid.Composite()
1919
full_model = pybamm.lead_acid.Full()
2020

21-
def current_function(t):
22-
return pybamm.InputParameter("Current")
23-
2421
# Same parameters, same geometry
2522
parameter_values = full_model.default_parameter_values
26-
parameter_values["Current function [A]"] = current_function
23+
parameter_values["Current function [A]"] = "[input]"
2724
parameter_values.process_model(leading_order_model)
2825
parameter_values.process_model(composite_model)
2926
parameter_values.process_model(full_model)
@@ -51,23 +48,17 @@ def get_max_error(current):
5148
pybamm.logger.info("current = {}".format(current))
5249
# Solve, make sure times are the same and use tight tolerances
5350
t_eval = np.linspace(0, 0.6)
54-
solver_loqs = leading_order_model.default_solver
55-
solver_loqs.rtol = 1e-8
56-
solver_loqs.atol = 1e-8
57-
solution_loqs = solver_loqs.solve(
58-
leading_order_model, t_eval, inputs={"Current": current}
51+
solver = pybamm.CasadiSolver()
52+
solver.rtol = 1e-8
53+
solver.atol = 1e-8
54+
solution_loqs = solver.solve(
55+
leading_order_model, t_eval, inputs={"Current function [A]": current}
5956
)
60-
solver_comp = composite_model.default_solver
61-
solver_comp.rtol = 1e-8
62-
solver_comp.atol = 1e-8
63-
solution_comp = solver_comp.solve(
64-
composite_model, t_eval, inputs={"Current": current}
57+
solution_comp = solver.solve(
58+
composite_model, t_eval, inputs={"Current function [A]": current}
6559
)
66-
solver_full = full_model.default_solver
67-
solver_full.rtol = 1e-8
68-
solver_full.atol = 1e-8
69-
solution_full = solver_full.solve(
70-
full_model, t_eval, inputs={"Current": current}
60+
solution_full = solver.solve(
61+
full_model, t_eval, inputs={"Current function [A]": current}
7162
)
7263

7364
# Post-process variables
@@ -105,5 +96,4 @@ def get_max_error(current):
10596

10697
if "-v" in sys.argv:
10798
debug = True
108-
pybamm.set_logging_level("DEBUG")
10999
unittest.main()

tests/unit/test_parameters/test_parameter_values.py

+22
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,18 @@ def test_check_and_update_parameter_values(self):
115115
param["C-rate"][1], np.hstack([x, 0.2 * x])
116116
)
117117

118+
# With input parameters
119+
# if only C-rate and capacity provided, update current
120+
values = {"C-rate": "[input]", "Cell capacity [A.h]": 10}
121+
param = pybamm.ParameterValues(values)
122+
self.assertEqual(param["Current function [A]"](2).evaluate(u={"C-rate": 1}), 10)
123+
# if only current and capacity provided, update C-rate
124+
values = {"Current function [A]": "[input]", "Cell capacity [A.h]": 10}
125+
param = pybamm.ParameterValues(values)
126+
self.assertEqual(
127+
param["C-rate"](5).evaluate(u={"Current function [A]": 5}), 0.5
128+
)
129+
118130
def test_process_symbol(self):
119131
parameter_values = pybamm.ParameterValues({"a": 1, "b": 2, "c": 3})
120132
# process parameter
@@ -297,6 +309,16 @@ def test_process_function_parameter(self):
297309
processed_diff_func = parameter_values.process_symbol(diff_func)
298310
self.assertEqual(processed_diff_func.evaluate(u={"a": 3}), 123)
299311

312+
# function itself as input (different to the variable being an input)
313+
parameter_values = pybamm.ParameterValues({"func": "[input]"})
314+
a = pybamm.Scalar(3)
315+
func = pybamm.FunctionParameter("func", a)
316+
processed_func = parameter_values.process_symbol(func)
317+
self.assertEqual(processed_func.evaluate(u={"func": 13}), 13)
318+
319+
320+
321+
300322
def test_process_inline_function_parameters(self):
301323
def D(c):
302324
return c ** 2

0 commit comments

Comments
 (0)