Skip to content

Commit 6319729

Browse files
rtimmspre-commit-ci[bot]kratman
authored
Allow 3D process variables (#4804)
* #4776 initial fix * Update src/pybamm/solvers/processed_variable_computed.py * #4776 handle current collector case * #4776 processed var tests * #4776 processed var tests * style: pre-commit fixes * #4776 debugging processed computed var * #4776 processed computed var shape * #4776 add tertiary x average particle concentration * #4776 test set initial conditions * #4776 coverage and 3D scikit computed var * #4776 add 3D on edge test * #4776 add 3D on edge test processed computed * style: pre-commit fixes * #4776 more coverage * #4776 add postfix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Eric G. Kratz <[email protected]>
1 parent 9bb6eed commit 6319729

File tree

10 files changed

+1003
-144
lines changed

10 files changed

+1003
-144
lines changed

docs/source/examples/notebooks/models/coupled-degradation.ipynb

+61-5
Large diffs are not rendered by default.

docs/source/examples/notebooks/models/simulating-ORegan-2022-parameter-set.ipynb

+73-13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"name": "stdout",
2121
"output_type": "stream",
2222
"text": [
23+
"\n",
24+
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.0.1\u001b[0m\n",
25+
"\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
2326
"Note: you may need to restart the kernel to use updated packages.\n"
2427
]
2528
}
@@ -52,7 +55,7 @@
5255
"param = pybamm.ParameterValues(\"ORegan2022\")\n",
5356
"\n",
5457
"# Choose CasADI fast (we do a short discharge so there are no events, if events are needed choose \"fast with events\")\n",
55-
"solver = pybamm.CasadiSolver(mode=\"fast\")"
58+
"solver = pybamm.IDAKLUSolver()"
5659
]
5760
},
5861
{
@@ -108,12 +111,12 @@
108111
{
109112
"data": {
110113
"application/vnd.jupyter.widget-view+json": {
111-
"model_id": "7e9913de41054c7cb71be948ebf63375",
114+
"model_id": "2c6b050e722f45c9921d891d4a3c1c19",
112115
"version_major": 2,
113116
"version_minor": 0
114117
},
115118
"text/plain": [
116-
"interactive(children=(FloatSlider(value=0.0, description='t', max=9.999999999999998, step=0.09999999999999998)"
119+
"interactive(children=(FloatSlider(value=0.0, description='t', max=1800.0, step=18.0), Output()), _dom_classes="
117120
]
118121
},
119122
"metadata": {},
@@ -122,7 +125,7 @@
122125
{
123126
"data": {
124127
"text/plain": [
125-
"<pybamm.plotting.quick_plot.QuickPlot at 0x7fe0c1824eb0>"
128+
"<pybamm.plotting.quick_plot.QuickPlot at 0x17e0440d0>"
126129
]
127130
},
128131
"execution_count": 4,
@@ -131,15 +134,69 @@
131134
}
132135
],
133136
"source": [
137+
"sim = pybamm.Simulation(\n",
138+
" model,\n",
139+
" parameter_values=param,\n",
140+
" C_rate=1,\n",
141+
" solver=solver,\n",
142+
" var_pts=var_pts,\n",
143+
" submesh_types=submesh_types,\n",
144+
")\n",
145+
"sim.solve(\n",
146+
" [0, 1800]\n",
147+
") # solving time kept short for testing purposes, feel free to extend it\n",
148+
"sim.plot()"
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": 7,
154+
"id": "e86b053e",
155+
"metadata": {},
156+
"outputs": [
157+
{
158+
"data": {
159+
"application/vnd.jupyter.widget-view+json": {
160+
"model_id": "a79ea249a7c94d43a219067c00259084",
161+
"version_major": 2,
162+
"version_minor": 0
163+
},
164+
"text/plain": [
165+
"interactive(children=(FloatSlider(value=0.0, description='t', max=3316.4079454263174, step=33.164079454263174)…"
166+
]
167+
},
168+
"metadata": {},
169+
"output_type": "display_data"
170+
},
171+
{
172+
"data": {
173+
"text/plain": [
174+
"<pybamm.plotting.quick_plot.QuickPlot at 0x29e78fd50>"
175+
]
176+
},
177+
"execution_count": 7,
178+
"metadata": {},
179+
"output_type": "execute_result"
180+
}
181+
],
182+
"source": [
183+
"sim = pybamm.Simulation(\n",
184+
" model,\n",
185+
" parameter_values=param,\n",
186+
" C_rate=1,\n",
187+
" solver=solver,\n",
188+
" # var_pts=var_pts,\n",
189+
" # submesh_types=submesh_types,\n",
190+
")\n",
134191
"sim.solve(\n",
135-
" [0, 10]\n",
192+
" [0, 3600]\n",
136193
") # solving time kept short for testing purposes, feel free to extend it\n",
137194
"sim.plot()"
138195
]
139196
},
140197
{
141198
"cell_type": "code",
142-
"execution_count": 5,
199+
"execution_count": 6,
143200
"id": "lined-illustration",
144201
"metadata": {},
145202
"outputs": [
@@ -148,12 +205,15 @@
148205
"output_type": "stream",
149206
"text": [
150207
"[1] Joel A. E. Andersson, Joris Gillis, Greg Horn, James B. Rawlings, and Moritz Diehl. CasADi – A software framework for nonlinear optimization and optimal control. Mathematical Programming Computation, 11(1):1–36, 2019. doi:10.1007/s12532-018-0139-4.\n",
151-
"[2] Chang-Hui Chen, Ferran Brosa Planella, Kieran O'Regan, Dominika Gastol, W. Dhammika Widanage, and Emma Kendrick. Development of Experimental Techniques for Parameterization of Multi-scale Lithium-ion Battery Models. Journal of The Electrochemical Society, 167(8):080534, 2020. doi:10.1149/1945-7111/ab9050.\n",
152-
"[3] Marc Doyle, Thomas F. Fuller, and John Newman. Modeling of galvanostatic charge and discharge of the lithium/polymer/insertion cell. Journal of the Electrochemical society, 140(6):1526–1533, 1993. doi:10.1149/1.2221597.\n",
153-
"[4] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.\n",
154-
"[5] Kieran O'Regan, Ferran Brosa Planella, W. Dhammika Widanage, and Emma Kendrick. Thermal-electrochemical parametrisation of a lithium-ion battery: mapping Li concentration and temperature dependencies. Journal of The Electrochemical Society, ():, 2021. doi:.\n",
155-
"[6] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.\n",
156-
"[7] Robert Timms, Scott G Marquis, Valentin Sulzer, Colin P. Please, and S Jonathan Chapman. Asymptotic Reduction of a Lithium-ion Pouch Cell Model. SIAM Journal on Applied Mathematics, 81(3):765–788, 2021. doi:10.1137/20M1336898.\n",
208+
"[2] Von DAG Bruggeman. Berechnung verschiedener physikalischer konstanten von heterogenen substanzen. i. dielektrizitätskonstanten und leitfähigkeiten der mischkörper aus isotropen substanzen. Annalen der physik, 416(7):636–664, 1935.\n",
209+
"[3] Chang-Hui Chen, Ferran Brosa Planella, Kieran O'Regan, Dominika Gastol, W. Dhammika Widanage, and Emma Kendrick. Development of Experimental Techniques for Parameterization of Multi-scale Lithium-ion Battery Models. Journal of The Electrochemical Society, 167(8):080534, 2020. doi:10.1149/1945-7111/ab9050.\n",
210+
"[4] Marc Doyle, Thomas F. Fuller, and John Newman. Modeling of galvanostatic charge and discharge of the lithium/polymer/insertion cell. Journal of the Electrochemical society, 140(6):1526–1533, 1993. doi:10.1149/1.2221597.\n",
211+
"[5] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.\n",
212+
"[6] Alan C. Hindmarsh. The PVODE and IDA algorithms. Technical Report, Lawrence Livermore National Lab., CA (US), 2000. doi:10.2172/802599.\n",
213+
"[7] Alan C. Hindmarsh, Peter N. Brown, Keith E. Grant, Steven L. Lee, Radu Serban, Dan E. Shumaker, and Carol S. Woodward. SUNDIALS: Suite of nonlinear and differential/algebraic equation solvers. ACM Transactions on Mathematical Software (TOMS), 31(3):363–396, 2005. doi:10.1145/1089014.1089020.\n",
214+
"[8] Kieran O'Regan, Ferran Brosa Planella, W. Dhammika Widanage, and Emma Kendrick. Thermal-electrochemical parameters of a high energy lithium-ion cylindrical battery. Electrochimica Acta, 425:140700, 2022. doi:10.1016/j.electacta.2022.140700.\n",
215+
"[9] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.\n",
216+
"[10] Robert Timms, Scott G Marquis, Valentin Sulzer, Colin P. Please, and S Jonathan Chapman. Asymptotic Reduction of a Lithium-ion Pouch Cell Model. SIAM Journal on Applied Mathematics, 81(3):765–788, 2021. doi:10.1137/20M1336898.\n",
157217
"\n"
158218
]
159219
}
@@ -179,7 +239,7 @@
179239
"name": "python",
180240
"nbconvert_exporter": "python",
181241
"pygments_lexer": "ipython3",
182-
"version": "3.9.16"
242+
"version": "3.11.5"
183243
},
184244
"toc": {
185245
"base_numbering": 1,

src/pybamm/discretisations/discretisation.py

+7
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,13 @@ def process_symbol(self, symbol):
783783
]
784784
else:
785785
discretised_symbol.secondary_mesh = None
786+
787+
# Assign tertiary mesh
788+
if symbol.domains["tertiary"] != []:
789+
discretised_symbol.tertiary_mesh = self.mesh[symbol.domains["tertiary"]]
790+
else:
791+
discretised_symbol.tertiary_mesh = None
792+
786793
return discretised_symbol
787794

788795
def _process_symbol(self, symbol):

src/pybamm/models/base_model.py

+40-38
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ def generic_deserialise(cls, instance, properties):
126126
else:
127127
var.secondary_mesh = None
128128

129+
if var.domains["tertiary"] != []:
130+
var.tertiary_mesh = properties["mesh"][var.domains["tertiary"]]
131+
else:
132+
var.tertiary_mesh = None
133+
129134
if properties["geometry"]:
130135
instance._geometry = pybamm.Geometry(properties["geometry"])
131136
else:
@@ -897,51 +902,48 @@ def set_initial_conditions_from(self, solution, inplace=True, return_type="model
897902
initial_conditions = {}
898903
if isinstance(solution, pybamm.Solution):
899904
solution = solution.last_state
905+
906+
def get_final_state_eval(final_state):
907+
if isinstance(solution, pybamm.Solution):
908+
final_state = final_state.data
909+
910+
if final_state.ndim == 0:
911+
return np.array([final_state])
912+
elif final_state.ndim == 1:
913+
return final_state[-1:]
914+
elif final_state.ndim == 2:
915+
return final_state[:, -1]
916+
elif final_state.ndim == 3:
917+
return final_state[:, :, -1].flatten(order="F")
918+
elif final_state.ndim == 4:
919+
return final_state[:, :, :, -1].flatten(order="F")
920+
else:
921+
raise NotImplementedError("Variable must be 0D, 1D, 2D, or 3D")
922+
923+
def get_variable_state(var_name):
924+
try:
925+
return solution[var_name]
926+
except KeyError as e:
927+
raise pybamm.ModelError(
928+
"To update a model from a solution, each variable in "
929+
"model.initial_conditions must appear in the solution with "
930+
"the same key as the variable name. In the solution provided, "
931+
f"'{e.args[0]}' was not found."
932+
) from e
933+
900934
for var in self.initial_conditions:
901935
if isinstance(var, pybamm.Variable):
902-
try:
903-
final_state = solution[var.name]
904-
except KeyError as e:
905-
raise pybamm.ModelError(
906-
"To update a model from a solution, each variable in "
907-
"model.initial_conditions must appear in the solution with "
908-
"the same key as the variable name. In the solution provided, "
909-
f"'{e.args[0]}' was not found."
910-
) from e
911-
if isinstance(solution, pybamm.Solution):
912-
final_state = final_state.data
913-
if final_state.ndim == 0:
914-
final_state_eval = np.array([final_state])
915-
elif final_state.ndim == 1:
916-
final_state_eval = final_state[-1:]
917-
elif final_state.ndim == 2:
918-
final_state_eval = final_state[:, -1]
919-
elif final_state.ndim == 3:
920-
final_state_eval = final_state[:, :, -1].flatten(order="F")
921-
else:
922-
raise NotImplementedError("Variable must be 0D, 1D, or 2D")
936+
final_state = get_variable_state(var.name)
937+
final_state_eval = get_final_state_eval(final_state)
938+
923939
elif isinstance(var, pybamm.Concatenation):
924940
children = []
925941
for child in var.orphans:
926-
try:
927-
final_state = solution[child.name]
928-
except KeyError as e:
929-
raise pybamm.ModelError(
930-
"To update a model from a solution, each variable in "
931-
"model.initial_conditions must appear in the solution with "
932-
"the same key as the variable name. In the solution "
933-
f"provided, {e.args[0]}"
934-
) from e
935-
if isinstance(solution, pybamm.Solution):
936-
final_state = final_state.data
937-
if final_state.ndim == 2:
938-
final_state_eval = final_state[:, -1]
939-
else:
940-
raise NotImplementedError(
941-
"Variable in concatenation must be 1D"
942-
)
942+
final_state = get_variable_state(child.name)
943+
final_state_eval = get_final_state_eval(final_state)
943944
children.append(final_state_eval)
944945
final_state_eval = np.concatenate(children)
946+
945947
else:
946948
raise NotImplementedError(
947949
"Variable must have type 'Variable' or 'Concatenation'"

src/pybamm/models/submodels/particle/base_particle.py

+1-9
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,7 @@ def _get_standard_concentration_distribution_variables(self, c_s):
337337
c_s_distribution = c_s
338338

339339
# x-average the *tertiary* domain.
340-
# NOTE: not yet implemented. Make 0.5 everywhere
341-
c_s_xav_distribution = pybamm.FullBroadcast(
342-
0.5,
343-
[f"{domain} {phase_name}particle"],
344-
{
345-
"secondary": f"{domain} {phase_name}particle size",
346-
"tertiary": "current collector",
347-
},
348-
)
340+
c_s_xav_distribution = pybamm.x_average(c_s)
349341

350342
# Surface concentration distribution variables
351343
c_s_surf_distribution = pybamm.surf(c_s)

0 commit comments

Comments
 (0)