← Back to team overview

dolfin team mailing list archive

Re: Image to Function data structure conversion

 

2009/2/16 Garth N. Wells <gnw20@xxxxxxxxx>:
>
>
> A Navaei wrote:
>>
>> 2009/2/16 Garth N. Wells <gnw20@xxxxxxxxx>:
>>>
>>> A Navaei wrote:
>>>>
>>>> 2009/2/16 Anders Logg <logg@xxxxxxxxx>:
>>>>>
>>>>> On Mon, Feb 16, 2009 at 04:36:21PM +0000, A Navaei wrote:
>>>>>>
>>>>>> 2009/2/15 Anders Logg <logg@xxxxxxxxx>:
>>>>>>>
>>>>>>> On Sat, Feb 14, 2009 at 06:44:05PM +0000, Garth N. Wells wrote:
>>>>>>>>
>>>>>>>> A Navaei wrote:
>>>>>>>>>
>>>>>>>>> [snip]
>>>>>>>>>>>>
>>>>>>>>>>>> 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.
>>>>>>>>>
>>>>>>>>> That can be done _outside_ of a sub-class. A sub-class of
>>>>>>>>> FunctionSpace doesn't have a control over _mesh of its own parent
>>>>>>>>> FunctionSpace. The following example may make this more clear:
>>>>>>>>>
>>>>>>>>> template <typename TImage>
>>>>>>>>> class DolfinImageFunctionSpace : public dolfin::FunctionSpace
>>>>>>>>> {
>>>>>>>>> public:
>>>>>>>>>       // just some itk typedefs -- ignore
>>>>>>>>>   typedef TImage ImageType;
>>>>>>>>>   typedef typename ImageType::PixelType PixelType;
>>>>>>>>>   typedef typename ImageType::SizeType SizeType;
>>>>>>>>>
>>>>>>>>>       // .. and some dolfin typedefs -- ignore
>>>>>>>>>   typedef typename std::tr1::shared_ptr<const dolfin::Mesh>
>>>>>>>>> MeshConstPointerType;
>>>>>>>>>   typedef typename std::tr1::shared_ptr<const
>>>>>>>>> dolfin::FiniteElement>
>>>>>>>>> ElementConstPointerType;
>>>>>>>>>   typedef typename std::tr1::shared_ptr<const dolfin::DofMap>
>>>>>>>>> DofMapConstPointerType;
>>>>>>>>>
>>>>>>>>>       // the ctor
>>>>>>>>>   DolfinImageFunctionSpace(ImageType* imageData,
>>>>>>>>>                                           MeshConstPointerType
>>>>>>>>> mesh,
>>>>>>>>>                                           ElementConstPointerType
>>>>>>>>> element,
>>>>>>>>>                                           DofMapConstPointerType
>>>>>>>>> dofmap) :
>>>>>>>>>   dolfin::FunctionSpace(mesh, element, dofmap)
>>>>>>>>>   {
>>>>>>>>>           SizeType imageSize =
>>>>>>>>> imageData->GetBufferedRegion().GetSize();
>>>>>>>>>
>>>>>>>>>               // here, we whish to call some thing like:
>>>>>>>>>               // _mesh = UnitSquare(imageSize[0], imageSize[1]);
>>>>>>>>>               // but it's private and the accessor is read-only.
>>>>>>>>>   };
>>>>>>>>> }
>>>>>>>>>
>>>>>>>> This breaks the concept of a function space. A function space is
>>>>>>>> defined
>>>>>>>> in terms of a mesh (and other things). A function space does not
>>>>>>>> define
>>>>>>>> its mesh.
>>>>>>>>
>>>>>>>> It looks to me like the class that you're creating should be called
>>>>>>>> something like
>>>>>>>>
>>>>>>>>  DolfinImageProblem,
>>>>>>>>
>>>>>>>> which can create its own Mesh, FunctionSpace and other objects.
>>>>>>>>
>>>>>>>> Garth
>>>>>>>>
>>>>>>>>> -Ali
>>>>>>>
>>>>>>> I think what you need to do is something like this:
>>>>>>>
>>>>>>> 1. Create a subclass of Function
>>>>>>>
>>>>>>> 2. In the constructor of your Function, call the empty Function()
>>>>>>> constructor
>>>>>>>
>>>>>>> 3. Then, still in the constructor of your Function (not
>>>>>>> FunctionSpace), create everything necessary like figuring out the
>>>>>>> mesh, dofmap etc and from that create a FunctionSpace
>>>>>>>
>>>>>>> 4. Then use that FunctionSpace (still in the constructor of your
>>>>>>> Function subclass) to create a new Function v which uses your special
>>>>>>> FunctionSpace in its constructor
>>>>>>>
>>>>>>> 5. Finally, assign this function to the created Function:
>>>>>>>
>>>>>>>  *this = v;
>>>>>>
>>>>>>  error: no match for 'operator=' in
>>>>>> '*(itk::DolfinImageFunction<itk::Image<double, 2u> >*)this = v'
>>>>>>
>>>>>> Assigning Function to ImageFunction is a trouble, see the full code
>>>>>> here:
>>>>>>
>>>>>>
>>>>>>
>>>>>> http://code.google.com/p/wrapitk/source/browse/trunk/ExternalProjects/ItkDolfin/src/itkDolfinImageFunction.h#87
>>>>>
>>>>> Do you have the latest hg version?
>>>>>
>>>>> Function assignment should work (see recent discussion on the mailing
>>>>> list on copy constructors and assignment operators for Function).
>>>>>
>>>>>> I don't understand the philosophy behind this tight security: why no
>>>>>> protected member variables? Why is everything either public or
>>>>>> private? Needless to say, the protected members were designed to allow
>>>>>> class extensions, by banning it, you're making sub classing a
>>>>>> unnecessarily complicated task. The above problem has it's own work
>>>>>> arounds, but I don't understand why the obvious way is blocked.
>>>>>
>>>>> The reason is simply that the constructor arguments in Function and
>>>>> FunctionSpace are const. This means no one is allowed to change the
>>>>> variables, not even the Function class (or FunctionSpace class)
>>>>> itself. For example, it's reasonable when you create a Function on a
>>>>> FunctionSpace that the Function will not change the FunctionSpace.
>>>>
>>>> Whether the member variables are read-only or not, and their
>>>> visibility are two separate concepts - you can have any combination of
>>>> these. Function and FunctionSpace do change their const variables
>>>> anyway, eg, in operator= you have:
>>>>
>>>> // Assign vector
>>>> init();
>>>> dolfin_assert(_vector);
>>>> *_vector = *v._vector;
>>>>
>>>> Which is in contradiction with what you wrote about not even the class
>>>> itself cannot change the variables.
>>>>
>>> Anders was referring to FunctionSpace. Obviously, the vector associated
>>> with
>>> a discrete Function cannot be const (and it isn't).
>>
>> Yes, that wasn't a good example. However, this is also applied to
>> FunctionSpace, here are the const inputs:
>>
>>  FunctionSpace(const Mesh& mesh,
>>                  const FiniteElement& element,
>>                  const DofMap& dofmap);
>>
>> But later, they are changed:
>>
>> const FunctionSpace& FunctionSpace::operator= (const FunctionSpace& V)
>> {
>>  // Assign data (will be shared)
>>  _mesh    = V._mesh;
>>  _element = V._element;
>>  _dofmap  = V._dofmap;
>> ...
>> }
>>
>> or am I wrong?
>>
>
> The actual mesh, finite element and dof_map objects are not being changed.
> What's changing in assigning a FunctionSpace is the mesh, finite element and
> dof_map to which the FunctionSpace points.

By 'change' I mean changing the value or reference of the member
variables and not the actual variables defined outside of the class,
which is in agreement with what you wrote. Given this, why isn't a
subclass allowed to do the very same thing? Can you elaborate an
example where this might be an issue?

If this is about user-defined functions, like I mensioned earlier,
maybe you want to specify a difference between user-defined functions
which simply need overriding eval(), and other classes which require
extending Function more extensively. Here is one approach:

(0) Function allowes its sub-classes to change the private member
variables, by protected accessors.

(1) A sub-class called UserFunction:Function, dedicated for overriding
eval() where the protected accessors are not allowed any more.

(2) Now any XFunction::Function can extend Function happily.


-Ali

>
> Garth
>
>>>> It would be rare that all classes have to have read-only inputs, where
>>>> the sub-classes are setences to inherit the same properties. Now, I
>>>> simply cannot have the right operator= assinging Function to
>>>> ImageFunction implemented, since I cannot assign anything to the
>>>> private member variables.
>>>>
>>>> If the visibility of the members variables is not going to change to
>>>> protected, or at least a protected read/write accessor is not
>>>> provided, then there will be no option but implementing everything in
>>>> a third-party class faking the current ImageFunction, as it's not
>>>> going to be derived from Function.
>>>>
>>> All you need to do is create a suitable FunctionSpace before creating
>>> your
>>> Function.
>>
>> That's right, but where? Like I mentioned, this will only work
>> somwhere outside of these two classes. The idea was that ImageFunction
>> should be of Function type and it would be nice to sub class it.
>>
>>
>> -Ali
>>
>>> Garth
>>>
>>>> -Ali
>>>>
>>>>> --
>>>>> Anders
>>>>>
>>>>> -----BEGIN PGP SIGNATURE-----
>>>>> Version: GnuPG v1.4.9 (GNU/Linux)
>>>>>
>>>>> iEYEARECAAYFAkmZmlsACgkQTuwUCDsYZdH2CQCfV+zCXddCSL0oGrSKcyDBj2Mp
>>>>> RSUAn3uZT4JixKq62p7BTTsHuA+qMG29
>>>>> =P6Ji
>>>>> -----END PGP SIGNATURE-----
>>>>>
>>>>> _______________________________________________
>>>>> DOLFIN-dev mailing list
>>>>> DOLFIN-dev@xxxxxxxxxx
>>>>> http://www.fenics.org/mailman/listinfo/dolfin-dev
>>>>>
>>>>>
>>>> _______________________________________________
>>>> DOLFIN-dev mailing list
>>>> DOLFIN-dev@xxxxxxxxxx
>>>> http://www.fenics.org/mailman/listinfo/dolfin-dev
>


References