def _binary_jac(self, left_jac, right_jac): """ See :meth:`pybamm.BinaryOperator._binary_jac()`. """ # apply chain rule and power rule left, right = self.orphans if right.evaluates_to_constant_number(): return left_jac elif left.evaluates_to_constant_number(): return -right_jac * pybamm.Floor(left / right) else: return left_jac - right_jac * pybamm.Floor(left / right)
def test_floor(self): a = pybamm.Symbol("a") floora = pybamm.Floor(a) self.assertEqual(floora.name, "floor") self.assertEqual(floora.children[0].name, a.name) b = pybamm.Scalar(3.5) floorb = pybamm.Floor(b) self.assertEqual(floorb.evaluate(), 3) c = pybamm.Scalar(-3.2) floorc = pybamm.Floor(c) self.assertEqual(floorc.evaluate(), -4)
def test_diff(self): a = pybamm.StateVector(slice(0, 1)) y = np.array([5]) # negation self.assertEqual((-a).diff(a).evaluate(y=y), -1) self.assertEqual((-a).diff(-a).evaluate(), 1) # absolute value self.assertEqual((a**3).diff(a).evaluate(y=y), 3 * 5**2) self.assertEqual((abs(a**3)).diff(a).evaluate(y=y), 3 * 5**2) self.assertEqual((a**3).diff(a).evaluate(y=-y), 3 * 5**2) self.assertEqual((abs(a**3)).diff(a).evaluate(y=-y), -3 * 5**2) # sign self.assertEqual((pybamm.sign(a)).diff(a).evaluate(y=y), 0) # floor self.assertEqual((pybamm.Floor(a)).diff(a).evaluate(y=y), 0) # ceil self.assertEqual((pybamm.Ceiling(a)).diff(a).evaluate(y=y), 0) # spatial operator (not implemented) spatial_a = pybamm.SpatialOperator("name", a) with self.assertRaises(NotImplementedError): spatial_a.diff(a)
def test_jac_of_floor(self): y = pybamm.StateVector(slice(0, 10)) func = pybamm.Floor(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.floor(y_test))
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 _diff(self, variable): """ See :meth:`pybamm.Symbol._diff()`. """ # apply chain rule and power rule left, right = self.orphans # derivative if variable is in the base diff = left.diff(variable) # derivative if variable is in the right term (rare, check separately to avoid # unecessarily big tree) if any(variable.id == x.id for x in right.pre_order()): diff += -pybamm.Floor(left / right) * right.diff(variable) return diff
def test_convert_scalar_symbols(self): a = pybamm.Scalar(0) b = pybamm.Scalar(1) c = pybamm.Scalar(-1) d = pybamm.Scalar(2) e = pybamm.Scalar(3) g = pybamm.Scalar(3.3) self.assertEqual(a.to_casadi(), casadi.MX(0)) self.assertEqual(d.to_casadi(), casadi.MX(2)) # negate self.assertEqual((-b).to_casadi(), casadi.MX(-1)) # absolute value self.assertEqual(abs(c).to_casadi(), casadi.MX(1)) # floor self.assertEqual(pybamm.Floor(g).to_casadi(), casadi.MX(3)) # ceiling self.assertEqual(pybamm.Ceiling(g).to_casadi(), casadi.MX(4)) # function def square_plus_one(x): return x**2 + 1 f = pybamm.Function(square_plus_one, b) self.assertEqual(f.to_casadi(), 2) def myfunction(x, y): return x + y f = pybamm.Function(myfunction, b, d) self.assertEqual(f.to_casadi(), casadi.MX(3)) # use classes to avoid simplification # addition self.assertEqual((pybamm.Addition(a, b)).to_casadi(), casadi.MX(1)) # subtraction self.assertEqual(pybamm.Subtraction(c, d).to_casadi(), casadi.MX(-3)) # multiplication self.assertEqual( pybamm.Multiplication(c, d).to_casadi(), casadi.MX(-2)) # power self.assertEqual(pybamm.Power(c, d).to_casadi(), casadi.MX(1)) # division self.assertEqual(pybamm.Division(b, d).to_casadi(), casadi.MX(1 / 2)) # modulo self.assertEqual(pybamm.Modulo(e, d).to_casadi(), casadi.MX(1)) # minimum and maximum self.assertEqual(pybamm.Minimum(a, b).to_casadi(), casadi.MX(0)) self.assertEqual(pybamm.Maximum(a, b).to_casadi(), casadi.MX(1))