def test_gradient(self): # gradient of scalar symbol should fail a = pybamm.Symbol("a") with self.assertRaisesRegex( pybamm.DomainError, "Cannot take gradient of 'a' since its domain is empty"): pybamm.Gradient(a) # gradient of variable evaluating on edges should fail a = pybamm.PrimaryBroadcastToEdges(pybamm.Scalar(1), "test") with self.assertRaisesRegex(TypeError, "evaluates on edges"): pybamm.Gradient(a) # gradient of broadcast should return broadcasted zero a = pybamm.PrimaryBroadcast(pybamm.Variable("a"), "test domain") grad = pybamm.grad(a) self.assertIsInstance(grad, pybamm.PrimaryBroadcastToEdges) self.assertIsInstance(grad.child, pybamm.PrimaryBroadcast) self.assertIsInstance(grad.child.child, pybamm.Scalar) self.assertEqual(grad.child.child.value, 0) # otherwise gradient should work a = pybamm.Symbol("a", domain="test domain") grad = pybamm.Gradient(a) self.assertEqual(grad.children[0].name, a.name) self.assertEqual(grad.domain, a.domain)
def test_div(self): # divergence of scalar symbol should fail a = pybamm.Symbol("a") with self.assertRaisesRegex( pybamm.DomainError, "Cannot take divergence of 'a' since its domain is empty", ): pybamm.Divergence(a) # divergence of variable evaluating on edges should fail a = pybamm.PrimaryBroadcast(pybamm.Scalar(1), "test") with self.assertRaisesRegex(TypeError, "evaluate on edges"): pybamm.Divergence(a) # divergence of broadcast should return broadcasted zero a = pybamm.PrimaryBroadcastToEdges(pybamm.Variable("a"), "test domain") div = pybamm.div(a) self.assertIsInstance(div, pybamm.PrimaryBroadcast) self.assertIsInstance(div.child, pybamm.PrimaryBroadcast) self.assertIsInstance(div.child.child, pybamm.Scalar) self.assertEqual(div.child.child.value, 0) # otherwise divergence should work a = pybamm.Symbol("a", domain="test domain") div = pybamm.Divergence(pybamm.Gradient(a)) self.assertEqual(div.domain, a.domain) # check div commutes with negation a = pybamm.Symbol("a", domain="test domain") div = pybamm.div(-pybamm.Gradient(a)) self.assertEqual(div.id, (-pybamm.Divergence(pybamm.Gradient(a))).id)
def test_to_equation(self): a = pybamm.Symbol("a", domain="negative particle") b = pybamm.Symbol("b", domain="current collector") c = pybamm.Symbol("c", domain="test") # Test print_name pybamm.Floor.print_name = "test" self.assertEqual(pybamm.Floor(-2.5).to_equation(), sympy.symbols("test")) # Test Negate self.assertEqual(pybamm.Negate(4).to_equation(), -4.0) # Test AbsoluteValue self.assertEqual(pybamm.AbsoluteValue(-4).to_equation(), 4.0) # Test Gradient self.assertEqual(pybamm.Gradient(a).to_equation(), sympy_Gradient("a")) # Test Divergence self.assertEqual( pybamm.Divergence(pybamm.Gradient(a)).to_equation(), sympy_Divergence(sympy_Gradient(a)), ) # Test BoundaryValue self.assertEqual( pybamm.BoundaryValue(a, "right").to_equation(), sympy.symbols("a^{surf}") ) self.assertEqual( pybamm.BoundaryValue(b, "positive tab").to_equation(), sympy.symbols(str(b)) ) self.assertEqual( pybamm.BoundaryValue(c, "left").to_equation(), sympy.symbols("c^{left}") )
def test_process_symbol(self): parameter_values = pybamm.ParameterValues({"a": 4, "b": 2, "c": 3}) # process parameter a = pybamm.Parameter("a") processed_a = parameter_values.process_symbol(a) self.assertIsInstance(processed_a, pybamm.Scalar) self.assertEqual(processed_a.value, 4) # process binary operation var = pybamm.Variable("var") add = a + var processed_add = parameter_values.process_symbol(add) self.assertIsInstance(processed_add, pybamm.Addition) self.assertIsInstance(processed_add.children[0], pybamm.Scalar) self.assertIsInstance(processed_add.children[1], pybamm.Variable) self.assertEqual(processed_add.children[0].value, 4) b = pybamm.Parameter("b") add = a + b processed_add = parameter_values.process_symbol(add) self.assertIsInstance(processed_add, pybamm.Scalar) self.assertEqual(processed_add.value, 6) scal = pybamm.Scalar(34) mul = a * scal processed_mul = parameter_values.process_symbol(mul) self.assertIsInstance(processed_mul, pybamm.Scalar) self.assertEqual(processed_mul.value, 136) # process integral aa = pybamm.Parameter("a", domain=["negative electrode"]) x = pybamm.SpatialVariable("x", domain=["negative electrode"]) integ = pybamm.Integral(aa, x) processed_integ = parameter_values.process_symbol(integ) self.assertIsInstance(processed_integ, pybamm.Integral) self.assertIsInstance(processed_integ.children[0], pybamm.Scalar) self.assertEqual(processed_integ.children[0].value, 4) self.assertEqual(processed_integ.integration_variable[0].id, x.id) # process unary operation v = pybamm.Variable("v", domain="test") grad = pybamm.Gradient(v) processed_grad = parameter_values.process_symbol(grad) self.assertIsInstance(processed_grad, pybamm.Gradient) self.assertIsInstance(processed_grad.children[0], pybamm.Variable) # process delta function aa = pybamm.Parameter("a") delta_aa = pybamm.DeltaFunction(aa, "left", "some domain") processed_delta_aa = parameter_values.process_symbol(delta_aa) self.assertIsInstance(processed_delta_aa, pybamm.DeltaFunction) self.assertEqual(processed_delta_aa.side, "left") processed_a = processed_delta_aa.children[0] self.assertIsInstance(processed_a, pybamm.Scalar) self.assertEqual(processed_a.value, 4) # process boundary operator (test for BoundaryValue) aa = pybamm.Parameter("a", domain=["negative electrode"]) x = pybamm.SpatialVariable("x", domain=["negative electrode"]) boundary_op = pybamm.BoundaryValue(aa * x, "left") processed_boundary_op = parameter_values.process_symbol(boundary_op) self.assertIsInstance(processed_boundary_op, pybamm.BoundaryOperator) processed_a = processed_boundary_op.children[0].children[0] processed_x = processed_boundary_op.children[0].children[1] self.assertIsInstance(processed_a, pybamm.Scalar) self.assertEqual(processed_a.value, 4) self.assertEqual(processed_x.id, x.id) # process broadcast whole_cell = ["negative electrode", "separator", "positive electrode"] broad = pybamm.PrimaryBroadcast(a, whole_cell) processed_broad = parameter_values.process_symbol(broad) self.assertIsInstance(processed_broad, pybamm.Broadcast) self.assertEqual(processed_broad.domain, whole_cell) self.assertIsInstance(processed_broad.children[0], pybamm.Scalar) self.assertEqual(processed_broad.children[0].evaluate(), 4) # process concatenation conc = pybamm.concatenation( pybamm.Vector(np.ones(10), domain="test"), pybamm.Vector(2 * np.ones(15), domain="test 2"), ) processed_conc = parameter_values.process_symbol(conc) self.assertIsInstance(processed_conc.children[0], pybamm.Vector) self.assertIsInstance(processed_conc.children[1], pybamm.Vector) np.testing.assert_array_equal(processed_conc.children[0].entries, 1) np.testing.assert_array_equal(processed_conc.children[1].entries, 2) # process domain concatenation c_e_n = pybamm.Variable("c_e_n", ["negative electrode"]) c_e_s = pybamm.Variable("c_e_p", ["separator"]) test_mesh = shared.get_mesh_for_testing() dom_con = pybamm.DomainConcatenation([a * c_e_n, b * c_e_s], test_mesh) processed_dom_con = parameter_values.process_symbol(dom_con) a_proc = processed_dom_con.children[0].children[0] b_proc = processed_dom_con.children[1].children[0] self.assertIsInstance(a_proc, pybamm.Scalar) self.assertIsInstance(b_proc, pybamm.Scalar) self.assertEqual(a_proc.value, 4) self.assertEqual(b_proc.value, 2) # process variable c = pybamm.Variable("c") processed_c = parameter_values.process_symbol(c) self.assertIsInstance(processed_c, pybamm.Variable) self.assertEqual(processed_c.name, "c") # process scalar d = pybamm.Scalar(14) processed_d = parameter_values.process_symbol(d) self.assertIsInstance(processed_d, pybamm.Scalar) self.assertEqual(processed_d.value, 14) # process array types e = pybamm.Vector(np.ones(4)) processed_e = parameter_values.process_symbol(e) self.assertIsInstance(processed_e, pybamm.Vector) np.testing.assert_array_equal(processed_e.evaluate(), np.ones((4, 1))) f = pybamm.Matrix(np.ones((5, 6))) processed_f = parameter_values.process_symbol(f) self.assertIsInstance(processed_f, pybamm.Matrix) np.testing.assert_array_equal(processed_f.evaluate(), np.ones((5, 6))) # process statevector g = pybamm.StateVector(slice(0, 10)) processed_g = parameter_values.process_symbol(g) self.assertIsInstance(processed_g, pybamm.StateVector) np.testing.assert_array_equal( processed_g.evaluate(y=np.ones(10)), np.ones((10, 1)) ) # not implemented sym = pybamm.Symbol("sym") with self.assertRaises(NotImplementedError): parameter_values.process_symbol(sym) # not found with self.assertRaises(KeyError): x = pybamm.Parameter("x") parameter_values.process_symbol(x)
def test_gradient(self): a = pybamm.Symbol("a") grad = pybamm.Gradient(a) self.assertEqual(grad.children[0].name, a.name)
def test_printing(self): a = pybamm.Symbol("a") self.assertEqual(str(-a), "-a") grad = pybamm.Gradient(a) self.assertEqual(grad.name, "grad") self.assertEqual(str(grad), "grad(a)")