def get_fundamental_variables(self): # Get necessary parameters param = self.param l_cn = param.l_cn l_cp = param.l_cp sigma_cn_dbl_prime = param.sigma_cn_dbl_prime sigma_cp_dbl_prime = param.sigma_cp_dbl_prime delta = param.delta # aspect ratio # Set model variables: Note: we solve using a scaled version that is # better conditioned R_cn_scaled = pybamm.Variable( "Scaled negative current collector resistance", domain="current collector" ) R_cp_scaled = pybamm.Variable( "Scaled positive current collector resistance", domain="current collector" ) R_cn = delta * R_cn_scaled / (l_cn * sigma_cn_dbl_prime) R_cp = delta * R_cp_scaled / (l_cp * sigma_cp_dbl_prime) # Define effective current collector resistance if self.options["dimensionality"] == 1: R_cc_n = -pybamm.z_average(R_cn) R_cc_p = -pybamm.z_average(R_cp) elif self.options["dimensionality"] == 2: R_cc_n = -pybamm.yz_average(R_cn) R_cc_p = -pybamm.yz_average(R_cp) R_cc = R_cc_n + R_cc_p R_scale = param.potential_scale / param.I_typ variables = { "Scaled negative current collector resistance": R_cn_scaled, "Negative current collector resistance": R_cn, "Negative current collector resistance [Ohm]": R_cn * R_scale, "Scaled positive current collector resistance": R_cp_scaled, "Positive current collector resistance": R_cp, "Positive current collector resistance [Ohm]": R_cp * R_scale, "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 if self.options["dimensionality"] == 1: variables.update({"z": var.z, "z [m]": var.z * L_z}) elif self.options["dimensionality"] == 2: variables.update( {"y": var.y, "y [m]": var.y * L_y, "z": var.z, "z [m]": var.z * L_z} ) return variables
def _yz_average(self, var): "Computes the y-z average" # TODO: change the behaviour of z_average and yz_average so the if statement # can be removed if self.cc_dimension in [0, 1]: return pybamm.z_average(var) elif self.cc_dimension == 2: return pybamm.yz_average(var)
def test_yz_average(self): a = pybamm.Scalar(1) z_average_a = pybamm.z_average(a) yz_average_a = pybamm.yz_average(a) self.assertEqual(z_average_a.id, a.id) self.assertEqual(yz_average_a.id, a.id) z_average_broad_a = pybamm.z_average( pybamm.PrimaryBroadcast(a, ["current collector"])) yz_average_broad_a = pybamm.yz_average( pybamm.PrimaryBroadcast(a, ["current collector"])) self.assertEqual(z_average_broad_a.evaluate(), np.array([1])) self.assertEqual(yz_average_broad_a.evaluate(), np.array([1])) a = pybamm.Variable("a", domain=["current collector"]) y = pybamm.SpatialVariable("y", ["current collector"]) z = pybamm.SpatialVariable("z", ["current collector"]) z_av_a = pybamm.z_average(a) yz_av_a = pybamm.yz_average(a) self.assertIsInstance(yz_av_a, pybamm.Division) self.assertIsInstance(z_av_a, pybamm.Division) self.assertIsInstance(z_av_a.children[0], pybamm.Integral) self.assertIsInstance(yz_av_a.children[0], pybamm.Integral) self.assertEqual(z_av_a.children[0].integration_variable[0].domain, z.domain) self.assertEqual(yz_av_a.children[0].integration_variable[0].domain, y.domain) self.assertEqual(yz_av_a.children[0].integration_variable[1].domain, z.domain) self.assertIsInstance(z_av_a.children[1], pybamm.Integral) self.assertIsInstance(yz_av_a.children[1], pybamm.Integral) self.assertEqual(z_av_a.children[1].integration_variable[0].domain, a.domain) self.assertEqual(z_av_a.children[1].children[0].id, pybamm.ones_like(a).id) self.assertEqual(yz_av_a.children[1].integration_variable[0].domain, y.domain) self.assertEqual(yz_av_a.children[1].integration_variable[0].domain, z.domain) self.assertEqual(yz_av_a.children[1].children[0].id, pybamm.ones_like(a).id) self.assertEqual(z_av_a.domain, []) self.assertEqual(yz_av_a.domain, []) a = pybamm.Symbol("a", domain="bad domain") with self.assertRaises(pybamm.DomainError): pybamm.z_average(a) with self.assertRaises(pybamm.DomainError): pybamm.yz_average(a) # average of symbol that evaluates on edges raises error symbol_on_edges = pybamm.PrimaryBroadcastToEdges(1, "domain") with self.assertRaisesRegex( ValueError, "Can't take the z-average of a symbol that evaluates on edges" ): pybamm.z_average(symbol_on_edges)
def test_yz_average(self): a = pybamm.Scalar(1) z_average_a = pybamm.z_average(a) yz_average_a = pybamm.yz_average(a) self.assertEqual(z_average_a.id, a.id) self.assertEqual(yz_average_a.id, a.id) z_average_broad_a = pybamm.z_average( pybamm.Broadcast(a, ["current collector"])) yz_average_broad_a = pybamm.yz_average( pybamm.Broadcast(a, ["current collector"])) self.assertEqual(z_average_broad_a.evaluate(), np.array([1])) self.assertEqual(yz_average_broad_a.evaluate(), np.array([1])) a = pybamm.Symbol("a", domain=["current collector"]) y = pybamm.SpatialVariable("y", ["current collector"]) z = pybamm.SpatialVariable("z", ["current collector"]) z_av_a = pybamm.z_average(a) yz_av_a = pybamm.yz_average(a) self.assertIsInstance(z_av_a, pybamm.Division) self.assertIsInstance(yz_av_a, pybamm.Division) self.assertIsInstance(z_av_a.children[0], pybamm.Integral) self.assertIsInstance(yz_av_a.children[0], pybamm.Integral) self.assertEqual(z_av_a.children[0].integration_variable[0].domain, z.domain) self.assertEqual(yz_av_a.children[0].integration_variable[0].domain, y.domain) self.assertEqual(yz_av_a.children[0].integration_variable[1].domain, z.domain) self.assertEqual(z_av_a.domain, []) self.assertEqual(yz_av_a.domain, []) a = pybamm.Symbol("a", domain="bad domain") with self.assertRaises(pybamm.DomainError): pybamm.z_average(a) with self.assertRaises(pybamm.DomainError): pybamm.yz_average(a)
def test_averages(self): # create discretisation disc = get_discretisation_for_testing( cc_method=pybamm.ZeroDimensionalSpatialMethod) # create and discretise variable var = pybamm.Variable("var", domain="current collector") disc.set_variable_slices([var]) var_disc = disc.process_symbol(var) # check average returns the same value y = np.array([1]) for expression in [pybamm.z_average(var), pybamm.yz_average(var)]: expr_disc = disc.process_symbol(expression) np.testing.assert_array_equal(var_disc.evaluate(y=y), expr_disc.evaluate(y=y))
def _yz_average(self, var): """Computes the y-z average by integration over z (no y-direction)""" return pybamm.z_average(var)