← Back to team overview

dolfin team mailing list archive

Re: Another suggestion for the Function class

 

On Tuesday 02 December 2008 12:06:17 Anders Logg wrote:
> On Tue, Dec 02, 2008 at 12:00:34PM +0100, Martin Sandve Alnæs wrote:
> > 2008/12/2 Anders Logg <logg@xxxxxxxxx>:
> > > Would it be difficult to add the possibility of sending in a SymPy or
> > > Swiginac expression to the Function constructor? As I understand, both
> > > can generate C++ code so it seems we could reuse what we already have
> > > for cppexpr.
> >
> > Trivial. Except that the symbols used must be named like
> > x = swiginac.symbol("x[0]") etc from the user side, we can
> > just call "swiginac_expression.printc()" to get a scalar string.
> > Eventually "swiginac_expression.evalm().evalf().printc()"
> > to be on the safe side.

We need to think of why we want this. Is it to be able to automatic 
differentiate a coeffisient function in a form, which I suppose ufl.sin will 
be able to, or to _even_ easier write user defined coefficient functions? 

If it is the latter, and only the latter, I really do not think we need it. We 
have already stated for a user that a compiled coefficient function can be 
used by 

  f = Function(cppexpr = "sin(x[0])")

By this we have stated that we have to do something behind the seen to make it 
happen, and I think this is good. It is a one liner and it cannot be 
missinterpreted as something else. 

If we make it too easy a la,

  f = sin(x)

we can run into different namespace trubles as mentioned below. The code above 
could produce different results depending of what "sin" actually is.

Introducing swiginac or sympy statements should also include a benefit of 
using the symbolic character of these libraries to legitemise the use. Not 
only the "to_c" functionality. And as I understand it will at least some of 
the symbolic character be supported in ufl, right?

> Can't we just define
>
>   x = swiginac.symbol("x[0]")

I am strongly against this. Symbols that are often used in user code should 
not be predefined in a library code. I see this quite a bit in dolfin where 
the namespace of ffc is included. D, i, j, n and m are all defined and have 
explicit meaning. When ffc is used in form files this is obviuosly OK, but 
when included in the dolfin namespace we get potential complications.

> in the __init__ file for DOLFIN so x would be available directly, just
> like dx, ds, grad, etc.
>
> > > Then, one could do things like
> > >
> > > f = Function(V, sin(x))
> > >
> > > which would be close to optimal.
> >
> > You're forgetting namespace clashes here...
> > In real code there will have to be detailed imports from different
> > modules or explicit namespace handling to separate
> > sympy.sin, numpy.sin, ufl.sin and math.sin.
>
> Ah, this can be problematic.

Yes, see below.

> > > The best of course would be if one
> > > did not need to first define f and then use it, but instead could
> > > write it directly in the form:
> > >
> > > L = v*sin(x)*dx
> >
> > We can do that easily if we add terminal symbols x,y,z or x[0], x[1],
> > ... to UFL.
> >
> > from ufl import *
> > polygon = triangle
> > element = FiniteElement("CG", polygon, 1)
> > v = TestFunction(element)
> > x = SpatialCoordinate(polygon)
> > f = sin(x[0])
> > a = f*v*dx
> >
> > Generated quadrature code can handle this directly, while tensor
> > representation would require some function extraction magic.
>
> Sounds good.

This looks good, but in a dolfin contex I think we need to hide this, e.g., in 
a dolfin.ufl namespace. Then if a user want to include sin, cos, x, y, z... 
from ufl in a dolfin setting he/she need to from dolfin.ufl include *, and 
they should not be included in a from dolfin import * statement.


Johan


Follow ups

References