diff --git a/CHANGELOG.md b/CHANGELOG.md index c477799b25..8b962a9f0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Features +- Added tab, edge, and surface cooling ([#965](https://github.com/pybamm-team/PyBaMM/pull/965)) - Added functionality to solver to automatically discretise a 0D model ([#947](https://github.com/pybamm-team/PyBaMM/pull/947)) - Added sensitivity to `CasadiAlgebraicSolver` ([#940](https://github.com/pybamm-team/PyBaMM/pull/940)) - Added `ProcessedSymbolicVariable` class, which can handle symbolic variables (i.e. variables for which the inputs are symbolic) ([#940](https://github.com/pybamm-team/PyBaMM/pull/940)) diff --git a/examples/notebooks/using-model-options_thermal-example.ipynb b/examples/notebooks/using-model-options_thermal-example.ipynb index 851ae6ef5a..6a089069c7 100644 --- a/examples/notebooks/using-model-options_thermal-example.ipynb +++ b/examples/notebooks/using-model-options_thermal-example.ipynb @@ -65,7 +65,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We choose to use the parameters from [1]. We then update the heat transfer coefficient to be 0.1 [W/m^2/K] (see the [Parameter Values notebook](./parameter-values.ipynb) for more details)" + "We choose to use the parameters from [1]. We then update the heat transfer coefficients (see the [Parameter Values notebook](./parameter-values.ipynb) for more details)" ] }, { @@ -75,7 +75,17 @@ "outputs": [], "source": [ "param = pybamm.ParameterValues(chemistry=pybamm.parameter_sets.Marquis2019)\n", - "param.update({\"Heat transfer coefficient [W.m-2.K-1]\": 0.1})" + "param.update(\n", + " {\n", + " \"Negative current collector\"\n", + " + \" surface heat transfer coefficient [W.m-2.K-1]\": 5,\n", + " \"Positive current collector\"\n", + " + \" surface heat transfer coefficient [W.m-2.K-1]\": 5,\n", + " \"Negative tab heat transfer coefficient [W.m-2.K-1]\": 0,\n", + " \"Positive tab heat transfer coefficient [W.m-2.K-1]\": 0,\n", + " \"Edge heat transfer coefficient [W.m-2.K-1]\": 0,\n", + " }\n", + ")" ] }, { @@ -121,7 +131,7 @@ "source": [ "# solve model\n", "solver = model.default_solver\n", - "t_eval = np.linspace(0, 1, 250)\n", + "t_eval = np.linspace(0, 3600, 250)\n", "solution = solver.solve(model, t_eval)" ] }, @@ -140,12 +150,12 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c3d04dd597c24caf83c370bd01fe6131", + "model_id": "115696cc7c7e4297bb6d85a9f8220a82", "version_major": 2, "version_minor": 0 }, "text/plain": [ - "interactive(children=(FloatSlider(value=0.0, description='t', max=1.0, step=0.01), Output()), _dom_classes=('w…" + "interactive(children=(FloatSlider(value=0.0, description='t', max=3599.9999999999995, step=35.99999999999999),…" ] }, "metadata": {}, @@ -202,9 +212,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.7.5" } }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +} diff --git a/examples/scripts/thermal_lithium_ion.py b/examples/scripts/thermal_lithium_ion.py index f9766b4f0d..cd4c1fbdea 100644 --- a/examples/scripts/thermal_lithium_ion.py +++ b/examples/scripts/thermal_lithium_ion.py @@ -18,7 +18,20 @@ # load parameter values and process models and geometry param = models[0].default_parameter_values -param.update({"Heat transfer coefficient [W.m-2.K-1]": 1}) + +# for x-full, cooling is only implemented on the surfaces +# so set other forms of cooling to zero for comparison. +param.update( + { + "Negative current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 5, + "Positive current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 5, + "Negative tab heat transfer coefficient [W.m-2.K-1]": 0, + "Positive tab heat transfer coefficient [W.m-2.K-1]": 0, + "Edge heat transfer coefficient [W.m-2.K-1]": 0, + } +) for model in models: param.process_model(model) diff --git a/pybamm/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv b/pybamm/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv index 154de5565e..18cc3b5eac 100644 --- a/pybamm/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv +++ b/pybamm/input/parameters/lead-acid/experiments/1C_discharge_from_full/parameters.csv @@ -5,8 +5,11 @@ Name [units],Value,Reference,Notes Reference temperature [K],294.85,Room temperature, Maximum temperature [K],333.15,, Ambient temperature [K], 294.85,, -Heat transfer coefficient [W.m-2.K-1],10,, -Initial temperature [K],294.85,Room temperature, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Negative tab heat transfer coefficient [W.m-2.K-1],10,, +Positive tab heat transfer coefficient [W.m-2.K-1],10,, +Edge heat transfer coefficient [W.m-2.K-1],0.3,, ,,, # Electrical @@ -18,3 +21,4 @@ Upper voltage cut-off [V],2.44,(just over) 14.5V across 6-cell battery, # Initial conditions Initial State of Charge,1,-, Initial oxygen concentration [mol.m-3],0,, +Initial temperature [K],294.85,Room temperature, diff --git a/pybamm/input/parameters/lithium-ion/experiments/1C_charge_from_empty_Mohtat2020/parameters.csv b/pybamm/input/parameters/lithium-ion/experiments/1C_charge_from_empty_Mohtat2020/parameters.csv index ae32f40bb8..e843bfe334 100644 --- a/pybamm/input/parameters/lithium-ion/experiments/1C_charge_from_empty_Mohtat2020/parameters.csv +++ b/pybamm/input/parameters/lithium-ion/experiments/1C_charge_from_empty_Mohtat2020/parameters.csv @@ -3,10 +3,14 @@ Name [units],Value,Reference,Notes ,,, # Temperature Reference temperature [K],298.15,25C, -Heat transfer coefficient [W.m-2.K-1],5,Peyman MPM, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Negative tab heat transfer coefficient [W.m-2.K-1],0,, +Positive tab heat transfer coefficient [W.m-2.K-1],0,, +Edge heat transfer coefficient [W.m-2.K-1],5,Peyman MPM, Ambient temperature [K], 298.15,, ,,, -# Electrical +# Electrical Number of electrodes connected in parallel to make a cell,1,, Number of cells connected in series to make a battery,1,, Lower voltage cut-off [V],2.5,, diff --git a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Chen2020/parameters.csv b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Chen2020/parameters.csv index 7f59fcfd10..d91bb6f89b 100644 --- a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Chen2020/parameters.csv +++ b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Chen2020/parameters.csv @@ -3,11 +3,15 @@ Name [units],Value,Reference,Notes ,,, # Temperature Reference temperature [K],298.15,25C, -Heat transfer coefficient [W.m-2.K-1],10,, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Negative tab heat transfer coefficient [W.m-2.K-1],10,, +Positive tab heat transfer coefficient [W.m-2.K-1],10,, +Edge heat transfer coefficient [W.m-2.K-1],0.3,, Ambient temperature [K], 298.15,, ,,, -# Electrical +# Electrical Number of electrodes connected in parallel to make a cell,1,, Number of cells connected in series to make a battery,1,, Lower voltage cut-off [V],2.5,, diff --git a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Ecker2015/parameters.csv b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Ecker2015/parameters.csv index 131c087945..0397997a1b 100644 --- a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Ecker2015/parameters.csv +++ b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Ecker2015/parameters.csv @@ -3,7 +3,11 @@ Name [units],Value,Reference,Notes ,,, # Temperature Reference temperature [K],296.15,23C, -Heat transfer coefficient [W.m-2.K-1],10, The paper does not consider thermal effects so a typical value is chosen, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,Paper does not consider thermal effects +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,Paper does not consider thermal effects +Negative tab heat transfer coefficient [W.m-2.K-1],10,Paper does not consider thermal effects, +Positive tab heat transfer coefficient [W.m-2.K-1],10,Paper does not consider thermal effects, +Edge heat transfer coefficient [W.m-2.K-1],0.3,Paper does not consider thermal effects, Ambient temperature [K], 298.15,, ,,, diff --git a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Kim2011/parameters.csv b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Kim2011/parameters.csv index e1e4b77c65..4d475c47e8 100644 --- a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Kim2011/parameters.csv +++ b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Kim2011/parameters.csv @@ -3,7 +3,11 @@ Name [units],Value,Reference,Notes ,,, # Temperature Reference temperature [K],298.15,25C, -Heat transfer coefficient [W.m-2.K-1],25,, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Negative tab heat transfer coefficient [W.m-2.K-1],25,, +Positive tab heat transfer coefficient [W.m-2.K-1],25,, +Edge heat transfer coefficient [W.m-2.K-1],0.3,, Ambient temperature [K], 298.15,, ,,, diff --git a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv index bd463472c5..fb80497c1a 100644 --- a/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv +++ b/pybamm/input/parameters/lithium-ion/experiments/1C_discharge_from_full_Marquis2019/parameters.csv @@ -4,9 +4,13 @@ Name [units],Value,Reference,Notes # Temperature Reference temperature [K],298.15,25C, Ambient temperature [K], 298.15,, -Heat transfer coefficient [W.m-2.K-1],10,, +Negative current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Positive current collector surface heat transfer coefficient [W.m-2.K-1],0,, +Negative tab heat transfer coefficient [W.m-2.K-1],10,, +Positive tab heat transfer coefficient [W.m-2.K-1],10,, +Edge heat transfer coefficient [W.m-2.K-1],0.3,, ,,, -# Electrical +# Electrical Number of electrodes connected in parallel to make a cell,1,, Number of cells connected in series to make a battery,1,, Lower voltage cut-off [V],3.105,, diff --git a/pybamm/models/full_battery_models/base_battery_model.py b/pybamm/models/full_battery_models/base_battery_model.py index 4e4c2673f6..606142a5c4 100644 --- a/pybamm/models/full_battery_models/base_battery_model.py +++ b/pybamm/models/full_battery_models/base_battery_model.py @@ -3,6 +3,7 @@ # import pybamm +import warnings class BaseBatteryModel(pybamm.BaseModel): @@ -239,6 +240,12 @@ def options(self, extra_options): "particle model '{}' not recognised".format(options["particle"]) ) + if options["thermal"] == "x-lumped" and options["dimensionality"] == 1: + warnings.warn( + "1+1D Thermal models are only valid if both tabs are" + + "placed at the top of the cell." + ) + self._options = options def set_standard_output_variables(self): diff --git a/pybamm/models/submodels/thermal/lumped.py b/pybamm/models/submodels/thermal/lumped.py index 3b4a63dc9e..78fe5e525c 100644 --- a/pybamm/models/submodels/thermal/lumped.py +++ b/pybamm/models/submodels/thermal/lumped.py @@ -53,12 +53,47 @@ def set_rhs(self, variables): # the choice of non-dimensionalisation. # TODO: allow for arbitrary surface area to volume ratio in order to model # different cell geometries (see #718) - A = self.param.l_y * self.param.l_z - V = self.param.l * self.param.l_y * self.param.l_z - cooling_coeff = -2 * self.param.h * A / V / (self.param.delta ** 2) + cell_volume = self.param.l * self.param.l_y * self.param.l_z + + yz_cell_surface_area = self.param.l_y * self.param.l_z + yz_surface_cooling_coefficient = ( + -(self.param.h_cn + self.param.h_cp) + * yz_cell_surface_area + / cell_volume + / (self.param.delta ** 2) + ) + + negative_tab_area = self.param.l_tab_n * self.param.l_cn + negative_tab_cooling_coefficient = ( + -self.param.h_tab_n * negative_tab_area / cell_volume / self.param.delta + ) + + positive_tab_area = self.param.l_tab_p * self.param.l_cp + positive_tab_cooling_coefficient = ( + -self.param.h_tab_p * positive_tab_area / cell_volume / self.param.delta + ) + + edge_area = ( + 2 * self.param.l_y * self.param.l + + 2 * self.param.l_z * self.param.l + - negative_tab_area + - positive_tab_area + ) + edge_cooling_coefficient = ( + -self.param.h_edge * edge_area / cell_volume / self.param.delta + ) + + total_cooling_coefficient = ( + yz_surface_cooling_coefficient + + negative_tab_cooling_coefficient + + positive_tab_cooling_coefficient + + edge_cooling_coefficient + ) self.rhs = { - T_vol_av: (self.param.B * Q_vol_av + cooling_coeff * (T_vol_av - T_amb)) + T_vol_av: ( + self.param.B * Q_vol_av + total_cooling_coefficient * (T_vol_av - T_amb) + ) / (self.param.C_th * self.param.rho) } diff --git a/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_1D_current_collectors.py b/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_1D_current_collectors.py index 1fb3a43529..3b47bf1604 100644 --- a/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_1D_current_collectors.py +++ b/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_1D_current_collectors.py @@ -60,15 +60,30 @@ def set_rhs(self, variables): # Account for surface area to volume ratio of pouch cell in cooling # coefficient. Note: the factor 1/delta^2 comes from the choice of # non-dimensionalisation - A = self.param.l_y * self.param.l_z - V = self.param.l * self.param.l_y * self.param.l_z - cooling_coeff = -2 * self.param.h * A / V / (self.param.delta ** 2) + cell_volume = self.param.l * self.param.l_y * self.param.l_z + + yz_surface_area = self.param.l_y * self.param.l_z + yz_surface_cooling_coefficient = ( + -(self.param.h_cn + self.param.h_cp) + * yz_surface_area + / cell_volume + / (self.param.delta ** 2) + ) + + side_edge_area = 2 * self.param.l_z * self.param.l + side_edge_cooling_coefficient = ( + -self.param.h_edge * side_edge_area / cell_volume / self.param.delta + ) + + total_cooling_coefficient = ( + yz_surface_cooling_coefficient + side_edge_cooling_coefficient + ) self.rhs = { T_av: ( pybamm.laplacian(T_av) + self.param.B * Q_av - + cooling_coeff * (T_av - T_amb) + + total_cooling_coefficient * (T_av - T_amb) ) / (self.param.C_th * self.param.rho) } @@ -76,24 +91,51 @@ def set_rhs(self, variables): def set_boundary_conditions(self, variables): T_amb = variables["Ambient temperature"] T_av = variables["X-averaged cell temperature"] - T_av_left = pybamm.boundary_value(T_av, "negative tab") - T_av_right = pybamm.boundary_value(T_av, "positive tab") + T_av_top = pybamm.boundary_value(T_av, "right") + T_av_bottom = pybamm.boundary_value(T_av, "left") + + # Tab cooling only implemented for both tabs at the top. + negative_tab_area = self.param.l_tab_n * self.param.l_cn + positive_tab_area = self.param.l_tab_p * self.param.l_cp + total_top_area = self.param.l * self.param.l_y + non_tab_top_area = total_top_area - negative_tab_area - positive_tab_area + + negative_tab_cooling_coefficient = ( + self.param.h_tab_n / self.param.delta * negative_tab_area / total_top_area + ) + positive_tab_cooling_coefficient = ( + self.param.h_tab_p / self.param.delta * positive_tab_area / total_top_area + ) + + top_edge_cooling_coefficient = ( + self.param.h_edge / self.param.delta * non_tab_top_area / total_top_area + ) + + bottom_edge_cooling_coefficient = ( + self.param.h_edge / self.param.delta * total_top_area / total_top_area + ) + + total_top_cooling_coefficient = ( + negative_tab_cooling_coefficient + + positive_tab_cooling_coefficient + + top_edge_cooling_coefficient + ) + + total_bottom_cooling_coefficient = bottom_edge_cooling_coefficient - # Three boundary conditions here to handle the cases of both tabs at - # the same side (top or bottom), or one either side. For both tabs on the - # same side, T_av_left and T_av_right are equal, and the boundary condition - # "no tab" is used on the other side. + # just use left and right for clarity + # left = bottom of cell (z=0) + # right = top of cell (z=L_z) self.boundary_conditions = { T_av: { - "negative tab": ( - self.param.h * (T_av_left - T_amb) / self.param.delta, + "left": ( + total_bottom_cooling_coefficient * (T_av_bottom - T_amb), "Neumann", ), - "positive tab": ( - -self.param.h * (T_av_right - T_amb) / self.param.delta, + "right": ( + -total_top_cooling_coefficient * (T_av_top - T_amb), "Neumann", ), - "no tab": (pybamm.Scalar(0), "Neumann"), } } diff --git a/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_2D_current_collectors.py b/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_2D_current_collectors.py index 8901318dc9..36aa2e5a51 100644 --- a/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_2D_current_collectors.py +++ b/pybamm/models/submodels/thermal/pouch_cell/pouch_cell_2D_current_collectors.py @@ -60,34 +60,61 @@ def set_rhs(self, variables): # Account for surface area to volume ratio of pouch cell in cooling # coefficient. Note: the factor 1/delta^2 comes from the choice of # non-dimensionalisation - A = self.param.l_y * self.param.l_z - V = self.param.l * self.param.l_y * self.param.l_z - cooling_coeff = -2 * self.param.h * A / V / (self.param.delta ** 2) + yz_surface_area = self.param.l_y * self.param.l_z + cell_volume = self.param.l * self.param.l_y * self.param.l_z + yz_surface_cooling_coefficient = ( + -(self.param.h_cn + self.param.h_cp) + * yz_surface_area + / cell_volume + / (self.param.delta ** 2) + ) + + edge_cooling_coefficient = self.param.h_edge / self.param.delta - # Add boundary source term which accounts for surface cooling around - # the edge of the domain in the weak formulation. - # TODO: update to allow different cooling conditions at the tabs + # Governing equations contain: + # - source term for y-z surface cooling + # - boundary source term of edge cooling + # Boundary conditions contain: + # - Neumann condition for tab cooling self.rhs = { T_av: ( pybamm.laplacian(T_av) + self.param.B * pybamm.source(Q_av, T_av) - + cooling_coeff * pybamm.source(T_av - T_amb, T_av) - - (self.param.h / self.param.delta) + + yz_surface_cooling_coefficient * pybamm.source(T_av - T_amb, T_av) + - edge_cooling_coefficient * pybamm.source(T_av - T_amb, T_av, boundary=True) ) / (self.param.C_th * self.param.rho) } + # TODO: Make h_edge a function of position to have bottom/top/side cooled cells. + def set_boundary_conditions(self, variables): T_av = variables["X-averaged cell temperature"] - # Dummy no flux boundary conditions since cooling at the the tabs is - # accounted for in the boundary source term in the weak form of the - # governing equation - # TODO: update to allow different cooling conditions at the tabs + T_amb = variables["Ambient temperature"] + + # Subtract the edge cooling from the tab portion so as to not double count + # Note: tab cooling is also only applied on the current collector hence + # the (l_cn / l) and (l_cp / l) prefactors. + # We also still have edge cooling on the region: x in (0, 1) + h_tab_n_corrected = ( + (self.param.l_cn / self.param.l) + * (self.param.h_tab_n - self.param.h_edge) + / self.param.delta + ) + h_tab_p_corrected = ( + (self.param.l_cp / self.param.l) + * (self.param.h_tab_p - self.param.h_edge) + / self.param.delta + ) + + T_av_n = pybamm.BoundaryValue(T_av, "negative tab") + T_av_p = pybamm.BoundaryValue(T_av, "positive tab") + self.boundary_conditions = { T_av: { - "negative tab": (pybamm.Scalar(0), "Neumann"), - "positive tab": (pybamm.Scalar(0), "Neumann"), + "negative tab": (-h_tab_n_corrected * (T_av_n - T_amb), "Neumann"), + "positive tab": (-h_tab_p_corrected * (T_av_p - T_amb), "Neumann"), } } diff --git a/pybamm/models/submodels/thermal/x_full.py b/pybamm/models/submodels/thermal/x_full.py index 22ebb8a745..41f8d75d94 100644 --- a/pybamm/models/submodels/thermal/x_full.py +++ b/pybamm/models/submodels/thermal/x_full.py @@ -51,6 +51,7 @@ def set_rhs(self, variables): # Fourier's law for heat flux q = -self.param.lambda_k * pybamm.grad(T) + # N.B only y-z surface cooling is implemented for this model self.rhs = { T: (-pybamm.div(q) / self.param.delta ** 2 + self.param.B * Q) / (self.param.C_th * self.param.rho_k) @@ -62,14 +63,16 @@ def set_boundary_conditions(self, variables): T_p_right = pybamm.boundary_value(T, "right") T_amb = variables["Ambient temperature"] + # N.B only y-z surface cooling is implemented for this thermal model. + # Tab and edge cooling is not accounted for. self.boundary_conditions = { T: { "left": ( - self.param.h * (T_n_left - T_amb) / self.param.lambda_n, + self.param.h_cn * (T_n_left - T_amb) / self.param.lambda_n, "Neumann", ), "right": ( - -self.param.h * (T_p_right - T_amb) / self.param.lambda_p, + -self.param.h_cp * (T_p_right - T_amb) / self.param.lambda_p, "Neumann", ), } diff --git a/pybamm/parameters/standard_parameters_lead_acid.py b/pybamm/parameters/standard_parameters_lead_acid.py index 6cb4516426..fce599c2b1 100644 --- a/pybamm/parameters/standard_parameters_lead_acid.py +++ b/pybamm/parameters/standard_parameters_lead_acid.py @@ -458,7 +458,13 @@ def U_p_dimensional(c_e, T): lambda_k = pybamm.thermal_parameters.lambda_k Theta = pybamm.thermal_parameters.Theta -h = pybamm.thermal_parameters.h + +h_edge = pybamm.thermal_parameters.h_edge +h_tab_n = pybamm.thermal_parameters.h_tab_n +h_tab_p = pybamm.thermal_parameters.h_tab_p +h_cn = pybamm.thermal_parameters.h_cn +h_cp = pybamm.thermal_parameters.h_cp + B = ( i_typ * R diff --git a/pybamm/parameters/standard_parameters_lithium_ion.py b/pybamm/parameters/standard_parameters_lithium_ion.py index 0571fa9cb6..499d73569f 100644 --- a/pybamm/parameters/standard_parameters_lithium_ion.py +++ b/pybamm/parameters/standard_parameters_lithium_ion.py @@ -381,7 +381,13 @@ def chi(c_e): lambda_k = pybamm.thermal_parameters.lambda_k Theta = pybamm.thermal_parameters.Theta -h = pybamm.thermal_parameters.h + +h_edge = pybamm.thermal_parameters.h_edge +h_tab_n = pybamm.thermal_parameters.h_tab_n +h_tab_p = pybamm.thermal_parameters.h_tab_p +h_cn = pybamm.thermal_parameters.h_cn +h_cp = pybamm.thermal_parameters.h_cp + B = ( i_typ * R diff --git a/pybamm/parameters/thermal_parameters.py b/pybamm/parameters/thermal_parameters.py index 76ce5e850d..2c3a45ba3c 100644 --- a/pybamm/parameters/thermal_parameters.py +++ b/pybamm/parameters/thermal_parameters.py @@ -55,13 +55,18 @@ ) / pybamm.geometric_parameters.L # Cooling coefficient -h_dim = pybamm.Parameter("Heat transfer coefficient [W.m-2.K-1]") +h_cn_dim = pybamm.Parameter( + "Negative current collector surface heat transfer coefficient [W.m-2.K-1]" +) +h_cp_dim = pybamm.Parameter( + "Positive current collector surface heat transfer coefficient [W.m-2.K-1]" +) +h_tab_n_dim = pybamm.Parameter("Negative tab heat transfer coefficient [W.m-2.K-1]") +h_tab_p_dim = pybamm.Parameter("Positive tab heat transfer coefficient [W.m-2.K-1]") +h_edge_dim = pybamm.Parameter("Edge heat transfer coefficient [W.m-2.K-1]") # Typical temperature rise -Phi_dim = pybamm.Scalar(1) # typical scale for voltage drop across cell (order 1V) -Delta_T = ( - pybamm.electrical_parameters.i_typ * Phi_dim / h_dim -) # computed from balance of typical cross-cell Ohmic heating with surface heat loss +Delta_T = pybamm.Scalar(1) # Initial temperature T_init_dim = pybamm.Parameter("Initial temperature [K]") @@ -99,7 +104,13 @@ Theta = Delta_T / T_ref -h = h_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim + +h_edge = h_edge_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim +h_tab_n = h_tab_n_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim +h_tab_p = h_tab_p_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim +h_cn = h_cn_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim +h_cp = h_cp_dim * pybamm.geometric_parameters.L_x / lambda_eff_dim + T_init = (T_init_dim - T_ref) / Delta_T diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_compare_outputs.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_compare_outputs.py index 63a076abf7..30eecc79ab 100644 --- a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_compare_outputs.py +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_compare_outputs.py @@ -64,6 +64,20 @@ def test_compare_outputs_thermal(self): for models in model_combos: # load parameter values (same for all models) param = models[0].default_parameter_values + + # for x-full, cooling is only implemented on the surfaces + # so set other forms of cooling to zero for comparison. + param.update( + { + "Negative current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 5, + "Positive current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 5, + "Negative tab heat transfer coefficient [W.m-2.K-1]": 0, + "Positive tab heat transfer coefficient [W.m-2.K-1]": 0, + "Edge heat transfer coefficient [W.m-2.K-1]": 0, + } + ) for model in models: param.process_model(model) diff --git a/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_thermal_models.py b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_thermal_models.py new file mode 100644 index 0000000000..22d9ce6d6b --- /dev/null +++ b/tests/integration/test_models/test_full_battery_models/test_lithium_ion/test_thermal_models.py @@ -0,0 +1,105 @@ +# +# Tests for the thermal lithium-ion models produce consistent +# thermal response +# +import pybamm +import numpy as np +import unittest + + +class TestThermal(unittest.TestCase): + def test_consistent_cooling(self): + # use spme for comparison instead of spm as + # much larger realistic temperature rises + # so that errors can be more easily observed + C_rate = 5 + options = { + "thermal": "x-lumped", + } + spme_1D = pybamm.lithium_ion.SPMe(options=options) + + options = { + "thermal": "x-lumped", + "current collector": "potential pair", + "dimensionality": 1, + } + spme_1p1D = pybamm.lithium_ion.SPMe(options=options) + + options = { + "thermal": "x-lumped", + "current collector": "potential pair", + "dimensionality": 2, + } + spme_2p1D = pybamm.lithium_ion.SPMe(options=options) + + models = {"SPMe 1D": spme_1D, "SPMe 1+1D": spme_1p1D, "SPMe 2+1D": spme_2p1D} + solutions = {} + + for model_name, model in models.items(): + var = pybamm.standard_spatial_vars + var_pts = { + var.x_n: 3, + var.x_s: 3, + var.x_p: 3, + var.r_n: 3, + var.r_p: 3, + var.y: 5, + var.z: 5, + } + chemistry = pybamm.parameter_sets.NCA_Kim2011 + parameter_values = pybamm.ParameterValues(chemistry=chemistry) + + # high thermal and electrical conductivity in current collectors + parameter_values.update( + { + "Negative current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 10, + "Positive current collector" + + " surface heat transfer coefficient [W.m-2.K-1]": 5, + "Negative tab heat transfer coefficient [W.m-2.K-1]": 250, + "Positive tab heat transfer coefficient [W.m-2.K-1]": 250, + "Edge heat transfer coefficient [W.m-2.K-1]": 100, + "Negative current collector" + + " thermal conductivity [W.m-1.K-1]": 267.467 * 100000, + "Positive current collector" + + " thermal conductivity [W.m-1.K-1]": 158.079 * 100000, + "Negative current collector conductivity [S.m-1]": 1e10, + "Positive current collector conductivity [S.m-1]": 1e10, + } + ) + + solver = pybamm.CasadiSolver(mode="fast") + sim = pybamm.Simulation( + model, + var_pts=var_pts, + solver=solver, + parameter_values=parameter_values, + C_rate=C_rate, + ) + t_eval = np.linspace(0, 3500 / 6, 100) + sim.solve(t_eval=t_eval) + + solutions[model_name] = sim.solution[ + "Volume-averaged cell temperature [K]" + ].entries + + # check volume-averaged cell temperature is within + # 1e-5 relative error + + def err(a, b): + return np.max(np.abs(a - b)) / np.max(np.abs(a)) + + self.assertGreater(1e-5, err(solutions["SPMe 1D"], solutions["SPMe 1+1D"])) + self.assertGreater(1e-5, err(solutions["SPMe 1D"], solutions["SPMe 2+1D"])) + self.assertGreater(1e-5, err(solutions["SPMe 1+1D"], solutions["SPMe 2+1D"])) + + +if __name__ == "__main__": + print("Add -v for more debug output") + import sys + + sys.setrecursionlimit(10000) + + if "-v" in sys.argv: + debug = True + unittest.main() diff --git a/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py b/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py index 7c7dd3000c..cfd5f2869a 100644 --- a/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py +++ b/tests/unit/test_parameters/test_dimensionless_parameter_values_lithium_ion.py @@ -172,8 +172,6 @@ def test_thermal_parameters(self): np.testing.assert_almost_equal(values.evaluate(param.Theta / c_rate), 0.008, 2) - np.testing.assert_almost_equal(values.evaluate(param.h), 3.7881 * 10 ** (-5), 7) - # np.testing.assert_almost_equal( # values.evaluate(param.B / c_rate), 36.216, 2 # )