← Back to team overview

dolfin team mailing list archive

Re: Expression class

 



Anders Logg wrote:
On Fri, Nov 13, 2009 at 08:18:38AM +0000, Garth N. Wells wrote:

Anders Logg wrote:
On Fri, Nov 13, 2009 at 07:28:07AM +0100, Johan Hake wrote:
On Thursday 12 November 2009 21:15:51 Anders Logg wrote:
I have received some complaints on the new Expression class. It works
reasonably well from C++ but is still confusing from Python:

1. Why does a function space need to be specified in the constructor?

  f = Expression("sin(x[0])", V=V)

Does this mean f is a function on V? (No, it doesn't.)

2. The keyword argument V=foo is confusing:

  f = Expression(("sin(x[0])", "cos(x[1])"), V=V)
  g = Expression("1 - x[0]", V=Q)

The reason for the function space argument V is that we need to know
how to approximate an expression when it appears in a form. For
example, when we do

  L = dot(v, grad(f))*dx

we need to interpolate f (locally) into a finite element space so we
can compute the gradient.

Sometimes we also need to know the mesh on which the expression is defined:

  M = f*dx

This integral can't be computed unless we know the mesh which is why
one needs to do

  assemble(M, mesh=mesh)

My suggestion for fixing these issues is the following:

1. We require a mesh argument when constructing an expression.

  f = Expression("sin(x[0])", mesh)

2. We allow an optional argument for specifying the finite element.

  f = Expression("sin(x[0])", mesh, element)

We could also have

     f = Expression("sin(x[0])", mesh, k)

where k is the order of the continuous Lagrange basis since that's the
most commonly used.

3. When the element is not specified, we choose a simple default
element which is piecewise linear approximation. We can derive the
geometric dimension from the mesh and we can derive the value shape
from the expression (scalar, vector or tensor).

This is bad. If a user increases the polynomial order of the test/trial
functions and f remains P1, the convergence rate will not be optimal.

A better solution would be to define it on a QuadratureElement by
default. This, I think, is the behaviour that most people would expect.
This would take care of higher-order cases.

Yes, I've thought about this. That would perhaps be the best solution.
Does a quadrature element have a fixed degree or can the form compiler
adjust it later to match the degree of for example the basis functions
in the form?


Kristian?

If one should happen to differentiate a coefficient in a form, we just
need to give an informative error message and advise that one needs to
specify a finite element for the approximation of the coefficient.

This will remove the need for the V argument and the confusion about
whether an expression is defined on some function space (which it is
not).
But it is when it's used in a form since it's interpolated in the given
space.

The important point is that we only need to be able to interpolate it
locally to any given cell in the mesh, so we just need a mesh and a
cell. The dofmap is never used so it's different from a full function
space.


I think you mean element rather than cell?

Garth

It also removes the need for an additional mesh=mesh argument
when assembling functionals and computing norms.

This change will make the Constant and Expression constructors very
similar in that they require a value and a mesh (and some optional
stuff). Therefore it would be good to change the order of the
arguments in Constant so they are the same as in Expression:

 f = Constant(0, mesh)
 f = Expression("0", mesh)

Yes.

Good.

And we should change Constant rather than Expression since Expression
might have an optional element argument:

 f = Expression("0", mesh, element)

Does this sound good?
Yes, I think so. I suppose you mean

  f = CompiledExpression("0", mesh)

Just referring to the Blueprint about the simplification of the Expression
class in PyDOLFIN.
I'm not so sure anymore. Calling it Expression looks simpler.
Agree.

Good.

--
Anders


Garth

What
were the reasons for splitting it into Expression and
CompiledExpression? Is it the problem with the non-standard
constructor when implementing subclasses?

It's just that the most common use of expressions in simple demos will
be stuff like

  f = Expression("sin(x([0])", mesh)

so one could argue that this should be as simple as possible (and just
be named Expression).

Should an Expression in PyDOLFIN  then always have a mesh? This will make an
Expression in PyDOLFIN and DOLFIN different, which is fine with me.
Yes, to avoid needing to pass the mesh to assemble() and norm() in
some cases and to automatically get the geometric dimension.

If others agree, can you add it to the Blueprint, mentioned above, and I can
do the change some time next week, or after a release (?).
Let's hear some more comments first.


_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/mailman/listinfo/dolfin-dev



Follow ups

References