Пример #1
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
Пример #2
0
class IDiv(AugmentedAssignment):

    """A UFL `/=` operator."""
    _symbol = "/="
    _ast = ast.IDiv
    _identity = IntValue(1)
    __slots__ = ()
Пример #3
0
class IMul(AugmentedAssignment):

    """A UFL `*=` operator."""
    _symbol = "*="
    _ast = ast.IMul
    _identity = IntValue(1)
    __slots__ = ()
Пример #4
0
    def __new__(cls, a, b):
        # Conversion
        a = as_ufl(a)
        b = as_ufl(b)

        # Type checking
        if not is_true_ufl_scalar(a):
            error("Cannot take the power of a non-scalar expression %s." %
                  ufl_err_str(a))
        if not is_true_ufl_scalar(b):
            error("Cannot raise an expression to a non-scalar power %s." %
                  ufl_err_str(b))

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

        # Construction
        self = Operator.__new__(cls)
        self._init(a, b)
        return self
Пример #5
0
    def _make_ones_diff(self, o):
        ufl_assert(o.shape() == self._var_shape,
                   "This is only used by VariableDerivative, yes?")
        # Define a scalar value with the right indices
        # (kind of cumbersome this... any simpler way?)

        sh = o.shape()
        fi = o.free_indices()
        idims = dict(o.index_dimensions())

        if self._var_free_indices:
            # Currently assuming only one free variable index
            i, = self._var_free_indices
            if i not in idims:
                fi = unique_indices(fi + (i, ))
                idims[i] = self._var_index_dimensions[i]

        # Create a 1 with index annotations
        one = IntValue(1, (), fi, idims)

        res = None
        if sh == ():
            return one
        elif len(sh) == 1:
            # FIXME: If sh == (1,), I think this will get the wrong shape?
            # I think we should make sure sh=(1,...,1) is always converted to () early.
            fp = Identity(sh[0])
        else:
            ind1 = ()
            ind2 = ()
            for d in sh:
                i, j = indices(2)
                dij = Identity(d)[i, j]
                if res is None:
                    res = dij
                else:
                    res *= dij
                ind1 += (i, )
                ind2 += (j, )
            fp = as_tensor(res, ind1 + ind2)

        # Apply index annotations
        if fi:
            fp *= one

        return fp
Пример #6
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
Пример #7
0
    def __new__(cls, *operands):
        # Make sure everything is an Expr
        operands = [as_ufl(o) for o in operands]

        # Make sure everything is scalar
        #ufl_assert(not any(o.shape() for o in operands),
        #    "Product can only represent products of scalars.")
        if any(o.shape() for o in operands):
            error("Product can only represent products of scalars.")

        # No operands? Return one.
        if not operands:
            return IntValue(1)

        # Got one operand only? Just return it.
        if len(operands) == 1:
            return operands[0]

        # Got any zeros? Return zero.
        if any(isinstance(o, Zero) for o in operands):
            free_indices     = unique_indices(tuple(chain(*(o.free_indices() for o in operands))))
            index_dimensions = subdict(mergedicts([o.index_dimensions() for o in operands]), free_indices)
            return Zero((), free_indices, index_dimensions)

        # Merge scalars, but keep nonscalars sorted
        scalars = []
        nonscalars = []
        for o in operands:
            if isinstance(o, ScalarValue):
                scalars.append(o)
            else:
                nonscalars.append(o)
        if scalars:
            # merge scalars
            p = as_ufl(product(s._value for s in scalars))
            # only scalars?
            if not nonscalars:
                return p
            # merged scalar is unity?
            if p == 1:
                scalars = []
                # Left with one nonscalar operand only after merging scalars?
                if len(nonscalars) == 1:
                    return nonscalars[0]
            else:
                scalars = [p]

        # Sort operands in a canonical order (NB! This is fragile! Small changes here can have large effects.)
        operands = scalars + sorted_expr(nonscalars)

        # Replace n-repeated operands foo with foo**n
        newoperands = []
        op, nop = operands[0], 1
        for o in operands[1:] + [None]:
            if o == op:
                # op is repeated, count number of repetitions
                nop += 1
            else:
                if nop == 1:
                    # op is not repeated
                    newoperands.append(op)
                elif op.free_indices():
                    # We can't simplify products to powers if the operands has
                    # free indices, because of complications in differentiation.
                    # op repeated, but has free indices, so we don't simplify
                    newoperands.extend([op]*nop)
                else:
                    # op repeated, make it a power
                    newoperands.append(op**nop)
                # Reset op as o
                op, nop = o, 1
        operands = newoperands

        # Left with one operand only after simplifications?
        if len(operands) == 1:
            return operands[0]

        # Construct and initialize a new Product object
        self = AlgebraOperator.__new__(cls)
        self._init(*operands)
        return self
Пример #8
0
 def _tensor(self, key, indices):
     tensor = ExprTensor(self._shape(key))
     tensor[indices] = IntValue(1)
     return {key: tensor}