dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #10610
Re: PyDOLFIN interface
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).
>> >> 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
>
--
Martin
Follow ups
References