def set_algebraic(self, variables): R_cn_scaled = variables["Scaled negative current collector resistance"] R_cp_scaled = variables["Scaled positive current collector resistance"] self.algebraic = { R_cn_scaled: pybamm.laplacian(R_cn_scaled) - pybamm.source(1, R_cn_scaled), R_cp_scaled: pybamm.laplacian(R_cp_scaled) - pybamm.source(1, R_cp_scaled), }
def set_algebraic(self, variables): param = self.param applied_current = variables["Total current density"] cc_area = self._get_effective_current_collector_area() z = pybamm.standard_spatial_vars.z phi_s_cn = variables["Negative current collector potential"] phi_s_cp = variables["Positive current collector potential"] i_boundary_cc = variables["Current collector current density"] i_boundary_cc_0 = variables[ "Leading-order current collector current density"] c = variables["Lagrange multiplier"] # Note that the second argument of 'source' must be the same as the argument # in the laplacian (the variable to which the boundary conditions are applied) self.algebraic = { phi_s_cn: (param.sigma_cn * param.delta**2 * param.l_cn) * pybamm.laplacian(phi_s_cn) - pybamm.source(i_boundary_cc_0, phi_s_cn), i_boundary_cc: (param.sigma_cp * param.delta**2 * param.l_cp) * pybamm.laplacian(phi_s_cp) + pybamm.source(i_boundary_cc_0, phi_s_cp) + c * pybamm.PrimaryBroadcast(cc_area, "current collector"), c: pybamm.Integral(i_boundary_cc, z) - applied_current / cc_area + 0 * c, }
def set_algebraic(self, variables): param = self.param phi_s_cn = variables["Negative current collector potential"] phi_s_cp = variables["Positive current collector potential"] i_boundary_cc = variables["Current collector current density"] self.algebraic = { phi_s_cn: (param.sigma_cn * param.delta ** 2 * param.l_cn) * pybamm.laplacian(phi_s_cn) - pybamm.source(i_boundary_cc, phi_s_cn), i_boundary_cc: (param.sigma_cp * param.delta ** 2 * param.l_cp) * pybamm.laplacian(phi_s_cp) + pybamm.source(i_boundary_cc, phi_s_cp), }
def set_rhs(self, variables): T_av = variables["X-averaged cell temperature"] Q_av = variables["X-averaged total heating"] T_amb = variables["Ambient temperature"] # 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 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 # 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) + 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) }
def set_rhs(self, variables): T_av = variables["X-averaged cell temperature"] Q_av = variables["X-averaged total heating"] T_amb = variables["Ambient temperature"] # 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 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 + total_cooling_coefficient * (T_av - T_amb) ) / (self.param.C_th * self.param.rho(T_av)) }
def set_rhs(self, variables): T_av = variables["X-averaged cell temperature"] Q_av = variables["X-averaged total heating"] self.rhs = { T_av: (pybamm.laplacian(T_av) + self.param.B * Q_av - (2 * self.param.h / (self.param.delta**2) / self.param.l) * T_av) / self.param.C_th }
def set_rhs(self, variables): T_av = variables["X-averaged cell temperature"] Q_av = variables["X-averaged total heating"] cooling_coeff = self._surface_cooling_coefficient() self.rhs = { T_av: (pybamm.laplacian(T_av) + self.param.B * Q_av + cooling_coeff * T_av) / self.param.C_th }
def set_rhs(self, variables): T_av = variables["X-averaged cell temperature"] Q_av = variables["X-averaged total heating"] # 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 self.rhs = { T_av: (pybamm.laplacian(T_av) + self.param.B * pybamm.source(Q_av, T_av) - (2 * self.param.h / (self.param.delta**2) / self.param.l) * pybamm.source(T_av, T_av) - (self.param.h / self.param.delta) * pybamm.source(T_av, T_av, boundary=True)) / self.param.C_th }
def test_pure_neumann_poisson(self): # grad^2 u = 1, du/dz = 1 at z = 1, du/dn = 0 elsewhere, u has zero average u = pybamm.Variable("u", domain="current collector") c = pybamm.Variable("c") # lagrange multiplier y = pybamm.SpatialVariable("y", ["current collector"]) z = pybamm.SpatialVariable("z", ["current collector"]) model = pybamm.BaseModel() # 0*c hack otherwise gives KeyError model.algebraic = { u: pybamm.laplacian(u) - pybamm.source(1, u) + c * pybamm.DefiniteIntegralVector(u, vector_type="column"), c: pybamm.Integral(u, [y, z]) + 0 * c, } model.initial_conditions = {u: pybamm.Scalar(0), c: pybamm.Scalar(0)} # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) model.boundary_conditions = { u: { "negative tab": (0, "Neumann"), "positive tab": (1, "Neumann") } } model.variables = {"c": c, "u": u} # create discretisation mesh = get_unit_2p1D_mesh_for_testing(ypts=32, zpts=32, include_particles=False) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) disc.process_model(model) # solve model solver = pybamm.AlgebraicSolver() solution = solver.solve(model) z = mesh["current collector"].coordinates[1, :][:, np.newaxis] u_exact = z**2 / 2 - 1 / 6 np.testing.assert_array_almost_equal(solution.y[:-1], u_exact, decimal=1)
def test_dirichlet_bcs(self): # manufactured solution u = a*z^2 + b*z + c model = pybamm.BaseModel() a = 3 b = 4 c = 5 u = pybamm.Variable("variable", domain="current collector") model.algebraic = {u: -pybamm.laplacian(u) + pybamm.source(2 * a, u)} # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) model.boundary_conditions = { u: { "negative tab": (pybamm.Scalar(c), "Dirichlet"), "positive tab": (pybamm.Scalar(a + b + c), "Dirichlet"), } } # bad initial guess (on purpose) model.initial_conditions = {u: pybamm.Scalar(1)} model.variables = {"u": u} # create discretisation mesh = get_unit_2p1D_mesh_for_testing(ypts=8, zpts=32, include_particles=False) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) disc.process_model(model) # solve model solver = pybamm.AlgebraicSolver() solution = solver.solve(model) # indepedent of y, so just check values for one y z = mesh["current collector"].edges["z"][:, np.newaxis] u_exact = a * z**2 + b * z + c np.testing.assert_array_almost_equal(solution.y[0:len(z)], u_exact)
def __init__(self): super().__init__() self.name = "Effective resistance in current collector model" self.param = pybamm.standard_parameters_lithium_ion # Get useful parameters param = self.param l_cn = param.l_cn l_cp = param.l_cp l_y = param.l_y sigma_cn_dbl_prime = param.sigma_cn_dbl_prime sigma_cp_dbl_prime = param.sigma_cp_dbl_prime alpha_prime = param.alpha_prime # Set model variables var = pybamm.standard_spatial_vars psi = pybamm.Variable("Current collector potential weighted sum", ["current collector"]) W = pybamm.Variable( "Perturbation to current collector potential difference", ["current collector"], ) c_psi = pybamm.Variable("Lagrange multiplier for variable `psi`") c_W = pybamm.Variable("Lagrange multiplier for variable `W`") self.variables = { "Current collector potential weighted sum": psi, "Perturbation to current collector potential difference": W, "Lagrange multiplier for variable `psi`": c_psi, "Lagrange multiplier for variable `W`": c_W, } # Algebraic equations (enforce zero mean constraint through Lagrange multiplier) # 0*LagrangeMultiplier hack otherwise gives KeyError self.algebraic = { psi: pybamm.laplacian(psi) + c_psi * pybamm.DefiniteIntegralVector(psi, vector_type="column"), W: pybamm.laplacian(W) - pybamm.source(1, W) + c_W * pybamm.DefiniteIntegralVector(W, vector_type="column"), c_psi: pybamm.Integral(psi, [var.y, var.z]) + 0 * c_psi, c_W: pybamm.Integral(W, [var.y, var.z]) + 0 * c_W, } # Boundary conditons psi_neg_tab_bc = l_cn psi_pos_tab_bc = -l_cp W_neg_tab_bc = l_y / (alpha_prime * sigma_cn_dbl_prime) W_pos_tab_bc = l_y / (alpha_prime * sigma_cp_dbl_prime) self.boundary_conditions = { psi: { "negative tab": (psi_neg_tab_bc, "Neumann"), "positive tab": (psi_pos_tab_bc, "Neumann"), }, W: { "negative tab": (W_neg_tab_bc, "Neumann"), "positive tab": (W_pos_tab_bc, "Neumann"), }, } # "Initial conditions" provides initial guess for solver # TODO: better guess than zero? self.initial_conditions = { psi: pybamm.Scalar(0), W: pybamm.Scalar(0), c_psi: pybamm.Scalar(0), c_W: pybamm.Scalar(0), } # Define effective current collector resistance psi_neg_tab = pybamm.BoundaryValue(psi, "negative tab") psi_pos_tab = pybamm.BoundaryValue(psi, "positive tab") W_neg_tab = pybamm.BoundaryValue(W, "negative tab") W_pos_tab = pybamm.BoundaryValue(W, "positive tab") R_cc = ((alpha_prime / l_y) * (sigma_cn_dbl_prime * l_cn * W_pos_tab + sigma_cp_dbl_prime * l_cp * W_neg_tab) - (psi_pos_tab - psi_neg_tab)) / (sigma_cn_dbl_prime * l_cn + sigma_cp_dbl_prime * l_cp) R_cc_dim = R_cc * param.potential_scale / param.I_typ self.variables.update({ "Current collector potential weighted sum (negative tab)": psi_neg_tab, "Current collector potential weighted sum (positive tab)": psi_pos_tab, "Perturbation to c.c. potential difference (negative tab)": W_neg_tab, "Perturbation to c.c. potential difference (positive tab)": W_pos_tab, "Effective current collector resistance": R_cc, "Effective current collector resistance [Ohm]": R_cc_dim, })
def __init__(self): super().__init__() self.name = "Effective resistance in current collector model (2D)" self.param = pybamm.standard_parameters_lithium_ion # Get necessary parameters param = self.param l_cn = param.l_cn l_cp = param.l_cp l_tab_p = param.l_tab_p A_tab_p = l_cp * l_tab_p sigma_cn_dbl_prime = param.sigma_cn_dbl_prime sigma_cp_dbl_prime = param.sigma_cp_dbl_prime delta = param.delta # Set model variables -- we solve a auxilliary problem in each current collector # then relate this to the potentials and resistances later f_n = pybamm.Variable("Unit solution in negative current collector", domain="current collector") f_p = pybamm.Variable("Unit solution in positive current collector", domain="current collector") # Governing equations -- we impose that the average of f_p is zero # by introducing a Lagrange multiplier c = pybamm.Variable("Lagrange multiplier") self.algebraic = { f_n: pybamm.laplacian(f_n) + pybamm.source(1, f_n), c: pybamm.laplacian(f_p) - pybamm.source(1, f_p) + c * pybamm.DefiniteIntegralVector(f_p, vector_type="column"), f_p: pybamm.yz_average(f_p) + 0 * c, } # Boundary conditons pos_tab_bc = l_cp / A_tab_p self.boundary_conditions = { f_n: { "negative tab": (0, "Dirichlet"), "positive tab": (0, "Neumann") }, f_p: { "negative tab": (0, "Neumann"), "positive tab": (pos_tab_bc, "Neumann"), }, } # "Initial conditions" provides initial guess for solver self.initial_conditions = { f_n: pybamm.Scalar(0), f_p: pybamm.Scalar(0), c: pybamm.Scalar(0), } # Define effective current collector resistance R_cc_n = delta * pybamm.yz_average(f_n) / (l_cn * sigma_cn_dbl_prime) R_cc_p = (delta * pybamm.BoundaryIntegral(f_p, "positive tab") / (l_cp * sigma_cp_dbl_prime)) R_cc = R_cc_n + R_cc_p R_scale = param.potential_scale / param.I_typ self.variables = { "Unit solution in negative current collector": f_n, "Unit solution in positive current collector": f_p, "Effective current collector resistance": R_cc, "Effective current collector resistance [Ohm]": R_cc * R_scale, "Effective negative current collector resistance": R_cc_n, "Effective negative current collector resistance [Ohm]": R_cc_n * R_scale, "Effective positive current collector resistance": R_cc_p, "Effective positive current collector resistance [Ohm]": R_cc_p * R_scale, } # Add spatial variables var = pybamm.standard_spatial_vars L_y = pybamm.geometric_parameters.L_y L_z = pybamm.geometric_parameters.L_z self.variables.update({ "y": var.y, "y [m]": var.y * L_y, "z": var.z, "z [m]": var.z * L_z }) pybamm.citations.register("timms2020")
def test_manufactured_solution_exponential_grid(self): param = pybamm.ParameterValues( values={ "Electrode width [m]": 1, "Electrode height [m]": 1, "Negative tab width [m]": 1, "Negative tab centre y-coordinate [m]": 0.5, "Negative tab centre z-coordinate [m]": 0, "Positive tab width [m]": 1, "Positive tab centre y-coordinate [m]": 0.5, "Positive tab centre z-coordinate [m]": 1, "Negative electrode thickness [m]": 0.3, "Separator thickness [m]": 0.3, "Positive electrode thickness [m]": 0.3, } ) geometry = pybamm.battery_geometry( include_particles=False, current_collector_dimension=2 ) param.process_geometry(geometry) var = pybamm.standard_spatial_vars var_pts = {var.x_n: 3, var.x_s: 3, var.x_p: 3, var.y: 32, var.z: 32} submesh_types = { "negative electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "separator": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "positive electrode": pybamm.MeshGenerator(pybamm.Uniform1DSubMesh), "current collector": pybamm.MeshGenerator( pybamm.ScikitExponential2DSubMesh ), } mesh = pybamm.Mesh(geometry, submesh_types, var_pts) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) # laplace of u = cos(pi*y)*sin(pi*z) var = pybamm.Variable("var", domain="current collector") laplace_eqn = pybamm.laplacian(var) # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Dirichlet"), } } disc.set_variable_slices([var]) laplace_eqn_disc = disc.process_symbol(laplace_eqn) y_vertices = mesh["current collector"].coordinates[0, :][:, np.newaxis] z_vertices = mesh["current collector"].coordinates[1, :][:, np.newaxis] u = np.cos(np.pi * y_vertices) * np.sin(np.pi * z_vertices) mass = pybamm.Mass(var) mass_disc = disc.process_symbol(mass) soln = -np.pi ** 2 * u np.testing.assert_array_almost_equal( laplace_eqn_disc.evaluate(None, u), mass_disc.entries @ soln, decimal=1 )
def test_discretise_equations(self): # get mesh mesh = get_2p1d_mesh_for_testing(include_particles=False) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) # discretise some equations var = pybamm.Variable("var", domain="current collector") y = pybamm.SpatialVariable("y", ["current collector"]) z = pybamm.SpatialVariable("z", ["current collector"]) disc.set_variable_slices([var]) y_test = np.ones(mesh["current collector"].npts) unit_source = pybamm.PrimaryBroadcast(1, "current collector") disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Neumann"), "positive tab": (pybamm.Scalar(0), "Neumann"), } } for eqn in [ pybamm.laplacian(var), pybamm.source(unit_source, var), pybamm.laplacian(var) - pybamm.source(unit_source, var), pybamm.source(var, var), pybamm.laplacian(var) - pybamm.source(2 * var, var), pybamm.laplacian(var) - pybamm.source(unit_source ** 2 + 1 / var, var), pybamm.Integral(var, [y, z]) - 1, pybamm.source(var, var, boundary=True), pybamm.laplacian(var) - pybamm.source(unit_source, var, boundary=True), pybamm.laplacian(var) - pybamm.source(unit_source ** 2 + 1 / var, var, boundary=True), ]: # Check that equation can be evaluated in each case # Dirichlet disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(1), "Dirichlet"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # Neumann disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Neumann"), "positive tab": (pybamm.Scalar(1), "Neumann"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # One of each disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Neumann"), "positive tab": (pybamm.Scalar(1), "Dirichlet"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # One of each disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(1), "Neumann"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # check ValueError raised for non Dirichlet or Neumann BCs eqn = pybamm.laplacian(var) - pybamm.source(unit_source, var) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(1), "Other BC"), } } with self.assertRaises(ValueError): eqn_disc = disc.process_symbol(eqn) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Other BC"), "positive tab": (pybamm.Scalar(1), "Neumann"), } } with self.assertRaises(ValueError): eqn_disc = disc.process_symbol(eqn) # raise ModelError if no BCs provided new_var = pybamm.Variable("new_var", domain="current collector") disc.set_variable_slices([new_var]) eqn = pybamm.laplacian(new_var) with self.assertRaises(pybamm.ModelError): eqn_disc = disc.process_symbol(eqn) # check GeometryError if using scikit-fem not in y or z x = pybamm.SpatialVariable("x", ["current collector"]) with self.assertRaises(pybamm.GeometryError): disc.process_symbol(x)
def test_manufactured_solution(self): mesh = get_unit_2p1D_mesh_for_testing(ypts=32, zpts=32, include_particles=False) spatial_methods = { "macroscale": pybamm.FiniteVolume(), "current collector": pybamm.ScikitFiniteElement(), } disc = pybamm.Discretisation(mesh, spatial_methods) # linear u = z (to test coordinates to degree of freedom mapping) var = pybamm.Variable("var", domain="current collector") disc.set_variable_slices([var]) var_disc = disc.process_symbol(var) z_vertices = mesh["current collector"].coordinates[1, :] np.testing.assert_array_almost_equal( var_disc.evaluate(None, z_vertices), z_vertices[:, np.newaxis] ) # linear u = 6*y (to test coordinates to degree of freedom mapping) y_vertices = mesh["current collector"].coordinates[0, :] np.testing.assert_array_almost_equal( var_disc.evaluate(None, 6 * y_vertices), 6 * y_vertices[:, np.newaxis] ) # mixed u = y*z (to test coordinates to degree of freedom mapping) np.testing.assert_array_almost_equal( var_disc.evaluate(None, y_vertices * z_vertices), y_vertices[:, np.newaxis] * z_vertices[:, np.newaxis], ) # laplace of u = sin(pi*z) var = pybamm.Variable("var", domain="current collector") eqn_zz = pybamm.laplacian(var) # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Dirichlet"), } } disc.set_variable_slices([var]) eqn_zz_disc = disc.process_symbol(eqn_zz) z_vertices = mesh["current collector"].coordinates[1, :][:, np.newaxis] u = np.sin(np.pi * z_vertices) mass = pybamm.Mass(var) mass_disc = disc.process_symbol(mass) soln = -np.pi ** 2 * u np.testing.assert_array_almost_equal( eqn_zz_disc.evaluate(None, u), mass_disc.entries @ soln, decimal=3 ) # laplace of u = cos(pi*y)*sin(pi*z) var = pybamm.Variable("var", domain="current collector") laplace_eqn = pybamm.laplacian(var) # set boundary conditions ("negative tab" = bottom of unit square, # "positive tab" = top of unit square, elsewhere normal derivative is zero) disc.bcs = { var.id: { "negative tab": (pybamm.Scalar(0), "Dirichlet"), "positive tab": (pybamm.Scalar(0), "Dirichlet"), } } disc.set_variable_slices([var]) laplace_eqn_disc = disc.process_symbol(laplace_eqn) y_vertices = mesh["current collector"].coordinates[0, :][:, np.newaxis] z_vertices = mesh["current collector"].coordinates[1, :][:, np.newaxis] u = np.cos(np.pi * y_vertices) * np.sin(np.pi * z_vertices) mass = pybamm.Mass(var) mass_disc = disc.process_symbol(mass) soln = -np.pi ** 2 * u np.testing.assert_array_almost_equal( laplace_eqn_disc.evaluate(None, u), mass_disc.entries @ soln, decimal=2 )
def test_discretise_diffusivity_times_spatial_operator(self): # Set up whole_cell = ["negative electrode", "separator", "positive electrode"] # create discretisation mesh = get_mesh_for_testing() spatial_methods = {"macroscale": pybamm.FiniteVolume()} disc = pybamm.Discretisation(mesh, spatial_methods) combined_submesh = mesh.combine_submeshes(*whole_cell) # Discretise some equations where averaging is needed var = pybamm.Variable("var", domain=whole_cell) disc.set_variable_slices([var]) y_test = np.ones_like(combined_submesh[0].nodes[:, np.newaxis]) for eqn in [ var * pybamm.grad(var), var**2 * pybamm.grad(var), var * pybamm.grad(var)**2, var * (pybamm.grad(var) + 2), (pybamm.grad(var) + 2) * (-var), (pybamm.grad(var) + 2) * (2 * var), pybamm.grad(var) * pybamm.grad(var), (pybamm.grad(var) + 2) * pybamm.grad(var)**2, pybamm.div(pybamm.grad(var)), pybamm.div(pybamm.grad(var)) + 2, pybamm.div(pybamm.grad(var)) + var, pybamm.div(2 * pybamm.grad(var)), pybamm.div(2 * pybamm.grad(var)) + 3 * var, -2 * pybamm.div(var * pybamm.grad(var) + 2 * pybamm.grad(var)), pybamm.laplacian(var), ]: # Check that the equation can be evaluated in each case # Dirichlet disc.bcs = { var.id: { "left": (pybamm.Scalar(0), "Dirichlet"), "right": (pybamm.Scalar(1), "Dirichlet"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # Neumann disc.bcs = { var.id: { "left": (pybamm.Scalar(0), "Neumann"), "right": (pybamm.Scalar(1), "Neumann"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) # One of each disc.bcs = { var.id: { "left": (pybamm.Scalar(0), "Dirichlet"), "right": (pybamm.Scalar(1), "Neumann"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test) disc.bcs = { var.id: { "left": (pybamm.Scalar(0), "Neumann"), "right": (pybamm.Scalar(1), "Dirichlet"), } } eqn_disc = disc.process_symbol(eqn) eqn_disc.evaluate(None, y_test)