← Back to team overview

dolfin team mailing list archive

Re: Status of new Expression interface

 

On Fri, Nov 27, 2009 at 11:48:11AM -0800, Johan Hake wrote:
> On Friday 27 November 2009 01:20:14 Anders Logg wrote:
> > On Thu, Nov 26, 2009 at 10:49:16PM -0800, Johan Hake wrote:
> > > On Thursday 26 November 2009 16:09:53 Garth N. Wells wrote:
> > > > Anders Logg wrote:
> > > > > On Thu, Nov 26, 2009 at 09:42:22PM +0000, Harish Narayanan wrote:
> > > > >> Anders Logg wrote:
> > > > >>> Looks like the new Expression interface might be working now but
> > > > >>> more tests are needed. Please help out getting all the demos over
> > > > >>> to the new interface.
> > > > >>>
> > > > >>> The changes to the interface are as follows:
> > > > >>>
> > > > >>> 1. V=V argument in Expression should be removed
> > > > >>>
> > > > >>> 2. mesh argument in Constant should be removed
> > > > >>>
> > > > >>> 3. Subclasses of Expression overloading eval must overload dim if
> > > > >>> not scalar
> > >
> > > Ok, this might seem to be a bit far fetched but I think it is quite nice.
> > >
> > > What with:
> > >
> > >   class MyExpression(Expression):
> > >       def eval(self, x):
> > >           ....
> > >           return x_values, y_values
> > >
> > > The value dimension would then just be the length of the return argument.
> > > The _actual_ eval function would then, using the fabulous metaclass, be:
> > >
> > >    def eval(self, values, x):
> > >        values[0], values[1] = user_eval(self, x)
> > >
> > > where user_eval is the eval method defined above by the user.
> > >
> > > This will solve the value dimension problem for python expressions, and
> > > make the eval method the user specify more pythonic.
> >
> > Being able to do return sin(x[0]), cos(x[1]) would be very nice.
> >
> > But I guess we would still have to implement the dim() function when
> > subclassing Expression?
>
> The point was actually to not do that. My initial thought was to call the user
> provided function using a dummy self, (or an initialized one) and a dummy x
> arg. Then the number of return argument would decide the value dimension.
>
> This approach would work for simple Expressions, with no need for a special
> initialization.
>
>    class MyExpression(Expression):
>        def eval(self, x):
>            return sin(x[0]), cos(x[1])
>
> A more complex Expression a la:
>
>    class MyExpression(Expression):
>        def __init__(self, foo, bar):
>            self._bar = bar
>            self._foo = foo
>        def eval(self, x):
>            return self._bar.baz*x[0], 2*self._foo
>
> would be impossible to evaluate as it need both bar and foo, when the class i
> constructed.
>
> So the bottom line is , yes wee need to provide the dim method.

Yes, I think we do. I have thought about doing something like this
before, but the problem is more basic than in your example. We simply
can't tell which values of x are valid inputs. Consider this:

  class MyExpression(Expression):
      def eval(self, x):
          return 1/x[0]

This fails for input x = (0,).

> > > How do we evaluate the value dimension for multi line C++ expression? Do
> > > we require the user to initialize the base Expression class using either
> > > the uint dim constructor or the vector<uint> value_shape constructor?
> > >
> > > If so I do not see that the code in __init__ take care of this case,
> > > yet...
> >
> > I have assumed that the cpparg input is either a single string (and
> > then it's scalar), a tuple of strings (and then it's a vector) or a
> > nested tuple (and then it's a tensor).
>
> Correct. This is how we have used these argument before.
>
> > Are there other cases I have missed?
>
> Yes, the __new__ method is called when a derived class is instantiated too. So
> when one try f = Source(V), the logic tells us that it is a scalar function
> that is instantiated. This can be prevented with some tests of
> course.

ok. Would be good if you took a look at expression.py since you are
more familiar with it. I tried by best but I might have missed some more.

> > > We also need a cleanup of different erroneous user cases. The one that
> > > Garth sketches below, should issue an error. Now it assume the the V is a
> > > "cpparg", and somehow gets through.
> >
> > Yes.
> >
> > > I have also provided the protected attribute _ufl_element. Now there
> > > seems to be an element, and a degree attribute. The latter is OK, but I
> > > think the former should use the _ufl_element attribute, as other code use
> > > the method ufl_element() to access this.
> >
> > ok.
> >
> > > > How should subclaases be initialised?
> > > >
> > > >   f = Source(V)
> > > >
> > > > works, but
> > >
> > > Should issue an error.
> > >
> > > >   f = Source
> > > >
> > > > doesn't.
> > >
> > > Here you just tell f to be the subclass Source. With the present design
> > > you should just use:
> > >
> > >   f = Source()
> > >
> > > I have pushed a fix for a bug that prevented this :)
> >
> > I thought f = Source() worked already. It did when I tested yesterday.
>
> It didn't when I tried.

It worked in the elasticity demo with r = Rotation().

> > Or did you mean you remove the f = Source(V) thing?
>
> No, not yet.
>
> I Can look at it this evening if not someone(TM) has done it
> already.

Great.

> > There were quite a few references to function spaces and V in
> > expression.py when I left it yesterday. Did you clean those out as
> > well?
>
> No, I just tried to get into the changes that has been done.

ok.

--
Anders

Attachment: signature.asc
Description: Digital signature


References