Subject: [UFL-dev] [HG UFL] Implement short-hand inner product notation (v, u)

From: [email-masked] (UFL)
Date: Mon, 30 Mar 2009 02:15:25 +0200 (CEST)

One or more new changesets pushed to the primary ufl repository.
A short summary of the last three changesets is included below.

changeset:   778:540ea93daca99a3893f2a1417d1c97eeea2e9479
tag:         tip
user:        Anders Logg <[email-masked]>
date:        Mon Mar 30 02:14:58 2009 +0200
files:       ufl/form.py
description:
Implement short-hand inner product notation (v, u)

changeset:   777:328ed696649e25a7abd9c06cefa36f7e240b5a87
user:        "Martin Sandve Alnæs <[email-masked]>"
date:        Sat Mar 28 13:45:57 2009 +0100
files:       ufl/algorithms/renumbering.py
description:
Removed debug print.

changeset:   776:1099016b8c5e306ee8feec8a22a5215583edea34
user:        "Martin Sandve Alnæs <[email-masked]>"
date:        Sat Mar 28 13:29:52 2009 +0100
files:       sandbox/scripts/rendertrees.sh ufl/integral.py
description:
bugfix in multiplication of forms with python scalars.

----------------------------------------------------------------------
For more details, visit http://www.fenics.org/hg/ufl

---

From: Anders Logg <[email-masked]>
Date: Mon, 30 Mar 2009 02:29:50 +0200

> Implement short-hand inner product notation (v, u)

Just arrived in LA and wanted to push something I played with on the
plane.

I've modified form.py to allow a Form to be initialized from a tuple
of integrands and optional measures. It's a small fix, just an added
function call in the constructor that extracts the proper
integrals. Note that no operator overloading is used to accomplish
this. The expression is just written as a common Python tuple from
which the UFL Form is extracted.

The new notation (which is optional) allows the use of the inner
product notation commonly used in the formulation of most finite
element methods.

Here are some examples:

Poisson:

  a = (grad(v), grad(u))

Convection-diffusion-reaction:

  a = (v, dot(beta, grad(u))) + (grad(v), grad(u)) + (v, u)

DG Poisson:

  a = (grad(v), grad(u))
    + (alpha/h('+')*jump(v, n), jump(u, n), dS)
    + (gamma/h*v, u, ds)
    ...

A term is specified either as a tuple

  (expr1, expr2)

or as a triple

  (expr1, expr2, measure)

If no measure is specified, then dx is used.

Caveats:

1. Subtraction does not work, so one needs to do

  a = (grad(v), grad(u)) + (-v, u)

2. Mixing notation does not work:

  a = (grad(v), grad(u)) + v*u*dx

Does this seem ok? I think it's pretty cool. :-)

-- 
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Mon, 30 Mar 2009 08:40:50 +0200

So... This obviously doesn't construct Form instances, but long tuples.
I see how this tuple can be interpreted if you _know_ that it is supposed
to be a Form, so in principle all UFL algorithms can do "form = as_form(form)"
at the top to convert input argument.

But... In load_forms, how can I differentiate between the variables
  a = (u, v) # supposed to be a form
and
  tmp = (u, v) # just a random tuple
or equivalently
  foo = bar() # returns some tuple of expressions that are handy to
compute together
?

The point being, this is not only additional syntax sugar,
but it restricts the features you can use as a side-effect.

Perhaps this should be a PyDOLFIN feature?

Martin

2009/3/30 Anders Logg <[email-masked]>:
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAknQEn0ACgkQTuwUCDsYZdG4mQCeIkCbjXFrj3xniVMpJEFky9j5
> 1QcAn3D5Q0eR9zVSF2Bh0X0DpCPDwkjC
> =bkQc
> -----END PGP SIGNATURE-----
>
> _______________________________________________
> UFL-dev mailing list
> [email-masked]
> http://fenics.org/mailman/listinfo/ufl-dev
>
>

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Mon, 30 Mar 2009 10:17:41 +0200

If we skip the default measure part, this point is weakened.

A tuple t with
  len(t) % 3 == 0
  n = len(t) // 3

can represent a form iff the types match exactly (Expr,Expr,Measure)*n, or
  all(isinstance(a, b) for (a, b) in zip(t, (Expr,Expr,Measure)*n))

and the form is then

form = 0
for i in range(n):
    a,b,c = t[i*3:i*3+3]
    form += inner(a,b)*c

Martin