← Back to team overview

dolfin team mailing list archive

Re: [HG DOLFIN] Work on new sub Function logic.

 

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


Follow ups

References