Johan Hake wrote:
> 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.
>

It would help me understand what to do on the C++ side if I knew what 
the Python would/should look like. In C++ we can do

    // We know that u0 will share the data because of the reference
    Function& u0_ref = u[0];

    // We know that u0 will be a copy because there is no reference
    Function u0_copy = u[0];

What's the plan to distinguish the two cases in Python?

Garth

> 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

Reply via email to