← Back to team overview

dolfin team mailing list archive

Re: Work on a new function.py

 

On Friday 24 October 2008 10:42:23 Martin Sandve Alnæs wrote:
> 2008/10/23 Johan Hake <hake@xxxxxxxxx>:
> > Hello!
> >
> > I have worked on a "new" function.py. Please have a look. It is built
> > around a metaclass for Functions. It makes it "easy" to create both a)
> > userdefined python functions and b) compiled functions.
> >
> > The work flow is the same for both cases:
> >
> >  1) Define a class
> >  2) Instantiate it with a FunctionSpace, and any user specific arguments
> >
> > With the suggested design a user can define classes a la:
> >
> >    class MyCustomFunction(Function):
> >        def __init__(self,V,dummy):
> >            # Note no call to Function.__init__!
> >            self.dummy = dummy
> >
> >        def eval(self,val,x):
> >            val[0] = 0.5
> >            val[1] = 0.5
> >
> >        def dim(self):
> >            return 2
> >
> >        def rank(self):
> >            return 1
> >
> >    # Can also declare dim and rank as int attributes, see below
> >
> >    class MyCustomCompiledFunction(Function):
> >        cppcode = "Jada"
> >        dim  = 1
> >        rank = 0
> >
> > They are then instantiated by:
> >
> >    mesh = UnitSquare(10,10)
> >    element = FiniteElement('Lagrange','triangle',1)
> >
> >    print ""
> >    V = FunctionSpace(mesh,element)
> >
> >    print ""
> >    f0 = MyCustomFunction(V,"Dummy")
> >
> >    print ""
> >    f1 = MyCustomCompiledFunction(V)
> >
> >    try:
> >        # Cannot instantiate the Function class
> >        f2 = Function(V)
> >    except Exception, e:
> >        print e
> >
> > With this interface only one user defined function can be compiled at a
> > time, but we will gain in similare workflow between pure python and
> > compiled functions.
> >
> > I realize that the C++ design must be in place first before we can
> > advance, but this is a proof of principle, that we can use metaclasses to
> > do nice stuff for the end user.
> >
> > Johan
>
> A possible improvement: deducting dim and rank from cppcode like
> compile_functions does today (can probably just reuse the code).

I had that in mind. But a common error for user defined functions is to not 
define the dim and rank, producing nasty errors. My thought was to force the 
user to define these, at least in the python interface. Then we can choose to 
not force them to be set in the compiled interface, but forcing the user to 
do it make the interfaces consistent.

> Also, compile_functions extracts variable names from the strings.
> Then we can do just:
>
>     class MyFunc(Function):
>         cppcode = ("t*sin(x[0]", "cos(x[1])", "x[0]*x[2]")
>
>     f = MyFunc(V)
>     f.t = 0.0

That's right. We could also extract them from the cppcode before we send them 
to the code compiler, createing an __init__ function on the fly, which the 
code already do, so we will get:

     class MyFunc(Function):
         cppcode = ("t*sin(x[0]", "cos(x[1])", "x[0]*x[2]")
	
     f = MyFunc(V,0.0)

Maybe this would be a bit too magic? This is only possible when the cppcode is 
given in the nice tuple representation you already have implemented. This 
will be a bit more cumbersome when a whole code segment is handed, but 
probaby doable with the right regexp? If not we could add an extra 
attribute, 'args' which take a list of strings that are added to the created 
__init__ function and then passed to the compiled cpp_function.

> Although the V here is a little too magic for my taste, it does save
> space and looks very nice...

I like it and I am looking forward to se how and if it all wrapps up!

Johan


Follow ups

References