← 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 A Navaei <axnavaei@xxxxxxxxxxxxxx>:
>>>
>>> 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.
>>
>
> Function should not change the FunctionSpace (that's why FunctionSpace is
> const). FunctionSpace shouldn't depend on the data and its size should be
> defined when creating the FunctionSpace.

The same applies for FunctionSpace as its member variables are private
and the public accessors are read-only which. Consider a sub-class
ImageFunctionSpace:FunctionSpace, with a constructor like:

ImageFunctionSpace(ImageType *imagePtr)

where imagePtr is supposed to initialise FunctionSpace::_mesh using
the image size, and then _dofmaps itself is initialised using _mesh.
How would you do that considering the restrictions?


-Ali

>
>> Well, I guess that's why you have so many friend classes in dolfin -
>> that's one solution.
>>
>
> The reason for the friend classes is another one.
>
> Garth
>
>>
>> -Ali
>>
>>>
>>> -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
>>>>
>>>>
>
> --
> 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