← Back to team overview

ufl team mailing list archive

Re: UFL transformer

 

Quoting Martin Sandve Alnæs <martinal@xxxxxxxxx>:

> Hi Kristian,
> I'm sending this to ufl-dev as well, some others may be interested.
> (For those who don't know what the Transformer is,
> it is partially documented in the manual now.)
> 
> First you need to understand the difference between defining handlers
> as pre- or post-handlers:
> 
>    def index_sum(self, index_sum, summand, index):
>        ... summand and index has already been visited
> vs
>    def index_sum(self, index_sum):
>        #... visit summand and index yourself:
>        summand, index = index_sum.operands()
>        summand = self.visit(summand)
>        ...
> 
> Then consider that you can attach arbitrary data structures
> to 'self' and update them during the recursion. Thus you can
> keep a stack of the current component and indices:
> push values before visiting subtrees, pop values when they return,
> peek at the top of the stack to get the current value.
> Take a look at the Stack and StackDict classes in ufl.common.
> Something like this would evaluate an index sum
> (probably not what you want now, just an example):
> 
>    def index_sum(self, index_sum):
>        #... visit summand and index yourself:
>        summand, index = index_sum.operands()
>        tmp = 0
>        for i in range(index_sum.dimension()):
>            self._index_values.push(index, i)
>            tmp += self.visit(summand)
>            self._index_values.pop()
>        return tmp

I think this approach will work out, I was thinking about using the replace()
algorithm, but didn't because it has potential of becoming super slow.

> where self._index_values is a StackDict with a "Index -> int" mapping.
> 
> I'll dig up an example of this, but take a look at e.g.
> IndexSum.evaluate, Indexed.evaluate, and
> ComponentTensor.evaluate for the same concept.
> 
> Also, you should apply expand_derivatives to the form before
> you start working with it. This will get rid of all FunctionDerivative
> and VariableDerivative nodes, and propagate all SpatialDerivative
> occurences to terminals, so when you handle a SpatialDerivative
> you know its operand is a terminal (eventually another
> SpatialDerivative for higher order derivatives).
> (I'm currently ironing out some bugs here.)

OK, thanks for the hint.
 
> Are you working on quadrature or tensor code generation?
> I see Anders is working on monomial representation,
> so I'm guessing quadrature?

Yes, I'm working on quadrature. Still poking in all different directions to get
an idea of how to do things.

Kristian
 
> Martin
> 
> 
> 
> On Fri, Feb 20, 2009 at 1:25 PM, Kristian Oelgaard
> <k.b.oelgaard@xxxxxxxxxx> wrote:
> >
> >
> > Hi Martin,
> >
> > I'm afraid that I need a hint on how to go around the only big problem I
> have
> > with Transformer.
> >
> > The problem is picking components or taking derivatives of BasisFunctions
> > (essentially FormArguments)
> >
> > When I generate the code i.e. handle a BasisFunction, I need to know which
> > component is asked for and the number of derivatives and in which
> direction.
> > This is difficult in the current setup as BasisFuncion will be handled
> *before*
> > SpatialDerivative or Indexed.
> >
> > I think one way of handling this would be to traverse the entire expression
> in a
> > forward fashion first and apply indices and derivatives to the
> BasisFunction by
> > creating a new class object which can be handled by the Transformer. Could
> this
> > work? Or is there an obvious way around this which I just don't see?
> >
> > Kristian
> >
> _______________________________________________
> UFL-dev mailing list
> UFL-dev@xxxxxxxxxx
> http://fenics.org/mailman/listinfo/ufl-dev
> 




Follow ups

References