← Back to team overview

dolfin team mailing list archive

Re: Patch with fixes to PyDOLFIN

 

On Mon, Nov 03, 2008 at 11:38:27AM +0100, Johan Hake wrote:
> On Monday 03 November 2008 10:36:52 Martin Sandve Alnæs wrote:
> > 2008/11/3 Johan Hake <hake@xxxxxxxxx>:
> > > 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?
> >
> > That's the point of inheritance, yes. And that's why "itself" must act
> > as an "envelope" around the "letter" that it owns by forwarding calls,
> > giving an envelope-letter design.
> >
> > >> >> 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)
> >
> > That jit is used to compile a finite_element and dof_map in FunctionSpace
> > is a separate use of jit from compiling the forms a and L. 
> > The 
> > ufl.Form instances
> > a and L won't see the dolfin.FunctionSpace, only the ufl.FiniteElement.
> > So the form is never instantiated with any function space.
> 
> I think I mixed ufc::Form and dolfin::Form. I thought jit returned a compiled 
> and instantiated dolfin::Form. But I suppose we then need some form of jit 
> compiling of a dolfin::Dofmap and dolfin::FiniteElement, based on the 
> ufc::dofmap, and ufc::FiniteElement that resides in the module returned from 
> jit today.

There is a new jit() function in FFC that takes a FiniteElement and
returns a compiled ufc::dof_map and ufc::finite_element:

  (compiled_element, compiled_dofmap) =3D jit(element)

In the current implementation of assembly/JIT compilation in
PyDOLFIN, we have avoided using dolfin::Form. This is really just a
convenience wrapper that makes life easy in C++ so it's not
necessarily convenient to use from Python.

So, the constructor of FunctionSpace needs to call jit() to get a
compiled ufc::finite_element and a compiled ufc::dof_map. It may then
instantiate the dolfin::FunctionSpace from those two and the Mesh.

--
Anders


> > If we want to construct dolfin.Form objects in PyDOLFIN, we need to do
> > something more.
> 
> Ok, I think I am a bit lost with regard to [dolfin,ufc]::Form. The 
> dolfin::Assembler takes a dolfin::Form. Where is this "instantiated" today?
> 
> > > 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.
> >
> > Yes. I think that can work out ok. When fetching ufl.FiniteElement objects
> > from a ufl.Form, those objects will actually be the dolfin.FunctionSpace
> > objects because of the inheritance above.
> 
> Ok, you go for inheritance then ;)?
> 
> > formdata = ufl.FormData(a)
> > # formdata.elements == [V, ...]
> >
> > Thus the mesh will actually be implicitly defined through the function
> > spaces, and can be optional in assemble!
> >
> > So this should be possible:
> >
> > mesh = ...
> > V = FunctionSpace(mesh, "CG", 1)
> > f = Function(V)
> > a = f**2*dx
> > b = assemble(a)
> >
> > or this way for separately defined functions:
> >
> > mesh = ...
> > V = FunctionSpace(mesh, "CG", 1)
> > f = Function(V)
> > a = f**2*dx
> > fc = compiled_function...
> > b = assemble(a, {f: fc})
> >
> > However, I'd still like to be able to define forms separately in .ufl files
> > instead of always having to merge them with the PyDOLFIN application.
> 
> Agree.
> 
> > In that case we need to instantiate dolfin.FunctionSpace from the elements
> > in a given form. And we need to reuse those across forms, e.g. a and L.
> 
> Exactly.
> 
> > (But at least then we can get the function names from the .ufl file.)
> 
> How is this different from the earlier scenario?
> 
> > forms = ufl.load_forms(ufl_filename) # can add returning functions later
> >
> > a, L = forms
> > formdata_a = ufl.FormData(a)
> > formdata_L = ufl.FormData(L)
> >
> > a_spaces = [dolfin.FunctionSpace(mesh, element) for element in
> > formdata_a.elements]
> > L_spaces = [dolfin.FunctionSpace(mesh, element) for element in
> > formdata_a.elements]
> >
> > a_form = dolfin.Form(a, a_spaces)
> >
> > Eh... This is getting complicated.
> > Maybe we can generate PyDOLFIN code as well ;)
> 
> If we let jit compile the form with -l dolfin we can extract the 
> FunctionSpaces from the module. These will only need a mesh to be 
> instantiated.
> 
> jit can then be called with either a mesh, which implies that new 
> FunctionSpaces are instantiated and used to instantiate the dolfin::form, or 
> it can be called with an allready instantiated FunctionSpace(s), which are 
> used to instantiate the dolfin::Form. 
> 
> With this we have reuse of FunctionSpaces, but with the cost that we are using 
> dolfin::Form instead of ufc::Form.
> 
> > >> > 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
> 
> 
> Johan
> 
> _______________________________________________
> DOLFIN-dev mailing list
> DOLFIN-dev@xxxxxxxxxx
> http://www.fenics.org/mailman/listinfo/dolfin-dev

Attachment: signature.asc
Description: Digital signature


References