← Back to team overview

dolfin team mailing list archive

Re: Reading functions from file

 

On Monday 08 December 2008 14:53:09 Anders Logg wrote:
> On Mon, Dec 08, 2008 at 02:31:23PM +0100, Johan Hake wrote:
> > On Monday 08 December 2008 13:55:26 Anders Logg wrote:
> > > On Mon, Dec 08, 2008 at 08:01:32AM +0100, Johan Hake wrote:
> > > > On Sunday 07 December 2008 23:33:53 Anders Logg wrote:
> > > > > Something that needs to be added to the new Function interface is
> > > > > reading functions from file. This has worked before:
> > > > >
> > > > >   f = Function("function.xml")
> > > > >
> > > > > Can this be added to the metaclass machinery?
> > > >
> > > > No, but to the __new__ function ;) so I guess yes!
> > > >
> > > > The metalclass produces Function classes. The __new__ function
> > > > instantiate new Functions from what ever argument. This is such a
> > > > case.
> > >
> > > It looks like some work is needed to get this in place.
> > >
> > > The "constructor" currently looks as follows:
> > >
> > >     def __new__(cls, V, **kwargs):
> > >
> > > so to do
> > >
> > >     f = Function("function.xml")
> > >
> > > we need to check if V is a string. Could you add some hooks for this?
> >
> > I will have a look at it. I do not like V beeing both a FunctionSpace and
> > potentially a filename. I consider having a bunch of kwargs, all
> > defaulting to None. E.g.
> >
> >   def __new__(cls, V=None,cpparg=None,defaults=None,filename=None):
> >
> > Then if you create a Function from file you do:
> >
> >   f = Function(filename="some_function.xml")
> >
> > the cpparg can the repreresent what is sent to compile_function.
>
> Then it would be different from the C++ constructor (which doesn't
> handle named default arguments) and the Mesh constructor in both C++
> and Python:
>
>   mesh = Mesh("mesh.xml")

The Mesh class has a much clearer C++ interface. It is either instantiated 
with a filename-string or from another mesh. The Function class is a 
versatile class already in the C++ interface, which defines different 
constructors, but evenmore so in the python interface. 

Then I do not think that adding a kwarg for filename is that bad. The design 
goal of having as similare interface as possible is good, but then there are 
different programming cultures too, to take into acount. I am not religious 
about it, but as far as we can I think we should define kwargs to reflect 
different instantiation protocol.

kwargs gives information about how to instantiate a Function. A common 
way to figure out how to use a class in python, is to look at the args and 
kwargs in class.__init__.

> > > Also, we need to figure out how to define the file format for
> > > Functions.
> > >
> > > Currently, it looks like this:
> > >
> > > <dolfin ...>
> > >   <function>
> > >     <mesh ...>
> > >       ...
> > >     </mesh>
> > >     <vector ...>
> > >       ...
> > >     </vector>
> > >     <finiteelement signature="..."/>
> > >     <dofmap signature="..."/>
> > >   </function>
> > > </dolfin>
> > >
> > > Should we change the file format to reflect the new design? We would
> > > need something like this:
> > >
> > > <dolfin ...>
> > >   <function>
> > >     <functionspace>
> > >       <mesh>
> > >         ...
> > >       </mesh>
> > >       <finiteelement signature="..."/>
> > >       <dofmap signature="..."/>
> > >     </functionspace>
> > >     <vector ...>
> > >       ...
> > >     </vector>
> > >   </function>
> > > </dolfin>
> >
> > The loaded function instantiate a FunctionSpace in any case, so I guess
> > the present format is good enough.
> >
> > Our problem is that, after we have instantiated the cpp.Function,
> > together with the cpp.FunctionSpace, we then have to reverse engeneer the
> > ffc.FiniteElement together with the dolfin.FunctionSpace.
>
> Yes.
>
> > > We also need to change the signature strings so that one may
> > > create form compiler elements (and dofmaps) from the strings.
> > >
> > > The simplest option could be to let the signature be something like
> > >
> > >    FiniteElement("Lagrange", "triangle", 1)
> >
> > So you mean substituting the present
> >
> >   "Lagrange finite element of degree 1 on a triangle"
> >
> > with the above? Won't this signature be lost in the parsing of the
> > XMLFile, or do you meen that we should parse the function.xml file after
> > we have sent it to cpp.Function() and then extract the element signature?
>
> Yes, first create the cpp.Function, then extract
> v.function_space.element().signature() and use that to create the form
> compiler element. Will that work?

Yes it will be doable. I didn't know that the FiniteElements in the 
elementlibrary all defined its signature. To accomplish this we need to add 
some construction options for the dolfin.FunctionSpace though, as it is too 
restrictive now.

Martin has also asked for a way to instantiate a dolfin.FunctionSpace either 
with an ufc form or from an ufc_finite_element together with an ufc_dofmap. 
We should not forget the pure ufc interface. I think it is good that Martin 
keep up that pressure! To reverse engeneer a dolfin.FunctionSpace from these 
entities will probably not be doable.

But for that usercase it should be sufficient to construct a cpp.FunctionSpace 
which can be sent to assemble, e.g:

  V = cpp.FunctionSpace(mesh,ufc_element,ufc_dofmap)
  f = Function(V,...) # We need to add support for sending in just 
                      # a cpp.FunctionSpace to a Function, and then return 
                      # a cpp.Function
  
  A = assemble(compiled_ufc_form,function_spaces=V,coefficients=[f])

We already have checks for cpp.FunctionSpace and cpp.Function for the 
coefficients.

I do not know how the coefficient kwarg should work though. 

  assemble(...,coefficient ={f_ufl:f_cpp}) 

as the form that is sent in to the assemble function is compiled and does not 
carry any information about the ufl/ffc coefficient function. Do you have 
anything to add here Martin?


Johan


Follow ups

References