| Thread Previous • Date Previous • Date Next • Thread Next |
. 2008/10/22 Johan Hake <hake@xxxxxxxxx>: > On Wednesday 22 October 2008 11:55:10 Martin Sandve Alnæs wrote: >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>: >> > On Wednesday 22 October 2008 11:12:02 Martin Sandve Alnæs wrote: >> >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>: >> >> > On Wednesday 22 October 2008 10:17:43 Martin Sandve Alnæs wrote: >> >> >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>: >> >> >> > On Wednesday 22 October 2008 09:32:31 Martin Sandve Alnæs wrote: >> >> >> >> 2008/10/22 Johan Hake <hake@xxxxxxxxx>: >> >> >> >> > On Tuesday 21 October 2008 23:23:27 Martin Sandve Alnæs wrote: >> >> >> >> >> 2008/10/21 Johan Hake <hake@xxxxxxxxx>: >> >> >> >> >> > 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. >> >> >> >> >> >> >> >> >> >> I'm with you up to this point. >> >> >> >> >> >> >> >> >> >> > 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. >> >> >> >> >> >> >> >> >> >> What you describe here sounds like the envelope-letter design >> >> >> >> >> that was just _removed_ from dolfin. >> >> >> >> > >> >> >> >> > Yes, but only for compiled functions in Python. No other places. >> >> >> >> > >> >> >> >> >> What I'm suggesting is that >> >> >> >> >> compile_functions dynamically creates a Python class that >> >> >> >> >> inherits from ufl.Function and the freshly compiled C++ class, >> >> >> >> >> which is a dolfin::Function subclass. Then it can construct an >> >> >> >> >> object of this new class, passing a FunctionSpace object given >> >> >> >> >> by the user to the dolfin::Function constructor, and an >> >> >> >> >> ufl.FiniteElement to the ufl.Function constructor. >> >> >> >> > >> >> >> >> > This sounds doable. I realize now that this was what you were >> >> >> >> > talking about in your previous emails, but I did not get it >> >> >> >> > until now ;) >> >> >> >> > >> >> >> >> >> This of course requires that dolfin.FunctionSpace >> >> >> >> >> is a Python subclass of dolfin::FunctionSpace with an >> >> >> >> >> additional ufl.FiniteElement member variable. Using jit, >> >> >> >> >> dolfin.FunctionSpace can compile the ufc::finite_element and >> >> >> >> >> ufc::dof_map classes it needs from an ufl.FiniteElement. And >> >> >> >> >> then there's the issue of reusing dofmaps, where DofMapSet >> >> >> >> >> enters the play... >> >> >> >> > >> >> >> >> > Do we need to jit compile ufc::finite_elements and ufc::dof_maps >> >> >> >> > from the created ufl.FiniteElement? What about the one that >> >> >> >> > follows from the FunctionSpace? >> >> >> >> >> >> >> >> I was thinking about when _constructing_ the FunctionSpace. >> >> >> >> Just like PyDOLFIN uses jit in Function.__init__ today. >> >> >> > >> >> >> > Ok, something like: >> >> >> > >> >> >> > # Note pseudo code... >> >> >> > class FunctionSpace(cpp_FunctionSpace): >> >> >> > def __init__(self,ufl_finite_element,mesh): >> >> >> > ufc_finit_element = jit(ufl_finite_element) >> >> >> > form = ufl.FiniteElement*ufl.TestFunction*ufl.dx >> >> >> > dof_map = jit(form) >> >> >> > cpp_FucntionSpace.__init__(mesh,ufc_FinitElement,dof_map) >> >> >> > self._UFL_FiniteElement = ufl_finite_element >> >> >> > >> >> >> > def UFL_FiniteElement(self): >> >> >> > return self._UFL_FiniteElement >> >> >> > >> >> >> > By this the the ufc_element, ufl_element, the dofmaps and the mesh, >> >> >> > are cached in the FunctionSpace. >> >> >> > >> >> >> > The Function would then be something like: >> >> >> > >> >> >> > class Function(cpp_Function,ufl.Function): >> >> >> > def __init__(self,function_space): >> >> >> > cpp_Function.__init__(function_space): >> >> >> > ufl.Function.__init__(function_space.UFL_FiniteElement()) >> >> >> > >> >> >> > and dynamical created code in compile_functions() >> >> >> > >> >> >> > class MyFunction(MyCompiledFunction,ufl.Function): >> >> >> > def __init__(self,function_space): >> >> >> > MyCompiledFunction.__init__(function_space): >> >> >> > ufl.Function.__init__(function_space.UFL_FiniteElement()) >> >> >> >> >> >> Something like that, yes. This is close to the current PyDOLFIN. >> >> >> >> >> >> But FunctionSpace might become a subclass of ufl.FunctionSpace >> >> >> if we introduce that in UFL, and it should be possible to get >> >> >> cached initialized and renumbered DofMaps from a DofMapSet. >> >> >> >> >> >> Since a DofMapSet will typically be initialized with a Form, >> >> >> a Form depends on a Function, and a Function depends on >> >> >> a FunctionSpace which should be initialized by the DofMapSet, >> >> >> we have a cirular dependency right there. >> >> > >> >> > But won't you have this circular dependency in UFL already? >> >> >> >> In UFL this is simple: >> >> >> >> FiniteElement depends on nothing >> >> Function depends on FiniteElement >> >> Form depends on Function >> > >> > I ment for a potential FunctionSpace class in UFL. >> >> Then it is simply: >> >> FiniteElement depends on nothing >> FunctionSpace depends on FiniteElement >> Function depends on FunctionSpace >> Form depends on Function > > Ok, and FunctionSpace then compile/create a dofmap to be included in it, or > will a possible UFLFunctionSpace not include that? > > Johan UFL has nothing to do with dofmaps (or anything related to a Mesh) at all. -- Martin
| Thread Previous • Date Previous • Date Next • Thread Next |