dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #09527
Re: Function and DofMap
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...
--
Martin
> The thing to keep in mind is that the reference counter
> is attached to the shared_ptr, so creating two shared_ptr
> instances from x separately won't work. So f.ex.:
>
> {
> Vector v(...);
> Function f(v);
> {
> Function g(v);
> } // the shared_ptr g.x deletes v
> } // the shared_ptr f.x deletes v again
>
> It is possible to create a common baseclass in dolfin
> for reference counting, such that the counter is attached
> to the object being counted, and make shared_ptr use this
> mechanism by calling a different shared_ptr constructor.
>
> --
> Martin
>
>
>> Garth
>>
>>
>>> Having different options for ownership of data isn't just
>>> an interface issue, it's important for coupling dolfin code
>>> with other code.
>>>
>>> It's also not only Function that's affected by this issue,
>>> you might have a PETSc Vec or Epetra_FEVector and
>>> wish to assemble into if, so you'll need to wrap it in a
>>> dolfin::*Vector during assembly, without giving up
>>> ownership of the data.
>>>
>>> --
>>> Martin
>>> _______________________________________________
>>> DOLFIN-dev mailing list
>>> DOLFIN-dev@xxxxxxxxxx
>>> http://www.fenics.org/mailman/listinfo/dolfin-dev
>>
>>
>>
>
Follow ups
References