dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #10253
Re: new Function design
On Tuesday 21 October 2008 22:34:04 Martin Sandve Alnæs wrote:
> 2008/10/21 Johan Hake <hake@xxxxxxxxx>:
> > On Tuesday 21 October 2008 21:37:13 Martin Sandve Alnæs wrote:
> >> 2008/10/21 Anders Logg <logg@xxxxxxxxx>:
> >> > On Tue, Oct 21, 2008 at 06:01:53PM +0100, Garth N. Wells wrote:
> >> >> Anders Logg wrote:
> >> >> > On Tue, Oct 21, 2008 at 04:45:01PM +0100, Garth N. Wells wrote:
> >> >> >> I have a few questions and thoughts regarding the new Function
> >> >> >> design
> >> >> >>
> >> >> >> * It's not clear to me what the intention is with user-defined
> >> >> >> functions. The functions Function::interpolate(...) never call
> >> >> >> eval(..), so they can't pick up user-defined values. Should
> >> >> >> Function::interpolate test for the presence of a GenericVector to
> >> >> >> decide whether or not the Function is discrete or user-defined?
> >> >> >
> >> >> > Yes, sorry. I've missed this. I'll fix it.
> >> >> >
> >> >> >> * It would be useful to declare user-defined functions without
> >> >> >> associating a FunctionSpace. If we want to interpolate the
> >> >> >> function, a FunctionSpace must then be provided. Anyone see any
> >> >> >> problems with this?
> >> >> >
> >> >> > The reasoning here is that all Functions must always be associated
> >> >> > with a FunctionSpace so that they may be correctly interpreted in
> >> >> > forms and correctly plotted. When a Function is created in
> >> >> > PyDOLFIN, it must always be associated with a certain FiniteElement
> >> >> > (and in a while FunctionSpace). It would simplify the handling of
> >> >> > Functions if they are always associated with a FunctionSpace.
> >> >>
> >> >> I agree that is makes life simple if every function has a space, but
> >> >> it is a bit clunky for declaring user-defined functions. The forms
> >> >> must be declared first to extract the finite element to create the
> >> >> function space. Could look nasty when a lot of functions are
> >> >> involved.
> >> >>
> >> >> We have a function Function::interpolate which takes a function space
> >> >> V as an argument and it interpolates the function u in V. What if we
> >> >> permit undefined function spaces (which perhaps only have a domain)?
> >> >> We would then interpolate the user defined function u in the provided
> >> >> space V.
> >> >>
> >> >> Garth
> >> >
> >> > Are user-defined functions ever used without being related to a
> >> > particular element/function space?
> >> >
> >> > It don't think it will be very clumsy. The clumsy thing will be to (in
> >> > C++) get from something compiled by a form compiler to a
> >> > FunctionSpace.
> >> >
> >> > If we can make that operation smooth, then creating (user-defined)
> >> > functions will be very simple and convenient. One just needs to supply
> >> > the variable V holding the function space.
> >> >
> >> > The current way of extracting function space data from the form is not
> >> > very nice (in C++). What would be the optimal way to initialize a
> >> > FunctionSpace in C++? We could think of extending the code generation
> >> > to generate code that makes this convenient.
> >> >
> >> > --
> >> > Anders
> >>
> >> The current way of extracting function space data from the form is not
> >> very nice in Python either, since it doesn't work with compiled
> >> functions. (Never mind that the current code is FFC-specific, this will
> >> be the same with UFL).
> >>
> >> Using Python functors can easily make the assembly slower than solving
> >> the linear system, so it's not really interesting to do in real
> >> applications...
> >>
> >> To make a function object that is both of a C++ subclass of
> >> dolfin::Function and of the Python class ufl.Function, we can't use the
> >> fixed multiple inheritance
> >> solution in the current PyDOLFIN.
> >>
> >> We would have to define a new class dynamically in python, inheriting
> >> from both ufl.Function and the freshly compiled C++ Function subclass.
> >> After all this work cleaning up the Function class hierarchy, is that
> >> really something you want?
> >>
> >> I'm not sure if that is even possible to do while maintaining
> >> efficiency, with cross-language inheritance and SWIG directors and all
> >> that.
> >>
> >> If anyone has another solution, I'm very interested in hearing it!
> >> Otherwise, I'm all for keeping the ufl.Function objects used in form
> >> definition separated from dolfin.Function objects used in assembly.
> >
> > I agree with Martin that we need to have a solution for PyDOLFIN users
> > that does not depend on using python functors, as it will take forever
> > for a complex form together with a moderate mesh to just assemble the
> > form.
> >
> > Is it possible to let compile_functions compile a cpp function, with a
> > FunctionSpace and all, instead of a mesh as it is today. Then after doing
>
> If you have a dolfin::FunctionSpace object already, there's no reason
> compile_functions can't take this instead of dolfin::Mesh.
> That's exactly the same and no problem at all.
>
> > this compile_function extract the element, and instantiate a
> > UFL/FFC/PyFunction-function, and "attach" the compiled version to it.
> > This
>
> What I state above is that this "attachment" must be done with
> dynamic creation of a new class with multiple inheritance.
> And I am unsure whether this will work out properly with SWIG directors
> etc. I believe it _may_ work, but I don't dare to keep my hopes up :-)
Ok, I get it. For a moment I thought we could get away by defineing our own
PyDOLFIN::Function class that could inherit from UFL/FFC, and then have a
cpp_Function, but I realise this will not work.
> See the attached python file for a prototype of dynamic class creation
> with multiple inheritance using pure python classes.
> (I think this is called "aspect oriented programming" by some people)
>
> > can be used to define forms, but more important it can be handed to the
> > python assembly that check if the function has a compiled version
> > attached to it and send this to the cpp_assembler?
>
> If the "attachment" is anything other than inheritance, it will have
> to be checked with manually written python code _everywhere_
> a dolfin::Function is expected... We can't have one kind of functions
> for assembly and one for other stuff.
Ok, I guess we have three different cases:
1) PyFunctions inherting from both UFL/FFC and cpp_Function as today,
taking a functionsspace in its constructor. This will work with both
user defined and discrete functions, more or less as we have it today.
2) The special functions, MeshSize, etc, can also be defined in the same
way as now, right?
3) Using compile_functions, that creates a multi inheritance object that
can be sent to any function expecting a cpp_Function, without manually
extending the python interface.
Could the last be done by letting compile_function create a muliti inheritance
Function. Instantiate the cpp_one with the function space and by that
creating a dummy cpp_function. Then "attach" the compiled function to a
protected attribute and define eval, by overloading it in python. This will
then just call the attached and compiled cpp_functions eval.
This will hopefully work in all cases that expect a cpp_Function? In assembly
where we need speed we extract the compiled function and send that one to
cpp_assembly. Neat? No... but could work!
Johan
Follow ups
References