← 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/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); }

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