Anders Logg wrote:
> On Sun, Sep 07, 2008 at 03:38:44PM +0100, Garth N. Wells wrote:
>>
>> Anders Logg wrote:
>>> On Sun, Sep 07, 2008 at 03:29:14PM +0200, Anders Logg wrote:
>>>> On Sun, Sep 07, 2008 at 03:11:51PM +0200, Martin Sandve Alnæs wrote:
>>>>> 2008/9/7 Anders Logg <[EMAIL PROTECTED]>:
>>>>>> On Sun, Sep 07, 2008 at 08:27:41AM +0100, Garth N. Wells wrote:
>>>>>>> Martin Sandve Alnæs wrote:
>>>>>>>> 2008/9/6 Anders Logg <[EMAIL PROTECTED]>:
>>>>>>>>> On Sat, Sep 06, 2008 at 04:22:09PM +0200, Martin Sandve Alnæs wrote:
>>>>>>>>>> 2008/9/6 Garth N. Wells <[EMAIL PROTECTED]>:
>>>>>>>>>>> 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?
>>>>>>
>>>>>>>> 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.
>>>> I don't think the first option is what one might expect, and I don't
>>>> think the second example looks very nice.
>>>>
>>>> We initialize Functions with a Mesh all the time and it would then be
>>>> either very expensive to copy the mesh every time we create a Function
>>>> from it (and one usually creates many functions on the same mesh), or
>>>> we would have to write "shared_ptr" and "new" every time we used a
>>>> Mesh.
>>>>
>>>> Isn't there another option? I don't like the all the flags we have now
>>>> like is_view, local_vector, etc, but this looks worse.
>>> Is there a way to increase the count for a shared_ptr?
>>>
>>> If there is, say a member named increase_ref(), we could do
>>>
>>> class DiscreteFunction
>>> {
>>> public:
>>>
>>> DiscreteFunction() : x(new Vector) {}
>>>
>>> DiscreteFunction(GenericVector& x) : x(x);
>>> {
>>> x.increase_ref(1);
>>> }
>>>
>>> DiscreteFunction(shared_ptr<GenericVector> x) : x(x) {}
>>> { x(x); }
>>>
>>> shared_ptr<GenericVector> vec()
>>> {return x;}
>>>
>>> private:
>>>
>>> shared_ptr<GenericVector> x;
>>>
>>> };
>>>
>>> Then it would be possible to do
>>>
>>> Vector x;
>>> Function u(x);
>>>
>>> as we can now and the Function u would know that someone else is
>>> responsible for deleting the data.
>>>
>>> Then if one writes code where the Vector goes out of scope, one must
>>> use a shared_ptr, but not otherwise. We would not force everyone to
>>> use shared_ptr all the time.
>>>
>> I think that having two options would lead to confusion.
>>
>> On a another note, I don't really like the above code anyway. We could
>> avoid this in many cases by adding the constructor
>>
>> Function::Function(Mesh& mesh, Form& form, uint i = 1);
>>
>> and letting Function create the Vector. Function already has a member
>> function for accessing the underlying Vector.
>>
>> Garth
>
> That's what I suggested earlier. It would simplify many things if we
> always know who owns what. We could assume that the Function never
> owns the Mesh but always owns the Vector (for discrete functions).
>
> If someone has a Vector and wants to create a Function from it, then
> just do
>
> Vector x;
> Function u;
> u.vector() = x; // Copy data
>
OK, and if someone really wants a Function to point to x, they can do
shared_ptr<Vector> x(new Vector);
Function u;
u.vector() = x; // Share data
If Function uses shared_ptr internally for its Vector, it doesn't have
to worry about keeping track of ownership.
Garth
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> 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