← Back to team overview

dolfin team mailing list archive

Re: Image to Function data structure conversion

 

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.


-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
>
>
>


Follow ups

References