← Back to team overview

dolfin team mailing list archive

Re: [HG DOLFIN] Automatically interpolate user-defined functions on assignment

 

On Thursday 12 March 2009 13:42:55 Martin Sandve Alnæs wrote:
> On Thu, Mar 12, 2009 at 1:16 PM, Johan Hake <hake@xxxxxxxxx> wrote:
> > On Thursday 12 March 2009 12:58:33 Garth N. Wells wrote:
> >> Anders Logg wrote:
> >> > On Thu, Mar 12, 2009 at 10:46:14AM +0100, Martin Sandve Alnæs wrote:
> >> >> On Thu, Mar 12, 2009 at 10:32 AM, Anders Logg <logg@xxxxxxxxx> wrote:
> >> >>> On Thu, Mar 12, 2009 at 10:25:36AM +0100, Martin Sandve Alnæs wrote:
> >> >>>> I have serious problems with the idea of letting user-defined
> >> >>>> functions change nature to discrete functions as a side effect
> >> >>>> of other operations, effectively hiding the user-defined
> >> >>>> implementation of eval.
> >> >>>>
> >> >>>> (I know this concept wasn't introduced in this discussion, but it's
> >> >>>> related).
> >> >>>
> >> >>> You mean by calling u.vector()? Yes, I agree it's problematic.
> >> >>>
> >> >>> But I don't know how to handle it otherwise. Consider the following
> >> >>> example:
> >> >>>
> >> >>>  u = Function(V)
> >> >>>  solve(A, u.vector(), b)
> >> >>>
> >> >>> First u is a user-defined function since it doesn't have a
> >> >>> vector. Then it becomes discrete when we ask for the vector.
> >> >>>
> >> >>> The problem I think is that there is no way for us to check whether
> >> >>> a user has overloaded eval() without trying to call it.
> >> >>
> >> >> If we didn't require that user-defined functions had a function space
> >> >> for various operations, this wouldn't be as large a problem.
> >> >> Then you could do
> >> >>
> >> >> class MyFunction(Function)
> >> >> {
> >> >>   MyFunction(V): Function(V) {}
> >> >>   MyFunction(): Function() {}
> >> >>   void eval(...) { ... }
> >> >> }
> >> >>
> >> >> MyFunction f;
> >> >> f.vector(); // error, no function space!
> >> >>
> >> >> MyFunction f(V);
> >> >> f.vector(); // ok, should interpolate and make f discrete
> >> >>
> >> >> This is already possible, but function spaces get attached
> >> >> unneccesarily:
> >> >>
> >> >>
> >> >> 1) It's not necessary to attach function spaces to functions for
> >> >> assembly, since a user-defined function is evaluated through
> >> >> ufc::finite_element::evaluate_dofs for each cell anyway.
> >> >> This would remove the need for the side-effect in
> >> >>
> >> >> MyFunction f;
> >> >> MyForm a;
> >> >> a.f = f; // attaches function space to f
> >
> > Isn't the function space used to deduct the value rank during assemble
> > now? If we go for this approach we probably need to readd the rank
> > function and make it virtual?
>
> I don't see how the current approach with rank deducted from
> some function space is any safer than deducting it from the
> finite element of the form. Which is to say: this is unsafe, the
> user should define the rank when defining eval.

My point had nothing to do with safety or not. It was just an observation of a 
possible change to the interface. But that said I do see your point.

A user can still implement an erronious rank function, or eval function, 
forcing a segfault during assemble.

> > The geometric dimension is proably deducable from other places during
> > assemble.
>
> Of course, but that doesn't guarantee that the Function and the Form
> uses the same dimensions. Error checking is _the_ reason for
> making the user provide this information explicitly.
>
> The point of having explicit rank in a Function is not that the expected
> rank isn't available during assembly, but because the actual rank of the
> Function should be _checked against_ the rank expected for the form
> argument.
>
> In general, I find it very frustrating that DOLFIN has so little error
> checking. User friendly does not equate to "looking pretty" (which DOLFIN
> does), the user must also get proper feedback _when_ he does mistakes at
> any stage possible. During code generation we can make sure things
> are right by construction, but in library code we must assume the user
> does stupid things all the time (I certainly do!).

I agree.

> >> >> 2) It's not necessary to require f to have a function space to
> >> >> interpolate it into another discrete function, as in:
> >> >>
> >> >> MyFunction f(V);
> >> >> Function g(V);
> >> >> f.interpolate(g.vector(), V)
> >> >>
> >> >> could just be:
> >> >>
> >> >> MyFunction f;
> >> >> Function g(V);
> >> >> f.interpolate(g.vector(), V);
> >> >>
> >> >> or even shorter:
> >> >>
> >> >> MyFunction f;
> >> >> Function g(V);
> >> >> f.interpolate_into(g); // I'm often confused about the direction of
> >> >> "interpolate"
> >> >
> >> > Yes, it's a bit confusing but it can be deduced from the constness or
> >> > no-constness of the functions.
> >> >
> >> > The above example could be
> >> >
> >> >   MyFunction f;
> >> >   Function g(V);
> >> >   g.interpolate(f); // g interpolates f
> >> >
> >> >> Any other places this affects?
> >> >
> >> > I think it's worth trying.
> >>
> >> Agree.
> >
> > Just thinking a bit head of things here:
> > Should it be possible to create a user defined function in python without
> > a FunctionSpace too, with the same inherited restrictions of not beeing
> > able to create a discrete version of it?
>
> Yes. This is both a safety mechanism (it cannot "suddenly" turn discrete),
> and a more flexible construction (see example below).
>
> > I would say that we keep the Python interface as it is, i.e., not letting
> > a a user create functions without a FunctionSpace. The Functions and
> > FunctionSpaces are more connected in python as they (most often) are
> > created in connection to each other.
> >
> > What you say?
>
> I don't agree. Functions don't have to be part of a form, there are
> other uses as well:
>
> f = Function("sin(x[0])")
> g = Function(V1)
> g.interpolate(f)
> h = Function(V2)
> h.interpolate(f)

Sounds reasonable. 

More magical logics behind the scene in function.py comming up! ;)

Johan


References