dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #10286
Re: new Function design in C++
On Wed, Oct 22, 2008 at 07:48:38PM +0100, Garth N. Wells wrote:
>
>
> Anders Logg wrote:
> > On Wed, Oct 22, 2008 at 08:24:18PM +0200, Anders Logg wrote:
> >> On Wed, Oct 22, 2008 at 07:05:09PM +0100, Garth N. Wells wrote:
> >>>
> >>> Anders Logg wrote:
> >>>> On Wed, Oct 22, 2008 at 12:08:43PM +0100, Garth N. Wells wrote:
> >>>>> The thread on the new Function design has digressed from the immediate
> >>>>> issue, so I'm restarting it.
> >>>>>
> >>>>> The issue is how to deal with user defined functions in C++. What if we
> >>>>> have a design such that:
> >>>>>
> >>>>> - All Functions must have a FunctionSpace
> >>>> Yes.
> >>>>
> >>>>> - A FunctionSpace does not have to be complete (a complete FunctionSpace
> >>>>> having a Mesh, a FiniteElement and a DofMap). As a minimum requirement,
> >>>>> and FunctionSpace must have a Mesh.
> >>>> I think it should always need to be complete. We can avoid a lot of
> >>>> trouble if we make firm requirements: a Function is always associated
> >>>> with a FunctionSpace and the FunctionSpace is always completely
> >>>> defined.
> >>>>
> >>>>> - A FiniteElement and/or DofMap can be attached to a FunctionSpace after
> >>>>> its creation
> >>>>>
> >>>>>
> >>>>> Related to the functions Function::interpolate(double* coefficients, ..)
> >>>>> for interpolating Functions on cells
> >>>>>
> >>>>> - The new Function::interpolate functions do not take a FiniteElement as
> >>>>> an argument, so it is not possible to interpolate a function in a
> >>>>> different space. Is it desirable to allow Functions from one space to be
> >>>>> interpolated in another?
> >>>> Yes, it's desirable. This can be done globally when needed:
> >>>>
> >>>> Function v(V);
> >>>> Vector coefficients;
> >>>> v.interpolate(coefficients, W);
> >>>>
> >>>> This will compute the global coefficient vector for v on W.
> >>>>
> >>>> This is currently implemented with the assumption that the meshes for
> >>>> V and W are the same but could quite easily be extended to
> >>>> non-matching meshes now that functions can be evaluated at arbitrary
> >>>> points (using GTS).
> >>>>
> >>>>> If we do this, would:
> >>>>>
> >>>>> - The above allow FiniteElement types to be checked at runtime for
> >>>>> consistency (the FiniteElement passed to Function::interpolate should be
> >>>>> the same as the Functions own FiniteElement for discrete Functions. This
> >>>>> is what we did with the old design.)>
> >>>>>
> >>>>> - The above deal with the issue of user-defined functions which have a a
> >>>>> FunctionSpace but no FiniteElement?
> >>>>>
> >>>>> - The above deal with special functions, like the mesh size h?
> >>>> Here's my suggestion for how to handle initialization of Functions in C++.
> >>>> There is no need for a circular dependency. First some simple facts:
> >>>>
> >>>> 1. The constructor of a Form may require one or more Functions
> >>>> 2. The constructor of a Function requires a FunctionSpace
> >>>>
> >>>> From this it follows that we must do something like
> >>>>
> >>>> Function f(V);
> >>>> Poisson::BilinearForm a;
> >>>> Poisson::LinearForm L(f);
> >>>>
> >>>> The question is now how to initialize the FunctionSpace V. My
> >>>> suggestion would be to extend the code generation to generate code for
> >>>> creating the FunctionSpace(s), just like we do already when we
> >>>> generate UFC code + some extra code for defining the Form classes
> >>>> (when using -l dolfin in FFC). This does not make FFC DOLFIN-specific
> >>>> or DOLFIN FFC-specific. One can still use other form compilers, but the
> >>>> interface will not be as nice.
> >>>>
> >>>> So, one would do something like this:
> >>>>
> >>>> #include "Poisson.h"
> >>>>
> >>>> int main()
> >>>> {
> >>>> Mesh mesh("mesh.xml");
> >>>> Poisson::TestSpace V(mesh);
> >>> Why 'TestSpace'?
> >>>
> >>> Also, when many functions are present, how would we
> >>> identify each one? Could FFC create a class Poisson::FunctionSpace::foo
> >>> when 'foo' is the name of the function in the FFC input?
> >> We could let FFC create a number of function space classes:
> >>
> >> Poisson::TestSpace
> >> Poisson::TrialSpace
> >> Poisson::FunctionSpace_0
> >> Poisson::FunctionSpace_1
> >> ...
> >>
> >> or even
> >>
> >> Poisson::v::FunctionSpace
> >> Poisson::u::FunctionSpace
> >> Poisson::f::FunctionSpace
> >> Poisson::g::FunctionSpace
> >>
> >> (but I'm not sure it looks very nice).
> >>
> >> A complication I didn't think of before is how to handle the case when
> >> all spaces are the same (to get reuse of dofmaps). One option would be
> >> to either generate just one class if all spaces are the same, and
> >> otherwise generate separate clases like above. So either one does
> >>
> >> Poisson::FunctionSpace V(mesh);
> >> Function f(V);
> >> Function g(V);
> >> Poisson::LinearForm(f, g);
> >>
> >> or
> >>
> >> Poisson::FunctionSpace_0 V(mesh);
> >> Poisson::FunctionSpace_1 W(mesh);
> >> Function f(V);
> >> Function g(W);
> >> Poisson::LinearForm(f, g);
> >>
> >>>> Function f(V);
> >>>> Poisson::BilinearForm a;
> >>>> Poisson::LinearForm L(f);
> >>>> ...
> >>>> }
> >>>>
> >>>> First V, then f, then L.
> >>>>
> >>> Would this work for all the Functions in SpecialFunction.h?
> >> I haven't thought about it, but yes I guess it would.
> >>
> >> We can provide a set of predefined FunctionSpaces (like DG on
> >> triangles and tetrahedra).
> >
> > I'm moving the discussion of the removal of DofMapSet over here since
> > it's related.
> >
> > If a Form should own a set of FunctionSpaces (replacing the current
> > DofMapSet), that would prevent reuse of FunctionSpaces (and DofMaps)
> > across multiple Forms.
> >
> > Another option would be to always require that a Form is initialized
> > with one or more FunctionSpaces. This makes sense and is in agreement
> > with the requirement of a FunctionSpace when initializing a Function.
> >
> > It would then be
> >
> > PoissonFunctionSpace V(mesh);
> > Function f(V);
> > Function g(V);
> > PoissonBilinearForm a(V, V);
> > PoissonLinearForm L(V, f, g);
> >
> > Then it's possible to reuse V across multiple forms (even forms not
> > included in Poisson.h).
> >
>
> I like this because it's crystal clear where the DofMap which is being
> used comes from, which will make it easy to re-order the DofMap and be
> sure everything keeps working.
>
> Garth
Yes, we avoid having to implement any fancy caching of DofMaps. The
DofMap/FunctionSpace will simply be reused whenever a user asks for
it.
I think we should generally try to follow this strategy as much as we
can throughout the library, that is, always require any data needed by
an object to be given to the constructor. So all code will essentially
look something like
A a;
B b(a);
C c(a, b);
D d(a, b, c);
etc.
I pose the conjecture that whenever this seems to break (circular
dependencies), we've done something wrong with the design.
--
Anders
Attachment:
signature.asc
Description: Digital signature
References