Johan Hake wrote:
> 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?
>
Adding it shouldn't cause any problems. Need to think about the correct
syntax.
Garth
> I can see why the assigment operator should not work.
>
> 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