← Back to team overview

ufl team mailing list archive

Re: More thoughts on tuple notation

 

On Wed, Apr 01, 2009 at 08:58:09AM +0200, Martin Sandve Alnæs wrote:
> 2009/4/1 Anders Logg <logg@xxxxxxxxx>:
> > Here are some more thoughts about the (v, w) notation.
> >
> > On paper, we have two different ways to express a form. Assuming here
> > that v and w are two vector-valued functions, one may either write
> > out the integrals explicitly:
> >
> >  (1.a)  \int_{\Omega} v \cdot w dx
> >  (1.b)  \int_{\Omega} v_i w_i dx
> >
> > or use the shorthand L^2 inner-product notation:
> >
> >  (2)    (v, w)
> >
> > UFL currently supports both (1.a) and (1.b) but not (2).
> > I think we should support all three.
> >
> > What we have now is a mix:
> >
> >  (3)    \int_{\Omega} (v, w) dx
> 
> Not really. It's a definition, see below.
> 
> > This doesn't really make sense and we run into all sorts of trouble.
> > Just consider something like
> >
> >  a = v*div(inner(w, grad(u)))*dx # works
> >  a = v*div((w, grad(u)))*dx      # ???
> 
> 1) This doesn't even make any sense. Inner always returns a scalar.

ok, so replace it by

 a = inner(v, grad(inner(w, grad(u))))*dx # works
 a = (v, grad((w, grad(u))))*dx           # ???

The point is operators can't be applied to a tuple until it has been
multiplied by a measure and turned into a Form.

> 2) A proper error message will trigger so it's not a problem.
> 3) The definition of inner(.,.) and (.,.) is not the same, *dx is
> currently part of the _definition_ of the latter syntax.
> 4) Your tuple syntax (u,v) still runs into all sorts of trouble, e.g.,
> k*(u,v), so you're arguing against that as well.

No, it's different. What we have now is a language for expressing
*integrands*. Then one expects to be able to operate on the
integrands. The tuple notation is for L^2 inner products and then it's
not clear on may operate on the inner products except addition, which
works, and multiplication, which does not work.

> > So I suggest we remove tuples from the form language, in particular
> > multiplying a tuple with a measure, but add back the possibility to
> > create a Form from a tuple. This means that there are two different
> > notations: (1) and (2) and one can be transformed into the other, just
> > as on paper. Sometimes one notation is convenient, sometimes the
> > other.
> 
> The way I see it, we have
>   f*dx
> which is similar to and defined to represent
>   \int_{\Omega} f dx

Yes.

> and
>   f*dx(0)
> which is similar to and defined to represent
>   \int_{\Omega_0} f dx

Yes,

> and
>   (u,v)*dx
> which is similar to and defined to represent
>   (u, v)_{\Omega}

This can be replaced by (u, v).

> and
>   (u,v)*dx(0)
> which is similar to and defined to represent
>   (u, v)_{\Omega_0}

This can be replaced by (u, v, dx(0)).

> Neither of these look exactly the same in UFL as anyone would
> write on paper, because we're working within the constraints of
> a programming language embedded in Python. There are lots
> of mathematical operations that we cannot write as simply
> as on paper, so that's not an argument in itself.

But it *is* possible in this case. The notation is

  (u, v)

and the implementation is

  (u, v)

> > To make it even more explicit, we can move the extraction of a UFL
> > Form from the constructor of the Form class to a function named
> > something like tuple2form and place it under ufl.algorithms. The form
> > compiler may then check the input argument to see whether or not a
> > call to tuple2form is necessary.
> 
> That's what load_forms did the short while this was implemented.
> It doesn't make it any more explicit for the user.

Not for the user, but it separates the tuple notation from the form
language. The form language remains nice and clean (no tuples, just
UFL objects) with an additional utility function to transform a tuple
into a Form.

From the user's perspective, there are two ways to express a form,
either by writing out the integrands or by writing out the L^2 inner
products. The form compiler automatically figures out which notation
is used (either it is a tuple or not a tuple) and makes a simple call
to tuple2form when necessary. It is simple (it just involves a single
function call), non-invasive (it doesn't modify the form language like
the current mix) and it's already implemented.

> It still isn't enough to place this in the form compiler, for example
> rhs and similar functions require a Form.

We can either live without lhs and rhs for the tuple notation, or we
could add a simple call to as_form for a limited number of operators
(like lhs and rhs) that are used to operate on an entire form, which
is everything in formoperators.py:

  lsh
  rhs
  action
  adjoint
  derivative

-- 
Anders

Attachment: signature.asc
Description: Digital signature


Follow ups

References