← Back to team overview

dolfin team mailing list archive

Re: Collect function data in subclass to prepare for user-defined functions.

 


Good. It seems that we agree on this.

/Johan

On Tue, 15 Feb 2005, Anders Logg wrote:

We could of course have things like time-dependent functions that are
automatically updated and interpolated from a previously saved
solution (saving the primal problem to solve the dual later), but
perhaps we should wait and try to keep things as simple as possible as
long as possible?

Maybe the class (New)Function should always just represent a function
that does not depend on time. We could later add functionality to read
values from a file at a given time, something like

   NewFunction::update(const File& file, real t);

/Anders

On Tue, Feb 15, 2005 at 02:54:42AM -0500, Johan Hoffman wrote:

Good, I think this is a simple way to handle functions. Weather we use i
or comp doesn't matter on my part.

As for time dependent functions, I think a solution of the form you
suggest is good in the case of functions given by expressions. For time
dependent functions given as FE functions in discrete time, such as a
computed time dependent solution, a user could also declare a function
for example given by interpolation in time based on FE functions in
discrete time, and where for large problems one would typically write to
file.

So, there are various ways to implement specific functions, and I think it
is a good idea to leave much to the user. In particular at this stage, as
we need to focus on getting the basics in place. If it turns out that a
particular type of function would be very useful, we could add it later
on.

/Johan


On Mon, 14 Feb 2005, Anders Logg wrote:

Yes, I think we should add alternative evaluation operators. But I
suggest changing comp to i, and maybe we don't need time. A user that
wants a time-dependent function declares her own function and can just
put in a public member variable called t and use that:

In solver:

  f.t = 2.0;

In function:

class MyFunction : public Function
{
public:

  real operator() (const Point& p)
  {
     return sin(t)*p.x;
  }

  real t;

}

/Anders

On Mon, Feb 14, 2005 at 05:52:20PM -0500, Johan Hoffman wrote:

Looks simple and good, I think. How about vector functions (and time
dependent functions)? Should we add alternative operator() functions to
NewFunction to be implemented by the user:

virtual real operator()(const Point& p, int comp)
virtual real operator()(const Point& p, real time)
virtual real operator()(const Point& p, int comp, real time)

or should we introduce new classes?

/Johan

On Mon, 14 Feb 2005, Anders Logg wrote:

I understand your point. However, I just checked in some updates of
NewFunction that lets a user do

class MyFunction : NewFunctionExpression
{
 real operator()(const Point& p)
{
    return sin(p.x);
}
};

MyFunction f;

Could you take a look and see if you like the new/old solution?
It's not very complicated. The projection just checks if data is null
and in that case calls the user defined evaluation operator.

/Anders

On Mon, Feb 14, 2005 at 03:35:25PM +0100, Johan Jansson wrote:

I'm thinking about how to enable user-defined functions, but I don't
have a clear solution.

The idea right now seems to be to subclass NewFunction, a la:

// Source term
// Example using NewFunction

class F : public NewFunction
{
public:
F(const Mesh& mesh, const NewFiniteElement& element, NewVector& x) :
  NewFunction(mesh, element, x)
{
}
virtual real operator()(const Point& p)
{
  real pi = DOLFIN_PI;
  return 14.0 * pi*pi * sin(pi*p.x) * sin(2.0*pi*p.y) *
  sin(3.0*pi*p.z);
}
};

We could have a separate constructor when an expression is given, and
then project the given expression.

I think this is a bit ugly though, it seems unnecessarily complex.

Another solution would be to separate the expression out into a
functor (function class), and the example would be:

class F : Expression
{
virtual real operator()(const Point& p)
{
  real pi = DOLFIN_PI;
  return 14.0 * pi*pi * sin(pi*p.x) * sin(2.0*pi*p.y) *
  sin(3.0*pi*p.z);
}
}

then:

int main()
{
...

F fexpression;
NewFunction f(mesh, element, fexpression);

..
}

This seems much more natural. When we have a function given by the
values of its degrees of freedom, we pass a vector with the dofs to
NewFunction. When we have a function given by an expression, we pass
the expression to NewFunction and it projects it and stores it as
values of the dofs. However, we would need to introduce a new class:
Expression. What do you think?

Johan

_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev


_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev



_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev


_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev



_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev


_______________________________________________
DOLFIN-dev mailing list
DOLFIN-dev@xxxxxxxxxx
http://www.fenics.org/cgi-bin/mailman/listinfo/dolfin-dev





References