Repository: sympy/sympy

Issue:
Add .evalf() method to sympy.physics.vector.Vector and Dyadic
These two classes are missing many of the core SymPy methods because they do not inherit from the core SymPy classes. It would be nice to add them, starting with `.evalf()`.

Discussion:

Patch:
diff --git a/sympy/physics/vector/dyadic.py b/sympy/physics/vector/dyadic.py
index 028df40760..a608b7cc19 100644
--- a/sympy/physics/vector/dyadic.py
+++ b/sympy/physics/vector/dyadic.py
@@ -1,10 +1,11 @@
 from sympy.core.backend import sympify, Add, ImmutableMatrix as Matrix
+from sympy.core.evalf import EvalfMixin, prec_to_dps
 from sympy.printing.defaults import Printable
 
 __all__ = ['Dyadic']
 
 
-class Dyadic(Printable):
+class Dyadic(Printable, EvalfMixin):
     """A Dyadic object.
 
     See:
@@ -17,6 +18,8 @@ class Dyadic(Printable):
 
     """
 
+    is_number = False
+
     def __init__(self, inlist):
         """
         Just like Vector's init, you shouldn't call this unless creating a
@@ -55,6 +58,11 @@ def __init__(self, inlist):
                 i -= 1
             i += 1
 
+    @property
+    def func(self):
+        """Returns the class Dyadic. """
+        return Dyadic
+
     def __add__(self, other):
         """The add operator for Dyadic. """
         other = _check_dyadic(other)
@@ -521,6 +529,15 @@ def applyfunc(self, f):
     dot = __and__
     cross = __xor__
 
+    def _eval_evalf(self, prec):
+        if not self.args:
+            return self
+        new_args = []
+        for inlist in self.args:
+            new_inlist = list(inlist)
+            new_inlist[0] = inlist[0].evalf(n=prec_to_dps(prec))
+            new_args.append(tuple(new_inlist))
+        return Dyadic(new_args)
 
 def _check_dyadic(other):
     if not isinstance(other, Dyadic):
diff --git a/sympy/physics/vector/vector.py b/sympy/physics/vector/vector.py
index 7d946d047d..d87d51e7f7 100644
--- a/sympy/physics/vector/vector.py
+++ b/sympy/physics/vector/vector.py
@@ -3,11 +3,12 @@
 from sympy import trigsimp
 from sympy.printing.defaults import Printable
 from sympy.utilities.misc import filldedent
+from sympy.core.evalf import EvalfMixin, prec_to_dps
 
 __all__ = ['Vector']
 
 
-class Vector(Printable):
+class Vector(Printable, EvalfMixin):
     """The class used to define vectors.
 
     It along with ReferenceFrame are the building blocks of describing a
@@ -22,6 +23,7 @@ class Vector(Printable):
     """
 
     simp = False
+    is_number = False
 
     def __init__(self, inlist):
         """This is the constructor for the Vector class.  You shouldn't be
@@ -52,6 +54,11 @@ def __init__(self, inlist):
             if v != Matrix([0, 0, 0]):
                 self.args.append((v, k))
 
+    @property
+    def func(self):
+        """Returns the class Vector. """
+        return Vector
+
     def __hash__(self):
         return hash(tuple(self.args))
 
@@ -704,6 +711,14 @@ def free_symbols(self, reference_frame):
 
         return self.to_matrix(reference_frame).free_symbols
 
+    def _eval_evalf(self, prec):
+        if not self.args:
+            return self
+        new_args = []
+        for mat, frame in self.args:
+            new_args.append([mat.evalf(n=prec_to_dps(prec)), frame])
+        return Vector(new_args)
+
 
 class VectorTypeError(TypeError):
 


Test patch:
diff --git a/sympy/physics/vector/tests/test_dyadic.py b/sympy/physics/vector/tests/test_dyadic.py
index 58bb1c1edb..527f757a2f 100644
--- a/sympy/physics/vector/tests/test_dyadic.py
+++ b/sympy/physics/vector/tests/test_dyadic.py
@@ -1,4 +1,4 @@
-from sympy import sin, cos, symbols, pi, ImmutableMatrix as Matrix
+from sympy import sin, cos, symbols, pi, Float, ImmutableMatrix as Matrix
 from sympy.physics.vector import ReferenceFrame, Vector, dynamicsymbols
 from sympy.physics.vector.dyadic import _check_dyadic
 from sympy.testing.pytest import raises
@@ -95,3 +95,12 @@ def test_dyadic_subs():
 
 def test_check_dyadic():
     raises(TypeError, lambda: _check_dyadic(0))
+
+
+def test_dyadic_evalf():
+    N = ReferenceFrame('N')
+    a = pi * (N.x | N.x)
+    assert a.evalf(3) == Float('3.1416', 3) * (N.x | N.x)
+    s = symbols('s')
+    a = 5 * s * pi* (N.x | N.x)
+    assert a.evalf(2) == Float('5', 2) * Float('3.1416', 2) * s * (N.x | N.x)
diff --git a/sympy/physics/vector/tests/test_vector.py b/sympy/physics/vector/tests/test_vector.py
index 497991a1ff..82fe0a8f64 100644
--- a/sympy/physics/vector/tests/test_vector.py
+++ b/sympy/physics/vector/tests/test_vector.py
@@ -1,4 +1,4 @@
-from sympy import symbols, pi, sin, cos, ImmutableMatrix as Matrix
+from sympy import symbols, pi, sin, cos, Float, ImmutableMatrix as Matrix
 from sympy.physics.vector import ReferenceFrame, Vector, dynamicsymbols, dot
 from sympy.abc import x, y, z
 from sympy.testing.pytest import raises
@@ -169,3 +169,11 @@ def test_vector_simplify():
     test4 = ((-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2) * N.x
     test4 = test4.simplify()
     assert (test4 & N.x) == -2 * y
+
+
+def test_vector_evalf():
+    a, b = symbols('a b')
+    v = pi * A.x
+    assert v.evalf(2) == Float('3.1416', 2) * A.x
+    v = pi * A.x + 5 * a * A.y - b * A.z
+    assert v.evalf(3) == Float('3.1416', 3) * A.x + Float('5', 3) * a * A.y - b * A.z