def simplified_matrix_multiplication(left, right): left, right = preprocess_binary(left, right) if pybamm.is_matrix_zero(left) or pybamm.is_matrix_zero(right): return pybamm.zeros_like(pybamm.MatrixMultiplication(left, right)) if isinstance(right, Multiplication) and left.is_constant(): # Simplify A @ (b * c) to (A * b) @ c if (A * b) is constant if right.left.evaluates_to_constant_number(): r_left, r_right = right.orphans new_left = left * r_left return new_left @ r_right # Simplify A @ (b * c) to (A * c) @ b if (A * c) is constant elif right.right.evaluates_to_constant_number(): r_left, r_right = right.orphans new_left = left * r_right return new_left @ r_left elif isinstance(right, Division) and left.is_constant(): # Simplify A @ (b / c) to (A / c) @ b if (A / c) is constant if right.right.evaluates_to_constant_number(): r_left, r_right = right.orphans new_left = left / r_right new_mul = new_left @ r_left # Keep the domain of the old left new_mul.copy_domains(left) return new_mul # Simplify A @ (B @ c) to (A @ B) @ c if (A @ B) is constant # This is a common construction that appears from discretisation of spatial # operators if (isinstance(right, MatrixMultiplication) and right.left.is_constant() and left.is_constant()): r_left, r_right = right.orphans new_left = left @ r_left # be careful about domains to avoid weird errors new_left.clear_domains() new_mul = new_left @ r_right # Keep the domain of the old right new_mul.copy_domains(right) return new_mul # Simplify A @ (b + c) to (A @ b) + (A @ c) if (A @ b) or (A @ c) is constant # This is a common construction that appears from discretisation of spatial # operators # Don't do this if either b or c is a number as this will lead to matmul errors elif isinstance(right, Addition): if (right.left.is_constant() or right.right.is_constant() ) and not (right.left.size_for_testing == 1 or right.right.size_for_testing == 1): r_left, r_right = right.orphans return (left @ r_left) + (left @ r_right) return pybamm.simplify_if_constant(pybamm.MatrixMultiplication( 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 __rmatmul__(self, other): """return a :class:`MatrixMultiplication` object""" return pybamm.simplify_if_constant(pybamm.MatrixMultiplication( other, self), keep_domains=True)
def __rmatmul__(self, other): """return a :class:`MatrixMultiplication` object""" if isinstance(other, (Symbol, numbers.Number)): return pybamm.MatrixMultiplication(other, self) else: raise NotImplementedError