Subject: [Ffc] Current developments

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 02:09:09 +0100

We're working on simplifying the FFC code (and parts of UFL). Both
have grown out of hand and with limited resources (like Martin and
Johan leaving for other ventures) we need to make the codebase easier
to maintain.

As part of this, we've made some changes to how UFL and FFC handle the
preprocessing of forms. In particular, we've removed the caching of so
called form data in a form. Ideally, this should not lead to any
problems but there may be regressions such as slow JIT compilation as
a result of not caching certain data so keep an eye out for this.

Oh, and we also changed the name of Function to Coefficient in UFL so
.ufl files need to be updated. We also moved from BasisFunction to
Argument but this should not be visible in the user interface.

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Tue, 8 Dec 2009 23:52:38 -0800

> a result of not caching certain data so keep an eye out for this.

Do you know why Martin did include these in the first place? 

How do we retrieve the original UFL/PyDolfin objects now? I thought these were 
cached because otherwise they might get lost in some UFL algorithm. 

> Argument but this should not be visible in the user interface.

Why?

Johan

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 10:59:58 +0100

> Do you know why Martin did include these in the first place?

Yes, we discussed it quite a bit but I believe he was never happy with
the solution. We had things like form_data being cached in a form and
form_data also storing a modified version of the form so there were
things like

  self.form.form_data().form

being used in the form. I believe the new design is cleaner.

> cached because otherwise they might get lost in some UFL algorithm.

The original objects are still stored in form data:

  form_data.original_arguments
  form_data.original_coefficients

> > Argument but this should not be visible in the user interface.

Since it agrees better with the naming elsewhere, including some
chapters in the FEniCS book.

More precisely:

1. The first arguments in a form like v and u are the form
arguments. They can be test and trial functions and when we assemble
they are basis functions, but they are not always basis functions.
Hence Argument instead of BasisFunction.

2. The last arguments in a form like w_0, w_1, ... are the form
coefficients. They can be functions (as in dolfin::Function),
expressions or constants, but they are not always functions.
Hence Coefficient instead of Function.

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Wed, 9 Dec 2009 08:04:48 -0800

> being used in the form. I believe the new design is cleaner.

Ok. 

  v = TestFunction
  u = TrialFunction

  M0 = assemble(u*v*dx)

  v = TestFunction
  u = TrialFunction

  M1 = assemble(u*v*dx)

I think that he wanted to prevent recompilation of M1, as it is basically the 
same code that is generated as for M0. But due to some internal and necessary  
they are treated differently. I think that the form_data thing was a 
workaround for that. Is this correct?

> > How do we retrieve the original UFL/PyDolfin objects now? I thought these
> > were cached because otherwise they might get lost in some UFL algorithm.
> 

Ok.
 
> Hence Coefficient instead of Function.

Ok.

Johan

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 17:13:20 +0100

> workaround for that. Is this correct?

I don't think form_data has anything to do with this.

The above code should not lead to any new code generation as both M0
and M1 should have the same signatures. If not, there's a bug in
jit.py in FFC. The code for M1 should be picked up from disk cache.

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Wed, 9 Dec 2009 08:25:24 -0800

On Wednesday 09 December 2009 08:13:20 Anders Logg wrote:
> > > > > Johan leaving for other ventures) we need to make the codebase
> > > > > easier to maintain.
> > > > >
> > > > > As part of this, we've made some changes to how UFL and FFC handle
> > > > > the preprocessing of forms. In particular, we've removed the
> > > > > caching of so called form data in a form. Ideally, this should not
> > > > > lead to any problems but there may be regressions such as slow JIT
> > > > > compilation as a result of not caching certain data so keep an eye
> > > > > out for this.
> > > >
> > I think that he wanted to prevent recompilation of M1, as it is basically
> > the same code that is generated as for M0. But due to some internal and
> > necessary they are treated differently. I think that the form_data thing
> > was a workaround for that. Is this correct?
> 

Ok, I see that this is not the case for Arguments (BasisFunctions), but it is 
for Coefficients (Functions):

   f = Function(V)
   u = TestFunction(V)

   m0 = assemble(v*f*dx)

   f = Function(V)

   m1 = assemble(v*f*dx)
 
will now trigger a recompilation.

Just take a repr on the two 'f' and see.

Johan

> --
> Anders
> 
> > > > How do we retrieve the original UFL/PyDolfin objects now? I thought
> > > > these were cached because otherwise they might get lost in some UFL
> > > > algorithm.
> > >
> > > > > Oh, and we also changed the name of Function to Coefficient in UFL
> > > > > so .ufl files need to be updated. We also moved from BasisFunction
> > > > > to Argument but this should not be visible in the user interface.
> > > >
> > > > Why?
> > >

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 17:39:17 +0100

> Just take a repr on the two 'f' and see.

Should be fixed now. I've added a call to preprocess before computing
the form signature.

Does it work now?

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Wed, 9 Dec 2009 08:56:51 -0800

On Wednesday 09 December 2009 08:39:17 Anders Logg wrote:
> > > > > > > We're working on simplifying the FFC code (and parts of UFL).
> > > > > > > Both have grown out of hand and with limited resources (like
> > > > > > > Martin and Johan leaving for other ventures) we need to make
> > > > > > > the codebase easier to maintain.
> > > > > > >
> > > > > > > As part of this, we've made some changes to how UFL and FFC
> > > > > > > handle the preprocessing of forms. In particular, we've removed
> > > > > > > the caching of so called form data in a form. Ideally, this
> > > > > > > should not lead to any problems but there may be regressions
> > > > > > > such as slow JIT compilation as a result of not caching certain
> > > > > > > data so keep an eye out for this.
> > > > > >
> > > > > Yes, we discussed it quite a bit but I believe he was never happy
> > > > > with the solution. We had things like form_data being cached in a
> > > > > form and form_data also storing a modified version of the form so
> > > > > there were things like
> > > > >
> > > > I think that he wanted to prevent recompilation of M1, as it is
> > > > basically the same code that is generated as for M0. But due to some
> > > > internal and necessary they are treated differently. I think that the
> > > > form_data thing was a workaround for that. Is this correct?
> > >
> > Ok, I see that this is not the case for Arguments (BasisFunctions), but
> > it is for Coefficients (Functions):
> >
> >    f = Function(V)
> >    u = TestFunction(V)
> >
> >    m0 = assemble(v*f*dx)
> >
> >    f = Function(V)
> >
> >    m1 = assemble(v*f*dx)
> >

Did you push it?

  el = FiniteElement("CG",triangle,1)
  f = Coefficient(el)
  
  repr(f*dx)

  f = Coefficient(el)

  repr(f*dx)

repr does here return different results, and JitObject.signature() does only 
use repr on the passed form.

Johan

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 18:09:56 +0100

> > Should be fixed now. I've added a call to preprocess before computing

Yes.

> use repr on the passed form.

repr should return a different string because there are two different
instances of f.

But JITObject gets the preprocessed form and should therefore see an f
with number (count) 0 since it should have been renumbered.

I'll take a closer look.

--
Anders

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 18:17:17 +0100

> with number (count) 0 since it should have been renumbered.

It looks to me like the signature is correct so the second assembly
should trigger a reload from (disk) cache.

Does it seem to work on your end?

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Wed, 9 Dec 2009 09:32:23 -0800

On Wednesday 09 December 2009 09:17:17 Anders Logg wrote:
> > > > > > > > > > We're working on simplifying the FFC code (and parts of
> > > > > > > > > > UFL). Both have grown out of hand and with limited
> > > > > > > > > > resources (like Martin and Johan leaving for other
> > > > > > > > > > ventures) we need to make the codebase easier to
> > > > > > > > > > maintain.
> > > > > > > > > >
> > > > > > > > > > As part of this, we've made some changes to how UFL and
> > > > > > > > > > FFC handle the preprocessing of forms. In particular,
> > > > > > > > > > we've removed the caching of so called form data in a
> > > > > > > > > > form. Ideally, this should not lead to any problems but
> > > > > > > > > > there may be regressions such as slow JIT compilation as
> > > > > > > > Yes, we discussed it quite a bit but I believe he was never
> > > > > > > > happy with the solution. We had things like form_data being
> > > > > > > > cached in a form and form_data also storing a modified
> > > > > > > > version of the form so there were things like
> > > > > > > >
> > > > > > > basically the same code that is generated as for M0. But due to
> > > > > > > some internal and necessary they are treated differently. I
> > > > > > > think that the form_data thing was a workaround for that. Is
> > > > > > > this correct?
> > > > > >
> > > > > > The above code should not lead to any new code generation as both
> > > > > > M0 and M1 should have the same signatures. If not, there's a bug
> > > > > > in jit.py in FFC. The code for M1 should be picked up from disk
> > > > > > cache.
> > > > >
> > > > > Ok, I see that this is not the case for Arguments (BasisFunctions),
> > > > > but it is for Coefficients (Functions):
> > > > >
> > > > >    f = Function(V)
> > > > >    u = TestFunction(V)
> > > > >
> > > > >    m0 = assemble(v*f*dx)
> > > > >
> > > > >    f = Function(V)
> > > > >
> > > > >    m1 = assemble(v*f*dx)
> > > > >
> > > repr does here return different results, and JitObject.signature() does
> > > only use repr on the passed form.
> >

Yes! I did only look at the signature method :P

However when I tried to assemble:

  assemble(f*dx)

where f is a dolfin.Function assemble complained of no mesh provided. Is this 
correct, as f has a FunctionSpace?

Johan

---

From: Anders Logg <[email-masked]>
Date: Wed, 9 Dec 2009 19:02:44 +0100

> correct, as f has a FunctionSpace?

I think this has been the case before. We should be able to make it so
that the mesh argument is not needed if it can be figured out.

I won't have time to fix that now but will do it at some point in the
future. (But feel free to fix it.)

--
Anders