← Back to team overview

dolfin team mailing list archive

Re: PyDOLFIN interface

 

On Tuesday 04 November 2008 15:00:42 Martin Sandve Alnæs wrote:
> 2008/11/4 Johan Hake <hake@xxxxxxxxx>:
> > On Tuesday 04 November 2008 13:59:22 Martin Sandve Alnæs wrote:
> >> 2008/11/4 Johan Hake <hake@xxxxxxxxx>:
> >> > On Tuesday 04 November 2008 13:07:07 Martin Sandve Alnæs wrote:
> >> >> 2008/11/4 Johan Hake <hake@xxxxxxxxx>:
> >> >> > Hello!
> >> >> >
> >> >> > I have started the work on the PyDOLFIN. We can now define the
> >> >> > forms in the poisson demo, using the syntax previously discussed,
> >> >> > see python poisson demo.
> >> >> >
> >> >> > A FunctionSpace now inherits both dolfin::FunctionSpace and
> >> >> > ffc.FiniteElement, and it can be used to instantiate user defined
> >> >> > Functions which can be used to define forms.
> >> >> >
> >> >> > We need to discuss how to implement a discrete function. This is a
> >> >> > bit complicated using the metaclass magic that is implemented now.
> >> >> > Now we cannot do:
> >> >> >
> >> >> >  u = Function(V)
> >> >> >  x = u.vector()
> >> >> >
> >> >> > as Function is just a dummy class for creation of userdefined
> >> >> > functions.
> >>
> >> I don't quite understand the problem here.
> >> Are you saying that type(u) is not a subclass of cpp_Function or what?
> >
> > With the metaclass implementation, Function cannot inherit cpp_Function
> > or ffc.Function. A derived class of Function will inherit Function,
> > cpp_Function and ffc.Function though. Function is as it is now, only an
> > more or less empty class that can be inherited.
> >
> > The syntax above can be valid with some __new__ magic in Function,
> > probably much in line with what you had in mind.
>
> But in the metaclass __new__ function you have explicit control of the
> bases of the new class you're building, so where's the problem?
> Just set bases = (cpp_Function, ufl.Function).

Of course. When I wrote the code I never intended Function to be instantiated. 

Would it make sense to always create a Function that is discrete when we just 
write, u = Function(V)?

Johan

> >> >> We don't have to use metaclasses, it would be enough to implement
> >> >> Function.__new__(cls, *args). This function can return objects of
> >> >> a different type, e.g. a compiled function that doesn't inherit from
> >> >> dolfin.Function but directly from dolfin::Function.
> >> >
> >> > and from ufl.Function too?
> >>
> >> Yes.
> >>
> >> >> (I didn't understand this stuff fully until last week...)
> >> >
> >> > Yes I have thought about that solution, but then the created class
> >> > wont be a Function. It can be handy to have a class that all python
> >> > Function can be checked if isinstance of. With the __new__ function we
> >> > create different classes.
> >>
> >> This is not a problem. On the contrary, you either wish to
> >> check if a function is a cpp_Function or a ufl.Function.
> >> I would consider "isinstance(f, dolfin.Function)" a bug in
> >> most circumstances. That's one of the things I don't
> >> like about this design...
> >
> > Yes, but if you check if u is a Function you allready know it is a
> > cpp_Function _and_ an ufl.Function. Just one to keep in mind ;)
> >
> >> > The advantage, as I see it with your suggestion would be that we can
> >> > use the present feature of compiling many functions at a time, but we
> >> > loose the consistent syntax:
> >> >
> >> >  class MyFunction(Function):
> >> >      def eval(v,x):
> >> >           do something
> >> >
> >> >  class MyCompiledFunction(Function):
> >> >      cpp_code = do something
> >> >
> >> >  f = MyFunction(V)
> >> >  g = MyCompiledFunction(V)
> >> >
> >> > and it could be complicated to pass the right FunctionSpaces to the
> >> > compile_function function.
> >>
> >> I forgot about this syntax. It's nice, but personally I'll be fine
> >> without it :-)
> >>
> >> >> > Is it possible to define a DiscreteFunction class in c++ (or just
> >> >> > in swig?) that inherits dolfin::Function, and in its constructor
> >> >> > calls vector()?
> >> >> >
> >> >> > Then we can use this class in python to create discrete functions.
> >> >> > We then avoid the director class that is created by swig for all
> >> >> > functions that inherits the cpp_Function. The obvious syntax would
> >> >> > then be
> >> >> >
> >> >> >  u = DiscreteFunction(V)
> >> >> >
> >> >> > in python. I think with some python magic we still can have the
> >> >> > syntax
> >> >> >
> >> >> >  u = Function(V)
> >> >> >
> >> >> > which would imply that a discrete function is created, but I
> >> >> > haven't implemented it.
> >> >>
> >> >> That would basically be duplicating the design that has been
> >> >> replaced... I think dropping the metaclass is a much easier solution.
> >> >
> >> > No, this is just for the python interface. This could come handy with
> >> > the __new__ implementation you want too. By this we circumvent the
> >> > director class that swig creates for dolfin::functions. We dont want
> >> > to call eval on such a class to often do we? :)
> >> >
> >> >> > We also have a problem with MixedElements. Now the FunctionSpace
> >> >> > inherits ffc.FiniteElement and a MixedElement is not a
> >> >> > FiniteElement. I suppose we could overload the __add__ operator for
> >> >> > the FunctionSpace together with a new class MixedFunctionSpace, to
> >> >> > fix this?
> >> >> >
> >> >> > Johan
> >> >>
> >> >> We also have (in UFL at least) the classes VectorElement and
> >> >> TensorElement, so this gets complicated. I think we should just make
> >> >> FunctionSpace own an element instead.
> >> >>
> >> >> element = FiniteElement(...)
> >> >> V = FunctionSpace(mesh, element)
> >> >> f = Function(V) # calls FiniteElement.__init__(self, element)
> >> >
> >> > Thats looks nice. We could also use the syntax Anders suggested,
> >> >
> >> >  V = FunctionSpace(mesh, "Lagrange", 1)
> >> >
> >> > and then instantiate the FiniteElement in the __init__ function.
> >>
> >> No, we can't, that's exactly the issue you brought up with MixedElement.
> >> ("Lagrange", 1) doesn't carry all information about an element.
> >> In UFL we have classes FiniteElement, MixedElement, VectorElement,
> >> and TensorElement. In addition to (family,domain,degree), a
> >> VectorElement can have a dim, and a TensorElement
> >> can have a shape and symmetries...
> >
> > Of course :P
> >
> > But would it be possible to create a MixedFunctionSpace by adding two
> > other function spaces, with some overloading of __add__? And would it be
> > possible to extend the initialization of FunctionSpace, with kwargs and
> > some __new__ magic, to instantiate FunctionSpace of different elements?
> >
> > Maybee more relevant do we want it?
> >
> >> > This wont work for the basis functions though, but we could just add a
> >> > class that inherits the ffc.BasisFunction and which can be
> >> > instantiated with both a FunctionSpace and a FiniteElement.
> >>
> >> We'd need to consider both BasisFunction, and BasisFunctions, which is a
> >> function and a bit more complicated. Also TestFunction(s) and
> >> TrialFunction(s), but those are just syntactic sugar.
> >
> > Ok.
> >
> >> I'd very much prefer letting BasisFunction be and just passing it an
> >> element.
> >
> > I see you point.
> >
> > Johan




Follow ups

References