A Navaei wrote:
> 2009/2/14 Garth N. Wells <[email protected]>:
>>
>> A Navaei wrote:
>>> 2009/2/14 A Navaei <[email protected]>:
>>>> 2009/2/14 Garth N. Wells <[email protected]>:
>>>>> A Navaei wrote:
>>>>>> 2009/2/14 Johan Hake <[email protected]>:
>>>>>>> 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?
>
The FunctionSpace has pointers to the mesh, etc. You just need to create
your mesh and pass it to the FunctionSpace constructor. What else you
then do with the mesh, etc is up to you.
Garth
>
> -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
>>>>>>>>> [email protected]
>>>>>>>>> http://www.fenics.org/mailman/listinfo/dolfin-dev
_______________________________________________
DOLFIN-dev mailing list
[email protected]
http://www.fenics.org/mailman/listinfo/dolfin-dev