Subject: [Ufl] [[email-masked]: [Branch ~ufl-core/ufl/main] Rev 1051: erge]

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 10:28:37 +0200

I've been trying the new foo, foo/trunk, foo/work setup and it's
working pretty well, except for the missing commit messages.

I write a commit message when I commit in work, but when I merge it
into trunk, I just enter 'merge' since I don't want to repeat the
commit message I've already written. When a large piece of work is
merged in (consisting of many changesets), it's natural to write a
summary when it's merged in, but if it's just a single changeset, I
don't want to repeat the message I just wrote.

Any suggestions for how to handle this?

--
Anders

Subject: [Branch ~ufl-core/ufl/main] Rev 1051: erge
From: [email-masked]
To: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 08:24:22 -0000

Merge authors:
  Anders Logg (logg)
------------------------------------------------------------
revno: 1051 [merge]
committer: Anders Logg <[email-masked]>
branch nick: ufl
timestamp: Thu 2011-05-12 10:22:29 +0200
message:
  erge
modified:
  ufl/algorithms/preprocess.py

--
lp:ufl
https://code.launchpad.net/~ufl-core/ufl/main

Your team UFL Core Team is subscribed to branch lp:ufl.
To unsubscribe from this branch go to https://code.launchpad.net/~ufl-core/ufl/main/+edit-subscription
=== modified file 'ufl/algorithms/preprocess.py'
--- ufl/algorithms/preprocess.py	2011-05-12 07:08:22 +0000
+++ ufl/algorithms/preprocess.py	2011-05-12 08:21:50 +0000
@@ -56,29 +56,11 @@
     else:
         name = "a"
 
-    # Create empty form data
-    form_data = FormData()
-
-    # Store name of form
-    form_data.name = name
-
-    # Store elements, sub elements and element map
-    form_data.elements            = extract_elements(form)
-    form_data.unique_elements     = unique_tuple(form_data.elements)
-    form_data.sub_elements        = extract_sub_elements(form_data.elements)
-    form_data.unique_sub_elements = unique_tuple(form_data.sub_elements)
-
-    # Store common cell
-    form_data.cell = _extract_common_cell(form_data.unique_sub_elements,
-                                          common_cell)
-
-    # Store data related to cell
-    form_data.geometric_dimension = form_data.cell.geometric_dimension()
-    form_data.topological_dimension = form_data.cell.topological_dimension()
-    form_data.num_facets = form_data.cell.num_facets()
+    # Extract common cell
+    common_cell = common_cell or form.cell()
 
     # Expand derivatives
-    form = expand_derivatives(form, form_data.geometric_dimension)
+    form = expand_derivatives(form, common_cell.geometric_dimension())
 
     # Renumber indices
     form = renumber_indices(form)
@@ -97,6 +79,12 @@
     original_arguments = [inv_replace_map[v] for v in arguments]
     original_coefficients = [inv_replace_map[v] for v in coefficients]
 
+    # Create empty form data
+    form_data = FormData()
+
+    # Store name of form
+    form_data.name = name
+
     # Store data extracted by preprocessing
     form_data.arguments             = arguments
     form_data.coefficients          = coefficients
@@ -106,6 +94,22 @@
     # Store signature of form
     form_data.signature = form.signature()
 
+    # Store elements, sub elements and element map
+    form_data.elements            = extract_elements(form)
+    form_data.unique_elements     = unique_tuple(form_data.elements)
+    form_data.sub_elements        = extract_sub_elements(form_data.elements)
+    form_data.unique_sub_elements = unique_tuple(form_data.sub_elements)
+
+    # Store common cell
+    #form_data.cell = _extract_common_cell(form_data.unique_sub_elements,
+    #                                      common_cell)
+    form_data.cell = common_cell
+
+    # Store data related to cell
+    form_data.geometric_dimension = form_data.cell.geometric_dimension()
+    form_data.topological_dimension = form_data.cell.topological_dimension()
+    form_data.num_facets = form_data.cell.num_facets()
+
     # Store some useful dimensions
     form_data.rank = len(form_data.arguments)
     form_data.num_coefficients = len(form_data.coefficients)

---

From: "Garth N. Wells" <[email-masked]>
Date: Thu, 12 May 2011 09:37:24 +0100

> Any suggestions for how to handle this?

Work the way we did before? I don't see the problem with the old
approach. It worked, was simple, and we never lost history.

Garth

> --
> Anders
> 
> 
> 
> _______________________________________________
> Mailing list: https://launchpad.net/~ufl
> Post to     : [email-masked]
> Unsubscribe : https://launchpad.net/~ufl
> More help   : https://help.launchpad.net/ListHelp

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 10:48:07 +0200

Don't use merge when you don't need to merge. Just push to the server
if possible.

Martin

On 12 May 2011 10:28, Anders Logg <[email-masked]> wrote:
> ---------- Forwarded message ----------

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 10:48:16 +0200

> approach. It worked, was simple, and we never lost history.

I find the "xx changesets removed" thing annoying and it doesn't seem
to be recommended practice.

--
Anders

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 10:51:52 +0200

> Don't use merge when you don't need to merge. Just push to the server

I tried that but it didn't work. Probably because I hadn't pulled the
latest merge done in trunk into work before making the changes.

So the work flow is then:

  cd work
  bzr pull lp:foo
  do some changes
  bzr commit
  bzr push lp:foo

If the above fails, then

  cd ../trunk
  bzr merge ../work
  bzr commit -m merge

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 10:58:49 +0200

> approach. It worked, was simple, and we never lost history.

No history is lost either way, the problem is that when history is
rewritten (renumbered), we loose unique revision numbers.

Martin

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 10:58:56 +0200

> So the work flow is then:

bzr update

>  bzr commit -m merge

Otherwise looks ok. I like to commit more often locally than I push,
and then the merge message can be just a quick summary like 'Merge
work on foobar.' while the other commits have more detailed messages
about the steps.

Martin

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 11:36:42 +0200

> > So the work flow is then:

Yes, forgot to include that (but I've been using it).

> >  bzr commit -m merge

So in other words, the work flow is exactly the same as before except
that when push fails, we replace

  bzr merge
  bzr commit -m merge
  bzr push

by

  cd ../trunk
  bzr update
  bzr merge ../work
  bzr commit -m merge

> work on foobar.' while the other commits have more detailed messages

Sure.

--
Anders

---

From: "Garth N. Wells" <[email-masked]>
Date: Thu, 12 May 2011 10:52:50 +0100

Since there are no commit messages, can you tell us where the UFL/FFC
fixes to get DOLFIN working again are at?

Garth

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 12:13:12 +0200

> fixes to get DOLFIN working again are at?

How do you mean? I don't yet know which fixes should be made to get
DOLFIN working again or I would have fixed it already.

I've fixed quite a few issues. FFC is green again and the test cases
I've been using (JIT-compilation of Expressions and the DOLFIN
function unit tests) run.

The changes I've made are mainly to analysis.py (FFC) and
preprocess.py (UFL) + tons of other files.

The main outline of the change is:

1. preprocess tries to figure out the common cell

2. no elements are modified or mapped

3. FFC keeps track of suitable values for cells and degrees when they
are missing (as part of element_data computed in analysis.py)

I'm about to leave my office and be offline for a few hours.

--
Anders

---

From: "Garth N. Wells" <[email-masked]>
Date: Thu, 12 May 2011 11:21:34 +0100

> DOLFIN working again or I would have fixed it already.

So your commits are random and with no purpose? ;)

I mean what you describe below.

Garth

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 17:16:30 +0200

> 2. no elements are modified or mapped

Hmm...

Then the signature of the form will still be incomplete after preprocessing.
If there is no valid cell in the form, the form signature does not
identify whether it is in e.g. R^2 or R^3. Or am I missing something?

> I'm about to leave my office and be offline for a few hours.

But the preprocess function does look nice now at least :)

Martin

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 17:32:57 +0200

> identify whether it is in e.g. R^2 or R^3. Or am I missing something?

That's true. I didn't think about that. Hmm...

But perhaps that's not really a problem after all? The form compiler
should select the same elements the second time it sees a form with
the same signature containing unknowns.

I can think of one case when this can go wrong which is the case when
one integrates an expression over with unspecified domain in 2D, and
then later wants to integrate the same expression in 3D, and the 2D
version gets reused. We can get around this by including common_cell
passed to the JIT compiler in the signature used for caching.

Are there other cases when this can go wrong?

--
Anders

---

From: Johan Hake <[email-masked]>
Date: Thu, 12 May 2011 08:44:29 -0700

On Thursday May 12 2011 08:32:57 Anders Logg wrote:
> > Then the signature of the form will still be incomplete after
> > preprocessing. If there is no valid cell in the form, the form signature
> > does not identify whether it is in e.g. R^2 or R^3. Or am I missing
> > something?
> 

Not sure this relates to the situation after the redesign, but I had a lot of 
triggered recompilations becuase sometimes the generated singatures included a 
'?' for the cell and sometimes it was given a cell, for the exact same form. 

Also I have included a cell argument to the Constant constructor in DOLFIN so 
a user can define the cell if he wants to. That fixed all my problems with 
form caching.

Johan

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 18:28:33 +0200

> passed to the JIT compiler in the signature used for caching.

Reusing the same form for 2D and 3D is not possible anyway.

> Are there other cases when this can go wrong?

While your analysis may currently be right (I can't be sure), we can't
follow the "what could possibly go wrong" kind of logic when defining
a language like UFL. In particular when the logic depends on how ffc
and pydolfin happens to work today. To handle unforeseen combinations
(which is kinda the point of a language) we need to be able to
guarantee certain properties of objects. There are too many
combinations to enumerate and test them all.

I'll take a shot at implementing reconstruct tonight.

Martin

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 19:39:39 +0200

I've pushed some changes to lp:~martinal/ufl/reconstruction mostly
implementing the ufl side of taking an (optional) element_mapping
as input to preprocess, but I want to test it a bit more before pushing
to trunk.

Martin

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 20:39:55 +0200

> as input to preprocess, but I want to test it a bit more before pushing

ok. I'm currently working on sorting out some remaining cache problems
in the FFC JIT compiler. That should hopefully take care of the
remaining tests that fail in DOLFIN. When that works, I can try out
the reconstruction.

--
Anders

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 22:21:14 +0200

> remaining tests that fail in DOLFIN. When that works, I can try out

Is it safe to try out the new element replacement now?

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 22:22:51 +0200

> Is it safe to try out the new element replacement now?

Yes, I even checked it in. element_mapping is None by default, just
try adding it.

Martin

---

From: Anders Logg <[email-masked]>
Date: Thu, 12 May 2011 22:30:35 +0200

> Yes, I even checked it in. element_mapping is None by default, just

ok, will try.

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Thu, 12 May 2011 22:37:08 +0200

Be aware that form_data.elements and friends are _after_ mapping, so
if you get to the dolfin.FunctionSpaces through them something must be
changed. If you get them from the original functions everything should
be fine though.

Martin

---

From: Anders Logg <[email-masked]>
Date: Fri, 13 May 2011 00:33:46 +0200

It seems to work fine, but some unit tests are failing since
reconstruct is only implemented for FiniteElement (not for mixed
elements etc).

Could you add a suitable reconstruct for mixed elements? I'm not sure
how it should be done, in particular how the input should be
propagated to the subelements.

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Fri, 13 May 2011 09:03:27 +0200

Done, did a manual test and checking in now:

In [5]: print FiniteElement("CG", triangle,
2).reconstruct(family="DG", cell=quadrilateral, degree=3)
<DG3 on a <quadrilateral cell in R2>>

In [8]: print VectorElement("CG", triangle,
2).reconstruct(family="DG", cell=quadrilateral, degree=3)
<Discontinuous Lagrange vector element of degree 3 on a <quadrilateral
cell in R2>: 2 x <DG3 on a <quadrilateral cell in R2>>>

In [9]: print TensorElement("CG", triangle,
2).reconstruct(family="DG", cell=quadrilateral, degree=3)
<Discontinuous Lagrange tensor element of degree 3 and shape (2, 2) on
a <quadrilateral cell in R2>>

In [10]: print MixedElement(VectorElement("CG", triangle, 2),
FiniteElement("CG", triangle, 2)).reconstruct(family="DG",
cell=quadrilateral, degree=3)
<Mixed element: (<Discontinuous Lagrange vector element of degree 3 on
a <quadrilateral cell in R2>: 2 x <DG3 on a <quadrilateral cell in
R2>>>, <DG3 on a <quadrilateral cell in R2>>)>

I'll move this into the unit tests, but don't have more time for this today.

Martin

---

From: Anders Logg <[email-masked]>
Date: Fri, 13 May 2011 09:53:05 +0200

Thanks! I'll see if it works.

Have you thought about what should happen if say degree is given for a
mixed element but only one of the subelements has an undefined degree?

It might also be the case that we will completely miss such cases. I
think degree() for a mixed element returns the maximum degree of the
subelements and if one of them is None but not all, we will miss it
since max(None, q) = q.

--
Anders

---

From: Martin Sandve Alnæs <[email-masked]>
Date: Fri, 13 May 2011 10:16:22 +0200

> mixed element but only one of the subelements has an undefined degree?

No. If you specify the degree, reconstruct will set it for all subelements.
There is no other unique way. If you want to treat certain subelements
in a hierarchy specially you'll just have to traverse the mixed elements
yourself. I just added a reconstruct_from_elements(*elements) to
MixedElement which you can use to get some checking when piecing
together the mixed elements.

Note that it is important that reconstructed elements have the same
value shape. If used to reconstruct functions to reconstruct an expression,
the result of a changing value shape would be completely undefined
behaviour and there is no way to do that correctly. I've added some
asserts for this, just so you know they are really there for a very good reason.

> subelements and if one of them is None but not all, we will miss it

Seems so. But that's a problem for FFC/PyDOLFIN :)
I don't know why you would want to put yourself in that situation...

Martin

\> --

---

From: Anders Logg <[email-masked]>
Date: Fri, 13 May 2011 10:18:43 +0200

> asserts for this, just so you know they are really there for a very good reason.

ok. I'm not saying I foresee that we will run into these cases very
often, but I wanted to point it out. I'm usually not the one bringing
up the nasty corner cases. ;-)

> I don't know why you would want to put yourself in that situation...

I will try to avoid it. :-)

--
Anders