← Back to team overview

ufl team mailing list archive

Re: UFL transformer

 

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

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.)

Are you working on quadrature or tensor code generation?
I see Anders is working on monomial representation,
so I'm guessing quadrature?

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
>


Follow ups