← Back to team overview

dolfin team mailing list archive

Re: Reading functions from file

 

2008/12/9 Johan Hake <hake@xxxxxxxxx>:
> On Monday 08 December 2008 22:31:58 Martin Sandve Alnæs wrote:
>> 2008/12/8 Johan Hake <hake@xxxxxxxxx>:
>> > 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__.
>>
>> Here, let me fix that for you:
>>
>>   A common way to figure out how to use a
>>   poorly designed and/or documented
>>   class in python, is to look at the args and kwargs in class.__init__.
>>
>> Forcing the user to look at the source code rarely reflects good code.
>
> I suppose you do not mean that forcing a user to look at the argument list is
> reflecting bad code design, but rather the other way around. If we have bad
> code design we may force the user to look at the argument list together with
> other documentation?

Sorry, I was thinking "*args" and "**kwargs", because that's where
I saw this discussion going... And I strangely interpreted "look in __init__"
as looking at the implementation, not the signature.

I agree completely with you, an explicit argument list with good names is
perhaps the most important piece of documentation (in any language actually).

>> But I agree that keyword arguments isn't such a bad thing in python.
>
> Good!
>
>> >> 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.
>>
>> Whatever requirements you decide to put on the element signature,
>> it would be nice if they were documented formally (i.e. not as ffc code),
>> and placed in the UFC manual.
>>
>> > 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?
>>
>> Looks good. Either a dict or a list should be accepted.
>> UFC does not require a UFL source!
>
> Exactly.
>
>> Maybe we can add a helper function:
>>
>> def function_spaces(form, mesh):
>>     spaces = []
>>     ... loop over form arguments and create FunctionSpace objects with
>> reuse if possible
>>     return spaces
>
> My hands on experience with pure ffc code is nil, so please be more explicit.

"An easy way of creating FunctionSpaces from a ufc::form"
should be detailed enough for this disussion.

>> Maybe not exactly what's needed. But preferably we will have tools
>> that enable easy use of UFC code directly, but which are also
>> used behind the scenes regularly by common code such that
>> they are actually in use and being maintained.
>> Otherwise somebody(tm) will just keep making design decisions
>> that breaks UFC compatibility, which sort of weakens the point of
>> a unified interface...
>
> I think I see your point. Instead of hiding the ufc stuff, in ffc.jit, which
> is the case today, we should use it more explicitly in the code, together
> with hooks to the outside world, for people that want to use PyDOLFIN with
> pure ufc.
>
> But isn't this desing desision already broken in C++ DOLFIN?

That's what I'm wondering...

(This thread is messed up now...)

--
Martin


References