dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #09673
Re: PyDOLFIN Function
On Mon, Sep 15, 2008 at 03:47:59PM +0100, Garth N. Wells wrote:
>
>
> Anders Logg wrote:
> > On Mon, Sep 15, 2008 at 03:12:58PM +0100, Garth N. Wells wrote:
> >>
> >> Anders Logg wrote:
> >>> On Mon, Sep 15, 2008 at 03:06:55PM +0200, Johan Hake wrote:
> >>>> On Monday 15 September 2008 14:29:08 Garth N. Wells wrote:
> >>>>> Could a Python expert take a look at site-packges/dolfin/function.py?
> >>>>> The code directly following the comment
> >>>>>
> >>>>> # Special case, Function(element, mesh, x), need to create simple form
> >>>>> to get arguments
> >>>>>
> >>>>> need to be updated but I don't understand it well.
> >>>> The first special case is for initializing a Function with a given Vector, by
> >>>> constructing a dofmap from the handed element.
> >>>>
> >>>> As constructing a Function from a vector is removed from the cpp interface,
> >>>> and we have not, (or have we?) figured out how to wrap a shared_ptr in swig,
> >>>> we should probably just remove the first case for now.
> >>>>
> >>>> Johan
> >>> The question is how we want to create discrete Functions in Python.
> >>> Previously, this was done by
> >>>
> >>> u = Function(element, mesh, Vector())
> >>>
> >>> but now the third argument is not needed anymore. If we remove it,
> >>> we get
> >>>
> >>> u = Function(element, mesh)
> >>>
> >>> but that doesn't work since that is the way to initialize a
> >>> user-defined function (something overloading eval()).
> >>>
> >>> We could put in a flag and make "discrete" the default. Then all
> >>> user-defined functions need to set the flag to "user".
> >>>
> >>> Suggestions? This is a good time to worry about how we want to design
> >>> the Function interface.
> >>>
> >> Sounds ok to me. This is basically what Vector() was doing, and a flag
> >> would be more descriptive.
> >>
> >> Garth
> >
> > Maybe we could first try to think seriously about reducing the number
> > of different constructors in Function. There are 14 now! See below.
> >
> > I guess we need the following two basic constructors (empty and copy):
> >
> > /// Create empty function (read data from file)
> > Function();
> >
> > /// Copy constructor
> > Function(const Function& f);
> >
> > Then we have one for reading from file, which seems ok:
> >
> > /// Create function from data file
> > explicit Function(const std::string filename);
> >
> > And then the following set of constructors for constants:
> >
> > /// Create constant scalar function from given value
> > Function(Mesh& mesh, real value);
> >
>
> This one is useful.
>
> > /// Create constant vector function from given size and value
> > Function(Mesh& mesh, uint size, real value);
> >
>
> We could get rid of this one and use the below constructor.
>
> > /// Create constant vector function from given size and values
> > Function(Mesh& mesh, const Array<real>& values);
> >
>
> This one is useful.
>
> > /// Create constant tensor function from given shape and values
> > Function(Mesh& mesh, const Array<uint>& shape, const Array<real>& values);
> >
>
> This is the most generic of the constant functions, so I guess we need it.
>
> > And then there's this constructor which is needed for w.split(u, p):
> >
> > /// Create discrete function from sub function
> > explicit Function(SubFunction sub_function);
> >
> > But then there's the following mess of constructors:
> >
>
> Some of these constructors are necessary to support the PyDOLFIN
> interface. Can we get around this somehow to avoid duplication?
>
> > /// Create function from given ufc::function
> > Function(Mesh& mesh, const ufc::function& function, uint size);
> >
> > /// Create discrete function for argument function i of form
> > Function(Mesh& mesh, Form& form, uint i = 1);
> >
> > /// Create discrete function for argument function i of form
> > Function(Mesh& mesh, DofMap& dof_map, const ufc::form& form, uint i = 1);
> >
> > /// Create discrete function for argument function i of form (data may be shared)
> > Function(std::tr1::shared_ptr<Mesh> mesh,
> > std::tr1::shared_ptr<GenericVector> x,
> > std::tr1::shared_ptr<DofMap> dof_map, const ufc::form& form, uint i = 1);
> >
> > /// Create discrete function based on signatures
> > Function(std::tr1::shared_ptr<Mesh> mesh,
> > const std::string finite_element_signature,
> > const std::string dof_map_signature);
> >
> > /// Create user-defined function (evaluation operator must be overloaded)
> > explicit Function(Mesh& mesh);
> >
>
> We need this one.
>
> Garth
If we just consider discrete functions for a while, the question is
how these may be most conveniently (and naturally) defined in C++ and
Python.
In C++, one only has a dolfin::Form, for example PoissonBilinearForm,
and then it's simple to create a discrete Function by
Function u(mesh, form);
This will extract the element and dof map for the second argument of
the form (the trial function) which is normally what is needed.
In Python, one does not have a dolfin::Form, but instead one has a
FiniteElement, and then the simplest thing to do is
u = Function(element, mesh)
The element is the first argument for practical reasons (see
function.py) but maybe it shouldn't. I'd like to change this so that
the mesh is always first. All Functions require a Mesh and then it's
natural to put this first.
So then we would have
C++: Function u(mesh, form);
Python: u = Function(mesh, element)
On the other hand, we've been discussing adding a FunctionSpace class,
and then it might be natural to just have
C++: Function u(V);
Python: u = Function(V)
This would create a discrete Function. Constant Functions and
user-defined Functions may be created without reference to a
FunctionSpace. This would solve the problem of overloading
constructors. It would be very clear that whenever a FunctionSpace is
involved, it is a discrete Function.
--
Anders
Attachment:
signature.asc
Description: Digital signature
Follow ups
References