Subject: [UFL-dev] [HG UFL] Implemented better version of tuple syntax:

From: [email-masked] (UFL)
Date: Mon, 30 Mar 2009 14:00:51 +0200 (CEST)

One or more new changesets pushed to the primary ufl repository.
A short summary of the last three changesets is included below.

changeset:   780:bc9680be05bfd5048c3de1fbcc2f9281c3f2c5ef
tag:         tip
user:        "Martin Sandve Alnæs <[email-masked]>"
date:        Mon Mar 30 14:02:24 2009 +0200
files:       ufl/algorithms/formfiles.py ufl/integral.py
description:
Implemented better version of tuple syntax:

  a = (u,v)*dx + (f,v)*dx

in this case a is a Form, so no changes are needed anywhere else.

changeset:   779:73dbe41ad55fb2ff3f2d4575691741e33627bfcb
user:        "Martin Sandve Alnæs <[email-masked]>"
date:        Mon Mar 30 13:13:54 2009 +0200
files:       sandbox/algorithmtests/renumber_indices.py test/analyse_demos.py ufl/algorithms/renumbering.py ufl/common.py
description:
Implemented an alternative renumber_indices with some
different properties. Not enabled since there are
some bugs and I'm not sure if it's what we really want.

changeset:   778:540ea93daca99a3893f2a1417d1c97eeea2e9479
user:        Anders Logg <[email-masked]>
date:        Mon Mar 30 02:14:58 2009 +0200
files:       ufl/form.py
description:
Implement short-hand inner product notation (v, u)

----------------------------------------------------------------------
For more details, visit http://www.fenics.org/hg/ufl

---

From: Anders Logg <[email-masked]>
Date: Mon, 30 Mar 2009 15:28:32 +0200

> in this case a is a Form, so no changes are needed anywhere else.

Nice. I thought about this (implementing __rmul__ to handle tuples)
but wanted the even shorter version (without dx).

Can we keep both options?

I haven't figured out how to make load_forms work though. The current
implementation seems to extract *all* forms from a file, which may not
always be appropriate. One might want to keep contributions in
separate variables and then add up the results:

  CONV = (v, dot(beta, grad(u)))*dx
  DIFF = (grad(v), grad(u))*dx
  a = CONV + DIFF

Code should here be generated only for the form a, not CONV and DIFF.

FFC solves this by using reserved variable names for forms:

  a: bilinear form
  L: linear form
  M: functional

  element: single element

-- 
Anders

---

From: Anders Logg <[email-masked]>
Date: Mon, 30 Mar 2009 15:37:58 +0200

> FFC solves this by using reserved variable names for forms:

If this is not enough, load_forms could also look for a variable named
"forms" that lists the forms that should be compiled:

  forms = [a0, a1, L]

or

  forms = ["a0", "a1", "L"]

and if this is not found there could be a sensible default (like a, L,
M).

-- 
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Mon, 30 Mar 2009 16:11:27 +0200

I'm ok with the "forms / (a,L,M)" feature, and that pretty much
solves the interpretation problem for (u,v) in that context.
We should also have an optional list "elements" like "forms".
I like
  forms = [a, L]
better, quotes are unnecessary.

In the context of PyDOLFIN, PyDOLFIN can itself check for
tuple or Form, so we don't need to check it everywhere.

It is possible to have a function "as_form(form)" in UFL to
help with this, but it would be nice to not have to call this
all over the place just so you can write the mass matrix
with three letters less ;-P

But I think (f,v)*ds is more readable than (f,v,ds) and
they're exactly the same length,

  a = (u,v) + (f,v)*ds

so we don't need the (f,v,ds) syntax, ok?

Martin

2009/3/30 Anders Logg <[email-masked]>:
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iEYEARECAAYFAknQyzYACgkQTuwUCDsYZdGHeQCfdv4PqTb/Hj5SEdiFbHnYKrKN
> mvcAn2URikn1MlQOSP56bBJq+QaY29Vu
> =e1k9
> -----END PGP SIGNATURE-----
>
> _______________________________________________
> UFL-dev mailing list
> [email-masked]
> http://fenics.org/mailman/listinfo/ufl-dev
>
>

---

From: [email-masked]
Date: Mon, 30 Mar 2009 19:48:51 +0200 (CEST)

> better, quotes are unnecessary.

ok!

> tuple or Form, so we don't need to check it everywhere.

I don't think DOLFIN should need to check for this. Wouldn't it be better
to let the form compiler handle it?

Which interfaces does SFC have? FFC has two interfaces:

1. The compile() command in FFC (takes a single object or list of objects)

2. Command-line interface which ends up calling the compile() command.

The compile command checks each object in the list to see if it's an
object of type ElementBase (and then adds it to a list of elements), a
Form (and then adds it to a list of forms) and otherwise tries to create a
Form from it. This is where the extraction of integrals from a tuple comes
in:

 for object in objects:
        if isinstance(object, Form):
            forms.append(object)
        elif isinstance(object, FiniteElementBase):
            elements.append(object)
        elif not object is None:
            forms.append(Form(object))

> so we don't need the (f,v,ds) syntax, ok?

But wouldn't *dx be required above as well? I'm not really happy with the

  (f, v, ds)

syntax but it was the only solution I could come up with.

But I really like being able to write just (grad(v), grad(u)) for Poisson.

In striving for the simplest possible notation, this is *the* global optimum
(not just a local optimum)... :-)

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Tue, 31 Mar 2009 13:06:36 +0200

> 1. The compile() command in FFC (takes a single object or list of objects)

compile is a builtin function in Python, so this should be renamed.

> 2. Command-line interface which ends up calling the compile() command.

SFC has a similar structure.

>            forms.append(Form(object))

Ok. I think jit should return a list of compiled objects if objects is a list,
or a single compiled object if objects is a single object, so there's a
one to one relationship between the two. An element maps to the tuple
(dofmap, finiteelement) or the other way around.

> syntax but it was the only solution I could come up with.

No, both are implemented now. If you add (u,v) and a Form, you get a Form.

> (not just a local optimum)... :-)

I prefer optimizing the notation within the constraints
given by proper types and error checking. :-P

Martin

---

From: "Garth N. Wells" <[email-masked]>
Date: Tue, 31 Mar 2009 19:41:14 +0800

> given by proper types and error checking. :-P

I actually prefer inner(v, v)*dx because what's going on is unambiguous. 
It also seems that it's also simpler in implementation. I don't see that 
typing 'inner' burdens the user excessively.

Garth

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Tue, 31 Mar 2009 14:34:19 +0200

On Tue, Mar 31, 2009 at 1:41 PM, Garth N. Wells <[email-masked]> wrote:
> I actually prefer inner(v, v)*dx because what's going on is unambiguous. It
> also seems that it's also simpler in implementation. I don't see that typing
> 'inner' burdens the user excessively.
>
> Garth

I agree completely, and this is an unsafe feature.
I just tried to make the implementation slightly safer.

The "form" doesn't have the right type, potentially leading to
additional typechecking code many places.
(I certainly won't bother with this).

Error checking is not as good, making a proper form
instantaneously triggers some checks.
Also consider 2*(u,v) -> (u,v,u,v).

I won't use this feature and I won't spend more time on it.

Martin

---

From: Anders Logg <[email-masked]>
Date: Tue, 31 Mar 2009 15:55:54 +0200

> compile is a builtin function in Python, so this should be renamed.

Good point. I've been told this before (by Rob). Do you have a good
suggestion for a better name?

> (dofmap, finiteelement) or the other way around.

Sounds good.

> No, both are implemented now. If you add (u,v) and a Form, you get a Form.

ok, I didn't realize that. Then I'm happy!

> given by proper types and error checking. :-P

;-P back.

-- 
Anders

---

From: Anders Logg <[email-masked]>
Date: Tue, 31 Mar 2009 17:02:21 +0200

> Also consider 2*(u,v) -> (u,v,u,v).

But that's correct, right? Doing (u, v) + (u, v) also gives
(u, v, u, v) which will be interpreted as

  inner(u, v)*dx + inner(u, v)*dx = 2*inner(u, v)*dx

> I won't use this feature and I won't spend more time on it.

I'll use it.

-- 
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Tue, 31 Mar 2009 17:13:13 +0200

> suggestion for a better name?

I have
def generate_code(input, options=None):
def jit(input, options=None):

Martin

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Tue, 31 Mar 2009 18:22:05 +0200

>  inner(u, v)*dx + inner(u, v)*dx = 2*inner(u, v)*dx

True.

>> I won't use this feature and I won't spend more time on it.

Can we at least drop the "a = (u,v)" version?
The forms look more consistent if we require *dx.
The implementation becomes simpler and we don't need
typechecks all over the place. Subtraction works since *
has higher precedence than -.

Martin

---

From: Anders Logg <[email-masked]>
Date: Tue, 31 Mar 2009 20:27:32 +0200

> has higher precedence than -.

ok. I guess that's a good compromise.

-- 
Anders

---

From: Johan Hake <[email-masked]>
Date: Tue, 31 Mar 2009 20:39:42 +0200

On Tuesday 31 March 2009 17:13:13 Martin Sandve Alnæs wrote:
> >> > I don't think DOLFIN should need to check for this. Wouldn't it be
> >> > better to let the form compiler handle it?
> >> >

Will this be different if we let ufc take care of the jit compilation? 

I think,

  def generate_code(input, options=None):
  def signature(input, options=None):

make sense then.

Johan

---

From: Anders Logg <[email-masked]>
Date: Tue, 31 Mar 2009 21:17:33 +0200

>   def generate_code(input, options=None):

I think it should be made more explicit:

  def compile_form(form, options=None)
  def compile_forms(forms, options=None)
  def compile_element(element, options=None)
  def compile_elements(elements, options=None)

>   def signature(input, options=None):

This looks like a function that just computes a signature.

To match the above functions, we could have

  def jit_form(form, options=None)
  def jit_forms(forms, options=None)
  def jit_element(element, options=None)
  def jit_elements(elements, options=None)

-- 
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Tue, 31 Mar 2009 21:24:21 +0200

>  def compile_elements(elements, options=None)

Why? It's convenient to share code between these.

> This looks like a function that just computes a signature.

Because that's what it is? SFC has a similar function. I suggest
compute_signature.

>  def jit_elements(elements, options=None)

I don't see the need.

Martin

---

From: Johan Hake <[email-masked]>
Date: Tue, 31 Mar 2009 22:09:26 +0200

On Tuesday 31 March 2009 21:24:21 Martin Sandve Alnæs wrote:
> >> > >> > I don't think DOLFIN should need to check for this. Wouldn't it
> >> > >> > be better to let the form compiler handle it?
> >> > >> >

Agree. 

Sounds good.

I am not deep into this but I suggested this function because I imagine that 
the form compilers defines their own signatures, based on for example some 
formcompiler specific options or state of some configuration file of the form 
compiler or what not.

> >  def jit_elements(elements, options=None)

I think a common jit function is enough. 

Johan

---

From: Anders Logg <[email-masked]>
Date: Tue, 31 Mar 2009 23:06:15 +0200

> > Why? It's convenient to share code between these.

Yes, but that's an implementation issue. It's perfeclty fine to
implement compile form by

  return compile_forms([form], options)

or even

  return _compile_objects([form], options)

Having separate functions simplifies error checking on input.

> > Because that's what it is? SFC has a similar function. I suggest

Aren't we talking about the call to the JIT compiler? What is
signature supposed to do?

-- 
Anders

---

From: Johan Hake <[email-masked]>
Date: Tue, 31 Mar 2009 23:38:08 +0200

On Tuesday 31 March 2009 23:06:15 Anders Logg wrote:
> > > >> > >> >> I'm ok with the "forms / (a,L,M)" feature, and that pretty
> > > >> > >> >> much solves the interpretation problem for (u,v) in that
> > > >> > >> >> context. We should also have an optional list "elements"
> > > >> > >> >> like "forms". I like
> > > >> > >> >>   forms = [a, L]
> > > >> > >> > I don't think DOLFIN should need to check for this. Wouldn't
> > > >> > >> > it be better to let the form compiler handle it?
> > > >> > >> >
> > > >> > > Good point. I've been told this before (by Rob). Do you have a
> > > >> > > good suggestion for a better name?
> > > >> >
> > > >> > I have

You meen that ufc provides a jit function. This function check what is 
provided and call the proper function, you mentioned above, which is provided 
by the formcompiler? 

Couldn't we just send the ufl input to generate_code(). Then we compile the 
extension module and based on the ufl input we try to instantiate the form(s) 
or finite element(s) and dofmap(s) and return these to the user. Based on the 
input we type check the instantiated objects and that is enough?

> signature supposed to do?

The jit function will be implemented in ufc. ufc needs to be able to compute a 
signature to check whether the form(s) or element(s) allready are compiled.  
This, as I have argued above but still not sure is right, is formcompiler 
specific.

Johan

---

From: Anders Logg <[email-masked]>
Date: Wed, 1 Apr 2009 01:19:14 +0200

> input we type check the instantiated objects and that is enough?

Does the jit function need to know what type of objects it gets? If it
knows whether an object is a form or element, then it appropriate to
call either compile_form or compile_element. If not, then I agree it's
better to let the form compiler resolve the type of object.

> This, as I have argued above but still not sure is right, is formcompiler 

ok, then I understand. Should it be named something like compute_signature?

-- 
Anders

---

From: Johan Hake <[email-masked]>
Date: Wed, 1 Apr 2009 08:41:58 +0200

On Wednesday 01 April 2009 01:19:14 Anders Logg wrote:
> > > > > >> > On Tue, Mar 31, 2009 at 3:55 PM, Anders Logg <[email-masked]>
> >
> > wrote:
> > > > > >> > > On Tue, Mar 31, 2009 at 01:06:36PM +0200, Martin Sandve
> > > > > >> > > Alnæs
> >
> > wrote:
> > > > > >> > >> >> I'm ok with the "forms / (a,L,M)" feature, and that
> > > > > >> > >> >> pretty much solves the interpretation problem for (u,v)
> > > > > >> > >> >> in that context. We should also have an optional list
> > > > > >> > >> >> "elements" like "forms". I like
> > > > > >> > >> >>   forms = [a, L]
> > > > > >> > >> >> In the context of PyDOLFIN, PyDOLFIN can itself check
> > > > > >> > >> >> for tuple or Form, so we don't need to check it
> > > > > >> > >> >> everywhere.
> > > > > >> > >> >
> > > > > >> > >> > I don't think DOLFIN should need to check for this.
> > > > > >> > >> > Wouldn't it be better to let the form compiler handle it?
> > > > > >> > >> >
> > > > > >> > > Good point. I've been told this before (by Rob). Do you have
> > > > > >> > > a good suggestion for a better name?
> > > > > >> >
> > > > > >> > I have
> > provided and call the proper function, you mentioned above, which is
> > provided by the formcompiler?
> >
> > Couldn't we just send the ufl input to generate_code(). Then we compile
> > the extension module and based on the ufl input we try to instantiate the
> > form(s) or finite element(s) and dofmap(s) and return these to the user.
> > Based on the input we type check the instantiated objects and that is
> > enough?
>

I vote for this. The interface between ufc.jit and the formcompiler will then 
be minimal, and that is good.

I added the type check suggestion as a sanity check for what the formcompiler 
returns. But I do not think it is nescessary.

> > The jit function will be implemented in ufc. ufc needs to be able to
> > compute a signature to check whether the form(s) or element(s) allready
> > are compiled. This, as I have argued above but still not sure is right,
> > is formcompiler specific.
>

I think that sounds good.

Johan

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 09:01:29 +0200

> returns. But I do not think it is nescessary.

If we are supposed to handle a list of objects that can be a mixture of
elements and forms, it doesn't make any sense to split the implementations.
Since we have a single "jit" command, the types of the input must be
inspected anyway, so I don't really see what the splitting simplifies.

> I think that sounds good.

Good.

Martin

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 09:10:40 +0200

> This, as I have argued above but still not sure is right, is formcompiler

I'm not sure why we need to move jit to ufc. Why is that?

It seems to me that large parts of newsfc.jit is concerned with
handling sfc specific options. If ufc.jit is supposed to be a complete
replacement, it would need many options to cater for the
same functionality. I don't feel like standardizing the form compiler
options, and I don't feel like removing functionality. I just don't
see the point of this.

Martin

---

From: Johan Hake <[email-masked]>
Date: Wed, 1 Apr 2009 09:28:02 +0200

On Wednesday 01 April 2009 09:01:29 Martin Sandve Alnæs wrote:
> >> > > > > >> > >> >> pretty much solves the interpretation problem for
> >> > > > > >> > >> >> (u,v) in that context. We should also have an
> >> > > > > >> > >> >> optional list "elements" like "forms". I like
> >> > > > > >> > >> >>   forms = [a, L]
> >> > > > > >> > > Good point. I've been told this before (by Rob). Do you
> >> > > > > >> > > have a good suggestion for a better name?
> >> > > > > >> >
> >> > > > > >> > I have
> >> > Couldn't we just send the ufl input to generate_code(). Then we
> >> > compile the extension module and based on the ufl input we try to
> >> > instantiate the form(s) or finite element(s) and dofmap(s) and return
> >> > these to the user. Based on the input we type check the instantiated
> >> > objects and that is enough?
> >>
> > I vote for this. The interface between ufc.jit and the formcompiler will
> > then be minimal, and that is good.
> >
> > I added the type check suggestion as a sanity check for what the
> > formcompiler returns. But I do not think it is nescessary.
>

Agree.

While at it, when we compile a list of objects these will go into the same 
extension module, right? If so, how will ufc.jit know the name of the classes 
it will instantiate from the module? Will this be formcompiler specific?

Maybe open a new thread?

Johan

> >> > compute a signature to check whether the form(s) or element(s)
> >> > allready are compiled. This, as I have argued above but still not sure
> >> > is right, is formcompiler specific.
> >>

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 09:30:39 +0200

> it will instantiate from the module? Will this be formcompiler specific?

This + options handling is basically what jit does now, and it is
formcompiler specific. See my other email.

Martin

---

From: Johan Hake <[email-masked]>
Date: Wed, 1 Apr 2009 09:34:06 +0200

On Wednesday 01 April 2009 09:10:40 Martin Sandve Alnæs wrote:
> >> > > >> > > On Tue, Mar 31, 2009 at 01:06:36PM +0200, Martin Sandve Alnæs
> >
> > wrote:

I see your point. It was a suggestion I thought was resonable wrt to code 
sharing, and the nice logic (I think ;) ):

   You send ufl statements to ufc, and get compiled ufc objects back

In an other email I also raised a problem wrt to instantiate the right objects 
from ufc, when it has compiled the module. The names of the different classes 
are probably also formcompiler specific?

Johan

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 10:31:32 +0200

>   You send ufl statements to ufc, and get compiled ufc objects back

The flaw in this statement is that the signature of jit is not
  def jit(input)
but
  def jit(input, options)

and options are formcompiler specific ways to change the behaviour of jit.

Another argument against this is that it makes ufc depend on ufl, we
don't want that.

> are probably also formcompiler specific?

Yes.

Martin

---

From: Johan Hake <[email-masked]>
Date: Wed, 1 Apr 2009 13:09:13 +0200

On Wednesday 01 April 2009 10:31:32 Martin Sandve Alnæs wrote:
> >> >> > > >> > >> >> (u,v) in that context. We should also have an optional
> >> >> > > >> > >> >> list "elements" like "forms". I like
> >> >> > > >> > >> >>   forms = [a, L]

I intended this to be the signature of ufc.jit.

> and options are formcompiler specific ways to change the behaviour of jit.

Yes and I thought these could just be sent to the formcompiler, and the 
compiler could do what ever it would like to do with them.

> Another argument against this is that it makes ufc depend on ufl, we

Not necessary, it could just send the input to 
   
  form_compiler.compute_signature()

and then to 

  form_compiler.generate_code()

the generated code will then be used to build the extension module. However 
the classes will not easily be instantiated from ufc, without any more 
information. I think this is a show stopper. Also if ufc will not depend on 
UFL we cannot check the input to see what we should extract and again the 
point is lost.

So then we are almost back to what we have today. The formcompiler define its 
own jit, which returns instantiated form(s), (element(s), dofmap(s)), 
depending on the input?

Johan

> > In an other email I also raised a problem wrt to instantiate the right
> > objects from ufc, when it has compiled the module. The names of the
> > different classes are probably also formcompiler specific?
>
> Yes.
>
> Martin

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Wed, 1 Apr 2009 13:34:19 +0200

> I intended this to be the signature of ufc.jit.

Yes, and therefore we're not sending _just_ ufl statements.

> compiler could do what ever it would like to do with them.

However, the options in sfc include compilation options.
Different header files may be needed. Different filenames
are used. Different classnames are used. And probably more.

> own jit, which returns instantiated form(s), (element(s), dofmap(s)),

I guess so.

Martin