← Back to team overview

dolfin team mailing list archive

Re: PyDOLFIN interface

 

On Tue, Nov 04, 2008 at 01:59:22PM +0100, 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?
> 
> 
> >> 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...
> 
> 
> > 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...

Yes, but all these arguments can easily be added to the FunctionSpace
constructor.

> > 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.
> 
> I'd very much prefer letting BasisFunction be and just passing it an element.

v = TestFunction(V)

looks much nicer than

v = TestFunction(element)

It would be good if we could avoid exposing the FiniteElement class in
application code since they are mostly concerned with function spaces,
not placeholders for reference elements.

-- 
Anders

Attachment: signature.asc
Description: Digital signature


Follow ups

References