← Back to team overview

dolfin team mailing list archive

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

 

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.

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

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

should be a natural thing to do.

Martin


Follow ups

References