← Back to team overview

dolfin team mailing list archive

Re: Function and DofMap

 

2008/9/7 Garth N. Wells <gnw20@xxxxxxxxx>:
>
>
> Martin Sandve Alnæs wrote:
>>
>> 2008/9/7 Anders Logg <logg@xxxxxxxxx>:
>>>
>>> On Sun, Sep 07, 2008 at 08:27:41AM +0100, Garth N. Wells wrote:
>>>>
>>>> Martin Sandve Alnæs wrote:
>>>>>
>>>>> 2008/9/6 Anders Logg <logg@xxxxxxxxx>:
>>>>>>
>>>>>> On Sat, Sep 06, 2008 at 04:22:09PM +0200, Martin Sandve Alnæs wrote:
>>>>>>>
>>>>>>> 2008/9/6 Garth N. Wells <gnw20@xxxxxxxxx>:
>>>>>>>>
>>>>>>>> Dag Lindbo wrote:
>>>>>>>>>
>>>>>>>>> Anders Logg wrote:
>>>>>>>>>>
>>>>>>>>>> There seems to be a problem (among many) with the current design
>>>>>>>>>> of
>>>>>>>>>> the Function classes (see thread "evaluating higher order mesh
>>>>>>>>>> function").
>>>>>>>>>>
>>>>>>>>>> In particular, the finite element is missing in DiscreteFunction.
>>>>>>>>>> My
>>>>>>>>>> suggestion would be to just add it and let a DiscreteFunction
>>>>>>>>>> consist
>>>>>>>>>> of the following four items which are always available:
>>>>>>>>>>
>>>>>>>>>>  mesh, x, dof_map, finite_element
>>>>>>>>>>
>>>>>>>>>> Is this enough, and what other issues to we need to fix?
>>>>>>>>>>
>>>>>>>>> One major issue which I just want to reiterate is ownership of
>>>>>>>>> data. As
>>>>>>>>> it stands, the DiscreteFunction may or may not be responsible for
>>>>>>>>> e.g.
>>>>>>>>> the dof vector x, depending on whether local_vector is a NULL
>>>>>>>>> pointer or
>>>>>>>>> not. Take a look at the thread "Ownership" from Garth on
>>>>>>>>> 06/26/2008.
>>>>>>>>>
>>>>>>>> Yes, this is a big problem and has caused me a few headaches with
>>>>>>>> bugs.
>>>>>>>> For example, passing a user-defined Function to a function to
>>>>>>>> convert it
>>>>>>>> to a DiscreteFunction via a projection onto a finite element basis
>>>>>>>> causes a problem because the FiniteElement which the projected
>>>>>>>> Function
>>>>>>>> points to goes out of scope once the function is exited.
>>>>>>>>
>>>>>>>>> A problem related to this is initialization of the
>>>>>>>>> DiscreteFunction. We
>>>>>>>>> had a bug previously where the LinearPDE class maintained ownership
>>>>>>>>> of
>>>>>>>>> the solution vector. The only way to prevent this was to break the
>>>>>>>>> encapsulation of DiscreteFunction by making it a friend of
>>>>>>>>> LinearPDE (as
>>>>>>>>> with XMLFile for the same reasons). Here is some of the code that
>>>>>>>>> handles this initializaton today (L101 in LinearPDE.cpp):
>>>>>>>>>
>>>>>>>>>  u.init(mesh, *x, a, 1);
>>>>>>>>>  DiscreteFunction& uu = dynamic_cast<DiscreteFunction&>(*u.f);
>>>>>>>>>  uu.local_vector = x;
>>>>>>>>>
>>>>>>>>> This ain't poetry in my opinion :)
>>>>>>>>>
>>>>>>>> Indeed, this isn't nice, and there is something similar in
>>>>>>>> XMLFile.cpp.
>>>>>>>>
>>>>>>>> Garth
>>>>>>>
>>>>>>> We should start to use std::tr1::shared_ptr. There is some support
>>>>>>> for it
>>>>>>> with python in swig 1.3.35, which is part of the upcoming Ubuntu
>>>>>>> Intrepid
>>>>>>
>>>>>> The main issue is how we want to initialize Functions, and if one
>>>>>> should allow to set members.
>>>>>>
>>>>>> For simplicity, say that a Function is defined only by a Vector.
>>>>>> Then we have a few different situations to consider:
>>>>>>
>>>>>> 1. Function creates the Vector
>>>>>>
>>>>>>  Function u;
>>>>>>  Vector& x = u.vector();
>>>>>>
>>>>>> 2. Function gets the Vector
>>>>>>
>>>>>>  Vector x;
>>>>>>  Function u(x);
>>>>>>
>>>>>> 3. Function gets initialized with a Vector
>>>>>>
>>>>>>  Function u;
>>>>>>  Vector x;
>>>>>>  u.init(x);
>>>>>>
>>>>>> Do we want to support all of 1-3? Things become considerable easier if
>>>>>> we can make some simplifying assumptions.
>>>>>>
>>>>>> How visible would a shared_ptr be in the interface?
>>>>>
>>>>> A shared_ptr must be visible to the user every single place
>>>>> a pointer is passed around, otherwise the reference count
>>>>> won't be correct and we'll just have more problems.
>>>>>
>>>> So, in pseudo code, would it look something link this?
>>>>
>>>>   class DiscreteFunction
>>>>   {
>>>>     private:
>>>>
>>>>       shared_ptr<GenericVector> x;
>>>>
>>>>     public:
>>>>
>>>>       DiscreteFunction() : x(new Vector) {}
>>>>
>>>>       DiscreteFunction(shared_ptr<GenericVector> x)
>>>>       { x(x); }
>>>>
>>>>       shared_ptr<GenericVector> vec()
>>>>       {return x;}
>>>>   }
>>>> ?
>>>>
>>>> Garth
>>>
>>> What would the user code look like if we use shared_ptr for examples
>>> 1-3 above?
>>>
>>> --
>>> Anders
>>
>>
>>>>> 1. Function creates the Vector
>>>>>
>>>>>  Function u;
>>>>>  Vector& x = u.vector();
>>
>> Function u;
>> Vector& x = u.vector(); // Storing this Vector& for later access is
>> unsafe.
>> or
>> Function u;
>> shared_ptr<Vector> x = u.vector(); // Allows keeping the Vector around
>> after u is destroyed.
>>
>>
>>>>> 2. Function gets the Vector
>>>>>
>>>>>  Vector x;
>>>>>  Function u(x);
>>
>> Vector x;
>> Function u(x); // Copy vector.
>>
>> shared_ptr<Vector> x = new Vector();
>> Function u(x); // Copy vector pointer, x or u may be deleted without
>> the other getting in trouble.
>>
>>>>> 3. Function gets initialized with a Vector
>>>>>
>>>>>  Function u;
>>>>>  Vector x;
>>>>>  u.init(x);
>>
>> Function u;
>> Vector x;
>> u.init(x); // Copy Vector.
>>
>> and/or
>>
>> Function u;
>> shared_ptr<Vector> x = new Vector();
>> u.init(x); // Copy pointer.
>>
>
> We could add typedefs inside common classes to ease the notation,
>
>  shared_ptr<Vector> -> Vector_ptr,
>  shared_ptr<GenericVector> -> GenericVector_ptr,
>  etc
>
> We might even want to instantiate them to ease the SWIG wrapping.
>
> Garth

The SWIG wrapping of shared_ptr is not that easy... The shared_ptr<T>
class does not have the properties of class T, so you can't just instantiate it.
We'll need to look into the shared_ptr support in the latest SWIG.

--
Martin


References