Пример #1
0
def _eval(self, coord, mapping=None, component=()):
    # Evaluate expression at this particular coordinate, with provided
    # values for other terminals in mapping

    # Evaluate derivatives first
    from ufl.algorithms import expand_derivatives
    f = expand_derivatives(self)

    # Evaluate recursively
    if mapping is None:
        mapping = {}
    index_values = StackDict()
    return f.evaluate(coord, mapping, component, index_values)
Пример #2
0
 def __init__(self):
     ReuseTransformer.__init__(self)
     self._components = Stack()
     self._index2value = StackDict()
Пример #3
0
class IndexExpander(ReuseTransformer):
    """..."""
    def __init__(self):
        ReuseTransformer.__init__(self)
        self._components = Stack()
        self._index2value = StackDict()

    def component(self):
        "Return current component tuple."
        if self._components:
            return self._components.peek()
        return ()

    def terminal(self, x):
        if x.ufl_shape:
            c = self.component()
            if len(x.ufl_shape) != len(c):
                error("Component size mismatch.")
            return x[c]
        return x

    def form_argument(self, x):
        sh = x.ufl_shape
        if sh == ():
            return x
        else:
            e = x.ufl_element()
            r = len(sh)

            # Get component
            c = self.component()
            if r != len(c):
                error("Component size mismatch.")

            # Map it through an eventual symmetry mapping
            s = e.symmetry()
            c = s.get(c, c)
            if r != len(c):
                error("Component size mismatch after symmetry mapping.")

            return x[c]

    def zero(self, x):
        if len(x.ufl_shape) != len(self.component()):
            error("Component size mismatch.")

        s = set(x.ufl_free_indices) - set(i.count()
                                          for i in self._index2value.keys())
        if s:
            error(
                "Free index set mismatch, these indices have no value assigned: %s."
                % str(s))

        # There is no index/shape info in this zero because that is asserted above
        return Zero()

    def scalar_value(self, x):
        if len(x.ufl_shape) != len(self.component()):
            self.print_visit_stack()
        if len(x.ufl_shape) != len(self.component()):
            error("Component size mismatch.")

        s = set(x.ufl_free_indices) - set(i.count()
                                          for i in self._index2value.keys())
        if s:
            error(
                "Free index set mismatch, these indices have no value assigned: %s."
                % str(s))

        return x._ufl_class_(x.value())

    def conditional(self, x):
        c, t, f = x.ufl_operands

        # Not accepting nonscalars in condition
        if c.ufl_shape != ():
            error("Not expecting tensor in condition.")

        # Conditional may be indexed, push empty component
        self._components.push(())
        c = self.visit(c)
        self._components.pop()

        # Keep possibly non-scalar components for values
        t = self.visit(t)
        f = self.visit(f)

        return self.reuse_if_possible(x, c, t, f)

    def division(self, x):
        a, b = x.ufl_operands

        # Not accepting nonscalars in division anymore
        if a.ufl_shape != ():
            error("Not expecting tensor in division.")
        if self.component() != ():
            error("Not expecting component in division.")

        if b.ufl_shape != ():
            error("Not expecting division by tensor.")
        a = self.visit(a)

        # self._components.push(())
        b = self.visit(b)
        # self._components.pop()

        return self.reuse_if_possible(x, a, b)

    def index_sum(self, x):
        ops = []
        summand, multiindex = x.ufl_operands
        index, = multiindex

        # TODO: For the list tensor purging algorithm, do something like:
        # if index not in self._to_expand:
        #     return self.expr(x, *[self.visit(o) for o in x.ufl_operands])

        for value in range(x.dimension()):
            self._index2value.push(index, value)
            ops.append(self.visit(summand))
            self._index2value.pop()
        return sum(ops)

    def _multi_index_values(self, x):
        comp = []
        for i in x._indices:
            if isinstance(i, FixedIndex):
                comp.append(i._value)
            elif isinstance(i, Index):
                comp.append(self._index2value[i])
        return tuple(comp)

    def multi_index(self, x):
        comp = self._multi_index_values(x)
        return MultiIndex(tuple(FixedIndex(i) for i in comp))

    def indexed(self, x):
        A, ii = x.ufl_operands

        # Push new component built from index value map
        self._components.push(self._multi_index_values(ii))

        # Hide index values (doing this is not correct behaviour)
        # for i in ii:
        #     if isinstance(i, Index):
        #         self._index2value.push(i, None)

        result = self.visit(A)

        # Un-hide index values
        # for i in ii:
        #     if isinstance(i, Index):
        #         self._index2value.pop()

        # Reset component
        self._components.pop()
        return result

    def component_tensor(self, x):
        # This function evaluates the tensor expression
        # with indices equal to the current component tuple
        expression, indices = x.ufl_operands
        if expression.ufl_shape != ():
            error("Expecting scalar base expression.")

        # Update index map with component tuple values
        comp = self.component()
        if len(indices) != len(comp):
            error("Index/component mismatch.")
        for i, v in zip(indices.indices(), comp):
            self._index2value.push(i, v)
        self._components.push(())

        # Evaluate with these indices
        result = self.visit(expression)

        # Revert index map
        for _ in comp:
            self._index2value.pop()
        self._components.pop()
        return result

    def list_tensor(self, x):
        # Pick the right subtensor and subcomponent
        c = self.component()
        c0, c1 = c[0], c[1:]
        op = x.ufl_operands[c0]
        # Evaluate subtensor with this subcomponent
        self._components.push(c1)
        r = self.visit(op)
        self._components.pop()
        return r

    def grad(self, x):
        f, = x.ufl_operands
        if not isinstance(f, (Terminal, Grad)):
            error("Expecting expand_derivatives to have been applied.")
        # No need to visit child as long as it is on the form [Grad]([Grad](terminal))
        return x[self.component()]
Пример #4
0
def test_stackdict():
    from ufl.utils.stacks import StackDict
    d = StackDict(a=1)
    assert d["a"] == 1
    d.push("a", 2)
    assert d["a"] == 2
    d.push("a", 3)
    d.push("b", 9)
    assert d["a"] == 3
    assert d["b"] == 9
    d.pop()
    assert d["a"] == 3
    assert "b" not in d
    d.pop()
    assert d["a"] == 2
    d.pop()
    assert d["a"] == 1
Пример #5
0
 def __init__(self):
     ReuseTransformer.__init__(self)
     self._components = Stack()
     self._index2value = StackDict()
Пример #6
0
class IndexExpander(ReuseTransformer):
    """..."""

    def __init__(self):
        ReuseTransformer.__init__(self)
        self._components = Stack()
        self._index2value = StackDict()

    def component(self):
        "Return current component tuple."
        if self._components:
            return self._components.peek()
        return ()

    def terminal(self, x):
        if x.ufl_shape:
            c = self.component()
            if len(x.ufl_shape) != len(c):
                error("Component size mismatch.")
            return x[c]
        return x

    def form_argument(self, x):
        sh = x.ufl_shape
        if sh == ():
            return x
        else:
            e = x.ufl_element()
            r = len(sh)

            # Get component
            c = self.component()
            if r != len(c):
                error("Component size mismatch.")

            # Map it through an eventual symmetry mapping
            s = e.symmetry()
            c = s.get(c, c)
            if r != len(c):
                error("Component size mismatch after symmetry mapping.")

            return x[c]

    def zero(self, x):
        if len(x.ufl_shape) != len(self.component()):
            error("Component size mismatch.")

        s = set(x.ufl_free_indices) - set(i.count() for i in self._index2value.keys())
        if s:
            error("Free index set mismatch, these indices have no value assigned: %s." % str(s))

        # There is no index/shape info in this zero because that is asserted above
        return Zero()

    def scalar_value(self, x):
        if len(x.ufl_shape) != len(self.component()):
            self.print_visit_stack()
        if len(x.ufl_shape) != len(self.component()):
            error("Component size mismatch.")

        s = set(x.ufl_free_indices) - set(i.count() for i in self._index2value.keys())
        if s:
            error("Free index set mismatch, these indices have no value assigned: %s." % str(s))

        return x._ufl_class_(x.value())

    def conditional(self, x):
        c, t, f = x.ufl_operands

        # Not accepting nonscalars in condition
        if c.ufl_shape != ():
            error("Not expecting tensor in condition.")

        # Conditional may be indexed, push empty component
        self._components.push(())
        c = self.visit(c)
        self._components.pop()

        # Keep possibly non-scalar components for values
        t = self.visit(t)
        f = self.visit(f)

        return self.reuse_if_possible(x, c, t, f)

    def division(self, x):
        a, b = x.ufl_operands

        # Not accepting nonscalars in division anymore
        if a.ufl_shape != ():
            error("Not expecting tensor in division.")
        if self.component() != ():
            error("Not expecting component in division.")

        if b.ufl_shape != ():
            error("Not expecting division by tensor.")
        a = self.visit(a)

        # self._components.push(())
        b = self.visit(b)
        # self._components.pop()

        return self.reuse_if_possible(x, a, b)

    def index_sum(self, x):
        ops = []
        summand, multiindex = x.ufl_operands
        index, = multiindex

        # TODO: For the list tensor purging algorithm, do something like:
        # if index not in self._to_expand:
        #     return self.expr(x, *[self.visit(o) for o in x.ufl_operands])

        for value in range(x.dimension()):
            self._index2value.push(index, value)
            ops.append(self.visit(summand))
            self._index2value.pop()
        return sum(ops)

    def _multi_index_values(self, x):
        comp = []
        for i in x._indices:
            if isinstance(i, FixedIndex):
                comp.append(i._value)
            elif isinstance(i, Index):
                comp.append(self._index2value[i])
        return tuple(comp)

    def multi_index(self, x):
        comp = self._multi_index_values(x)
        return MultiIndex(tuple(FixedIndex(i) for i in comp))

    def indexed(self, x):
        A, ii = x.ufl_operands

        # Push new component built from index value map
        self._components.push(self._multi_index_values(ii))

        # Hide index values (doing this is not correct behaviour)
        # for i in ii:
        #     if isinstance(i, Index):
        #         self._index2value.push(i, None)

        result = self.visit(A)

        # Un-hide index values
        # for i in ii:
        #     if isinstance(i, Index):
        #         self._index2value.pop()

        # Reset component
        self._components.pop()
        return result

    def component_tensor(self, x):
        # This function evaluates the tensor expression
        # with indices equal to the current component tuple
        expression, indices = x.ufl_operands
        if expression.ufl_shape != ():
            error("Expecting scalar base expression.")

        # Update index map with component tuple values
        comp = self.component()
        if len(indices) != len(comp):
            error("Index/component mismatch.")
        for i, v in zip(indices.indices(), comp):
            self._index2value.push(i, v)
        self._components.push(())

        # Evaluate with these indices
        result = self.visit(expression)

        # Revert index map
        for _ in comp:
            self._index2value.pop()
        self._components.pop()
        return result

    def list_tensor(self, x):
        # Pick the right subtensor and subcomponent
        c = self.component()
        c0, c1 = c[0], c[1:]
        op = x.ufl_operands[c0]
        # Evaluate subtensor with this subcomponent
        self._components.push(c1)
        r = self.visit(op)
        self._components.pop()
        return r

    def grad(self, x):
        f, = x.ufl_operands
        if not isinstance(f, (Terminal, Grad)):
            error("Expecting expand_derivatives to have been applied.")
        # No need to visit child as long as it is on the form [Grad]([Grad](terminal))
        return x[self.component()]
Пример #7
0
def test_stackdict():
    from ufl.utils.stacks import StackDict
    d = StackDict(a=1)
    assert d["a"] == 1
    d.push("a", 2)
    assert d["a"] == 2
    d.push("a", 3)
    d.push("b", 9)
    assert d["a"] == 3
    assert d["b"] == 9
    d.pop()
    assert d["a"] == 3
    assert "b" not in d
    d.pop()
    assert d["a"] == 2
    d.pop()
    assert d["a"] == 1