← Back to team overview

dolfin team mailing list archive

Re: Function and DofMap

 

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.

--
Martin


Follow ups

References