← Back to team overview

dolfin team mailing list archive

Re: Image to Function data structure conversion

 

2009/2/14 Garth N. Wells <gnw20@xxxxxxxxx>:
>
>
> A Navaei wrote:
>>
>> 2009/2/14 Johan Hake <hake@xxxxxxxxx>:
>>>
>>> On Saturday 14 February 2009 17:28:18 Garth N. Wells wrote:
>>>>
>>>> Johan Hake wrote:
>>>>>
>>>>> On Saturday 14 February 2009 13:48:05 A Navaei wrote:
>>>>>>
>>>>>> It seems that the error can be re-produced even without sub-classing
>>>>>> and using existing dolfin classes in pure c++. Based on the itk-dolfin
>>>>>> interface code, the below minimal code should generate the error (note
>>>>>> that I use the binary distribution which uses std::tr1, replacing it
>>>>>> with boost shared pointer should not have any effect).
>>>>>
>>>>> Not in c++ but swig only support std::tr1::shared_ptr from version
>>>>> 1.3.37. But if you intend to use shared_ptr only internally there
>>>>> whould
>>>>> not be any problems.
>>>>>
>>>>>> After wrapping in python:
>>>>>>
>>>>>> (1) Calling FunctionTest.CreateFunction(), which returns by value,
>>>>>> results this error:
>>>>>>
>>>>>> RuntimeError: *** Error: Unable to assign to function, missing
>>>>>> coefficients (user-defined function).
>>>>>
>>>>> You cannot assign another user-defined function to another Function. It
>>>>> must be a discrete function, which has an initialized _vector. This is
>>>>> probably a feature that other developers should answer for.
>>>>>
>>>>> However this means that you cannot copy a userdefined function, with
>>>>> the
>>>>> side effect of not beeing able to return a user-defined Function by
>>>>> value.
>>>>>
>>>>>> Since dolfin::Function does come with the required copy ctors, the
>>>>>> problem cannot be stemmed from this.
>>>>>
>>>>> This use the assignment operator which requires the Function to be a
>>>>> discrete and not a user-defined Function.
>>>>>
>>>>> I consider this to be a bug in the library. Any other comments from the
>>>>> C++ DOLFIN developers (I am mostly dealing with the python interface)?
>>>>
>>>> In a nutshell, are you suggesting that the Function copy constructor
>>>> should work for user-defined Functions?
>>>
>>> Yes. Why shouldn't it?
>>>
>>> I can see why the assigment operator should not work.
>>
>> By 'user-defined' Function, do you mean those sub-classes which simply
>> override eval() in order to implement user-defined values? In this
>> case, perhaps there should be a difference between a 'user-defined'
>> Function class and a class which requires extending Function more
>> extensively. The latter should have access to the private member
>> variables.
>>
>
> I can't see why this is needed. Function only has two pieces of private
> member data, both of which can be accessed through member functions.

The accessors are read-only:

const FunctionSpace& function_space() const;
boost::shared_ptr<const FunctionSpace> function_space_ptr() const;

For instance, in the ImageFunction case, FunctionSpace instance needs
to be initialised using the image size and image data.


-Ali

>
> Garth
>
>>
>> -Ali
>>
>>> Johan
>>>
>>>
>>>> Garth
>>>>
>>>>>> (2) Calling FunctionTest.CreateFunctionPtr(), which returns the shared
>>>>>> pointer, does not generate any errors.
>>>>>
>>>>> This should be expected, as the copy constructors is not called. When
>>>>> you
>>>>> get all this to work, eventually ;), I would suggest using shared_ptr
>>>>> types for the return argument, as shared_ptrs are much nicer to deal
>>>>> with
>>>>> in both c++ and python. But then you probably need the development
>>>>> version of DOLFIN. We do consider a release soon, which you can switch
>>>>> to
>>>>> when this is out.
>>>>>
>>>>> The support for shared_ptr in PyDOLFIN is lately added, but has more or
>>>>> less stabilized now, I think.
>>>>>
>>>>>> However, there are problems
>>>>>> with handling the shared pointer in python. I used this in my swig
>>>>>> interface file (or in an implicit way you can include dolfin.i
>>>>>> defining the right flags):
>>>>>>
>>>>>> #define SWIG_SHARED_PTR_NAMESPACE std // comment out if it's boost
>>>>>> #define SWIG_SHARED_PTR_SUBNAMESPACE tr1 // comment out if it's boost
>>>>>> %include "boost_shared_ptr.i"
>>>>>> # if defined(SWIG_SHARED_PTR_QNAMESPACE)
>>>>>> SWIG_SHARED_PTR(Function, dolfin::Function)
>>>>>> #endif
>>>>>
>>>>> Which version of swig do you have, refering to the comment above. You
>>>>> need swig version >= 1.3.35 to be able to use shared_ptr in the first
>>>>> place and >= 1.3.37 to be able to use std::str1::shared_ptr.
>>>>>
>>>>>> Having this, in python, FunctionTest.CreateFunctionPtr() returns a
>>>>>> proxy to the shared pointer object which is not useful. Are there any
>>>>>> steps missed in the wrapping process?
>>>>>
>>>>> Strictly speaking it does _not_ return a proxy but rather a raw pointer
>>>>> to the object. The proxy is the python wrapper class that swig creates
>>>>> for us when it have the correct type knowledge, which in this case,
>>>>> swig
>>>>> does not have.
>>>>>
>>>>>> c++ test code:
>>>>>> -----------------------------
>>>>>> class FunctionTest
>>>>>> {
>>>>>> public:
>>>>>>   typedef std::tr1::shared_ptr<const dolfin::Mesh>
>>>>>> MeshConstPointerType;
>>>>>>   typedef std::tr1::shared_ptr<const dolfin::FiniteElement>
>>>>>> ElementConstPointerType;
>>>>>>   typedef std::tr1::shared_ptr<const dolfin::DofMap>
>>>>>> DofMapConstPointerType; typedef std::tr1::shared_ptr<const
>>>>>> dolfin::FunctionSpace>
>>>>>> FSConstPointerType; typedef std::tr1::shared_ptr<dolfin::Function>
>>>>>> FPointerType;
>>>>>>
>>>>>>   static dolfin::Function CreateFunction()
>>>>>>   {
>>>>>>           dolfin::Mesh mesh = dolfin::UnitSquare(100, 100);
>>>>>>           std::string elemSig("FiniteElement('Lagrange', 'triangle',
>>>>>> 1)");
>>>>>>           std::string dofSig("FFC dof map for
>>>>>> FiniteElement('Lagrange',
>>>>>> 'triangle', 1)");
>>>>>>
>>>>>>           FSConstPointerType fs(new dolfin::FunctionSpace(
>>>>>>           typename IFSType::MeshConstPointerType(&mesh,
>>>>>> dolfin::NoDeleter<const dolfin::Mesh>()),
>>>>>>           typename IFSType::ElementConstPointerType(new
>>>>>> dolfin::FiniteElement(elemSig)), typename
>>>>>> IFSType::DofMapConstPointerType(new dolfin::DofMap(dofSig, mesh))) );
>>>>>>
>>>>>>           dolfin::Function func(fs);
>>>>>>           return func;
>>>>>>   };
>>>>>>
>>>>>>   static FPointerType CreateFunctionPtr()
>>>>>>   {
>>>>>>           dolfin::Mesh mesh = dolfin::UnitSquare(100, 100);
>>>>>>           std::string elemSig("FiniteElement('Lagrange', 'triangle',
>>>>>> 1)");
>>>>>>           std::string dofSig("FFC dof map for
>>>>>> FiniteElement('Lagrange',
>>>>>> 'triangle', 1)");
>>>>>>
>>>>>>           FSConstPointerType fs(new dolfin::FunctionSpace(
>>>>>>           typename IFSType::MeshConstPointerType(&mesh,
>>>>>> dolfin::NoDeleter<const dolfin::Mesh>()),
>>>>>>           typename IFSType::ElementConstPointerType(new
>>>>>> dolfin::FiniteElement(elemSig)), typename
>>>>>> IFSType::DofMapConstPointerType(new dolfin::DofMap(dofSig, mesh))) );
>>>>>>
>>>>>>           FPointerType funcp = FPointerType(new dolfin::Function(fs));
>>>>>>           return funcp;
>>>>>>   };
>>>>>> };
>>>>>> ----------------------------
>>>>>>
>>>>>>> Yes, I can call wrapped DolfinImageFunction in python with no
>>>>>>> problem,
>>>>>>> but when using it in pure c++ (itk::ImageToDolfinFunction) an then
>>>>>>> calling ImageToDolfinFunction after wrapped in python generated the
>>>>>>> error:
>>>>>>>
>>>>>>> RuntimeError: *** Error: Unable to assign to function, missing
>>>>>>> coefficients (user-defined function).
>>>>>
>>>>> I think we sorted out this problem above: do not return by value.
>>>>>
>>>>>>> why v._vector is not null in the first case? I also tried the shared
>>>>>>> pointer ctors and ended up with the same result. Moreover, I tried
>>>>>>> sub-classing FunctionSpace (see
>>>>>>>
>>>>>>> http://code.google.com/p/wrapitk/source/browse/trunk/ExternalProjects/I
>>>>>>> tk Dolfin/src/itkDolfinImageFunctionSpace.h), with and without shared
>>>>>>> pointer ctors, again the same error.
>>>>>>>
>>>>>>>> First I assume that you properly instantiate the templates somewhere
>>>>>>>> else in your build script, as itkDolfin.swg does not define any such
>>>>>>>> templates.
>>>>>>>
>>>>>>> That's correct, wrapitk instantiates the templates automatically.
>>>>>
>>>>> Ok. Is this done in some of the SMake macros? I am really not familiar
>>>>> to
>>>>> CMake
>>>>>
>>>>>>>> Second you should probably return a pointer to the created function
>>>>>>>> in
>>>>>>>> DolfinImageFunction(), and set
>>>>>>>>
>>>>>>>>  %newobject
>>>>>>>> itk::ImageToDolfinFunction<YourImageTypes>.DolfinImageFunction;
>>>>>>>>
>>>>>>>> or define a copy constructor to your DolfinImageFunction, as you are
>>>>>>>> returning by value now.
>>>>>>>
>>>>>>> I've tried a simple copy ctor like this:
>>>>>>>
>>>>>>>       DolfinImageFunction(const DolfinImageFunction &v)
>>>>>>>       {
>>>>>>>                *this = v;
>>>>>>>       }
>>>>>>>
>>>>>>> which does get called, but didn't help.
>>>>>
>>>>> Again, bug in copy constructor. You should be able to return a raw
>>>>> pointer to the function, but make sure you use the %newobject directive
>>>>> mentioned above, to till swig that it should take ownership to the
>>>>> returned object.
>>>>>
>>>>>>> Just to mention that one problem with c++ dolfin classes is that
>>>>>>> their
>>>>>>> member variables are mostly private, causing restrictions on the
>>>>>>> sub-classes.
>>>>>
>>>>> This should others answer.
>>>>>
>>>>>>> Is there a specific reason for having private variables
>>>>>>> instead of protected? For instance, DolfinImageFunction ctors are not
>>>>>>> able to initialise _function_space or _vector.
>>>>>
>>>>> This should not be any problems in the ordinary constructor as you can
>>>>> just pass the function_space to the super constructor, and a properly
>>>>> working copy constructor should also fix this for any derived copy
>>>>> constructors.
>>>>>
>>>>> The _vector is created by calling init(). But you do not want to do
>>>>> this
>>>>> as the Function will then change status from a user-defined to a
>>>>> discrete
>>>>> function, making it impossible to reach the eval function.
>>>>>
>>>>> Again hope this helps.
>>>>>
>>>>> Johan
>>>>> _______________________________________________
>>>>> DOLFIN-dev mailing list
>>>>> DOLFIN-dev@xxxxxxxxxx
>>>>> http://www.fenics.org/mailman/listinfo/dolfin-dev
>>>
>>>
>
> --
> Dr Garth N Wells
> Department of Engineering
> University of Cambridge
> Trumpington Street
> Cambridge CB2 1PZ
> United Kingdom
>
> tel.   +44 1223 3 32743
> fax.   +44 1223 3 32662
> e-mail gnw20@xxxxxxxxx
>
>


Follow ups

References