def test_power(self): a = pybamm.Symbol("a") b = pybamm.Symbol("b") pow1 = pybamm.Power(a, b) self.assertEqual(pow1.name, "**") self.assertEqual(pow1.children[0].name, a.name) self.assertEqual(pow1.children[1].name, b.name) a = pybamm.Scalar(4) b = pybamm.Scalar(2) pow2 = pybamm.Power(a, b) self.assertEqual(pow2.evaluate(), 16)
def get_coupled_variables(self, variables): variables.update(self._get_standard_surface_variables(variables)) variables.update(self._get_mechanical_results(variables)) T = variables[self.domain + " electrode temperature"] if self.domain == "Negative": k_cr = self.param.k_cr_n(T) m_cr = self.param.m_cr_n b_cr = self.param.b_cr_n else: k_cr = self.param.k_cr_p(T) m_cr = self.param.m_cr_p b_cr = self.param.b_cr_p stress_t_surf = variables[self.domain + " particle surface tangential stress"] l_cr = variables[self.domain + " particle crack length"] # # compressive stress will not lead to crack propagation dK_SIF = stress_t_surf * b_cr * pybamm.Sqrt( np.pi * l_cr) * (stress_t_surf >= 0) dl_cr = k_cr * pybamm.Power(dK_SIF, m_cr) / self.param.t0_cr variables.update({ self.domain + " particle cracking rate": dl_cr, "X-averaged " + self.domain.lower() + " particle cracking rate": pybamm.x_average(dl_cr), }) return variables
def _stress_driven_LAM_full(self, variables): # This is loss of active material model by mechanical effects stress_t_surf = variables[self.domain + " particle surface tangential stress"] stress_r_surf = variables[self.domain + " particle surface radial stress"] if self.domain == "Negative": beta_LAM = self.param.beta_LAM_n stress_critical = self.param.stress_critical_n m_LAM = self.param.m_LAM_n else: beta_LAM = self.param.beta_LAM_p stress_critical = self.param.stress_critical_p m_LAM = self.param.m_LAM_p stress_h_surf = (stress_r_surf + 2 * stress_t_surf) / 3 # compressive stress make no contribution stress_h_surf *= stress_h_surf > 0 # assuming the minimum hydrostatic stress is zero for full cycles stress_h_surf_min = stress_h_surf * 0 j_stress_LAM = ( -beta_LAM * pybamm.Power( (stress_h_surf - stress_h_surf_min) / stress_critical, m_LAM, ) / self.param.t0_cr ) return j_stress_LAM
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))
def test_convert_scalar_symbols(self): a = pybamm.Scalar(0) b = pybamm.Scalar(1) c = pybamm.Scalar(-1) d = pybamm.Scalar(2) 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)) # function def sin(x): return np.sin(x) f = pybamm.Function(sin, b) self.assertEqual(f.to_casadi(), casadi.MX(np.sin(1))) 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)) # 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))
def simplified_power(left, right): left, right = simplify_elementwise_binary_broadcasts(left, right) # Check for Concatenations and Broadcasts out = simplified_binary_broadcast_concatenation(left, right, simplified_power) if out is not None: return out # anything to the power of zero is one if pybamm.is_scalar_zero(right): return pybamm.ones_like(left) # zero to the power of anything is zero if pybamm.is_scalar_zero(left): return pybamm.Scalar(0) # anything to the power of one is itself if pybamm.is_scalar_one(right): return left if isinstance(left, Multiplication): # Simplify (a * b) ** c to (a ** c) * (b ** c) # if (a ** c) is constant or (b ** c) is constant if left.left.is_constant() or left.right.is_constant(): l_left, l_right = left.orphans new_left = l_left**right new_right = l_right**right if new_left.is_constant() or new_right.is_constant(): return new_left * new_right elif isinstance(left, Division): # Simplify (a / b) ** c to (a ** c) / (b ** c) # if (a ** c) is constant or (b ** c) is constant if left.left.is_constant() or left.right.is_constant(): l_left, l_right = left.orphans new_left = l_left**right new_right = l_right**right if new_left.is_constant() or new_right.is_constant(): return new_left / new_right return pybamm.simplify_if_constant(pybamm.Power(left, right))
def test_to_equation(self): # Test print_name pybamm.Addition.print_name = "test" self.assertEqual(pybamm.Addition(1, 2).to_equation(), sympy.symbols("test")) # Test Power self.assertEqual(pybamm.Power(7, 2).to_equation(), 49) # Test Division self.assertEqual(pybamm.Division(10, 2).to_equation(), 5) # Test Matrix Multiplication arr1 = pybamm.Array([[1, 0], [0, 1]]) arr2 = pybamm.Array([[4, 1], [2, 2]]) self.assertEqual( pybamm.MatrixMultiplication(arr1, arr2).to_equation(), sympy.Matrix([[4.0, 1.0], [2.0, 2.0]]), ) # Test EqualHeaviside self.assertEqual(pybamm.EqualHeaviside(1, 0).to_equation(), False) # Test NotEqualHeaviside self.assertEqual(pybamm.NotEqualHeaviside(2, 4).to_equation(), True)
def __rpow__(self, other): """return a :class:`Power` object""" return pybamm.simplify_if_constant(pybamm.Power(other, self), keep_domains=True)
def __rpow__(self, other): """return a :class:`Power` object""" if isinstance(other, (Symbol, numbers.Number)): return pybamm.Power(other, self) else: raise NotImplementedError