Ejemplo n.º 1
0
def inner(a, b):
    "UFL operator: Take the inner product of a and b."
    a = as_ufl(a)
    b = as_ufl(b)
    if a.shape() == () and b.shape() == ():
        return a*b
    return Inner(a, b)
Ejemplo n.º 2
0
def inner(a, b):
    "UFL operator: Take the inner product of *a* and *b*. The complex conjugate of the second argument is taken."
    a = as_ufl(a)
    b = as_ufl(b)
    if a.ufl_shape == () and b.ufl_shape == ():
        return a * Conj(b)
    return Inner(a, b)
Ejemplo n.º 3
0
def dot(a, b):
    "UFL operator: Take the dot product of *a* and *b*. The complex conjugate of the second argument is taken."
    a = as_ufl(a)
    b = as_ufl(b)
    if a.ufl_shape == () and b.ufl_shape == ():
        return a * b
    return Dot(a, b)
Ejemplo n.º 4
0
    def __init__(self, name, left, right):
        left = as_ufl(left)
        right = as_ufl(right)

        Condition.__init__(self, (left, right))

        self._name = name

        if name in ('!=', '=='):
            # Since equals and not-equals are used for comparing
            # representations, we have to allow any shape here. The
            # scalar properties must be checked when used in
            # conditional instead!
            pass
        elif name in ('&&', '||'):
            # Binary operators acting on boolean expressions allow
            # only conditions
            for arg in (left, right):
                if not isinstance(arg, Condition):
                    error("Expecting a Condition, not %s." % ufl_err_str(arg))
        else:
            # Binary operators acting on non-boolean expressions allow
            # only scalars
            if left.ufl_shape != () or right.ufl_shape != ():
                error("Expecting scalar arguments.")
            if left.ufl_free_indices != () or right.ufl_free_indices != ():
                error("Expecting scalar arguments.")
Ejemplo n.º 5
0
def dot(a, b):
    "UFL operator: Take the dot product of a and b."
    a = as_ufl(a)
    b = as_ufl(b)
    if a.shape() == () and b.shape() == ():
        return a*b
    return Dot(a, b)
Ejemplo n.º 6
0
    def __new__(cls, a, b):
        a = as_ufl(a)
        b = as_ufl(b)

        # Assertions
        # TODO: Enabled workaround for nonscalar division in __div__,
        # so maybe we can keep this assertion. Some algorithms may need updating.
        if not is_ufl_scalar(a):
            error("Expecting scalar nominator in Division.")
        if not is_true_ufl_scalar(b):
            error("Division by non-scalar is undefined.")
        if isinstance(b, Zero):
            error("Division by zero!")

        # Simplification a/b -> a
        if isinstance(a, Zero) or b == 1:
            return a
        # Simplification "literal a / literal b" -> "literal value of a/b"
        # Avoiding integer division by casting to float
        if isinstance(a, ScalarValue) and isinstance(b, ScalarValue):
            return as_ufl(float(a._value) / float(b._value))
        # Simplification "a / a" -> "1"
        if not a.free_indices() and not a.shape() and a == b:
            return as_ufl(1)

        # construct and initialize a new Division object
        self = AlgebraOperator.__new__(cls)
        self._init(a, b)
        return self
Ejemplo n.º 7
0
def cross(a, b):
    "UFL operator: Take the cross product of a and b."
    a = as_ufl(a)
    b = as_ufl(b)
    #ufl_assert(a.shape() == (3,) and b.shape() == (3,),
    #           "Expecting 3D vectors in cross product.")
    return Cross(a, b)
Ejemplo n.º 8
0
def atan_2(f1,f2):
    "UFL operator: Take the inverse tangent of f."
    f1 = as_ufl(f1)
    f2 = as_ufl(f2)
    r = Atan2(f1, f2)
    if isinstance(r, (ScalarValue, Zero, int, float)):
        return float(r)
    return r
Ejemplo n.º 9
0
def derivative(form, coefficient, argument=None, coefficient_derivatives=None):
    """UFL form operator:
    Compute the Gateaux derivative of *form* w.r.t. *coefficient* in direction
    of *argument*.

    If the argument is omitted, a new ``Argument`` is created
    in the same space as the coefficient, with argument number
    one higher than the highest one in the form.

    The resulting form has one additional ``Argument``
    in the same finite element space as the coefficient.

    A tuple of ``Coefficient`` s may be provided in place of
    a single ``Coefficient``, in which case the new ``Argument``
    argument is based on a ``MixedElement`` created from this tuple.

    An indexed ``Coefficient`` from a mixed space may be provided,
    in which case the argument should be in the corresponding
    subspace of the coefficient space.

    If provided, *coefficient_derivatives* should be a mapping from
    ``Coefficient`` instances to their derivatives w.r.t. *coefficient*.
    """

    coefficients, arguments = _handle_derivative_arguments(form, coefficient,
                                                           argument)

    if coefficient_derivatives is None:
        coefficient_derivatives = ExprMapping()
    else:
        cd = []
        for k in sorted_expr(coefficient_derivatives.keys()):
            cd += [as_ufl(k), as_ufl(coefficient_derivatives[k])]
        coefficient_derivatives = ExprMapping(*cd)

    # Got a form? Apply derivatives to the integrands in turn.
    if isinstance(form, Form):
        integrals = []
        for itg in form.integrals():
            if not isinstance(coefficient, SpatialCoordinate):
                fd = CoefficientDerivative(itg.integrand(), coefficients,
                                           arguments, coefficient_derivatives)
            else:
                fd = CoordinateDerivative(itg.integrand(), coefficients,
                                          arguments, coefficient_derivatives)
            integrals.append(itg.reconstruct(fd))
        return Form(integrals)

    elif isinstance(form, Expr):
        # What we got was in fact an integrand
        if not isinstance(coefficient, SpatialCoordinate):
            return CoefficientDerivative(form, coefficients,
                                         arguments, coefficient_derivatives)
        else:
            return CoordinateDerivative(form, coefficients,
                                        arguments, coefficient_derivatives)

    error("Invalid argument type %s." % str(type(form)))
Ejemplo n.º 10
0
def atan_2(f1, f2):
    "UFL operator: Take the inverse tangent with two the arguments *f1* and *f2*."
    f1 = as_ufl(f1)
    f2 = as_ufl(f2)
    if isinstance(f1, (ComplexValue, complex)) or isinstance(f2, (ComplexValue, complex)):
        raise TypeError('atan_2 is incompatible with complex numbers.')
    r = Atan2(f1, f2)
    if isinstance(r, (RealValue, Zero, int, float)):
        return float(r)
    if isinstance(r, (ComplexValue, complex)):
        return complex(r)
    return r
Ejemplo n.º 11
0
 def __init__(self, name, classname, nu, argument):
     Operator.__init__(self)
     ufl_assert(is_true_ufl_scalar(nu), "Expecting scalar nu.")
     ufl_assert(is_true_ufl_scalar(argument), "Expecting scalar argument.")
     fnu = float(nu)
     inu = int(nu)
     if fnu == inu:
         nu = as_ufl(inu)
     else:
         nu = as_ufl(fnu)
     self._classname = classname
     self._name     = name
     self._nu       = nu
     self._argument = argument
Ejemplo n.º 12
0
def test_float(self):
    f1 = as_ufl(1)
    f2 = as_ufl(1.0)
    f3 = FloatValue(1)
    f4 = FloatValue(1.0)
    f5 = 3 - FloatValue(1) - 1
    f6 = 3 * FloatValue(2) / 6

    assert f1 == f1
    self.assertNotEqual(f1, f2)  # IntValue vs FloatValue, == compares representations!
    assert f2 == f3
    assert f2 == f4
    assert f2 == f5
    assert f2 == f6
Ejemplo n.º 13
0
def test_int(self):
    f1 = as_ufl(1)
    f2 = as_ufl(1.0)
    f3 = IntValue(1)
    f4 = IntValue(1.0)
    f5 = 3 - IntValue(1) - 1
    f6 = 3 * IntValue(2) / 6

    assert f1 == f1
    self.assertNotEqual(f1, f2)  # IntValue vs FloatValue, == compares representations!
    assert f1 == f3
    assert f1 == f4
    assert f1 == f5
    assert f2 == f6  # Division produces a FloatValue
Ejemplo n.º 14
0
def outer(*operands):
    "UFL operator: Take the outer product of two or more operands. The complex conjugate of the first argument is taken."
    n = len(operands)
    if n == 1:
        return operands[0]
    elif n == 2:
        a, b = operands
    else:
        a = outer(*operands[:-1])
        b = operands[-1]
    a = as_ufl(a)
    b = as_ufl(b)
    if a.ufl_shape == () and b.ufl_shape == ():
        return Conj(a) * b
    return Outer(a, b)
Ejemplo n.º 15
0
def outer(*operands):
    "UFL operator: Take the outer product of two or more operands."
    n = len(operands)
    if n == 1:
        return operands[0]
    elif n == 2:
        a, b = operands
    else:
        a = outer(*operands[:-1])
        b = operands[-1]
    a = as_ufl(a)
    b = as_ufl(b)
    if a.shape() == () and b.shape() == ():
        return a*b
    return Outer(a, b)
Ejemplo n.º 16
0
def Dn(f):
    """UFL operator: Take the directional derivative of *f* in the
    facet normal direction, Dn(f) := dot(grad(f), n)."""
    f = as_ufl(f)
    if is_cellwise_constant(f):
        return Zero(f.ufl_shape, f.ufl_free_indices, f.ufl_index_dimensions)
    return dot(grad(f), FacetNormal(f.ufl_domain()))
Ejemplo n.º 17
0
def test_scalar_sums(self):
    n = 10
    s = [as_ufl(i) for i in range(n)]

    for i in range(n):
        self.assertNotEqual(s[i], i+1)

    for i in range(n):
        assert s[i] == i

    for i in range(n):
        assert 0 + s[i] == i

    for i in range(n):
        assert s[i] + 0 == i

    for i in range(n):
        assert 0 + s[i] + 0 == i

    for i in range(n):
        assert 1 + s[i] - 1 == i

    assert s[1] + s[1] == 2
    assert s[1] + s[2] == 3
    assert s[1] + s[2] + s[3] == s[6]
    assert s[5] - s[2] == 3
    assert 1*s[5] == 5
    assert 2*s[5] == 10
    assert s[6]/3 == 2
Ejemplo n.º 18
0
def test_complex(self):
    f1 = as_ufl(1 + 1j)
    f2 = as_ufl(1)
    f3 = as_ufl(1j)
    f4 = ComplexValue(1 + 1j)
    f5 = ComplexValue(1.0 + 1.0j)
    f6 = as_ufl(1.0)
    f7 = as_ufl(1.0j)

    assert f1 == f1
    assert f1 == f4
    assert f1 == f5  # ComplexValue uses floats
    assert f1 == f2 + f3  # Type promotion of IntValue to ComplexValue with arithmetic
    assert f4 == f2 + f3
    assert f5 == f2 + f3
    assert f4 == f5
    assert f6 + f7 == f2 + f3
Ejemplo n.º 19
0
def Dn(f):
    """UFL operator: Take the directional derivative of f in the
    facet normal direction, Dn(f) := dot(grad(f), n)."""
    f = as_ufl(f)
    cell = f.cell()
    if cell is None: # FIXME: Rather if f.is_cellwise_constant()?
        return Zero(f.shape(), f.free_indices(), f.index_dimensions())
    return dot(grad(f), cell.n)
Ejemplo n.º 20
0
def _mathfunction(f, cls):
    f = as_ufl(f)
    r = cls(f)
    if isinstance(r, (RealValue, Zero, int, float)):
        return float(r)
    if isinstance(r, (ComplexValue, complex)):
        return complex(r)
    return r
Ejemplo n.º 21
0
    def __init__(self, name, classname, nu, argument):
        if not is_true_ufl_scalar(nu):
            error("Expecting scalar nu.")
        if not is_true_ufl_scalar(argument):
            error("Expecting scalar argument.")

        # Use integer representation if suitable
        fnu = float(nu)
        inu = int(nu)
        if fnu == inu:
            nu = as_ufl(inu)
        else:
            nu = as_ufl(fnu)

        Operator.__init__(self, (nu, argument))

        self._classname = classname
        self._name = name
Ejemplo n.º 22
0
 def __init__(self, condition, true_value, false_value):
     Operator.__init__(self)
     ufl_assert(isinstance(condition, Condition), "Expectiong condition as first argument.")
     true_value = as_ufl(true_value)
     false_value = as_ufl(false_value)
     tsh = true_value.shape()
     fsh = false_value.shape()
     ufl_assert(tsh == fsh, "Shape mismatch between conditional branches.")
     tfi = true_value.free_indices()
     ffi = false_value.free_indices()
     ufl_assert(tfi == ffi, "Free index mismatch between conditional branches.")
     if isinstance(condition, (EQ,NE)):
         ufl_assert(condition._left.shape() == ()
                    and condition._left.free_indices() == ()
                    and condition._right.shape() == ()
                    and condition._right.free_indices() == (),
                    "Non-scalar == or != is not allowed.")
     self._condition = condition
     self._true_value = true_value
     self._false_value = false_value
Ejemplo n.º 23
0
    def __init__(self, condition, true_value, false_value):
        if not isinstance(condition, Condition):
            error("Expectiong condition as first argument.")
        true_value = as_ufl(true_value)
        false_value = as_ufl(false_value)
        tsh = true_value.ufl_shape
        fsh = false_value.ufl_shape
        if tsh != fsh:
            error("Shape mismatch between conditional branches.")
        tfi = true_value.ufl_free_indices
        ffi = false_value.ufl_free_indices
        if tfi != ffi:
            error("Free index mismatch between conditional branches.")
        if isinstance(condition, (EQ, NE)):
            if not all((condition.ufl_operands[0].ufl_shape == (),
                        condition.ufl_operands[0].ufl_free_indices == (),
                        condition.ufl_operands[1].ufl_shape == (),
                        condition.ufl_operands[1].ufl_free_indices == ())):
                error("Non-scalar == or != is not allowed.")

        Operator.__init__(self, (condition, true_value, false_value))
Ejemplo n.º 24
0
def elem_op(op, *args):
    "UFL operator: Take the elementwise application of operator *op* on scalar values from one or more tensor arguments."
    args = [as_ufl(arg) for arg in args]
    sh = args[0].ufl_shape
    if not all(sh == x.ufl_shape for x in args):
        error("Cannot take elementwise operation with different shapes.")

    if sh == ():
        return op(*args)

    def op_ind(ind, *args):
        return op(*[x[ind] for x in args])
    return as_tensor(elem_op_items(op_ind, (), *args))
Ejemplo n.º 25
0
def nabla_div(f):
    """UFL operator: Take the divergence of f.

    This operator follows the div convention where

      nabla_div(v) = v[i].dx(i)

      nabla_div(T)[:] = T[i,:].dx(i)

    for vector expressions v, and
    arbitrary rank tensor expressions T.
    """
    f = as_ufl(f)
    return NablaDiv(f)
Ejemplo n.º 26
0
    def __new__(cls, a, b):
        a = as_ufl(a)
        b = as_ufl(b)
        if not is_true_ufl_scalar(a): error("Cannot take the power of a non-scalar expression.")
        if not is_true_ufl_scalar(b): error("Cannot raise an expression to a non-scalar power.")

        if isinstance(a, ScalarValue) and isinstance(b, ScalarValue):
            return as_ufl(a._value ** b._value)
        if a == 0 and isinstance(b, ScalarValue):
            bf = float(b)
            if bf < 0:
                error("Division by zero, annot raise 0 to a negative power.")
            else:
                return zero()
        if b == 1:
            return a
        if b == 0:
            return IntValue(1)

        # construct and initialize a new Power object
        self = AlgebraOperator.__new__(cls)
        self._init(a, b)
        return self
Ejemplo n.º 27
0
def test_zero(self):
    z1 = Zero(())
    z2 = Zero(())
    z3 = as_ufl(0)
    z4 = as_ufl(0.0)
    z5 = FloatValue(0)
    z6 = FloatValue(0.0)

    # self.assertTrue(z1 is z2)
    # self.assertTrue(z1 is z3)
    # self.assertTrue(z1 is z4)
    # self.assertTrue(z1 is z5)
    # self.assertTrue(z1 is z6)
    assert z1 == z1
    assert int(z1) == 0
    assert float(z1) == 0.0
    assert complex(z1) == 0.0 + 0.0j
    self.assertNotEqual(z1, 1.0)
    self.assertFalse(z1)

    # If zero() == 0 is to be allowed, it must not have the same hash or it will collide with 0 as key in dicts...
    self.assertNotEqual(hash(z1), hash(0.0))
    self.assertNotEqual(hash(z1), hash(0))
Ejemplo n.º 28
0
 def __init__(self, name, left, right):
     Operator.__init__(self)
     self._name = name
     self._left = as_ufl(left)
     self._right = as_ufl(right)
     if name in ('!=', '=='):
         # Since equals and not-equals are used for comparing representations,
         # we have to allow any shape here. The scalar properties must be
         # checked when used in conditional instead!
         pass
     elif name in ('&&', '||'):
         # Binary operators acting on boolean expressions allow only conditions
         ufl_assert(isinstance(self._left, Condition),
                    "Expecting a Condition, not a %s." % self._left._uflclass)
         ufl_assert(isinstance(self._right, Condition),
                    "Expecting a Condition, not a %s." % self._right._uflclass)
     else:
         # Binary operators acting on non-boolean expressions allow only scalars
         ufl_assert(self._left.shape() == () \
                        and  self._right.shape() == (),
                    "Expecting scalar arguments.")
         ufl_assert(self._left.free_indices() == () \
                        and self._right.free_indices() == (),
                    "Expecting scalar arguments.")
Ejemplo n.º 29
0
    def __init__(self, expression, label=None):
        # Conversion
        expression = as_ufl(expression)
        if label is None:
            label = Label()

        # Checks
        if not isinstance(expression, Expr):
            error("Expecting Expr.")
        if not isinstance(label, Label):
            error("Expecting a Label.")
        if expression.ufl_free_indices:
            error("Variable cannot wrap an expression with free indices.")

        Operator.__init__(self, (expression, label))
def test_dolfin_expression_compilation_of_scalar_literal():
    # Define some literal ufl expression
    uexpr = as_ufl(3.14)

    # Define expected output from compilation
    expected_lines = ['double s[1];',
                      's[0] = 3.14;',
                      'values[0] = s[0];']

    # Define expected evaluation values: [(x,value), (x,value), ...]
    expected_values = [((0.0, 0.0), (3.14,)),
                       ((0.6, 0.7), (3.14,)),
                       ]

    # Execute all tests
    check_dolfin_expression_compilation(uexpr, expected_lines, expected_values)
Ejemplo n.º 31
0
def Dx(f, *i):
    """UFL operator: Take the partial derivative of f with respect
    to spatial variable number i. Equivalent to f.dx(\*i)."""
    f = as_ufl(f)
    return f.dx(*i)