← Back to team overview

dolfin team mailing list archive

New design of Function classes

 

Here is a suggestion for a redesign of the Function classes in DOLFIN.

The class Function is central in DOLFIN and so it is important that we get
it right. Please comment on the following suggestion of a redesign of the
Function class (and related classes).

First some initial conditions:

1. The main purpose of a Function is that one should be able to evaluate
it. The central method of a Function is thus

    real operator() (const Point& p, real t);

2. The class Function should be allround, simple to use and hide its
current representation to the user. A user shouldn't need to care whether
or not a Function is represented in terms of a list of degrees of freedom
or if the Function is specified in terms of some expression.

3. One should be able to inherit from the class Function to create one's
own Functions.

Condition 2 calls for an envelope-letter design pattern: The class
Function holds a pointer to a GenericFunction. Several classes inherit
from GenericFunction. At all times, the pointer inside Function is
instantiated to one of the subclasses of GenericFunction. The choice of
subclass is handled by the constructor of the class Function, which
determines the type based on the arguments to the constructor.

I can think of three types of Functions, each implemented as a subclass of
GenericFunction:

StaticFunction: constant in time function (until changed) represented by a
list of degrees of freedom (a Vector) on a Mesh. This will in large parts
be the same as the current DofFunction.

DynamicFunction: time-dependent function with data partly stored in a
file.  It should internally hold a variable t telling the current time. If
data is requested at a time other than the current time, new data is
fetched from file. We could also add things such as caching of data (like
with ODEFunction).

FunctionPointerFunction: a function represented by a function pointer.
Replaces the current class ExpressionFunction. (I think we might be
needing the name for something else later, maybe there can be a class
FunctionExpression which allows a simple algebra for functions?)

This design is quite similar to what we have now.

To meet condition 3, we need in addition to make the methods in Function
virtual so that people can make things like

class MyFunction : public Function
{
public:
   real operator() (const Point& p, real t) { return p.x*p.y; }
};

This means that we also need to add an empty constructor to Function and
GenericFunction. For a user-defined Function, the pointer to
GenericFunction  is instantiated to a GenericFunction. This means in turn
that the methods in  GenericFunction should be virtual but not pure
virtual (=0). The impplementations of these functions in GenericFunction
should just say something like

    dolfin_error("Not implemented.");

By the way, this is the same design as we have for the Matrix classes,
motivated by the fact that the actual representation of a Matrix (dense or
sparse) should be hidden, but users should also be able to create their
own Matrix class by inheriting from the class Matrix.

Then there's also the question of the design of the class VectorFunction,
but that may be a separate discussion?

What do you think? Is this a good design? Can we start writing the code?

/Anders

PS: I'm waiting for my computer to arrive, which means I'm stuck with
Windows XP for a few days. This means that all I'll be able to do is write
emails for a few days...





Follow ups