← Back to team overview

ufl team mailing list archive

Support for tan(x)

 

I have attached a patch which adds support for evaluating and
differentiating tan(f) in UFL forms. If this is acceptable, I plan to
similarly add inverse trigonometric functions.

Harish
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: hnarayanan@xxxxxxxxx-20100316142718-t6amwqkb9j70u0j5
# target_branch: bzr+ssh://bazaar.launchpad.net/~ufl-core/ufl/main/
# testament_sha1: b8523f9c30cb9e70ef5f736b0c5b00d198551b87
# timestamp: 2010-03-16 15:31:38 +0100
# base_revision_id: k.b.oelgaard@xxxxxxxxx-20100216094344-\
#   xgpckx7p1jdwh523
# 
# Begin patch
=== modified file 'TODO'
--- TODO	2009-12-08 15:59:29 +0000
+++ TODO	2010-03-16 14:27:18 +0000
@@ -145,7 +145,6 @@
       even if f is defined on a quadrature element.
 
 # Additional operators (low priority):
-    - tan(f)
     - log(f, base)
     - other mathematical functions in <cmath> (need derivatives)
     - bessel functions (needs non-standard library code)

=== modified file 'test/derivative.py'
--- test/derivative.py	2010-02-07 21:15:52 +0000
+++ test/derivative.py	2010-03-16 14:27:18 +0000
@@ -91,6 +91,11 @@
         def df(w, v): return -v*sin(w)
         self._test(f, df)
 
+    def testTan(self):
+        def f(w):  return tan(w)
+        def df(w, v): return v*2.0/(cos(2.0*w) + 1.0)
+        self._test(f, df)
+
     def testIndexSum(self):
         def f(w):
             # 3*w + 4*w**2 + 5*w**3

=== modified file 'test/diff.py'
--- test/diff.py	2009-03-27 13:03:47 +0000
+++ test/diff.py	2010-03-16 14:27:18 +0000
@@ -83,6 +83,11 @@
         def df(v): return -sin(v)
         self._test(f, df)
 
+    def testTan(self):
+        def f(v):  return tan(v)
+        def df(v): return 2.0/(cos(2.0*v) + 1.0)
+        self._test(f, df)
+
     def testIndexSum(self):
         def f(v):
             # 3*v + 4*v**2 + 5*v**3

=== modified file 'test/evaluate.py'
--- test/evaluate.py	2009-12-08 15:59:29 +0000
+++ test/evaluate.py	2010-03-16 14:27:18 +0000
@@ -120,6 +120,11 @@
         e = s((5,7))
         v = math.cos(5)
         self.assertTrue(e == v)
+
+        s = tan(x)
+        e = s((5,7))
+        v = math.tan(5)
+        self.assertTrue(e == v)
         
         s = ln(x)
         e = s((5,7))

=== modified file 'ufl/__init__.py'
--- ufl/__init__.py	2010-02-15 15:12:43 +0000
+++ ufl/__init__.py	2010-03-16 14:27:18 +0000
@@ -80,7 +80,7 @@
     Dx, grad, div, curl, rot, Dn
 
 Nonlinear functions:
-    abs, sign, sqrt, exp, ln, cos, sin,
+    abs, sign, sqrt, exp, ln, cos, sin, tan
 
 Discontinuous Galerkin operators:
     jump, avg, v('+'), v('-')
@@ -163,7 +163,7 @@
                        outer, inner, dot, cross, \
                        det, inv, cofac, \
                        transpose, tr, dev, skew, sym, \
-                       sqrt, exp, ln, cos, sin, \
+                       sqrt, exp, ln, cos, sin, tan, \
                        eq, ne, le, ge, lt, gt, conditional, sign, \
                        variable, diff, \
                        Dx,  grad, div, curl, rot, Dn, \

=== modified file 'ufl/algorithms/forward_ad.py'
--- ufl/algorithms/forward_ad.py	2009-12-08 15:59:29 +0000
+++ ufl/algorithms/forward_ad.py	2010-03-16 14:27:18 +0000
@@ -23,7 +23,7 @@
 from ufl.algebra import Sum, Product, Division, Power, Abs
 from ufl.tensoralgebra import Transposed, Outer, Inner, Dot, Cross, Trace, \
     Determinant, Inverse, Deviatoric, Cofactor
-from ufl.mathfunctions import MathFunction, Sqrt, Exp, Ln, Cos, Sin
+from ufl.mathfunctions import MathFunction, Sqrt, Exp, Ln, Cos, Sin, Tan
 from ufl.restriction import Restricted, PositiveRestricted, NegativeRestricted
 from ufl.differentiation import Derivative, FunctionDerivative,\
     SpatialDerivative, VariableDerivative
@@ -33,7 +33,7 @@
 #from ufl.classes import ufl_classes, terminal_classes, nonterminal_classes
 from ufl.classes import terminal_classes
 from ufl.operators import dot, inner, outer, lt, eq, conditional, sign
-from ufl.operators import sqrt, exp, ln, cos, sin
+from ufl.operators import sqrt, exp, ln, cos, sin, tan
 from ufl.algorithms.traversal import iter_expressions
 from ufl.algorithms.analysis import extract_type
 from ufl.algorithms.transformations import expand_compounds, Transformer, transform, transform_integrands
@@ -402,6 +402,12 @@
         op = fp*cos(f)
         return (o, op)
 
+    def tan(self, o, a):
+        f, fp = a
+        o = self.reuse_if_possible(o, f)
+        op = fp*2.0/(cos(2.0*f) + 1.0)
+        return (o, op)
+
     # --- Restrictions
 
     def positive_restricted(self, o, a):

=== modified file 'ufl/algorithms/pdiffs.py'
--- ufl/algorithms/pdiffs.py	2009-04-25 09:47:05 +0000
+++ ufl/algorithms/pdiffs.py	2010-03-16 14:27:18 +0000
@@ -7,7 +7,7 @@
 from ufl.log import error
 from ufl.assertions import ufl_assert
 from ufl.classes import Zero, IntValue, FloatValue
-from ufl.operators import sin, cos, exp, ln, sqrt, conditional, sign
+from ufl.operators import sin, cos, tan, exp, ln, sqrt, conditional, sign
 from ufl.tensors import unit_vectors, ListTensor
 from ufl.algorithms.transformations import MultiFunction
 
@@ -100,6 +100,11 @@
         "d/dx sin x = cos(x)"
         x, = f.operands()
         return (cos(x),)
+
+    def tan(self, f):
+        "d/dx tan x = (sec(x))^2 = 2/(cos(2x) + 1)"
+        x, = f.operands()
+        return (2.0/(cos(2.0*x) + 1.0),)
     
     # --- Shape and indexing manipulators
     

=== modified file 'ufl/algorithms/ufl2latex.py'
--- ufl/algorithms/ufl2latex.py	2010-02-07 21:15:52 +0000
+++ ufl/algorithms/ufl2latex.py	2010-03-16 14:27:18 +0000
@@ -22,7 +22,7 @@
 from ufl.algebra import Sum, Product, Division, Power, Abs
 from ufl.indexsum import IndexSum
 from ufl.tensoralgebra import Transposed, Outer, Inner, Dot, Cross, Trace, Determinant, Inverse, Deviatoric, Cofactor
-from ufl.mathfunctions import Sqrt, Exp, Ln, Cos, Sin
+from ufl.mathfunctions import Sqrt, Exp, Ln, Cos, Sin, Tan
 from ufl.restriction import PositiveRestricted, NegativeRestricted
 from ufl.differentiation import SpatialDerivative, VariableDerivative, Grad, Div, Curl
 from ufl.conditional import EQ, NE, LE, GE, LT, GT, Conditional
@@ -206,6 +206,9 @@
     def sin(self, o, f):
         return r"\sin{%s}" % par(f)
 
+    def tan(self, o, f):
+        return r"\tan{%s}" % par(f)
+
     def power(self, o, a, b):
         return "{%s}^{%s}" % (par(a), par(b))
 

=== modified file 'ufl/classes.py'
--- ufl/classes.py	2009-12-08 15:59:29 +0000
+++ ufl/classes.py	2010-03-16 14:27:18 +0000
@@ -21,7 +21,7 @@
 from ufl.tensors import ListTensor, ComponentTensor
 from ufl.algebra import Sum, Product, Division, Power, Abs
 from ufl.tensoralgebra import CompoundTensorOperator, Transposed, Outer, Inner, Dot, Cross, Trace, Determinant, Cofactor, Inverse, Deviatoric, Skew, Sym
-from ufl.mathfunctions import MathFunction, Sqrt, Exp, Ln, Cos, Sin
+from ufl.mathfunctions import MathFunction, Sqrt, Exp, Ln, Cos, Sin, Tan
 from ufl.restriction import Restricted, PositiveRestricted, NegativeRestricted
 from ufl.lifting import LiftingResult, LiftingOperatorResult, LiftingFunctionResult, TerminalOperator, LiftingOperator, LiftingFunction
 from ufl.differentiation import Derivative, CompoundDerivative, FunctionDerivative, SpatialDerivative, VariableDerivative, Grad, Div, Curl

=== modified file 'ufl/mathfunctions.py'
--- ufl/mathfunctions.py	2009-04-21 07:40:04 +0000
+++ ufl/mathfunctions.py	2010-03-16 14:27:18 +0000
@@ -94,3 +94,11 @@
     def __init__(self, argument):
         MathFunction.__init__(self, "sin", argument)
 
+class Tan(MathFunction):
+    def __new__(cls, argument):
+        if isinstance(argument, (ScalarValue, Zero)):
+            return FloatValue(math.tan(float(argument)))
+        return MathFunction.__new__(cls)
+    
+    def __init__(self, argument):
+        MathFunction.__init__(self, "tan", argument)

=== modified file 'ufl/operators.py'
--- ufl/operators.py	2009-12-01 17:09:26 +0000
+++ ufl/operators.py	2010-03-16 14:27:18 +0000
@@ -16,7 +16,7 @@
 from ufl.variable import Variable
 from ufl.tensors import as_tensor
 from ufl.conditional import EQ, NE, LE, GE, LT, GT, Conditional
-from ufl.mathfunctions import Sqrt, Exp, Ln, Cos, Sin
+from ufl.mathfunctions import Sqrt, Exp, Ln, Cos, Sin, Tan
 from ufl.indexing import indices
 from ufl.geometry import SpatialCoordinate
 
@@ -283,3 +283,6 @@
     "The sinus of f."
     return _mathfunction(f, Sin, math.sin)
 
+def tan(f):
+    "The tangent of f."
+    return _mathfunction(f, Tan, math.tan)

# Begin bundle
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
50A=

Follow ups