Subject: [FFC-dev] More thoughts on tuple notation

From: Anders Logg <[email-masked]>
Date: Wed, 1 Apr 2009 01:21:24 +0200

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

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      # ???

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.

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.

-- 
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 08:58:09 +0200

>  (3)    \int_{\Omega} (v, w) dx

Not really. It's a definition, see below.

>  a = v*div((w, grad(u)))*dx      # ???

1) This doesn't even make any sense. Inner always returns a scalar.
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.

> as on paper. Sometimes one notation is convenient, sometimes the

The way I see it, we have
  f*dx
which is similar to and defined to represent
  \int_{\Omega} f dx

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

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

and
  (u,v)*dx(0)
which is similar to and defined to represent
  (u, v)_{\Omega_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.

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

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

Martin

---

From: Anders Logg <[email-masked]>
Date: Wed, 1 Apr 2009 15:35:12 +0200

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

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

> which is similar to and defined to represent

Yes.

> which is similar to and defined to represent

Yes,

> which is similar to and defined to represent

This can be replaced by (u, v).

> which is similar to and defined to represent

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

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

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

> 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

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 23:25:28 +0200

It seems important to you, so I won't argue any further.
You're right that it's non-intrusive, so it won't be a big problem.

Martin

2009/4/1 Anders Logg <[email-masked]>:
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAknTbY8ACgkQTuwUCDsYZdEYpwCgljQhHg5AcVOZjGTro1+AJYvG
> PmEAn14HoIXVinGLM186YdW53WBDy8dH
> =ntRz
> -----END PGP SIGNATURE-----
>
>

---

From: Anders Logg <[email-masked]>
Date: Thu, 2 Apr 2009 22:13:12 +0200

Thanks. I'll make the changes.

-- 
Anders

On Wed, Apr 01, 2009 at 11:25:28PM +0200, Martin Sandve Alnæs wrote:
> _______________________________________________
> FFC-dev mailing list
> [email-masked]
> http://www.fenics.org/mailman/listinfo/ffc-dev