def test_advanced_functions(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) y = np.array([5, 3]) # func = a * pybamm.exp(b) self.assertAlmostEqual(func.diff(a).evaluate(y=y)[0], np.exp(3)) func = pybamm.exp(a + 2 * b + a * b) + a * pybamm.exp(b) self.assertEqual( func.diff(a).evaluate(y=y), (4 * np.exp(3 * 5 + 5 + 2 * 3) + np.exp(3)) ) self.assertEqual( func.diff(b).evaluate(y=y), np.exp(3) * (7 * np.exp(3 * 5 + 5 + 3) + 5) ) # func = pybamm.sin(pybamm.cos(a * 4) / 2) * pybamm.cos(4 * pybamm.exp(b / 3)) self.assertEqual( func.diff(a).evaluate(y=y), -2 * np.sin(20) * np.cos(np.cos(20) / 2) * np.cos(4 * np.exp(1)), ) self.assertEqual( func.diff(b).evaluate(y=y), -4 / 3 * np.exp(1) * np.sin(4 * np.exp(1)) * np.sin(np.cos(20) / 2), ) # func = pybamm.sin(a * b) self.assertEqual(func.diff(a).evaluate(y=y), 3 * np.cos(15))
def test_shape_and_size_for_testing(self): scal = pybamm.Scalar(1) self.assertEqual(scal.shape_for_testing, scal.shape) self.assertEqual(scal.size_for_testing, scal.size) state = pybamm.StateVector(slice(10, 25), domain="test") state2 = pybamm.StateVector(slice(10, 25), domain="test 2") self.assertEqual(state.shape_for_testing, state.shape) param = pybamm.Parameter("a") self.assertEqual(param.shape_for_testing, ()) func = pybamm.FunctionParameter("func", {"state": state}) self.assertEqual(func.shape_for_testing, state.shape_for_testing) concat = pybamm.concatenation(state, state2) self.assertEqual(concat.shape_for_testing, (30, 1)) self.assertEqual(concat.size_for_testing, 30) var = pybamm.Variable("var", domain="negative electrode") broadcast = pybamm.PrimaryBroadcast(0, "negative electrode") self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing) self.assertEqual((var + broadcast).shape_for_testing, broadcast.shape_for_testing) var = pybamm.Variable("var", domain=["random domain", "other domain"]) broadcast = pybamm.PrimaryBroadcast(0, ["random domain", "other domain"]) self.assertEqual(var.shape_for_testing, broadcast.shape_for_testing) self.assertEqual((var + broadcast).shape_for_testing, broadcast.shape_for_testing) sym = pybamm.Symbol("sym") with self.assertRaises(NotImplementedError): sym.shape_for_testing
def test_known_eval(self): # Scalars a = pybamm.Scalar(4) b = pybamm.StateVector(slice(0, 1)) expr = (a + b) - (a + b) * (a + b) value = expr.evaluate(y=np.array([2])) self.assertEqual(expr.evaluate(y=np.array([2]), known_evals={})[0], value) self.assertIn((a + b).id, expr.evaluate(y=np.array([2]), known_evals={})[1]) self.assertEqual( expr.evaluate(y=np.array([2]), known_evals={})[1][(a + b).id], 6 ) # Matrices a = pybamm.Matrix(np.random.rand(5, 5)) b = pybamm.StateVector(slice(0, 5)) expr2 = (a @ b) - (a @ b) * (a @ b) + (a @ b) y_test = np.linspace(0, 1, 5) value = expr2.evaluate(y=y_test) np.testing.assert_array_equal( expr2.evaluate(y=y_test, known_evals={})[0], value ) self.assertIn((a @ b).id, expr2.evaluate(y=y_test, known_evals={})[1]) np.testing.assert_array_equal( expr2.evaluate(y=y_test, known_evals={})[1][(a @ b).id], (a @ b).evaluate(y=y_test), )
def test_interpolation(self): x = np.linspace(0, 1) y = pybamm.StateVector(slice(0, 2)) casadi_y = casadi.MX.sym("y", 2) # linear y_test = np.array([0.4, 0.6]) for interpolator in ["linear", "pchip", "cubic spline"]: interp = pybamm.Interpolant(x, 2 * x, y, interpolator=interpolator) interp_casadi = interp.to_casadi(y=casadi_y) f = casadi.Function("f", [casadi_y], [interp_casadi]) np.testing.assert_array_almost_equal(interp.evaluate(y=y_test), f(y_test)) # square y = pybamm.StateVector(slice(0, 1)) for interpolator in ["pchip", "cubic spline"]: interp = pybamm.Interpolant(x, x**2, y, interpolator=interpolator) interp_casadi = interp.to_casadi(y=casadi_y) f = casadi.Function("f", [casadi_y], [interp_casadi]) np.testing.assert_array_almost_equal(interp.evaluate(y=y_test), f(y_test)) # len(x)=1 but y is 2d y = pybamm.StateVector(slice(0, 1)) casadi_y = casadi.MX.sym("y", 1) data = np.tile(2 * x, (10, 1)).T y_test = np.array([0.4]) for interpolator in ["linear", "pchip", "cubic spline"]: interp = pybamm.Interpolant(x, data, y, interpolator=interpolator) interp_casadi = interp.to_casadi(y=casadi_y) f = casadi.Function("f", [casadi_y], [interp_casadi]) np.testing.assert_array_almost_equal(interp.evaluate(y=y_test), f(y_test))
def test_diff(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) y = np.array([5]) func = pybamm.Function(test_function, a) self.assertEqual(func.diff(a).evaluate(y=y), 2) self.assertEqual(func.diff(func).evaluate(), 1) func = pybamm.sin(a) self.assertEqual(func.evaluate(y=y), np.sin(a.evaluate(y=y))) self.assertEqual(func.diff(a).evaluate(y=y), np.cos(a.evaluate(y=y))) func = pybamm.exp(a) self.assertEqual(func.evaluate(y=y), np.exp(a.evaluate(y=y))) self.assertEqual(func.diff(a).evaluate(y=y), np.exp(a.evaluate(y=y))) # multiple variables func = pybamm.Function(test_multi_var_function, 4 * a, 3 * a) self.assertEqual(func.diff(a).evaluate(y=y), 7) func = pybamm.Function(test_multi_var_function, 4 * a, 3 * b) self.assertEqual(func.diff(a).evaluate(y=np.array([5, 6])), 4) self.assertEqual(func.diff(b).evaluate(y=np.array([5, 6])), 3) func = pybamm.Function(test_multi_var_function_cube, 4 * a, 3 * b) self.assertEqual(func.diff(a).evaluate(y=np.array([5, 6])), 4) self.assertEqual( func.diff(b).evaluate(y=np.array([5, 6])), 3 * 3 * (3 * 6) ** 2 ) # exceptions func = pybamm.Function( test_multi_var_function_cube, 4 * a, 3 * b, derivative="derivative" ) with self.assertRaises(ValueError): func.diff(a)
def test_interpolation(self): x = np.linspace(0, 1)[:, np.newaxis] y = pybamm.StateVector(slice(0, 2)) # linear linear = np.hstack([x, 2 * x]) for interpolator in ["pchip", "cubic spline"]: interp = pybamm.Interpolant(linear, y, interpolator=interpolator) np.testing.assert_array_almost_equal( interp.evaluate(y=np.array([0.397, 1.5]))[:, 0], np.array([0.794, 3])) # square square = np.hstack([x, x**2]) y = pybamm.StateVector(slice(0, 1)) for interpolator in ["pchip", "cubic spline"]: interp = pybamm.Interpolant(square, y, interpolator=interpolator) np.testing.assert_array_almost_equal( interp.evaluate(y=np.array([0.397]))[:, 0], np.array([0.397**2])) # with extrapolation set to False for interpolator in ["pchip", "cubic spline"]: interp = pybamm.Interpolant(square, y, interpolator=interpolator, extrapolate=False) np.testing.assert_array_equal( interp.evaluate(y=np.array([2]))[:, 0], np.array([np.nan]))
def test_test_shape(self): # right shape, passes y1 = pybamm.StateVector(slice(0, 10)) y1.test_shape() # bad shape, fails y2 = pybamm.StateVector(slice(0, 5)) with self.assertRaises(pybamm.ShapeError): (y1 + y2).test_shape()
def test_name(self): sv = pybamm.StateVector(slice(0, 10)) self.assertEqual(sv.name, "y[0:10]") sv = pybamm.StateVector(slice(0, 10), slice(20, 30)) self.assertEqual(sv.name, "y[0:10,20:30]") sv = pybamm.StateVector(slice(0, 10), slice(20, 30), slice(40, 50), slice(60, 70)) self.assertEqual(sv.name, "y[0:10,20:30,...,60:70]")
def test_functions(self): y = pybamm.StateVector(slice(0, 4)) u = pybamm.StateVector(slice(0, 2)) v = pybamm.StateVector(slice(2, 4)) const = pybamm.Scalar(1) y0 = np.array([1.0, 2.0, 3.0, 4.0]) func = pybamm.sin(u) jacobian = np.array([[np.cos(1), 0, 0, 0], [0, np.cos(2), 0, 0]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.cos(v) jacobian = np.array([[0, 0, -np.sin(3), 0], [0, 0, 0, -np.sin(4)]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.sin(3 * u * v) jacobian = np.array( [ [9 * np.cos(9), 0, 3 * np.cos(9), 0], [0, 12 * np.cos(24), 0, 6 * np.cos(24)], ] ) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.cos(5 * pybamm.exp(u + v)) jacobian = np.array( [ [ -5 * np.exp(4) * np.sin(5 * np.exp(4)), 0, -5 * np.exp(4) * np.sin(5 * np.exp(4)), 0, ], [ 0, -5 * np.exp(6) * np.sin(5 * np.exp(6)), 0, -5 * np.exp(6) * np.sin(5 * np.exp(6)), ], ] ) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) # when child evaluates to number func = pybamm.Sin(const) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(0, dfunc_dy) # several children func = pybamm.Function(test_multi_var_function, 2 * y, 3 * y) jacobian = np.diag(5 * np.ones(4)) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray())
def test_nonlinear(self): y = pybamm.StateVector(slice(0, 8)) u = pybamm.StateVector(slice(0, 2), slice(4, 6)) v = pybamm.StateVector(slice(2, 4), slice(6, 8)) y0 = np.arange(1, 9) func = v**2 jacobian = np.array([ [0, 0, 6, 0, 0, 0, 0, 0], [0, 0, 0, 8, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 14, 0], [0, 0, 0, 0, 0, 0, 0, 16], ]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = 2**v jacobian = np.array([ [0, 0, 2**3 * np.log(2), 0, 0, 0, 0, 0], [0, 0, 0, 2**4 * np.log(2), 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 2**7 * np.log(2), 0], [0, 0, 0, 0, 0, 0, 0, 2**8 * np.log(2)], ]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = v**v jacobian = [ [0, 0, 27 * (1 + np.log(3)), 0, 0, 0, 0, 0], [0, 0, 0, 256 * (1 + np.log(4)), 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 823543 * (1 + np.log(7)), 0], [0, 0, 0, 0, 0, 0, 0, 16777216 * (1 + np.log(8))], ] dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_almost_equal(jacobian, dfunc_dy.toarray()) func = u * v jacobian = np.array([ [3, 0, 1, 0, 0, 0, 0, 0], [0, 4, 0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 7, 0, 5, 0], [0, 0, 0, 0, 0, 8, 0, 6], ]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = u * (u + v) jacobian = np.array([ [5, 0, 1, 0, 0, 0, 0, 0], [0, 8, 0, 2, 0, 0, 0, 0], [0, 0, 0, 0, 17, 0, 5, 0], [0, 0, 0, 0, 0, 20, 0, 6], ]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray())
def test_interpolation_2_x_2d_y(self): x = (np.arange(-5.01, 5.01, 0.05), np.arange(-5.01, 5.01, 0.05)) xx, yy = np.meshgrid(x[0], x[1]) z = np.sin(xx**2 + yy**2) var1 = pybamm.StateVector(slice(0, 1)) var2 = pybamm.StateVector(slice(1, 2)) # linear interp = pybamm.Interpolant(x, z, (var1, var2), interpolator="linear") np.testing.assert_array_almost_equal( interp.evaluate(y=np.array([0, 0])), 0, decimal=3)
def test_jac_of_inner(self): a = pybamm.Scalar(1) b = pybamm.Scalar(2) y = pybamm.StateVector(slice(0, 1)) self.assertEqual(pybamm.inner(a, b).jac(y).evaluate(), 0) self.assertEqual(pybamm.inner(a, y).jac(y).evaluate(), 1) self.assertEqual(pybamm.inner(y, b).jac(y).evaluate(), 2) vec = pybamm.StateVector(slice(0, 2)) jac = pybamm.inner(a * vec, b * vec).jac(vec).evaluate(y=np.ones(2)).toarray() np.testing.assert_array_equal(jac, 4 * np.eye(2))
def test_multislice_raises(self): y1 = pybamm.StateVector(slice(0, 4), slice(7, 8)) y_dot1 = pybamm.StateVectorDot(slice(0, 4), slice(7, 8)) y2 = pybamm.StateVector(slice(4, 7)) with self.assertRaises(NotImplementedError): y1.jac(y1) with self.assertRaises(NotImplementedError): y2.jac(y1) with self.assertRaises(NotImplementedError): y_dot1.jac(y1)
def test_functions(self): y = pybamm.StateVector(slice(0, 8)) u = pybamm.StateVector(slice(0, 2), slice(4, 6)) v = pybamm.StateVector(slice(2, 4), slice(6, 8)) y0 = np.arange(1, 9) const = pybamm.Scalar(1) func = pybamm.sin(u) jacobian = np.array( [ [np.cos(1), 0, 0, 0, 0, 0, 0, 0], [0, np.cos(2), 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, np.cos(5), 0, 0, 0], [0, 0, 0, 0, 0, np.cos(6), 0, 0], ] ) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.cos(v) jacobian = np.array( [ [0, 0, -np.sin(3), 0, 0, 0, 0, 0], [0, 0, 0, -np.sin(4), 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, -np.sin(7), 0], [0, 0, 0, 0, 0, 0, 0, -np.sin(8)], ] ) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.sin(3 * u * v) jacobian = np.array( [ [9 * np.cos(9), 0, 3 * np.cos(9), 0, 0, 0, 0, 0], [0, 12 * np.cos(24), 0, 6 * np.cos(24), 0, 0, 0, 0], [0, 0, 0, 0, 21 * np.cos(105), 0, 15 * np.cos(105), 0], [0, 0, 0, 0, 0, 24 * np.cos(144), 0, 18 * np.cos(144)], ] ) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) # when child evaluates to number func = pybamm.sin(const) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(0, dfunc_dy) # several children func = pybamm.Function(test_multi_var_function, 2 * y, 3 * y) jacobian = np.diag(5 * np.ones(8)) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray())
def test_evaluate_list(self): sv = pybamm.StateVector(slice(0, 11), slice(20, 31)) y = np.linspace(0, 3, 31) np.testing.assert_array_almost_equal( sv.evaluate(y=y), np.concatenate([np.linspace(0, 1, 11), np.linspace(2, 3, 11)])[ :, np.newaxis ], ) sv = pybamm.StateVector(slice(0, 11), slice(11, 20), slice(20, 31)) y = np.linspace(0, 3, 31) np.testing.assert_array_almost_equal(sv.evaluate(y=y), y[:, np.newaxis])
def test_diff(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) y = np.array([5, 3]) # power self.assertEqual((a ** b).diff(b).evaluate(y=y), 5 ** 3 * np.log(5)) self.assertEqual((a ** b).diff(a).evaluate(y=y), 3 * 5 ** 2) self.assertEqual((a ** b).diff(a ** b).evaluate(), 1) self.assertEqual( (a ** a).diff(a).evaluate(y=y), 5 ** 5 * np.log(5) + 5 * 5 ** 4 ) self.assertEqual((a ** a).diff(b).evaluate(y=y), 0) # addition self.assertEqual((a + b).diff(a).evaluate(), 1) self.assertEqual((a + b).diff(b).evaluate(), 1) self.assertEqual((a + b).diff(a + b).evaluate(), 1) self.assertEqual((a + a).diff(a).evaluate(), 2) self.assertEqual((a + a).diff(b).evaluate(), 0) # subtraction self.assertEqual((a - b).diff(a).evaluate(), 1) self.assertEqual((a - b).diff(b).evaluate(), -1) self.assertEqual((a - b).diff(a - b).evaluate(), 1) self.assertEqual((a - a).diff(a).evaluate(), 0) self.assertEqual((a + a).diff(b).evaluate(), 0) # multiplication self.assertEqual((a * b).diff(a).evaluate(y=y), 3) self.assertEqual((a * b).diff(b).evaluate(y=y), 5) self.assertEqual((a * b).diff(a * b).evaluate(y=y), 1) self.assertEqual((a * a).diff(a).evaluate(y=y), 10) self.assertEqual((a * a).diff(b).evaluate(y=y), 0) # matrix multiplication (not implemented) matmul = a @ b with self.assertRaises(NotImplementedError): matmul.diff(a) # inner self.assertEqual(pybamm.inner(a, b).diff(a).evaluate(y=y), 3) self.assertEqual(pybamm.inner(a, b).diff(b).evaluate(y=y), 5) self.assertEqual(pybamm.inner(a, b).diff(pybamm.inner(a, b)).evaluate(y=y), 1) self.assertEqual(pybamm.inner(a, a).diff(a).evaluate(y=y), 10) self.assertEqual(pybamm.inner(a, a).diff(b).evaluate(y=y), 0) # division self.assertEqual((a / b).diff(a).evaluate(y=y), 1 / 3) self.assertEqual((a / b).diff(b).evaluate(y=y), -5 / 9) self.assertEqual((a / b).diff(a / b).evaluate(y=y), 1) self.assertEqual((a / a).diff(a).evaluate(y=y), 0) self.assertEqual((a / a).diff(b).evaluate(y=y), 0)
def test_to_python(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) # test a * b expr = a + b constant_str, variable_str = pybamm.to_python(expr) expected_str = ("var_[0-9m]+ = y\[0:1\].*\\n" "var_[0-9m]+ = y\[1:2\].*\\n" "var_[0-9m]+ = var_[0-9m]+ \+ var_[0-9m]+") self.assertRegex(variable_str, expected_str)
def test_nonlinear(self): y = pybamm.StateVector(slice(0, 4)) u = pybamm.StateVector(slice(0, 2)) v = pybamm.StateVector(slice(2, 4)) y0 = np.array([1, 2, 3, 4]) func = v**2 jacobian = np.array([[0, 0, 6, 0], [0, 0, 0, 8]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = 2**v jacobian = np.array([[0, 0, 2**3 * np.log(2), 0], [0, 0, 0, 2**4 * np.log(2)]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = v**v jacobian = [[0, 0, 27 * (1 + np.log(3)), 0], [0, 0, 0, 256 * (1 + np.log(4))]] dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_almost_equal(jacobian, dfunc_dy.toarray()) func = u * v jacobian = np.array([[3, 0, 1, 0], [0, 4, 0, 2]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = u * (u + v) jacobian = np.array([[5, 0, 1, 0], [0, 8, 0, 2]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = 1 / u + v / 3 jacobian = np.array([[-1, 0, 1 / 3, 0], [0, -1 / 4, 0, 1 / 3]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = u / v jacobian = np.array([[1 / 3, 0, -1 / 9, 0], [0, 1 / 4, 0, -1 / 8]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = v / (1 + v) jacobian = np.array([[0, 0, 1 / 16, 0], [0, 0, 0, 1 / 25]]) dfunc_dy = func.jac(y).evaluate(y=y0) np.testing.assert_array_equal(jacobian, dfunc_dy.toarray()) func = pybamm.AbsoluteValue(v) with self.assertRaises(pybamm.UndefinedOperationError): func.jac(y)
def test_to_python(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) # test a * b expr = a + b constant_str, variable_str = pybamm.to_python(expr) expected_str = ( "self\.var_[0-9m]+ = y\[:1\]\[\[True\]\].*\\n" "self\.var_[0-9m]+ = y\[:2\]\[\[False, True\]\].*\\n" "self\.var_[0-9m]+ = self\.var_[0-9m]+ \+ self\.var_[0-9m]+") self.assertRegex(variable_str, expected_str)
def test_shape(self): scal = pybamm.Scalar(1) self.assertEqual(scal.shape, ()) self.assertEqual(scal.size, 1) state = pybamm.StateVector(slice(10)) self.assertEqual(state.shape, (10, 1)) self.assertEqual(state.size, 10) state = pybamm.StateVector(slice(10, 25)) self.assertEqual(state.shape, (15, 1)) # test with big object state = 2 * pybamm.StateVector(slice(100000)) self.assertEqual(state.shape, (100000, 1))
def test_advanced(self): a = pybamm.StateVector(slice(0, 1)) b = pybamm.StateVector(slice(1, 2)) y = np.array([5, 3]) # func = (a * 2 + 5 * (-b)) / (a * b) self.assertEqual(func.diff(a).evaluate(y=y), 1 / 5) self.assertEqual(func.diff(b).evaluate(y=y), -2 / 9) # func = a * b**a testing.assert_array_almost_equal( func.diff(a).evaluate(y=y)[0], 3**5 * (5 * np.log(3) + 1)) self.assertEqual(func.diff(b).evaluate(y=y), 5**2 * 3**4)
def test_numpy_concatenation_vectors(self): # with entries y = np.linspace(0, 1, 15)[:, np.newaxis] a = pybamm.Vector(y[:5]) b = pybamm.Vector(y[5:9]) c = pybamm.Vector(y[9:]) conc = pybamm.NumpyConcatenation(a, b, c) np.testing.assert_array_equal(conc.evaluate(None, y), y) # with y_slice a = pybamm.StateVector(slice(0, 10)) b = pybamm.StateVector(slice(10, 15)) c = pybamm.StateVector(slice(15, 23)) conc = pybamm.NumpyConcatenation(a, b, c) y = np.linspace(0, 1, 23)[:, np.newaxis] np.testing.assert_array_equal(conc.evaluate(None, y), y)
def test_jac_of_heaviside(self): a = pybamm.Scalar(1) y = pybamm.StateVector(slice(0, 5)) np.testing.assert_array_equal( ((a < y) * y**2).jac(y).evaluate(y=5 * np.ones(5)), 10 * np.eye(5)) np.testing.assert_array_equal( ((a < y) * y**2).jac(y).evaluate(y=-5 * np.ones(5)), 0)
def test_symbol_evaluates_to_number(self): a = pybamm.Scalar(3) self.assertTrue(a.evaluates_to_number()) a = pybamm.Parameter("a") self.assertFalse(a.evaluates_to_number()) a = pybamm.Scalar(3) * pybamm.Time() self.assertTrue(a.evaluates_to_number()) # highlight difference between this function and isinstance(a, Scalar) self.assertNotIsInstance(a, pybamm.Scalar) a = pybamm.Variable("a") self.assertFalse(a.evaluates_to_number()) a = pybamm.Scalar(3) - 2 self.assertTrue(a.evaluates_to_number()) a = pybamm.Vector(np.ones(5)) self.assertFalse(a.evaluates_to_number()) a = pybamm.Matrix(np.ones((4, 6))) self.assertFalse(a.evaluates_to_number()) a = pybamm.StateVector(slice(0, 10)) self.assertFalse(a.evaluates_to_number()) # Time variable returns true a = 3 * pybamm.t + 2 self.assertTrue(a.evaluates_to_number())
def test_convert_input_parameter(self): casadi_t = casadi.MX.sym("t") casadi_y = casadi.MX.sym("y", 10) casadi_ydot = casadi.MX.sym("ydot", 10) casadi_inputs = { "Input 1": casadi.MX.sym("Input 1"), "Input 2": casadi.MX.sym("Input 2"), } pybamm_y = pybamm.StateVector(slice(0, 10)) pybamm_u1 = pybamm.InputParameter("Input 1") pybamm_u2 = pybamm.InputParameter("Input 2") # Input only self.assert_casadi_equal( pybamm_u1.to_casadi(casadi_t, casadi_y, casadi_ydot, casadi_inputs), casadi_inputs["Input 1"], ) # More complex expr = pybamm_u1 + pybamm_y self.assert_casadi_equal( expr.to_casadi(casadi_t, casadi_y, casadi_ydot, casadi_inputs), casadi_inputs["Input 1"] + casadi_y, ) expr = pybamm_u2 * pybamm_y self.assert_casadi_equal( expr.to_casadi(casadi_t, casadi_y, casadi_ydot, casadi_inputs), casadi_inputs["Input 2"] * casadi_y, )
def test_numpy_concatenation_vector_scalar(self): # with entries y = np.linspace(0, 1, 10)[:, np.newaxis] a = pybamm.Vector(y) b = pybamm.Scalar(16) c = pybamm.Scalar(3) conc = pybamm.NumpyConcatenation(a, b, c) np.testing.assert_array_equal( conc.evaluate(y=y), np.concatenate([y, np.array([[16]]), np.array([[3]])])) # with y_slice a = pybamm.StateVector(slice(0, 10)) conc = pybamm.NumpyConcatenation(a, b, c) np.testing.assert_array_equal( conc.evaluate(y=y), np.concatenate([y, np.array([[16]]), np.array([[3]])])) # with time b = pybamm.t conc = pybamm.NumpyConcatenation(a, b, c) np.testing.assert_array_equal( conc.evaluate(16, y), np.concatenate([y, np.array([[16]]), np.array([[3]])]))
def test_jac_of_sign(self): y = pybamm.StateVector(slice(0, 10)) func = pybamm.sign(y) * y jac = func.jac(y) y_test = np.linspace(-2, 2, 10) np.testing.assert_array_equal(np.diag(jac.evaluate(y=y_test)), np.sign(y_test))
def test_jac_of_abs(self): y = pybamm.StateVector(slice(0, 10)) absy = abs(y) jac = absy.jac(y) y_test = np.linspace(-2, 2, 10) np.testing.assert_array_equal( np.diag(jac.evaluate(y=y_test).toarray()), np.sign(y_test))
def test_convert_array_symbols(self): # Arrays a = np.array([1, 2, 3, 4, 5]) pybamm_a = pybamm.Array(a) self.assert_casadi_equal(pybamm_a.to_casadi(), casadi.MX(a)) casadi_t = casadi.MX.sym("t") casadi_y = casadi.MX.sym("y", 10) casadi_y_dot = casadi.MX.sym("y_dot", 10) pybamm_t = pybamm.Time() pybamm_y = pybamm.StateVector(slice(0, 10)) pybamm_y_dot = pybamm.StateVectorDot(slice(0, 10)) # Time self.assertEqual(pybamm_t.to_casadi(casadi_t, casadi_y), casadi_t) # State Vector self.assert_casadi_equal(pybamm_y.to_casadi(casadi_t, casadi_y), casadi_y) # State Vector Dot self.assert_casadi_equal( pybamm_y_dot.to_casadi(casadi_t, casadi_y, casadi_y_dot), casadi_y_dot)
def test_symbol_evaluates_to_constant_number(self): a = pybamm.Scalar(3) self.assertTrue(a.evaluates_to_constant_number()) a = pybamm.Parameter("a") self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Variable("a") self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Scalar(3) - 2 self.assertTrue(a.evaluates_to_constant_number()) a = pybamm.Vector(np.ones(5)) self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.Matrix(np.ones((4, 6))) self.assertFalse(a.evaluates_to_constant_number()) a = pybamm.StateVector(slice(0, 10)) self.assertFalse(a.evaluates_to_constant_number()) # Time variable returns true a = 3 * pybamm.t + 2 self.assertFalse(a.evaluates_to_constant_number())