← Back to team overview

dolfin team mailing list archive

Re: Patch with fixes to PyDOLFIN

 

On Monday 03 November 2008 09:00:58 Martin Sandve Alnæs wrote:
> 2008/11/2 Johan Hake <hake@xxxxxxxxx>:
> > On Sunday 02 November 2008 17:44:39 Anders Logg wrote:
> >> On Sun, Nov 02, 2008 at 04:28:45PM +0100, Johan Hake wrote:
> >> > Hello!
> >> >
> >> > I have fixed the swig interface so it compiles. I had to add
> >> > SubFunction in dolfin_function.h. If we do not want this we have to
> >> > add
> >> >
> >> >   #include "SubFunction.h"
> >> >
> >> > to Function.h, as it is in 0.8.1.
> >> >
> >> > As function inherits ufc::function I also %imported ufc.h and added
> >> > ufc-1 as swig dependencies in scons.cfg.
> >> >
> >> > I %renamed function.in to function._in and %extended the interface to
> >> > SubFunction so one can write
> >> >
> >> >   u in V
> >> >
> >> > as discussed previously.
> >>
> >> Very nice!
> >>
> >> > I am curious of how we will fix the whole PyDOLFIN interface with the
> >> > precompiled function spaces aso. These can all be hidden in the
> >> > assemble function and/or in the LinearPDE class. But what if we want
> >> > to expose a FunctionSpace from a compiled form? Do we want this?
> >> >
> >> > Or what if we want to create a FunctionSpace from an element and a
> >> > mesh. This can be done more or less in the same way as we have solved
> >> > Function in 0.8.1, but then we miss the whole point of reusing
> >> > FunctionSpaces.
> >> >
> >> > Any good suggestions?
> >> >
> >> > Johan
> >>
> >> Here's a good suggestion... :-)
> >>
> >> We create a new Python class (in site-packages/dolfin/functionspace.py)
> >> which either inherits from FormCompiler.FiniteElement and
> >> dolfin::FunctionSpace or owns such objects as member data.
> >
> > I suppose it have to inherit from FormCompiler.FiniteElement, but it only
> > have to owe a cpp:FunctionSpace.
>
> To clarify: The (only?) reason for owning and not inheriting is that
> we want to reuse function spaces.
>
> > So the __init__ function in FunctionSpace would be something like:
> >
> >  def __init__(self, mesh, family, order):
> >      FormCompiler.FiniteElement.__init__\
> >         (self,family,dim2shape(mesh.geometry().dim(),order))
> >      if self.value_dimension(0) > 1:
> >          form = ffc.TestFunction(self)[0]*ffc.dx
> >      else:
> >          form = ffc.TestFunction(self)*ffc.dx
> >      (compiled_form, module, form_data) = jit(form,mesh)
> >      self._V = compiled_form.function_space(0)
> >
> > and then we can add something like
> >
> >  def cpp_function_space(self):
> >      return self._V
> >
> > to the interface, where the latter function is used in the __init__
> > function of the Function class to initialize the cpp_Function?
> >
> > Maybee we for compatability should let FunctionSpace inherit
> > cpp_FunctionSpace. If we do that the __init__ function from above would
> > look a bit differently.
>
> To still allow reusing FunctionSpaces, it would have to be some kind
> of envelope-letter design then.

Can't it just pass it self to where ever it is needed, instead of passing the 
function space that it owe? 

> >> In PyDOLFIN, FunctionSpace will then be something that replaces both
> >> FormCompiler.FiniteElement and dolfin::FunctionSpace:
> >>
> >>   V = FunctionSpace(mesh, "Lagrange", 1)
> >>   v = TestFunction(V)
> >>   u = TrialFunction(V)
> >>   f = Function(V)
> >>   a = dot(grad(v), grad(u))*dx
> >>   L = v*f*dx
> >>   A = assemble(a)
> >>   b = assemble(L)
> >>
> >> Note that the "triangle" or "tetrahedron" argument is not needed since
> >> this can be deduced from the mesh.
> >
> > Looks nice. Would it then be possible to reuse the cpp_FunctionSpace that
> > is initialized for V when the form is compiled using jit?
>
> The reuse must happen when V is constructed, so this has nothing to do
> with compiling forms with jit.

If V is constructed as suggested above, see __init__, jit needs to instantiate 
the functionspace from the compiled form module, and then use this to 
instantiate the form. (In this case where we only is interested in the 
actuall function space we do not need jit to instantiate the form though)

But when jit is called in the assemble function, it needs to instantiate the 
form using the functions spaces that are provided through the uncompiled form 
instead of instantiating them from the compiled form module.

> > I see that this is a very handy way of defining and assemble a form, but
> > would it be possible with this design to define a form using only the
> > FormCompiler language, and then pass this form to jit, or directly to
> > assemble. Then either add the functions manually to the form a là c++ or
> > as it is in the assemble function now, i.e., passing them as an optional
> > kwarg. The latter could be facilitated as Martin suggested previously as
> >
> >  assemble(..., coefficients = {'f':f,'g':g},...)
>
> That's not exactly what I suggested, and it won't work here, since the
> names of functions are not known! We just agreed to remove "name" from
> ufl.Function, but if we keep that this would be possible.
>
> What I suggested was using the (FormCompiler.) ufl.Function instances as
> keys:
>
> ...
> fu = ufl.Function(element)
> a = ...*fu*dx
> fc = compiled_function
>
> assemble(a, ..., coefficients = {fu: fc},...)

Ok!

Johan


Follow ups

References