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.
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
>>
>>
--
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 [email protected]
_______________________________________________
DOLFIN-dev mailing list
[email protected]
http://www.fenics.org/mailman/listinfo/dolfin-dev