On Monday 24 August 2009 13:04:45 Garth N. Wells wrote: > Johan Hake wrote: > > On Monday 24 August 2009 10:30:52 Garth N. Wells wrote: > >> Johan Hake wrote: > >>> On Monday 24 August 2009 10:11:49 Garth N. Wells wrote: > >>>>>>>>>> dolfin/swig/dolfin_headers.i description: Work on new sub > >>>>>>>>>> Function logic. > >>>>>>>>> > >>>>>>>>> I am not sure we can completely wrap the new logic to PyDOLFIN. > >>>>>>>>> > >>>>>>>>> To be able to have the double inheritance of cpp.Function and > >>>>>>>>> ufl.Function in PyDOLFIN, new Functions have to be constructed in > >>>>>>>>> the Python interface (function.py). > >>>>>>>>> > >>>>>>>>> The operator[] is mapped to a hidden function _sub. The created > >>>>>>>>> Function that is returned from this is passed to the copy > >>>>>>>>> constructor in the Python version of sub (creating a new Function > >>>>>>>>> object). This is basically just how we did it before the new > >>>>>>>>> design, because previously operator[] returned a > >>>>>>>>> SubFunctionData, which was passed to a Function constructor. The > >>>>>>>>> transition to the new logic works in PyDOLFIN because the > >>>>>>>>> Function copy constructor is used instead of the removed > >>>>>>>>> SubFunctionData constructor. > >>>>>>>>> > >>>>>>>>> This means that the handy operator[], which returns a Function > >>>>>>>>> with a shared vector, cannot fully be used from PyDOLFIN. Would > >>>>>>>>> it be possible to add a shallow copy function in some way. Would > >>>>>>>>> this work with the present SubFunction design? > >>>>>>>> > >>>>>>>> Would something like > >>>>>>>> > >>>>>>>> Function::sub_function(Function& sub_function, uint i) > >>>>>>> > >>>>>>> Yes I think so. If we could make this a constructor (shallow copy > >>>>>>> constructor) I would be most happy! > >>>>>> > >>>>>> So a constructor > >>>>>> > >>>>>> Function::Function(uint i) > >>>>>> > >>>>>> would be better? > >>>>> > >>>>> Yes, but then we could not fetch the shared Vector? > >>>>> > >>>>>> I'm reluctant to add a constructor since it breaks the > >>>>>> paradigm that a Function constructor gives a deep copy. > >>>>> > >>>>> Ok. > >>>>> > >>>>>> Could you create > >>>>>> an empty Function internally on the PyDOLFIN side and then pass it > >>>>>> to > >>>>>> > >>>>>> Function::sub_function(Function& sub_function, uint i) > >>>>>> > >>>>>> to attach the shared data to create the sub-Function 'sub_function'? > >>>>> > >>>>> Yes, this should be fine. I guess such a function will then just > >>>>> destroy any present vector and exchange it with the one shared with > >>>>> the FullFunction? > >>>> > >>>> Yes. We can throw an error if there is any data already attached to > >>>> the Function. > >>> > >>> When we create a new Function in PyDOLFIN using the DiscreteFunction, > >>> we do create a vector, so this will prevent us using this class. We use > >>> the DiscreteFunction to circumvent some director (SWIG stuff to be able > >>> to inherit a cpp.Function in Python) overhead wrt to call the eval > >>> function during assemble. I guess we will not assemble the function > >>> returned from operator[] so then we can create the Function using > >>> cpp.Function instead. > >> > >> What if we add a constructor to DiscreteFunction to take care of > >> sub-functions? Would that work? > > > > Yes, this should work. Then we could add a constructor taking a Function > > and a number as you suggested above. > > This is trickier than I anticipated. The problem with > > Function::Function(const Function& v, uint i) > > is that v cannot be const since v keeps track of its sub-functions and > create and stores them on-demand. I could just create a sub-function and > not cache it, but then it would be re-created every time. The problem > with this is that creating a sub-dof map is not trivial if the dof map > has been renumbered. > > I'm also a bit uncomfortable with shallow copies because bad things can > happen when something goes out of scope.
If we make _vector protected, we should be able to handle everything in something like: DiscreteFunction::DiscreteFunction(Function& v, uint i) Here we just let the new DiscreteFunction share both _vector and _function_space. Maybe this was what you did not like? > Could this be taken care of on the Python side by introducing something > like a SubFunction? Function::operator[] returns a reference, and > PyDOLFIN could take are of things through the assignment operators of > the Python Function and SubFunction classes? This is exactly what happens now (if I understand your suggestion correctly :) ) and this is probably why the new SubFunction design just works in PyDOLFIN now. The thing is that we make a deep copy. The sharing of data we get from operator[] is lost. This might not be a big problem. Johan > I don't really understand > how things work on the Python side for Functions, so I'm clutching at > straws. > Garth > > >>>> It would be neat if we could somehow make member functions 'private' > >>>> to PyDOLFIN. > >>> > >>> We can, just rename them in dolfin_function_pre.i > >>> > >>> %rename (_foo) dolfin::Function::foo; > >>> > >>> We do this for some of the functions (_sub: operator[] and _in for in) > >>> already. > >> > >> I meant C++ member functions which are intended for use through PyDOLFIN > >> only. > > > > I see :) > > > > We could hide some python specific classes, like the DiscreteFunction > > class, by not including it in dolfin_function.h, and then manually add it > > to dolfin_headers.i. > > > > With this we hide it from > > > > #include <dolfin.h> > > > > We then have to manually add them as #includes in dolfin.i and to > > dolfin_headers.i. We can automate this by adding a > > dolfin_pydolfin_headers.i, which lists the #includes. This file is then > > parsed by generate.py. > > > > If this sounds reasonable I can look into it. > > > > Johan > > > >> Garth _______________________________________________ DOLFIN-dev mailing list [email protected] http://www.fenics.org/mailman/listinfo/dolfin-dev
