← 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 11:16:06AM +0200, Martin Sandve Alnæs wrote:
>> 2008/9/7 Martin Sandve Alnæs <martinal@xxxxxxxxx>:
>> > 2008/9/7 Garth N. Wells <gnw20@xxxxxxxxx>:
>> >>
>> >>
>> >> 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;}
>> >>  }
>> >> ?
>> >
>> > Looks right. And the copy constructor:
>> >
>> >      DiscreteFunction(const DiscreteFunction & f)
>> >      { x(f.x); }
>>
>>
>> Sorry, that's a "move constructor", not a copy constructor...
>
> What is a move constructor? It looks like a copy constructor to me.
>
> --
> Anders

A true copy constructor would copy the vector.
This implementation shares the vector.

Consider this pseudo-code:

Function g;
...
Function f = g;
f *= 2;

Would you expect g to be modified by the last line?
It will, if the copy constructor if Function just copies the pointer.

--
Martin


References